target_link_libraries¶
在链接给定目标及其依赖项时指定要使用的库或标志。已链接的库目标的 使用要求 将被传播。目标依赖项的使用要求影响其自身源的编译。
概述¶
该命令有多个签名,如下面的子部分所述。它们全部采用以下通用形式
target_link_libraries(<target> ... <item>... ...)
命名的 <target>
必须由类似 add_executable()
或 add_library()
的命令创建,并且不能是 别名目标。如果策略 CMP0079
未设置为 NEW
,则必须在当前目录中创建目标。对同一 <target>
的重复调用将按调用顺序追加项。
3.13 版新增: <target>
不一定要在与 target_link_libraries
调用相同的目录中定义。
每个 <item>
都可能是
库目标名称:生成的链接行将有与目标关联的可链接库文件的完整路径。如果库文件发生更改,构建系统将有重新链接
<target>
的依赖项。命名的目标必须由
add_library()
在项目中创建,或作为 导入的库 创建。如果在项目中创建,则将在构建系统中自动添加顺序依赖项,以确保在<target>
链接之前,命名的库目标是最新的。如果导入的库有
IMPORTED_NO_SONAME
目标属性的集合,CMake 可能会要求链接器搜索库,而不是使用完整的路径(例如,/usr/lib/libfoo.so
变为-lfoo
)。目标工件的完整路径会自动用 shell 进行引用/转义。
指向库文件的完整路径:生成的链接行通常会保留文件的完整路径。如果库文件发生变化,该构建系统将依赖重新链接
<target>
。在某些情况下,CMake 可能会要求链接器搜索库(例如
/usr/lib/libfoo.so
变为-lfoo
),例如当检测到共享库没有SONAME
字段时。对于其他情况的讨论,请参阅策略CMP0060
。如果库文件在 macOS 框架中,框架的
Headers
目录也将作为 使用要求 进行处理。这与将框架目录作为包含目录传递的效果相同。在版本 3.28 中添加: 库文件可能会指向 Apple 平台上的
.xcframework
文件夹。如果指向,目标将获取选定库的Headers
目录作为使用要求。在版本 3.8 中添加: 在 Visual Studio 生成器 VS 2010 及更高版本中,以
.targets
结尾的库文件将被视为 MSBuild 目标文件并导入到生成的项目文件中。其他生成器不支持此功能。库文件的完整路径会自动用 shell 进行引用/转义。
一个普通的库名称:生成的链接行将要求链接器搜索库(例如
foo
变为-lfoo
或foo.lib
)。库名称/标志被视为命令行字符串片段,且不带任何额外的引号或转义符而使用。
一个链接标志:以
-
开头但不是-l
或-framework
的项名称被视为链接标志。请注意,此类标志将被视为传传递依赖项方面与任何其他链接库项一样,所以通常安全地将其仅指定为私有链接项,而不会传播给依赖项。此处指定 link flag 已插入 link 命令与 link libraries 相同的位置。视 linker 而定,这可能不正确。使用
LINK_OPTIONS
target 属性或target_link_options()
命令以显式添加 link flags。link flags 将放置在 link 命令中由工具链定义的 flag 位置。3.13 版本新增:
LINK_OPTIONS
target 属性及target_link_options()
命令。对于较早版本的 CMake,请改用LINK_FLAGS
属性。link flag 被当作命令行字符串片段处理,不会使用任何额外的引号或转义符。
生成器表达式:
$<...>
generator expression
可以变为上述任何项或 分号分隔列表。如果...
包含;
字符,例如,评估${list}
变量之后,请务必使用显式引号参数"$<...>"
,以便该命令将其作为单个<item>
接收。此外,生成器表达式可用作上述任何项的片段,例如
foo$<1:_d>
。一个
debug
、optimized
或general
关键字紧跟另一个<item>
。此类关键字之后的项仅用于相应的构建配置。debug
关键字对应于Debug
配置(或若已设置,对应于DEBUG_CONFIGURATIONS
全局属性中命名的配置)。optimized
关键字对应于所有其他配置。general
关键字对应于所有配置,且为纯粹可选。可通过创建并链接至 IMPORTED 库目标 来实现针对每个配置规则的更细粒度。此命令将立即解释这些关键字,因此在生成器表达式生成时,它们没有任何特殊含义。
包含 ::
的项(如 Foo::Bar
)被假定为 IMPORTED 或 ALIAS 库目标名称,并且若不存在此类目标,将会引发一个错误。请参阅 CMP0028
策略。
请参阅 CMAKE_LINK_LIBRARIES_STRATEGY
变量和相应的 LINK_LIBRARIES_STRATEGY
目标属性,了解有关 CMake 针对链接器命令行对直接链接依赖项排序的详细信息。
请参阅 cmake-buildsystem(7)
手册,进一步了解有关定义构建系统属性的内容。
目标及其依赖项的库¶
target_link_libraries(<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
可以使用 PUBLIC
、PRIVATE
和 INTERFACE
范围 关键字在一行命令中同时指定链接依赖项和链接接口。
紧跟 PUBLIC
的库和目标会链接到目标上,并且成为链接接口的一部分。紧跟 PRIVATE
的库和目标会链接到目标上,但不会成为链接接口的一部分。紧跟 INTERFACE
的库会追加到链接接口上,但不用于链接 <target>
。
针对目标及其从属目标的函数库¶
target_link_libraries(<target> <item>...)
使用此签名时,函数库依赖关系默认可传递。当此目标链接到另一个目标时,链接到此目标的函数库也将出现在另一个目标的链接行中。此可传递“链接接口”存储在 INTERFACE_LINK_LIBRARIES
目标属性中,如果直接设置属性,则可能会被覆盖。当 CMP0022
未设置为 NEW
时,会内置可传递链接,但可通过 LINK_INTERFACE_LIBRARIES
属性覆盖它。对本命令的其他签名的调用可能会设置属性,从而使任何仅由此签名链接的函数库变为专用。
针对目标和/或其从属目标(旧版)的函数库¶
target_link_libraries(<target>
<LINK_PRIVATE|LINK_PUBLIC> <lib>...
[<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...)
可以使用 LINK_PUBLIC
和 LINK_PRIVATE
模式在一个命令中同时指定链接依赖项和链接接口。
此签名仅用于兼容性。优先使用 PUBLIC
或 PRIVATE
关键字。
后跟 LINK_PUBLIC
的函数库和目标将链接到,并将成为 INTERFACE_LINK_LIBRARIES
的一部分。如果策略 CMP0022
不为 NEW
,则它们也将成为 LINK_INTERFACE_LIBRARIES
的一部分。后跟 LINK_PRIVATE
的函数库和目标将链接,但不会成为 INTERFACE_LINK_LIBRARIES
(或 LINK_INTERFACE_LIBRARIES
)的一部分。
仅针对从属目标的函数库(旧版)¶
target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...)
模式 LINK_INTERFACE_LIBRARIES
将库附加到 INTERFACE_LINK_LIBRARIES
目标属性中,而不是将其用于链接。如果策略 CMP0022
不是 NEW
,则此模式还会将库附加到 LINK_INTERFACE_LIBRARIES
及其对应的每个配置。
此签名仅用于兼容性。最好使用 INTERFACE
模式。
指定为 debug
的库封装在生成器表达式中,以对应调试版本。如果策略 CMP0022
不是 NEW
,则这些库还会附加到 LINK_INTERFACE_LIBRARIES_DEBUG
属性(或附加到全局属性 DEBUG_CONFIGURATIONS
中列出的配置相对应的属性,如果已设置)。指定为 optimized
的库附加到 INTERFACE_LINK_LIBRARIES
属性。如果策略 CMP0022
不是 NEW
,则这些库还附加到 LINK_INTERFACE_LIBRARIES
属性。指定为 general
(或未指定任何关键字)的库将视为同时指定于 debug
和 optimized
。
链接对象库¶
在版本 3.12 中增加。
对象库可以用作 <target>
(第一)参数 target_link_libraries
,用于指定其源文件对于其他库的依赖性。例如,以下代码
add_library(A SHARED a.c)
target_compile_definitions(A PUBLIC A)
add_library(obj OBJECT obj.c)
target_compile_definitions(obj PUBLIC OBJ)
target_link_libraries(obj PUBLIC A)
使用 -DA -DOBJ
编译 obj.c
,并建立 obj
的使用要求,并将这些要求传播给它的依赖库。
典型的库和可执行文件可以链接到 对象库 以获取其对象和使用要求。继续上述示例,以下代码
add_library(B SHARED b.c)
target_link_libraries(B PUBLIC obj)
使用 -DA -DOBJ
编译 b.c
,用 b.c
和 obj.c
中的对象文件创建共享库 B
,并将 B
链接到 A
。此外,以下代码
add_executable(main main.c)
target_link_libraries(main B)
使用 -DA -DOBJ
编译 main.c
,并将可执行文件 main
链接到 B
和 A
。对象库的使用要求通过 B
瞬时传播,但对象文件不会传播。
对象库 可以“链接”到其他对象库以获取使用要求,但由于它们没有链接这一步骤,因此不会对它们的对象文件执行任何操作。从上述示例继续,以下代码
add_library(obj2 OBJECT obj2.c)
target_link_libraries(obj2 PUBLIC obj)
add_executable(main2 main2.c)
target_link_libraries(main2 obj2)
使用 -DA -DOBJ
编译 obj2.c
,用 main2.c
和 obj2.c
中的对象文件创建可执行文件 main2
,并将 main2
链接到 A
。
换句话说,当 对象库 出现目标的属性 INTERFACE_LINK_LIBRARIES
中时,它们将被视为 接口库,但当它们出现在目标的属性 LINK_LIBRARIES
中时,它们的对象文件也将被包含在链接中。
通过 $<TARGET_OBJECTS>
链接对象库¶
在 3.21 版本中新增。
与对象库相关联的对象文件可以通过 $<TARGET_OBJECTS>
生成器表达式进行引用。此类对象文件在所有库之前(而与它们各自的顺序无关)置于链接行中。此外,还会向构建系统添加一个顺序依赖项,以确保对象库在目标依赖项链接之前更新。例如,以下代码:
add_library(obj3 OBJECT obj3.c)
target_compile_definitions(obj3 PUBLIC OBJ3)
add_executable(main3 main3.c)
target_link_libraries(main3 PRIVATE a3 $<TARGET_OBJECTS:obj3> b3)
将可执行文件 main3
与来自 main3.c
和 obj3.c
的对象文件链接在一起,然后链接 a3
和 b3
库。 main3.c
不会使用 obj3
的使用要求(例如,-DOBJ3
)进行编译。
这种方法可用于将对象文件作为使用要求以传递方式包含在链接行中。继续上面的示例,以下代码:
add_library(iface_obj3 INTERFACE)
target_link_libraries(iface_obj3 INTERFACE obj3 $<TARGET_OBJECTS:obj3>)
创建了接口库 iface_obj3
,该库转发 obj3
使用要求,并将 obj3
对象文件添加到依赖项的链接行中。以下代码:
add_executable(use_obj3 use_obj3.c)
target_link_libraries(use_obj3 PRIVATE iface_obj3)
使用 -DOBJ3
编译 use_obj3.c
,并将可执行文件 use_obj3
与来自 use_obj3.c
和 obj3.c
的对象文件链接在一起。
这也可以通过静态库传递实现。由于静态库不链接,因此它不会使用以这种方式引用的对象库中的对象文件。相反,对象文件将成为静态库的传递链接依赖项。继续上面的示例,以下代码:
add_library(static3 STATIC static3.c)
target_link_libraries(static3 PRIVATE iface_obj3)
add_executable(use_static3 use_static3.c)
target_link_libraries(use_static3 PRIVATE static3)
使用 -DOBJ3
编译 static3.c
,并仅使用其自己的对象文件创建 libstatic3.a
。 use_static3.c
不使用 -DOBJ3
编译,因为使用要求不通过 static3
的私有依赖项进行传递。但是,static3
的链接依赖项会进行传播,包括 iface_obj3
对 $<TARGET_OBJECTS:obj3>
的引用。 use_static3
可执行文件是使用来自 use_static3.c
和 obj3.c
的对象文件创建的,并链接到库 libstatic3.a
。
使用此方法时,项目需要负责避免将多个相关二进制文件链接到 iface_obj3
,因为所有这些文件都将在它们的链接行中获取 obj3
对象文件。
注意
在 3.21 以前的 CMake 版本中,某些情况下 target_link_libraries
调用中引用的 $<TARGET_OBJECTS>
起作用,但没有得到完全支持
它没有在链接行上将对象文件放在库之前。
它没有添加对对象库的排序相关性。
它无法在具有多个架构的 Xcode 中工作。
静态库的循环相关性¶
库相关性图通常是非循环的(DAG),但是在相等相关的 STATIC
库的情况下,CMake 允许图中包含循环(强连接组件)。当另一个目标链接到其中一个库时,CMake 会重复整个连接组件。例如,代码
add_library(A STATIC a.c)
add_library(B STATIC b.c)
target_link_libraries(A B)
target_link_libraries(B A)
add_executable(main main.c)
target_link_libraries(main A)
将 main
链接到 A B A B
。虽然通常一次重复就足够了,但病态对象文件和符号排列可能需要更多。可以使用 LINK_INTERFACE_MULTIPLICITY
目标属性或在最后一个 target_link_libraries
调用中手动重复组件来处理此类情况。但是,如果两个存档文件真的互相依赖,那么应该将它们组合到单个存档文件中,可能通过使用 对象库 来实现。
创建可重定位包¶
请注意,不建议使用某个目标的绝对路径来填充 INTERFACE_LINK_LIBRARIES
的相关性。这将把相关性的库文件路径(在创建包时在计算机上找到的路径)硬编码到已安装软件包中。
有关在为重新分发创建软件包时指定使用要求时必须采取的额外注意事项,请参见 cmake-packages(7)
手册的 创建可重定位软件包 部分。