diff --git a/Makefile.buildtests b/Makefile.buildtests index 4a80aa47e1a95d1a1c06cd4e0483293d17ce48c7..d11d9da1d18d8524a1535c70154e34e317959242 100644 --- a/Makefile.buildtests +++ b/Makefile.buildtests @@ -164,6 +164,9 @@ info-build: @echo 'FEATURES_MISSING (only non-optional features):' @echo ' $(or $(sort $(filter-out $(FEATURES_OPTIONAL) $(FEATURES_PROVIDED), $(FEATURES_REQUIRED))), -none-)' @echo '' + @echo 'FEATURES_CONFLICT: $(FEATURES_CONFLICT)' + @echo 'FEATURES_CONFLICT_MSG: $(FEATURES_CONFLICT_MSG)' + @echo '' @echo 'CC: $(CC)' @echo -e 'CFLAGS:$(patsubst %, \n\t%, $(CFLAGS))' @echo '' diff --git a/Makefile.include b/Makefile.include index 8a543ba0a30dd64424771c0ebf496ca5d4c543d8..2177dadf1a1fe353aca0838d1a728b32be1c0674 100644 --- a/Makefile.include +++ b/Makefile.include @@ -37,6 +37,7 @@ ifeq (, ${JENKINS_URL}) ifeq (0, $(shell tput colors 2>&1 > /dev/null; echo $$?)) COLOR_GREEN := \033[1;32m COLOR_RED := \033[1;31m + COLOR_YELLOW := \033[1;33m COLOR_PURPLE := \033[1;35m COLOR_RESET := \033[0m ifeq ($(OS),Darwin) @@ -316,6 +317,7 @@ include $(RIOTBASE)/Makefile.vars # Warn if the selected board and drivers don't provide all needed featues: ifneq (, $(filter all, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all))) EXPECT_ERRORS := + EXPECT_CONFLICT := # Test if there where dependencies against a module in DISABLE_MODULE. ifneq (, $(filter $(DISABLE_MODULE), $(USEMODULE))) @@ -331,6 +333,17 @@ ifneq (, $(filter all, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all))) EXPECT_ERRORS := 1 endif + # Test if any required feature conflict with another one. + CONFLICT := $(foreach var,$(FEATURES_CONFLICT),$(if $(filter $(words $(subst :, ,$(var))),$(words $(filter $(FEATURES_REQUIRED),$(subst :, ,$(var))))),$(subst :, ,$(var)))) + ifneq (, $(strip $(CONFLICT))) + $(shell $(COLOR_ECHO) "$(COLOR_YELLOW)The following features may conflict:$(COLOR_RESET)"\ + "$(COLOR_GREEN)$(sort $(filter $(FEATURES_REQUIRED), $(CONFLICT)))$(COLOR_RESET)" 1>&2) + ifneq (, $(FEATURES_CONFLICT_MSG)) + $(shell $(COLOR_ECHO) "$(COLOR_YELLOW)Rationale: $(COLOR_RESET)$(FEATURES_CONFLICT_MSG)" 1>&2) + endif + EXPECT_CONFLICT := 1 + endif + # If there is a whitelist, then test if the board is whitelisted. ifneq (, $(BOARD_WHITELIST)) ifeq (, $(filter $(BOARD_WHITELIST), $(BOARD))) @@ -347,9 +360,14 @@ ifneq (, $(filter all, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all))) endif endif + ifneq (, $(EXPECT_CONFLICT)) + $(shell $(COLOR_ECHO) "\n$(COLOR_YELLOW)EXPECT undesired behaviour!$(COLOR_RESET)" 1>&2) + endif + ifneq (, $(EXPECT_ERRORS)) $(shell $(COLOR_ECHO) "\n\n$(COLOR_RED)EXPECT ERRORS!$(COLOR_RESET)\n\n" 1>&2) endif + endif else # RIOT_VERSION diff --git a/boards/stm32f4discovery/Makefile.features b/boards/stm32f4discovery/Makefile.features index bf0edc3fb0fe96db197b8646d7e5a003a798d8c3..f17556808cc5a09b9cf422640cdcee4416f25e27 100644 --- a/boards/stm32f4discovery/Makefile.features +++ b/boards/stm32f4discovery/Makefile.features @@ -9,3 +9,7 @@ FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_dac FEATURES_PROVIDED += periph_cpuid FEATURES_MCU_GROUP = cortex_m4 + +FEATURES_CONFLICT += periph_spi:periph_dac + +FEATURES_CONFLICT_MSG += "On stm32f4discovery boards there are the same pins for the DAC and/or SPI_0." diff --git a/tests/warn_conflict/Makefile b/tests/warn_conflict/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e3c6cd2750c2c2b50a608159b182c411966df47f --- /dev/null +++ b/tests/warn_conflict/Makefile @@ -0,0 +1,12 @@ +APPLICATION = warn_conflict +include ../Makefile.tests_common + +# The stm32f4discovery is the only board that provides known conflicting features, +# so using this compile test on other boards will not provide the expected warning. +BOARD_WHITELIST := stm32f4discovery + +# These features have a chance to use/access the shared `SPI_0` on stm32f4discovery, +# which would probably produce an unexpected behaviour in the user application. +FEATURES_REQUIRED = periph_dac periph_spi + +include $(RIOTBASE)/Makefile.include diff --git a/tests/warn_conflict/README.md b/tests/warn_conflict/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0169964a842272fdad67ea1ed8c2ca0c0a9cc373 --- /dev/null +++ b/tests/warn_conflict/README.md @@ -0,0 +1,41 @@ +Test warning on conflicting features +================================================== +Using conflicting features provided by boards was invisible for the user until the used features resulted in a traceable problem or the user was aware of the conflict in advance from documentation ect. +Now, existing and known conflicts can be recorded into `FEATURES_CONFLICT` for each board to inform the user on a conflict situation during compile time. + +This test requires conflicting features in its `Makefile`, i.e. `FEATURES_REQUIRED = periph_dac periph_spi`. +It is expected to be presented with a warning on the conflicts with a short description message during compile time for the [stm32f4discovery](https://github.com/RIOT-OS/RIOT/wiki/Board%3A-STM32F4discovery) by now, i.e. : + +``` +$ make BOARD=stm32f4discovery +The following features may conflict: periph_dac periph_spi +Rationale: On stm32f4discovery boards there are the same pins for the DAC and/or SPI_0. + +EXPECT undesired behaviour! +``` +The warning presents the conflicting features derived from `FEATURES_CONFLICT` and an optional message derived from `FEATURES_CONFLICT_MSG` provided int the `./RIOT/board/stm32f4discovery/Makefile.features`. + +Whenever an application, such as this test, requires board features that match a _conflict group_, e.g. `FEATURES_REQUIRED = periph_dac periph_spi`, a similar warning to the above will be displayed during compile time. + + +--------- +###Usage of _conflict groups_: + +* Conflicting features are described in groups separated by a `:` (doublecolon) for each feature, e.g.: +`FEATURES_CONFLICT = periph_spi:periph_dac`, which states that `periph_spi` conflicts with `periph_dac`. +As seen above, this is the conflict of `SPI_0` pinout is shared with `DAC` on the [stm32f4discovery](https://github.com/RIOT-OS/RIOT/wiki/Board%3A-STM32F4discovery) board. + +* Distinct groups of conflicts are whitespace separated, e.g.: +`featureA:featureB featureC:featureD`, which states that `featureA` conflicts with `featureB`, and `featureC` conflicts with `featureD`. +This also means, that e.g. `FEATURES_REQUIRED = featureA featureD` would **not** produce a warning. + +* The groups can have an arbitrary number of conflicting features, e.g.: +`featureA:featureB:featureC:featureX:featureY:featureZ` + +* An optional information can be given using the `FEATURES_CONFLICT_MSG`, e.g.: +`FEATURES_CONFLICT_MSG = "featureA uses the same pins as featureB"` + +* If the required features match multiple conflict groups, **ALL** conflicting features are provided to the user, e.g.: +`FEATURES_CONFLICT = featureA:featureB featureC:featureD` and +`FEATURES_REQUIRED = featureA featureB featureC featureD` +would result in: `The following features may conflict: featureA featureB featureC featureD` diff --git a/tests/warn_conflict/main.c b/tests/warn_conflict/main.c new file mode 100644 index 0000000000000000000000000000000000000000..6e5230d6b13ed2ebab52c3fb5bbea9a3064ca12f --- /dev/null +++ b/tests/warn_conflict/main.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test whether EXPECT_CONFLICT works. + * + * @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de> + * + * @} + */ + +#include <stdio.h> + +int main(void) +{ + puts("Hello, nothing to do here.\nbye."); + + return 0; +} diff --git a/tests/warn_conflict/test.py b/tests/warn_conflict/test.py new file mode 100755 index 0000000000000000000000000000000000000000..65a2b2568d6e999cbaea7edb9bd030c6a67f4973 --- /dev/null +++ b/tests/warn_conflict/test.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import subprocess, os + +cross_gcc = "arm-none-eabi-gcc" + +try: + devnull = open(os.devnull) + subprocess.Popen([cross_gcc], stdout=devnull, stderr=devnull).communicate() + output = subprocess.Popen(["make", "BOARD=stm32f4discovery"], stderr=subprocess.PIPE, stdout=subprocess.PIPE ) + out,err = output.communicate() + + compare = b'\x1b[1;33mThe following features may conflict:\x1b[0m \x1b[1;32mperiph_dac periph_spi\x1b[0m\n\x1b[1;33mRationale: \x1b[0mOn stm32f4discovery boards there are the same pins for the DAC and/or SPI_0.\n\n\x1b[1;33mEXPECT undesired behaviour!\x1b[0m\n' + if err == compare: + print("Test SUCCEEDED! Compile time output is as expected!\n") + else: + print("Test FAILED! Compile time output is NOT as expected!\n") + print("Expected:\n" + compare.decode("ascii") ) + print("Received:\n" + err.decode("ascii") ) + +except OSError as e: + if e.errno == os.errno.ENOENT: + print("ABORTING TEST:"+ cross_gcc +" seems to be missing.\n")