From 8fb30660b5a9bc2dab2e85ddd77b44981b209d06 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 9 Feb 2021 20:52:31 +0100 Subject: [PATCH 1/3] makefiles/features_check.inc.mk: fix declaration order FEATURES_CONFLICTING previously was declared prior to the function it is calling, resulting in empty output during the first dependency resolution iteration. This fixes the order so that the conflicting features are detected right from the first recursion. --- makefiles/features_check.inc.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/makefiles/features_check.inc.mk b/makefiles/features_check.inc.mk index abca2fb644cb..8438ab5d4510 100644 --- a/makefiles/features_check.inc.mk +++ b/makefiles/features_check.inc.mk @@ -47,11 +47,6 @@ FEATURES_USED := $(sort $(FEATURES_REQUIRED) \ $(FEATURES_REQUIRED_ONE_OUT_OF) \ $(FEATURES_OPTIONAL_USED)) -# Used features that conflict when used together -FEATURES_CONFLICTING := $(sort $(foreach conflict,\ - $(FEATURES_CONFLICT),\ - $(call _features_conflicting,$(conflict)))) - # Return conflicting features from the conflict string feature1:feature2 # $1: feature1:feature2 # Return the list of conflicting features @@ -61,6 +56,11 @@ _features_conflicting = $(if $(call _features_used_conflicting,$(subst :, ,$1)), # Return non empty on error _features_used_conflicting = $(filter $(words $1),$(words $(filter $(FEATURES_USED),$1))) +# Used features that conflict when used together +FEATURES_CONFLICTING := $(sort $(foreach conflict,\ + $(FEATURES_CONFLICT),\ + $(call _features_conflicting,$(conflict)))) + # Features that are used by the application but blacklisted by the BSP. # Having blacklisted features may cause the build to fail. FEATURES_USED_BLACKLISTED := $(sort $(filter $(FEATURES_USED), $(FEATURES_BLACKLIST))) From 4304600512950c6dd63937d17adcb22559e0e55a Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Wed, 10 Feb 2021 09:37:06 +0100 Subject: [PATCH 2/3] build system: fix using optional blacklisted features --- makefiles/features_check.inc.mk | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/makefiles/features_check.inc.mk b/makefiles/features_check.inc.mk index 8438ab5d4510..b10ac34aab68 100644 --- a/makefiles/features_check.inc.mk +++ b/makefiles/features_check.inc.mk @@ -1,16 +1,20 @@ # Check if all required FEATURES are provided +# Features that are provided and not blacklisted +FEATURES_USABLE := $(filter-out $(FEATURES_BLACKLIST),$(FEATURES_PROVIDED)) + +# Features that may be used, if 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))) + +# Optional features that end up being used +FEATURES_OPTIONAL_USED := $(sort $(filter $(FEATURES_USABLE),$(FEATURES_OPTIONAL_ONLY))) + +# Optional features that will not be used because they are not provided or blacklisted +FEATURES_OPTIONAL_MISSING := $(sort $(filter-out $(FEATURES_USABLE),$(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": From ed2ae85985ec2872a2329a13d6a3e2ef6f06a202 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 9 Feb 2021 20:51:06 +0100 Subject: [PATCH 3/3] tests/feature_resolution: add build system unit tests This test "application" contains a set of unit tests for the feature resolution of RIOT's build system. --- dist/tools/ci/static_tests.sh | 1 + dist/tools/feature_resolution/check.sh | 2 ++ makefiles/tests/feature_resolution/Makefile | 12 ++++++++++ .../tests/feature_resolution/Makefile.test | 23 +++++++++++++++++++ makefiles/tests/feature_resolution/README.md | 15 ++++++++++++ .../test-blacklist-failure.mk | 15 ++++++++++++ .../test-blacklist-optional.mk | 15 ++++++++++++ .../test-blacklist-success.mk | 15 ++++++++++++ .../test-complex-failure.mk | 15 ++++++++++++ .../test-complex-success.mk | 15 ++++++++++++ .../test-conflict-failure.mk | 15 ++++++++++++ .../test-conflict-success.mk | 15 ++++++++++++ .../tests/feature_resolution/test-empty.mk | 15 ++++++++++++ .../test-required-any-corner-case.mk | 15 ++++++++++++ .../test-required-any-fail.mk | 15 ++++++++++++ .../test-required-any-order.mk | 15 ++++++++++++ .../test-required-any-reuse-optional.mk | 15 ++++++++++++ .../test-required-any-reuse-required.mk | 15 ++++++++++++ .../test-trivial-failure.mk | 15 ++++++++++++ .../test-trivial-success.mk | 15 ++++++++++++ 20 files changed, 278 insertions(+) create mode 100755 dist/tools/feature_resolution/check.sh create mode 100644 makefiles/tests/feature_resolution/Makefile create mode 100644 makefiles/tests/feature_resolution/Makefile.test create mode 100644 makefiles/tests/feature_resolution/README.md create mode 100644 makefiles/tests/feature_resolution/test-blacklist-failure.mk create mode 100644 makefiles/tests/feature_resolution/test-blacklist-optional.mk create mode 100644 makefiles/tests/feature_resolution/test-blacklist-success.mk create mode 100644 makefiles/tests/feature_resolution/test-complex-failure.mk create mode 100644 makefiles/tests/feature_resolution/test-complex-success.mk create mode 100644 makefiles/tests/feature_resolution/test-conflict-failure.mk create mode 100644 makefiles/tests/feature_resolution/test-conflict-success.mk create mode 100644 makefiles/tests/feature_resolution/test-empty.mk create mode 100644 makefiles/tests/feature_resolution/test-required-any-corner-case.mk create mode 100644 makefiles/tests/feature_resolution/test-required-any-fail.mk create mode 100644 makefiles/tests/feature_resolution/test-required-any-order.mk create mode 100644 makefiles/tests/feature_resolution/test-required-any-reuse-optional.mk create mode 100644 makefiles/tests/feature_resolution/test-required-any-reuse-required.mk create mode 100644 makefiles/tests/feature_resolution/test-trivial-failure.mk create mode 100644 makefiles/tests/feature_resolution/test-trivial-success.mk diff --git a/dist/tools/ci/static_tests.sh b/dist/tools/ci/static_tests.sh index e25ac9ace933..aef94ff74dbf 100755 --- a/dist/tools/ci/static_tests.sh +++ b/dist/tools/ci/static_tests.sh @@ -122,6 +122,7 @@ run ./dist/tools/coccinelle/check.sh run ./dist/tools/flake8/check.sh run ./dist/tools/headerguards/check.sh run ./dist/tools/buildsystem_sanity_check/check.sh +run ./dist/tools/feature_resolution/check.sh run ./dist/tools/codespell/check.sh if [ -z "${GITHUB_RUN_ID}" ]; then run ./dist/tools/uncrustify/uncrustify.sh --check diff --git a/dist/tools/feature_resolution/check.sh b/dist/tools/feature_resolution/check.sh new file mode 100755 index 000000000000..20daea1a16b0 --- /dev/null +++ b/dist/tools/feature_resolution/check.sh @@ -0,0 +1,2 @@ +#!/bin/sh +make --silent -C "$(dirname "$0")"/../../../makefiles/tests/feature_resolution diff --git a/makefiles/tests/feature_resolution/Makefile b/makefiles/tests/feature_resolution/Makefile new file mode 100644 index 000000000000..f3c42efa2515 --- /dev/null +++ b/makefiles/tests/feature_resolution/Makefile @@ -0,0 +1,12 @@ +.PHONY: all info-boards-supported + +TESTS := $(patsubst test-%.mk,run-%,$(wildcard test-*.mk)) + +all: $(TESTS) + +info-boards-supported: + @echo none + +run-%: test-%.mk + @echo "Running test $(patsubst run-%,%,$@)" + @$(MAKE) --silent -f $< diff --git a/makefiles/tests/feature_resolution/Makefile.test b/makefiles/tests/feature_resolution/Makefile.test new file mode 100644 index 000000000000..f6046276113d --- /dev/null +++ b/makefiles/tests/feature_resolution/Makefile.test @@ -0,0 +1,23 @@ +include ../../features_check.inc.mk + +FEATURES_VARS := \ + FEATURES_CONFLICTING \ + FEATURES_USED \ + FEATURES_USED_BLACKLISTED \ + FEATURES_MISSING \ + # + +define _expected = + ifneq ($$(EXPECTED_$1),$$($1)) + $$(info EXPECTED_$1 = $$(EXPECTED_$1)) + $$(info $1 = $$($1)) + $$(error $1 incorrectly resolved) + endif +endef + +$(foreach var,$(FEATURES_VARS),$(eval $(call _expected,$(var)))) + + +.PHONY: all +all: + @echo Success diff --git a/makefiles/tests/feature_resolution/README.md b/makefiles/tests/feature_resolution/README.md new file mode 100644 index 000000000000..0f94aab5c1e1 --- /dev/null +++ b/makefiles/tests/feature_resolution/README.md @@ -0,0 +1,15 @@ +Simple Unit Tests for Feature Resolution +======================================== + +This folder contains a Makefile that runs a set of unit tests for the feature resolution logic. +Each unit test is defined in a file named `tests-.mk` in which the inputs and the +expected outputs are defined. Finally, the include `Makefile.test`, which will perform the tests. + +The tests can be run simply by typing `make`. Also, `make static-test` at the root of the repo will +run these tests and, hence, these tests are also executed on each CI run. + +Adding new Test Cases +--------------------- + +Just create a new `tests-.mk` file and start with the contests of an existing +test case and change the inputs and expected outputs accordingly. diff --git a/makefiles/tests/feature_resolution/test-blacklist-failure.mk b/makefiles/tests/feature_resolution/test-blacklist-failure.mk new file mode 100644 index 000000000000..f89a8d1997e7 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-blacklist-failure.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := b +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := b +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-blacklist-optional.mk b/makefiles/tests/feature_resolution/test-blacklist-optional.mk new file mode 100644 index 000000000000..94112cc4529a --- /dev/null +++ b/makefiles/tests/feature_resolution/test-blacklist-optional.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := c +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := c +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-blacklist-success.mk b/makefiles/tests/feature_resolution/test-blacklist-success.mk new file mode 100644 index 000000000000..d4955218eaae --- /dev/null +++ b/makefiles/tests/feature_resolution/test-blacklist-success.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := c +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-complex-failure.mk b/makefiles/tests/feature_resolution/test-complex-failure.mk new file mode 100644 index 000000000000..b371a89156cf --- /dev/null +++ b/makefiles/tests/feature_resolution/test-complex-failure.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := a b +FEATURES_REQUIRED := c d +FEATURES_REQUIRED_ANY := e|f|d a|h|i +FEATURES_PROVIDED := a b c d e f g +FEATURES_BLACKLIST := a +FEATURES_CONFLICT := f:e c:d + +# expected results +EXPECTED_FEATURES_USED := a|h|i b c d +EXPECTED_FEATURES_MISSING := a|h|i +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := c d + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-complex-success.mk b/makefiles/tests/feature_resolution/test-complex-success.mk new file mode 100644 index 000000000000..5b15ec093aee --- /dev/null +++ b/makefiles/tests/feature_resolution/test-complex-success.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := a b +FEATURES_REQUIRED := c d +FEATURES_REQUIRED_ANY := e|f|d +FEATURES_PROVIDED := a b c d e f g +FEATURES_BLACKLIST := a +FEATURES_CONFLICT := f:e + +# expected results +EXPECTED_FEATURES_USED := b c d +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-conflict-failure.mk b/makefiles/tests/feature_resolution/test-conflict-failure.mk new file mode 100644 index 000000000000..fcfc9e6661b8 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-conflict-failure.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a b c d +FEATURES_BLACKLIST := +FEATURES_CONFLICT := a:b c:d + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := a b + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-conflict-success.mk b/makefiles/tests/feature_resolution/test-conflict-success.mk new file mode 100644 index 000000000000..cdbd738d79f4 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-conflict-success.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a c +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a b c d +FEATURES_BLACKLIST := +FEATURES_CONFLICT := a:b c:d + +# expected results +EXPECTED_FEATURES_USED := a c +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-empty.mk b/makefiles/tests/feature_resolution/test-empty.mk new file mode 100644 index 000000000000..e5df3be88dfa --- /dev/null +++ b/makefiles/tests/feature_resolution/test-empty.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-required-any-corner-case.mk b/makefiles/tests/feature_resolution/test-required-any-corner-case.mk new file mode 100644 index 000000000000..6583cba8c2c6 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-required-any-corner-case.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a +FEATURES_REQUIRED_ANY := b +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-required-any-fail.mk b/makefiles/tests/feature_resolution/test-required-any-fail.mk new file mode 100644 index 000000000000..137614e95ee3 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-required-any-fail.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := +FEATURES_REQUIRED_ANY := d|b|a +FEATURES_PROVIDED := c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := d|b|a +EXPECTED_FEATURES_MISSING := d|b|a +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-required-any-order.mk b/makefiles/tests/feature_resolution/test-required-any-order.mk new file mode 100644 index 000000000000..d1314debea15 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-required-any-order.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := +FEATURES_REQUIRED_ANY := d|b|a +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-required-any-reuse-optional.mk b/makefiles/tests/feature_resolution/test-required-any-reuse-optional.mk new file mode 100644 index 000000000000..ce5888f11aa3 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-required-any-reuse-optional.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := a +FEATURES_REQUIRED := +FEATURES_REQUIRED_ANY := d|b|a +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-required-any-reuse-required.mk b/makefiles/tests/feature_resolution/test-required-any-reuse-required.mk new file mode 100644 index 000000000000..24f4ec292f6c --- /dev/null +++ b/makefiles/tests/feature_resolution/test-required-any-reuse-required.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := c|b +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-trivial-failure.mk b/makefiles/tests/feature_resolution/test-trivial-failure.mk new file mode 100644 index 000000000000..89992cfde862 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-trivial-failure.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := b +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test diff --git a/makefiles/tests/feature_resolution/test-trivial-success.mk b/makefiles/tests/feature_resolution/test-trivial-success.mk new file mode 100644 index 000000000000..d11e8038e0e4 --- /dev/null +++ b/makefiles/tests/feature_resolution/test-trivial-success.mk @@ -0,0 +1,15 @@ +# inputs +FEATURES_OPTIONAL := +FEATURES_REQUIRED := a b +FEATURES_REQUIRED_ANY := +FEATURES_PROVIDED := a b c +FEATURES_BLACKLIST := +FEATURES_CONFLICT := + +# expected results +EXPECTED_FEATURES_USED := a b +EXPECTED_FEATURES_MISSING := +EXPECTED_FEATURES_USED_BLACKLISTED := +EXPECTED_FEATURES_CONFLICTING := + +include Makefile.test