173
173
in ~/.arduino15/preferences.txt, to disable the aggressive caching feature:
174
174
https://forum.arduino.cc/t/no-aggressively-cache-compiled-core-in-ide-1-8-15/878954/2
175
175
176
+ Added workaround for `compiler.cache_core=true` case.
177
+ See `if use_aggressive_caching_workaround:` in main().
178
+
176
179
7) Suspected but not confirmed. A quick edit and rebuild don't always work well.
177
180
Build does not work as expected. This does not fail often. Maybe PIC NIC.
178
181
"""
191
194
docs_url = "https://arduino-esp8266.readthedocs.io/en/latest/faq/a06-global-build-options.html"
192
195
193
196
def print_msg (* args , ** kwargs ):
194
- print (* args , flush = True , ** kwargs )
197
+ print (* args , ** kwargs )
195
198
196
199
200
+ # I prefer error messages to stand out; however, using stderr for a different
201
+ # color does not work on the new Arduino IDE 2.0 RC4. Also, separate pipes,
202
+ # buffering, and multiple threads with output can create mixed-up messages.
203
+ # Bring attention to errors with a blank line and lines starting with "*** ".
204
+ # Let multiple prints buffer to aid them in staying together.
197
205
def print_err (* args , ** kwargs ):
198
- print (* args , flush = True , file = sys .stderr , ** kwargs ) # file=sys.stderr,
206
+ if (args [0 ])[0 ] != ' ' :
207
+ print ("" )
208
+ print ("*** " , end = '' )
209
+ print (* args , ** kwargs )
199
210
200
211
201
212
def copy_create_build_file (source_fqfn , build_target_fqfn ):
@@ -221,18 +232,19 @@ def copy_create_build_file(source_fqfn, build_target_fqfn):
221
232
else :
222
233
# Place holder - Must have an empty file to satisfy parameter list
223
234
# specifications in platform.txt.
224
- open (build_target_fqfn , 'w' ).close ()
235
+ with open (build_target_fqfn , 'w' ):
236
+ pass
225
237
return True # file changed
226
238
227
239
228
240
def add_include_line (build_opt_fqfn , include_fqfn ):
229
241
if not os .path .exists (include_fqfn ):
230
242
# If file is missing, we need an place holder
231
- open (include_fqfn , 'w' ).close ()
243
+ with open (include_fqfn , 'w' ):
244
+ pass
232
245
print ("add_include_line: Created " + include_fqfn )
233
- build_opt = open (build_opt_fqfn , 'a' )
234
- build_opt .write ('-include "' + include_fqfn .replace ('\\ ' , '\\ \\ ' ) + '"\n ' )
235
- build_opt .close ()
246
+ with open (build_opt_fqfn , 'a' ) as build_opt :
247
+ build_opt .write ('-include "' + include_fqfn .replace ('\\ ' , '\\ \\ ' ) + '"\n ' )
236
248
237
249
238
250
def extract_create_build_opt_file (globals_h_fqfn , file_name , build_opt_fqfn ):
@@ -261,7 +273,7 @@ def extract_create_build_opt_file(globals_h_fqfn, file_name, build_opt_fqfn):
261
273
if line == build_opt_signature :
262
274
if complete_comment :
263
275
build_opt_error = True
264
- print_err ("Multiple embedded build.opt blocks in " + file_name + ":" + str (line_no ))
276
+ print_err (" Multiple embedded build.opt blocks in " + file_name + ":" + str (line_no ))
265
277
continue
266
278
print_msg ("Extracting embedded compiler command-line options from " + file_name + ":" + str (line_no ))
267
279
for line in src :
@@ -280,27 +292,26 @@ def extract_create_build_opt_file(globals_h_fqfn, file_name, build_opt_fqfn):
280
292
continue
281
293
# some consistency checking before writing - give some hints about what is wrong
282
294
elif line == build_opt_signature :
283
- print_err ("Double begin before end for embedded build.opt block in " + file_name + ":" + str (line_no ))
295
+ print_err (" Double begin before end for embedded build.opt block in " + file_name + ":" + str (line_no ))
284
296
build_opt_error = True
285
297
elif line .startswith (build_opt_signature ):
286
- print_err ("build.opt signature block ignored, trailing character for embedded build.opt block in " + file_name + ":" + str (line_no ))
298
+ print_err (" build.opt signature block ignored, trailing character for embedded build.opt block in " + file_name + ":" + str (line_no ))
287
299
build_opt_error = True
288
300
elif "/*" in line or "*/" in line :
289
- print_err ("Nesting issue for embedded build.opt block in " + file_name + ":" + str (line_no ))
301
+ print_err (" Nesting issue for embedded build.opt block in " + file_name + ":" + str (line_no ))
290
302
build_opt_error = True
291
303
else :
292
304
build_opt .write (line + "\n " )
293
305
elif line .startswith (build_opt_signature ):
294
- print_err ("build.opt signature block ignored, trailing character for embedded build.opt block in " + file_name + ":" + str (line_no ))
306
+ print_err (" build.opt signature block ignored, trailing character for embedded build.opt block in " + file_name + ":" + str (line_no ))
295
307
build_opt_error = True
296
- src .close ()
297
308
if not complete_comment or build_opt_error :
298
309
build_opt .truncate (0 )
299
310
build_opt .close ()
300
311
if build_opt_error :
301
312
# this will help the script start over when the issue is fixed
302
313
os .remove (globals_h_fqfn )
303
- print_err ("Extraction failed" )
314
+ print_err (" Extraction failed" )
304
315
# Don't let the failure get hidden by a spew of nonsensical error
305
316
# messages that will follow. Bring things to a halt.
306
317
sys .exit (1 )
@@ -312,54 +323,66 @@ def extract_create_build_opt_file(globals_h_fqfn, file_name, build_opt_fqfn):
312
323
313
324
314
325
def enable_override (enable , commonhfile_fqfn ):
315
- file = open (commonhfile_fqfn , 'w' )
316
- if enable :
317
- file .write ("//Override aggressive caching\n " )
318
- file .close ()
326
+ with open (commonhfile_fqfn , 'w' ) as file :
327
+ if enable :
328
+ file .write ("//Override aggressive caching\n " )
319
329
# enabled when getsize(commonhfile_fqfn) is non-zero, disabled when zero
320
330
331
+
321
332
def find_preferences_txt ():
322
333
platform_name = platform .system ()
323
334
# OS Path list from:
324
335
# https://www.arduino.cc/en/hacking/preferences
325
- if "Windows" == platform_name :
326
- fqfn = os .path .expanduser ("\Arduino15\preferences.txt" ) # Windows
336
+ if "Linux" == platform_name :
337
+ # Test for portable 1ST
338
+ # <Arduino IDE installation folder>/portable/preferences.txt (when used in portable mode)
339
+ # For more on portable mode see https://docs.arduino.cc/software/ide-v1/tutorials/PortableIDE
340
+ # Working directory must be set to the location of the Arduino IDE executable.
341
+ fqfn = "./portable/preferences.txt" # Linux portable - verified
327
342
if os .path .exists (fqfn ):
328
343
return fqfn
329
- fqfn = os .path .expanduser ("\Documents\ArduinoData\ preferences.txt" ) # Windows app version
344
+ fqfn = os .path .expanduser ("~/.arduino15/ preferences.txt" ) # Linux - verified
330
345
if os .path .exists (fqfn ):
331
346
return fqfn
332
- elif "Darwin" == platform_name :
333
- fqfn = os .path .expanduser ("~/Library/Arduino15/preferences.txt" ) # Max OS X
347
+ elif "Windows" == platform_name :
348
+ fqfn = ".\portable\preferences.txt"
349
+ if os .path .exists (fqfn ):
350
+ return fqfn
351
+ fqfn = os .path .expanduser ("~\Documents\ArduinoData\preferences.txt" ) # Windows app version - verified
334
352
if os .path .exists (fqfn ):
335
353
return fqfn
336
- elif "Linux" == platform_name :
337
- fqfn = os .path .expanduser ("~/.arduino15/preferences.txt" ) # Linux - works
354
+ fqfn = os .path .expanduser ("~\Arduino15\preferences.txt" ) # Windows
338
355
if os .path .exists (fqfn ):
339
356
return fqfn
340
- # Where and how would I find this?
341
- # <Arduino IDE installation folder>/portable/preferences.txt (when used in portable mode)
357
+ elif "Darwin" == platform_name :
358
+ # Skip portable on Macs. Portable is not compatable with Macs
359
+ # see https://docs.arduino.cc/software/ide-v1/tutorials/PortableIDE
360
+ fqfn = os .path .expanduser ("~/Library/Arduino15/preferences.txt" ) # Max OS X
361
+ if os .path .exists (fqfn ):
362
+ return fqfn
363
+
364
+ print_err ("File preferences.txt not found on " + platform_name )
342
365
return ""
343
366
344
367
345
368
def get_preferences_txt (file_fqfn , key ):
346
- with open (file_fqfn ) as fd :
347
- for line in fd :
369
+ with open (file_fqfn ) as file :
370
+ for line in file :
348
371
name , value = line .partition ("=" )[::2 ]
349
372
if name .strip ().lower () == key :
350
373
if value .strip ().lower () == 'true' :
351
- print_msg ("found compiler.cache_core " + value .strip ()) #D debug
352
374
return True
353
375
else :
354
376
return False
377
+ print_err ("Key " + key + " not found in preferences.txt. Default to true." )
355
378
return True # If we don't find it just assume it is set True
356
379
357
380
358
381
def check_preferences_txt ():
359
382
file_fqfn = find_preferences_txt ()
360
383
if file_fqfn == "" :
361
384
return True # cannot find file assume enabled
362
- print_msg ("\n found preferences " + file_fqfn ) #D debug
385
+ print_msg ("Using preferences from " + file_fqfn )
363
386
return get_preferences_txt (file_fqfn , "compiler.cache_core" )
364
387
365
388
@@ -368,25 +391,27 @@ def touch(fname, times=None):
368
391
os .utime (fname , times )
369
392
370
393
371
- def time_sync (globals_h_fqfn , commonhfile_fqfn ):
372
- ts = time .time ()
373
- touch (globals_h_fqfn , (ts , ts ))
374
- touch (commonhfile_fqfn , (ts , ts ))
394
+ def synchronous_touch (globals_h_fqfn , commonhfile_fqfn ):
395
+ with open (globals_h_fqfn , 'a' ):
396
+ os .utime (globals_h_fqfn )
397
+ ts = os .stat (globals_h_fqfn )
398
+ with open (commonhfile_fqfn , 'a' ):
399
+ os .utime (commonhfile_fqfn , ns = (ts .st_atime_ns , ts .st_mtime_ns ))
375
400
376
401
377
402
def main ():
378
403
global build_opt_signature
379
404
global docs_url
380
405
num_include_lines = 1
381
- use_aggressive_caching_workaround = check_preferences_txt () #? preliminary
406
+ use_aggressive_caching_workaround = check_preferences_txt ()
382
407
383
408
if len (sys .argv ) >= 5 :
384
409
source_globals_h_fqfn = os .path .normpath (sys .argv [1 ])
385
410
globals_name = os .path .basename (source_globals_h_fqfn )
386
411
globals_h_fqfn = os .path .normpath (sys .argv [2 ])
387
412
build_path = os .path .dirname (globals_h_fqfn )
388
- build_opt_fqfn = os .path .normpath (sys .argv [3 ])
389
413
# Assumption: globals_h_fqfn and build_opt_fqfn have the same dirname
414
+ build_opt_fqfn = os .path .normpath (sys .argv [3 ])
390
415
commonhfile_fqfn = os .path .normpath (sys .argv [4 ])
391
416
392
417
if os .path .exists (commonhfile_fqfn ):
@@ -425,21 +450,26 @@ def main():
425
450
copy_create_build_file (source_globals_h_fqfn , globals_h_fqfn )
426
451
427
452
# globals_h_fqfn timestamp was only updated if the source changed. This
428
- # controls the rebuild on change. We can always extact a new build.opt
453
+ # controls the rebuild on change. We can always extract a new build.opt
429
454
# w/o triggering a needless rebuild.
430
455
embedded_options = extract_create_build_opt_file (globals_h_fqfn , globals_name , build_opt_fqfn )
431
456
432
457
if use_aggressive_caching_workaround :
458
+ # When a Sketch owns a "Sketch.ino.globals.h" file in the build tree
459
+ # that exactly matches the timestamp of "CommonHFile.h" in the
460
+ # platform source tree, it owns the core cache. If not, or
461
+ # "Sketch.ino.globals.h" has changed, rebuild core.
433
462
if os .path .getsize (commonhfile_fqfn ):
434
- print ("os.path.getmtime(globals_h_fqfn) " + str (os .path .getmtime (globals_h_fqfn )))
435
- print ("os.path.getmtime(commonhfile_fqfn) " + str (os .path .getmtime (commonhfile_fqfn )))
436
463
if (os .path .getmtime (globals_h_fqfn ) != os .path .getmtime (commonhfile_fqfn )):
437
464
# Need to rebuild core.a
438
465
# touching commonhfile_fqfn in the source core tree will cause rebuild.
439
- time_sync (globals_h_fqfn , commonhfile_fqfn )
466
+ # Looks like touching or writing unrelated files in the source core tree will cause rebuild.
467
+ synchronous_touch (globals_h_fqfn , commonhfile_fqfn )
468
+ print_msg ("Using 'aggressive caching' workaround." )
440
469
elif os .path .getsize (globals_h_fqfn ):
441
470
enable_override (True , commonhfile_fqfn )
442
- time_sync (globals_h_fqfn , commonhfile_fqfn )
471
+ synchronous_touch (globals_h_fqfn , commonhfile_fqfn )
472
+ print_msg ("Using 'aggressive caching' workaround." )
443
473
444
474
add_include_line (build_opt_fqfn , commonhfile_fqfn )
445
475
add_include_line (build_opt_fqfn , globals_h_fqfn )
0 commit comments