You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
453 lines
16 KiB
453 lines
16 KiB
# SPDX-License-Identifier: Apache-2.0 |
|
|
|
include_guard(GLOBAL) |
|
|
|
include(extensions) |
|
include(python) |
|
|
|
# autoconf.h is generated by Kconfig and placed in |
|
# <build>/zephyr/include/generated/autoconf.h. |
|
# A project may request a custom location by setting AUTOCONF_H explicitly before |
|
# calling 'find_package(Zephyr)' or loading this module. |
|
set_ifndef(AUTOCONF_H ${PROJECT_BINARY_DIR}/include/generated/autoconf.h) |
|
# Re-configure (Re-execute all CMakeLists.txt code) when autoconf.h changes |
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${AUTOCONF_H}) |
|
|
|
# Folders needed for conf/mconf files (kconfig has no method of redirecting all output files). |
|
# conf/mconf needs to be run from a different directory because of: GH-3408 |
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/kconfig/include/generated) |
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/kconfig/include/config) |
|
|
|
set_ifndef(KCONFIG_NAMESPACE "CONFIG") |
|
|
|
set_ifndef(KCONFIG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Kconfig) |
|
file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}) |
|
|
|
if(HWMv1) |
|
# Support multiple SOC_ROOT |
|
file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}/soc) |
|
set(kconfig_soc_root ${BOARD_ROOT}) |
|
list(REMOVE_ITEM kconfig_soc_root ${ZEPHYR_BASE}) |
|
set(soc_defconfig_file ${KCONFIG_BINARY_DIR}/soc/Kconfig.defconfig) |
|
|
|
# This loads Zephyr base SoC root defconfigs |
|
file(WRITE ${soc_defconfig_file} "osource \"soc/soc_legacy/$(ARCH)/*/Kconfig.defconfig\"\n") |
|
|
|
set(OPERATION WRITE) |
|
foreach(root ${kconfig_soc_root}) |
|
file(APPEND ${soc_defconfig_file} |
|
"osource \"${root}/soc/$(ARCH)/*/Kconfig.defconfig\"\n") |
|
file(${OPERATION} ${KCONFIG_BINARY_DIR}/soc/Kconfig.soc.choice |
|
"osource \"${root}/soc/$(ARCH)/*/Kconfig.soc\"\n" |
|
) |
|
file(${OPERATION} ${KCONFIG_BINARY_DIR}/soc/Kconfig.soc.arch |
|
"osource \"${root}/soc/$(ARCH)/Kconfig\"\n" |
|
"osource \"${root}/soc/$(ARCH)/*/Kconfig\"\n" |
|
) |
|
set(OPERATION APPEND) |
|
endforeach() |
|
endif() |
|
|
|
# Support multiple shields in BOARD_ROOT, remove ZEPHYR_BASE as that is always sourced. |
|
set(kconfig_board_root ${BOARD_ROOT}) |
|
list(REMOVE_ITEM kconfig_board_root ${ZEPHYR_BASE}) |
|
set(OPERATION WRITE) |
|
foreach(root ${kconfig_board_root}) |
|
file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.shield.defconfig |
|
"osource \"${root}/boards/shields/*/Kconfig.defconfig\"\n" |
|
) |
|
file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.shield |
|
"osource \"${root}/boards/shields/*/Kconfig.shield\"\n" |
|
) |
|
set(OPERATION APPEND) |
|
endforeach() |
|
|
|
if(KCONFIG_ROOT) |
|
# Perform any variable substitutions if they are present |
|
string(CONFIGURE "${KCONFIG_ROOT}" KCONFIG_ROOT) |
|
|
|
zephyr_file(APPLICATION_ROOT KCONFIG_ROOT) |
|
# KCONFIG_ROOT has either been specified as a CMake variable or is |
|
# already in the CMakeCache.txt. This has precedence. |
|
elseif(EXISTS ${APPLICATION_SOURCE_DIR}/Kconfig) |
|
set(KCONFIG_ROOT ${APPLICATION_SOURCE_DIR}/Kconfig) |
|
else() |
|
set(KCONFIG_ROOT ${ZEPHYR_BASE}/Kconfig) |
|
endif() |
|
|
|
if(NOT DEFINED BOARD_DEFCONFIG) |
|
zephyr_file(CONF_FILES ${BOARD_DIR} DEFCONFIG BOARD_DEFCONFIG) |
|
endif() |
|
|
|
if(DEFINED BOARD_REVISION) |
|
zephyr_build_string(config_board_string |
|
BOARD ${BOARD} |
|
BOARD_QUALIFIERS ${BOARD_QUALIFIERS} |
|
BOARD_REVISION ${BOARD_REVISION} |
|
) |
|
set(board_rev_file ${config_board_string}) |
|
if(EXISTS ${BOARD_DIR}/${board_rev_file}.conf) |
|
message(DEPRECATION "Use of '${board_rev_file}.conf' is deprecated, please switch to '${board_rev_file}_defconfig'") |
|
set_ifndef(BOARD_REVISION_CONFIG ${BOARD_DIR}/${board_rev_file}.conf) |
|
endif() |
|
endif() |
|
|
|
set(DOTCONFIG ${PROJECT_BINARY_DIR}/.config) |
|
set(PARSED_KCONFIG_SOURCES_TXT ${PROJECT_BINARY_DIR}/kconfig/sources.txt) |
|
|
|
if(CONF_FILE) |
|
string(CONFIGURE "${CONF_FILE}" CONF_FILE_EXPANDED) |
|
string(REPLACE " " ";" CONF_FILE_AS_LIST "${CONF_FILE_EXPANDED}") |
|
endif() |
|
|
|
if(EXTRA_CONF_FILE) |
|
string(CONFIGURE "${EXTRA_CONF_FILE}" EXTRA_CONF_FILE_EXPANDED) |
|
string(REPLACE " " ";" EXTRA_CONF_FILE_AS_LIST "${EXTRA_CONF_FILE_EXPANDED}") |
|
endif() |
|
|
|
zephyr_file(CONF_FILES ${BOARD_EXTENSION_DIRS} KCONF board_extension_conf_files SUFFIX ${FILE_SUFFIX}) |
|
|
|
# DTS_ROOT_BINDINGS is a semicolon separated list, this causes |
|
# problems when invoking kconfig_target since semicolon is a special |
|
# character in the C shell, so we make it into a question-mark |
|
# separated list instead. |
|
string(REPLACE ";" "?" DTS_ROOT_BINDINGS "${DTS_ROOT_BINDINGS}") |
|
|
|
# Export each `ZEPHYR_<module>_MODULE_DIR` to Kconfig. |
|
# This allows Kconfig files to refer relative from a modules root as: |
|
# source "$(ZEPHYR_FOO_MODULE_DIR)/Kconfig" |
|
foreach(module_name ${ZEPHYR_MODULE_NAMES}) |
|
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name}) |
|
list(APPEND |
|
ZEPHYR_KCONFIG_MODULES_DIR |
|
"ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR=${ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR}" |
|
) |
|
|
|
if(ZEPHYR_${MODULE_NAME_UPPER}_KCONFIG) |
|
list(APPEND |
|
ZEPHYR_KCONFIG_MODULES_DIR |
|
"ZEPHYR_${MODULE_NAME_UPPER}_KCONFIG=${ZEPHYR_${MODULE_NAME_UPPER}_KCONFIG}" |
|
) |
|
endif() |
|
endforeach() |
|
|
|
# A list of common environment settings used when invoking Kconfig during CMake |
|
# configure time or menuconfig and related build target. |
|
string(REPLACE ";" "\\\;" SHIELD_AS_LIST_ESCAPED "${SHIELD_AS_LIST}") |
|
# cmake commands are escaped differently |
|
string(REPLACE ";" "\\;" SHIELD_AS_LIST_ESCAPED_COMMAND "${SHIELD_AS_LIST}") |
|
|
|
if(TOOLCHAIN_HAS_NEWLIB) |
|
set(_local_TOOLCHAIN_HAS_NEWLIB y) |
|
else() |
|
set(_local_TOOLCHAIN_HAS_NEWLIB n) |
|
endif() |
|
|
|
if(TOOLCHAIN_HAS_PICOLIBC) |
|
set(_local_TOOLCHAIN_HAS_PICOLIBC y) |
|
else() |
|
set(_local_TOOLCHAIN_HAS_PICOLIBC n) |
|
endif() |
|
|
|
set(COMMON_KCONFIG_ENV_SETTINGS |
|
PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} |
|
srctree=${ZEPHYR_BASE} |
|
KERNELVERSION=${KERNELVERSION} |
|
APPVERSION=${APP_VERSION_STRING} |
|
APP_VERSION_EXTENDED_STRING=${APP_VERSION_EXTENDED_STRING} |
|
APP_VERSION_TWEAK_STRING=${APP_VERSION_TWEAK_STRING} |
|
CONFIG_=${KCONFIG_NAMESPACE}_ |
|
KCONFIG_CONFIG=${DOTCONFIG} |
|
BOARD_DIR=${BOARD_DIR} |
|
BOARD=${BOARD} |
|
BOARD_REVISION=${BOARD_REVISION} |
|
BOARD_QUALIFIERS=${BOARD_QUALIFIERS} |
|
HWM_SCHEME=${HWM} |
|
KCONFIG_BINARY_DIR=${KCONFIG_BINARY_DIR} |
|
APPLICATION_SOURCE_DIR=${APPLICATION_SOURCE_DIR} |
|
ZEPHYR_TOOLCHAIN_VARIANT=${ZEPHYR_TOOLCHAIN_VARIANT} |
|
TOOLCHAIN_KCONFIG_DIR=${TOOLCHAIN_KCONFIG_DIR} |
|
TOOLCHAIN_HAS_NEWLIB=${_local_TOOLCHAIN_HAS_NEWLIB} |
|
TOOLCHAIN_HAS_PICOLIBC=${_local_TOOLCHAIN_HAS_PICOLIBC} |
|
EDT_PICKLE=${EDT_PICKLE} |
|
# Export all Zephyr modules to Kconfig |
|
${ZEPHYR_KCONFIG_MODULES_DIR} |
|
) |
|
|
|
if(HWMv1) |
|
list(APPEND COMMON_KCONFIG_ENV_SETTINGS |
|
ARCH=${ARCH} |
|
ARCH_DIR=${ARCH_DIR} |
|
) |
|
else() |
|
# For HWMv2 we should in future generate a Kconfig.arch.v2 which instead |
|
# glob-sources all arch roots, but for Zephyr itself, the current approach is |
|
# sufficient. |
|
list(APPEND COMMON_KCONFIG_ENV_SETTINGS |
|
ARCH=* |
|
ARCH_DIR=${ZEPHYR_BASE}/arch |
|
) |
|
endif() |
|
|
|
# Allow out-of-tree users to add their own Kconfig python frontend |
|
# targets by appending targets to the CMake list |
|
# 'EXTRA_KCONFIG_TARGETS' and setting variables named |
|
# 'EXTRA_KCONFIG_TARGET_COMMAND_FOR_<target>' |
|
# |
|
# e.g. |
|
# cmake -DEXTRA_KCONFIG_TARGETS=cli |
|
# -DEXTRA_KCONFIG_TARGET_COMMAND_FOR_cli=cli_kconfig_frontend.py |
|
|
|
set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_menuconfig |
|
${ZEPHYR_BASE}/scripts/kconfig/menuconfig.py |
|
) |
|
|
|
set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_guiconfig |
|
${ZEPHYR_BASE}/scripts/kconfig/guiconfig.py |
|
) |
|
|
|
set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_hardenconfig |
|
${ZEPHYR_BASE}/scripts/kconfig/hardenconfig.py |
|
) |
|
|
|
set_ifndef(KCONFIG_TARGETS menuconfig guiconfig hardenconfig) |
|
|
|
foreach(kconfig_target |
|
${KCONFIG_TARGETS} |
|
${EXTRA_KCONFIG_TARGETS} |
|
) |
|
add_custom_target( |
|
${kconfig_target} |
|
${CMAKE_COMMAND} -E env |
|
ZEPHYR_BASE=${ZEPHYR_BASE} |
|
${COMMON_KCONFIG_ENV_SETTINGS} |
|
"SHIELD_AS_LIST=${SHIELD_AS_LIST_ESCAPED}" |
|
DTS_POST_CPP=${DTS_POST_CPP} |
|
DTS_ROOT_BINDINGS=${DTS_ROOT_BINDINGS} |
|
${PYTHON_EXECUTABLE} |
|
${EXTRA_KCONFIG_TARGET_COMMAND_FOR_${kconfig_target}} |
|
${KCONFIG_ROOT} |
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/kconfig |
|
USES_TERMINAL |
|
COMMAND_EXPAND_LISTS |
|
) |
|
endforeach() |
|
|
|
# Support assigning Kconfig symbols on the command-line with CMake |
|
# cache variables prefixed according to the Kconfig namespace. |
|
# This feature is experimental and undocumented until it has undergone more |
|
# user-testing. |
|
unset(EXTRA_KCONFIG_OPTIONS) |
|
if(SYSBUILD) |
|
get_property(sysbuild_variable_names TARGET sysbuild_cache PROPERTY "SYSBUILD_CACHE:VARIABLES") |
|
zephyr_get(SYSBUILD_MAIN_APP) |
|
zephyr_get(SYSBUILD_NAME) |
|
|
|
foreach (name ${sysbuild_variable_names}) |
|
if("${name}" MATCHES "^${SYSBUILD_NAME}_${KCONFIG_NAMESPACE}_") |
|
string(REGEX REPLACE "^${SYSBUILD_NAME}_" "" org_name ${name}) |
|
get_property(${org_name} TARGET sysbuild_cache PROPERTY ${name}) |
|
list(APPEND cache_variable_names ${org_name}) |
|
elseif(SYSBUILD_MAIN_APP AND "${name}" MATCHES "^${KCONFIG_NAMESPACE}_") |
|
get_property(${name} TARGET sysbuild_cache PROPERTY ${name}) |
|
list(APPEND cache_variable_names ${name}) |
|
endif() |
|
endforeach() |
|
else() |
|
get_cmake_property(cache_variable_names CACHE_VARIABLES) |
|
list(FILTER cache_variable_names INCLUDE REGEX "^(CLI_)?${KCONFIG_NAMESPACE}_") |
|
list(TRANSFORM cache_variable_names REPLACE "^CLI_" "") |
|
list(REMOVE_DUPLICATES cache_variable_names) |
|
endif() |
|
|
|
# Sorting the variable names will make checksum calculation more stable. |
|
list(SORT cache_variable_names) |
|
foreach (name ${cache_variable_names}) |
|
if(DEFINED ${name}) |
|
# When a cache variable starts with the 'KCONFIG_NAMESPACE' value, it is |
|
# assumed to be a Kconfig symbol assignment from the CMake command line. |
|
set(EXTRA_KCONFIG_OPTIONS |
|
"${EXTRA_KCONFIG_OPTIONS}\n${name}=${${name}}" |
|
) |
|
set(CLI_${name} "${${name}}") |
|
list(APPEND cli_config_list ${name}) |
|
elseif(DEFINED CLI_${name}) |
|
# An additional 'CLI_' prefix means that the value was set by the user in |
|
# an earlier invocation. Append it to extra config only if no new value was |
|
# assigned above. |
|
set(EXTRA_KCONFIG_OPTIONS |
|
"${EXTRA_KCONFIG_OPTIONS}\n${name}=${CLI_${name}}" |
|
) |
|
endif() |
|
endforeach() |
|
|
|
if(EXTRA_KCONFIG_OPTIONS) |
|
set(EXTRA_KCONFIG_OPTIONS_FILE ${PROJECT_BINARY_DIR}/misc/generated/extra_kconfig_options.conf) |
|
file(WRITE |
|
${EXTRA_KCONFIG_OPTIONS_FILE} |
|
${EXTRA_KCONFIG_OPTIONS} |
|
) |
|
endif() |
|
|
|
# Bring in extra configuration files dropped in by the user or anyone else; |
|
# make sure they are set at the end so we can override any other setting |
|
file(GLOB config_files ${APPLICATION_BINARY_DIR}/*.conf) |
|
list(SORT config_files) |
|
set( |
|
merge_config_files |
|
${BOARD_DEFCONFIG} |
|
${BOARD_REVISION_CONFIG} |
|
${board_extension_conf_files} |
|
${CONF_FILE_AS_LIST} |
|
${shield_conf_files} |
|
${EXTRA_CONF_FILE_AS_LIST} |
|
${EXTRA_KCONFIG_OPTIONS_FILE} |
|
${config_files} |
|
) |
|
|
|
# Create a list of absolute paths to the .config sources from |
|
# merge_config_files, which is a mix of absolute and relative paths. |
|
set(merge_config_files_with_absolute_paths "") |
|
foreach(f ${merge_config_files}) |
|
if(IS_ABSOLUTE ${f}) |
|
set(path ${f}) |
|
else() |
|
set(path ${APPLICATION_CONFIG_DIR}/${f}) |
|
endif() |
|
|
|
list(APPEND merge_config_files_with_absolute_paths ${path}) |
|
endforeach() |
|
set(merge_config_files ${merge_config_files_with_absolute_paths}) |
|
|
|
foreach(f ${merge_config_files}) |
|
if(NOT EXISTS ${f} OR IS_DIRECTORY ${f}) |
|
message(FATAL_ERROR "File not found: ${f}") |
|
endif() |
|
endforeach() |
|
|
|
# Calculate a checksum of merge_config_files to determine if we need |
|
# to re-generate .config |
|
set(merge_config_files_checksum "") |
|
foreach(f ${merge_config_files}) |
|
file(MD5 ${f} checksum) |
|
set(merge_config_files_checksum "${merge_config_files_checksum}${checksum}") |
|
endforeach() |
|
|
|
# Create a new .config if it does not exists, or if the checksum of |
|
# the dependencies has changed |
|
set(merge_config_files_checksum_file ${PROJECT_BINARY_DIR}/.cmake.dotconfig.checksum) |
|
set(CREATE_NEW_DOTCONFIG 1) |
|
# Check if the checksum file exists too before trying to open it, though it |
|
# should under normal circumstances |
|
if(EXISTS ${DOTCONFIG} AND EXISTS ${merge_config_files_checksum_file}) |
|
# Read out what the checksum was previously |
|
file(READ |
|
${merge_config_files_checksum_file} |
|
merge_config_files_checksum_prev |
|
) |
|
if( |
|
${merge_config_files_checksum} STREQUAL |
|
${merge_config_files_checksum_prev} |
|
) |
|
# Checksum is the same as before |
|
set(CREATE_NEW_DOTCONFIG 0) |
|
endif() |
|
endif() |
|
|
|
if(CREATE_NEW_DOTCONFIG) |
|
set(input_configs_flags --handwritten-input-configs) |
|
set(input_configs ${merge_config_files} ${FORCED_CONF_FILE}) |
|
else() |
|
set(input_configs ${DOTCONFIG} ${FORCED_CONF_FILE}) |
|
endif() |
|
|
|
if(DEFINED FORCED_CONF_FILE) |
|
list(APPEND input_configs_flags --forced-input-configs) |
|
endif() |
|
|
|
cmake_path(GET AUTOCONF_H PARENT_PATH autoconf_h_path) |
|
if(NOT EXISTS ${autoconf_h_path}) |
|
file(MAKE_DIRECTORY ${autoconf_h_path}) |
|
endif() |
|
|
|
execute_process( |
|
COMMAND ${CMAKE_COMMAND} -E env |
|
${COMMON_KCONFIG_ENV_SETTINGS} |
|
SHIELD_AS_LIST=${SHIELD_AS_LIST_ESCAPED_COMMAND} |
|
${PYTHON_EXECUTABLE} |
|
${ZEPHYR_BASE}/scripts/kconfig/kconfig.py |
|
--zephyr-base=${ZEPHYR_BASE} |
|
${input_configs_flags} |
|
${KCONFIG_ROOT} |
|
${DOTCONFIG} |
|
${AUTOCONF_H} |
|
${PARSED_KCONFIG_SOURCES_TXT} |
|
${input_configs} |
|
WORKING_DIRECTORY ${APPLICATION_SOURCE_DIR} |
|
# The working directory is set to the app dir such that the user |
|
# can use relative paths in CONF_FILE, e.g. CONF_FILE=nrf5.conf |
|
RESULT_VARIABLE ret |
|
) |
|
if(NOT "${ret}" STREQUAL "0") |
|
message(FATAL_ERROR "command failed with return code: ${ret}") |
|
endif() |
|
|
|
if(CREATE_NEW_DOTCONFIG) |
|
# Write the new configuration fragment checksum. Only do this if kconfig.py |
|
# succeeds, to avoid marking zephyr/.config as up-to-date when it hasn't been |
|
# regenerated. |
|
file(WRITE ${merge_config_files_checksum_file} |
|
${merge_config_files_checksum}) |
|
endif() |
|
|
|
# Read out the list of 'Kconfig' sources that were used by the engine. |
|
file(STRINGS ${PARSED_KCONFIG_SOURCES_TXT} PARSED_KCONFIG_SOURCES_LIST) |
|
|
|
# Force CMAKE configure when the Kconfig sources or configuration files changes. |
|
foreach(kconfig_input |
|
${merge_config_files} |
|
${DOTCONFIG} |
|
${PARSED_KCONFIG_SOURCES_LIST} |
|
) |
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${kconfig_input}) |
|
endforeach() |
|
|
|
add_custom_target(config-twister DEPENDS ${DOTCONFIG}) |
|
|
|
# Remove the CLI Kconfig symbols from the namespace and |
|
# CMakeCache.txt. If the symbols end up in DOTCONFIG they will be |
|
# re-introduced to the namespace through 'import_kconfig'. |
|
foreach (name ${cli_config_list}) |
|
unset(${name}) |
|
unset(${name} CACHE) |
|
endforeach() |
|
|
|
# Before importing the symbol values from DOTCONFIG, process the CLI values by |
|
# re-importing them from EXTRA_KCONFIG_OPTIONS_FILE. Later, we want to compare |
|
# the values from both files, and 'import_kconfig' will make this easier. |
|
if(EXTRA_KCONFIG_OPTIONS_FILE) |
|
import_kconfig(${KCONFIG_NAMESPACE} ${EXTRA_KCONFIG_OPTIONS_FILE}) |
|
foreach (name ${cache_variable_names}) |
|
if(DEFINED ${name}) |
|
set(temp_${name} "${${name}}") |
|
unset(${name}) |
|
endif() |
|
endforeach() |
|
endif() |
|
|
|
# Import the .config file and make all settings available in CMake processing. |
|
import_kconfig(${KCONFIG_NAMESPACE} ${DOTCONFIG}) |
|
|
|
# Cache the CLI Kconfig symbols that survived through Kconfig, prefixed with CLI_. |
|
# Remove those who might have changed compared to earlier runs, if they no longer appears. |
|
foreach (name ${cache_variable_names}) |
|
# Note: "${CLI_${name}}" is the verbatim value of ${name} from command-line, |
|
# while "${temp_${name}}" is the same value processed by 'import_kconfig'. |
|
if(((NOT DEFINED ${name}) AND (NOT DEFINED temp_${name})) OR |
|
((DEFINED ${name}) AND (DEFINED temp_${name}) AND (${name} STREQUAL temp_${name}))) |
|
set(CLI_${name} ${CLI_${name}} CACHE INTERNAL "") |
|
else() |
|
unset(CLI_${name} CACHE) |
|
endif() |
|
unset(temp_${name}) |
|
endforeach()
|
|
|