@@ -195,28 +195,20 @@ def install_arduino_library_dependencies(library_names, on_behalf_of, already_in
195195 installed
196196end
197197
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 ) }
218211 end
219- all_packages . each { |p | assure ( "Installing board package #{ p } " ) { @backend . install_boards ( p ) } }
220212end
221213
222214# @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
248240 end
249241
250242 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 )
251251 inform ( "Environment variable #{ expectation_envvar } is" ) { "(#{ ENV [ expectation_envvar ] . class } ) #{ ENV [ expectation_envvar ] } " }
252252 if ENV [ expectation_envvar ] . nil?
253253 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
256256 puts " To force an error in this case, set the environment variable #{ expectation_envvar } "
257257 true
258258 end
259259 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
262262 false
263263 end
264264 end
@@ -305,6 +305,55 @@ def perform_custom_initialization(_config)
305305 end
306306end
307307
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+
308357# Unit test procedure
309358def perform_unit_tests ( cpp_library , file_config )
310359 if @cli_options [ :skip_unittests ]
@@ -314,7 +363,6 @@ def perform_unit_tests(cpp_library, file_config)
314363
315364 config = file_config . with_override_config ( @cli_options [ :ci_config ] )
316365 compilers = get_annotated_compilers ( config , cpp_library )
317- config . platforms_to_unittest . each_with_object ( { } ) { |p , acc | acc [ p ] = assured_platform ( "unittest" , p , config ) }
318366
319367 inform ( "Library conforms to Arduino library specification" ) { cpp_library . one_point_five? ? "1.5" : "1.0" }
320368
@@ -324,15 +372,20 @@ def perform_unit_tests(cpp_library, file_config)
324372 return
325373 end
326374
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
331384 end
332385
333386 install_arduino_library_dependencies ( config . aux_libraries_for_unittest , "<unittest/libraries>" )
334387
335- config . platforms_to_unittest . each do |p |
388+ platforms . each do |p |
336389 config . allowable_unittest_files ( cpp_library . test_files ) . each do |unittest_path |
337390 unittest_name = unittest_path . basename . to_s
338391 compilers . each do |gcc_binary |
@@ -363,47 +416,33 @@ def perform_example_compilation_tests(cpp_library, config)
363416 return
364417 end
365418
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-
374419 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>" )
393420
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?
398422 handle_expectation_of_files ( VAR_EXPECT_EXAMPLES , "builds" , "examples" , "the examples directory" , cpp_library . examples_dir )
399423 return
400424 end
401425
402426 library_examples . each do |example_path |
427+ example_name = File . basename ( example_path )
403428 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 ]
407446 attempt ( "Compiling #{ example_name } for #{ board } " ) do
408447 ret = @backend . compile_sketch ( example_path , board )
409448 unless ret
0 commit comments