diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000000..8c55134455 --- /dev/null +++ b/Kconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2019 HAW Hamburg +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. +# +mainmenu "RIOT Configuration" + +# For now, get used modules as macros from this file (see kconfig.mk) +osource "$(KCONFIG_GENERATED_DEPENDENCIES)" + +# The application may declare new symbols as well +osource "$(APPDIR)/Kconfig" + +comment "RIOT is in a migration phase." +comment "Some configuration options may not be here. Use CFLAGS instead." diff --git a/Makefile.base b/Makefile.base index 5f7fd9f02d..d9dfbc00b0 100644 --- a/Makefile.base +++ b/Makefile.base @@ -96,19 +96,19 @@ CCASFLAGS = $(filter-out $(CCASUWFLAGS), $(CFLAGS)) $(CCASEXFLAGS) $(OBJC_LTO): CFLAGS+=$(LTOFLAGS) -$(OBJC): $(BINDIR)/$(MODULE)/%.o: %.c $(RIOTBUILD_CONFIG_HEADER_C) +$(OBJC): $(BINDIR)/$(MODULE)/%.o: %.c $(RIOTBUILD_CONFIG_HEADER_C) $(KCONFIG_GENERATED_AUTOCONF_HEADER_C) $(Q)$(CCACHE) $(CC) \ -DRIOT_FILE_RELATIVE=\"$(patsubst $(RIOTBASE)/%,%,$(abspath $<))\" \ -DRIOT_FILE_NOPATH=\"$(notdir $<)\" \ $(CFLAGS) $(INCLUDES) -MQ '$@' -MD -MP -c -o $@ $(abspath $<) -$(GENOBJC): %.o: %.c $(RIOTBUILD_CONFIG_HEADER_C) +$(GENOBJC): %.o: %.c $(RIOTBUILD_CONFIG_HEADER_C) $(KCONFIG_GENERATED_AUTOCONF_HEADER_C) $(Q) $(CCACHE) $(CC) \ -DRIOT_FILE_RELATIVE=\"$(patsubst $(RIOTBASE)/%,%,$<)\" \ -DRIOT_FILE_NOPATH=\"$(notdir $<)\" \ $(CFLAGS) $(INCLUDES) -MQ '$@' -MD -MP -c -o $@ $< -$(OBJCXX): $(BINDIR)/$(MODULE)/%.o: %.cpp $(RIOTBUILD_CONFIG_HEADER_C) +$(OBJCXX): $(BINDIR)/$(MODULE)/%.o: %.cpp $(RIOTBUILD_CONFIG_HEADER_C) $(KCONFIG_GENERATED_AUTOCONF_HEADER_C) $(Q)$(CCACHE) $(CXX) \ -DRIOT_FILE_RELATIVE=\"$(patsubst $(RIOTBASE)/%,%,$(abspath $<))\" \ -DRIOT_FILE_NOPATH=\"$(notdir $<)\" \ @@ -117,7 +117,7 @@ $(OBJCXX): $(BINDIR)/$(MODULE)/%.o: %.cpp $(RIOTBUILD_CONFIG_HEADER_C) $(ASMOBJ): $(BINDIR)/$(MODULE)/%.o: %.s $(Q)$(AS) $(ASFLAGS) -o $@ $(abspath $<) -$(ASSMOBJ): $(BINDIR)/$(MODULE)/%.o: %.S $(RIOTBUILD_CONFIG_HEADER_C) +$(ASSMOBJ): $(BINDIR)/$(MODULE)/%.o: %.S $(RIOTBUILD_CONFIG_HEADER_C) $(KCONFIG_GENERATED_AUTOCONF_HEADER_C) $(Q)$(CCAS) $(CCASFLAGS) $(INCLUDES) -MQ '$@' -MD -MP -c -o $@ $(abspath $<) # pull in dependency info for *existing* .o files diff --git a/Makefile.include b/Makefile.include index 805c23bffe..4a1ecaec2b 100644 --- a/Makefile.include +++ b/Makefile.include @@ -148,6 +148,9 @@ include $(RIOTMAKE)/scan-build.inc.mk export RIOTBUILD_CONFIG_HEADER_C = $(BINDIR)/riotbuild/riotbuild.h +# Include Kconfig functionalities +include $(RIOTMAKE)/kconfig.mk + ifeq ($(OS),Darwin) OPEN := open else diff --git a/makefiles/kconfig.mk b/makefiles/kconfig.mk new file mode 100644 index 0000000000..119ded8642 --- /dev/null +++ b/makefiles/kconfig.mk @@ -0,0 +1,88 @@ +# This is the root Kconfig +KCONFIG ?= $(RIOTBASE)/Kconfig + +# Include tools targets +include $(RIOTMAKE)/tools/kconfiglib.inc.mk + +# Generated dir will contain Kconfig generated configurations +GENERATED_DIR = $(BINDIR)/generated + +# This file will contain all generated configuration from kconfig +export KCONFIG_GENERATED_AUTOCONF_HEADER_C = $(GENERATED_DIR)/autoconf.h + +# Add configuration header to build dependencies +BUILDDEPS += $(KCONFIG_GENERATED_AUTOCONF_HEADER_C) + +# Include configuration header when building +CFLAGS += -include '$(KCONFIG_GENERATED_AUTOCONF_HEADER_C)' + +# Header for the generated header file +define KCONFIG_AUTOHEADER_HEADER +/* RIOT Configuration File */ + +endef +export KCONFIG_AUTOHEADER_HEADER + +# This file will contain the calculated dependencies formated in Kconfig +export KCONFIG_GENERATED_DEPENDENCIES = $(GENERATED_DIR)/Kconfig.dep + +# This file will contain application default configurations +KCONFIG_APP_CONFIG = $(APPDIR)/app.config + +# Default and user overwritten configurations +KCONFIG_USER_CONFIG = $(APPDIR)/user.config + +# This file will contain merged configurations from MERGE_SOURCES and is the +# one that is used to generate the 'riotconf.h' header +KCONFIG_MERGED_CONFIG = $(GENERATED_DIR)/merged.config + +# Flag that indicates that the configuration has been edited +KCONFIG_EDITED_CONFIG = $(GENERATED_DIR)/.editedconfig + +# Add configurations to merge, in ascendent priority (i.e. a file overrides the +# previous ones) +MERGE_SOURCES += $(wildcard $(KCONFIG_APP_CONFIG)) +MERGE_SOURCES += $(wildcard $(KCONFIG_USER_CONFIG)) + +# Create directory to place generated files +$(GENERATED_DIR): $(CLEAN) + $(Q)mkdir -p $@ + +# Build a Kconfig file defining all used modules. This is done by defining +# symbols like 'MODULE_' which default to 'y'. Then, every module +# Kconfig menu will depend on that symbol being set to show its options. +$(KCONFIG_GENERATED_DEPENDENCIES): FORCE | $(GENERATED_DIR) + $(Q)printf "%s " $(USEMODULE) \ + | awk 'BEGIN {RS=" "}{ gsub("-", "_", $$0); \ + printf "config MODULE_%s\n\tbool\n\tdefault y\n", toupper($$0)}' \ + | $(LAZYSPONGE) $(LAZYSPONGE_FLAGS) $@ + +.PHONY: menuconfig + +# Opens the menuconfig interface for configuration of modules using the Kconfig +# system. +menuconfig: $(MENUCONFIG) $(KCONFIG_MERGED_CONFIG) $(KCONFIG_EDITED_CONFIG) + $(Q)KCONFIG_CONFIG=$(KCONFIG_MERGED_CONFIG) $(MENUCONFIG) $(KCONFIG) + +# Marks that the configuration file has been edited via some interface, such as +# menuconfig +$(KCONFIG_EDITED_CONFIG): FORCE + $(Q)touch $(KCONFIG_EDITED_CONFIG) + +# Generates a merged configuration file from the given sources. If the config +# file has been edited a '.editedconfig' file will be present. +# This is used to decide if the sources have to be merged or not. +$(KCONFIG_MERGED_CONFIG): $(MERGECONFIG) $(KCONFIG_GENERATED_DEPENDENCIES) FORCE + $(Q)\ + if ! test -f $(KCONFIG_EDITED_CONFIG); then \ + if ! test -z "$(strip $(MERGE_SOURCES))"; then \ + $(MERGECONFIG) $(KCONFIG) $@ $(MERGE_SOURCES); \ + else \ + rm -f $@; \ + fi \ + fi + +# Build a header file with all the Kconfig configurations. genconfig will avoid +# any unnecessary rewrites of the header file if no configurations changed. +$(KCONFIG_GENERATED_AUTOCONF_HEADER_C): $(KCONFIG_GENERATED_DEPENDENCIES) $(GENCONFIG) $(KCONFIG_MERGED_CONFIG) FORCE + $(Q)KCONFIG_CONFIG=$(KCONFIG_MERGED_CONFIG) $(GENCONFIG) --header-path $@ $(KCONFIG) diff --git a/tests/kconfig/Kconfig b/tests/kconfig/Kconfig new file mode 100644 index 0000000000..c18dffdd8f --- /dev/null +++ b/tests/kconfig/Kconfig @@ -0,0 +1,22 @@ +menu "Application" + +menuconfig KCONFIG_APP_MSG_1 + bool "Configure message 1" + default y + help + This will enable configuring the first message via Kconfig + +if KCONFIG_APP_MSG_1 + +config APP_MSG_1_TEXT + string "Message 1 text" + default "Message 1 defined in Kconfig file" + +endif # KCONFIG_APP_MSG_1 + +config APP_MSG_2 + bool "Message 2" + help + Activate printing the second message + +endmenu # Application diff --git a/tests/kconfig/Makefile b/tests/kconfig/Makefile new file mode 100644 index 0000000000..e386d876b9 --- /dev/null +++ b/tests/kconfig/Makefile @@ -0,0 +1,2 @@ +include ../Makefile.tests_common +include $(RIOTBASE)/Makefile.include diff --git a/tests/kconfig/README.md b/tests/kconfig/README.md new file mode 100644 index 0000000000..89153817b2 --- /dev/null +++ b/tests/kconfig/README.md @@ -0,0 +1,27 @@ +# Basic Kconfig test +This test aims to test Kconfig on RIOT, and to show how symbols will be handled +during the migration phase. + +## Configuration options +The application exposes the following configuration options: +- `APP_MSG_1_TEXT`: Text for the first message +- `APP_MSG_2`: Enable/disable printing the second message +- `KCONFIG_APP_MSG_1`: Enable/disable configuring the first message via Kconfig + +All these options can be used by the application via macros, adding the +`CONFIG_` prefix to the symbol name (e.g. `CONFIG_APP_MSG_1_TEXT`). + +## Optionally using Kconfig +`KCONFIG_APP_MSG_1` option exists for compatibility with the current way of +configuring RIOT. The `app.h` header contains the default value for the first +message, which is the one used if `KCONFIG_APP_MSG_1` is not set by the user. +Note that, in this case, the default text for message 1 in the header file +differs from the one in the Kconfig file, this is just to make more evident +which the applied value was. + +## Changing configuration +The user can configure the values via the menuconfig interface +(`make menuconfig`), or by hand, either editing the `app.config` file or adding +an `user.config` file. Note that once the user has used the menuconfig interface +(i.e. has edited the `merge.config` file directly) a `make clean` has to be +issued in order to edit the value by hand. diff --git a/tests/kconfig/app.config b/tests/kconfig/app.config new file mode 100644 index 0000000000..45ea06df25 --- /dev/null +++ b/tests/kconfig/app.config @@ -0,0 +1,7 @@ +# enable configuring message 1 via kconfig +CONFIG_KCONFIG_APP_MSG_1=y +# change message 1 text +CONFIG_APP_MSG_1_TEXT="Message 1 defined in app.config file" + +# enable printing message 2 +CONFIG_APP_MSG_2=y diff --git a/tests/kconfig/app.h b/tests/kconfig/app.h new file mode 100644 index 0000000000..a616b4fde9 --- /dev/null +++ b/tests/kconfig/app.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ +#ifndef APP_H +#define APP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Default text for the message 1 + */ +#ifndef CONFIG_APP_MSG_1_TEXT +#define CONFIG_APP_MSG_1_TEXT "Message 1 defined in header file" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* APP_H */ diff --git a/tests/kconfig/main.c b/tests/kconfig/main.c new file mode 100644 index 0000000000..fa41ff1cb1 --- /dev/null +++ b/tests/kconfig/main.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 HAW Hamburg + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test for Kconfig configuration + * + * @author Leandro Lanzieri + * + * @} + */ + +#include +#include +#include "app.h" +#include "kernel_defines.h" + +int main(void) +{ + puts(CONFIG_APP_MSG_1_TEXT); + + if (IS_ACTIVE(CONFIG_APP_MSG_2)) { + puts("MSG_2 is active"); + } + return 0; +} diff --git a/tests/kconfig/tests/01-run.py b/tests/kconfig/tests/01-run.py new file mode 100755 index 0000000000..fb964a8e1c --- /dev/null +++ b/tests/kconfig/tests/01-run.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2019 HAW Hamburg +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +import sys +from testrunner import run + + +def testfunc(child): + child.expect_exact("Message 1 defined in app.config file") + child.expect_exact("MSG_2 is active") + + +if __name__ == "__main__": + sys.exit(run(testfunc))