blob: 83f051dce0c0a500f1df80097056c7b350eb7086 [file] [log] [blame]
Jianliang Shen7e48bef2022-10-31 16:15:36 +08001#-------------------------------------------------------------------------------
Kevin Penga2b68022023-01-13 13:54:05 +08002# Copyright (c) 2022-2023, Arm Limited. All rights reserved.
Jianliang Shen7e48bef2022-10-31 16:15:36 +08003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
Kevin Peng97ac6982022-11-24 17:10:00 +08008# Load multiple config files and merge into one, generates CMake config file and config header file.
9# The first loaded configs would be overridden by later ones. That's how the "merge" works.
10# Check CONFIG_FILE_LIST for the loading order.
11# Configurations not set by any of the config files would be set to the default values in Kconfig
12# files with dependencies respected.
13# If a ".config" already exists in the output folder, then the CONFIG_FILE_LIST is ignored.
14# For more details, check the kconfig_system.rst.
15
16set(KCONFIG_OUTPUT_DIR ${CMAKE_BINARY_DIR}/kconfig)
17
18set(DOTCONFIG_FILE ${KCONFIG_OUTPUT_DIR}/.config)
19set(ROOT_KCONFIG ${CMAKE_SOURCE_DIR}/Kconfig)
20set(PLATFORM_KCONFIG ${TARGET_PLATFORM_PATH}/Kconfig)
Jianliang Shen7e48bef2022-10-31 16:15:36 +080021
Kevin Peng026b8112023-01-13 11:24:38 +080022# This function parses the input ${cmake_file} to get normal CMake variables and their values in the
23# format of "set(_VAR_ _VALUE_)". The format could be split into multiple lines.
24# Note that CMake does not allow the "(" to be in a different line as "set" and no white spaces are
25# recommanded between "set" and "(". So the function only covers format of "set(".
26function(convert_normal_cmake_config_to_kconfig cmake_file out_var)
27 # Operate on a local var and write back to the "out_var" later.
28 set(local_var "")
29
30 # Read out the strings of the file. Binary data in the file are ignored
31 file(STRINGS ${cmake_file} CONTENTS)
32
33 # Exclude lines of comments (started with "#")
34 set(CONTENTS_WITHOUT_COMMENTS "")
35
36 foreach(LINE ${CONTENTS})
37 string(REGEX MATCH "^#.*" OUT_STRING ${LINE})
38 if(NOT OUT_STRING)
39 string(APPEND CONTENTS_WITHOUT_COMMENTS "${LINE}\n")
40 endif()
Kevin Peng13f0c252023-03-23 17:26:38 +080041
42 string(REGEX MATCH "^include\\((.*)\\)$" OUT_STRING ${LINE})
43 if(OUT_STRING AND CMAKE_MATCH_COUNT EQUAL 1)
44 message(FATAL_ERROR "Including another file in config file is not supported yet: ${LINE}")
45 endif()
Kevin Peng026b8112023-01-13 11:24:38 +080046 endforeach()
47
48 # Search for strings match set(_VAR_ _VALUE_) with support of multi-line format
49 string(REGEX MATCHALL
50 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*([^ \t\r\n]*)[ \t\r\n]*\\)"
51 OUT_STRINGS ${CONTENTS_WITHOUT_COMMENTS})
52
53 foreach(MATCHED_ITEM ${OUT_STRINGS})
54 # Try to convert CMake format to Kconfig one
55 # If the format does not match, the content will not be changed and fall down to the next
56
57 # Bool types
58 string(REGEX REPLACE
59 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*(TRUE|ON)[ \t\r\n]*\\)"
60 "config \\1\n default y\n"
61 MATCHED_ITEM ${MATCHED_ITEM})
62 string(REGEX REPLACE
63 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*(FALSE|OFF)[ \t\r\n]*\\)"
64 "config \\1\n default n\n"
65 MATCHED_ITEM ${MATCHED_ITEM})
66 # Hex int
67 string(REGEX REPLACE
68 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*(0x[0-9a-fA-F]+[ \t\r\n]*)\\)"
69 "config \\1\n default \\2\n"
70 MATCHED_ITEM ${MATCHED_ITEM})
71 # Decimal int
72 string(REGEX REPLACE
73 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*([0-9]+)[ \t\r\n]*\\)"
74 "config \\1\n default \\2\n"
75 MATCHED_ITEM ${MATCHED_ITEM})
76 # Quoted string
77 string(REGEX REPLACE
78 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*(\".*\")[ \t\r\n]*\\)"
79 "config \\1\n default \\2\n"
80 MATCHED_ITEM ${MATCHED_ITEM})
81 # If none of the above matches, must be a non-quoted string
82 string(REGEX REPLACE
83 "set\\([ \t\r\n]*([A-Za-z0-9_]*)[ \t\r\n]*(.*)[ \t\r\n]*\\)"
84 "config \\1\n default \"\\2\"\n"
85 MATCHED_ITEM ${MATCHED_ITEM})
86
87 string(APPEND local_var ${MATCHED_ITEM})
88 endforeach()
89
90 set(${out_var} ${local_var} PARENT_SCOPE)
91endfunction()
92
Kevin Penge72f29e2023-01-29 17:05:35 +080093# This function goes through the CMake cache variables and convert them to .config format.
94# The function distinguishes command-line variables and other ones and it can only handle one of
95# them in the same time.
96function(convert_cache_config_to_dotconfig convert_cl_var out_var)
97 # Operate on a local var and write back to the out_var later
98 set(local_var "")
Kevin Pengb9c99f02022-12-07 11:23:17 +080099
Kevin Penge72f29e2023-01-29 17:05:35 +0800100 get_cmake_property(CACHE_VARS CACHE_VARIABLES)
101 foreach(CACHE_VAR ${CACHE_VARS})
102 get_property(HELP_STRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING)
103
104 if("${HELP_STRING}" MATCHES "variable specified on the command line")
105 # Command-line variables have the help string above by default
106 set(IS_CL_VAR TRUE)
107 else()
108 set(IS_CL_VAR FALSE)
109 endif()
110
111 if((IS_CL_VAR AND NOT ${convert_cl_var}) OR (NOT IS_CL_VAR AND ${convert_cl_var}))
112 continue()
113 endif()
114
115 set(CACHE_VAR_VAL ${${CACHE_VAR}})
116 STRING(TOUPPER "${CACHE_VAR_VAL}" CACHE_VAR_VAL_UPPER)
117
118 set(CACHE_VAR "CONFIG_${CACHE_VAR}")
119
120 set(KCONFIG_OPTION_ITEM "")
121
122 # False CMAKE values
123 if(CACHE_VAR_VAL_UPPER STREQUAL "OFF" OR CACHE_VAR_VAL_UPPER STREQUAL "FALSE")
124 set(KCONFIG_OPTION_ITEM "${CACHE_VAR}=n\r\n")
125 # True CMAKE Values
126 elseif(CACHE_VAR_VAL_UPPER STREQUAL "ON" OR CACHE_VAR_VAL_UPPER STREQUAL "TRUE")
127 set(KCONFIG_OPTION_ITEM "${CACHE_VAR}=y\r\n")
128 # Non-quoted values (hex and decimal numbers)
129 elseif(CACHE_VAR_VAL MATCHES "^0x[a-fA-F0-9]+$" OR CACHE_VAR_VAL MATCHES "^[0-9]+$" )
130 set(KCONFIG_OPTION_ITEM "${CACHE_VAR}=${CACHE_VAR_VAL}\r\n")
131 # Everything else is a quoted string
132 else()
133 if(${CACHE_VAR} STREQUAL "CONFIG_TEST_PSA_API")
134 # Turn on the corresponding "choice" option for psa-arch-test
135 list(APPEND _LEGAL_PSA_API_TEST_LIST "IPC" "CRYPTO" "INITIAL_ATTESTATION" "INTERNAL_TRUSTED_STORAGE" "PROTECTED_STORAGE" "STORAGE")
136 list(FIND _LEGAL_PSA_API_TEST_LIST ${CACHE_VAR_VAL_UPPER} _RET_VAL)
137 if(NOT ${_RET_VAL} EQUAL -1)
138 set(KCONFIG_OPTION_ITEM "CONFIG_PSA_API_TEST_${CACHE_VAR_VAL_UPPER}=y\r\n")
139
140 if(${CACHE_VAR_VAL_UPPER} STREQUAL "IPC")
141 # PSA API IPC test requires IPC model to be enabled while
142 # the CONFIG_TFM_SPM_BACKEND_IPC cannot be selected or implied because it is a choice.
143 # It can be only enabled in a Kconfig config file. So append it here.
144 string(APPEND KCONFIG_OPTION_ITEM "CONFIG_CONFIG_TFM_SPM_BACKEND_IPC=y\r\n")
145 endif()
146 endif()
147 elseif(${CACHE_VAR} STREQUAL "CONFIG_CONFIG_TFM_SPM_BACKEND")
148 # Turn on the corresponding "choice" option for SPM backend
149 set(KCONFIG_OPTION_ITEM "CONFIG_CONFIG_TFM_SPM_BACKEND_${CACHE_VAR_VAL_UPPER}=y\r\n")
150 else()
151 set(KCONFIG_OPTION_ITEM "${CACHE_VAR}=\"${CACHE_VAR_VAL}\"\r\n")
152 endif()
153 endif()
154
155 string(APPEND local_var ${KCONFIG_OPTION_ITEM})
156 endforeach()
157
158 set(${out_var} ${local_var} PARENT_SCOPE)
159endfunction()
160
161# Initialize the .cl_config
162set(COMMAND_LINE_CONFIG_TO_FILE ${KCONFIG_OUTPUT_DIR}/.cl_config)
163file(REMOVE ${COMMAND_LINE_CONFIG_TO_FILE})
164
165# Initialize the .cache_var_config
166set(CACHE_VAR_CONFIG_FILE ${KCONFIG_OUTPUT_DIR}/.cache_var_config)
167file(REMOVE ${CACHE_VAR_CONFIG_FILE})
168
169if(NOT EXISTS ${PLATFORM_KCONFIG})
Kevin Peng026b8112023-01-13 11:24:38 +0800170 # Parse platform's preload.cmake and config.cmake to get config options.
171 set(PLATFORM_KCONFIG_OPTIONS "")
172 set(PLATFORM_KCONFIG ${KCONFIG_OUTPUT_DIR}/platform/Kconfig)
173
174 convert_normal_cmake_config_to_kconfig(${TARGET_PLATFORM_PATH}/preload.cmake PLATFORM_KCONFIG_OPTIONS)
175 file(WRITE ${PLATFORM_KCONFIG} ${PLATFORM_KCONFIG_OPTIONS})
176
Kevin Pengb9c99f02022-12-07 11:23:17 +0800177 if(EXISTS ${TARGET_PLATFORM_PATH}/config.cmake)
178 include(${TARGET_PLATFORM_PATH}/config.cmake)
Kevin Peng026b8112023-01-13 11:24:38 +0800179 convert_normal_cmake_config_to_kconfig(${TARGET_PLATFORM_PATH}/config.cmake PLATFORM_KCONFIG_OPTIONS)
180 file(APPEND ${PLATFORM_KCONFIG} ${PLATFORM_KCONFIG_OPTIONS})
Kevin Penge72f29e2023-01-29 17:05:35 +0800181
182 set(PLATFORM_CMAKE_CONFIGS "")
183 set(CONVERT_CL_VAR FALSE)
184 convert_cache_config_to_dotconfig(CONVERT_CL_VAR PLATFORM_CMAKE_CONFIGS)
185 file(APPEND ${CACHE_VAR_CONFIG_FILE} ${PLATFORM_CMAKE_CONFIGS})
Kevin Pengb9c99f02022-12-07 11:23:17 +0800186 endif()
187endif()
Kevin Peng026b8112023-01-13 11:24:38 +0800188get_filename_component(PLATFORM_KCONFIG_PATH ${PLATFORM_KCONFIG} DIRECTORY)
Jianliang Shen7e48bef2022-10-31 16:15:36 +0800189
Jianliang Shen9e90a562023-02-20 15:04:12 +0800190# TF-M profile config file
191if(TFM_PROFILE)
192 set(TFM_PROFILE_KCONFIG_FILE ${CMAKE_SOURCE_DIR}/config/profile/${TFM_PROFILE}.conf)
193 if(NOT EXISTS ${TFM_PROFILE_KCONFIG_FILE})
194 message(FATAL_ERROR "No such file: ${TFM_PROFILE_KCONFIG_FILE}, please check ${TFM_PROFILE} is right.")
195 endif()
196
197 set(TFM_PROFILE_TEST_KCONFIG_FILE ${CMAKE_SOURCE_DIR}/lib/ext/tf-m-tests/${TFM_PROFILE}_test.conf)
198 if(NOT EXISTS ${TFM_PROFILE_TEST_KCONFIG_FILE})
199 message(FATAL_ERROR "No such file: ${TFM_PROFILE_TEST_KCONFIG_FILE}, please check ${TFM_PROFILE} is right.")
200 endif()
201endif()
202
Kevin Penge72f29e2023-01-29 17:05:35 +0800203# Parse command-line variables
204set(CL_CONFIGS "")
205set(CONVERT_CL_VAR TRUE)
206convert_cache_config_to_dotconfig(CONVERT_CL_VAR CL_CONFIGS)
207file(APPEND ${COMMAND_LINE_CONFIG_TO_FILE} ${CL_CONFIGS})
208
209if(NOT EXISTS ${CACHE_VAR_CONFIG_FILE})
210 set(CACHE_VAR_CONFIG_FILE "")
211endif()
212
Kevin Peng97ac6982022-11-24 17:10:00 +0800213# User customized config file
214if(DEFINED KCONFIG_CONFIG_FILE AND NOT EXISTS ${KCONFIG_CONFIG_FILE})
215 message(FATAL_ERROR "No such file: ${KCONFIG_CONFIG_FILE}")
216endif()
217
218# Note the order of CONFIG_FILE_LIST, as the first loaded configs would be
219# overridden by later ones.
220list(APPEND CONFIG_FILE_LIST
Jianliang Shen9e90a562023-02-20 15:04:12 +0800221 ${TFM_PROFILE_KCONFIG_FILE}
222 ${TFM_PROFILE_TEST_KCONFIG_FILE}
Kevin Penge72f29e2023-01-29 17:05:35 +0800223 ${CACHE_VAR_CONFIG_FILE}
224 ${KCONFIG_CONFIG_FILE}
225 ${COMMAND_LINE_CONFIG_TO_FILE})
Kevin Peng97ac6982022-11-24 17:10:00 +0800226
227# Set up ENV variables for the tfm_kconfig.py which are then consumed by Kconfig files.
Jianliang Shenc4e719b2023-03-02 14:37:54 +0800228set(KCONFIG_ENV_VARS "TFM_SOURCE_DIR=${CMAKE_SOURCE_DIR} \
Kevin Peng97ac6982022-11-24 17:10:00 +0800229 TFM_VERSION=${TFM_VERSION} \
Kevin Peng026b8112023-01-13 11:24:38 +0800230 PLATFORM_PATH=${PLATFORM_KCONFIG_PATH} \
Kevin Peng97ac6982022-11-24 17:10:00 +0800231 CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
232
233if(MENUCONFIG)
234 # Note: Currently, only GUI menuconfig can be supported with CMake integration
235 set(MENUCONFIG_ARG "-u=gui")
236else()
237 set(MENUCONFIG_ARG "")
238endif()
239
Jianliang Shen7c67ab12023-03-14 14:41:34 +0800240if(DEFINED PROJECT_CONFIG_HEADER_FILE)
241 get_property(HELP_STRING CACHE PROJECT_CONFIG_HEADER_FILE PROPERTY HELPSTRING)
242
243 # It is not supported to set PROJECT_CONFIG_HEADER_FILE while using Kconfig, either from
244 # command line or CMake files. It should be set to the file generated the Kconfig system.
245 # As this file set it itself, if the user re-run the CMake config command, the
246 # PROJECT_CONFIG_HEADER_FILE will be already defined set.
247 # So the existence of the ${DOTCONFIG_FILE} is used to indicate if it is a re-configuration.
248 if("${HELP_STRING}" MATCHES "variable specified on the command line" OR NOT EXISTS ${DOTCONFIG_FILE})
249 message(FATAL_ERROR "It is NOT supported to manually set PROJECT_CONFIG_HEADER_FILE while using Kconfig.")
250 endif()
251endif()
252
Jianliang Shen7e48bef2022-10-31 16:15:36 +0800253find_package(Python3)
254
Jianliang Shen7e48bef2022-10-31 16:15:36 +0800255execute_process(
256 COMMAND
257 ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/kconfig/tfm_kconfig.py
Kevin Peng97ac6982022-11-24 17:10:00 +0800258 -k ${ROOT_KCONFIG} -o ${KCONFIG_OUTPUT_DIR}
259 --envs ${KCONFIG_ENV_VARS}
260 --config-files ${CONFIG_FILE_LIST}
261 ${MENUCONFIG_ARG}
Jianliang Shen7e48bef2022-10-31 16:15:36 +0800262 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
263 RESULT_VARIABLE ret
264)
265
266if(NOT ret EQUAL 0)
267 message(FATAL_ERROR "Kconfig tool failed!")
268endif()
269
Kevin Peng97ac6982022-11-24 17:10:00 +0800270# Component configs generated by tfm_kconfig.py
271set(PROJECT_CONFIG_HEADER_FILE ${KCONFIG_OUTPUT_DIR}/project_config.h CACHE FILEPATH "User defined header file for TF-M config")
272
Jianliang Shen7e48bef2022-10-31 16:15:36 +0800273# Load project cmake configs generated by tfm_kconfig.py
Kevin Peng97ac6982022-11-24 17:10:00 +0800274include(${KCONFIG_OUTPUT_DIR}/project_config.cmake)
Kevin Pengb9c99f02022-12-07 11:23:17 +0800275
276####################################################################################################
277
278# The Kconfig system does not cover all the config options for the time being.
279# So part of them still use the CMake config system.
280
281# Load regression configs overrided by platform
282if(EXISTS ${TARGET_PLATFORM_PATH}/reg_config_override.cmake)
283 include(${TARGET_PLATFORM_PATH}/reg_config_override.cmake)
284endif()
285
286# Load build type config, setting options not already set
287if(EXISTS ${CMAKE_SOURCE_DIR}/config/build_type/${CMAKE_BUILD_TYPE_LOWERCASE}.cmake)
288 include(${CMAKE_SOURCE_DIR}/config/build_type/${CMAKE_BUILD_TYPE_LOWERCASE}.cmake)
289endif()
290
Kevin Pengb9c99f02022-12-07 11:23:17 +0800291# Load defaults, setting options not already set
292include(config/config_base.cmake)
293
294# Set secure log configs
295# It also depends on regression test config.
296include(config/tfm_secure_log.cmake)