@@ -195,28 +195,20 @@ def install_arduino_library_dependencies(library_names, on_behalf_of, already_in
195
195
installed
196
196
end
197
197
198
- # @param example_platform_info [Hash] mapping of platform name to package information
199
- # @param board_package_url [Hash] mapping of package name to URL
200
- def install_all_packages ( example_platform_info , board_package_url )
201
- # with all platform info, we can extract unique packages and their urls
202
- # do that, set the URLs, and download the packages
203
- all_packages = example_platform_info . values . map { |v | v [ :package ] } . uniq . reject ( &:nil? )
204
-
205
- # make sure any non-builtin package has a URL defined
206
- all_packages . each { |p | assure ( "Board package #{ p } has a defined URL" ) { board_package_url [ p ] } }
207
-
208
- # set up all the board manager URLs.
209
- # we can safely reject nils now, they would be for the builtins
210
- all_urls = all_packages . map { |p | board_package_url [ p ] } . uniq . reject ( &:nil? )
211
- unless all_urls . empty?
212
- assure_multiline ( "Setting board manager URLs" ) do
213
- @backend . board_manager_urls = all_urls
214
- result = @backend . board_manager_urls
215
- result . each { |u | puts " #{ u } " }
216
- ( all_urls - result ) . empty? # check that all_urls is completely contained in the result
217
- end
198
+ # @param platforms [Array<String>] list of platforms to consider
199
+ # @param specific_config [CIConfig] configuration to use
200
+ def install_all_packages ( platforms , specific_config )
201
+
202
+ # get packages from platforms
203
+ all_packages = specific_config . platform_info . select { |p , _ | platforms . include? ( p ) } . values . map { |v | v [ :package ] } . compact . uniq
204
+
205
+ all_packages . each do |pkg |
206
+ next if @backend . boards_installed? ( pkg )
207
+
208
+ url = assure ( "Board package #{ pkg } has a defined URL" ) { specific_config . package_url ( pkg ) }
209
+ @backend . board_manager_urls = [ url ]
210
+ assure ( "Installing board package #{ pkg } " ) { @backend . install_boards ( pkg ) }
218
211
end
219
- all_packages . each { |p | assure ( "Installing board package #{ p } " ) { @backend . install_boards ( p ) } }
220
212
end
221
213
222
214
# @param expectation_envvar [String] the name of the env var to check
@@ -248,17 +240,25 @@ def handle_expectation_of_files(expectation_envvar, operation, filegroup_name, d
248
240
end
249
241
250
242
inform ( problem ) { dir_path }
243
+ explain_and_exercise_envvar ( expectation_envvar , operation , "contents of #{ dir_desc } " ) { display_files ( dir ) }
244
+ end
245
+
246
+ # @param expectation_envvar [String] the name of the env var to check
247
+ # @param operation [String] a description of what operation we might be skipping
248
+ # @param block_desc [String] a description of what information will be dumped to assist the user
249
+ # @param block [Proc] a function that dumps information
250
+ def explain_and_exercise_envvar ( expectation_envvar , operation , block_desc , &block )
251
251
inform ( "Environment variable #{ expectation_envvar } is" ) { "(#{ ENV [ expectation_envvar ] . class } ) #{ ENV [ expectation_envvar ] } " }
252
252
if ENV [ expectation_envvar ] . nil?
253
253
inform_multiline ( "Skipping #{ operation } " ) do
254
- puts " In case that's an error, this is what was found in the #{ dir_desc } :"
255
- display_files ( dir )
254
+ puts " In case that's an error, displaying #{ block_desc } :"
255
+ block . call
256
256
puts " To force an error in this case, set the environment variable #{ expectation_envvar } "
257
257
true
258
258
end
259
259
else
260
- assure_multiline ( "Dumping project's #{ dir_desc } before exit" ) do
261
- display_files ( dir )
260
+ assure_multiline ( "Displaying #{ block_desc } before exit" ) do
261
+ block . call
262
262
false
263
263
end
264
264
end
@@ -305,6 +305,55 @@ def perform_custom_initialization(_config)
305
305
end
306
306
end
307
307
308
+ # Auto-select some platforms to test based on the information available
309
+ #
310
+ # Top choice is always library.properties -- otherwise use the default.
311
+ # But filter that through any non-default config
312
+ #
313
+ # @param config [CIConfig] the overridden config object
314
+ # @param reason [String] description of why we might use this platform (i.e. unittest or compilation)
315
+ # @param desired_platforms [Array<String>] the platform names specified
316
+ # @param library_properties [Hash] the library properties defined by the library
317
+ # @return [Array<String>] platforms to use
318
+ def choose_platform_set ( config , reason , desired_platforms , library_properties )
319
+
320
+ # if there are no properties or no architectures, defer entirely to desired platforms
321
+ if library_properties . nil? || library_properties . architectures . nil? || library_properties . architectures . empty?
322
+ # verify that all platforms exist
323
+ desired_platforms . each { |p | assured_platform ( reason , p , config ) }
324
+ return inform_multiline ( "No architectures listed in library.properties, using configured platforms" ) do
325
+ desired_platforms . each { |p | puts " #{ p } " } # this returns desired_platforms
326
+ end
327
+ end
328
+
329
+ if library_properties . architectures . include? ( "*" )
330
+ return inform_multiline ( "Wildcard architecture in library.properties, using configured platforms" ) do
331
+ desired_platforms . each { |p | puts " #{ p } " } # this returns desired_platforms
332
+ end
333
+ end
334
+
335
+ platform_architecture = config . platform_info . transform_values { |v | v [ :board ] . split ( ":" ) [ 1 ] }
336
+ supported_platforms = platform_architecture . select { |_ , a | library_properties . architectures . include? ( a ) }
337
+
338
+ if config . is_default
339
+ # completely ignore default config, opting for brute-force library matches
340
+ # OTOH, we don't need to assure platforms because we defined them
341
+ return inform_multiline ( "Default config, platforms matching architectures in library.properties" ) do
342
+ supported_platforms . each_key do |p |
343
+ puts " #{ p } "
344
+ end # this returns supported_platforms
345
+ end
346
+ end
347
+
348
+ desired_supported_platforms = supported_platforms . select { |p , _ | desired_platforms . include? ( p ) } . keys
349
+ desired_supported_platforms . each { |p | assured_platform ( reason , p , config ) }
350
+ inform_multiline ( "Configured platforms that match architectures in library.properties" ) do
351
+ desired_supported_platforms . each do |p |
352
+ puts " #{ p } "
353
+ end # this returns supported_platforms
354
+ end
355
+ end
356
+
308
357
# Unit test procedure
309
358
def perform_unit_tests ( cpp_library , file_config )
310
359
if @cli_options [ :skip_unittests ]
@@ -314,7 +363,6 @@ def perform_unit_tests(cpp_library, file_config)
314
363
315
364
config = file_config . with_override_config ( @cli_options [ :ci_config ] )
316
365
compilers = get_annotated_compilers ( config , cpp_library )
317
- config . platforms_to_unittest . each_with_object ( { } ) { |p , acc | acc [ p ] = assured_platform ( "unittest" , p , config ) }
318
366
319
367
inform ( "Library conforms to Arduino library specification" ) { cpp_library . one_point_five? ? "1.5" : "1.0" }
320
368
@@ -324,15 +372,20 @@ def perform_unit_tests(cpp_library, file_config)
324
372
return
325
373
end
326
374
327
- # Handle lack of platforms
328
- if config . platforms_to_unittest . empty?
329
- inform ( "Skipping unit tests" ) { "no platforms were requested" }
330
- return
375
+ # Get platforms, handle lack of them
376
+ platforms = choose_platform_set ( config , "unittest" , config . platforms_to_unittest , cpp_library . library_properties )
377
+ if platforms . empty?
378
+ explain_and_exercise_envvar ( VAR_EXPECT_UNITTESTS , "unit tests" , "platforms and architectures" ) do
379
+ puts " Configured platforms: #{ config . platforms_to_unittest } "
380
+ puts " Configuration is default: #{ config . is_default } "
381
+ arches = cpp_library . library_properties . nil? ? nil : cpp_library . library_properties . architectures
382
+ puts " Architectures in library.properties: #{ arches } "
383
+ end
331
384
end
332
385
333
386
install_arduino_library_dependencies ( config . aux_libraries_for_unittest , "<unittest/libraries>" )
334
387
335
- config . platforms_to_unittest . each do |p |
388
+ platforms . each do |p |
336
389
config . allowable_unittest_files ( cpp_library . test_files ) . each do |unittest_path |
337
390
unittest_name = unittest_path . basename . to_s
338
391
compilers . each do |gcc_binary |
@@ -363,47 +416,33 @@ def perform_example_compilation_tests(cpp_library, config)
363
416
return
364
417
end
365
418
366
- # gather up all required boards for compilation so we can install them up front.
367
- # start with the "platforms to unittest" and add the examples
368
- # while we're doing that, get the aux libraries as well
369
- example_platform_info = { }
370
- board_package_url = { }
371
- aux_libraries = Set . new ( config . aux_libraries_for_build )
372
- # while collecting the platforms, ensure they're defined
373
-
374
419
library_examples = cpp_library . example_sketches
375
- library_examples . each do |path |
376
- ovr_config = config . from_example ( path )
377
- ovr_config . platforms_to_build . each do |platform |
378
- # assure the platform if we haven't already
379
- next if example_platform_info . key? ( platform )
380
-
381
- platform_info = assured_platform ( "library example" , platform , config )
382
- next if platform_info . nil?
383
-
384
- example_platform_info [ platform ] = platform_info
385
- package = platform_info [ :package ]
386
- board_package_url [ package ] = ovr_config . package_url ( package )
387
- end
388
- aux_libraries . merge ( ovr_config . aux_libraries_for_build )
389
- end
390
-
391
- install_all_packages ( example_platform_info , board_package_url )
392
- install_arduino_library_dependencies ( aux_libraries , "<compile/libraries>" )
393
420
394
- if config . platforms_to_build . empty?
395
- inform ( "Skipping builds" ) { "no platforms were requested" }
396
- return
397
- elsif library_examples . empty?
421
+ if library_examples . empty?
398
422
handle_expectation_of_files ( VAR_EXPECT_EXAMPLES , "builds" , "examples" , "the examples directory" , cpp_library . examples_dir )
399
423
return
400
424
end
401
425
402
426
library_examples . each do |example_path |
427
+ example_name = File . basename ( example_path )
403
428
ovr_config = config . from_example ( example_path )
404
- ovr_config . platforms_to_build . each do |p |
405
- board = example_platform_info [ p ] [ :board ]
406
- example_name = File . basename ( example_path )
429
+ platforms = choose_platform_set ( ovr_config , "library example" , ovr_config . platforms_to_build , cpp_library . library_properties )
430
+
431
+ if platforms . empty?
432
+ explain_and_exercise_envvar ( VAR_EXPECT_EXAMPLES , "examples compilation" , "platforms and architectures" ) do
433
+ puts " Configured platforms: #{ config . platforms_to_build } "
434
+ puts " Configuration is default: #{ config . is_default } "
435
+ arches = cpp_library . library_properties . nil? ? nil : cpp_library . library_properties . architectures
436
+ puts " Architectures in library.properties: #{ arches } "
437
+ end
438
+ end
439
+
440
+ install_all_packages ( platforms , ovr_config )
441
+
442
+ platforms . each do |p |
443
+ install_arduino_library_dependencies ( ovr_config . aux_libraries_for_build , "<compile/libraries>" )
444
+
445
+ board = ovr_config . platform_info [ p ] [ :board ]
407
446
attempt ( "Compiling #{ example_name } for #{ board } " ) do
408
447
ret = @backend . compile_sketch ( example_path , board )
409
448
unless ret
0 commit comments