chapter01 - basic
三个 stages:配置、生成、构建。
配置会生成 CMakeCache。生成是用它去生成 build tree 的其他内容。
Generating a Build System
生成 build tree:
cmake -B build/ -S source/
最好不要使用无参数的 cmake。
选择生成器:
cmake -G <generator>
也可以使用环境变量 CMAKE_GENERATOR
。但是要注意大小写:
CMAKE_GENERATOR=Ninja cmake -B build
对一个已经指定了生成器的 build tree 设置新的 CMAKE_GENERATOR
并重新配置是无效的,这个时候环境变量会背忽略。而使用 -G
指定则提示有冲突。
指定 cache:
cmake -C <dir-of-CMakeCache.txt>
cmake 会先读 cache 再去进行接下来的配置。
cmake -L[A][H] <path-to-source>
:在配置的时候还会列举出配置。
(py310) xxx /data/modern-cmake/examples/chapter01/01-hello $ cmake -B build -L
-- Configuring done
-- Generating done
-- Build files have been written to: /data/modern-cmake/examples/chapter01/01-hello/build
-- Cache values
CMAKE_BUILD_TYPE:STRING=
CMAKE_INSTALL_PREFIX:PATH=/usr/local
可以看到当前有两个选项可以通过 cache 或者命令行的 -D
选项更改。
-A
使得被标记为 ADVANCED 的变量也被列出。
-D 用来定义变量,-U 用来移除变量。
cmake --system-information
用来打印系统信息。
--log-level
指定日志等级。
--log-context
可以提供更多信息,比如调用栈。
CMakePresets.json
一个用来提供预设配置的文件。命令行 优先于 预设配置 优先于 环境变量 优先于 默认值。
相关命令:
cmake --list-presets
cmake --preset=<preset>
Building
cmake --build <dir> -- <build-tool-options>
用 make 的时候加 -j
会好一点,而用 ninja 不要加。ninja 自动选择的并行数似乎是比当前的处理器数量略大一些的,但是我也不清楚是多少。CMAKE_BUILD_PARALLEL_LEVEL
环境变量也能设置并发数。
在构建的时候 -t
/--target
都能用于指定目标。多个目标就重复 -t A -t B
。特殊目标有:
- clean 用于清理项目
先清理再构建:
cmake --build build/ --clean-first
多配置
有的生成器支持多配置:Ninja Multi-Config, Xcode, Visual Studio。
这样就不必在配置阶段通过 -DCMAKE_BUILD_TYPE=Release
指定好配置,而是在编译阶段通过 --config
传入配置(默认还是 Debug)。
export CMAKE_GENERATOR="Ninja Multi-Config"
cmake -B build
cmake --build build/ --config Debug
cmake --build build/ --config Release
# 再编译一次 Debug,提示:ninja: no work to do. 说明之前的编译结果得以保留
cmake --build build/ --config Debug
对于 Ninja Multi-Config:
如果在 add_executable
之前有 set(CMAKE_EXPORT_COMPILE_COMMANDS on)
,那么导出的 compile_commands.json 会同时包含多个配置下的文件生成方式。看起来可能有点问题,但实际上基本不影响正常工作。
https://gitlab.kitware.com/cmake/cmake/-/issues/23733
上面有人合并了新代码尝试解决这个问题,但是过去了一年现在最新的 3.28.1 仍然是生成了多份配置。
虽然 CMake 一共有 4 种配置,但是 Ninja Multi-Config 只能生成 Debug/Release/RelWithDebInfo。
Installing
略。
Scripting
可以创建独立脚本。
cmake [{-D <var>=<value>}...] -P <cmake-script-file> [-- <options>...]
参数被放在 CMAKE_ARGV1
, CMAKE_ARGV2
, … 里。需要自己用 CMAKE_ARGC
作字符串插值。而且不只是 --
之后的参数,连 cmake 这条语句本身的所有参数都会占用位置,比如 cmake
, -P
, some.cmake
也都会分别占据 CMAKE_ARGV0
, CMAKE_ARGV1
, CMAKE_ARGV2
。
When running scripts, CMake won’t execute any of the usual stages (such as configurationor generation), and it won’t use the cache.
由于没有 build tree 和 source tree 的概念,相关的变量值会变成当前的工作路径。
即便是脚本也应该有 cmake_minimum_required(VERSION 3.20.0)
这样类似的版本说明。
CMake command-line tool mode
cmake -E
可以运行 cmake 内置的命令,这些命令跨平台。支持的命令有 copy、cat、chdir 之类的。可以用 cmake -E capabilities
查看。
Navigating the project files
- source tree
- build tree/build root/binary tree
- listfiles – 推荐命名 CMakeLists.txt 或 xxx.cmake
CMakeCache.txt 中有:
########################
# EXTERNAL cache entries
########################
这一段是可以由用户修改的,不会被重新配置清理。实测 internal cache 也可以被修改,但是不会保证正确性。
配置文件
<PackageName>-config.cmake
或者 <PackageName>Config.cmake
配置文件可以暴露一些 cmake 宏以方便用户使用。
用 find_package 去找包。
<Config>Version.cmake
用来表明当前包的版本。
如果一个包的提供者没有给出 Config-file,则不能用 find_package,得用 Find-modules 来代替。Find-modules 会去找相关的系统路径,从而找出对编译有帮助的变量。举例:FindCURL
就是 Find-module。
模块
CMake 自带一些模块,可以用 include 来包含,比如 include(TestBigEndian)
cmake 其实自带大小端相关的变量。