Genex-LINK_GROUP: Add feature RESCAN

Feature RESCAN can be used to manage circular references between
static libraries.
This commit is contained in:
Marc Chevrier 2022-03-02 17:32:44 +01:00
parent a950fd9553
commit b0fada9964
11 changed files with 92 additions and 4 deletions

View File

@ -1236,7 +1236,7 @@ Output-Related Expressions
expression.
The ``library-list`` argument can hold CMake targets or external libraries.
Any ``CMake`` target of type :ref:`OBJECT <Object Libraries>` or
Any CMake target of type :ref:`OBJECT <Object Libraries>` or
:ref:`INTERFACE <Interface Libraries>` will be ignored by this expression and
will be handled in the standard way.
@ -1284,7 +1284,7 @@ Output-Related Expressions
target_link_libraries(lib4 PRIVATE lib3 "$<LINK_GROUP:feature1,lib1,lib2>")
# lib4 will only be linked with lib3 and the group {lib1,lib2}
This example will be "re-written" by ``CMake`` in the following form:
This example will be "re-written" by CMake in the following form:
.. code-block:: cmake
@ -1317,7 +1317,7 @@ Output-Related Expressions
target_link_libraries(lib3 PRIVATE "$<LINK_GROUP:feat,lib1A,lib1B>"
"$<LINK_GROUP:feat,lib2A,lib2B>")
This example will be "re-written" by ``CMake`` in the following form:
This example will be "re-written" by CMake in the following form:
.. code-block:: cmake
@ -1337,6 +1337,10 @@ Output-Related Expressions
So, we have a circular dependency between groups ``{lib1A,lib1B}`` and
``{lib2A,lib2B}``.
CMake pre-defines some features of general interest:
.. include:: ../variable/LINK_GROUP_PREDEFINED_FEATURES.txt
.. genex:: $<INSTALL_INTERFACE:...>
Content of ``...`` when the property is exported using :command:`install(EXPORT)`,

View File

@ -0,0 +1,5 @@
rescan-static-libraries
-----------------------
* The :genex:`LINK_GROUP` generator expression gained the ability to manage
circular references between static libraries by using ``RESCAN`` feature.

View File

@ -18,3 +18,10 @@ See also the associated variable
features independent from the link language.
.. include:: CMAKE_LINK_GROUP_USING_FEATURE.txt
Predefined Features
^^^^^^^^^^^^^^^^^^^
CMake pre-defines some features of general interest:
.. include:: LINK_GROUP_PREDEFINED_FEATURES.txt

View File

@ -23,3 +23,10 @@ for the linker language, the variable
set.
.. include:: CMAKE_LINK_GROUP_USING_FEATURE.txt
Predefined Features
^^^^^^^^^^^^^^^^^^^
CMake pre-defines some features of general interest:
.. include:: LINK_GROUP_PREDEFINED_FEATURES.txt

View File

@ -0,0 +1,22 @@
**Circular references with static libraries**
Some linkers are one-pass only so to handle circular references between
static libraries, the following feature can be used:
``RESCAN``
The specified static libraries are searched repeatedly until no
new undefined references are created. Normally, an static library is searched
only once in the order that it is specified on the command line. If a symbol
in that library is needed to resolve an undefined symbol referred to by an
object in an library that appears later on the command line, the linker would
not be able to resolve that reference. By grouping the static libraries, they
all be searched repeatedly until all possible references are resolved (use
linker options ``--start-group`` and ``--end-group`` or, on ``SunOS``,
``-z rescan-start`` and ``-z rescan-end``).
Using this feature has a significant performance cost. It is best to use it
only when there are unavoidable circular references between two or more static
libraries.
This feature is available on ``Linux`` and ``SunOS`` platforms as well as
``Windows`` when ``GNU`` toolchain is used.

View File

@ -19,6 +19,14 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic")
endforeach()
# Features for LINK_GROUP generator expression
## RESCAN: request the linker to rescan static libraries until there is
## no pending undefined symbols
set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group")
set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE)
# Debian policy requires that shared libraries be installed without
# executable permission. Fedora policy requires that shared libraries
# be installed with the executable permission. Since the native tools

View File

@ -7,6 +7,16 @@ if(CMAKE_SYSTEM MATCHES "SunOS-4")
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":")
endif()
# Features for LINK_GROUP generator expression
if (CMAKE_SYSTEM_VERSION VERSION_GREATER "5.9")
## RESCAN: request the linker to rescan static libraries until there is
## no pending undefined symbols
set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:-z,rescan-start" "LINKER:-z,rescan-end")
set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE)
endif()
include(Platform/UnixPaths)
list(APPEND CMAKE_SYSTEM_PREFIX_PATH

View File

@ -44,6 +44,14 @@ if("${_help}" MATCHES "GNU ld .* 2\\.1[1-6]")
set(__WINDOWS_GNU_LD_RESPONSE 0)
endif()
# Features for LINK_GROUP generator expression
## RESCAN: request the linker to rescan static libraries until there is
## no pending undefined symbols
set(CMAKE_LINK_GROUP_USING_RESCAN "LINKER:--start-group" "LINKER:--end-group")
set(CMAKE_LINK_GROUP_USING_RESCAN_SUPPORTED TRUE)
macro(__windows_compiler_gnu lang)
# Create archiving rules to support large object file lists for static libraries.

View File

@ -61,3 +61,11 @@ if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode"
unset(RunCMake_TEST_OUTPUT_MERGE)
endif()
# Feature RESCAN
if (CMAKE_SYSTEM_NAME STREQUAL "Linux"
OR (CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND (NOT CMAKE_C_COMPILER_ID STREQUAL "SunPro" OR CMAKE_C_COMPILER_VERSION VERSION_GREATER "5.9"))
OR (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "GNU"))
run_cmake(rescan)
run_cmake_target(rescan link main)
endif()

View File

@ -1,7 +1,7 @@
enable_language(C)
set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE)
set(CMAKE_C_LINK_GROUP_USING_cross_refs_SUPPORTED TRUE)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU"
AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CMAKE_C_LINK_GROUP_USING_cross_refs "LINKER:--start-group"

View File

@ -0,0 +1,9 @@
enable_language(C)
# Feature RESCAN
add_library(static1 STATIC func1.c func3.c)
add_library(static2 STATIC func2.c)
add_executable(main main.c)
target_link_libraries(main PRIVATE "$<LINK_GROUP:RESCAN,static1,static2>")