kconfig.cmake 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. include(ExternalProject)
  2. macro(kconfig_set_variables)
  3. set_default(IDF_SDKCONFIG_DEFAULTS "")
  4. set_default(CONFIG_DIR ${IDF_BUILD_ARTIFACTS_DIR}/config)
  5. set_default(SDKCONFIG ${IDF_PROJECT_PATH}/sdkconfig)
  6. set(SDKCONFIG_HEADER ${CONFIG_DIR}/sdkconfig.h)
  7. set(SDKCONFIG_CMAKE ${CONFIG_DIR}/sdkconfig.cmake)
  8. set(SDKCONFIG_JSON ${CONFIG_DIR}/sdkconfig.json)
  9. set(KCONFIG_JSON_MENUS ${CONFIG_DIR}/kconfig_menus.json)
  10. set(ROOT_KCONFIG ${IDF_PATH}/Kconfig)
  11. endmacro()
  12. if(CMAKE_HOST_WIN32)
  13. # Prefer a prebuilt mconf-idf on Windows
  14. if(DEFINED ENV{MSYSTEM})
  15. find_program(WINPTY winpty)
  16. else()
  17. unset(WINPTY CACHE) # in case previous CMake run was in a tty and this one is not
  18. endif()
  19. find_program(MCONF mconf-idf)
  20. # Fall back to the old binary which was called 'mconf' not 'mconf-idf'
  21. if(NOT MCONF)
  22. find_program(MCONF mconf)
  23. if(MCONF)
  24. message(WARNING "Falling back to mconf binary '${MCONF}' not mconf-idf. "
  25. "This is probably because an old version of IDF mconf is installed and this is fine. "
  26. "However if there are config problems please check the Getting Started guide for your platform.")
  27. endif()
  28. endif()
  29. if(NOT MCONF)
  30. find_program(NATIVE_GCC gcc)
  31. if(NOT NATIVE_GCC)
  32. message(FATAL_ERROR
  33. "Windows requires a prebuilt mconf-idf for your platform "
  34. "on the PATH, or an MSYS2 version of gcc on the PATH to build mconf-idf. "
  35. "Consult the setup docs for ESP-IDF on Windows.")
  36. endif()
  37. elseif(WINPTY)
  38. set(MCONF "${WINPTY}" "${MCONF}")
  39. endif()
  40. endif()
  41. if(NOT MCONF)
  42. # Use the existing Makefile to build mconf (out of tree) when needed
  43. #
  44. set(MCONF ${CMAKE_BINARY_DIR}/kconfig_bin/mconf-idf)
  45. externalproject_add(mconf-idf
  46. SOURCE_DIR ${IDF_PATH}/tools/kconfig
  47. CONFIGURE_COMMAND ""
  48. BINARY_DIR "kconfig_bin"
  49. BUILD_COMMAND make -f ${IDF_PATH}/tools/kconfig/Makefile mconf-idf
  50. BUILD_BYPRODUCTS ${MCONF}
  51. INSTALL_COMMAND ""
  52. EXCLUDE_FROM_ALL 1
  53. )
  54. file(GLOB mconf_srcfiles ${IDF_PATH}/tools/kconfig/*.c)
  55. externalproject_add_stepdependencies(mconf-idf build
  56. ${mconf_srcfiles}
  57. ${IDF_PATH}/tools/kconfig/Makefile
  58. ${CMAKE_CURRENT_LIST_FILE})
  59. unset(mconf_srcfiles)
  60. set(menuconfig_depends DEPENDS mconf-idf)
  61. endif()
  62. # Find all Kconfig files for all components
  63. function(kconfig_process_config)
  64. file(MAKE_DIRECTORY "${CONFIG_DIR}")
  65. set(kconfigs)
  66. set(kconfigs_projbuild)
  67. # Components are usually sorted (somewhat) topologically via their dependencies. This extends to the component
  68. # paths list. Obtain an alphabetical list in order to present menus also in the same order.
  69. set(components ${BUILD_COMPONENTS})
  70. list(SORT components)
  71. foreach(component ${components})
  72. list(FIND BUILD_COMPONENTS ${component} idx)
  73. list(GET BUILD_COMPONENT_PATHS ${idx} component_path)
  74. list(APPEND component_paths ${component_path})
  75. endforeach()
  76. # Find Kconfig and Kconfig.projbuild for each component as applicable
  77. # if any of these change, cmake should rerun
  78. foreach(dir ${component_paths})
  79. file(GLOB kconfig "${dir}/Kconfig")
  80. if(kconfig)
  81. set(kconfigs "${kconfigs} ${kconfig}")
  82. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${kconfig})
  83. endif()
  84. file(GLOB kconfig ${dir}/Kconfig.projbuild)
  85. if(kconfig)
  86. set(kconfigs_projbuild "${kconfigs_projbuild} ${kconfig}")
  87. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${kconfig})
  88. endif()
  89. endforeach()
  90. if(IDF_SDKCONFIG_DEFAULTS)
  91. set(defaults_arg --defaults "${IDF_SDKCONFIG_DEFAULTS}")
  92. endif()
  93. if(EXISTS "${IDF_SDKCONFIG_DEFAULTS}.${IDF_TARGET}")
  94. list(APPEND defaults_arg --defaults "${IDF_SDKCONFIG_DEFAULTS}.${IDF_TARGET}")
  95. endif()
  96. # Set these in the parent scope, so that they can be written to project_description.json
  97. set(kconfigs "${kconfigs}")
  98. set(COMPONENT_KCONFIGS "${kconfigs}" PARENT_SCOPE)
  99. set(COMPONENT_KCONFIGS_PROJBUILD "${kconfigs_projbuild}" PARENT_SCOPE)
  100. set(confgen_basecommand
  101. ${PYTHON} ${IDF_PATH}/tools/kconfig_new/confgen.py
  102. --kconfig ${ROOT_KCONFIG}
  103. --config ${SDKCONFIG}
  104. ${defaults_arg}
  105. --create-config-if-missing
  106. --env "COMPONENT_KCONFIGS=${kconfigs}"
  107. --env "COMPONENT_KCONFIGS_PROJBUILD=${kconfigs_projbuild}"
  108. --env "IDF_CMAKE=y")
  109. # Generate the menuconfig target (uses C-based mconf-idf tool, either prebuilt or via mconf-idf target above)
  110. add_custom_target(menuconfig
  111. ${menuconfig_depends}
  112. # create any missing config file, with defaults if necessary
  113. COMMAND ${confgen_basecommand} --env "IDF_TARGET=${IDF_TARGET}" --output config ${SDKCONFIG}
  114. COMMAND ${CMAKE_COMMAND} -E env
  115. "COMPONENT_KCONFIGS=${kconfigs}"
  116. "COMPONENT_KCONFIGS_PROJBUILD=${kconfigs_projbuild}"
  117. "IDF_CMAKE=y"
  118. "KCONFIG_CONFIG=${SDKCONFIG}"
  119. "IDF_TARGET=${IDF_TARGET}"
  120. ${MCONF} ${ROOT_KCONFIG}
  121. VERBATIM
  122. USES_TERMINAL)
  123. # Custom target to run confserver.py from the build tool
  124. add_custom_target(confserver
  125. COMMAND ${CMAKE_COMMAND} -E env
  126. "COMPONENT_KCONFIGS=${kconfigs}"
  127. "COMPONENT_KCONFIGS_PROJBUILD=${kconfigs_projbuild}"
  128. ${PYTHON} ${IDF_PATH}/tools/kconfig_new/confserver.py --kconfig ${IDF_PATH}/Kconfig --config ${SDKCONFIG}
  129. VERBATIM
  130. USES_TERMINAL)
  131. # Generate configuration output via confgen.py
  132. # makes sdkconfig.h and skdconfig.cmake
  133. #
  134. # This happens during the cmake run not during the build
  135. execute_process(COMMAND ${confgen_basecommand}
  136. --output header ${SDKCONFIG_HEADER}
  137. --output cmake ${SDKCONFIG_CMAKE}
  138. --output json ${SDKCONFIG_JSON}
  139. --output json_menus ${KCONFIG_JSON_MENUS}
  140. RESULT_VARIABLE config_result)
  141. if(config_result)
  142. message(FATAL_ERROR "Failed to run confgen.py (${confgen_basecommand}). Error ${config_result}")
  143. endif()
  144. # When sdkconfig file changes in the future, trigger a cmake run
  145. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SDKCONFIG}")
  146. # Ditto if either of the generated files are missing/modified (this is a bit irritating as it means
  147. # you can't edit these manually without them being regenerated, but I don't know of a better way...)
  148. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SDKCONFIG_HEADER}")
  149. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SDKCONFIG_CMAKE}")
  150. # Or if the config generation tool changes
  151. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IDF_PATH}/tools/kconfig_new/confgen.py")
  152. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IDF_PATH}/tools/kconfig_new/kconfiglib.py")
  153. set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
  154. ADDITIONAL_MAKE_CLEAN_FILES
  155. "${SDKCONFIG_HEADER}" "${SDKCONFIG_CMAKE}")
  156. endfunction()