CMakeLists.txt语法规则:部分常用命令说明四

一. 简介

前面几篇文章学习了CMakeLists.txt语法中前面几篇文章学习了CMakeLists.txt语法中部分常用命令。文章如下:

CMakeLists.txt语法规则:部分常用命令说明一-CSDN博客

CMakeLists.txt语法规则:部分常用命令说明二-CSDN博客

CMakeLists.txt语法规则:部分常用命令说明三-CSDN博客

本文继续学习 CMakeLists.txt语法中两个常用命令:target_include_directories命令 和 target_link_libraries命令。

二. CMakeLists.txt语法规则:部分常用命令

target_include_directories 命令为指定目标设置头文件搜索路径。
target_link_libraries 命令为指定目标设置链接库文件。
这听起来跟 include_directories 和 link_libraries 命令有着相同的作用,确实如此,它们的 功能的确相同,但是在一些细节方面却有不同。
target_include_directories 和 target_link_libraries 命令定义如下所示:

target_include_directories(<target> [SYSTEM] [BEFORE]
 <INTERFACE|PUBLIC|PRIVATE> [items1...]
 [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

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

这俩命令都有一个相同的参数 <target> 目标,这个目标指的就是譬如 add_executable 、 add_library 命令所创建的目标。
首 先 对 于 target_include_directories 命 令 来 说 , SYSTEM 、 BEFORE 这 两 个 选 项 与
include_directories 命令中 SYSTEM 、 BEFORE 选项的意义相同。
如果使用 SYSTEM 选项,会把指定目录当成系统的搜索目录。 通过 BEFORE 选项可显式指定添加到列表的前面。

我们重点关注的是 INTERFACE|PUBLIC|PRIVATE 这三个选项有何不同?
通过一个示例向大家说明,譬如工程目录结构如下所示:

调用关系:

根据以上工程,我们对 INTERFACE 、 PUBLIC 、 PRIVATE 三个关键字进行说明:
PRIVATE 私有的。
main.c 程序调用了 libhello_world.so 。生成 libhello_world.so 时,只在 hello_world.c 中包含了 hello.h , libhello_world.so 对外的头文件: hello_world.h 头文件中不包含 hello.h 。
而且 main.c 不会调用 hello.c 中的函数,或者说 main.c 不知道 hello.c 的存在,它只知道 libhello_world.so 的存在;
那么在 hello_world/CMakeLists.txt 中应该写入:

target_link_libraries(hello_world PRIVATE hello)
target_include_directories(hello_world PRIVATE hello)

INTERFACE 接口。
生成 libhello_world.so 时,只在 libhello_world.so 对外的头文件: hello_world.h 文件 中包含了 hello.h , hello_world.c 中不包含 hello.h ,即 libhello_world.so 不使用 libhello.so 提供的功能,但是 main.c 需要使用 libhello.so 中的功能。
那么在 hello_world/CMakeLists.txt 中应该写入:

target_link_libraries(hello-world INTERFACE hello)
target_include_directories(hello-world INTERFACE hello)

PUBLIC 公开的。
PUBLIC = PRIVATE + INTERFACE 。生成 libhello_world.so 时,在 hello_world.c 和 hello_world.h 中 都 包 含 了 hello.h 。 并 且 main.c 中 也 需 要 使 用 libhello.so 提 供 的 功 能 。
那 么 在 hello_world/CMakeLists.txt 中应该写入:

target_link_libraries(hello-world PUBLIC hello)
target_include_directories(hello-world PUBLIC hello)

对于 target_include_directories命令 来说,这些关键字用于指示 何时 需要传递给目标的 包含目录列表 ,指定了 包含目录列表 的使用范围( scope ):
⚫ 当使用 PRIVATE 关键字修饰时,意味着 包含目录列表 仅用于当前目标;
⚫ 当使用 INTERFACE 关键字修饰时,意味着 包含目录列表 不用于当前目标、只能用于依赖该目标的其它目标,也就是说 cmake 会将 包含目录列表 传递给当前目标的依赖目标;
⚫ 当使用 PUBLIC 关键字修饰时,这就是以上两个的集合, 包含目录列表 既用于当前目标、也会传递给当前目标的依赖目标。

对于 target_link_libraries命令 亦是如此,只不过 包含目录列表 换成了 链接库列表 。 譬如:
target_link_libraries(hello_world INTERFACE hello)
表示目标 hello_world 不需要链接 hello 库,但是对 于 hello_world 目标的依赖目标(依赖于 hello_world 的目标)它们需要链接 hello 库。
以上便是对 INTERFACE、PUBLIC、PRIVATE 这三个关键字的概括性理解,所以整出这几个关键 字主要还是为了控制包含目录列表或链接库列表的使用范围,这就是 target_include_directories、
target_link_libraries 命令与 include_directories、link_libraries 命令的不同之处。
target_include_directories() 功能与 target_link_libraries()的功能完全可以使用 include_directories()、link_libraries()来实现。
但是笔者强烈建议大家使用 target_include_directories()和 target_link_libraries()。为什么?保持清晰!
include_directories() 、 link_libraries() 是针对当前源码中的所有目标,并且还会向下传递(譬如通过 add_subdirectory 加载子源码时,也会将其传递给子源码)。
在一个大的工程当中,这通常不规范、有时还 会编译出现错误、混乱,所以我们应尽量使用 target_include_directories() 和 target_link_libraries() ,保持整个 工程的目录清晰。

下一篇文章继续学习 CMakeLists.txt语法的一个常用命令: message命令。

相关推荐
Zfox_24 分钟前
【Linux】进程信号全攻略(二)
linux·运维·c语言·c++
安於宿命28 分钟前
【Linux】简易版shell
linux·运维·服务器
黄小耶@40 分钟前
linux常见命令
linux·运维·服务器
叫我龙翔41 分钟前
【计网】实现reactor反应堆模型 --- 框架搭建
linux·运维·网络
古驿幽情43 分钟前
CentOS AppStream 8 手动更新 yum源
linux·运维·centos·yum
BillKu44 分钟前
Linux(CentOS)安装 Nginx
linux·运维·nginx·centos
BillKu1 小时前
Linux(CentOS)yum update -y 事故
linux·运维·centos
a266378961 小时前
解决yum命令报错“Could not resolve host: mirrorlist.centos.org
linux·运维·centos
2739920292 小时前
Ubuntu20.04 安装build-essential问题
linux
wowocpp5 小时前
查看 linux ubuntu 分区 和 挂载 情况 lsblk
linux·运维·ubuntu