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

一. 简介

前一篇文章简单介绍了CMakeLists.txt 简单的语法。文章如下:

CMakeLists.txt 简单的语法介绍-CSDN博客

接下来对 CMakeLists.txt语法规则进行具体的学习。本文具体学习 CMakeLists.txt语法规则中常用的命令。

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

cmake 提 供 了 很 多 命 令 , 每 一 个 命 令 都 有 它 自 己 的 功 能 、 作 用 , 通 过 这 个 链 接 地 址 :

复制代码
https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html

可以查询到所有的命令及其相应的介绍、使用方法等等,如下所示:

大家可以把这个链接地址保存起来,可以把它当成字典的形式在有需要的时候进行查询,由于命令非常多,笔者不可能将所有命令都给大家介绍一遍。
这里给大家介绍一些基本的命令,如下表所示:

|----------------------------|-------------------------------|
| command | 说明 |
| cmake_minimum_required | 设置 cmake 的最低版本号要求 |
| add_executable | 可执行程序目标 |
| add_library | 库文件目标 |
| add_subdirectory | 去指定目录中寻找新的 CMakeLists.txt 文件 |
| aux_source_directory | 收集目录中的文件名并赋值给变量 |
| get_target_property | 获取目标的属性 |
| include_directories | 设置所有目标头文件的搜索路径,相当于 gcc 的-I 选项 |
| link_directories | 设置所有目标库文件的搜索路径,相当于 gcc 的-L 选项 |
| link_libraries | 设置所有目标需要链接的库 |
| list | 列表相关的操作 |
| message | 用于打印、输出信息 |
| project | 设置工程名字 |
| set | 设置变量 |
| set_target_properties | 设置目标属性 |
| target_include_directories | 设置指定目标头文件的搜索路径 |
| target_link_libraries | 设置指定目标库文件的搜索路径 |
| target_sources | 设置指定目标所需的源文件 |

2. CMakeLists.txt 语法的部分常用命令

接下来详细地给大家介绍每一个命令。

(1) add_executable

add_executable 命令用于添加一个可执行程序目标,并设置目标所需的源文件,该命令定义如下所示:

复制代码
add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...]) 

该命令提供了一些可选参数,这些可选参数的含义笔者就不多说了,通常不需要加入,具体的含义大家可以自己查看 cmake 官方文档( https://cmake.org/cmake/help/v3.5/command/add_executable.html );只需传入 目标名和对应的源文件即可,譬如:

复制代码
#生成可执行文件 hello
add_executable(hello 1.c 2.c 3.c)

定义了一个可执行程序目标 hello ,生成该目标文件所需的源文件为 1.c 、 2.c 和 3.c 。需要注意的是,源 文件路径既可以使用相对路径、也可以使用绝对路径,相对路径被解释为相对于当前源码路径(注意,这里 源码指的是 CMakeLists.txt 文件,因为 CMakeLists.txt 被称为 cmake 的源码,若无特别说明,后续将沿用这 个概念!)。

(2) add_library

add_library 命令用于添加一个库文件目标,并设置目标所需的源文件,该命令定义如下所示:

复制代码
add_library(<name> [STATIC | SHARED | MODULE]
 [EXCLUDE_FROM_ALL]
 source1 [source2 ...])

第一个参数 name 指定目标的名字,参数 source1...source2 对应源文件列表; add_library 命令默认生成的库文件是静态库文件,通过 SHARED 选项可使其生成动态库文件。
具体的使用方法如下:

复制代码
#生成静态库文件 libmylib.a
add_library(mylib STATIC 1.c 2.c 3.c)

#生成动态库文件 libmylib.so
add_library(mylib SHARED 1.c 2.c 3.c)

与 add_executable 命令相同, add_library 命令中源文件既可以使用相对路径指定、也可以使用绝对路径指定,相对路径被解释为相对于当前源码路径。
不管是 add_executable 、还是 add_library ,它们所定义的目标名在整个工程中必须是唯一的,不可出现 两个目标名相同的目标。

(3) add_subdirectory

add_subdirectory 命令告诉 cmake 去指定的目录中寻找源码并执行它,有点像 Makefile 的 include ,其定 义如下所示:

复制代码
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

参数 source_dir 指定一个目录,告诉 cmake 去该目录下寻找 CMakeLists.txt 文件并执行它;
参数 binary_dir 指定了一个路径,该路径作为子源码(调用 add_subdirectory 命令的源码称为当前源码或父源码,被执行的 源码称为子源码)的输出文件( cmake 命令所产生的中间文件)目录, binary_dir 参数是一个可选参数,如 果没有显式指定,则会使用一个默认的输出文件目录;
为了后续便于表述,我们将输出文件目录称为 BINARY_DIR。
譬如工程目录结构如下所示:

顶层 CMakeLists.txt 文件内容如下所示:

复制代码
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
# 告诉 cmake 去 src 目录下寻找 CMakeLists.txt
add_subdirectory(src)

src 目录下的 CMakeLists.txt 文件:

复制代码
# src 下的 CMakeLists.txt
add_executable(hello main.c)

进入到 build 目录下,执行 cmake 、 make 进行构建编译;
在本例中,顶层源码对应的输出文件会存放在 build 目录,也就是执行 cmake 命令所在目录;子源码( src 目录下的 CMakeLists.txt )对应的输出文件会存 放在 build/src 目录,包括生成的可执行文件默认会与这些中间文件放置在同一个目录,如下所示:

复制代码
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── Makefile
│ └── src
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── hello
│ └── Makefile
├── CMakeLists.txt
└── src
 ├── CMakeLists.txt
 └── main.c

所以由此可知,当前源码调用 add_subdirectory 命令执行子源码时,若没有为子源码指定 BINARY_DIR ,默认情况下,会在当前源码的 BINARY_DIR 中创建与子目录(子源码所在目录)同名的文件夹,将其作为 子源码的 BINARY_DIR 。

接下来我们修改顶层 CMakeCache.txt 文件:

复制代码
# 顶层 CMakeLists.txt
cmake_minimum_required("VERSION" "3.5")
project("HELLO")
# 告诉 cmake 去 src 目录下寻找 CMakeLists.txt
add_subdirectory(src output)

指定子源码的 BINARY_DIR 为 output ,这里使用的是相对路径方式。
add_subdirectory **命令对于相对路径的解释为:**相对于当前源码的 BINARY_DIR ;
修改完成之后,再次进入到 build 目录下执行 cmake 、 make 命令进行构建、编译,此时会在 build 目录下生成一个 output 目录,这就是子源码的 BINARY_DIR 。
设置 BINARY_DIR 可以使用相对路径、也可以是绝对路径,相对路径则是相对于当前源码的
BINARY_DIR,并不是当前源码路径,这个要理解。
通过 add_subdirectory 命令加载、执行一个外部文件夹中的源码,既可以是当前源码路径的子目录、也可以是与当前源码路径平级的目录亦或者是当前源码路径上级目录等等;
对于当前源码路径的子目录,不强制调用者显式指定子源码的 BINARY_DIR;
如果不是当前源码路径的子目录,则需要调用者显式指定 BINARY_DIR,否则执行源码时会报错。

相关推荐
dishugj6 小时前
【linux】Redhat 6.3系统安装zabbix-agent软件包,无法使用YUM源问题
linux·运维·zabbix
无奈笑天下6 小时前
【麒麟镜像vmtools异常排查指导书】
linux·运维·经验分享·云计算·kylin
Xの哲學7 小时前
Linux多级时间轮:高精度定时器的艺术与科学
linux·服务器·网络·算法·边缘计算
QT 小鲜肉7 小时前
【Linux命令大全】001.文件管理之mmove命令(实操篇)
linux·服务器·前端·chrome·笔记
Winner13007 小时前
查看rk3566摄像头设备、能力、支持格式
linux·网络·人工智能
QT 小鲜肉8 小时前
【Linux命令大全】001.文件管理之mdel命令(实操篇)
linux·运维·服务器·chrome·笔记
大聪明-PLUS8 小时前
如何从零开始开发 Linux 驱动程序
linux·嵌入式·arm·smarc
物随心转9 小时前
input子系统工作原理
linux
一只旭宝9 小时前
Linux专题六:进程替换详解加五种进程间通讯方式(套接字放到tcp通信编程上讲述)
linux
开压路机9 小时前
Linux的基本指令
linux·服务器