INTERFACE_LINK_LIBRARIES_DIRECT¶
添加在版本 3.24 中。
依赖此库的使用者应该将其视为直接链接依赖的库列表。
此目标属性可以设置为包括相关目标最终组的直接链接依赖项。请参阅 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
目标属性以排除项。
指定相关目标的直接链接依赖项的最初集通过其 LINK_LIBRARIES
目标属性。间接链接依赖项通过直接链接依赖项的传递闭包指定 INTERFACE_LINK_LIBRARIES
属性。任何链接依赖项都可以使用 INTERFACE_LINK_LIBRARIES_DIRECT
目标属性指定其他直接链接依赖项。然后将直接链接依赖项集合过滤掉任何依赖项的 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
目标属性命名的项。
INTERFACE_LINK_LIBRARIES_DIRECT
的值可以使用 generator expressions
。
注意
INTERFACE_LINK_LIBRARIES_DIRECT
目标属性用于高级用例,例如将静态插件注入正在使用的可执行文件。不应将其用作组织对 target_link_libraries()
的常规调用的替代方法。
直接链接依赖项作为使用要求¶
INTERFACE_LINK_LIBRARIES_DIRECT
和 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
目标属性是 使用要求。它们的影响会传递给依赖目标,因此可能会影响依赖库链中的每个目标的直接链接依赖项。每当某个库目标 X
链接到另一个库目标 Y
,其直接或传递的使用要求包含 INTERFACE_LINK_LIBRARIES_DIRECT
或 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
时,这些属性可能会影响 X
的直接链接依赖项列表
如果
X
是共享库或可执行文件,则链接其依赖项。它们还会影响对编译X
源码所需用法要求。如果
X
是静态库或对象库,则它实际上不会链接,所以其依赖项最多会影响对编译X
源码所需用法要求。
这些属性还可能会影响 X
依赖项的直接链接依赖项列表
如果
X
公开链接Y
target_link_libraries(X PUBLIC Y)
则
Y
会放在X
的INTERFACE_LINK_LIBRARIES
中,因此包括INTERFACE_LINK_LIBRARIES_DIRECT
、INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
和它们添加的直接链接依赖项声明的用法要求,会在X
的依赖项中传播。如果
X
是静态库或对象库,且私有链接Y
target_link_libraries(X PRIVATE Y)
则
$<LINK_ONLY:Y>
会放在X
的INTERFACE_LINK_LIBRARIES
中。包括INTERFACE_LINK_LIBRARIES_DIRECT
、INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
和它们添加的直接链接依赖项声明的传递链接依赖项,会在X
的依赖项中传播。然而,Y
的非链接用法要求会被LINK_ONLY
生成器表达式阻止,不会传播到X
的依赖项。如果
X
是共享库或可执行文件,且私有链接Y
target_link_libraries(X PRIVATE Y)
则
Y
不会放在X
的INTERFACE_LINK_LIBRARIES
中,因此Y
的用法要求,甚至包括INTERFACE_LINK_LIBRARIES_DIRECT
和INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
,不会传播到X
的依赖项中。无论何种情况下,
X
的INTERFACE_LINK_LIBRARIES
中的内容不受Y
的INTERFACE_LINK_LIBRARIES_DIRECT
或INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
的影响。
通过使用 TARGET_PROPERTY
生成器表达式,可以将 INTERFACE_LINK_LIBRARIES_DIRECT
和 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
的影响限制为依赖目标的子集。例如,要将影响限制为可执行目标,请使用以下形式的输入
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:...>"
类似地,要将影响限制为特定目标,请使用以下形式的输入
"$<$<BOOL:$<TARGET_PROPERTY:USE_IT>>:...>"
此输入仅会影响将 USE_IT
目标属性设置为真值的那些目标。
直接链接依赖项排序¶
根据其 LINK_LIBRARIES
目标属性中的初始有序列表来计算目标的直接链接依赖项列表。对于每个项,从其直接和传递 INTERFACE_LINK_LIBRARIES_DIRECT
使用要求中发现其他直接链接依赖项。每个发现的项都被插入到指定它的项之前。但是,一个发现的项最多只会被添加一次,并且仅当它在初始列表中的任何位置都不出现时才添加。这使得 LINK_LIBRARIES
可以控制它明确指定的内容的那些直接链接依赖项的排序。
一旦收集所有直接链接依赖项,所有都由 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
使用要求命名的项都会从最终列表中移除。这不会影响保留的项的顺序。
示例:静态插件¶
考虑一个静态库 Foo
,它为使用应用程序可执行文件提供了一个静态插件 FooPlugin
,其中插件的实现取决于 Foo
和其他内容。在这种情况下,应用程序应直接链接到 FooPlugin
,在 Foo
之前。但是,应用程序编写者只知道 Foo
。我们可以将其表述为以下内容
# 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)
应用程序 app
只需要指定其链接到 Foo
add_executable(app main.cpp)
target_link_libraries(app PRIVATE Foo)
Foo
上的 INTERFACE_LINK_LIBRARIES_DIRECT
目标属性告知 CMake 假装 app
也直接链接到 FooPlugin
。 Foo
上的 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
目标属性告知 CMake 假装 app
没有直接链接到 Foo
。相反, Foo
将作为 FooPlugin
的依赖关系链接。对 app
的最终链接行将按以下顺序链接库
FooPlugin
作为app
的直接链接依赖关系(通过Foo
的使用要求)。FooExtras
作为FooPlugin
的依赖关系。Foo
作为FooPlugin
和FooExtras
的依赖关系。Core
作为FooPlugin
、FooExtras
和Foo
的依赖关系。
请注意,如果没有 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
目标属性, Foo
将被链接两次:一次作为 app
的直接依赖关系,一次作为 FooPlugin
的依赖关系。
示例:选择加入静态插件¶
在上述 示例:静态插件 中, app
可执行文件指定其直接链接到 Foo
。在实际应用程序中,可能有一个中间库
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)
在这种情况下,我们不希望 Foo
的 INTERFACE_LINK_LIBRARIES_DIRECT
和 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
目标属性影响 app_impl
的直接依赖关系。为了避免这种情况,我们可以修改属性值使其影响选择加入
# 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>"
)
现在,app
可执行文件可以选择加入以获取 Foo
的插件
set_property(TARGET app PROPERTY FOO_STATIC_PLUGINS 1)
app
的最终链接行现在将按以下顺序链接库
FooPlugin
作为app
的直接链接依赖关系(通过Foo
的使用要求)。app_impl
作为app
的直接链接依赖项。FooExtras
作为FooPlugin
的依赖关系。Foo
作为app_impl
、FooPlugin
和FooExtras
的依赖项。Core
作为FooPlugin
、FooExtras
和Foo
的依赖关系。