From 273633ee310fbc18b17edfaeae3f3121508e3b8d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 30 Mar 2022 00:42:32 +0200 Subject: [PATCH] build system: add WHOLE_ARCHIVE component property This component property allows including all component object files into the executable. It is equivalent to wrapping the component library with -Wl,--whole-archive and -Wl,--no-whole-archive flags. Closes https://github.com/espressif/esp-idf/issues/8667 --- docs/en/api-guides/build-system.rst | 5 ++++- tools/cmake/component.cmake | 5 ++++- tools/cmake/project.cmake | 13 ++++++++++++- .../cmake/scripts/component_get_requirements.cmake | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 87f0b8480d..f403348cba 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -1342,7 +1342,8 @@ Set a specified *component*'s :ref:`component property`, 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 created internally for the component if it specifies either: @@ -1399,6 +1401,7 @@ These are properties that describe a component. Values of component properties c - REQUIRED_IDF_TARGETS - list of targets the component supports; set from ``idf_component_register`` EMBED_TXTFILES argument - REQUIRES - list of public component dependencies; set from ``idf_component_register`` REQUIRES argument - SRCS - list of component source files; set from SRCS or SRC_DIRS/EXCLUDE_SRCS argument of ``idf_component_register`` +- WHOLE_ARCHIVE - if this property is set to ``TRUE`` (or any boolean "true" CMake value: 1, ``ON``, ``YES``, ``Y``), the component library is surrounded by ``-Wl,--whole-archive``, ``-Wl,--no-whole-archive`` when linked. This can be used to force the linker to include every object file into the executable, even if the object file doesn't resolve any references from the rest of the application. This is commonly used when a component contains plugins or modules which rely on link-time registration. This property is ``FALSE`` by default. It can be set to ``TRUE`` from the component CMakeLists.txt file. .. _cmake-file-globbing: diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index e28a52f4ca..25773bc5fe 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -88,6 +88,8 @@ macro(__component_set_properties) __component_set_property(${component_target} EMBED_FILES "${__EMBED_FILES}") __component_set_property(${component_target} EMBED_TXTFILES "${__EMBED_TXTFILES}") __component_set_property(${component_target} REQUIRED_IDF_TARGETS "${__REQUIRED_IDF_TARGETS}") + + __component_set_property(${component_target} WHOLE_ARCHIVE ${__WHOLE_ARCHIVE}) endmacro() # @@ -417,8 +419,9 @@ endfunction() # @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 +# @param[in, optional] WHOLE_ARCHIVE (option) link the component as --whole-archive function(idf_component_register) - set(options) + set(options WHOLE_ARCHIVE) set(single_value KCONFIG KCONFIG_PROJBUILD) set(multi_value SRCS SRC_DIRS EXCLUDE_SRCS INCLUDE_DIRS PRIV_INCLUDE_DIRS LDFRAGMENTS REQUIRES diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index a4f7da8db4..1c7c41707a 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -484,7 +484,18 @@ macro(project project_name) if(test_components) list(REMOVE_ITEM build_components ${test_components}) endif() - target_link_libraries(${project_elf} ${build_components}) + + foreach(build_component ${build_components}) + __component_get_target(build_component_target ${build_component}) + __component_get_property(whole_archive ${build_component_target} WHOLE_ARCHIVE) + if(whole_archive) + message(STATUS "Component ${build_component} will be linked with -Wl,--whole-archive") + target_link_libraries(${project_elf} "-Wl,--whole-archive" ${build_component} "-Wl,--no-whole-archive") + else() + target_link_libraries(${project_elf} ${build_component}) + endif() + endforeach() + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") set(mapfile "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.map") diff --git a/tools/cmake/scripts/component_get_requirements.cmake b/tools/cmake/scripts/component_get_requirements.cmake index aa294c6f0e..387d9aec63 100644 --- a/tools/cmake/scripts/component_get_requirements.cmake +++ b/tools/cmake/scripts/component_get_requirements.cmake @@ -66,7 +66,7 @@ macro(idf_component_mock) endmacro() macro(idf_component_register) - set(options) + set(options WHOLE_ARCHIVE) set(single_value KCONFIG KCONFIG_PROJBUILD) set(multi_value SRCS SRC_DIRS EXCLUDE_SRCS INCLUDE_DIRS PRIV_INCLUDE_DIRS LDFRAGMENTS REQUIRES