简介
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake, 只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows [Visual C++](https://baike.baidu.com/item/Visual C%2B%2B/1811800) 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件.
使用
CMake的所有的语句都写在一个叫:CMakeLists.txt的文件中。当CMakeLists.txt文件确定后,可以用ccmake命令对相关 的变量值进行配置。这个命令必须指向CMakeLists.txt所在的目录。配置完成之后,应用cmake命令生成相应的makefile(在Unix like系统下)或者 project文件(指定用window下的相应编程工具编译时)。
具体的操作流程:
- $> ccmake directory
- $> cmake directory
- $> make
其中directory为CMakeList.txt所在目录;
- 第一条语句用于配置编译选项,如VTK_DIR目录 ,一般这一步不需要配置,直接执行第二条语句即可,但当出现错误时,这里就需要认为配置了,这一步才真正派上用场;
- 第二条命令用于根据CMakeLists.txt生成Makefile文件;
- 第三条命令用于执行Makefile文件,编译程序,生成可执行文件;
生成Buildsytem
Cmake是一个生成 生成项目文件的工具, Cmakelists就是生成 生成项目文件的文件, 这个生成项目文件就是Build System.
不同的系统的build tool是不一样的, Cmake会根据平台的不同选择默认的build tool,也可以自己设置,
命令行为
$ cmake .. -G Ninja
GUI设置过程为官网上说
The “Configure” button triggers a new dialog to select the CMake generator to use
但是我试了一下有点奇怪, 直接生成了, 没有弹出对话框.
设置Build Variables
常见内部变量
| Variable | Meaning |
|---|---|
CMAKE_PREFIX_PATH |
Path to search for [dependent packages](https://cmake.org/cmake/help/v3.22/guide/using-dependencies/index.html#guide:Using Dependencies Guide) |
CMAKE_MODULE_PATH |
Path to search for additional CMake modules |
CMAKE_BUILD_TYPE |
Build configuration, such as Debug or Release, determining debug/optimization flags. This is only relevant for single-configuration buildsystems such as Makefile and Ninja. Multi-configuration buildsystems such as those for Visual Studio and Xcode ignore this setting. |
CMAKE_INSTALL_PREFIX |
Location to install the software to with the install build target |
CMAKE_TOOLCHAIN_FILE |
File containing cross-compiling data such as toolchains and sysroots. |
BUILD_SHARED_LIBS |
Whether to build shared instead of static libraries for add_library() commands used without a type |
CMAKE_EXPORT_COMPILE_COMMANDS |
Generate a compile_commands.json file for use with clang-based tools |
其它的特殊变量也许是用于构建系统, 通常禁止或者允许项目的组件.
CMAKE_开头的是 Cmake 自己提供的变量, 其它人应该使用自己的前缀, cmake-gui 可以识别出这些变量,比如 biogears:

内置变量的使用
- 在CMakeLists.txt中指定,使用set
- cmake命令中使用,如cmake -DBUILD_SHARED_LIBS=OFF
命令行参数
-G可以重写 Cmake 默认的 generater , 使用cmake --help可以本机支持的 generator:
$ cmake .. -G Ninja
-A是可以选择目标平台的体系结构,比如:
cmake .. -G "Visual Studio 2019" -A x64
cmake .. -G "Visual Studio 16" -A ARM
cmake .. -G "Visual Studio 16 2019" -A ARM64
-T可以选择Visual Studio的工具集:
$ # Build with the clang-cl toolset
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T ClangCL
$ # Build targeting Windows XP
$ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp
-D可以设置变量值
$ mkdir build
$ cd build
$ cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug
-U重置变量的值,比如
$ cd build
$ cmake . -UMyPackage_DIR
Cmake Cache
当首次执行时,CMake在包含键值对的构建目录中生成CMAKECACHE.TXT文件。可以通过运行cmake-gui(1) or ccmake(1) 工具来查看或编辑缓存文件。该工具提供了一个交互式界面,用于重新配置提供的软件并重新生成构建系统,如在编辑缓存值后所需的那样。每个缓存条目都可以具有关联的简短帮助文本,该文本显示在用户界面工具中。
Presets(预设参数)
Cmake识别CMakePresets.json和用户自定义的CMakeUserPresets.json来定义预定义参数,预定义参数列表, 这些都可以被用户自定义的参数覆盖,比如一个CMakePresets.json样例:
{
"version": 1,
"configurePresets": [
{
"name": "ninja-release",
"binaryDir": "${sourceDir}/build/${presetName}",
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
]
}
然后运行
cmake -S /path/to/source --preset=ninja-release
就可以在/path/to/source/build/ninja-release用Ninja生成一个build目录。
用下面这条语句可以列出所有的可用presets:
cmake -S /path/to/source --list-presets
这条语句会列出可以哦那个prests在/path/to/source/CMakePresets.json and /path/to/source/CMakeUsersPresets.json without generating a build tree.
Invoking the Buildsystem
在生成buildsystem后,软件可以通过调用特殊的build tool的方法被构建。在IDE生成器的情况下,这可能涉及将生成的项目文件加载到IDE中以调用构建。
而cmake也知道用命令行构建是常用的, 下面的命令可以在build目录调用用于生成buildsystem或者project.
$ cmake --build .
--build打开一个cmake tool的特殊模式, 它调用了generator的 CMAKE_MAKE_PROGRAM命令.或者是用户自定义配置指定的build tool.
--build也接收--target参数来指定特殊的目标来构建, 例如一个库, 执行文件或者自定义的目标就像install:
$ cmake --build . --target myexe
--build也接收--config参数用来在multi-config generators中指定某个配置来build:
$ cmake --build . --target myexe --config Release
--config参数在cmake时使用CMAKE_BUILD_TYPE时没有任何作用.
--verbose可以忽略提示信息:
$ cmake --build . --target myexe --verbose
--build还可以通过--提供更多的参数比如让cmake在失败时继续运行.
对于所有生成器,可以在调用CMake后运行底层构建工具。例如,可以在使用unix makefiles生成器生成之后执行,以在使用ninja生成器等生成后调用构建或ninja等。IDE构建系统通常提供用于构建也可以调用的项目的命令行工具。
Selecting a Target
每一个可执行文件和库文件在Cmake files都是一个 build taget, buildsystem也可以描述根据用户需求自定义的目标,比如生成一个文档.
Cmake提供了一些内置的build targets:
allThe default target used by
MakefileandNinjagenerators. Builds all targets in the buildsystem, except those which are excluded by theirEXCLUDE_FROM_ALLtarget property orEXCLUDE_FROM_ALLdirectory property. The nameALL_BUILDis used for this purpose for the Xcode and Visual Studio generators.helpLists the targets available for build. This target is available when using the [
Unix Makefiles](https://cmake.org/cmake/help/v3.22/generator/Unix Makefiles.html#generator:Unix Makefiles) orNinjagenerator, and the exact output is tool-specific.cleanDelete built object files and other output files. The
Makefilebased generators create acleantarget per directory, so that an individual directory can be cleaned. TheNinjatool provides its own granular-t cleansystem.testRuns tests. This target is only automatically available if the CMake files provide CTest-based tests. See also Running Tests.
installInstalls the software. This target is only automatically available if the software defines install rules with the
install()command. See also Software Installation.packageCreates a binary package. This target is only automatically available if the CMake files provide CPack-based packages.
package_sourceCreates a source package. This target is only automatically available if the CMake files provide CPack-based packages.
基于Makefile的系统也同样提供了build-targets来预处理, 汇编, 编译文件:
$ make foo.cpp.i
$ make foo.cpp.s
$ make foo.cpp.o
也提供了这种
$ make foo.i
$ make foo.s
$ make foo.o
Specifying a Build Program
CMAKE_MAKE_PROGRAM设置的模式可以用--build来被调用, 对于更多的generator, 特殊的程序不需要被配置,一些常见的Generator对应的make program:
| Generator | Default make program | Alternatives |
|---|---|---|
| XCode | xcodebuild |
|
| Unix Makefiles | make |
|
| NMake Makefiles | nmake |
jom |
| NMake Makefiles JOM | jom |
nmake |
| MinGW Makefiles | mingw32-make |
|
| MSYS Makefiles | make |
|
| Ninja | ninja |
|
| Visual Studio | msbuild |
|
| Watcom WMake | wmake |
Software Installation
CMAKE_INSTALL_PREFIX可以在Cmake cache中设置为在哪里安装软件,如果软件有特殊的安装目录需求, 用install()命令可以用上面那个参数的安装路径, Windows默认的安装路径是ProgramFiles, Unix是/usr/local.
The CMAKE_INSTALL_PREFIX变量永远指向target filesystem 的installation prefix.
下面的命令:
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_SYSROOT=$HOME/root \
-DCMAKE_STAGING_PREFIX=/tmp/package
$ cmake --build .
$ cmake --build . --target install
会在目标机器安装 /tmp/package/lib/libfoo.so,目标机器的/usr/local不会被影响.
一些软件会提供uninstall规则, 但是Cmake默认不提供.
Running Tests
Cmake自带的ctest(1)工具可以提供测试和报告结果,虽然test的build-target可以运行所有可用的tests,但是ctest允许granular控制哪个tests可以运行, 如何运行, 如何报告结果.执行ctest命令在build directory里面是这样的:
$ ctest
使用正则表达式可以用来告诉运行哪些tests, 比如运行Qt的 tests 就可以这样:
$ctest -R Qt
也可以指定名字:
$ ctest -E Qt
也可以用-j参数指定并行线程数
$ ctest -R Qt -j8
环境变量中的CTEST_PARALLEL_LEVEL就可以用-j来代替.
默认的ctest不打印tests的输出, -v或者--verbose打印所有输出,--output-on-failure打印只报错的信息.设置CTEST_OUTPUT_ON_FAILURE为1可以用来代替--output-on-failure这个参数.
欢迎在评论区中进行批评指正,转载请注明来源,如涉及侵权,请联系作者删除。