diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index f5d7a6f8b..915d340ef 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -308,6 +308,8 @@ The list of directories in ``COMPONENT_DIRS`` is searched for the project's comp When CMake runs to configure the project, it logs the components included in the build. This list can be useful for debugging the inclusion/exclusion of certain components. +.. _cmake-components-same-name: + Multiple components with the same name -------------------------------------- @@ -1266,7 +1268,9 @@ the first element/member instead. [LDFRAGMENTS ldfragment1 ldfragment2 ...] [REQUIRED_IDF_TARGETS target1 target2 ...] [EMBED_FILES file1 file2 ...] - [EMBED_TXTFILES file1 file2 ...]) + [EMBED_TXTFILES file1 file2 ...] + [KCONFIG kconfig] + [KCONFIG_PROJBUILD kconfig_projbuild]) Register a component to the build system. Much like the ``project()`` CMake command, this should be called from the component's CMakeLists.txt directly (not through a function or macro) and is recommended to be called before any other command. Here are some @@ -1289,6 +1293,8 @@ The arguments for ``idf_component_register`` include: - PRIV_REQUIRES - private component requirements for the component; ignored on config-only components - LDFRAGMENTS - component linker fragment files - REQUIRED_IDF_TARGETS - specify the only target the component supports + - KCONFIG - override the default Kconfig file + - KCONFIG_PROJBUILD - override the default Kconfig.projbuild file The following are used for :ref:`embedding data into the component`, and is considered as source files when determining if a component is config-only. This means that even if the component does not specify source files, a static library is still @@ -1313,6 +1319,7 @@ For example, to get the directory of the ``freertos`` component: - COMPONENT_ALIAS - alias for COMPONENT_LIB used for linking the component to external targets; set by ``idf_build_component`` and alias library itself is created by ``idf_component_register`` - COMPONENT_DIR - component directory; set by ``idf_build_component`` +- COMPONENT_OVERRIDEN_DIR - contains the directory of the original component if ref:`this component overrides another component` - COMPONENT_LIB - name for created component static/interface library; set by ``idf_build_component`` and library itself is created by ``idf_component_register`` - COMPONENT_NAME - name of the component; set by ``idf_build_component`` based on the component directory name diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index ef2ee5ce4..9f8ddc43e 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -743,6 +743,19 @@ endmenu\n" >> ${IDF_PATH}/Kconfig rm -rf build popd + print_status "Getting component overriden dir" + clean_build_dir + mkdir -p components/esp32 + echo "idf_component_get_property(overriden_dir \${COMPONENT_NAME} COMPONENT_OVERRIDEN_DIR)" >> components/esp32/CMakeLists.txt + echo "message(STATUS overriden_dir:\${overriden_dir})" >> components/esp32/CMakeLists.txt + (idf.py reconfigure | grep "overriden_dir:$IDF_PATH/components/esp32") || failure "Failed to get overriden dir" # no registration, overrides registration as well + print_status "Overriding Kconfig" + echo "idf_component_register(KCONFIG \${overriden_dir}/Kconfig)" >> components/esp32/CMakeLists.txt + echo "idf_component_get_property(kconfig \${COMPONENT_NAME} KCONFIG)" >> components/esp32/CMakeLists.txt + echo "message(STATUS kconfig:\${overriden_dir}/Kconfig)" >> components/esp32/CMakeLists.txt + (idf.py reconfigure | grep "kconfig:$IDF_PATH/components/esp32/Kconfig") || failure "Failed to verify original `main` directory" + rm -rf components + print_status "All tests completed" if [ -n "${FAILURES}" ]; then echo "Some failures were detected:" diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index b9b035bc5..4a7396501 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -171,6 +171,9 @@ function(__component_add component_dir prefix) add_library(${component_target} STATIC IMPORTED) endif() idf_build_set_property(__COMPONENT_TARGETS ${component_target} APPEND) + else() + __component_get_property(dir ${component_target} COMPONENT_DIR) + __component_set_property(${component_target} COMPONENT_OVERRIDEN_DIR ${dir}) endif() set(component_lib __${prefix}_${component_name}) @@ -413,9 +416,11 @@ endfunction() # @param[in, optional] REQUIRED_IDF_TARGETS (multivalue) the list of IDF build targets that the component only supports # @param[in, optional] EMBED_FILES (multivalue) list of binary files to embed with the component # @param[in, optional] EMBED_TXTFILES (multivalue) list of text files to embed with the component +# @param[in, optional] KCONFIG (single value) override the default Kconfig +# @param[in, optional] KCONFIG_PROJBUILD (single value) override the default Kconfig function(idf_component_register) set(options) - set(single_value) + set(single_value KCONFIG KCONFIG_PROJBUILD) set(multi_value SRCS SRC_DIRS EXCLUDE_SRCS INCLUDE_DIRS PRIV_INCLUDE_DIRS LDFRAGMENTS REQUIRES PRIV_REQUIRES REQUIRED_IDF_TARGETS EMBED_FILES EMBED_TXTFILES) diff --git a/tools/cmake/scripts/component_get_requirements.cmake b/tools/cmake/scripts/component_get_requirements.cmake index f7a8002b0..3b3bca04d 100644 --- a/tools/cmake/scripts/component_get_requirements.cmake +++ b/tools/cmake/scripts/component_get_requirements.cmake @@ -1,3 +1,4 @@ +cmake_minimum_required(VERSION 3.5) include("${BUILD_PROPERTIES_FILE}") include("${COMPONENT_PROPERTIES_FILE}") @@ -18,18 +19,52 @@ function(__component_get_property var component_target property) set(${var} ${${_property}} PARENT_SCOPE) endfunction() +# +# Given a component name or alias, get the corresponding component target. +# +function(__component_get_target var name_or_alias) + idf_build_get_property(component_targets __COMPONENT_TARGETS) + + # Assume first that the paramters is an alias. + string(REPLACE "::" "_" name_or_alias "${name_or_alias}") + set(component_target ___${name_or_alias}) + + if(component_target IN_LIST component_targets) + set(${var} ${component_target} PARENT_SCOPE) + set(target ${component_target}) + else() # assumption is wrong, try to look for it manually + unset(target) + foreach(component_target ${component_targets}) + __component_get_property(_component_name ${component_target} COMPONENT_NAME) + if(name_or_alias STREQUAL _component_name) + set(target ${component_target}) + break() + endif() + endforeach() + set(${var} ${target} PARENT_SCOPE) + endif() +endfunction() + +function(idf_component_get_property var component property) + __component_get_target(component_target ${component}) + __component_get_property(_var ${component_target} ${property}) + set(${var} ${_var} PARENT_SCOPE) +endfunction() + macro(require_idf_targets) endmacro() macro(idf_component_register) set(options) - set(single_value) + set(single_value KCONFIG KCONFIG_PROJBUILD) set(multi_value SRCS SRC_DIRS EXCLUDE_SRCS INCLUDE_DIRS PRIV_INCLUDE_DIRS LDFRAGMENTS REQUIRES PRIV_REQUIRES REQUIRED_IDF_TARGETS EMBED_FILES EMBED_TXTFILES) cmake_parse_arguments(_ "${options}" "${single_value}" "${multi_value}" "${ARGN}") - set(__component_requires "${__REQUIRES}") set(__component_priv_requires "${__PRIV_REQUIRES}") + set(__component_requires "${__REQUIRES}") + set(__component_kconfig "${__KCONFIG}") + set(__component_kconfig_projbuild "${__KCONFIG_PROJBUILD}") set(__component_registered 1) return() endmacro() @@ -64,6 +99,8 @@ function(__component_get_requirements) set(__component_requires "${__component_requires}" PARENT_SCOPE) set(__component_priv_requires "${__component_priv_requires}" PARENT_SCOPE) + set(__component_kconfig "${__component_kconfig}" PARENT_SCOPE) + set(__component_kconfig_projbuild "${__component_kconfig_projbuild}" PARENT_SCOPE) set(__component_registered ${__component_registered} PARENT_SCOPE) endfunction() @@ -97,6 +134,21 @@ foreach(__component_target ${__component_targets}) __component_set_property(${__component_target} PRIV_REQUIRES \"${__component_priv_requires}\") __component_set_property(${__component_target} __COMPONENT_REGISTERED ${__component_registered})" ) + + if(__component_kconfig) + get_filename_component(__component_kconfig "${__component_kconfig}" ABSOLUTE) + set(__contents +"${__contents}\n__component_set_property(${__component_target} KCONFIG \"${__component_kconfig}\")" + ) + endif() + + if(__component_kconfig_projbuild) + get_filename_component(__component_kconfig "${__component_kconfig}" ABSOLUTE) + set(__contents +"${__contents}\n__component_set_property(${__component_target} KCONFIG_PROJBUILD \"${__component_kconfig_projbuild}\")" + ) + endif() + set(__component_requires_contents "${__component_requires_contents}\n${__contents}") endforeach()