4
4
from datetime import timedelta
5
5
import json
6
6
import os
7
+ from packaging import version
7
8
import re
8
9
import shutil
9
10
import subprocess
52
53
arch = arch_default
53
54
arduino_platform = arduino_platform_default
54
55
arduino_cli = ""
56
+ arduino_cli_default_version = "0.10.0"
57
+ arduino_cli_version = arduino_cli_default_version
55
58
56
59
# List
57
60
sketch_list = []
@@ -117,9 +120,8 @@ def create_output_log_tree():
117
120
file .write (build_separator + "\n " )
118
121
# Folders
119
122
for board in board_fqbn :
123
+ createFolder (os .path .join (output_dir , board , bin_dir ))
120
124
createFolder (os .path .join (output_dir , board ))
121
- if args .bin :
122
- createFolder (os .path .join (output_dir , board , bin_dir ))
123
125
createFolder (os .path .join (build_output_dir , board ))
124
126
125
127
@@ -152,12 +154,15 @@ def create_config():
152
154
153
155
def check_config ():
154
156
global arduino_cli
157
+ global arduino_cli_version
155
158
global arduino_cli_path
156
159
global sketches_path_list
157
160
global build_output_dir
158
161
global root_output_dir
159
162
global output_dir
160
163
global log_file
164
+ global stm32_url
165
+
161
166
if args .ci is False :
162
167
if os .path .isfile (path_config_filename ):
163
168
try :
@@ -193,37 +198,69 @@ def check_config():
193
198
else :
194
199
arduino_cli = "arduino-cli"
195
200
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
+
196
223
try :
197
224
output = subprocess .check_output (
198
225
[arduino_cli , "core" , "search" , "stm32" , "--additional-urls" , stm32_url ],
199
- stderr = subprocess .DEVNULL ,
226
+ stderr = subprocess .STDOUT ,
200
227
)
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 :
201
233
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 )
203
236
# Add core and library path to sketches_path_list
204
237
try :
205
238
output = subprocess .check_output (
206
239
[arduino_cli , "config" , "dump" , "--format" , "json" ],
207
- stderr = subprocess .DEVNULL ,
240
+ stderr = subprocess .STDOUT ,
208
241
).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 :
209
249
cli_config = json .loads (output )
210
250
if cli_config is not None :
211
251
if cli_config ["directories" ]["data" ] is not None :
212
252
sketches_path_list .append (cli_config ["directories" ]["data" ])
213
253
else :
214
- raise subprocess .CalledProcessError (3 , "No data directory" )
254
+ print ("No data directory" )
255
+ quit (1 )
215
256
if cli_config ["directories" ]["user" ] is not None :
216
257
sketches_path_list .append (cli_config ["directories" ]["user" ])
217
258
else :
218
- raise subprocess .CalledProcessError (2 , "No user directory" )
259
+ print ("No user directory!" )
260
+ quit (1 )
219
261
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 )
227
264
228
265
229
266
def load_core_config ():
@@ -366,7 +403,7 @@ def manage_inos():
366
403
break
367
404
else :
368
405
print ("Sketch {} path does not exist!" .format (args .ino ))
369
- quit ()
406
+ quit (1 )
370
407
# Sketches listed in a file
371
408
elif args .file :
372
409
assert os .path .exists (args .file ), "Sketches list file does not exist"
@@ -397,7 +434,7 @@ def manage_inos():
397
434
sketch_list .append (sketch_default )
398
435
if len (sketch_list ) == 0 :
399
436
print ("No sketch to build for " + arduino_platform + "!" )
400
- quit ()
437
+ quit (1 )
401
438
402
439
403
440
# Find all .ino files and save directory
@@ -429,32 +466,41 @@ def find_board():
429
466
try :
430
467
output = subprocess .check_output (
431
468
[arduino_cli , "board" , "listall" , "--format" , "json" ],
432
- stderr = subprocess .DEVNULL ,
469
+ stderr = subprocess .STDOUT ,
433
470
).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 :
434
476
boards_list = json .loads (output )
435
477
if boards_list is not None :
436
478
for board in boards_list ["boards" ]:
437
479
if arduino_platform in board ["FQBN" ]:
438
480
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 )
446
484
447
485
# For STM32 core, pnum is requested
448
486
for fqbn in fqbn_list_tmp :
449
487
try :
450
488
output = subprocess .check_output (
451
489
[arduino_cli , "board" , "details" , "--format" , "json" , fqbn ],
452
- stderr = subprocess .DEVNULL ,
490
+ stderr = subprocess .STDOUT ,
453
491
).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 :
454
499
board_detail = json .loads (output )
455
500
if board_detail is not None :
456
501
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 )
458
504
for option in board_detail ["config_options" ]:
459
505
if option ["option" ] == "pnum" :
460
506
for value in option ["values" ]:
@@ -466,14 +512,12 @@ def find_board():
466
512
)
467
513
break
468
514
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 + '"!' )
472
516
if board_found :
473
517
board_fqbn = collections .OrderedDict (sorted (board_found .items ()))
474
518
else :
475
519
print ("No board found for " + arduino_platform + "!" )
476
- quit ()
520
+ quit (1 )
477
521
478
522
479
523
# Check the status
@@ -484,14 +528,13 @@ def check_status(status, build_conf, boardKo):
484
528
485
529
if status [1 ] == 0 :
486
530
result = "\033 [32msucceeded\033 [0m"
487
- if args .bin :
488
- bin_copy (build_conf [0 ], sketch_name )
489
531
nb_build_passed += 1
490
532
elif status [1 ] == 1 :
491
533
# Check if failed due to a region overflowed
492
534
logFile = os .path .join (build_conf [3 ], sketch_name + ".log" )
493
535
# 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:" )
495
538
ld_pattern = re .compile ("arm-none-eabi/bin/ld:" )
496
539
overflow_pattern = re .compile (
497
540
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):
500
543
for i , line in enumerate (open (logFile )):
501
544
if error_pattern .search (line ):
502
545
error_found = True
546
+ elif fork_pattern .search (line ):
547
+ error_found = True
503
548
elif ld_pattern .search (line ):
504
549
# If one ld line is not for region overflowed --> failed
505
550
if overflow_pattern .search (line ) is None :
@@ -514,8 +559,6 @@ def check_status(status, build_conf, boardKo):
514
559
else :
515
560
# else consider it succeeded
516
561
result = "\033 [32msucceeded*\033 [0m"
517
- if args .bin :
518
- empty_bin (build_conf [0 ], sketch_name )
519
562
nb_build_passed += 1
520
563
else :
521
564
result = "\033 [31merror\033 [0m"
@@ -645,34 +688,6 @@ def log_final_result():
645
688
print (output_dir )
646
689
647
690
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
-
676
691
# Set up specific options to customise arduino builder command
677
692
def get_fqbn (b_name ):
678
693
if b_name in board_custom_fqbn and board_custom_fqbn [b_name ]:
@@ -696,8 +711,12 @@ def genBasicCommand(b_name):
696
711
cmd .append (build_output_cache_dir )
697
712
if args .verbose :
698
713
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 ))
701
720
cmd .append ("--fqbn" )
702
721
cmd .append (get_fqbn (b_name ))
703
722
cmd .append ("dummy_sketch" )
@@ -727,6 +746,9 @@ def build_config(sketch, boardSkipped):
727
746
728
747
for idx in reversed (range (len (build_conf_list ))):
729
748
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
+ )
730
752
if na_sketch_pattern :
731
753
if build_conf_list [idx ][0 ] in na_sketch_pattern :
732
754
for pattern in na_sketch_pattern [build_conf_list [idx ][0 ]]:
@@ -860,12 +882,17 @@ def build(build_conf):
860
882
+ cores_config_file_default ,
861
883
)
862
884
885
+ parser .add_argument (
886
+ "-u" , "--url" , metavar = "<string>" , help = "additional URL for the board manager\
887
+ Default url : "
888
+ + stm32_url ,
889
+ )
890
+
863
891
parser .add_argument (
864
892
"-v" , "--verbose" , help = "enable arduino-cli verbose mode" , action = "store_true"
865
893
)
866
894
867
895
g1 = parser .add_mutually_exclusive_group ()
868
- g1 .add_argument ("--bin" , help = "save binaries" , action = "store_true" )
869
896
g1 .add_argument ("--ci" , help = "custom configuration for CI build" , action = "store_true" )
870
897
871
898
# Sketch options
0 commit comments