Skip to content

Commit 81ff6db

Browse files
committed
Consider library.properties when doing default iteration
1 parent 80740b7 commit 81ff6db

File tree

3 files changed

+108
-64
lines changed

3 files changed

+108
-64
lines changed

Diff for: .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

Diff for: CHANGELOG.md

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

2829
### Deprecated
2930

Diff for: exe/arduino_ci.rb

+103-64
Original file line numberDiff line numberDiff line change
@@ -195,28 +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)
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) } }
220212
end
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
306306
end
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
309358
def 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

Comments
 (0)