build.cmake 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. # idf_build_get_property
  2. #
  3. # @brief Retrieve the value of the specified property related to ESP-IDF build.
  4. #
  5. # @param[out] var the variable to store the value in
  6. # @param[in] property the property to get the value of
  7. #
  8. # @param[in, optional] GENERATOR_EXPRESSION (option) retrieve the generator expression for the property
  9. # instead of actual value
  10. function(idf_build_get_property var property)
  11. cmake_parse_arguments(_ "GENERATOR_EXPRESSION" "" "" ${ARGN})
  12. if(__GENERATOR_EXPRESSION)
  13. set(val "$<TARGET_PROPERTY:__idf_build_target,${property}>")
  14. else()
  15. get_property(val TARGET __idf_build_target PROPERTY ${property})
  16. endif()
  17. set(${var} ${val} PARENT_SCOPE)
  18. endfunction()
  19. # idf_build_set_property
  20. #
  21. # @brief Set the value of the specified property related to ESP-IDF build. The property is
  22. # also added to the internal list of build properties if it isn't there already.
  23. #
  24. # @param[in] property the property to set the value of
  25. # @param[out] value value of the property
  26. #
  27. # @param[in, optional] APPEND (option) append the value to the current value of the
  28. # property instead of replacing it
  29. function(idf_build_set_property property value)
  30. cmake_parse_arguments(_ "APPEND" "" "" ${ARGN})
  31. # Fixup property value, e.g. for compatibility. (Overwrites variable 'value'.)
  32. __build_fixup_property("${property}" "${value}" value)
  33. if(__APPEND)
  34. set_property(TARGET __idf_build_target APPEND PROPERTY ${property} ${value})
  35. else()
  36. set_property(TARGET __idf_build_target PROPERTY ${property} ${value})
  37. endif()
  38. # Keep track of set build properties so that they can be exported to a file that
  39. # will be included in early expansion script.
  40. idf_build_get_property(build_properties __BUILD_PROPERTIES)
  41. if(NOT property IN_LIST build_properties)
  42. idf_build_set_property(__BUILD_PROPERTIES "${property}" APPEND)
  43. endif()
  44. endfunction()
  45. # idf_build_unset_property
  46. #
  47. # @brief Unset the value of the specified property related to ESP-IDF build. Equivalent
  48. # to setting the property to an empty string; though it also removes the property
  49. # from the internal list of build properties.
  50. #
  51. # @param[in] property the property to unset the value of
  52. function(idf_build_unset_property property)
  53. idf_build_set_property(${property} "") # set to an empty value
  54. idf_build_get_property(build_properties __BUILD_PROPERTIES) # remove from tracked properties
  55. list(REMOVE_ITEM build_properties ${property})
  56. idf_build_set_property(__BUILD_PROPERTIES "${build_properties}")
  57. endfunction()
  58. #
  59. # Retrieve the IDF_PATH repository's version, either using a version
  60. # file or Git revision. Sets the IDF_VER build property.
  61. #
  62. function(__build_get_idf_git_revision)
  63. idf_build_get_property(idf_path IDF_PATH)
  64. git_describe(idf_ver_git "${idf_path}" "--match=v*.*")
  65. if(EXISTS "${idf_path}/version.txt")
  66. file(STRINGS "${idf_path}/version.txt" idf_ver_t)
  67. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${idf_path}/version.txt")
  68. else()
  69. set(idf_ver_t ${idf_ver_git})
  70. endif()
  71. # cut IDF_VER to required 32 characters.
  72. string(SUBSTRING "${idf_ver_t}" 0 31 idf_ver)
  73. idf_build_set_property(COMPILE_DEFINITIONS "IDF_VER=\"${idf_ver}\"" APPEND)
  74. git_submodule_check("${idf_path}")
  75. idf_build_set_property(IDF_VER ${idf_ver})
  76. endfunction()
  77. #
  78. # Sets initial list of build specifications (compile options, definitions, etc.) common across
  79. # all library targets built under the ESP-IDF build system. These build specifications are added
  80. # privately using the directory-level CMake commands (add_compile_options, include_directories, etc.)
  81. # during component registration.
  82. #
  83. function(__build_set_default_build_specifications)
  84. unset(compile_definitions)
  85. unset(compile_options)
  86. unset(c_compile_options)
  87. unset(cxx_compile_options)
  88. list(APPEND compile_definitions "_GLIBCXX_USE_POSIX_SEMAPHORE" # These two lines enable libstd++ to use
  89. "_GLIBCXX_HAVE_POSIX_SEMAPHORE" # posix-semaphores from components/pthread
  90. "_GNU_SOURCE")
  91. list(APPEND compile_options "-ffunction-sections"
  92. "-fdata-sections"
  93. # warning-related flags
  94. "-Wall"
  95. "-Werror=all"
  96. "-Wno-error=unused-function"
  97. "-Wno-error=unused-variable"
  98. "-Wno-error=unused-but-set-variable"
  99. "-Wno-error=deprecated-declarations"
  100. "-Wextra"
  101. "-Wno-unused-parameter"
  102. "-Wno-sign-compare"
  103. # ignore multiple enum conversion warnings since gcc 11
  104. # TODO: IDF-5163
  105. "-Wno-enum-conversion"
  106. # Default is dwarf-5 since GCC 11, fallback to dwarf-4 because of binary size
  107. # TODO: IDF-5160
  108. "-gdwarf-4"
  109. # always generate debug symbols (even in release mode, these don't
  110. # go into the final binary so have no impact on size
  111. "-ggdb")
  112. idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
  113. idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
  114. idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
  115. idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)
  116. endfunction()
  117. function(__build_set_lang_version)
  118. if(NOT IDF_TARGET STREQUAL "linux")
  119. # Building for chip targets: we use a known version of the toolchain.
  120. # Use latest supported versions.
  121. # Please update docs/en/api-guides/c.rst, docs/en/api-guides/cplusplus.rst and
  122. # tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this.
  123. set(c_std gnu17)
  124. set(cxx_std gnu++2b)
  125. else()
  126. enable_language(C CXX)
  127. # Building for Linux target, fall back to an older version of the standard
  128. # if the preferred one is not supported by the compiler.
  129. set(preferred_c_versions gnu17 gnu11 gnu99)
  130. set(ver_found FALSE)
  131. foreach(c_version ${preferred_c_versions})
  132. check_c_compiler_flag("-std=${c_version}" ver_${c_version}_supported)
  133. if(ver_${c_version}_supported)
  134. set(c_std ${c_version})
  135. set(ver_found TRUE)
  136. break()
  137. endif()
  138. endforeach()
  139. if(NOT ver_found)
  140. message(FATAL_ERROR "Failed to set C language standard to one of the supported versions: "
  141. "${preferred_c_versions}. Please upgrade the host compiler.")
  142. endif()
  143. set(preferred_cxx_versions gnu++2b gnu++20 gnu++2a gnu++17 gnu++14)
  144. set(ver_found FALSE)
  145. foreach(cxx_version ${preferred_cxx_versions})
  146. check_cxx_compiler_flag("-std=${cxx_version}" ver_${cxx_version}_supported)
  147. if(ver_${cxx_version}_supported)
  148. set(cxx_std ${cxx_version})
  149. set(ver_found TRUE)
  150. break()
  151. endif()
  152. endforeach()
  153. if(NOT ver_found)
  154. message(FATAL_ERROR "Failed to set C++ language standard to one of the supported versions: "
  155. "${preferred_cxx_versions}. Please upgrade the host compiler.")
  156. endif()
  157. endif()
  158. idf_build_set_property(C_COMPILE_OPTIONS "-std=${c_std}" APPEND)
  159. idf_build_set_property(CXX_COMPILE_OPTIONS "-std=${cxx_std}" APPEND)
  160. endfunction()
  161. #
  162. # Perform any fixes or adjustments to the values stored in IDF build properties.
  163. # This function only gets called from 'idf_build_set_property' and doesn't affect
  164. # the properties set directly via 'set_property'.
  165. #
  166. function(__build_fixup_property property value out_var)
  167. # Fixup COMPILE_DEFINITIONS property to support -D prefix, which had to be used in IDF v4.x projects.
  168. if(property STREQUAL "COMPILE_DEFINITIONS" AND NOT "${value}" STREQUAL "")
  169. string(REGEX REPLACE "^-D" "" stripped_value "${value}")
  170. set("${out_var}" "${stripped_value}" PARENT_SCOPE)
  171. endif()
  172. endfunction()
  173. #
  174. # Initialize the build. This gets called upon inclusion of idf.cmake to set internal
  175. # properties used for the processing phase of the build.
  176. #
  177. function(__build_init idf_path)
  178. set(target ${IDF_TARGET})
  179. # Create the build target, to which the ESP-IDF build properties, dependencies are attached to.
  180. # Must be global so as to be accessible from any subdirectory in custom projects.
  181. add_library(__idf_build_target STATIC IMPORTED GLOBAL)
  182. # Set the Python path (which may be passed in via -DPYTHON=) and store in a build property
  183. set_default(PYTHON "python")
  184. file(TO_CMAKE_PATH ${PYTHON} PYTHON)
  185. idf_build_set_property(PYTHON ${PYTHON})
  186. idf_build_set_property(IDF_PATH ${idf_path})
  187. idf_build_set_property(__PREFIX idf)
  188. idf_build_set_property(__CHECK_PYTHON 1)
  189. idf_build_set_property(IDF_COMPONENT_MANAGER 0)
  190. __build_set_default_build_specifications()
  191. __build_set_lang_version()
  192. # Add internal components to the build
  193. idf_build_get_property(idf_path IDF_PATH)
  194. idf_build_get_property(prefix __PREFIX)
  195. file(GLOB component_dirs ${idf_path}/components/*)
  196. list(SORT component_dirs)
  197. foreach(component_dir ${component_dirs})
  198. # A potential component must be a directory
  199. if(IS_DIRECTORY ${component_dir})
  200. __component_dir_quick_check(is_component ${component_dir})
  201. if(is_component)
  202. __component_add(${component_dir} ${prefix})
  203. endif()
  204. endif()
  205. endforeach()
  206. if("${target}" STREQUAL "linux")
  207. set(requires_common freertos esp_hw_support heap log soc hal esp_rom esp_common esp_system linux)
  208. idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
  209. else()
  210. # Set components required by all other components in the build
  211. #
  212. # - esp_hw_support is here for backward compatibility
  213. set(requires_common cxx newlib freertos esp_hw_support heap log soc hal esp_rom esp_common esp_system)
  214. idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
  215. endif()
  216. __build_get_idf_git_revision()
  217. __kconfig_init()
  218. endfunction()
  219. # idf_build_component
  220. #
  221. # @brief Present a directory that contains a component to the build system.
  222. # Relative paths are converted to absolute paths with respect to current directory.
  223. # All calls to this command must be performed before idf_build_process.
  224. #
  225. # @note This command does not guarantee that the component will be processed
  226. # during build (see the COMPONENTS argument description for command idf_build_process)
  227. #
  228. # @param[in] component_dir directory of the component
  229. function(idf_build_component component_dir)
  230. idf_build_get_property(prefix __PREFIX)
  231. __component_add(${component_dir} ${prefix} 0)
  232. endfunction()
  233. #
  234. # Resolve the requirement component to the component target created for that component.
  235. #
  236. function(__build_resolve_and_add_req var component_target req type)
  237. __component_get_target(_component_target ${req})
  238. __component_get_property(_component_registered ${component_target} __COMPONENT_REGISTERED)
  239. if(NOT _component_target OR NOT _component_registered)
  240. message(FATAL_ERROR "Failed to resolve component '${req}'.")
  241. endif()
  242. __component_set_property(${component_target} ${type} ${_component_target} APPEND)
  243. set(${var} ${_component_target} PARENT_SCOPE)
  244. endfunction()
  245. #
  246. # Build a list of components (in the form of component targets) to be added to the build
  247. # based on public and private requirements. This list is saved in an internal property,
  248. # __BUILD_COMPONENT_TARGETS.
  249. #
  250. function(__build_expand_requirements component_target)
  251. # Since there are circular dependencies, make sure that we do not infinitely
  252. # expand requirements for each component.
  253. idf_build_get_property(component_targets_seen __COMPONENT_TARGETS_SEEN)
  254. __component_get_property(component_registered ${component_target} __COMPONENT_REGISTERED)
  255. if(component_target IN_LIST component_targets_seen OR NOT component_registered)
  256. return()
  257. endif()
  258. idf_build_set_property(__COMPONENT_TARGETS_SEEN ${component_target} APPEND)
  259. get_property(reqs TARGET ${component_target} PROPERTY REQUIRES)
  260. get_property(priv_reqs TARGET ${component_target} PROPERTY PRIV_REQUIRES)
  261. __component_get_property(component_name ${component_target} COMPONENT_NAME)
  262. __component_get_property(component_alias ${component_target} COMPONENT_ALIAS)
  263. idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON)
  264. list(APPEND reqs ${common_reqs})
  265. if(reqs)
  266. list(REMOVE_DUPLICATES reqs)
  267. list(REMOVE_ITEM reqs ${component_alias} ${component_name})
  268. endif()
  269. foreach(req ${reqs})
  270. depgraph_add_edge(${component_name} ${req} REQUIRES)
  271. __build_resolve_and_add_req(_component_target ${component_target} ${req} __REQUIRES)
  272. __build_expand_requirements(${_component_target})
  273. endforeach()
  274. foreach(req ${priv_reqs})
  275. depgraph_add_edge(${component_name} ${req} PRIV_REQUIRES)
  276. __build_resolve_and_add_req(_component_target ${component_target} ${req} __PRIV_REQUIRES)
  277. __build_expand_requirements(${_component_target})
  278. endforeach()
  279. idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
  280. if(NOT component_target IN_LIST build_component_targets)
  281. idf_build_set_property(__BUILD_COMPONENT_TARGETS ${component_target} APPEND)
  282. __component_get_property(component_lib ${component_target} COMPONENT_LIB)
  283. idf_build_set_property(__BUILD_COMPONENTS ${component_lib} APPEND)
  284. idf_build_get_property(prefix __PREFIX)
  285. __component_get_property(component_prefix ${component_target} __PREFIX)
  286. __component_get_property(component_alias ${component_target} COMPONENT_ALIAS)
  287. idf_build_set_property(BUILD_COMPONENT_ALIASES ${component_alias} APPEND)
  288. # Only put in the prefix in the name if it is not the default one
  289. if(component_prefix STREQUAL prefix)
  290. __component_get_property(component_name ${component_target} COMPONENT_NAME)
  291. idf_build_set_property(BUILD_COMPONENTS ${component_name} APPEND)
  292. else()
  293. idf_build_set_property(BUILD_COMPONENTS ${component_alias} APPEND)
  294. endif()
  295. endif()
  296. endfunction()
  297. #
  298. # Write a CMake file containing set build properties, owing to the fact that an internal
  299. # list of properties is maintained in idf_build_set_property() call. This is used to convert
  300. # those set properties to variables in the scope the output file is included in.
  301. #
  302. function(__build_write_properties output_file)
  303. idf_build_get_property(build_properties __BUILD_PROPERTIES)
  304. foreach(property ${build_properties})
  305. idf_build_get_property(val ${property})
  306. set(build_properties_text "${build_properties_text}\nset(${property} \"${val}\")")
  307. endforeach()
  308. file(WRITE ${output_file} "${build_properties_text}")
  309. endfunction()
  310. #
  311. # Check if the Python interpreter used for the build has all the required modules.
  312. #
  313. function(__build_check_python)
  314. idf_build_get_property(check __CHECK_PYTHON)
  315. if(check)
  316. idf_build_get_property(python PYTHON)
  317. idf_build_get_property(idf_path IDF_PATH)
  318. message(STATUS "Checking Python dependencies...")
  319. execute_process(COMMAND "${python}" "${idf_path}/tools/idf_tools.py" "check-python-dependencies"
  320. RESULT_VARIABLE result)
  321. if(result EQUAL 1)
  322. # check_python_dependencies returns error code 1 on failure
  323. message(FATAL_ERROR "Some Python dependencies must be installed. Check above message for details.")
  324. elseif(NOT result EQUAL 0)
  325. # means check_python_dependencies.py failed to run at all, result should be an error message
  326. message(FATAL_ERROR "Failed to run Python dependency check. Python: ${python}, Error: ${result}")
  327. endif()
  328. endif()
  329. endfunction()
  330. #
  331. # Prepare for component processing expanding each component's project include
  332. #
  333. macro(__build_process_project_includes)
  334. # Include the sdkconfig cmake file, since the following operations require
  335. # knowledge of config values.
  336. idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
  337. include(${sdkconfig_cmake})
  338. # Make each build property available as a read-only variable
  339. idf_build_get_property(build_properties __BUILD_PROPERTIES)
  340. foreach(build_property ${build_properties})
  341. idf_build_get_property(val ${build_property})
  342. set(${build_property} "${val}")
  343. endforeach()
  344. idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
  345. # Include each component's project_include.cmake
  346. foreach(component_target ${build_component_targets})
  347. __component_get_property(dir ${component_target} COMPONENT_DIR)
  348. __component_get_property(_name ${component_target} COMPONENT_NAME)
  349. set(COMPONENT_NAME ${_name})
  350. set(COMPONENT_DIR ${dir})
  351. set(COMPONENT_PATH ${dir}) # this is deprecated, users are encouraged to use COMPONENT_DIR;
  352. # retained for compatibility
  353. if(EXISTS ${COMPONENT_DIR}/project_include.cmake)
  354. include(${COMPONENT_DIR}/project_include.cmake)
  355. endif()
  356. endforeach()
  357. endmacro()
  358. #
  359. # Utility macro for setting default property value if argument is not specified
  360. # for idf_build_process().
  361. #
  362. macro(__build_set_default var default)
  363. set(_var __${var})
  364. if(NOT "${${_var}}" STREQUAL "")
  365. idf_build_set_property(${var} "${${_var}}")
  366. else()
  367. idf_build_set_property(${var} "${default}")
  368. endif()
  369. unset(_var)
  370. endmacro()
  371. #
  372. # Import configs as build instance properties so that they are accessible
  373. # using idf_build_get_config(). Config has to have been generated before calling
  374. # this command.
  375. #
  376. function(__build_import_configs)
  377. # Include the sdkconfig cmake file, since the following operations require
  378. # knowledge of config values.
  379. idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
  380. include(${sdkconfig_cmake})
  381. idf_build_set_property(__CONFIG_VARIABLES "${CONFIGS_LIST}")
  382. foreach(config ${CONFIGS_LIST})
  383. set_property(TARGET __idf_build_target PROPERTY ${config} "${${config}}")
  384. endforeach()
  385. endfunction()
  386. # idf_build_process
  387. #
  388. # @brief Main processing step for ESP-IDF build: config generation, adding components to the build,
  389. # dependency resolution, etc.
  390. #
  391. # @param[in] target ESP-IDF target
  392. #
  393. # @param[in, optional] PROJECT_DIR (single value) directory of the main project the buildsystem
  394. # is processed for; defaults to CMAKE_SOURCE_DIR
  395. # @param[in, optional] PROJECT_VER (single value) version string of the main project; defaults
  396. # to 1
  397. # @param[in, optional] PROJECT_NAME (single value) main project name, defaults to CMAKE_PROJECT_NAME
  398. # @param[in, optional] SDKCONFIG (single value) sdkconfig output path, defaults to PROJECT_DIR/sdkconfig
  399. # if PROJECT_DIR is set and CMAKE_SOURCE_DIR/sdkconfig if not
  400. # @param[in, optional] SDKCONFIG_DEFAULTS (single value) config defaults file to use for the build; defaults
  401. # to none (Kconfig defaults or previously generated config are used)
  402. # @param[in, optional] BUILD_DIR (single value) directory for build artifacts; defautls to CMAKE_BINARY_DIR
  403. # @param[in, optional] COMPONENTS (multivalue) select components to process among the components
  404. # known by the build system
  405. # (added via `idf_build_component`). This argument is used to trim the build.
  406. # Other components are automatically added if they are required
  407. # in the dependency chain, i.e.
  408. # the public and private requirements of the components in this list
  409. # are automatically added, and in
  410. # turn the public and private requirements of those requirements,
  411. # so on and so forth. If not specified, all components known to the build system
  412. # are processed.
  413. macro(idf_build_process target)
  414. set(options)
  415. set(single_value PROJECT_DIR PROJECT_VER PROJECT_NAME BUILD_DIR SDKCONFIG)
  416. set(multi_value COMPONENTS SDKCONFIG_DEFAULTS)
  417. cmake_parse_arguments(_ "${options}" "${single_value}" "${multi_value}" ${ARGN})
  418. idf_build_set_property(BOOTLOADER_BUILD "${BOOTLOADER_BUILD}")
  419. idf_build_set_property(IDF_TOOLCHAIN "${IDF_TOOLCHAIN}")
  420. # Check build target is specified. Since this target corresponds to a component
  421. # name, the target component is automatically added to the list of common component
  422. # requirements.
  423. if(target STREQUAL "")
  424. message(FATAL_ERROR "Build target not specified.")
  425. endif()
  426. idf_build_set_property(IDF_TARGET ${target})
  427. if("${target}" STREQUAL "esp32" OR "${target}" STREQUAL "esp32s2" OR "${target}" STREQUAL "esp32s3")
  428. idf_build_set_property(IDF_TARGET_ARCH "xtensa")
  429. elseif("${target}" STREQUAL "linux")
  430. # No arch specified for linux host builds at the moment
  431. idf_build_set_property(IDF_TARGET_ARCH "")
  432. else()
  433. idf_build_set_property(IDF_TARGET_ARCH "riscv")
  434. endif()
  435. __build_set_default(PROJECT_DIR ${CMAKE_SOURCE_DIR})
  436. __build_set_default(PROJECT_NAME ${CMAKE_PROJECT_NAME})
  437. __build_set_default(PROJECT_VER 1)
  438. __build_set_default(BUILD_DIR ${CMAKE_BINARY_DIR})
  439. idf_build_get_property(project_dir PROJECT_DIR)
  440. __build_set_default(SDKCONFIG "${project_dir}/sdkconfig")
  441. __build_set_default(SDKCONFIG_DEFAULTS "")
  442. # Check for required Python modules
  443. __build_check_python()
  444. idf_build_get_property(target IDF_TARGET)
  445. idf_build_get_property(arch IDF_TARGET_ARCH)
  446. if(NOT "${target}" STREQUAL "linux")
  447. idf_build_set_property(__COMPONENT_REQUIRES_COMMON ${arch} APPEND)
  448. endif()
  449. # Call for component manager to download dependencies for all components
  450. idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER)
  451. if(idf_component_manager EQUAL 1)
  452. idf_build_get_property(build_dir BUILD_DIR)
  453. set(managed_components_list_file ${build_dir}/managed_components_list.temp.cmake)
  454. set(local_components_list_file ${build_dir}/local_components_list.temp.yml)
  455. set(__contents "components:\n")
  456. foreach(__component_name ${components})
  457. idf_component_get_property(__component_dir ${__component_name} COMPONENT_DIR)
  458. set(__contents "${__contents} - name: \"${__component_name}\"\n path: \"${__component_dir}\"\n")
  459. endforeach()
  460. file(WRITE ${local_components_list_file} "${__contents}")
  461. # Call for the component manager to prepare remote dependencies
  462. idf_build_get_property(python PYTHON)
  463. idf_build_get_property(component_manager_interface_version __COMPONENT_MANAGER_INTERFACE_VERSION)
  464. idf_build_get_property(dependencies_lock_file DEPENDENCIES_LOCK)
  465. execute_process(COMMAND ${python}
  466. "-m"
  467. "idf_component_manager.prepare_components"
  468. "--project_dir=${project_dir}"
  469. "--lock_path=${dependencies_lock_file}"
  470. "--interface_version=${component_manager_interface_version}"
  471. "prepare_dependencies"
  472. "--local_components_list_file=${local_components_list_file}"
  473. "--managed_components_list_file=${managed_components_list_file}"
  474. RESULT_VARIABLE result
  475. ERROR_VARIABLE error)
  476. if(NOT result EQUAL 0)
  477. message(FATAL_ERROR "${error}")
  478. endif()
  479. include(${managed_components_list_file})
  480. # Add managed components to list of all components
  481. # `managed_components` contains the list of components installed by the component manager
  482. # It is defined in the temporary managed_components_list_file file
  483. set(__COMPONENTS "${__COMPONENTS};${managed_components}")
  484. file(REMOVE ${managed_components_list_file})
  485. file(REMOVE ${local_components_list_file})
  486. else()
  487. message(VERBOSE "IDF Component manager was explicitly disabled by setting IDF_COMPONENT_MANAGER=0")
  488. idf_build_get_property(__component_targets __COMPONENT_TARGETS)
  489. set(__components_with_manifests "")
  490. foreach(__component_target ${__component_targets})
  491. __component_get_property(__component_dir ${__component_target} COMPONENT_DIR)
  492. if(EXISTS "${__component_dir}/idf_component.yml")
  493. set(__components_with_manifests "${__components_with_manifests}\t${__component_dir}\n")
  494. endif()
  495. endforeach()
  496. if(NOT "${__components_with_manifests}" STREQUAL "")
  497. message(WARNING "\"idf_component.yml\" file was found for components:\n${__components_with_manifests}"
  498. "However, the component manager is not enabled.")
  499. endif()
  500. endif()
  501. # Perform early expansion of component CMakeLists.txt in CMake scripting mode.
  502. # It is here we retrieve the public and private requirements of each component.
  503. # It is also here we add the common component requirements to each component's
  504. # own requirements.
  505. __component_get_requirements()
  506. idf_build_get_property(component_targets __COMPONENT_TARGETS)
  507. # Finally, do component expansion. In this case it simply means getting a final list
  508. # of build component targets given the requirements set by each component.
  509. # Check if we need to trim the components first, and build initial components list
  510. # from that.
  511. if(__COMPONENTS)
  512. unset(component_targets)
  513. foreach(component ${__COMPONENTS})
  514. __component_get_target(component_target ${component})
  515. if(NOT component_target)
  516. message(FATAL_ERROR "Failed to resolve component '${component}'.")
  517. endif()
  518. list(APPEND component_targets ${component_target})
  519. endforeach()
  520. endif()
  521. foreach(component_target ${component_targets})
  522. __build_expand_requirements(${component_target})
  523. endforeach()
  524. idf_build_unset_property(__COMPONENT_TARGETS_SEEN)
  525. # Get a list of common component requirements in component targets form (previously
  526. # we just have a list of component names)
  527. idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON)
  528. foreach(common_req ${common_reqs})
  529. __component_get_target(component_target ${common_req})
  530. __component_get_property(lib ${component_target} COMPONENT_LIB)
  531. idf_build_set_property(___COMPONENT_REQUIRES_COMMON ${lib} APPEND)
  532. endforeach()
  533. # Generate config values in different formats
  534. idf_build_get_property(sdkconfig SDKCONFIG)
  535. idf_build_get_property(sdkconfig_defaults SDKCONFIG_DEFAULTS)
  536. __kconfig_generate_config("${sdkconfig}" "${sdkconfig_defaults}")
  537. __build_import_configs()
  538. # All targets built under this scope is with the ESP-IDF build system
  539. set(ESP_PLATFORM 1)
  540. idf_build_set_property(COMPILE_DEFINITIONS "ESP_PLATFORM" APPEND)
  541. # Perform component processing (inclusion of project_include.cmake, adding component
  542. # subdirectories, creating library targets, linking libraries, etc.)
  543. __build_process_project_includes()
  544. idf_build_get_property(idf_path IDF_PATH)
  545. add_subdirectory(${idf_path} ${build_dir}/esp-idf)
  546. unset(ESP_PLATFORM)
  547. endmacro()
  548. # idf_build_executable
  549. #
  550. # @brief Specify the executable the build system can attach dependencies to (for generating
  551. # files used for linking, targets which should execute before creating the specified executable,
  552. # generating additional binary files, generating files related to flashing, etc.)
  553. function(idf_build_executable elf)
  554. # Set additional link flags for the executable
  555. idf_build_get_property(link_options LINK_OPTIONS)
  556. set_property(TARGET ${elf} APPEND PROPERTY LINK_OPTIONS "${link_options}")
  557. # Propagate link dependencies from component library targets to the executable
  558. idf_build_get_property(link_depends __LINK_DEPENDS)
  559. set_property(TARGET ${elf} APPEND PROPERTY LINK_DEPENDS "${link_depends}")
  560. # Set the EXECUTABLE_NAME and EXECUTABLE properties since there are generator expression
  561. # from components that depend on it
  562. get_filename_component(elf_name ${elf} NAME_WLE)
  563. get_target_property(elf_dir ${elf} BINARY_DIR)
  564. idf_build_set_property(EXECUTABLE_NAME ${elf_name})
  565. idf_build_set_property(EXECUTABLE ${elf})
  566. idf_build_set_property(EXECUTABLE_DIR "${elf_dir}")
  567. # Add dependency of the build target to the executable
  568. add_dependencies(${elf} __idf_build_target)
  569. endfunction()
  570. # idf_build_get_config
  571. #
  572. # @brief Get value of specified config variable
  573. function(idf_build_get_config var config)
  574. cmake_parse_arguments(_ "GENERATOR_EXPRESSION" "" "" ${ARGN})
  575. if(__GENERATOR_EXPRESSION)
  576. set(val "$<TARGET_PROPERTY:__idf_build_target,${config}>")
  577. else()
  578. get_property(val TARGET __idf_build_target PROPERTY ${config})
  579. endif()
  580. set(${var} ${val} PARENT_SCOPE)
  581. endfunction()