INTERFACE_LINK_LIBRARIES_DIRECT¶
在 3.24 版本加入.
该库的使用者应视为直接链接依赖项的库列表。
此目标属性可以设置为 include 依赖目标的最终直接链接依赖集中的项目。请参阅 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 属性适用于高级用例,例如将静态插件注入到使用中的可执行文件中。它不应该用作组织对 target_link_libraries() 的正常调用的替代品。
直接链接依赖作为使用需求¶
INTERFACE_LINK_LIBRARIES_DIRECT 和 INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE 目标属性是 usage requirements。它们的效果可传递地传播到依赖目标,因此可以影响依赖库链中每个目标的直接链接依赖性。每当某些库目标“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`中,所以``Y``的使用要求,包括``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中。Y的链接要求,包括``INTERFACE_LINK_LIBRARIES_DIRECT``、INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,以及由它们添加的直接链接依赖项声明的传递链接依赖项,被传播到``X`` 的依赖项。但是,Y的非链接使用要求被LINK_ONLY生成器表达式阻止,并且不会传播到``X`` 的依赖项。如果 X 是共享库或可执行文件,并且私下链接 Y:
target_link_libraries(X PRIVATE Y)
那么``Y``就没有放在``X``的 :prop_tgt:`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”和其他东西。在这种情况下,应用程序应该在 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”的依赖项。
示例:选择加入静态插件¶
在上面的“示例:静态插件”中,“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`` 的依赖项。