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 的值可以使用 生成器表达式。
注意
INTERFACE_LINK_LIBRARIES_DIRECT 目标属性旨在用于高级用例,例如将静态插件注入到消费方可执行文件中。它不应被用作组织常规 target_link_libraries() 调用的替代方案。
作为使用要求的直接链接依赖项¶
INTERFACE_LINK_LIBRARIES_DIRECT 和 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE 目标属性是 使用要求。它们的影响会传递性地传播到从属目标,因此可能会影响依赖库链中每个目标的直接链接依赖项。每当某个库目标 X 链接到另一个库目标 Y,且该目标 Y 的直接或传递使用要求中包含 INTERFACE_LINK_LIBRARIES_DIRECT 或 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE 时,这些属性可能会影响 X 的直接链接依赖项列表。
如果
X是共享库或可执行文件,则其依赖项会被链接。它们还会影响编译X源文件时所使用的使用要求。如果
X是静态库或对象库,则它实际上并不执行链接,因此其依赖项最多只会影响编译X源文件时所使用的使用要求。
这些属性也可能影响 X 的从属目标上的直接链接依赖项列表。
如果
X公开(publicly)链接Ytarget_link_libraries(X PUBLIC Y)
那么
Y会被放置在X的INTERFACE_LINK_LIBRARIES中,因此Y的使用要求(包括INTERFACE_LINK_LIBRARIES_DIRECT、INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE以及它们所添加的直接链接依赖项声明的使用要求)都会传播到X的从属目标中。如果
X是静态库或对象库,并且私有(privately)链接Ytarget_link_libraries(X PRIVATE Y)
那么
$<LINK_ONLY:Y>会被放置在X的INTERFACE_LINK_LIBRARIES中。Y的链接要求(包括INTERFACE_LINK_LIBRARIES_DIRECT、INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE以及它们所添加的直接链接依赖项声明的传递链接依赖项)会传播到X的从属目标中。然而,Y的非链接使用要求会被LINK_ONLY生成器表达式阻止,不会传播到X的从属目标中。如果
X是共享库或可执行文件,并且私有链接Ytarget_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 使用要求中命名的项目将从最终列表中移除。这不会影响剩余项目的顺序。
示例:静态插件¶
考虑一个向消费方应用程序可执行文件提供静态插件 FooPlugin 的静态库 Foo,其中插件的实现依赖于 Foo 及其他内容。在这种情况下,应用程序应该在 Foo 之前直接链接到 FooPlugin。然而,应用程序作者只知道 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 的依赖项。
示例:选择加入(Opt-In)的静态插件¶
在上面的 示例:静态插件 中,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的依赖项。