Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dist/tools/buildsystem_sanity_check/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ 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')

# Pathspec with exclude should start by an inclusive pathspec in git 2.7.4
pathspec+=('*')
Expand Down
5 changes: 5 additions & 0 deletions doc/doxygen/src/build-system-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.:
Expand Down
2 changes: 2 additions & 0 deletions makefiles/dependencies_debug.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
95 changes: 67 additions & 28 deletions makefiles/features_check.inc.mk
Original file line number Diff line number Diff line change
@@ -1,40 +1,79 @@
# Check if all required FEATURES are provided

FEATURES_OPTIONAL_ONLY := $(sort $(filter-out $(FEATURES_REQUIRED),$(FEATURES_OPTIONAL)))
FEATURES_OPTIONAL_USED := $(sort $(filter $(FEATURES_PROVIDED),$(FEATURES_OPTIONAL_ONLY)))
# 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 <features-list> <whitelist>
#
# 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 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))

# 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.
Expand Down
2 changes: 2 additions & 0 deletions makefiles/info.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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):'
Expand Down