11#!/usr/bin/env python3
22
33# This script manages the use of a file with a unique name, like
4- # `SketchName .ino.globals.h`, in the Sketch source directory to provide compiler
4+ # `Sketch .ino.globals.h`, in the Sketch source directory to provide compiler
55# command-line options (build options) and sketch global defines. The build
66# option data is encapsulated in a unique "C" comment block and extracted into
77# the build tree during prebuild.
3131"""
3232Operation
3333
34- "SketchName .ino.globals.h" - A global h file in the Source Sketch directory. The
35- string SketchName is the actual name of the sketch. A matching copy is kept in
36- the build path/core directory. The file is empty when it does not exist in the
37- source directory.
34+ "Sketch .ino.globals.h" - A global h file in the Source Sketch directory. The
35+ string Sketch.ino is the actual name of the sketch program . A matching copy is
36+ kept in the build path/core directory. The file is empty when it does not exist
37+ in the source directory.
3838
39- Using SketchName .ino.globals.h as a container to hold build.opt, gives implicit
40- dependency tracking for build.opt by way of SketchName .ino.globals.h's
39+ Using Sketch .ino.globals.h as a container to hold build.opt, gives implicit
40+ dependency tracking for build.opt by way of Sketch .ino.globals.h's
4141dependencies.
4242Example:
4343 gcc ... @{build.path}/core/build.opt -include "{build.path}/core/{build.project_name}.globals.h" ...
4848
4949At each build cycle, "{build.project_name}.globals.h" is conditoinally copied to
5050"{build.path}/core/" at prebuild, and build.opt is extraction as needed. The
51- SketchName .ino.globals.h's dependencies will trigger "rebuild all" as needed.
51+ Sketch .ino.globals.h's dependencies will trigger "rebuild all" as needed.
5252
53- If SketchName .ino.globals.h is not in the source sketch folder, an empty
53+ If Sketch .ino.globals.h is not in the source sketch folder, an empty
5454versions is created in the build tree. The file build.opt always contains a
5555"-include ..." entry so that file dependencies are generated for
56- SketchName .ino.globals.h. This allows for change detection when the file is
56+ Sketch .ino.globals.h. This allows for change detection when the file is
5757added.
5858"""
5959
136136issues when replacing files by renaming and rebuilding.
137137
138138A good example of this problem is when you correct the spelling of file
139- SketchName .ino.globals.h. You need to touch (update time stampt) the file so a
139+ Sketch .ino.globals.h. You need to touch (update time stampt) the file so a
140140rebuild all is performed.
141141
142- 3) During the build two identical copies of SketchName .ino.globals.h will exist.
143- #ifndef fencing will be needed for non comment blocks in SketchName .ino.globals.h.
142+ 3) During the build two identical copies of Sketch .ino.globals.h will exist.
143+ #ifndef fencing will be needed for non comment blocks in Sketch .ino.globals.h.
144144
1451454) By using a .h file to encapsulate "build.opt" options, the information is not
146146lost after a save-as. Before with an individual "build.opt" file, the file was
@@ -249,9 +249,9 @@ def add_include_line(build_opt_fqfn, include_fqfn):
249249
250250def extract_create_build_opt_file (globals_h_fqfn , file_name , build_opt_fqfn ):
251251 """
252- Extract the embedded build.opt from SketchName .ino.globals.h into build
252+ Extract the embedded build.opt from Sketch .ino.globals.h into build
253253 path/core/build.opt. The subdirectory path must already exist as well as the
254- copy of SketchName .ino.globals.h.
254+ copy of Sketch .ino.globals.h.
255255 """
256256 global build_opt_signature
257257
@@ -263,7 +263,7 @@ def extract_create_build_opt_file(globals_h_fqfn, file_name, build_opt_fqfn):
263263 complete_comment = False
264264 build_opt_error = False
265265 line_no = 0
266- # If the source sketch did not have the file SketchName .ino.globals.h, an empty
266+ # If the source sketch did not have the file Sketch .ino.globals.h, an empty
267267 # file was created in the ./core/ folder.
268268 # By using the copy, open will always succeed.
269269 with open (globals_h_fqfn , 'r' ) as src :
@@ -329,35 +329,53 @@ def enable_override(enable, commonhfile_fqfn):
329329 # enabled when getsize(commonhfile_fqfn) is non-zero, disabled when zero
330330
331331
332- def find_preferences_txt ():
332+ def find_preferences_txt (runtime_ide_path ):
333333 platform_name = platform .system ()
334- # OS Path list from:
335- # https://www.arduino.cc/en/hacking/preferences
334+ # OS Path list for Arduino IDE 1.6.0 and newer
335+ # from: https://www.arduino.cc/en/hacking/preferences
336336 if "Linux" == platform_name :
337337 # Test for portable 1ST
338338 # <Arduino IDE installation folder>/portable/preferences.txt (when used in portable mode)
339339 # 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
340+ fqfn = os . path . normpath ( runtime_ide_path + "/portable/preferences.txt" )
341+ # Linux - verified with Arduino IDE 1.8.19
342342 if os .path .exists (fqfn ):
343343 return fqfn
344- fqfn = os .path .expanduser ("~/.arduino15/preferences.txt" ) # Linux - verified
344+ fqfn = os .path .expanduser ("~/.arduino15/preferences.txt" )
345+ # Linux - verified with Arduino IDE 1.8.18 and 2.0 RC5 64bit and AppImage
345346 if os .path .exists (fqfn ):
346347 return fqfn
347348 elif "Windows" == platform_name :
348- fqfn = ".\portable\preferences.txt"
349+ fqfn = os .path .normpath (runtime_ide_path + "\portable\preferences.txt" )
350+ # verified on Windows 10 with Arduino IDE 1.8.19
349351 if os .path .exists (fqfn ):
350352 return fqfn
351- fqfn = os .path .expanduser ("~\Documents\ArduinoData\preferences.txt" ) # Windows app version - verified
353+ # It is never simple. Arduino from the Windows APP store or the download
354+ # Windows 8 and up option will save "preferences.txt" in one location.
355+ # The downloaded Windows 7 (and up version) will put "preferences.txt"
356+ # in a different location. When both are present due to various possible
357+ # scenarios, use the more modern.
358+ # Note, I am ignoring any permutations you might get into with storing
359+ # and running applications off Network servers.
360+ fqfn = os .path .expanduser ("~\Documents\ArduinoData\preferences.txt" )
361+ # Path for "Windows app" - verified on Windows 10 with Arduino IDE 1.8.19
362+ fqfn2 = os .path .expanduser ("~\AppData\local\Arduino15\preferences.txt" )
363+ # Path for Windows 7 and up - verified on Windows 10 with Arduino IDE 1.8.19
352364 if os .path .exists (fqfn ):
353- return fqfn
354- fqfn = os .path .expanduser ("~\Arduino15\preferences.txt" ) # Windows
355- if os .path .exists (fqfn ):
356- return fqfn
365+ if os .path .exists (fqfn2 ):
366+ print_err ("Multiple 'preferences.txt' files found:" )
367+ print_err (" " + fqfn )
368+ print_err (" " + fqfn2 )
369+ return fqfn
370+ else :
371+ return fqfn
372+ elif os .path .exists (fqfn2 ):
373+ return fqfn2
357374 elif "Darwin" == platform_name :
358- # Skip portable on Macs. Portable is not compatable with Macs
375+ # Portable is not compatable with Mac OS X
359376 # see https://docs.arduino.cc/software/ide-v1/tutorials/PortableIDE
360- fqfn = os .path .expanduser ("~/Library/Arduino15/preferences.txt" ) # Max OS X
377+ fqfn = os .path .expanduser ("~/Library/Arduino15/preferences.txt" )
378+ # Mac OS X - unverified
361379 if os .path .exists (fqfn ):
362380 return fqfn
363381
@@ -378,8 +396,8 @@ def get_preferences_txt(file_fqfn, key):
378396 return True # If we don't find it just assume it is set True
379397
380398
381- def check_preferences_txt ():
382- file_fqfn = find_preferences_txt ()
399+ def check_preferences_txt (runtime_ide_path ):
400+ file_fqfn = find_preferences_txt (runtime_ide_path )
383401 if file_fqfn == "" :
384402 return True # cannot find file assume enabled
385403 print_msg ("Using preferences from " + file_fqfn )
@@ -403,16 +421,17 @@ def main():
403421 global build_opt_signature
404422 global docs_url
405423 num_include_lines = 1
406- use_aggressive_caching_workaround = check_preferences_txt ()
407424
408- if len (sys .argv ) >= 5 :
425+ if len (sys .argv ) >= 6 :
409426 source_globals_h_fqfn = os .path .normpath (sys .argv [1 ])
410427 globals_name = os .path .basename (source_globals_h_fqfn )
411428 globals_h_fqfn = os .path .normpath (sys .argv [2 ])
412429 build_path = os .path .dirname (globals_h_fqfn )
413430 # Assumption: globals_h_fqfn and build_opt_fqfn have the same dirname
414431 build_opt_fqfn = os .path .normpath (sys .argv [3 ])
415432 commonhfile_fqfn = os .path .normpath (sys .argv [4 ])
433+ runtime_ide_path = os .path .normpath (sys .argv [5 ])
434+ use_aggressive_caching_workaround = check_preferences_txt (runtime_ide_path )
416435
417436 if os .path .exists (commonhfile_fqfn ):
418437 if os .path .getsize (commonhfile_fqfn ) and \
@@ -488,7 +507,7 @@ def main():
488507
489508 else :
490509 print_err ("Too few arguments. Add arguments:" )
491- print_err (" Source FQFN SketchName .ino.globals.h, Build FQFN SketchName .ino.globals.h, Build FQFN build.opt" )
510+ print_err (" Source FQFN Sketch .ino.globals.h, Build FQFN Sketch .ino.globals.h, Build FQFN build.opt" )
492511
493512if __name__ == '__main__' :
494513 sys .exit (main ())
0 commit comments