44from datetime import timedelta
55import json
66import os
7+ from packaging import version
78import re
89import shutil
910import subprocess
5253arch = arch_default
5354arduino_platform = arduino_platform_default
5455arduino_cli = ""
56+ arduino_cli_default_version = "0.10.0"
57+ arduino_cli_version = arduino_cli_default_version
5558
5659# List
5760sketch_list = []
@@ -117,9 +120,8 @@ def create_output_log_tree():
117120 file .write (build_separator + "\n " )
118121 # Folders
119122 for board in board_fqbn :
123+ createFolder (os .path .join (output_dir , board , bin_dir ))
120124 createFolder (os .path .join (output_dir , board ))
121- if args .bin :
122- createFolder (os .path .join (output_dir , board , bin_dir ))
123125 createFolder (os .path .join (build_output_dir , board ))
124126
125127
@@ -152,12 +154,15 @@ def create_config():
152154
153155def check_config ():
154156 global arduino_cli
157+ global arduino_cli_version
155158 global arduino_cli_path
156159 global sketches_path_list
157160 global build_output_dir
158161 global root_output_dir
159162 global output_dir
160163 global log_file
164+ global stm32_url
165+
161166 if args .ci is False :
162167 if os .path .isfile (path_config_filename ):
163168 try :
@@ -193,37 +198,69 @@ def check_config():
193198 else :
194199 arduino_cli = "arduino-cli"
195200
201+ try :
202+ output = subprocess .check_output (
203+ [arduino_cli , "version" ], stderr = subprocess .STDOUT ,
204+ )
205+ except subprocess .CalledProcessError as e :
206+ print ('"' + " " .join (e .cmd ) + '" failed with code: {}!' .format (e .returncode ))
207+ print (e .stdout .decode ("utf-8" ))
208+ quit (e .returncode )
209+ else :
210+ res = re .match (r".*Version:\s+(\d+\.\d+\.\d+).*" , output .decode ("utf-8" ))
211+ if res :
212+ arduino_cli_version = res .group (1 )
213+ print ("Arduino CLI version used: " + arduino_cli_version )
214+ else :
215+ print (
216+ "Unable to define Arduino CLI version, use default: "
217+ + arduino_cli_default_version
218+ )
219+
220+ if args .url :
221+ stm32_url = args .url
222+
196223 try :
197224 output = subprocess .check_output (
198225 [arduino_cli , "core" , "search" , "stm32" , "--additional-urls" , stm32_url ],
199- stderr = subprocess .DEVNULL ,
226+ stderr = subprocess .STDOUT ,
200227 )
228+ except subprocess .CalledProcessError as e :
229+ print ('"' + " " .join (e .cmd ) + '" failed with code: {}!' .format (e .returncode ))
230+ print (e .stdout .decode ("utf-8" ))
231+ quit (e .returncode )
232+ else :
201233 if arduino_platform not in output .decode ("utf-8" ):
202- raise subprocess .CalledProcessError (1 , "re" )
234+ print (arduino_platform + " is not installed!" )
235+ quit (1 )
203236 # Add core and library path to sketches_path_list
204237 try :
205238 output = subprocess .check_output (
206239 [arduino_cli , "config" , "dump" , "--format" , "json" ],
207- stderr = subprocess .DEVNULL ,
240+ stderr = subprocess .STDOUT ,
208241 ).decode ("utf-8" )
242+ except subprocess .CalledProcessError as e :
243+ print (
244+ '"' + " " .join (e .cmd ) + '" failed with code: {}!' .format (e .returncode )
245+ )
246+ print (e .stdout .decode ("utf-8" ))
247+ quit (e .returncode )
248+ else :
209249 cli_config = json .loads (output )
210250 if cli_config is not None :
211251 if cli_config ["directories" ]["data" ] is not None :
212252 sketches_path_list .append (cli_config ["directories" ]["data" ])
213253 else :
214- raise subprocess .CalledProcessError (3 , "No data directory" )
254+ print ("No data directory" )
255+ quit (1 )
215256 if cli_config ["directories" ]["user" ] is not None :
216257 sketches_path_list .append (cli_config ["directories" ]["user" ])
217258 else :
218- raise subprocess .CalledProcessError (2 , "No user directory" )
259+ print ("No user directory!" )
260+ quit (1 )
219261 else :
220- raise subprocess .CalledProcessError (1 , "No fqbn" )
221- except subprocess .CalledProcessError :
222- print ("No arduino-cli config!" )
223- quit ()
224- except subprocess .CalledProcessError :
225- print (arduino_platform + " is not installed!" )
226- quit ()
262+ print ("No arduino-cli config!" )
263+ quit (1 )
227264
228265
229266def load_core_config ():
@@ -366,7 +403,7 @@ def manage_inos():
366403 break
367404 else :
368405 print ("Sketch {} path does not exist!" .format (args .ino ))
369- quit ()
406+ quit (1 )
370407 # Sketches listed in a file
371408 elif args .file :
372409 assert os .path .exists (args .file ), "Sketches list file does not exist"
@@ -397,7 +434,7 @@ def manage_inos():
397434 sketch_list .append (sketch_default )
398435 if len (sketch_list ) == 0 :
399436 print ("No sketch to build for " + arduino_platform + "!" )
400- quit ()
437+ quit (1 )
401438
402439
403440# Find all .ino files and save directory
@@ -429,32 +466,41 @@ def find_board():
429466 try :
430467 output = subprocess .check_output (
431468 [arduino_cli , "board" , "listall" , "--format" , "json" ],
432- stderr = subprocess .DEVNULL ,
469+ stderr = subprocess .STDOUT ,
433470 ).decode ("utf-8" )
471+ except subprocess .CalledProcessError as e :
472+ print ('"' + " " .join (e .cmd ) + '" failed with code: {}!' .format (e .returncode ))
473+ print (e .stdout .decode ("utf-8" ))
474+ quit (e .returncode )
475+ else :
434476 boards_list = json .loads (output )
435477 if boards_list is not None :
436478 for board in boards_list ["boards" ]:
437479 if arduino_platform in board ["FQBN" ]:
438480 fqbn_list_tmp .append (board ["FQBN" ])
439- if not len (fqbn_list_tmp ):
440- raise subprocess .CalledProcessError (2 , "No fqbn" )
441- else :
442- raise subprocess .CalledProcessError (1 , "No fqbn" )
443- except subprocess .CalledProcessError :
444- print ("No fqbn found for " + arduino_platform + "!" )
445- quit ()
481+ if not len (fqbn_list_tmp ):
482+ print ("No boards found for " + arduino_platform )
483+ quit (1 )
446484
447485 # For STM32 core, pnum is requested
448486 for fqbn in fqbn_list_tmp :
449487 try :
450488 output = subprocess .check_output (
451489 [arduino_cli , "board" , "details" , "--format" , "json" , fqbn ],
452- stderr = subprocess .DEVNULL ,
490+ stderr = subprocess .STDOUT ,
453491 ).decode ("utf-8" )
492+ except subprocess .CalledProcessError as e :
493+ print (
494+ '"' + " " .join (e .cmd ) + '" failed with code: {}!' .format (e .returncode )
495+ )
496+ print (e .stdout .decode ("utf-8" ))
497+ quit (e .returncode )
498+ else :
454499 board_detail = json .loads (output )
455500 if board_detail is not None :
456501 if "config_options" not in board_detail :
457- raise subprocess .CalledProcessError (3 , "No config_options" )
502+ print ("No config_options found for " + fqbn )
503+ quit (1 )
458504 for option in board_detail ["config_options" ]:
459505 if option ["option" ] == "pnum" :
460506 for value in option ["values" ]:
@@ -466,14 +512,12 @@ def find_board():
466512 )
467513 break
468514 else :
469- raise subprocess .CalledProcessError (1 , "No fqbn" )
470- except subprocess .CalledProcessError as e :
471- print ("No fqbn detail found for " + e .cmd + "!" )
515+ print ('No detail found for:"' + fqbn + '"!' )
472516 if board_found :
473517 board_fqbn = collections .OrderedDict (sorted (board_found .items ()))
474518 else :
475519 print ("No board found for " + arduino_platform + "!" )
476- quit ()
520+ quit (1 )
477521
478522
479523# Check the status
@@ -484,14 +528,13 @@ def check_status(status, build_conf, boardKo):
484528
485529 if status [1 ] == 0 :
486530 result = "\033 [32msucceeded\033 [0m"
487- if args .bin :
488- bin_copy (build_conf [0 ], sketch_name )
489531 nb_build_passed += 1
490532 elif status [1 ] == 1 :
491533 # Check if failed due to a region overflowed
492534 logFile = os .path .join (build_conf [3 ], sketch_name + ".log" )
493535 # error or fatal error
494- error_pattern = re .compile (r":\d+:\d+:\s.*error:\s" )
536+ fork_pattern = re .compile (r"^Error during build: fork/exec" )
537+ error_pattern = re .compile (r":\d+:\d+:\s.*error:\s|^Error:" )
495538 ld_pattern = re .compile ("arm-none-eabi/bin/ld:" )
496539 overflow_pattern = re .compile (
497540 r"(will not fit in |section .+ is not within )?region( .+ overflowed by [\d]+ bytes)?"
@@ -500,6 +543,8 @@ def check_status(status, build_conf, boardKo):
500543 for i , line in enumerate (open (logFile )):
501544 if error_pattern .search (line ):
502545 error_found = True
546+ elif fork_pattern .search (line ):
547+ error_found = True
503548 elif ld_pattern .search (line ):
504549 # If one ld line is not for region overflowed --> failed
505550 if overflow_pattern .search (line ) is None :
@@ -514,8 +559,6 @@ def check_status(status, build_conf, boardKo):
514559 else :
515560 # else consider it succeeded
516561 result = "\033 [32msucceeded*\033 [0m"
517- if args .bin :
518- empty_bin (build_conf [0 ], sketch_name )
519562 nb_build_passed += 1
520563 else :
521564 result = "\033 [31merror\033 [0m"
@@ -645,34 +688,6 @@ def log_final_result():
645688 print (output_dir )
646689
647690
648- # Create an empty binary
649- def empty_bin (board_name , sketch_name ):
650- empty_path = os .path .abspath (os .path .join (output_dir , board_name , bin_dir ))
651- createFolder (empty_path )
652- empty_file = os .path .join (
653- empty_path , sketch_name + "_COULD_NOT_FIT_IN_THIS_BOARD.bin"
654- )
655- try :
656- f = open (empty_file , "w" )
657- except IOError :
658- print ("Cannot create empty binary: " , empty_file )
659- else :
660- f .close ()
661-
662-
663- # Create a "bin" directory for each board and copy all binary files
664- # from the builder output directory into it
665- def bin_copy (board_name , sketch_name ):
666- try :
667- shutil .copy (
668- os .path .join (build_output_dir , board_name , sketch_name + ".bin" ),
669- os .path .abspath (os .path .join (output_dir , board_name , bin_dir )),
670- )
671- except OSError as e :
672- print ("Cannot copy the binary from the arduino-cli output: " + e .strerror )
673- raise
674-
675-
676691# Set up specific options to customise arduino builder command
677692def get_fqbn (b_name ):
678693 if b_name in board_custom_fqbn and board_custom_fqbn [b_name ]:
@@ -696,8 +711,12 @@ def genBasicCommand(b_name):
696711 cmd .append (build_output_cache_dir )
697712 if args .verbose :
698713 cmd .append ("--verbose" )
699- cmd .append ("-o" )
700- cmd .append (os .path .join (build_output_dir , b_name , "sketch" ))
714+ if version .parse (arduino_cli_version ) <= version .parse (arduino_cli_default_version ):
715+ cmd .append ("--output" )
716+ cmd .append (os .path .join (output_dir , b_name , bin_dir , "dummy_sketch" ))
717+ else :
718+ cmd .append ("--output-dir" )
719+ cmd .append (os .path .join (output_dir , b_name , bin_dir ))
701720 cmd .append ("--fqbn" )
702721 cmd .append (get_fqbn (b_name ))
703722 cmd .append ("dummy_sketch" )
@@ -727,6 +746,9 @@ def build_config(sketch, boardSkipped):
727746
728747 for idx in reversed (range (len (build_conf_list ))):
729748 build_conf_list [idx ][4 ][- 1 ] = sketch
749+ build_conf_list [idx ][4 ][- 4 ] = build_conf_list [idx ][4 ][- 4 ].replace (
750+ "dummy_sketch" , os .path .basename (sketch )
751+ )
730752 if na_sketch_pattern :
731753 if build_conf_list [idx ][0 ] in na_sketch_pattern :
732754 for pattern in na_sketch_pattern [build_conf_list [idx ][0 ]]:
@@ -860,12 +882,17 @@ def build(build_conf):
860882 + cores_config_file_default ,
861883)
862884
885+ parser .add_argument (
886+ "-u" , "--url" , metavar = "<string>" , help = "additional URL for the board manager\
887+ Default url : "
888+ + stm32_url ,
889+ )
890+
863891parser .add_argument (
864892 "-v" , "--verbose" , help = "enable arduino-cli verbose mode" , action = "store_true"
865893)
866894
867895g1 = parser .add_mutually_exclusive_group ()
868- g1 .add_argument ("--bin" , help = "save binaries" , action = "store_true" )
869896g1 .add_argument ("--ci" , help = "custom configuration for CI build" , action = "store_true" )
870897
871898# Sketch options
0 commit comments