Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 1 | #------------------------------------------------------------------------------- |
Kevin Peng | a2b6802 | 2023-01-13 13:54:05 +0800 | [diff] [blame] | 2 | # Copyright (c) 2022-2023, Arm Limited. All rights reserved. |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 3 | # |
| 4 | # SPDX-License-Identifier: BSD-3-Clause |
| 5 | # |
| 6 | #------------------------------------------------------------------------------- |
| 7 | |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 8 | # 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 | |
| 16 | set(KCONFIG_OUTPUT_DIR ${CMAKE_BINARY_DIR}/kconfig) |
| 17 | |
| 18 | set(DOTCONFIG_FILE ${KCONFIG_OUTPUT_DIR}/.config) |
| 19 | set(ROOT_KCONFIG ${CMAKE_SOURCE_DIR}/Kconfig) |
| 20 | set(PLATFORM_KCONFIG ${TARGET_PLATFORM_PATH}/Kconfig) |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 21 | |
Kevin Peng | b9c99f0 | 2022-12-07 11:23:17 +0800 | [diff] [blame] | 22 | if(TFM_PROFILE) |
| 23 | # Selecting TF-M profiles is not supported yet. |
| 24 | message(FATAL_ERROR "Selecting TF-M profiles is not supported yet in Kconfig system!") |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 25 | endif() |
| 26 | |
Kevin Peng | 026b811 | 2023-01-13 11:24:38 +0800 | [diff] [blame^] | 27 | # This function parses the input ${cmake_file} to get normal CMake variables and their values in the |
| 28 | # format of "set(_VAR_ _VALUE_)". The format could be split into multiple lines. |
| 29 | # Note that CMake does not allow the "(" to be in a different line as "set" and no white spaces are |
| 30 | # recommanded between "set" and "(". So the function only covers format of "set(". |
| 31 | function(convert_normal_cmake_config_to_kconfig cmake_file out_var) |
| 32 | # Operate on a local var and write back to the "out_var" later. |
| 33 | set(local_var "") |
| 34 | |
| 35 | # Read out the strings of the file. Binary data in the file are ignored |
| 36 | file(STRINGS ${cmake_file} CONTENTS) |
| 37 | |
| 38 | # Exclude lines of comments (started with "#") |
| 39 | set(CONTENTS_WITHOUT_COMMENTS "") |
| 40 | |
| 41 | foreach(LINE ${CONTENTS}) |
| 42 | string(REGEX MATCH "^#.*" OUT_STRING ${LINE}) |
| 43 | if(NOT OUT_STRING) |
| 44 | string(APPEND CONTENTS_WITHOUT_COMMENTS "${LINE}\n") |
| 45 | endif() |
| 46 | 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) |
| 91 | endfunction() |
| 92 | |
| 93 | # Platform Kconfig file |
Kevin Peng | b9c99f0 | 2022-12-07 11:23:17 +0800 | [diff] [blame] | 94 | if(NOT EXISTS ${PLATFORM_KCONFIG}) |
| 95 | message(WARNING "The platform does not have Kconfig file! \ |
| 96 | The Kconfig system cannot get its configuration settings. |
| 97 | So it is not guaranteed that the Kconfig system works properly.") |
| 98 | |
Kevin Peng | 026b811 | 2023-01-13 11:24:38 +0800 | [diff] [blame^] | 99 | # Parse platform's preload.cmake and config.cmake to get config options. |
| 100 | set(PLATFORM_KCONFIG_OPTIONS "") |
| 101 | set(PLATFORM_KCONFIG ${KCONFIG_OUTPUT_DIR}/platform/Kconfig) |
| 102 | |
| 103 | convert_normal_cmake_config_to_kconfig(${TARGET_PLATFORM_PATH}/preload.cmake PLATFORM_KCONFIG_OPTIONS) |
| 104 | file(WRITE ${PLATFORM_KCONFIG} ${PLATFORM_KCONFIG_OPTIONS}) |
| 105 | |
Kevin Peng | b9c99f0 | 2022-12-07 11:23:17 +0800 | [diff] [blame] | 106 | if(EXISTS ${TARGET_PLATFORM_PATH}/config.cmake) |
| 107 | include(${TARGET_PLATFORM_PATH}/config.cmake) |
Kevin Peng | 026b811 | 2023-01-13 11:24:38 +0800 | [diff] [blame^] | 108 | convert_normal_cmake_config_to_kconfig(${TARGET_PLATFORM_PATH}/config.cmake PLATFORM_KCONFIG_OPTIONS) |
| 109 | file(APPEND ${PLATFORM_KCONFIG} ${PLATFORM_KCONFIG_OPTIONS}) |
Kevin Peng | b9c99f0 | 2022-12-07 11:23:17 +0800 | [diff] [blame] | 110 | endif() |
| 111 | endif() |
Kevin Peng | 026b811 | 2023-01-13 11:24:38 +0800 | [diff] [blame^] | 112 | get_filename_component(PLATFORM_KCONFIG_PATH ${PLATFORM_KCONFIG} DIRECTORY) |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 113 | |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 114 | # User customized config file |
| 115 | if(DEFINED KCONFIG_CONFIG_FILE AND NOT EXISTS ${KCONFIG_CONFIG_FILE}) |
| 116 | message(FATAL_ERROR "No such file: ${KCONFIG_CONFIG_FILE}") |
| 117 | endif() |
| 118 | |
| 119 | # Note the order of CONFIG_FILE_LIST, as the first loaded configs would be |
| 120 | # overridden by later ones. |
| 121 | list(APPEND CONFIG_FILE_LIST |
| 122 | ${KCONFIG_CONFIG_FILE}) |
| 123 | |
| 124 | # Set up ENV variables for the tfm_kconfig.py which are then consumed by Kconfig files. |
Jianliang Shen | c4e719b | 2023-03-02 14:37:54 +0800 | [diff] [blame] | 125 | set(KCONFIG_ENV_VARS "TFM_SOURCE_DIR=${CMAKE_SOURCE_DIR} \ |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 126 | TFM_VERSION=${TFM_VERSION} \ |
Kevin Peng | 026b811 | 2023-01-13 11:24:38 +0800 | [diff] [blame^] | 127 | PLATFORM_PATH=${PLATFORM_KCONFIG_PATH} \ |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 128 | CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") |
| 129 | |
| 130 | if(MENUCONFIG) |
| 131 | # Note: Currently, only GUI menuconfig can be supported with CMake integration |
| 132 | set(MENUCONFIG_ARG "-u=gui") |
| 133 | else() |
| 134 | set(MENUCONFIG_ARG "") |
| 135 | endif() |
| 136 | |
Jianliang Shen | 7c67ab1 | 2023-03-14 14:41:34 +0800 | [diff] [blame] | 137 | if(DEFINED PROJECT_CONFIG_HEADER_FILE) |
| 138 | get_property(HELP_STRING CACHE PROJECT_CONFIG_HEADER_FILE PROPERTY HELPSTRING) |
| 139 | |
| 140 | # It is not supported to set PROJECT_CONFIG_HEADER_FILE while using Kconfig, either from |
| 141 | # command line or CMake files. It should be set to the file generated the Kconfig system. |
| 142 | # As this file set it itself, if the user re-run the CMake config command, the |
| 143 | # PROJECT_CONFIG_HEADER_FILE will be already defined set. |
| 144 | # So the existence of the ${DOTCONFIG_FILE} is used to indicate if it is a re-configuration. |
| 145 | if("${HELP_STRING}" MATCHES "variable specified on the command line" OR NOT EXISTS ${DOTCONFIG_FILE}) |
| 146 | message(FATAL_ERROR "It is NOT supported to manually set PROJECT_CONFIG_HEADER_FILE while using Kconfig.") |
| 147 | endif() |
| 148 | endif() |
| 149 | |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 150 | find_package(Python3) |
| 151 | |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 152 | execute_process( |
| 153 | COMMAND |
| 154 | ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/kconfig/tfm_kconfig.py |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 155 | -k ${ROOT_KCONFIG} -o ${KCONFIG_OUTPUT_DIR} |
| 156 | --envs ${KCONFIG_ENV_VARS} |
| 157 | --config-files ${CONFIG_FILE_LIST} |
| 158 | ${MENUCONFIG_ARG} |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 159 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} |
| 160 | RESULT_VARIABLE ret |
| 161 | ) |
| 162 | |
| 163 | if(NOT ret EQUAL 0) |
| 164 | message(FATAL_ERROR "Kconfig tool failed!") |
| 165 | endif() |
| 166 | |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 167 | # Component configs generated by tfm_kconfig.py |
| 168 | set(PROJECT_CONFIG_HEADER_FILE ${KCONFIG_OUTPUT_DIR}/project_config.h CACHE FILEPATH "User defined header file for TF-M config") |
| 169 | |
Jianliang Shen | 7e48bef | 2022-10-31 16:15:36 +0800 | [diff] [blame] | 170 | # Load project cmake configs generated by tfm_kconfig.py |
Kevin Peng | 97ac698 | 2022-11-24 17:10:00 +0800 | [diff] [blame] | 171 | include(${KCONFIG_OUTPUT_DIR}/project_config.cmake) |
Kevin Peng | b9c99f0 | 2022-12-07 11:23:17 +0800 | [diff] [blame] | 172 | |
| 173 | #################################################################################################### |
| 174 | |
| 175 | # The Kconfig system does not cover all the config options for the time being. |
| 176 | # So part of them still use the CMake config system. |
| 177 | |
| 178 | # Load regression configs overrided by platform |
| 179 | if(EXISTS ${TARGET_PLATFORM_PATH}/reg_config_override.cmake) |
| 180 | include(${TARGET_PLATFORM_PATH}/reg_config_override.cmake) |
| 181 | endif() |
| 182 | |
| 183 | # Load build type config, setting options not already set |
| 184 | if(EXISTS ${CMAKE_SOURCE_DIR}/config/build_type/${CMAKE_BUILD_TYPE_LOWERCASE}.cmake) |
| 185 | include(${CMAKE_SOURCE_DIR}/config/build_type/${CMAKE_BUILD_TYPE_LOWERCASE}.cmake) |
| 186 | endif() |
| 187 | |
| 188 | # Load TF-M model specific default config |
| 189 | # Load IPC backend config if isolation level is explicitly specified to 2/3 or IPC backend is |
| 190 | # selected via build command line. Otherwise, load SFN backend config by default. |
| 191 | # If a pair of invalid settings are passed via command line, it will be captured later via config |
| 192 | # check. |
| 193 | # Also select IPC model by default for multi-core platform unless it has already selected SFN model |
| 194 | if((DEFINED TFM_ISOLATION_LEVEL AND TFM_ISOLATION_LEVEL GREATER 1) OR |
| 195 | CONFIG_TFM_SPM_BACKEND STREQUAL "IPC" OR |
| 196 | TFM_MULTI_CORE_TOPOLOGY) |
| 197 | include(config/tfm_ipc_config_default.cmake) |
| 198 | else() |
| 199 | #The default backend is SFN |
| 200 | include(config/tfm_sfn_config_default.cmake) |
| 201 | endif() |
| 202 | |
| 203 | # Load bl1 config |
| 204 | if(BL1 AND PLATFORM_DEFAULT_BL1) |
| 205 | include(${CMAKE_SOURCE_DIR}/bl1/config/bl1_config_default.cmake) |
| 206 | endif() |
| 207 | |
| 208 | # Load MCUboot specific default.cmake |
| 209 | if(NOT DEFINED BL2 OR BL2) |
| 210 | include(${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/mcuboot_default_config.cmake) |
| 211 | endif() |
| 212 | |
| 213 | # Include FWU partition configs. |
| 214 | include(config/tfm_fwu_config.cmake) |
| 215 | |
| 216 | # Include coprocessor configs |
| 217 | include(config/cp_config_default.cmake) |
| 218 | |
| 219 | # Load defaults, setting options not already set |
| 220 | include(config/config_base.cmake) |
| 221 | |
| 222 | # Set secure log configs |
| 223 | # It also depends on regression test config. |
| 224 | include(config/tfm_secure_log.cmake) |