cmake
https://cmake.org/cmake/help/v3.18/manual/cmake.1.html
概要
Generate a Project Buildsystem
cmake [\<options\>] \<path-to-source\>
cmake [\<options\>] \<path-to-existing-build\>
cmake [\<options\>] -S \<path-to-source\> -B \<path-to-build\>
Build a Project
cmake --build \<dir\> [\<options\>] [-- \<build-tool-options\>]
Install a Project
cmake --install \<dir\> [\<options\>]
Open a Project
cmake --open \<dir\>
Run a Script
cmake [{-D \<var\>=\<value\>}...] -P \<cmake-script-file\>
Run a Command-Line Tool
cmake -E \<command\> [\<options\>]
Run the Find-Package Tool
cmake --find-package [\<options\>]
View Help
cmake --help[-\<topic\>]
介绍
cmake可执行文件是一个命令行跨平台构建系统生成器的接口。上面概要介绍的各种各样的命令将会在下面详细介绍。
使用cmake编译一个软件工程,需要构建一个编译系统。选择使用cmake构建工程,安装工程或者仅仅运行相应的构建工具(比如make)。cmake可以使用帮助来了解如何使用。
另一个目的,软件开发者想要的,写一个cmake语言的脚本来支持自己的编译。
图形化的接口可以代替使用cmake,参考ccmake和cmake-gui。cmake测试和打包工具可以参考ctest和cpack。
更多cmake的信息,查看底部手册的链接。
cmake编译系统的入门
编译系统描述了如何编译一个项目的可执行文件和类库,从他的源码,使用编译工具自动完成。比如,一个编译系统可以是makefile,可以使用make工具的命令行或是一个集成开发环境(IED)的工程文件。为了避免包含多个编译系统,一个工程可以抽象的定义一个cmake编译系统。通过这些文件,cmake可以根据底层的构建器构建本地适合的编译系统。
为了使用cmake构建编译系统,如下的内容必须有:
源码树
最高层次的目录必须包含工程的源码。工程通过cmake-language手册中介绍的文件定义编译系统。最外层目录必须包含CMakeLists.txt文件。这个文件介绍了编译的目标和依赖的环境,这些介绍在cmake-buildsystem(7)手册中。
编译树
最外层目录包含编译系统的文件和编译的输出结果,比如可执行文件或者类库。cmake将会写入一个CMakeCache.txt文件,用来定义这个目录是编译树,并且把编译系统配置选项的信息持久化。
为了保持持久化的源码树,请使用分开的专用的编译树来执行超脱于源码的编译。同样支持在同一源码内的编译,把编译树与源码树放到一起,但是这不建议。
构建
选择一种编译系统构建。查看cmake-generators(7)手册了解所有的构建器。运行cmake --help,查看本地支持的构建器。使用-G选项定义一个构建器或是接收cmake在当前平台上默认选择的构建器。
当使用一个命令行的构建工具,cmake需要环境变量中有需要的编译工具链。如果使用IDE,就不需要对应的环境变量了。
构建一个工程编译系统
运行下面的命令行表达式来定义源码树,编译树和生成编译系统:
cmake [<options>] <path-to-source>
用当前的目录作为编译树,<path-to-source>作为源码树。定义的目录可以是绝对路径也可以是对于当前目录的相对路径。源码树必须包含CMakeLists.txt并且不能包含CMakeCache.txt,因为后者标明了一个现有的编译树。比如:
$ mkdir build ; cd build
$ cmake ../src
cmake [<options>] <path-to-existing-build>
使用<path-to-existing-build>作为编译树,从CMakeCache.txt文件加载源码树,必须一开始使用前面的命令运行过cmake。目录必须是绝对路径或是相对于当前目录的相对路径,比如:
$ cd build
$ cmake .
cmake [<options>] -S <path-to-source> -B <path-to-build>
使用<path-to-build>作为编译树,<path-to-source>作为源码树。定义的路径可以使绝对路径也可以是相对路径。源码树必须包含CMakeLists.txt。编译树如果没有,将会自动创建。比如:
$ cmake -S src -B build
所有的<options>都可以是0或者有如下的设置。
构建完成编译系统后,可以使用本地合适的编译工具来编译工程,比如使用Unix的Makefiles构建器:
$ make
$ make install
或者,可以使用选择本地合适的编译工具来构建工程。
选项
-S <path-to-source>
要编译的cmake工程的根目录
-B <path-to-build>
cmake用作编译的根目录。如果目录不存在,就创建一个。
-C <initial-cache>
预加载一个脚本用作缓存。
当cmake第一次运行在一个空的编译树时,会创建一个CMakeCache.txt文件,写入项目可定制的选项。这个设置可以用作在加载缓存条目时,定义一个文件,在第一次传入工程cmake文件列表的时候。这个加载的条目比工程默认值权限高。这个给定的文件,应该使用camke的脚本,包含set()命令使用CACHE设置,而不是cache-format文件。
在脚本中CMAKE_SOURCE_DIR和CMAKE_BINARY_DIR的引用会作为源码和编译树的最顶层。
-D <var>:<type>=<value>, -D <var>=<value>
创建或是更新CMake CACHE的条目
当cmake第一次运行与一个空的编译树,会创建CMakeCache.txt文件并且填充工程中可配置的设置。这些设置可能被用作定义一个高于工程默认值的选项。对于渴望越来越多的缓存条目,这些选项可能会重复。
如果:<type>已经被设置,那么必须是set()命令中为它的缓存签名的其中一项。如果:<type>的部分已经丢失了,那么就会创建一个没有类型的数据,如果也没有存在一个类型。如果一个工程合集中的命令设置了PATH或者FILEPATH的内容,那么<value>将会被绝对路径覆盖。
这个选项同样可以通过一条语句设置:-D<var>:<type>=<value> or -D<var>=<value>.
-U <globbing_expr>
从CMake CACHE删除匹配的数据。
这个选项用作从CMakeCache.txt文件中删除一条或多条数据,全局表达式可以使用*和?。这个选项可能会重复。
使用这个方法,可以使你的CMakeCache.txt不工作
-G <generator-name>
定义一个编译系统的构建器。
cmake支持多种本地的当前平台的构建系统。构建器的目的是为了生成编译系统。可用的构建器的名字在cmake-generators(7)手册中定义了。
如果没有声明,cmake就会检查CMAKE_GENERATOR环境变量,否则按照默认的选项构建。
-T <toolset-spec>
如果支持,定义构建器的工具集合。
有些cmake构建器支持定义一个工具集合告诉本地编译系统如何选择编译器。查看CMAKE_GENERATOR_TOOLSET获得更详细信息。
-A <platform-name>
定义构建器支持的平台名称。
有些cmake构建器支持指定平台名称给本地的编译系统,用来选择编译器和sdk。查看CMAKE_GENERATOR_PLATFORM获取更多信息。
-Wno-dev
禁止开发者的警告信息。
禁止的警告信息就是针对CMakeLists.txt文件作者的警告。默认情况下,也会关闭弃用警告。
-Wdev
打开开发者警告。
打开开发者警告就是针对CMakeLists.txt文件作者的警告。默认情况下也会打开弃用警告。
-Werror=dev
对开发者发出警告作为报错。
对开发这发出警告就是对CMakeLists.txt文件作者的报错。默认情况下也会打开弃用警告作为报错。
-Wno-error=dev
使开发者的警告不是报错。
表示CMakeLists.txt文件的作者的警告不是报错。默认情况下也会关闭弃用警告作为报错。
-Wdeprecated
开启废弃函数警告。用作CMakeLists.txt文件。
-Wno-deprecated
禁止废弃函数警告,用作CMakeLists.txt文件。
-Werror=deprecated
使废弃宏和函数的警告作为错误。用作CMakeLists.txt。
-Wno-error=deprecated
不把废弃宏和函数的警告作为错误。用作CMakeLists.txt文件。
-L[A][H]
列出非高级的缓存变量。
将会列出所有的cmake缓存中的非INTERNAL或ADVANCED的变量。对于打印当前的cmake设置非常有效,可以通过-D更改。更改一些变量将会导致更多的变量创建。如果A已经定义了,那么就会打印高级变量。如果H已经定义了,就会打印帮助信息。
-N
查看模式,仅仅加载缓存,并不运行配置和构建的步骤。
--graphviz=[file]
构建图形相关依赖,查看CMakeGraphVizOptions获得更多信息。
构建图形输入文件,将会包含所有的类库和可执行文件
--system-information [file]
输出关于系统的信息。如果在类库树的顶层运行,那么也会打印额外的信息,比如缓存、日志文件等。
--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>
设置日志的等级。
message()命令智慧打印比设定的等级一样或是更高的日志,默认是STATUS。
为了设置日志等级在cmake运行时有效,需要设置CMAKE_MESSAGE_LOG_LEVEL作为缓存的变量。如果命令行和变量都指定了,那么命令行的优先级高。
为了底层的兼容性,--loglevel这个同义词也可以接受。
--log-context
允许message()命令行打印每个消息的上下文信息。
这个设置知识打开当前运行的cmake的上下文信息。如果想永久的展示所有子序列的上下文信息,需要设置CMAKE_MESSAGE_CONTEXT_SHOW,当命令行指定后CMAKE_MESSAGE_CONTEXT_SHOW会被忽略。
--debug-trycompile
不删除try_compile()编译树,仅仅使用一个try_compile()在同一时间。
不删除文件和文件夹在创建try_compile()的时候。在调试try_compiles的时候非常有用。可能会更改结果,把try-compiles修改成前面try-compile的旧垃圾,这样导致测试失败或是成功,不确定。这个设置最好是仅仅在调试的时候用,每次使用一个。
--debug-output
是cmake运行在调试模式。打印额外的信息,就相当于cmake运行在SEND_ERROR消息下的堆栈跟踪。
--debug-find
使cmake在查找命令行的时候运行在调试模式,可以打印更多的查找调用信息的调试模式下的标准错误。输出内容被格式化为方便阅读的,但是不是解析。查看CMAKE_FIND_DEBUG_MODE参数用来调试更多的本地工程部分。
--trace
使cmake运行在trace模式,打印所有的调用执行和从哪里来。
--trace-expand
使cmake在trace模式,与--trace类似,只不过包含了变量的扩展信息。
--trace-format=<format>
使cmake在trace模式,并且设置输出格式。
<format>可以是如下值:
human
打印每一行内容用可读的格式,这是默认值。
json-v1
打印每一行内容用json格式。每一个新文件都用换行符分隔。在json内部没有换行符。如下:
{
"file": "/full/path/to/the/CMake/file.txt",
"line": 0,
"cmd": "add_executable",
"args": ["foo", "bar"],
"time": 1579512535.9687231,
"frame": 2
}
成员有:
file
cmake运行的源文件地址。
line
函数调用的文件中第几行
cmd
当前调用的函数名
args
所有的参数
time
系统调用的时间戳
frame
堆栈调用的深度
除此之外,第一个json文档输出包含了版本信息
{
"version": {
"major": 1,
"minor": 0
}
}
包含了version字段,有major和minor内容。
--trace-source=<file>
使cmake在跟踪模式,但只输出指定文件的行。多个设置可以接受。
--trace-redirect=<file>
使cmake在跟踪模式,并且重定向输出为file,而不是stderr
--warn-uninitialized
提醒没有初始化的变量。当没有初始化的变量使用时,警告。
--warn-unused-vars
提醒没有使用的变量。查找定义或是设置的变量,但是没有使用。
--no-warn-unused-cli
不警告命令行的设置。不查找在命令行中定义了但是没有使用的设置。
--check-system-vars
查找在系统文件中使用有问题的变量。
正常情况系,不使用或是没初始化的变量仅仅在CMAKE_SOURCE_DIR和CMAKE_BINARY_DIR中查找,这个设置告诉cmake在其他文件中查找。
--profiling-output=<path>
使用--profiling-format为给定的输出目录
--profiling-format=<file>
开启输出分析数据,由cmake提供的格式。
可以用于分析cmake脚本的执行。第三方程序需要输出可读的格式。
目前只支持:骨骼跟踪的输出格式,可以通过google chrome或是使用插件进行分析。
编译一个工程
cmake提供了命令行的表达式用作编译一个已经构建的工程二进制树:
cmake --build \<dir\> [\<options\>] [-- \<build-tool-options\>]
这个抽象了一个本地的编译工具的命令行接口,可以有如下设置:
--build <dir>
工程需要编译的二进制目录。这个是必须的,并且必须是第一个
--parallel [<jobs>], -j [<jobs>]
当前可用的最大内核数,如果<jobs>没有,就使用默认值。
CMAKE_BUILD_PARALLEL_LEVEL环境变量,如果设置了,定义一个默认的平行等级,当设置没有赋值时。
有些本地的编译工具一直都使用平行的。设置<jobs>为1可以限制使用一个工作。
--target <tgt>..., -t <tgt>...
编译<tgt>替换默认是目标。可以设置多个,用空格隔开。
--config <cfg>
对于多个配置工具,选择配置文件<cfg>
--clean-first
先清理然后再编译,如果仅仅清理,使用--target clean
--use-stderr
忽略。行为默认在CMake >= 3.0
--verbose, -v
允许详细的输出,如果支持的话,包括编译命令
如果VERBOSE环境变量或是CMAKE_VERBOSE_MAKEFILE缓存设置了,这个参数就被忽略。
--
传递保存的设置给本地的工具
运行cmake --编译,不附带任何设置
安装
cmake提供了命令行表达式用于安装已经构建的工程的二进制树
cmake --install \<dir\> [\<options\>]
当不使用构建系统或是本地编译工具编译工程的时候,可以使用这个编译工程,然后安装。设置是:
--install <dir>
工程二进制文件的安装目录,这个必须需要,并且是第一个
--config <cfg>
多个配置的构建器,选择配置<cfg>
--component <comp>
组件形式的安装,仅仅安装对应组件<comp>
--prefix <prefix>
覆盖安装前缀CMAKE_INSTALL_PREFIX
--strip
在安装之前卸载
-v, --verbose
允许详细信息输出。
如果VERBOSE设置了,这个参数就被忽略
运行cmake --install进行安装,不附带任何设置。
打开工程
cmake --open \<dir\>
用相关的程序打开构建的工程,这个只支持一些构建器。
运行脚本
cmake [{-D \<var\>=\<value\>}...] -P \<cmake-script-file\> [-- \<unparsed-options\>...]
把提供的cmake文件当作一个脚本写入到cmake语言中。没有设置和构建步骤执行,没有缓存修改。如果参数用-D定义,必须用-P进行结束。
任何--后面的设置都不会北cmake解析,但是它会被引用到CMAKE_ARGV<n>中传递给脚本,包括--自己。
运行命令行工具
cmake提供了内置的命令行表达式
cmake -E \<command\> [\<options\>]
运行cmake -E或者cmake -E help来链接命令,有效的命令是:
capabilities
通过json格式输出cmake的功能,包含如下格式:
version
json结构体的版本信息,包含如下关键字:
string
cmake --version展示的全部的版本信息
major
主版本信息
minor
次版本信息
patch
补丁的层次
suffix
cmake版本的前缀
isDirty
bool类型标明cmake编译的是否是一个污染的树
generators
列出可能的构建器。每一个构建器都是一个json结构体,包含如下关键字:
name
构建器的名字
toolsetSupport
如果构建器支持toolset,就是true
platformSupport
如果构建器支持平台,就是true
extraGenerators
列出所有扩展的构建器,使用同一个构建器兼容的。
fileApi
可选的成员,当cmake-file-api(7)可用时出现,包含一个成员:
requests
一个json数组,包含零个或是多个支持的file-api请求,每一个是一个json结构体,包含如下成员:
kind
定义一个支持的结构体特征
version
版本信息
serverMode
如果支持server-mode就是true
cat <files>...
连接文件并且打印到标准输出上。
chdir <dir> <cmd> [<arg>...]
切换当前的目录,并且运行命令
compare_files [--ignore-eol] <file1> <file2>
检测文件<file1>与<file2>是否相同,相同返回0,不同返回1。--ignore-eol定义了智能换行对比,忽略LF/CRLF的不同。
copy <file>... <destination>
拷贝文件到<destination> (可以是目录,也可以是文件)。如果多个文件定义了,<destination>必须是目录,并且必须存在。通配符不支持。拷贝跟踪符号链接。也就是不拷贝符号链接,但是拷贝符号链接指向的目录或是文件。
copy_directory <dir>... <destination>
拷贝<dir>的内容到<destination>文件夹。如果<destination>不存在,就创建一个。copy_directory跟踪符号链接
copy_if_different <file>... <destination>
如果修改了,拷贝文件到<destination> (文件或文件夹)。如果多个文件指定了,<destination>必须是目录并且必须存在。copy_if_different跟踪符号链接
create_symlink <old> <new>
从<old>创建一个新的<new>的符号链接
注意 <new>符号链接将要创建的目录,必须存在
echo [<string>...]
显示参数为文本
echo_append [<string>...]
显示参数为文本,在同一行
env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...
使用修改的环境变量运行命令。
environment
显示当前的环境变量
false
什么都不做,退出返回1
make_directory <dir>...
创建目录,如果需要,也会创建父目录,如果存在,则忽略
md5sum <file>...
使用md5sum兼容的格式创建文件的md5 checksum
351abe79cd3800b38cdfb25d45015a15 file1.txt
052f86c15bbde68af55c7f7b340ab639 file2.txt
sha1sum <file>...
使用sha1sum兼容的格式创建sha1 checksum
4bb7932a29e6f73c97bb9272f2bdc393122f86e0 file1.txt
1df4c8f318665f9a5f2ed38f55adadb7ef9f559c file2.txt
sha224sum <file>...
使用sha224sum兼容的格式创建sha224 checksum
b9b9346bc8437bbda630b0b7ddfc5ea9ca157546dbbf4c613192f930 file1.txt
6dfbe55f4d2edc5fe5c9197bca51ceaaf824e48eba0cc453088aee24 file2.txt
sha256sum <file>...
使用sha256sum兼容的格式创建sha256 checksum
76713b23615d31680afeb0e9efe94d47d3d4229191198bb46d7485f9cb191acc file1.txt
15b682ead6c12dedb1baf91231e1e89cfc7974b3787c1e2e01b986bffadae0ea file2.txt
sha384sum <file>...
使用sha384sum兼容的格式创建sha384 checksum
acc049fedc091a22f5f2ce39a43b9057fd93c910e9afd76a6411a28a8f2b8a12c73d7129e292f94fc0329c309df49434 file1.txt
668ddeb108710d271ee21c0f3acbd6a7517e2b78f9181c6a2ff3b8943af92b0195dcb7cce48aa3e17893173c0a39e23d file2.txt
sha512sum <file>...
使用sha512sum兼容的格式创建sha512 checksum
2a78d7a6c5328cfb1467c63beac8ff21794213901eaadafd48e7800289afbc08e5fb3e86aa31116c945ee3d7bf2a6194489ec6101051083d1108defc8e1dba89 file1.txt
7a0b54896fe5e70cca6dd643ad6f672614b189bf26f8153061c4d219474b05dad08c4e729af9f4b009f1a1a280cb625454bf587c690f4617c27e3aebdf3b7a2d file2.txt
remove [-f] <file>...
从3.17开始不建议使用。
删除文件。如果任何列出的文件不存在了,就返回非零的代码退出,但是没有日志。-f设置修改行为为退出附带零的代码。remove不跟踪符号链接。也就是仅仅删除符号链接,而不删除符号链接指定的文件。
这个实现有很多bug并且经常返回0。如果不破坏向后兼容性就无法修复它。使用rm替换吧。
remove_directory <dir>...
从3.17版本开始废弃。
删除<dir>目录和目录下的内容。如果目录不存在,会被忽略。如果是一个符号链接,仅仅删除链接。使用rm替换。
rename <oldname> <newname>
重命名文件或文件夹(在同一个卷内)。如果<newname>已经存在,会直接覆盖。
rm [-rRf] <file> <dir>...
删除文件<file>或文件夹<dir>。使用-r或-R删除文件夹和其里面的内容。如果任何一个files/directories列表中的内容不存在,命令会返回一个非零值,然后退出,并且没有日志。-f参数强制使返回值为零(比如成功)在这种情况。
server
运行cmake-server(7)模式
sleep <number>...
休眠number的秒钟。
tar [cxt][vf][zjJ] file.tar [<options>] [--] [<pathname>...]
创建或解压一个tar或zip包,参数是:
- c
创建一个文档。<pathname>...参数是强制的。
- x
从文档中解压到硬盘。<pathname>...可以在仅仅解压选中的文件或文件夹的时候使用。如果解压选中的文件或文件夹,必须提供解压的名字和目录。-t可以打印
- t
列出文档内容。<pathname>...可以用作仅仅列出选中的文件和文件夹
- v
提供详细的信息学。
- z
使用gzip压缩文档
- j
使用bzip2压缩文档。
- J
使用xz压缩文档。
- --zstd
使用Zstandard压缩文档。
- --files-from=<file>
读出给定文件的每一行。空行忽略。每行内容可能不以-开头,除非--add-file=<name>增加了以-开头
- --format=<format>
定义创建文档的格式。支持的有7zip, gnutar, pax, paxr (restricted pax, default), and zip
- --mtime=<date>
定义记录到tarball目录的修改时间。
停止解析参数,并且把所有的保留的参数都当作文件名,即使以-开头
time <command> [<args>...]
运行命令并且记录过去的时间
touch <file>...
如果<file>不存在,就创建一个,如果<file>存在,就更改访问和修改的时间
touch_nocreate <file>...
如果存在就创建一个,否则跳过。
true
什么都不做,退出,返回0
windows下定义的命令行工具
下面的这些在cmake -E后面的参数只在windows下有效:
delete_regv <key>
删除windows的注册表的key
env_vs8_wince <sdkname>
显示设置到环境中,有windows CE sdk在vs2005中提供的批处理
env_vs9_wince <sdkname>
显示有安装vs2008提供的windows CESDK设置的环境变量的批处理
write_regv <key> <value>
写入注册表值
运行查找打包工具
cmake提供了pkg-config,想makefile基础工程的帮助
cmake --find-package [<options>]
通过find_package()查找包,并且输出结果标志到stdout。这个可以替换pkg-config来查找安装的类库在makefile基础的工程中或是autoconf基础的工程中(通过share/aclocal/cmake.m4)
注意
这个模式由于一些限制,并不是很好的支持。保持只是为了兼容,并不建议在新工程中使用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏