CMake系列讲解(入门篇)1.7 基础命令CMake-target_link_libraries()

news/2024/12/22 22:13:59 标签: CMake, c++, 编译, 软件工程

基础命令target_link_libraries()

〓〓〓〓〓〓〓〓踏实学CMake总目录〓〓〓〓〓〓〓〓〓〓


7. target_link_libraries

不想看理论的可以直接跳转7.3查看实际使用示例即可。

7.1 命令格式:

该命令用于用于将目标与所需的库进行链接。它用于指定一个目标(例如可执行文件或库)需要依赖的其他库,以便在构建过程中正确地链接这些库。该命令有多种使用方法,但他们都符合下面的命令格式

target_link_libraries(<target> ... <item>... ...)

7.2 参数说明

target:要链接库的目标

target必须是由add_executable()或add_library()等命令创建的,并且不能是ALIAS目标。
对同一target的重复调用按照调用的顺序追加项。

item:item可以是:

(1) 一个库目标的名称:

  当使用target_link_libraries命令将目标与库进行链接时,生成的链接行(link line)将包含与目标关联的可链接库文件的完整路径。这意味着构建系统将依赖于目标链接的库文件,如果库文件发生更改,将重新链接目标。
  链接的库必须是由项目中的add_library()创建或者作为导入库创建。如果是在项目中创建的,则会在构建系统中自动添加排序依赖项,以确保指定的库目标在被链接时是最新的

注:链接行(link line)指的是使用CMake最终生成的命令行,例如,当我们使用target_link_libraries链接名为myapp的可执行文件和名为mylib的库时,可能会生成类似以下形式的链接行:
g++ main.o -o myapp -L/path/to/lib -lmylib

注: 构建系统自动添加排序依赖项,指的是在构建项目时,当目标(例如可执行文件或库)依赖于其他目标(通常是库)时,构建系统会确保按正确的顺序构建这些目标,以满足依赖关系。比如:
add_library(mylib1 ...)
target_link_libraries(mylib2 PRIVATE mylib1)
add_executable(myapp ...)
target_link_libraries(myapp PRIVATE mylib2)
add_library(mylib2 ...)
在这个例子中,myapp可执行文件依赖于mylib2库,而mylib2库又依赖于mylib1库。由于存在这种依赖关系,构建系统会自动添加构建规则,确保在构建myapp可执行文件之前,先构建mylib2库,而在构建mylib2库之前,先构建mylib1库。

(2) 库文件的完整路径:

 生成的链接行通常会保留文件的完整路径。 如果库文件发生更改,构建系统将具有重新链接 target的依赖关系。

(3) 普通的库名称:

 生成的链接行将要求链接器搜索库(例如 foo 变为 -lfoo 或 foo.lib)。
库名称/标志被视为命令行字符串片段,并且将在没有额外引用或转义的情况下使用。具体来说就是库名称会被转换成链接器可以识别的格式。例如将库名"foo"转换为"-lfoo"或"foo.lib"。这样链接器就能够根据这个名称来搜索相应的库文件进行链接。

(4) 链接标志:

  以 - 开头但不是 -l 或 -framework 的item被视为链接器标志。 请注意,出于传递依赖性的目的,此类标志将像任何其他库链接项一样被对待,因此通常可以安全地将它们仅指定为不会传播到依赖项的私有链接项。

(5) 一个生成器表达式

生成器表达式是一种方便的语法,可以生成一系列项。生成器表达式可以产生的项的类型包括字符串、数字、文件名等。

(6) 构建配置的关键字

这些关键字往往后边紧跟着另外一个item,常见的关键字有debug、optimized和general等。

  • debug关键字对应于debug配置(如果设置了DEBUG_CONFIGURATIONS全局属性,则对应于DEBUG_CONFIGURATIONS中指定的配置)
  • optimized关键字对应于其他的所有配置
  • general关键字对应于所有配置,是可选的。

这些关键字由该命令立即解释,因此在生成器表达式生成时没有特殊含义。

7.3 使用示例

7.3.1 最常使用方式

target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

在这个命令中,可以使用PUBLIC、PRIVATE和INTERFACE这三个作用域关键字来指定链接的依赖项和链接接口

  • PUBLIC表示将指定的库或目标链接到目标,并将其作为链接接口的一部分。这意味着当其他目标链接到当前目标时,也会自动链接这些PUBLIC作用域的依赖项。这样的依赖项将被传递给依赖于当前目标的其他目标
  • PRIVATE表示将指定的库或目标链接到目标,但不将其作为链接接口的一部分。这意味着这些PRIVATE作用域的依赖项只会影响当前目标,而不会传递给依赖于当前目标的其他目标
  • INTERFACE表示将指定的库链接到链接接口,而不进行实际的链接操作。这意味着这些INTERFACE作用域的依赖项不会对当前目标产生影响,但会被传递给依赖于当前目标的其他目标这通常用于定义一组接口,以满足其他目标的特定要求。

具体可以为:

cmake_minimum_required(VERSION 3.5)
project(hello_library)
add_library(hello_library STATIC 
    src/Hello.cpp
)
target_include_directories(hello_library
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)
add_executable(hello_binary 
    src/main.cpp
)
# link the new hello_library target with the hello_binary target
target_link_libraries( hello_binary
    PRIVATE 
        hello_library
)

此例中将生成的hello_library库链接给名为hello_library的target,且作用域为PRIVATE,表示hello_library库只会被链接给hello_library这个target,如果还有其他target依赖hello_library这个target,hello_library库不会被链接给其他target。

7.3.2 不指定作用域

target_link_libraries(<target> <item>...)

根据这个命令的默认行为,库的依赖关系是传递的,即如果一个目标链接到了另一个目标,那么链接到这个目标的库也会出现在另一个目标的链接行中。

例如:假设你有两个目标:my_app和my_library。你想要将my_library链接到my_app中。

# 定义my_library目标
add_library(my_library STATIC my_library.cpp)
# 定义my_app目标,并将my_library链接到my_app中
add_executable(my_app main.cpp)
target_link_libraries(my_app my_library)

# 定义other_library目标
add_library(other_library STATIC other_library.cpp)
# 将other_library链接到my_library中
target_link_libraries(my_library other_library)
# 将my_library链接到my_app中
target_link_libraries(my_app my_library)

在此例中,先将my_library链接到了my_app中,接着又将other_library链接到了my_library,最后将my_library链接到了my_app,因此,当构建my_app时,my_app会链接到my_library和other_library,并将它们一起包含在最终的可执行文件中。

7.3.3 不推荐使用的其他形式

使用LINK_PRIVATE|LINK_PUBLIC指定作用域

target_link_libraries(<target>
                      <LINK_PRIVATE|LINK_PUBLIC> <lib>...
                     [<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...)

这种方式通过LINK_PRIVATE或者LINK_PUBLIC指定作用域,但不推荐使用此方式,推荐使用PUBLIC和PRIVATE,即上文第一种方式。

使用LINK_INTERFACE_LIBRARIES指定作用域

target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...)

这种方式通过LINK_INTERFACE_LIBRARIES 指定作用域,但不推荐使用此方式,推荐使用INTERFACE,即上文第一种方式。


附:返回总目录的传送门如下:

〓〓〓〓〓〓〓〓踏实学CMake总目录〓〓〓〓〓〓〓〓〓〓


http://www.niftyadmin.cn/n/5054056.html

相关文章

AI智能视频监控技术如何助力美好乡村建设?

随着城市化发展&#xff0c;很多乡村设施也在逐渐完善&#xff0c;智能监控也成了乡村发展必不可少的一环&#xff0c;智能视频监控应该在乡村建设里如何发挥作用呢&#xff1f; 1、有效提升安全意识 通过在乡村重要区域、公共场所、道路等设置智能视频监控设备&#xff0c;可…

spring 2.2.9源码构建注意事项

这里第一点是 grable的构建总失败&#xff0c;所以把pom中的这个模块删除&#xff0c;同时我也把这个工程删除了。 还有是pom里加一个插件的标签它的意思大概是忽略一个下载的东西那个也总是导致失败&#xff01; 还就是编译maven编译时的jdk版本和实际运行时的差别不要差别太…

《数据结构、算法与应用C++语言描述》-栈的应用-列车车厢重排问题

列车车厢重排问题 一列货运列车有 n 节车厢&#xff0c;每节车厢要停靠在不同的车站。假设 n个车站从 1 到n 编号&#xff0c;而且货运列车按照从n到1的顺序经过车站。车厢的编号与它们要停靠的车站编号相同。为了便于从列车上卸掉相应的车厢&#xff0c;必须按照从前至后、从…

Sui流动性质押黑客松入围项目公布

经过40多天积极的报名以及精心的选拔&#xff0c;Sui流动性质押黑客松现已完成对所有报名项目的筛选&#xff0c;最终入围名单也在众人的期待中新鲜出炉。两个赛道各六支队伍成功晋级黑客松的Demo Day&#xff0c;让我们来认识一下他们&#xff1a; 入围名单 流动性质押协议 …

扫描转换椭圆与圆的绘制

扫描转换椭圆与圆的绘制 前提 我们先来设计一种数据类型 class Point{ public:double x,y;Point(){this->x 0; this->y 0;}Point(double x, double y){this->xx;this->yy;} };注意此处的类型为double这一点很重要&#xff0c;因为在某些迭代过程中设置为int会…

cocos2dx查看版本号的方法

打开文件&#xff1a;项目根目录\frameworks\cocos2d-x\docs\RELEASE_NOTES.md 知道引擎版本号的意义&#xff1a; 1.面试中经常被问到(面试官想知道你会不会查版本号&#xff0c;你会查也不一定会去看&#xff0c;如果你去看了说明你是一个有心人&#xff0c;或者想深入研究下…

机器人中的数值优化|【六】线性共轭梯度法,牛顿共轭梯度法

机器人中的数值优化|【六】线性共轭梯度法&#xff0c;牛顿共轭梯度法 往期回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化…

IP地址定位的特点

IP地址定位是一种广泛应用于网络领域的技术&#xff0c;它允许我们确定特定设备或用户在互联网上的位置。这项技术在很多方面都具有重要的特点&#xff0c;本文将深入探讨这些特点。 1.全球性覆盖&#xff1a; IP地址定位IP66_ip归属地在线查询_免费ip查询_ip精准定位平台具有全…