-
Notifications
You must be signed in to change notification settings - Fork 6.8k
/
kconfig.cmake
373 lines (329 loc) · 12.8 KB
/
kconfig.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# 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})
# Support multiple SOC_ROOT, remove ZEPHYR_BASE as that is always sourced.
set(kconfig_soc_root ${SOC_ROOT})
list(REMOVE_ITEM kconfig_soc_root ${ZEPHYR_BASE})
set(OPERATION WRITE)
foreach(root ${kconfig_soc_root})
file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.soc.defconfig
"osource \"${root}/soc/$(ARCH)/*/Kconfig.defconfig\"\n"
)
file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.soc
"osource \"${root}/soc/$(ARCH)/*/Kconfig.soc\"\n"
)
file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.soc.arch
"osource \"${root}/soc/$(ARCH)/Kconfig\"\n"
"osource \"${root}/soc/$(ARCH)/*/Kconfig\"\n"
)
set(OPERATION APPEND)
endforeach()
# 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)
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()
set_ifndef(BOARD_DEFCONFIG ${BOARD_DIR}/${BOARD}_defconfig)
if((DEFINED BOARD_REVISION) AND EXISTS ${BOARD_DIR}/${BOARD}_${BOARD_REVISION_STRING}.conf)
set_ifndef(BOARD_REVISION_CONFIG ${BOARD_DIR}/${BOARD}_${BOARD_REVISION_STRING}.conf)
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()
zephyr_get(OVERLAY_CONFIG SYSBUILD LOCAL)
if(OVERLAY_CONFIG)
string(CONFIGURE "${OVERLAY_CONFIG}" OVERLAY_CONFIG_EXPANDED)
string(REPLACE " " ";" OVERLAY_CONFIG_AS_LIST "${OVERLAY_CONFIG_EXPANDED}")
endif()
# 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}")
set(COMMON_KCONFIG_ENV_SETTINGS
PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
srctree=${ZEPHYR_BASE}
KERNELVERSION=${KERNELVERSION}
CONFIG_=${KCONFIG_NAMESPACE}_
KCONFIG_CONFIG=${DOTCONFIG}
# Set environment variables so that Kconfig can prune Kconfig source
# files for other architectures
ARCH=${ARCH}
ARCH_DIR=${ARCH_DIR}
BOARD_DIR=${BOARD_DIR}
BOARD_REVISION=${BOARD_REVISION}
KCONFIG_BINARY_DIR=${KCONFIG_BINARY_DIR}
ZEPHYR_TOOLCHAIN_VARIANT=${ZEPHYR_TOOLCHAIN_VARIANT}
TOOLCHAIN_KCONFIG_DIR=${TOOLCHAIN_KCONFIG_DIR}
TOOLCHAIN_HAS_NEWLIB=$<IF:$<BOOL:${TOOLCHAIN_HAS_NEWLIB}>,y,n>
EDT_PICKLE=${EDT_PICKLE}
# Export all Zephyr modules to Kconfig
${ZEPHYR_KCONFIG_MODULES_DIR}
)
# 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)
endif()
foreach (name ${cache_variable_names})
if("${name}" MATCHES "^CLI_${KCONFIG_NAMESPACE}_")
# Variable was set by user in earlier invocation, let's append to extra
# config unless a new value has been given.
string(REGEX REPLACE "^CLI_" "" org_name ${name})
if(NOT DEFINED ${org_name})
set(EXTRA_KCONFIG_OPTIONS
"${EXTRA_KCONFIG_OPTIONS}\n${org_name}=${${name}}"
)
endif()
elseif("${name}" MATCHES "^${KCONFIG_NAMESPACE}_")
# 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})
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}
${CONF_FILE_AS_LIST}
${shield_conf_files}
${OVERLAY_CONFIG_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_are_handwritten --handwritten-input-configs)
set(input_configs ${merge_config_files})
else()
set(input_configs ${DOTCONFIG})
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_are_handwritten}
${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()
# 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 ${cli_config_list})
if(DEFINED ${name})
set(CLI_${name} ${CLI_${name}} CACHE INTERNAL "")
else()
unset(CLI_${name} CACHE)
endif()
endforeach()