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
X
is a shared library or executable, its dependencies are linked. They also affect the usage requirements with whichX
's sources are compiled.If
X
is 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
X
linksY
publicly:target_link_libraries(X PUBLIC Y)
then
Y
is 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
X
is a static library or object library, and linksY
privately: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_ONLY
generator expression, and are not propagated toX
's dependents.If
X
is a shared library or executable, and linksY
privately:target_link_libraries(X PRIVATE Y)
then
Y
is not placed inX
'sINTERFACE_LINK_LIBRARIES
, soY
's usage requirements, evenINTERFACE_LINK_LIBRARIES_DIRECT
andINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
, are not propagated toX
's dependents.In all cases, the content of
X
'sINTERFACE_LINK_LIBRARIES
is not affected byY
'sINTERFACE_LINK_LIBRARIES_DIRECT
orINTERFACE_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:
FooPlugin
as a direct link dependency ofapp
(viaFoo
's usage requirements).FooExtras
as a dependency ofFooPlugin
.Foo
as a dependency ofFooPlugin
andFooExtras
.Core
as 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:
FooPlugin
as a direct link dependency ofapp
(viaFoo
's usage requirements).app_impl
as a direct link dependency ofapp
.FooExtras
as a dependency ofFooPlugin
.Foo
as a dependency ofapp_impl
,FooPlugin
, andFooExtras
.Core
as a dependency ofFooPlugin
,FooExtras
, andFoo
.