Linux 系统中,CMake 是一个跨平台的自动化构建系统,它通过 CMakeLists.txt 文件描述项目的构建规则,并生成适用于特定平台和编译器的 Makefile 或项目文件,掌握 CMake 命令行的使用对于项目的编译、管理和分发至关重要,以下将详细介绍 CMake 命令行的核心功能、常用参数、构建流程及实践技巧。

CMake 基础命令与构建流程
CMake 的使用通常分为三个主要阶段:配置(Configure)、生成(Generate)和构建(Build),每个阶段对应不同的命令和操作。
配置阶段(cmake)
配置阶段是 CMake 的核心,它会读取 CMakeLists.txt 文件,并根据用户指定的参数(如编译器、安装路径等)生成构建系统所需的配置文件,基本语法为:
cmake [选项] <路径>
<路径> 通常指向包含 CMakeLists.txt 的源目录(source directory)或一个空的构建目录(build directory),推荐的做法是创建一个独立的构建目录,以保持源码的整洁。
常用选项:

-S <source_dir>:指定源目录路径,如果未提供,默认为当前目录。-B <build_dir>:指定构建目录路径,如果未提供,默认为当前目录。-DCMAKE_BUILD_TYPE=<type>:设置构建类型,常见的有Debug(调试,包含调试信息,不优化)、Release(发布,开启优化,不包含调试信息)、RelWithDebInfo(发布调试,包含调试信息并开启优化)和MinSizeRel(最小体积发布,最高优化)。-DCMAKE_BUILD_TYPE=Release。-DCMAKE_C_COMPILER=<compiler>:指定 C 编译器,如/usr/bin/gcc或clang。-DCMAKE_CXX_COMPILER=<compiler>:指定 C++ 编译器,如/usr/bin/g++或clang++。-DCMAKE_INSTALL_PREFIX=<path>:指定项目的安装路径。-DCMAKE_INSTALL_PREFIX=/usr/local。-G <generator>:指定构建系统的生成器,在 Linux 上,默认通常是Unix Makefiles,也可以指定Ninja(需要安装 ninja)以获得更快的增量构建速度。
示例:
假设项目源码在 ~/my_project/src,我们希望在 ~/my_project/build 目录下进行构建。
mkdir -p ~/my_project/build cd ~/my_project/build cmake -S ~/my_project/src -B . -DCMAKE_BUILD_TYPE=Release
执行后,CMake 会在 build 目录下生成 Makefile(或其他构建文件)。
生成阶段
在较新版本的 CMake(3.13+)中,-S 和 -B 选项使得配置和生成可以一步完成,如果使用旧版本,可能需要先进入构建目录,然后运行 cmake <path_to_source> 来进行配置和生成,这一步的核心作用是根据 CMakeLists.txt 和用户选项,将高级的项目描述转换为底层的构建规则文件。
构建阶段
生成构建文件后,即可使用构建工具(如 make、ninja)进行编译和链接,CMake 提供了便捷的封装命令 cmake --build,可以自动调用正确的构建工具。

cmake --build <build_dir> [选项]
常用选项:
--config <config>:对于多配置生成器(如 Visual Studio),指定构建配置,Linux 上通常不需要。--target <target>:指定要构建的目标(target),可以是可执行文件、静态库、动态库或自定义目标,默认构建所有目标。-- -j <N>:传递参数给底层构建工具,用于并行编译。N是并行任务数,通常设置为 CPU 核心数加一,如-- -j8。--clean-first:在构建前先执行清理操作(等同于make clean)。
示例:
在 build 目录下构建所有目标,使用 8 个并行任务:
cmake --build . -- -j8
构建名为 my_app 的可执行文件:
cmake --build . --target my_app
CMake 高级命令与选项
除了基础的构建流程,CMake 命令行还提供了一些高级功能,用于更精细地控制构建过程。
预设和配置文件
对于复杂项目,每次在命令行输入大量参数会很繁琐,CMake 引入了 CMakePresets.json 和 CMakeUserPresets.json 文件,用于预设构建配置,用户可以定义多个预设,然后通过 cmake --preset <preset_name> 来快速应用。
依赖管理工具
CMake 可以与外部依赖管理工具集成,如 Conan、vcpkg 等,通过 find_package 命令,CMake 可以查找这些工具管理的依赖库,使用 vcpkg 时,可以通过设置 CMAKE_TOOLCHAIN_FILE 指向 vcpkg 的工具链文件:
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake
打包与安装
项目构建完成后,通常需要打包或安装,CMake 提供了 cmake --install 命令来执行安装步骤。
cmake --install <build_dir> [选项]
常用选项:
--prefix <prefix>:覆盖 CMakeLists.txt 中设置的安装前缀。--component <component>:只安装指定的组件。
示例:
将项目安装到 /usr/local:
cmake --install build --prefix /usr/local
CMake 常用命令速查表
为了方便查阅,以下是一些核心 CMake 命令和选项的总结:
| 命令/选项 | 描述 |
|---|---|
cmake -S <src> -B <build> |
在 <src> 目录配置,并在 <build> 目录生成构建文件。 |
cmake -DCMAKE_BUILD_TYPE=Release |
设置构建类型为 Release。 |
cmake -DCMAKE_C_COMPILER=clang |
指定 C 编译器为 clang。 |
cmake -G "Ninja" |
使用 Ninja 作为构建系统生成器。 |
cmake --build . |
在当前构建目录执行构建。 |
cmake --build . --target my_lib |
构建名为 my_lib 的特定目标。 |
cmake --build . -- -j8 |
使用 8 个并行任务进行构建。 |
cmake --install . --prefix /usr/local |
将当前构建目录下的项目安装到 /usr/local。 |
实践技巧
- 保持构建目录独立:始终在源码树之外创建构建目录,这有助于避免污染源码,并且可以轻松切换不同的构建配置(如 Debug 和 Release)。
- 利用 CCache 加速编译:安装 ccache 并配置 CMake 使用它,可以显著缩短重复编译的时间,通过设置
CCACHE=ON或在 CMake 中设置CMAKE_CXX_COMPILER_LAUNCHER=ccache来启用。 - 使用
target_compile_features:在 CMakeLists.txt 中,使用target_compile_features来指定 C++ 标准(如cxx_std_17),而不是依赖编译器标志,这样可以更好地保证跨平台兼容性。 - 检查 CMake 版本:在 CMakeLists.txt 文件开头使用
cmake_minimum_required(VERSION 3.10)来确保项目所需的最低 CMake 版本,避免因版本过低导致的问题。
相关问答 FAQs
问题 1:CMake 中 add_executable 和 add_library 有什么区别?如何选择使用?
解答:add_executable 和 add_library 是 CMake 中定义构建目标的核心命令,它们的主要区别在于生成的最终产物类型和用途。
add_executable:用于创建一个可执行文件,这是程序的入口点,可以直接运行,一个命令行工具或一个游戏的主程序,一个项目通常至少有一个可执行文件目标。add_library:用于创建一个库文件,可以是静态库(.a文件)或动态库(.so文件),库包含一组可被其他程序或库重复使用的函数和类,当你有一段希望被多个项目复用的代码,或者想将一个大型项目分解为多个模块时,就应该使用库。
选择使用:
- 如果你的模块是最终用户可以直接运行的程序,使用
add_executable。 - 如果你的模块包含的是可复用的组件、工具函数或类,并且希望其他项目可以链接它,使用
add_library,即使是一个单一的可执行文件项目,如果代码量很大,也可以将其拆分为多个库和一个主可执行文件,以提高模块化和可维护性。
问题 2:如何解决 CMake 找不到依赖库(如 Boost 或 OpenSSL)的问题?
解答:CMake 找不到依赖库通常是因为 find_package 命令无法定位库的安装位置,解决方法主要有以下几种:
- 安装开发包:确保已经安装了依赖库的开发包,在基于 Debian/Ubuntu 的系统上,安装 OpenSSL 的开发包需要运行
sudo apt-get install libssl-dev,而不是仅仅安装openssl,开发包包含了头文件(.h)和用于链接的库文件(.a或.so)。 - 设置
CMAKE_PREFIX_PATH:如果库安装在非标准路径(如/usr/local/boost_1_78_0),可以通过-DCMAKE_PREFIX_PATH告诉 CMake 在哪里查找。cmake -DCMAKE_PREFIX_PATH=/path/to/boost .,CMake 会在该路径下寻找lib/cmake/、share/cmake/或lib/等目录。 - 设置
PKG_CONFIG_PATH:对于遵循 pkg-config 规范的库(如大多数 GTK、Qt 库),可以设置PKG_CONFIG_PATH环境变量,指向.pc文件所在的目录,CMake 的find_package在某些情况下会自动使用 pkg-config。 - 手动指定路径:
find_package仍然失败,可以使用include_directories和target_link_libraries手动指定头文件目录和库文件路径,这是一种不推荐的做法,因为它降低了跨平台性,但在紧急情况下是可行的。include_directories(/path/to/boost/include) target_link_libraries(my_target /path/to/boost/lib/libboost_system.a)
- 使用工具链文件:对于交叉编译或复杂的依赖环境,可以编写一个工具链文件(
.cmake),在其中定义所有依赖库的路径和查找逻辑,然后通过-DCMAKE_TOOLCHAIN_FILE引用它。
