Kconfig
This document covers the following aspects of Kconfig:
Kconfig language.
Kconfig naming conventions.
Kconfig file structure.
Use of Kconfig in CMake scripts.
Best practices and tips.
Kconfig is a powerful configuration system. When integrated with CMake, it can achieve an efficient, flexible, and customizable build process for software development. Developers can flexibly configure, customize, and integrate project functionalities based on varied requirements, selecting the appropriate configuration to meet specific project without modifing the macros in the source code.
The generation of a Kconfig configuration file depends on a third-party Python library called Kconfiglib, available at Kconfiglib. To set up the Kconfig configurable file generation environment:
-
Install Kconfiglib using pip:
pip install kconfiglib
After installation, ensure the Kconfiglib path is added to the environment variables.
-
Kconfig will generate three files under the
include\generateddirectory:.config,config.cmakeandconfig.h. TheCONFIG_prefix will be added to the configuration symbol in these files. Therefore, do not add theCONFIG_prefix to symbol names in the Kconfig file..configis the classic configuration file generated by Kconfig, storing all configuration options as key-value pairs.config.cmakeconverts Kconfig configurations into CMake variables for CMake-based build systems.config.hconverts Kconfig configurations into C/C++ header files for source code integration.
Kconfig syntax is the same as the configuration system used by the Linux kenrnel. User can also refer to the official documentation for the Linux kernel: Kconfig Language and Kconfig macro language.
Kconfig Language
Kconfig symbols include mainmenu, menu/endmenu, config, choice/endchoice, conditional control with if/endif, and the inclusion of other Kconfig files using source/rsource/osource. Configuration item attributes in Kconfig include type (bool/int/hex/string/tristate), prompt message, default values, and the ability to set different values based on various conditions. Visibility can be controlled by dependencies using depends on. Here are some commonly used Kconfig symbols:
mainmenumenu/endmenuconfigmenuconfigchoice/endchoicesource/rsource/osource/orsourceif/endif
Config
A config is used to define a configurable option under menu or menconfig, and can also be controlled by conditional statements using if and endif. Each config entry typically includes the name of a configuration option and a series of attributes. Attributes can be the type of the configuration option, input prompt, dependencies, help text and default values.
To ensure clarity and consistency in configuration, each configuration option should have a unique name and should preferably be defined only once in the project. If a configuration option is defined multiple times, especially with the same prompt but different default values, it can lead to confusion and unexpected behavior. It is recommended to use conditional statements and dependencies to manage configuration complexity.
A config can be a visual symbol item when it is defined with a prompt. It will show up in the interactive configuration interfaces, and can be updated by the defconfig file and saved in the configuration file. If a config is without a prompt, it will be invisible. Invisible symbols are not shown in the interactive configuration interface, and can't update this configuration value by the defconfig file.
//example of a invisible configuration symbol
config REALTEK_SOC_SERIES_NAME
string
default "RTL8763E"
//example of a visiable configuration symbol
config REALTEK_APP_COMMON_CFU_ENABLE
bool "use app common cfu"
default n
help
compile app_common_cfu.c
Choice/Endchoice
choice and endchoice are used to define a mutually exclusive set of configuration options, where a user must select exactly one option from the specified list. This is particularly useful when there are multiple ways to configure a feature, but only one can be chosen at a time to prevent conflicting options from being simultaneously selected.
The choice can include a prompt to describe what the selection is about. This prompt is displayed in the configuration interface. Each choice must specify a type. bool is commonly used for options that are either enabled or disabled. A default option can be specified to indicate which choice should be pre-selected if the user doesn't explicitly make a selection. Additionally, depends on directive can be used within the choice block to specify conditions under which the entire set of options becomes visible or available for selection.
choice REALTEK_COMPILE_BANK
prompt "bank type"
default REALTEK_COMPILE_BANK0
config REALTEK_COMPILE_BANK0
bool "bank 0"
config REALTEK_COMPILE_BANK1
bool "bank 1"
endchoice
Source/Rsource/Osource/Orsource
The source, rsource, osource, and orsource directives are used to include other Kconfig files into the current Kconfig file. These statements support glob patterns and include each matching file. A pattern is required to match at least one file. Each of these directives has a specific behavior that dictates how the file paths are resolved or handled.
-
The
sourcedirective is used to include required configuration files with a relative or absolute path. If a relative path is provided, it's relative to the directory of the current Kconfig file that's including it. If the specified file cannot be found or does not exist, an error is generated.source "flash_map_config/Kconfig" source "drivers/*/Kconfig"
-
The
rsourcedirective is used to include required configuration file with the path relative to the directory of the current Kconfig file that contains thersourcestatement, and if the file cannot be found, an error will be generated.rsource "../../../Kconfig"
-
osourceis used to optionally include another Kconfig file with a relative or absolute path. If the specified file does not exist, no error is generated, and the inclusion is simply skipped.osource "Kconfig.RTL8763E"
-
orsourceis used to optionally include another Kconfig file with the path relative to the directory of the current Kconfig file that contains theorsourcestatement, If the specified file does not exist, no error is generated, and the inclusion is simply skipped.orsource "./gui/Kconfig.gui"
If/Endif
The if directive is used to specify a condition, and any configuration entries between if and endif are included only if the condition evaluates to true. This is useful for enabling or disabling sections of the configuration based on the presence or value of certain options. Conditions are typically based on the value of configuration symbols. They can involve logical operations such as && (AND), || (OR), and ! (NOT).
config FEATURE_A
bool "Enable Feature A"
config FEATURE_B
bool "Enable Feature B"
if FEATURE_A
config OPTION_1
bool "Option 1"
endif
if !FEATURE_B
config OPTION_2
bool "Option 2"
endif
if FEATURE_A && FEATURE_B
config OPTION_3
bool "Option 3"
endif
Kconfig Naming Convention
When Kconfig generates macros, it automatically adds the prefix CONFIG_. For example, the macro used in the source code is CONFIG_SAMPLE_ABC, while the configuration used in Kconfig is SAMPLE_ABC.
A defconfig file is a set of configurations to achieve specific functions based on the default values of Kconfig configurations. It is not a complete set of Kconfig configurations. Therefore, the default values of Kconfig configurations should not be changed easily, as this will affect the overall configuration status after loading defconfig. If changes to the default values are necessary, the scope of impact needs to be carefully evaluated.
-
SOC series configuration:
The macro prefix for distinguishing IC series is uniformly
CONFIG_SOC_SERIES_, such asCONFIG_SOC_SERIES_RTL8763E,CONFIG_SOC_SERIES_RTL8773D,CONFIG_SOC_SERIES_RTL8773E. -
IC cut version:
The macro for distinguishing IC cuts is based on the IC type macro and adds
_V0,_V1,_V2to indicateacut,bcut,ccut. For example,CONFIG_SOC_SERIES_RTL8763E_V1,CONFIG_SOC_SERIES_RTL8763E_V2,CONFIG_SOC_SERIES_RTL8763E_V3. -
Low-level configuration:
For low-level modules, such as BSP, and application modules that can be replaced with non-REALTEK solutions, the macro prefix is
CONFIG_REALTEK_to distinguish vendors. For example.REALTEK_GPIOB_SUPPORTin Kconfig. When Kconfig generates macros, it will automatically add theCONIFG_prefix to becomeCONFIG_REALTEK_GPIOB_SUPPORT. -
Application-level configuration:
For general application-level modules,
REALTEK_prefix is not necessary to be added to Kconfig configuration names.
In general, macro names are composed of module name_function. It is recommended that the string be named from left to right in Kconfig macro naming with each field reflecting the hierarchy level or domain relationship.
The defconfig name corresponds to the Kconfig name, and its naming convention is as follows:
The IC series name (
RTL8763E/RTL8773E/RTL8773D/RTL8773G) is added in thedefconfigfile name for applicaiton to identify the IC series type in the CMake configure procedure, such asdefconfig.RTL8763Eanddefconfig.RTL8773D.If target distinction is needed, user can add the target name in the
defconfigname, such asdefconfig.RTL8763E.bt_audio_trx_4M_lea_dual_bank0anddefconfig.RTL8773D.bt_audio_trx_16M_dual_bank0forbt_audio_trxapplicaiton,defconfig.RTL8763E.allanddefconfig.RTL8763E.defaultfor library project. For different library targets, the generated library names are also different, such aslibble_mgr_allandlibble_mgr_default.
Kconfig File Structure
For SDK user who develop applications based on pre-compiled static libraries, user can configure static library type without modifying the libraries. The detailed configurations in the static libraries remain invisible for the user. Taking the application bt_audio_trx as an example, the Kconfig structure in the SDK package is as follows:
├── sdk
├── Kconfig SDK Kconfig, rsource "./config/$(BOARD_DIR)/Kconfig.release".
├── config
├── RTL8763E The BOARD_DIR variable is set to RTL8763E.
├── Kconfig.release Configure SOC series type and name, rsource "../../bin/rtl87x3e/Kconfig.board" and "Kconfig.RTL8763E.sdk".
├── Kconfig.RTL8763E.sdk rsource "../../bin/rtl87x3e/Kconfig.soc.sdk".
├── bin Contains all binary symbol files that user applications are built upon.
├── rtl87x3e
├── Kconfig.soc.sdk Configures library used by application and define the library name and target type. All these libraries are compiled and ready for use.
├── Kconfig.board Configures the IC part number related type and target. rsource "flash_map_config/Kconfig"
├── flash_map_config
├── Kconfig Configures flash map type, flash map file path, and compile bank type.
├── board
├── evb
├── bt_audio_trx
├── gcc
├── defconfig.RTL8763E.bt_audio_trx_4M_lea_dual_bank0 The defconfig file of bt_audio_trx_4M_lea_dual_bank0 for RTL8763E.
├── Kconfig Defines mainmenu in the application Kconfig, define configuration in the application and include SDK Kconfig under the SDK. rsource "../../../src/Kconfig" to get the configuration in the application source code, and rsource the SDK Kconfig of "../../../Kconfig".
The defconfig file of an application should be located in the gcc subdirectory of the applicaiton's main directory. The Kconfig file of the applicaiton should be placed directly in the applicaiton's root directory. This relative path structure is essential for the CMake compilation process.
When developing application libraries, it's necessary to prepare a library-specific Kconfig file. In this Kconfig, the configurations that directly impact the compilation results need to be defined. Additionally, it should define the library target type configurations and the target name for different targets.
├── sdk
├── Kconfig SDK Kconfig with library detailed configurations, rsource "./config/$(BOARD_DIR)/Kconfig".
├── Kconfig.release SDK Kconfig, rsource "./config/$(BOARD_DIR)/Kconfig.release", This file will be renamed as "Kconfig" in the SDK package with compiled libraries.
├── config
├── RTL8763E The BOARD_DIR variable is set to RTL8763E.
├── Kconfig Configure SOC series type and name, rsource "../../bin/rtl87x3e/Kconfig.board". If compiling applicaiton only, rsource "Kconfig.RTL8763E.sdk". If compiling both applicaiton and library projects, rsource "Kconfig.RTL8763E".
├── Kconfig.RTL8763E.sdk rsource "../../bin/rtl87x3e/Kconfig.soc.sdk".
├── Kconfig.RTL8763E rsource library Kconfig from "../../board/evb/Kconfig.soc.RTL8763E".
├── bin Contains all binary symbol files that user applications are built upon.
├── rtl87x3e
├── Kconfig.soc.sdk Configures libraries used by applications and defines the library names and target types. All these libraries are pre-compiled and ready for use.
├── Kconfig.board Configures the IC part number related types and targets. rsource "flash_map_config/Kconfig"
├── flash_map_config
├── Kconfig Configures flash map type, flash map file path, and compile bank type.
├── board
├── evb
├── bt_audio_trx
├── Kconfig Defines mainmenu in the application Kconfig, defines configurations in the application and includes SDK Kconfig under the SDK. rsource "../../../src/Kconfig" to get the configuration in the application source code, and rsource the SDK Kconfig from "../../../Kconfig".
├── ble_audio_lib Library directory.
├── Kconfig Configures the library target type and library name for different targets. Adds configurations which can affect the compilation result for different requirements.
├── gcc
├── defconfig.RTL8763E.default Adds defconfig configurations of the default target for RTL8763E. The defconfig file will be loaded based on the default configuration values defined in Kconfig.
For library projects, the top-level Kconfig is the Kconfig file under the SDK directory. For application projects, the top-level Kconfig is the Kconfig file under the applicaiton directory.
The mainmenu of bt_audio_trx is in board\evb\bt_audio_trx\Kconfig. The guiconfig and menuconfig commands can be run through the command line:
-
First, Set the variable of
BOARD_DIRto the IC directory name under theconfigdirectory of the SDK, e.g.RTL8763E,RTL8773D,RTL8773EandRTL8773G. If theconfigdirectory doesn't exist under the SDK directory, skip this step. For various command line environment, the methods to set variable are different:In Windows Command Prompt, use
set VAR=variable_name.In PowerShell, use
$env:VAR="variable_name".In bash, use
exprot VAR=variable_name.
In this example, it is set to
RTL8763E:In Windows Command Prompt:
set BOARD_DIR=RTL8763E
In PowerShell:
$env:BOARD_DIR="RTL8763E"
In bash:
exprot BOARD_DIR=RTL8763E
-
Run the
guiconfigcommand. The parameter ofguiconfigormenuconfigis the absolute or relative path of the top-level Kconfig. For example, runguiconfigcommand under theboard\evb\bt_audio_trxdirectory.guiconfig Kconfig
The execution of the
guiconfigcommand in different command line windows are as follows:
guiconfig in Windows Command Prompt
guiconfig in PowerShell
guiconfig in Git Bash
Run
guiconfigcommand under the SDK directory, use the relative path to the Kconfig file:guiconfig .\board\evb\bt_audio_trx\Kconfig
The
guiconfiginterface forbt_audio_trxis as follows:
Configuration Interface of bt_audio_trx by guiconfig
User can configure the settings through the
guiconfiginterface, save asdefconfigfile, and switch between single-menu mode and full-tree mode. User can also click Open... to load adefconfigfile, update configurations based on it and save as a newdefconfigfile.
Load defconfig File by guiconfig
User can also run
menuconfigcommand under theboard\evb\bt_audio_trxdirectory. The python librarywindows-cursesis required formenuconfigcommand on Windows. Install this library using:pip install windows-curses
Then run:
menuconfig Kconfig
The
menuconfiginterface forbt_audio_trxis as follows:
Configuration Interface of bt_audio_trx by menuconfig
User can configure the settings through the
menuconfiginterface following the on-screen tips. For example, load adefconfigby pressing O:
Open defconfig File by menuconfig
After loading
gcc\defconfig.RTL8763E.4M_bank0, themenuconfigupdates as follows:
Load defconfig File Result by menuconfig
Use of Kconfig in CMake Script
The configurations defined in Kconfig and updated by the defconfig file can be generated into three files (config.cmake, config.h, .config) through tool\Gadgets\gcc_tool\kconfig.py during the CMake configure phase. The usuage of Kconfig.py is as follows:
python kconfig.py -h
usage: kconfig.py [-h] [--board {RTL8773D,RTL8773E,RTL8763E,RTL8773G}]
kconfig_file config_out header_out cmake_out kconfig_list_out configs_in [configs_in ...]
positional arguments:
kconfig_file Top-level Kconfig file
config_out Output configuration file
header_out Output header file
cmake_out Output cmake config file
kconfig_list_out Output file for list of parsed Kconfig files
configs_in Input configuration fragments. Will be merged together.
options:
-h, --help show this help message and exit
--board {RTL8773D,RTL8773E,RTL8763E,RTL8773G}
Top-level Kconfig file
The usage of Kconfig in the CMake script is in the config\cmake\build.cmake:
find_program(Python_EXECUTABLE python NO_CMAKE_FIND_ROOTO_PATH)
set(Python_ARGS "${CMAKE_CURRENT_SOURCE_DIR}/tool/Gadgets/gcc_tool/kconfig.py ${general_kconfig_path} ${gen_dir}/.config ${gen_dir}/config.h ${gen_dir}/config.cmake ${gen_dir}/sourcelist.txt ${kconfig_path} --board ${board}")
STRING(REPLACE " " ";" Python_ARGS ${Python_ARGS})
message(STATUS "[KCONFIG] Python_EXECUTABLE: ${Python_EXECUTABLE}")
message(STATUS "[KCONFIG] Python_ARGS: ${Python_ARGS}")
execute_process(
COMMAND ${Python_EXECUTABLE} ${Python_ARGS}
)
include(${gen_dir}/config.cmake)
A sample command line for kconfig.py is as follows:
python tool/Gadgets/gcc_tool/kconfig.py ./board/evb/bt_audio_trx/gcc/../Kconfig ./build/include/generated/.config ./build/include/generated/config.h ./build/include/generated/config.cmake ./build/include/generated/sourcelist.txt ./board/evb/bt_audio_trx/gcc/defconfig.RTL8763E.bt_audio_trx_4M_lea_dual_bank0 --board RTL8763E
The generated config.cmake will be used in the CMake script, and the config.h will be used in C/C++ source files precompilation by the command target_precompile_headers(btAudioTrx PRIVATE ${kconfig_header_dir_path}/config.h). The .config contains the total configuration definition.
Best Practices and Tips
Here are some tips in the practices:
Locate Kconfig files near the source code for easier modification and portability.
Group configuration items by functional modules to enhance readability and maintainability.
Use meaningful and consistent naming conventions for
configoptions. And select the appropriate Kconfig type based on how the macro is used (bool, tristate, string, int, hex).-
For
booltypeconfig:When not selected, the
CONFIG_XXXmacro is not defined. This macro can't be used for calculation or assignment.Use only conditional compilation directive (
#if,#ifdef,#ifndef,#if defined).It's recommended to use the same
ifor#ifdeffor a configuration macro.
For macros used as integers with values not limited to 0 or 1, define them as
inttype and specify an optional range.-
Be aware that
configwithout a prompt:Use their default value and are invisible in
guiconfigormenuconfig.They can't be updated by
defconfigfiles.
-
Use default values and range constraints appropriately.
Default values are often used directly in compilation scenarios without setting in the
defconfig.Be cautious when adjusting default values, as changes may affect
defconfigconfigurations.
Provide clear, concise, and informative help text for each configuration option.
Use
selectandimplydirectives carefully to manage the relationships between configurations and avoid circular dependencies.It is crucial to prevent redundant definitions of configurations. Maintaining a single point of definition for each configuration ensures system-wide consistency, mitigates potential conflicts, and eliminates ambiguity in the configuration process.
Consider the impact on build systems and scripts when adding or modifying configuration options.
How to Add a Kconfig Configuration to Control Source Code Compilation?
When adding a configuration to control source code compilation:
-
In Keil C/C++ preprocessor symbols definition settings of Keil projects:
Set the configuration macro to 1 (enabled) or 0 (disabled).
-
In the Kconfig file
Define the configuration as a
booltype.-
Add the configuration definition in the Kconfig file with an appropriate default value:
-
If the feature should be enabled by default:
Set the default value to
y.For targets needing it disabled, set to
nin thedefconfigfiles.
-
If the feature should be disabled by default:
Set the default value to
n.For targets needing it enabled, set to
yin thedefconfigfiles.
-
Example:
config REALTEK_FEATURE_A bool "enable feaure A" default y help Description about feaure A -
In the source code, add the configuration conditional compile control code.
#if (CONFIG_REALTEK_FEATURE_A == 1) //source code content #endif -
In the
defconfigfiles, for targets requiring a non-default configuration:If default is
yand feature should be disabled, set ton.If default is
nand feature should be enabled, set toy.
How to Remove a Kconfig Configuration?
Before removing a configuration, carefully review all usage scenarios to ensure it can be safely deleted. Once confirmed, follow these steps to clean up all instances of the macro:
Source code: Remove all usage of the configuration macro in the source code.
Kconfig: Delete the configuration definition from the Kconfig file.
Defconfig files: Remove the configuration value settings from all relevant
defconfigfiles.Keil project: Delete the configuration definition from the C/C++ preprocessor symbols definition settings.
Update any relevant documentation or any build scripts or CMakeLists that mentions this configuration.
After removal, thoroughly test the system to ensure no unexpected side effects.
When removing a configuration in Kconfig, considering a transition period is a also very good practice. This can reduce the impact on existing systems and users, and provide sufficient time for necessary adjustments.
Before completely removing the configuration, mark it as deprecated first.
Clearly state in comments or help text that the configuration will be removed in the future. If there are alternative configurations or new implementation methods, provide clear migration guidance in the help text.
Use conditional compilation in the code to gradually phase out the use of this configuration.
How to Adjust the Default Value of a Kconfig Configuration?
Once set, it is generally not recommended to modify the default values of macros in Kconfig, primarily due to the following two considerations:
Potential issues arising from SDK version iterations are easily overlooked.
Incomplete revisions may lead to unexpected risks.
However, if changes are absolutely necessary, follow these steps to maintain system consistency:
-
Modify the Kconfig file:
Locate the relevant macro definition in the Kconfig file.
Update the default value to the new desired default value.
-
Check and update
defconfigfiles:Review all
defconfigfiles for all compilation scenarios.-
For cases where the new default value differs from the current setting in
defconfig:If you want to maintain the original behavior, explicitly set the original value in
defconfig.If you accept the new default value, you can remove that setting from
defconfig.
Check and update the documentation or any build scripts or
CMakeListsthat mentions this configuration.Conduct a code review to ensure the impact of the change is fully understood and accepted. Inform related development.
Do comprehensive testing in all affected compilation scenarios to ensure the change hasn't introduced unexpected issues.