Usage requirement to update direct link dependencies
CMake computes the link line of a target as follows:
- Start with items in the
LINK_LIBRARIES
property of the target itself. - For each of those items that is a target, follow the transitive closure of its
INTERFACE_LINK_LIBRARIES
. - Append items found in the link interface closures needed for dependencies not satisfied by the original
LINK_LIBRARIES
list. Add them in an order that respects their dependencies.
The real implementation is a bit more complicated to handle inferred dependencies of non-target items, but the above is the gist of the logic for targets.
Note that the last step only ever appends to the original LINK_LIBRARIES
. It never inserts among them. This gives projects some control over their link order. However, it does not support a case Qt has for static plugin injection:
Qt plugin injection that causes circular dependency
# Core library used by other components.
add_library(Core STATIC core.cpp)
# Gui is a static library for use by applications.
add_library(Gui STATIC gui_plugin_helper.cpp gui_building_block.cpp)
target_link_libraries(Gui PRIVATE Core)
# Extra parts of Gui for use by its static plugins.
add_library(GuiExtras STATIC gui_extras.cpp)
target_link_libraries(GuiExtras PRIVATE Core Gui)
# The Gui library has associated static plugins that should be linked into the final executable.
add_library(gui_plugin STATIC gui_plugin.cpp)
# The plugins depend on some functions in Gui and other libraries.
target_link_libraries(gui_plugin PRIVATE Core Gui GuiExtras)
# Any application that links Gui should automatically get its plugins.
target_link_libraries(Gui INTERFACE gui_plugin)
# An application only specifies linking to the Gui static library.
add_executable(app main.cpp)
target_link_libraries(app PRIVATE Gui)
The resulting link line for app
contains:
-o app libGui.a libgui_plugin.a libGuiExtras.a libGui.a libgui_plugin.a libGuiExtras.a libCore.a
The reason for the repetition is that the link dependency graph contains a cycle between Gui
and gui_plugin
.
Each library's INTERFACE_LINK_LIBRARIES
specifies the other. This results in inefficient linker operation,
and in more complex cases possibly incorrect library ordering.
If we instead modify the example to link app
directly to gui_plugin
:
-# Any application that links Gui should automatically get its plugins.
-target_link_libraries(Gui INTERFACE gui_plugin)
-
-# An application only specifies linking to the Gui static library.
add_executable(app main.cpp)
-target_link_libraries(app PRIVATE Gui)
+target_link_libraries(app PRIVATE gui_plugin)
Then the resulting link line for app
references every library once in the desired order:
-o app libgui_plugin.a libGuiExtras.a libGui.a libCore.a
However, it is not practical for Qt to ask application authors to manually do this.
We need a way to specify this as a usage requirement of Gui
.
To solve this, we'll need some way for a usage requirement to modify behavior of the first step: to add/remove the initial list of items taken from LINK_LIBRARIES
. In the above Qt case, Gui
needs to be able to specify usage requirements that say:
- "pretend
app
linked directly togui_plugin
" - "pretend
app
did not link directly toGui
(except to propagate this requirement)"