Skip to content

Commit b5beb57

Browse files
committed
Consider library.properties when doing default iteration
1 parent 7883dbd commit b5beb57

File tree

3 files changed

+102
-49
lines changed

3 files changed

+102
-49
lines changed

.rubocop.yml

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ Layout/EmptyLinesAroundMethodBody:
4545
Layout/EmptyLinesAroundModuleBody:
4646
Enabled: false
4747

48+
# This can add clarity
49+
Style/CommentedKeyword:
50+
Enabled: false
51+
4852
# Configuration parameters: AllowForAlignment.
4953
Layout/ExtraSpacing:
5054
Enabled: false

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2323
- `assertEqual()` and `assertNotEqual()` use actual `==` and `!=` -- they no longer require a type to be totally ordered just to do equality tests
2424
- Evaluative assertions (is true/false/null/etc) now produce simpler error messages instead of masquerading as an operation (e.g. "== true")
2525
- `LibraryProperties.to_h` now properly uses formatters and symbolic keys, in order to support a `.to_s`
26+
- Architectures from `library.properties` are considered when iterating over unit test or examples compilation, as well as the configured platforms
2627

2728
### Deprecated
2829

exe/arduino_ci.rb

+97-49
Original file line numberDiff line numberDiff line change
@@ -195,19 +195,20 @@ def install_arduino_library_dependencies(library_names, on_behalf_of, already_in
195195
installed
196196
end
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)
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)
201201
# with all platform info, we can extract unique packages and their urls
202202
# do that, set the URLs, and download the packages
203-
all_packages = example_platform_info.values.map { |v| v[:package] }.uniq.reject(&:nil?)
203+
all_packages = specific_config.platform_info.select { |p, _| platforms.include?(p) }.values.map { |v| v[:package] }.compact.uniq
204+
puts "all_packages: #{all_packages}"
204205

205206
# 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+
all_packages.each { |p| assure("Board package #{p} has a defined URL") { specific_config.package_url(p) } }
207208

208209
# set up all the board manager URLs.
209210
# 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+
all_urls = all_packages.map { |p| specific_config.package_url(p) }.compact.uniq
211212
unless all_urls.empty?
212213
assure_multiline("Setting board manager URLs") do
213214
@backend.board_manager_urls = all_urls
@@ -248,17 +249,25 @@ def handle_expectation_of_files(expectation_envvar, operation, filegroup_name, d
248249
end
249250

250251
inform(problem) { dir_path }
252+
explain_and_exercise_envvar(expectation_envvar, operation, "contents of #{dir_desc}") { display_files(dir) }
253+
end
254+
255+
# @param expectation_envvar [String] the name of the env var to check
256+
# @param operation [String] a description of what operation we might be skipping
257+
# @param block_desc [String] a description of what information will be dumped to assist the user
258+
# @param block [Proc] a function that dumps information
259+
def explain_and_exercise_envvar(expectation_envvar, operation, block_desc, &block)
251260
inform("Environment variable #{expectation_envvar} is") { "(#{ENV[expectation_envvar].class}) #{ENV[expectation_envvar]}" }
252261
if ENV[expectation_envvar].nil?
253262
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)
263+
puts " In case that's an error, displaying #{block_desc}:"
264+
block.call
256265
puts " To force an error in this case, set the environment variable #{expectation_envvar}"
257266
true
258267
end
259268
else
260-
assure_multiline("Dumping project's #{dir_desc} before exit") do
261-
display_files(dir)
269+
assure_multiline("Displaying #{block_desc} before exit") do
270+
block.call
262271
false
263272
end
264273
end
@@ -305,6 +314,55 @@ def perform_custom_initialization(_config)
305314
end
306315
end
307316

317+
# Auto-select some platforms to test based on the information available
318+
#
319+
# Top choice is always library.properties -- otherwise use the default.
320+
# But filter that through any non-default config
321+
#
322+
# @param config [CIConfig] the overridden config object
323+
# @param reason [String] description of why we might use this platform (i.e. unittest or compilation)
324+
# @param desired_platforms [Array<String>] the platform names specified
325+
# @param library_properties [Hash] the library properties defined by the library
326+
# @return [Array<String>] platforms to use
327+
def choose_platform_set(config, reason, desired_platforms, library_properties)
328+
329+
# if there are no properties or no architectures, defer entirely to desired platforms
330+
if library_properties.nil? || library_properties.architectures.nil? || library_properties.architectures.empty?
331+
# verify that all platforms exist
332+
desired_platforms.each { |p| assured_platform(reason, p, config) }
333+
return inform_multiline("No architectures listed in library.properties, using configured platforms") do
334+
desired_platforms.each { |p| puts " #{p}" } # this returns desired_platforms
335+
end
336+
end
337+
338+
if library_properties.architectures.include?("*")
339+
return inform_multiline("Wildcard architecture in library.properties, using configured platforms") do
340+
desired_platforms.each { |p| puts " #{p}" } # this returns desired_platforms
341+
end
342+
end
343+
344+
platform_architecture = config.platform_info.transform_values { |v| v[:board].split(":")[1] }
345+
supported_platforms = platform_architecture.select { |_, a| library_properties.architectures.include?(a) }
346+
347+
if config.is_default
348+
# completely ignore default config, opting for brute-force library matches
349+
# OTOH, we don't need to assure platforms because we defined them
350+
return inform_multiline("Default config, platforms matching architectures in library.properties") do
351+
supported_platforms.each_key do |p|
352+
puts " #{p}"
353+
end # this returns supported_platforms
354+
end
355+
end
356+
357+
desired_supported_platforms = supported_platforms.select { |p, _| desired_platforms.include?(p) }.keys
358+
desired_supported_platforms.each { |p| assured_platform(reason, p, config) }
359+
inform_multiline("Configured platforms that match architectures in library.properties") do
360+
desired_supported_platforms.each do |p|
361+
puts " #{p}"
362+
end # this returns supported_platforms
363+
end
364+
end
365+
308366
# Unit test procedure
309367
def perform_unit_tests(cpp_library, file_config)
310368
if @cli_options[:skip_unittests]
@@ -314,7 +372,6 @@ def perform_unit_tests(cpp_library, file_config)
314372

315373
config = file_config.with_override_config(@cli_options[:ci_config])
316374
compilers = get_annotated_compilers(config, cpp_library)
317-
config.platforms_to_unittest.each_with_object({}) { |p, acc| acc[p] = assured_platform("unittest", p, config) }
318375

319376
inform("Library conforms to Arduino library specification") { cpp_library.one_point_five? ? "1.5" : "1.0" }
320377

@@ -324,15 +381,20 @@ def perform_unit_tests(cpp_library, file_config)
324381
return
325382
end
326383

327-
# Handle lack of platforms
328-
if config.platforms_to_unittest.empty?
329-
inform("Skipping unit tests") { "no platforms were requested" }
330-
return
384+
# Get platforms, handle lack of them
385+
platforms = choose_platform_set(config, "unittest", config.platforms_to_unittest, cpp_library.library_properties)
386+
if platforms.empty?
387+
explain_and_exercise_envvar(VAR_EXPECT_UNITTESTS, "unit tests", "platforms and architectures") do
388+
puts " Configured platforms: #{config.platforms_to_unittest}"
389+
puts " Configuration is default: #{config.is_default}"
390+
arches = cpp_library.library_properties.nil? ? nil : cpp_library.library_properties.architectures
391+
puts " Architectures in library.properties: #{arches}"
392+
end
331393
end
332394

333395
install_arduino_library_dependencies(config.aux_libraries_for_unittest, "<unittest/libraries>")
334396

335-
config.platforms_to_unittest.each do |p|
397+
platforms.each do |p|
336398
config.allowable_unittest_files(cpp_library.test_files).each do |unittest_path|
337399
unittest_name = unittest_path.basename.to_s
338400
compilers.each do |gcc_binary|
@@ -363,47 +425,33 @@ def perform_example_compilation_tests(cpp_library, config)
363425
return
364426
end
365427

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-
374428
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
390429

391-
install_all_packages(example_platform_info, board_package_url)
392-
install_arduino_library_dependencies(aux_libraries, "<compile/libraries>")
393-
394-
if config.platforms_to_build.empty?
395-
inform("Skipping builds") { "no platforms were requested" }
396-
return
397-
elsif library_examples.empty?
430+
if library_examples.empty?
398431
handle_expectation_of_files(VAR_EXPECT_EXAMPLES, "builds", "examples", "the examples directory", cpp_library.examples_dir)
399432
return
400433
end
401434

402435
library_examples.each do |example_path|
436+
example_name = File.basename(example_path)
403437
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)
438+
platforms = choose_platform_set(ovr_config, "library example", ovr_config.platforms_to_build, cpp_library.library_properties)
439+
440+
if platforms.empty?
441+
explain_and_exercise_envvar(VAR_EXPECT_EXAMPLES, "examples compilation", "platforms and architectures") do
442+
puts " Configured platforms: #{config.platforms_to_build}"
443+
puts " Configuration is default: #{config.is_default}"
444+
arches = cpp_library.library_properties.nil? ? nil : cpp_library.library_properties.architectures
445+
puts " Architectures in library.properties: #{arches}"
446+
end
447+
end
448+
449+
install_all_packages(platforms, ovr_config)
450+
451+
platforms.each do |p|
452+
install_arduino_library_dependencies(ovr_config.aux_libraries_for_build, "<compile/libraries>")
453+
454+
board = ovr_config.platform_info[p][:board]
407455
attempt("Compiling #{example_name} for #{board}") do
408456
ret = @backend.compile_sketch(example_path, board)
409457
unless ret

0 commit comments

Comments
 (0)