一. 简介
前一篇文章简单介绍了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,否则执行源码时会报错。