From ded345d97db3e881ef4161edbe9a2b0a8f52c32c Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 18 Aug 2020 11:56:46 +0200 Subject: [PATCH 1/3] makefiles/features_check.inc.mk: add _features_one_out_of func --- makefiles/features_check.inc.mk | 63 ++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/makefiles/features_check.inc.mk b/makefiles/features_check.inc.mk index 90b443bb3651..3a9bafa06448 100644 --- a/makefiles/features_check.inc.mk +++ b/makefiles/features_check.inc.mk @@ -1,40 +1,53 @@ # Check if all required FEATURES are provided +# Receives a list of list of '|' separated features and resturns for each +# item in list, the first match that is present in the whitelist. +# +# _features_one_out_of +# +# Parameters +# features-list: list of list of '|' separated features +# e.g.: "periph_spi|periph_i2c puf_sram|periph_hwrng" +# whitelist: possible features to select one out of +# e.g.: "$(FEATURES_PROVIDED)" +# +# One out of Algorithm: +# - For each list in features-list as "item": +# - Store the intersection of features-whitelist and the features in +# "item" in "tmp" +# - Append "item" to "tmp" (with pipes between features, e.g. +# "periph_spi|periph_i2c") +# - Appends the first's element of "tmp" to the caller +# ==> If one (or more) features in whitelist is listed in item, the first +# one will be taken. +# ==> At the end of the list item itself (with pipes between features) is the +# last item in "tmp". If no feature in the feature-list is in whitelist +# this will be the only item in "tmp" and be picked +_features_one_out_of = $(foreach item, $1, $(firstword \ + $(filter $2, $(subst |, ,$(item))) $(item))) + +# Features that are provided and not blacklisted +FEATURES_USABLE := $(filter-out $(FEATURES_BLACKLIST),$(FEATURES_PROVIDED)) + FEATURES_OPTIONAL_ONLY := $(sort $(filter-out $(FEATURES_REQUIRED),$(FEATURES_OPTIONAL))) FEATURES_OPTIONAL_USED := $(sort $(filter $(FEATURES_PROVIDED),$(FEATURES_OPTIONAL_ONLY))) + # Optional features that will not be used because they are not provided FEATURES_OPTIONAL_MISSING := $(sort $(filter-out $(FEATURES_PROVIDED),$(FEATURES_OPTIONAL_ONLY))) # Features that are used without taking "one out of" dependencies into account FEATURES_USED_SO_FAR := $(sort $(FEATURES_REQUIRED) $(FEATURES_OPTIONAL_USED)) -# Features that are provided and not blacklisted -FEATURES_USABLE := $(filter-out $(FEATURES_BLACKLIST),$(FEATURES_PROVIDED)) - # Additionally required features due to the "one out of" dependencies -# Algorithm: -# - For each list in FEATURES_REQUIRED_ANY as "item": -# - Store the intersection of FEATURES_USED_SO_FAR and the features in -# "item" in "tmp" -# - Append the intersection of FEATURES_USABLE and the features in "item" -# to "tmp" -# - Append "item" to "tmp" (with pipes between features, e.g. -# "periph_spi|periph_i2c") -# - Append the first element of "tmp" to FEATURES_REQUIRED_ONE_OUT_OF -# ==> If one (or more) already used features is listed in item, this (or -# one of these) will be in the front of "tmp" and be taken -# ==> If one (or more) usable features is listed in item, this will come -# afterwards. If no no feature in item is used so for, one of the -# features supported and listed in item will be picked -# ==> At the end of the list item itself (with pipes between features) is the -# last item in "tmp". If no feature is item is supported or used, this -# will be the only item in "tmp" and be picked -FEATURES_REQUIRED_ONE_OUT_OF := $(foreach item,\ +# For each features list in $(FEATURES_REQUIRED_ANY): +# ==> If one (or more) features is already used then the first one +# will be taken +# ==> If one (or more) features is usable select the first one in list +# ==> If no feature is usable return the list +FEATURES_REQUIRED_ONE_OUT_OF := $(call _features_one_out_of,\ $(FEATURES_REQUIRED_ANY),\ - $(word 1,\ - $(filter $(FEATURES_USED_SO_FAR) $(FEATURES_USABLE),\ - $(subst |, ,$(item)))\ - $(item))) + $(FEATURES_USED_SO_FAR) \ + $(FEATURES_USABLE)) # Features that are required by the application but not provided by the BSP # Having features missing may case the build to fail. From 1b42a6676678c79e41683d56df9fad2edae75c98 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 18 Aug 2020 11:57:24 +0200 Subject: [PATCH 2/3] makefiles: add FEATURES_OPTIONAL_ANY FEATURES_OPTIONAL_ANY are nice to have FEATURES that fulfill a similar function. Alternatives are separated by a pipe (|) in order of preference. e.g.: FEATURES_OPTIONAL_ANY += puf_sram|periph_hwrng if both are provided then only puf_sram will be used. --- dist/tools/buildsystem_sanity_check/check.sh | 1 + doc/doxygen/src/build-system-basics.md | 5 +++ makefiles/dependencies_debug.inc.mk | 2 ++ makefiles/features_check.inc.mk | 32 ++++++++++++++++++-- makefiles/info.inc.mk | 2 ++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/dist/tools/buildsystem_sanity_check/check.sh b/dist/tools/buildsystem_sanity_check/check.sh index 4c872f886e70..14712c7cdc07 100755 --- a/dist/tools/buildsystem_sanity_check/check.sh +++ b/dist/tools/buildsystem_sanity_check/check.sh @@ -64,6 +64,7 @@ check_not_parsing_features() { patterns+=(-e 'if.*filter.*FEATURES_PROVIDED') patterns+=(-e 'if.*filter.*FEATURES_REQUIRED') patterns+=(-e 'if.*filter.*FEATURES_OPTIONAL') + patterns+=(-e 'if.*filter.*FEATURES_OPTIONAL_ANY') # Pathspec with exclude should start by an inclusive pathspec in git 2.7.4 pathspec+=('*') diff --git a/doc/doxygen/src/build-system-basics.md b/doc/doxygen/src/build-system-basics.md index 433c5c78febd..eaba05a0fbeb 100644 --- a/doc/doxygen/src/build-system-basics.md +++ b/doc/doxygen/src/build-system-basics.md @@ -55,6 +55,11 @@ For a `FEATURE` to be provided by a `board` it must meet 2 criteria, and for - `FEATURES_OPTIONAL` are "nice to have" `FEATURES`, not needed but useful. If available they are always included. +- `FEATURES_OPTIONAL_ANY` are nice to have `FEATURES` that fullfil a similar + function. Alternatives are separated by a pipe (`|`) in order of preference, + e.g.: `FEATURES_OPTIONAL_ANY += puf_sram|periph_hwrng` if both are provided + then only `puf_sram` will be used. + - `FEATURES_REQUIRED_ANY` are `FEATURES` of which (at least) one of is needed by a `MODULE` or `APPLICATION`. Alternatives are separated by a pipe (`|`) in order of preference, e.g.: diff --git a/makefiles/dependencies_debug.inc.mk b/makefiles/dependencies_debug.inc.mk index d8618540dc3e..c09af12b2267 100644 --- a/makefiles/dependencies_debug.inc.mk +++ b/makefiles/dependencies_debug.inc.mk @@ -54,6 +54,7 @@ _DEPS_DEBUG_VARS += BOARD CPU CPU_MODEL CPU_FAM CPU_CORE CPU_ARCH _DEPS_DEBUG_VARS += FEATURES_PROVIDED _FEATURES_PROVIDED_SORTED _DEPS_DEBUG_VARS += FEATURES_REQUIRED _FEATURES_REQUIRED_SORTED _DEPS_DEBUG_VARS += FEATURES_REQUIRED_ANY _FEATURES_REQUIRED_ANY_SORTED +_DEPS_DEBUG_VARS += FEATURES_OPTIONAL_ANY _FEATURES_OPTIONAL_ANY_SORTED _DEPS_DEBUG_VARS += FEATURES_OPTIONAL FEATURES_USED FEATURES_MISSING _DEPS_DEBUG_VARS += FEATURES_CONFLICT FEATURES_CONFLICTING _DEPS_DEBUG_VARS += USEMODULE DEFAULT_MODULE DISABLE_MODULE @@ -62,6 +63,7 @@ DEPS_DEBUG_VARS ?= $(_DEPS_DEBUG_VARS) _FEATURES_PROVIDED_SORTED = $(sort $(FEATURES_PROVIDED)) _FEATURES_REQUIRED_SORTED = $(sort $(FEATURES_REQUIRED)) _FEATURES_REQUIRED_ANY_SORTED = $(sort $(FEATURES_REQUIRED_ANY)) +_FEATURES_OPTIONAL_ANY_SORTED = $(sort $(FEATURES_OPTIONAL_ANY)) file_save_dependencies_variables = $(call file_save_variable,$(DEPENDENCY_DEBUG_OUTPUT_DIR)/$1_$(BOARD),$(DEPS_DEBUG_VARS)) # Remove file before to be sure appending is started with an empty file diff --git a/makefiles/features_check.inc.mk b/makefiles/features_check.inc.mk index 3a9bafa06448..dad326132a87 100644 --- a/makefiles/features_check.inc.mk +++ b/makefiles/features_check.inc.mk @@ -29,11 +29,37 @@ _features_one_out_of = $(foreach item, $1, $(firstword \ # Features that are provided and not blacklisted FEATURES_USABLE := $(filter-out $(FEATURES_BLACKLIST),$(FEATURES_PROVIDED)) -FEATURES_OPTIONAL_ONLY := $(sort $(filter-out $(FEATURES_REQUIRED),$(FEATURES_OPTIONAL))) -FEATURES_OPTIONAL_USED := $(sort $(filter $(FEATURES_PROVIDED),$(FEATURES_OPTIONAL_ONLY))) +# FEATURES_OPTIONAL that have not been required +FEATURES_OPTIONAL_ONLY_SO_FAR := $(sort $(filter-out $(FEATURES_REQUIRED),\ + $(FEATURES_OPTIONAL))) + +# Only add FEATURES that are usable +FEATURES_OPTIONAL_USED_SO_FAR := $(sort $(filter $(FEATURES_USABLE),\ + $(FEATURES_OPTIONAL_ONLY_SO_FAR))) + +# Additionally optional features due to the "one out of" dependencies, +# For each features list in $(FEATURES_OPTIONAL_ANY): +# ==> If one (or more) features is already added to OPTIONAL_USED +# then the firs of the used ones is returned +# ==> If one (or more) features is usable select the first one in list +# ==> If no feature is usable return the list +FEATURES_OPTIONAL_ONE_OUT_OF := $(call _features_one_out_of,\ + $(FEATURES_OPTIONAL_ANY),\ + $(FEATURES_OPTIONAL_USED_SO_FAR) \ + $(FEATURES_USABLE)) + +# FEATURES_OPTIONAL that have not been required +FEATURES_OPTIONAL_ONLY := $(sort $(filter-out $(FEATURES_REQUIRED),\ + $(FEATURES_OPTIONAL_ONE_OUT_OF) \ + $(FEATURES_OPTIONAL))) + +# Only add FEATURES that are usable +FEATURES_OPTIONAL_USED := $(sort $(filter $(FEATURES_USABLE),\ + $(FEATURES_OPTIONAL_ONLY))) # Optional features that will not be used because they are not provided -FEATURES_OPTIONAL_MISSING := $(sort $(filter-out $(FEATURES_PROVIDED),$(FEATURES_OPTIONAL_ONLY))) +FEATURES_OPTIONAL_MISSING := $(sort $(filter-out $(FEATURES_PROVIDED),\ + $(FEATURES_OPTIONAL_ONLY))) # Features that are used without taking "one out of" dependencies into account FEATURES_USED_SO_FAR := $(sort $(FEATURES_REQUIRED) $(FEATURES_OPTIONAL_USED)) diff --git a/makefiles/info.inc.mk b/makefiles/info.inc.mk index 525388355ee2..5de783900988 100644 --- a/makefiles/info.inc.mk +++ b/makefiles/info.inc.mk @@ -60,6 +60,8 @@ info-build: @echo ' $(or $(sort $(FEATURES_REQUIRED_ANY)), -none-)' @echo 'FEATURES_OPTIONAL_ONLY (optional that are not required, strictly "nice to have"):' @echo ' $(or $(FEATURES_OPTIONAL_ONLY), -none-)' + @echo 'FEATURES_OPTIONAL_ANY:' + @echo ' $(or $(sort $(FEATURES_OPTIONAL_ANY)), -none-)' @echo 'FEATURES_OPTIONAL_MISSING (missing optional features):' @echo ' $(or $(FEATURES_OPTIONAL_MISSING), -none-)' @echo 'FEATURES_PROVIDED (by the board or USEMODULE'"'"'d drivers):' From 66f35705ad25d8970defeda0f6bcece390679c50 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Tue, 26 Jan 2021 09:43:08 +0100 Subject: [PATCH 3/3] build_system_check: add FEATURES_REQUIRED_ANY to check_not_parsing_features --- dist/tools/buildsystem_sanity_check/check.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/dist/tools/buildsystem_sanity_check/check.sh b/dist/tools/buildsystem_sanity_check/check.sh index 14712c7cdc07..cfd9022b8b68 100755 --- a/dist/tools/buildsystem_sanity_check/check.sh +++ b/dist/tools/buildsystem_sanity_check/check.sh @@ -63,6 +63,7 @@ check_not_parsing_features() { patterns+=(-e 'if.*filter.*FEATURES_PROVIDED') patterns+=(-e 'if.*filter.*FEATURES_REQUIRED') + patterns+=(-e 'if.*filter.*FEATURES_REQUIRED_ANY') patterns+=(-e 'if.*filter.*FEATURES_OPTIONAL') patterns+=(-e 'if.*filter.*FEATURES_OPTIONAL_ANY')