kconfig.cmake 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. include(ExternalProject)
  2. function(__kconfig_init)
  3. idf_build_get_property(idf_path IDF_PATH)
  4. idf_build_set_property(__ROOT_KCONFIG ${idf_path}/Kconfig)
  5. idf_build_set_property(__ROOT_SDKCONFIG_RENAME ${idf_path}/sdkconfig.rename)
  6. idf_build_set_property(__OUTPUT_SDKCONFIG 1)
  7. endfunction()
  8. #
  9. # Initialize Kconfig-related properties for components.
  10. # This function assumes that all basic properties of the components have been
  11. # set prior to calling it.
  12. #
  13. function(__kconfig_component_init component_target)
  14. __component_get_property(component_dir ${component_target} COMPONENT_DIR)
  15. file(GLOB kconfig "${component_dir}/Kconfig")
  16. list(SORT kconfig)
  17. __component_set_property(${component_target} KCONFIG "${kconfig}")
  18. file(GLOB kconfig "${component_dir}/Kconfig.projbuild")
  19. list(SORT kconfig)
  20. __component_set_property(${component_target} KCONFIG_PROJBUILD "${kconfig}")
  21. file(GLOB sdkconfig_rename "${component_dir}/sdkconfig.rename")
  22. file(GLOB sdkconfig_rename_target "${component_dir}/sdkconfig.rename.${IDF_TARGET}")
  23. list(APPEND sdkconfig_rename ${sdkconfig_rename_target})
  24. list(SORT sdkconfig_rename)
  25. __component_set_property(${component_target} SDKCONFIG_RENAME "${sdkconfig_rename}")
  26. endfunction()
  27. #
  28. # Add bootloader components Kconfig and Kconfig.projbuild files to BOOTLOADER_KCONFIG
  29. # and BOOTLOADER_KCONFIGS_PROJ properties respectively.
  30. #
  31. function(__kconfig_bootloader_component_add component_dir)
  32. idf_build_get_property(bootloader_kconfigs BOOTLOADER_KCONFIGS)
  33. idf_build_get_property(bootloader_kconfigs_proj BOOTLOADER_KCONFIGS_PROJ)
  34. file(GLOB kconfig "${component_dir}/Kconfig")
  35. list(SORT kconfig)
  36. if(EXISTS "${kconfig}" AND NOT IS_DIRECTORY "${kconfig}")
  37. list(APPEND bootloader_kconfigs "${kconfig}")
  38. endif()
  39. file(GLOB kconfig "${component_dir}/Kconfig.projbuild")
  40. list(SORT kconfig)
  41. if(EXISTS "${kconfig}" AND NOT IS_DIRECTORY "${kconfig}")
  42. list(APPEND bootloader_kconfigs_proj "${kconfig}")
  43. endif()
  44. idf_build_set_property(BOOTLOADER_KCONFIGS "${bootloader_kconfigs}")
  45. idf_build_set_property(BOOTLOADER_KCONFIGS_PROJ "${bootloader_kconfigs_proj}")
  46. endfunction()
  47. #
  48. # Find the initial IDF version used to generate the config.
  49. # This is needed to pass this variable back to confgen, so that the
  50. # value of CONFIG_IDF_INIT_VERSION option stays the same.
  51. #
  52. function(__get_init_config_version config version_out)
  53. set(${version_out} NOTFOUND PARENT_SCOPE)
  54. if(NOT EXISTS "${config}")
  55. return()
  56. endif()
  57. file(STRINGS "${config}" lines)
  58. foreach(line ${lines})
  59. string(STRIP "${line}" line)
  60. if(NOT "${line}" MATCHES "CONFIG_IDF_INIT_VERSION=\"([0-9]+\.[0-9]+\.[0-9]+)\"$")
  61. continue()
  62. endif()
  63. string(REGEX REPLACE "CONFIG_IDF_INIT_VERSION=\"([0-9]+\.[0-9]+\.[0-9]+)\"$" "\\1" version "${line}")
  64. set(${version_out} ${version} PARENT_SCOPE)
  65. return()
  66. endforeach()
  67. endfunction()
  68. #
  69. # Generate the config files and create config related targets and configure
  70. # dependencies.
  71. #
  72. function(__kconfig_generate_config sdkconfig sdkconfig_defaults)
  73. # List all Kconfig and Kconfig.projbuild in known components
  74. idf_build_get_property(component_targets __COMPONENT_TARGETS)
  75. idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
  76. foreach(component_target ${component_targets})
  77. if(component_target IN_LIST build_component_targets)
  78. __component_get_property(kconfig ${component_target} KCONFIG)
  79. __component_get_property(kconfig_projbuild ${component_target} KCONFIG_PROJBUILD)
  80. __component_get_property(sdkconfig_rename ${component_target} SDKCONFIG_RENAME)
  81. if(kconfig)
  82. list(APPEND kconfigs ${kconfig})
  83. endif()
  84. if(kconfig_projbuild)
  85. list(APPEND kconfig_projbuilds ${kconfig_projbuild})
  86. endif()
  87. if(sdkconfig_rename)
  88. list(APPEND sdkconfig_renames ${sdkconfig_rename})
  89. endif()
  90. endif()
  91. endforeach()
  92. __get_init_config_version(${sdkconfig} idf_init_version)
  93. if(NOT idf_init_version)
  94. set(idf_init_version $ENV{IDF_VERSION})
  95. endif()
  96. set(ENV{IDF_INIT_VERSION} ${idf_init_version})
  97. # Take into account bootloader components configuration files
  98. idf_build_get_property(bootloader_kconfigs BOOTLOADER_KCONFIGS)
  99. idf_build_get_property(bootloader_kconfigs_proj BOOTLOADER_KCONFIGS_PROJ)
  100. if(bootloader_kconfigs)
  101. list(APPEND kconfigs "${bootloader_kconfigs}")
  102. endif()
  103. if(bootloader_kconfigs_proj)
  104. list(APPEND kconfig_projbuilds "${bootloader_kconfigs_proj}")
  105. endif()
  106. # Store the list version of kconfigs and kconfig_projbuilds
  107. idf_build_set_property(KCONFIGS "${kconfigs}")
  108. idf_build_set_property(KCONFIG_PROJBUILDS "${kconfig_projbuilds}")
  109. idf_build_get_property(idf_target IDF_TARGET)
  110. idf_build_get_property(idf_toolchain IDF_TOOLCHAIN)
  111. idf_build_get_property(idf_path IDF_PATH)
  112. idf_build_get_property(idf_env_fpga __IDF_ENV_FPGA)
  113. # These are the paths for files which will contain the generated "source" lines for COMPONENT_KCONFIGS and
  114. # COMPONENT_KCONFIGS_PROJBUILD
  115. set(kconfigs_projbuild_path "${CMAKE_CURRENT_BINARY_DIR}/kconfigs_projbuild.in")
  116. set(kconfigs_path "${CMAKE_CURRENT_BINARY_DIR}/kconfigs.in")
  117. # Place config-related environment arguments into config.env file
  118. # to work around command line length limits for execute_process
  119. # on Windows & CMake < 3.11
  120. set(config_env_path "${CMAKE_CURRENT_BINARY_DIR}/config.env")
  121. configure_file("${idf_path}/tools/kconfig_new/config.env.in" ${config_env_path})
  122. idf_build_set_property(CONFIG_ENV_PATH ${config_env_path})
  123. if(sdkconfig_defaults)
  124. foreach(sdkconfig_default ${sdkconfig_defaults})
  125. list(APPEND defaults_arg --defaults "${sdkconfig_default}")
  126. if(EXISTS "${sdkconfig_default}.${idf_target}")
  127. list(APPEND defaults_arg --defaults "${sdkconfig_default}.${idf_target}")
  128. endif()
  129. endforeach()
  130. endif()
  131. idf_build_get_property(root_kconfig __ROOT_KCONFIG)
  132. idf_build_get_property(root_sdkconfig_rename __ROOT_SDKCONFIG_RENAME)
  133. idf_build_get_property(python PYTHON)
  134. set(prepare_kconfig_files_command
  135. ${python} ${idf_path}/tools/kconfig_new/prepare_kconfig_files.py
  136. --list-separator=semicolon
  137. --env-file ${config_env_path})
  138. set(kconfgen_basecommand
  139. ${python} -m kconfgen
  140. --list-separator=semicolon
  141. --kconfig ${root_kconfig}
  142. --sdkconfig-rename ${root_sdkconfig_rename}
  143. --config ${sdkconfig}
  144. ${defaults_arg}
  145. --env-file ${config_env_path})
  146. idf_build_get_property(build_dir BUILD_DIR)
  147. set(config_dir ${build_dir}/config)
  148. file(MAKE_DIRECTORY "${config_dir}")
  149. message(STATUS "Project sdkconfig file ${sdkconfig}")
  150. # Generate the config outputs
  151. set(sdkconfig_cmake ${config_dir}/sdkconfig.cmake)
  152. set(sdkconfig_header ${config_dir}/sdkconfig.h)
  153. set(sdkconfig_json ${config_dir}/sdkconfig.json)
  154. set(sdkconfig_json_menus ${config_dir}/kconfig_menus.json)
  155. idf_build_get_property(output_sdkconfig __OUTPUT_SDKCONFIG)
  156. if(output_sdkconfig)
  157. execute_process(
  158. COMMAND ${prepare_kconfig_files_command})
  159. execute_process(
  160. COMMAND ${kconfgen_basecommand}
  161. --output header ${sdkconfig_header}
  162. --output cmake ${sdkconfig_cmake}
  163. --output json ${sdkconfig_json}
  164. --output json_menus ${sdkconfig_json_menus}
  165. --output config ${sdkconfig}
  166. RESULT_VARIABLE config_result)
  167. else()
  168. execute_process(
  169. COMMAND ${prepare_kconfig_files_command})
  170. execute_process(
  171. COMMAND ${kconfgen_basecommand}
  172. --output header ${sdkconfig_header}
  173. --output cmake ${sdkconfig_cmake}
  174. --output json ${sdkconfig_json}
  175. --output json_menus ${sdkconfig_json_menus}
  176. RESULT_VARIABLE config_result)
  177. endif()
  178. if(config_result)
  179. message(FATAL_ERROR "Failed to run kconfgen (${kconfgen_basecommand}). Error ${config_result}")
  180. endif()
  181. # Add the generated config header to build specifications.
  182. idf_build_set_property(INCLUDE_DIRECTORIES ${config_dir} APPEND)
  183. # When sdkconfig file changes in the future, trigger a cmake run
  184. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${sdkconfig}")
  185. # Ditto if either of the generated files are missing/modified (this is a bit irritating as it means
  186. # you can't edit these manually without them being regenerated, but I don't know of a better way...)
  187. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${sdkconfig_header}")
  188. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${sdkconfig_cmake}")
  189. # Or if the config generation tool changes
  190. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${idf_path}/tools/kconfig_new/confgen.py")
  191. set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
  192. ADDITIONAL_CLEAN_FILES "${sdkconfig_header}" "${sdkconfig_cmake}")
  193. idf_build_set_property(SDKCONFIG_HEADER ${sdkconfig_header})
  194. idf_build_set_property(SDKCONFIG_JSON ${sdkconfig_json})
  195. idf_build_set_property(SDKCONFIG_CMAKE ${sdkconfig_cmake})
  196. idf_build_set_property(SDKCONFIG_JSON_MENUS ${sdkconfig_json_menus})
  197. idf_build_set_property(CONFIG_DIR ${config_dir})
  198. set(MENUCONFIG_CMD ${python} -m menuconfig)
  199. set(TERM_CHECK_CMD ${python} ${idf_path}/tools/check_term.py)
  200. # Generate the menuconfig target
  201. add_custom_target(menuconfig
  202. ${menuconfig_depends}
  203. # create any missing config file, with defaults if necessary
  204. COMMAND ${prepare_kconfig_files_command}
  205. COMMAND ${kconfgen_basecommand}
  206. --env "IDF_TARGET=${idf_target}"
  207. --env "IDF_TOOLCHAIN=${idf_toolchain}"
  208. --env "IDF_ENV_FPGA=${idf_env_fpga}"
  209. --env "IDF_INIT_VERSION=${idf_init_version}"
  210. --dont-write-deprecated
  211. --output config ${sdkconfig}
  212. COMMAND ${TERM_CHECK_CMD}
  213. COMMAND ${CMAKE_COMMAND} -E env
  214. "COMPONENT_KCONFIGS_SOURCE_FILE=${kconfigs_path}"
  215. "COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE=${kconfigs_projbuild_path}"
  216. "KCONFIG_CONFIG=${sdkconfig}"
  217. "IDF_TARGET=${idf_target}"
  218. "IDF_TOOLCHAIN=${idf_toolchain}"
  219. "IDF_ENV_FPGA=${idf_env_fpga}"
  220. "IDF_INIT_VERSION=${idf_init_version}"
  221. ${MENUCONFIG_CMD} ${root_kconfig}
  222. USES_TERMINAL
  223. # additional run of kconfgen esures that the deprecated options will be inserted into sdkconfig (for backward
  224. # compatibility)
  225. COMMAND ${kconfgen_basecommand}
  226. --env "IDF_TARGET=${idf_target}"
  227. --env "IDF_TOOLCHAIN=${idf_toolchain}"
  228. --env "IDF_ENV_FPGA=${idf_env_fpga}"
  229. --env "IDF_INIT_VERSION=${idf_init_version}"
  230. --output config ${sdkconfig}
  231. )
  232. # Custom target to run kconfserver from the build tool
  233. add_custom_target(confserver
  234. COMMAND ${prepare_kconfig_files_command}
  235. COMMAND ${python} -m kconfserver
  236. --env-file ${config_env_path}
  237. --kconfig ${IDF_PATH}/Kconfig
  238. --sdkconfig-rename ${root_sdkconfig_rename}
  239. --config ${sdkconfig}
  240. VERBATIM
  241. USES_TERMINAL)
  242. add_custom_target(save-defconfig
  243. COMMAND ${prepare_kconfig_files_command}
  244. COMMAND ${kconfgen_basecommand}
  245. --dont-write-deprecated
  246. --output savedefconfig ${CMAKE_SOURCE_DIR}/sdkconfig.defaults
  247. USES_TERMINAL
  248. )
  249. endfunction()