187187import glob
188188import os
189189import platform
190+ import traceback
190191import sys
191192import textwrap
192193import time
193194
195+ import locale
196+
194197# Need to work on signature line used for match to avoid conflicts with
195198# existing embedded documentation methods.
196199build_opt_signature = "/*@create-file:build.opt@"
201204err_print_flag = False
202205msg_print_buf = ""
203206debug_enabled = False
207+ default_encoding = None
204208
205209# Issues trying to address through buffered printing
206210# 1. Arduino IDE 2.0 RC5 does not show stderr text in color. Text printed does
@@ -295,16 +299,16 @@ def copy_create_build_file(source_fqfn, build_target_fqfn):
295299 pass
296300 return True # file changed
297301
298-
299302def add_include_line (build_opt_fqfn , include_fqfn ):
303+ global default_encoding
300304 if not os .path .exists (include_fqfn ):
301305 # If file is missing, we need an place holder
302- with open (include_fqfn , 'w' , encoding = "utf-8" ):
306+ with open (include_fqfn , 'w' , encoding = default_encoding ):
303307 pass
304- print ("add_include_line: Created " + include_fqfn )
305- with open (build_opt_fqfn , 'a' , encoding = "utf-8" ) as build_opt :
306- build_opt .write ('-include "' + include_fqfn .replace ('\\ ' , '\\ \\ ' ) + '"\n ' )
308+ print_msg ("add_include_line: Created " + include_fqfn )
307309
310+ with open (build_opt_fqfn , 'a' , encoding = default_encoding ) as build_opt :
311+ build_opt .write ('-include "' + include_fqfn .replace ('\\ ' , '\\ \\ ' ) + '"\n ' )
308312
309313def extract_create_build_opt_file (globals_h_fqfn , file_name , build_opt_fqfn ):
310314 """
@@ -313,8 +317,9 @@ def extract_create_build_opt_file(globals_h_fqfn, file_name, build_opt_fqfn):
313317 copy of Sketch.ino.globals.h.
314318 """
315319 global build_opt_signature
320+ global default_encoding
316321
317- build_opt = open (build_opt_fqfn , 'w' , encoding = "utf-8" )
322+ build_opt = open (build_opt_fqfn , 'w' , encoding = default_encoding )
318323 if not os .path .exists (globals_h_fqfn ) or (0 == os .path .getsize (globals_h_fqfn )):
319324 build_opt .close ()
320325 return False
@@ -605,12 +610,63 @@ def parse_args():
605610 # ref nargs='*'', https://stackoverflow.com/a/4480202
606611 # ref no '--n' parameter, https://stackoverflow.com/a/21998252
607612
613+
614+ # retrieve *system* encoding, not the one used by python internally
615+ if sys .version_info >= (3 , 11 ):
616+ def get_encoding ():
617+ return locale .getencoding ()
618+ else :
619+ def get_encoding ():
620+ return locale .getdefaultlocale ()[1 ]
621+
622+
623+ def show_value (desc , value ):
624+ print_dbg (f'{ desc :<40} { value } ' )
625+ return
626+
627+ def locale_dbg ():
628+ show_value ("get_encoding()" , get_encoding ())
629+ show_value ("locale.getdefaultlocale()" , locale .getdefaultlocale ())
630+ show_value ('sys.getfilesystemencoding()' , sys .getfilesystemencoding ())
631+ show_value ("sys.getdefaultencoding()" , sys .getdefaultencoding ())
632+ show_value ("locale.getpreferredencoding(False)" , locale .getpreferredencoding (False ))
633+ try :
634+ show_value ("locale.getpreferredencoding()" , locale .getpreferredencoding ())
635+ except :
636+ pass
637+ show_value ("sys.stdout.encoding" , sys .stdout .encoding )
638+
639+ # use current setting
640+ show_value ("locale.setlocale(locale.LC_ALL, None)" , locale .setlocale (locale .LC_ALL , None ))
641+ try :
642+ show_value ("locale.getencoding()" , locale .getencoding ())
643+ except :
644+ pass
645+ show_value ("locale.getlocale()" , locale .getlocale ())
646+
647+ # use user setting
648+ show_value ("locale.setlocale(locale.LC_ALL, '')" , locale .setlocale (locale .LC_ALL , '' ))
649+ # show_value("locale.getencoding()", locale.getencoding())
650+ show_value ("locale.getlocale()" , locale .getlocale ())
651+ return
652+
653+
608654def main ():
609655 global build_opt_signature
610656 global docs_url
611657 global debug_enabled
658+ global default_encoding
612659 num_include_lines = 1
613660
661+ # Given that GCC will handle lines from an @file as if they were on
662+ # the command line. I assume that the contents of @file need to be encoded
663+ # to match that of the shell running GCC runs. I am not 100% sure this API
664+ # gives me that, but it appears to work.
665+ #
666+ # However, elsewhere when dealing with source code we continue to use 'utf-8',
667+ # ref. https://gcc.gnu.org/onlinedocs/cpp/Character-sets.html
668+ default_encoding = get_encoding ()
669+
614670 args = parse_args ()
615671 debug_enabled = args .debug
616672 runtime_ide_path = os .path .normpath (args .runtime_ide_path )
@@ -623,6 +679,13 @@ def main():
623679 build_path_core , build_opt_name = os .path .split (build_opt_fqfn )
624680 globals_h_fqfn = os .path .join (build_path_core , globals_name )
625681
682+ if debug_enabled :
683+ locale_dbg ()
684+
685+ default_locale = locale .getdefaultlocale ()
686+ print_msg (f'default locale: { default_locale } ' )
687+ print_msg (f'default_encoding: { default_encoding } ' )
688+
626689 print_dbg (f"runtime_ide_path: { runtime_ide_path } " )
627690 print_dbg (f"runtime_ide_version: { args .runtime_ide_version } " )
628691 print_dbg (f"build_path: { build_path } " )
@@ -655,6 +718,10 @@ def main():
655718 print_dbg (f"first_time: { first_time } " )
656719 print_dbg (f"use_aggressive_caching_workaround: { use_aggressive_caching_workaround } " )
657720
721+ if not os .path .exists (build_path_core ):
722+ os .makedirs (build_path_core )
723+ print_msg ("Clean build, created dir " + build_path_core )
724+
658725 if first_time or \
659726 not use_aggressive_caching_workaround or \
660727 not os .path .exists (commonhfile_fqfn ):
@@ -667,10 +734,6 @@ def main():
667734 touch (commonhfile_fqfn )
668735 print_err (f"Neutralized future timestamp on build file: { commonhfile_fqfn } " )
669736
670- if not os .path .exists (build_path_core ):
671- os .makedirs (build_path_core )
672- print_msg ("Clean build, created dir " + build_path_core )
673-
674737 if os .path .exists (source_globals_h_fqfn ):
675738 print_msg ("Using global include from " + source_globals_h_fqfn )
676739
@@ -750,4 +813,10 @@ def main():
750813 handle_error (0 ) # commit print buffer
751814
752815if __name__ == '__main__' :
753- sys .exit (main ())
816+ rc = 1
817+ try :
818+ rc = main ()
819+ except :
820+ print_err (traceback .format_exc ())
821+ handle_error (0 )
822+ sys .exit (rc )
0 commit comments