概述
此命令具有以下各小节详细介绍的多个签名。所有这些签名都具有以下通用形式:
target_link_libraries( … … …)
命名的 必须是由 add_executable() 或 add_library() 等命令创建的,且不能是 ALIAS 目标。如果策略 CMP0079 没有设置为 NEW,那么目标必须在当前目录中创建。对于相同的 ,重复调用将按照调用顺序追加项。
版本 3.13 中的新功能:不需要在与 target_link_libraries 调用相同的目录中定义 。
每个 可能是:
- 库目标名称:生成的链接行将具有与目标关联的可链接库文件的完整路径。如果库文件更改,构建系统将依赖于重新链接 。
命名目标必须由项目内的 add_library() 或作为 IMPORTED
库创建。如果在项目内创建,构建系统将自动添加排序依赖项,以确保在 链接之前命名的库目标是最新的。
如果导入的库具有 IMPORTED_NO_SONAME 目标属性,CMake
可能会要求链接器搜索库,而不是使用完整路径(例如,/usr/lib/libfoo.so 变为 -lfoo)。
目标的工件的完整路径将自动为 shell 进行引用/转义。
- 库文件的完整路径:生成的链接行通常会保留文件的完整路径。如果库文件更改,构建系统将依赖于重新链接 。
在某些情况下,CMake 可能会要求链接器搜索库(例如,/usr/lib/libfoo.so 变为 -lfoo),例如,当检测到共享库没有
SONAME 字段时。有关另一种情况的讨论,请参阅策略 CMP0060。
如果库文件位于 macOS 框架中,框架的 Headers 目录也将作为使用要求进行处理。这与将框架目录作为包含目录传递的效果相同。
版本 3.8 中的新功能:对于 VS 2010 及更高版本的 Visual Studio 生成器,以 .targets 结尾的库文件将被视为
MSBuild 目标文件,并导入到生成的项目文件中。其他生成器不支持此功能。
库文件的完整路径将自动为 shell 进行引用/转义。
- 纯库名称:生成的链接行将要求链接器搜索库(例如,foo 变为 -lfoo 或 foo.lib)。
库名称/标志被视为命令行字符串片段,将在没有额外引用或转义的情况下使用。
- 链接标志:以 - 开头的项目名称,但不是 -l 或 -framework,被视为链接器标志。请注意,这些标志将被视为传递依赖性目的任何其他库链接项,因此通常只能将它们指定为私有链接项,这些项不会传播到依赖项。
此处指定的链接标志将插入到链接库的链接命令中的相同位置。根据链接器的不同,这可能不正确。使用 LINK_OPTIONS 目标属性或
target_link_options() 命令显式添加链接标志。然后,链接命令中的标志将放在工具链定义的标志位置。
版本 3.13 中的新功能:LINK_OPTIONS 目标属性和 target_link_options() 命令。对于早期版本的
CMake,请改用 LINK_FLAGS 属性。
链接标志被视为命令行字符串片段,将在没有额外引用或转义的情况下使用。
生成器表达式:$<…> 生成器表达式可以计算为上述任何项,或者计算为以分号分隔的这些项列表。如果 … 包含任何 ; 字符,例如在评估 l i s t 变量之后,请确保使用显式引用参数 " {list} 变量之后,请确保使用显式引用参数 "list变量之后,请确保使用显式引用参数"<…>",以便此命令将其作为单个 接收。
此外,生成器表达式可用作上述任何项的片段,例如 foo$<1:_d>。
请注意,生成器表达式不会在策略 CMP0003 或策略 CMP0004 的旧处理中使用。
- 紧跟在另一个 后的 debug、optimized 或 general 关键字。紧跟在此类关键字后的项将仅用于相应的构建配置。debug 关键字对应于 Debug 配置(或者如果设置了 DEBUG_CONFIGURATIONS 全局属性,则对应于其中命名的配置)。optimized 关键字对应于所有其他配置。general 关键字对应于所有配置,纯粹是可选的。可以通过创建和链接到 IMPORTED 库目标来实现更高粒度的每个配置规则。这些关键字会被此命令立即解释,因此当由生成器表达式生成时没有特殊含义。
包含 :: 的项,例如 Foo::Bar,被认为是 IMPORTED 或 ALIAS 库目标名称,如果不存在此类目标,将引发错误。请参阅策略 CMP0028。
有关定义构建系统属性的更多信息,请参阅 cmake-buildsystem(7) 手册。
针对目标和/或其依赖项的库
target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
PUBLIC、PRIVATE 和 INTERFACE 范围关键字可用于在一个命令中指定链接依赖关系和链接接口。
紧跟在 PUBLIC 后的库和目标将被链接,并成为链接接口的一部分。紧跟在 PRIVATE
后的库和目标将被链接,但不会成为链接接口的一部分。紧跟在 INTERFACE 后的库将附加到链接接口,但不会用于链接 。
针对目标及其依赖项的库
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>...) • 1
LINK_INTERFACE_LIBRARIES 模式将库追加到 INTERFACE_LINK_LIBRARIES
目标属性,而不是用于链接。如果策略 CMP0022 不是 NEW,则此模式还将库追加到 LINK_INTERFACE_LIBRARIES
及其每个配置的等效项。
此签名仅用于兼容性。请改用 INTERFACE 模式。
指定为调试的库将在生成器表达式中包装,以对应调试构建。如果策略 CMP0022 不是 NEW,则库还将追加到
LINK_INTERFACE_LIBRARIES_DEBUG 属性(或者,如果已设置 DEBUG_CONFIGURATIONS
全局属性,则追加到列出的配置对应的属性)。指定为优化的库将追加到 INTERFACE_LINK_LIBRARIES 属性。如果策略
CMP0022 不是 NEW,它们还将追加到 LINK_INTERFACE_LIBRARIES
属性。指定为通用(或没有任何关键字)的库将被视为同时指定为调试和优化。
链接对象库
新版本 3.12。
对象库可以用作 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 属性中时,它们的对象文件也将包含在链接中。
通过 $ 链接对象库
新版本 3.21。
对象库相关的对象文件可以通过 $ 生成器表达式引用。这样的对象文件将在链接行的所有库之前放置,无论它们的相对顺序如何。此外,构建系统将添加一个排序依赖项,以确保在依赖目标链接之前对象库是最新的。例如,代码
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)
编译 use_obj3.c 时使用 -DOBJ3,创建包含 use_obj3.c 和 obj3.c 对象文件的可执行文件 use_obj3。
这也可以通过静态库传递。由于静态库不链接,因此它不会消耗以这种方式引用的对象库的对象文件。相反,对象文件成为静态库的传递链接依赖项。继续上面的示例,代码
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 编译,因为使用要求在静态库的私有依赖关系中不是传递性的。然而,静态库的链接依赖关系被传播,包括 iface_obj3 对 $ 的引用。可执行文件 use_static3 使用来自 use_static3.c 和 obj3.c 的对象文件创建,并链接到库 libstatic3.a。
在使用这种方法时,项目有责任避免将多个依赖二进制文件链接到 iface_obj3,因为它们的链接行都会得到 obj3 对象文件。
注意:在 target_link_libraries 调用中引用 $ 在 3.21 之前的 CMake 版本中对于某些情况是有效的,但不是完全支持的:
- 它没有将对象文件放在链接行的库前面。
- 它没有添加对对象库的排序依赖。
- 它在 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)
手册的创建可重定位软件包部分,以了解在创建用于重新分发的软件包时指定使用要求时需要采取的其他注意事项。