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