INTERFACE_LINK_LIBRARIES_DIRECT¶
Added in version 3.24.
List of libraries that consumers of this library should treat as direct link dependencies.
This target property may be set to include items in a dependent
target's final set of direct link dependencies. See the
INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE target property
to exclude items.
The initial set of a dependent target's direct link dependencies is
specified by its LINK_LIBRARIES target property. Indirect
link dependencies are specified by the transitive closure of the direct
link dependencies' INTERFACE_LINK_LIBRARIES properties.
Any link dependency may specify additional direct link dependencies
using the INTERFACE_LINK_LIBRARIES_DIRECT target property.
The set of direct link dependencies is then filtered to exclude items named
by any dependency's INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
target property.
The value of INTERFACE_LINK_LIBRARIES_DIRECT may use
generator expressions.
Note
The INTERFACE_LINK_LIBRARIES_DIRECT target property is intended for
advanced use cases such as injection of static plugins into a consuming
executable. It should not be used as a substitute for organizing
normal calls to target_link_libraries().
Direct Link Dependencies as Usage Requirements¶
The INTERFACE_LINK_LIBRARIES_DIRECT and
INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE target properties
are usage requirements.
Their effects propagate to dependent targets transitively, and can
therefore affect the direct link dependencies of every target in a
chain of dependent libraries. Whenever some library target X links
to another library target Y whose direct or transitive usage
requirements contain INTERFACE_LINK_LIBRARIES_DIRECT or
INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, the properties may affect
X's list of direct link dependencies:
If
Xis a shared library or executable, its dependencies are linked. They also affect the usage requirements with whichX's sources are compiled.If
Xis a static library or object library, it does not actually link, so its dependencies at most affect the usage requirements with whichX's sources are compiled.
The properties may also affect the list of direct link dependencies
on X's dependents:
If
XlinksYpublicly:target_link_libraries(X PUBLIC Y)
then
Yis placed inX'sINTERFACE_LINK_LIBRARIES, soY's usage requirements, includingINTERFACE_LINK_LIBRARIES_DIRECT,INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, and the usage requirements declared by the direct link dependencies they add, are propagated toX's dependents.If
Xis a static library or object library, and linksYprivately:target_link_libraries(X PRIVATE Y)
then
$<LINK_ONLY:Y>is placed inX'sINTERFACE_LINK_LIBRARIES.Y's linking requirements, includingINTERFACE_LINK_LIBRARIES_DIRECT,INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, and the transitive link dependencies declared by the direct link dependencies they add, are propagated toX's dependents. However,Y's non-linking usage requirements are blocked by theLINK_ONLYgenerator expression, and are not propagated toX's dependents.If
Xis a shared library or executable, and linksYprivately:target_link_libraries(X PRIVATE Y)
then
Yis not placed inX'sINTERFACE_LINK_LIBRARIES, soY's usage requirements, evenINTERFACE_LINK_LIBRARIES_DIRECTandINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE, are not propagated toX's dependents.In all cases, the content of
X'sINTERFACE_LINK_LIBRARIESis not affected byY'sINTERFACE_LINK_LIBRARIES_DIRECTorINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE.
One may limit the effects of INTERFACE_LINK_LIBRARIES_DIRECT and
INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE to a subset of dependent
targets by using the TARGET_PROPERTY generator expression.
For example, to limit the effects to executable targets, use an
entry of the form:
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:...>"
Similarly, to limit the effects to specific targets, use an entry of the form:
"$<$<BOOL:$<TARGET_PROPERTY:USE_IT>>:...>"
This entry will only affect targets that set their USE_IT
target property to a true value.
Direct Link Dependency Ordering¶
The list of direct link dependencies for a target is computed from an
initial ordered list in its LINK_LIBRARIES target property.
For each item, additional direct link dependencies are discovered from
its direct and transitive INTERFACE_LINK_LIBRARIES_DIRECT usage
requirements. Each discovered item is injected before the item that
specified it. However, a discovered item is added at most once,
and only if it did not appear anywhere in the initial list.
This gives LINK_LIBRARIES control over ordering of
those direct link dependencies that it explicitly specifies.
Once all direct link dependencies have been collected, items named by
all of their INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
usage requirements are removed from the final list. This does not
affect the order of the items that remain.
Example: Static Plugins¶
Consider a static library Foo that provides a static plugin
FooPlugin to consuming application executables, where the
implementation of the plugin depends on Foo and other things.
In this case, the application should link to FooPlugin directly,
before Foo. However, the application author only knows about Foo.
We can express this as follows:
# Core library used by other components.
add_library(Core STATIC core.cpp)
# Foo is a static library for use by applications.
# Implementation of Foo depends on Core.
add_library(Foo STATIC foo.cpp foo_plugin_helper.cpp)
target_link_libraries(Foo PRIVATE Core)
# Extra parts of Foo for use by its static plugins.
# Implementation of Foo's extra parts depends on both Core and Foo.
add_library(FooExtras STATIC foo_extras.cpp)
target_link_libraries(FooExtras PRIVATE Core Foo)
# The Foo library has an associated static plugin
# that should be linked into the final executable.
# Implementation of the plugin depends on Core, Foo, and FooExtras.
add_library(FooPlugin STATIC foo_plugin.cpp)
target_link_libraries(FooPlugin PRIVATE Core Foo FooExtras)
# An app that links Foo should link Foo's plugin directly.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT FooPlugin)
# An app does not need to link Foo directly because the plugin links it.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE Foo)
An application app only needs to specify that it links to Foo:
add_executable(app main.cpp)
target_link_libraries(app PRIVATE Foo)
The INTERFACE_LINK_LIBRARIES_DIRECT target property on Foo tells
CMake to pretend that app also links directly to FooPlugin.
The INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE target property on Foo
tells CMake to pretend that app did not link directly to Foo.
Instead, Foo will be linked as a dependency of FooPlugin. The
final link line for app will link the libraries in the following
order:
FooPluginas a direct link dependency ofapp(viaFoo's usage requirements).FooExtrasas a dependency ofFooPlugin.Fooas a dependency ofFooPluginandFooExtras.Coreas a dependency ofFooPlugin,FooExtras, andFoo.
Note that without the INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE target
property, Foo would be linked twice: once as a direct dependency
of app, and once as a dependency of FooPlugin.
Example: Opt-In Static Plugins¶
In the above Example: Static Plugins, the app executable specifies
that it links directly to Foo. In a real application, there might
be an intermediate library:
add_library(app_impl STATIC app_impl.cpp)
target_link_libraries(app_impl PRIVATE Foo)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE app_impl)
In this case we do not want Foo's INTERFACE_LINK_LIBRARIES_DIRECT
and INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE target properties to affect
the direct dependencies of app_impl. To avoid this, we can revise
the property values to make their effects opt-in:
# An app that links Foo should link Foo's plugin directly.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
"$<$<BOOL:$<TARGET_PROPERTY:FOO_STATIC_PLUGINS>>:FooPlugin>"
)
# An app does not need to link Foo directly because the plugin links it.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
"$<$<BOOL:$<TARGET_PROPERTY:FOO_STATIC_PLUGINS>>:Foo>"
)
Now, the app executable can opt-in to get Foo's plugin(s):
set_property(TARGET app PROPERTY FOO_STATIC_PLUGINS 1)
The final link line for app will now link the libraries in the following
order:
FooPluginas a direct link dependency ofapp(viaFoo's usage requirements).app_implas a direct link dependency ofapp.FooExtrasas a dependency ofFooPlugin.Fooas a dependency ofapp_impl,FooPlugin, andFooExtras.Coreas a dependency ofFooPlugin,FooExtras, andFoo.