1# SPDX-License-Identifier: Apache-2.0 2 3# Folders needed for conf/mconf files (kconfig has no method of redirecting all output files). 4# conf/mconf needs to be run from a different directory because of: GH-3408 5file(MAKE_DIRECTORY ${APPLICATION_BINARY_DIR}/kconfig/include/generated) 6file(MAKE_DIRECTORY ${APPLICATION_BINARY_DIR}/kconfig/include/config) 7 8if(KCONFIG_ROOT) 9 # KCONFIG_ROOT has either been specified as a CMake variable or is 10 # already in the CMakeCache.txt. This has precedence. 11elseif(EXISTS ${APPLICATION_SOURCE_DIR}/Kconfig) 12 set(KCONFIG_ROOT ${APPLICATION_SOURCE_DIR}/Kconfig) 13endif() 14 15if (EXISTS ${BOARD_DIR}/${BOARD}_defconfig) 16set(BOARD_DEFCONFIG ${BOARD_DIR}/${BOARD}_defconfig) 17endif() 18 19if(EXISTS ${APPLICATION_SOURCE_DIR}/config.cmake) 20 set(DOTCONFIG_IN ${APPLICATION_SOURCE_DIR}/config.cmake) 21else() 22 set(DOTCONFIG_IN ${APPLICATION_SOURCE_DIR}/.config) 23endif() 24set(DOTCONFIG_OUT ${APPLICATION_SOURCE_DIR}/.config) 25set(PARSED_KCONFIG_SOURCES_TXT ${APPLICATION_BINARY_DIR}/kconfig/sources.txt) 26 27if(CONF_FILE) 28string(REPLACE " " ";" CONF_FILE_AS_LIST "${CONF_FILE}") 29endif() 30 31if(OVERLAY_CONFIG) 32 string(REPLACE " " ";" OVERLAY_CONFIG_AS_LIST "${OVERLAY_CONFIG}") 33endif() 34 35# DTS_ROOT_BINDINGS is a semicolon separated list, this causes 36# problems when invoking kconfig_target since semicolon is a special 37# character in the C shell, so we make it into a question-mark 38# separated list instead. 39string(REPLACE ";" "?" DTS_ROOT_BINDINGS "${DTS_ROOT_BINDINGS}") 40 41set(ENV{srctree} ${PROJECT_ROOT}) 42set(ENV{KCONFIG_BASE} ${PROJECT_ROOT}) 43 44# Not used in current MCUXpresso SDK, take from zephyr cmake build system 45set(ENV{KERNELVERSION} ${KERNELVERSION}) 46 47set(ENV{KCONFIG_CONFIG} ${DOTCONFIG_IN}) 48set(ENV{PYTHON_EXECUTABLE} ${PYTHON_EXECUTABLE}) 49 50message("project root: ${PROJECT_ROOT}") 51 52# Set environment variables so that Kconfig can prune Kconfig source 53# files for other architectures 54set(ENV{BOARD_DIR} ${BOARD_DIR}) 55 56# Below environment variables currently not used in MCUXpresso SDK, take from zephyr cmake build system, remain it for future use. 57set(ENV{ARCH} ${ARCH}) 58set(ENV{SOC_DIR} ${SOC_DIR}) 59set(ENV{SHIELD_AS_LIST} "${SHIELD_AS_LIST}") 60set(ENV{CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}) 61set(ENV{ARCH_DIR} ${ARCH_DIR}) 62set(ENV{DEVICETREE_CONF} ${DEVICETREE_CONF}) 63set(ENV{DTS_POST_CPP} ${DTS_POST_CPP}) 64set(ENV{DTS_ROOT_BINDINGS} "${DTS_ROOT_BINDINGS}") 65set(ENV{TOOLCHAIN_KCONFIG_DIR} "${TOOLCHAIN_KCONFIG_DIR}") 66 67# Allow out-of-tree users to add their own Kconfig python frontend 68# targets by appending targets to the CMake list 69# 'EXTRA_KCONFIG_TARGETS' and setting variables named 70# 'EXTRA_KCONFIG_TARGET_COMMAND_FOR_<target>' 71# 72# e.g. 73# cmake -DEXTRA_KCONFIG_TARGETS=cli 74# -DEXTRA_KCONFIG_TARGET_COMMAND_FOR_cli=cli_kconfig_frontend.py 75 76set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_menuconfig 77 ${PROJECT_ROOT}/scripts/kconfig/menuconfig.py 78 ) 79 80set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_guiconfig 81 ${PROJECT_ROOT}/scripts/kconfig/guiconfig.py 82 ) 83 84set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_hardenconfig 85 ${PROJECT_ROOT}/scripts/kconfig/hardenconfig.py 86 ) 87 88foreach(kconfig_target 89 menuconfig 90 guiconfig 91 hardenconfig 92 ${EXTRA_KCONFIG_TARGETS} 93 ) 94 add_custom_target( 95 ${kconfig_target} 96 ${CMAKE_COMMAND} -E env 97 PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} 98 KCONFIG_BASE=${PROJECT_ROOT} 99 KCONFIG_CONFIG=${DOTCONFIG_IN} 100 ARCH=$ENV{ARCH} 101 BOARD_DIR=$ENV{BOARD_DIR} 102 SOC_DIR=$ENV{SOC_DIR} 103 SHIELD_AS_LIST=$ENV{SHIELD_AS_LIST} 104 CMAKE_BINARY_DIR=$ENV{CMAKE_BINARY_DIR} 105 TOOLCHAIN_KCONFIG_DIR=${TOOLCHAIN_KCONFIG_DIR} 106 ARCH_DIR=$ENV{ARCH_DIR} 107 DEVICETREE_CONF=${DEVICETREE_CONF} 108 DTS_POST_CPP=${DTS_POST_CPP} 109 DTS_ROOT_BINDINGS=${DTS_ROOT_BINDINGS} 110 ${PYTHON_EXECUTABLE} 111 ${PROJECT_ROOT}/scripts/kconfig/mcux.py 112 ${kconfig_target} 113 ${KCONFIG_ROOT} 114 WORKING_DIRECTORY ${APPLICATION_BINARY_DIR}/kconfig 115 USES_TERMINAL 116 ) 117endforeach() 118 119# Support assigning Kconfig symbols on the command-line with CMake 120# cache variables prefixed with 'CONFIG_'. This feature is 121# experimental and undocumented until it has undergone more 122# user-testing. 123unset(EXTRA_KCONFIG_OPTIONS) 124get_cmake_property(cache_variable_names CACHE_VARIABLES) 125foreach (name ${cache_variable_names}) 126 if("${name}" MATCHES "^CONFIG_") 127 # When a cache variable starts with 'CONFIG_', it is assumed to be 128 # a Kconfig symbol assignment from the CMake command line. 129 set(EXTRA_KCONFIG_OPTIONS 130 "${EXTRA_KCONFIG_OPTIONS}\n${name}=${${name}}" 131 ) 132 endif() 133endforeach() 134 135if(EXTRA_KCONFIG_OPTIONS) 136 set(EXTRA_KCONFIG_OPTIONS_FILE ${APPLICATION_BINARY_DIR}/misc/generated/extra_kconfig_options.conf) 137 file(WRITE 138 ${EXTRA_KCONFIG_OPTIONS_FILE} 139 ${EXTRA_KCONFIG_OPTIONS} 140 ) 141endif() 142 143# Bring in extra configuration files dropped in by the user or anyone else; 144# make sure they are set at the end so we can override any other setting 145set(config_files ${APPLICATION_SOURCE_DIR}/config.cmake) 146set( 147 merge_config_files 148 ${BOARD_DEFCONFIG} 149 ${CONF_FILE_AS_LIST} 150 ${shield_conf_files} 151 ${OVERLAY_CONFIG_AS_LIST} 152 ${EXTRA_KCONFIG_OPTIONS_FILE} 153 ${config_files} 154) 155 156# Create a list of absolute paths to the .config sources from 157# merge_config_files, which is a mix of absolute and relative paths. 158set(merge_config_files_with_absolute_paths "") 159foreach(f ${merge_config_files}) 160 if(IS_ABSOLUTE ${f}) 161 set(path ${f}) 162 else() 163 set(path ${APPLICATION_SOURCE_DIR}/${f}) 164 endif() 165 166 list(APPEND merge_config_files_with_absolute_paths ${path}) 167endforeach() 168 169foreach(f ${merge_config_files_with_absolute_paths}) 170 if(NOT EXISTS ${f} OR IS_DIRECTORY ${f}) 171 message(FATAL_ERROR "File not found: ${f}") 172 endif() 173endforeach() 174 175# Calculate a checksum of merge_config_files to determine if we need 176# to re-generate .config 177set(merge_config_files_checksum "") 178foreach(f ${merge_config_files_with_absolute_paths}) 179 file(MD5 ${f} checksum) 180 set(merge_config_files_checksum "${merge_config_files_checksum}${checksum}") 181endforeach() 182 183# Create a new .config if it does not exists, or if the checksum of 184# the dependencies has changed 185set(merge_config_files_checksum_file ${APPLICATION_BINARY_DIR}/.cmake.dotconfig.checksum) 186set(CREATE_NEW_DOTCONFIG 1) 187# Check if the checksum file exists too before trying to open it, though it 188# should under normal circumstances 189if(EXISTS ${DOTCONFIG_OUT} AND EXISTS ${merge_config_files_checksum_file}) 190 # Read out what the checksum was previously 191 file(READ 192 ${merge_config_files_checksum_file} 193 merge_config_files_checksum_prev 194 ) 195 if( 196 ${merge_config_files_checksum} STREQUAL 197 ${merge_config_files_checksum_prev} 198 ) 199 # Checksum is the same as before 200 set(CREATE_NEW_DOTCONFIG 0) 201 endif() 202endif() 203 204if(CREATE_NEW_DOTCONFIG) 205# set(input_configs_are_handwritten --handwritten-input-configs="") 206 set(input_configs ${merge_config_files}) 207else() 208 set(input_configs ${DOTCONFIG_IN}) 209endif() 210 211 212message( 213 ${PYTHON_EXECUTABLE} 214 ${PROJECT_ROOT}/scripts/kconfig/kconfig.py 215 ${input_configs_are_handwritten} 216 ${KCONFIG_ROOT} 217 ${DOTCONFIG_OUT} 218 ${AUTOCONF_H} 219 ${PARSED_KCONFIG_SOURCES_TXT} 220 ${input_configs} 221 ) 222execute_process( 223 COMMAND 224 ${PYTHON_EXECUTABLE} 225 ${PROJECT_ROOT}/scripts/kconfig/kconfig.py 226 ${input_configs_are_handwritten} 227 ${KCONFIG_ROOT} 228 ${DOTCONFIG_OUT} 229 ${AUTOCONF_H} 230 ${PARSED_KCONFIG_SOURCES_TXT} 231 ${input_configs} 232 WORKING_DIRECTORY ${PROJECT_ROOT} 233 # The working directory is set to the app dir such that the user 234 # can use relative paths in CONF_FILE, e.g. CONF_FILE=nrf5.conf 235 RESULT_VARIABLE ret 236 ) 237if(NOT "${ret}" STREQUAL "0") 238 message(FATAL_ERROR "command failed with return code: ${ret}") 239endif() 240 241if(CREATE_NEW_DOTCONFIG) 242 # Write the new configuration fragment checksum. Only do this if kconfig.py 243 # succeeds, to avoid marking APPLICATION_BINARY_DIR/.config as up-to-date when it hasn't been 244 # regenerated. 245 file(WRITE ${merge_config_files_checksum_file} 246 ${merge_config_files_checksum}) 247endif() 248 249# Read out the list of 'Kconfig' sources that were used by the engine. 250file(STRINGS ${PARSED_KCONFIG_SOURCES_TXT} PARSED_KCONFIG_SOURCES_LIST) 251 252# Force CMAKE configure when the Kconfig sources or configuration files changes. 253foreach(kconfig_input 254 ${merge_config_files} 255 ${DOTCONFIG_IN} 256 ${PARSED_KCONFIG_SOURCES_LIST} 257 ) 258 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${kconfig_input}) 259endforeach() 260 261add_custom_target(config-sanitycheck DEPENDS ${DOTCONFIG_OUT}) 262 263# Remove the CLI Kconfig symbols from the namespace and 264# CMakeCache.txt. If the symbols end up in DOTCONFIG they will be 265# re-introduced to the namespace through 'import_kconfig'. 266foreach (name ${cache_variable_names}) 267 if("${name}" MATCHES "^CONFIG_") 268 unset(${name}) 269 unset(${name} CACHE) 270 endif() 271endforeach() 272 273# Parse the lines prefixed with CONFIG_ in the .config file from Kconfig 274import_kconfig("^CONFIG_" ${DOTCONFIG_OUT}) 275 276# Re-introduce the CLI Kconfig symbols that survived 277foreach (name ${cache_variable_names}) 278 if("${name}" MATCHES "^CONFIG_") 279 if(DEFINED ${name}) 280 set(${name} ${${name}} CACHE STRING "") 281 endif() 282 endif() 283endforeach() 284