2、Cmake使用教程
约 4416 字大约 15 分钟
2025-03-03
编写者:bugcode
本文已完成并校对
CMake 命令完全使用教程
目录
- CMake 简介
- 安装 CMake
- CMake 命令基础
- 配置项目
- 构建项目
- 安装项目
- CMake 脚本模式
- CMake 预设 (Presets)
- CMake 命令行工具
- CMake 环境变量
- CMake 与包管理器集成
- 高级用法
- 调试和故障排除
- 完整实战项目
1. CMake 简介
CMake 是一个跨平台的开源构建系统生成器。它不直接构建项目,而是生成特定平台的原生构建文件(如 Makefile、Ninja 文件、Visual Studio 解决方案等)。
1.1 CMake 工作流程
CMakeLists.txt (项目描述)
↓
cmake 命令 (配置)
↓
原生构建文件 (Makefile, .sln, ...)
↓
cmake --build (构建)
↓
可执行文件/库2. 安装 CMake
2.1 Linux
# Ubuntu/Debian
sudo apt update
sudo apt install cmake
# CentOS/RHEL/Fedora
sudo yum install cmake
# 或
sudo dnf install cmake
# 从源码安装最新版本
wget https://github.com/Kitware/CMake/releases/download/v3.27.0/cmake-3.27.0.tar.gz
tar -xzvf cmake-3.27.0.tar.gz
cd cmake-3.27.0
./bootstrap
make -j$(nproc)
sudo make install2.2 macOS
# 使用 Homebrew
brew install cmake
# 使用 MacPorts
sudo port install cmake2.3 Windows
# 下载安装程序
# 访问 https://cmake.org/download/ 下载 .msi 安装包
# 使用 Chocolatey
choco install cmake
# 使用 winget
winget install Kitware.CMake2.4 验证安装
# 查看版本
cmake --version
# 查看安装路径
which cmake # Linux/macOS
where cmake # Windows3. CMake 命令基础
3.1 命令语法
cmake [<选项>] <源码路径>
cmake [<选项>] <现有构建路径>
cmake [<选项>] -S <源码路径> -B <构建路径>3.2 查看帮助
# 基本帮助
cmake --help
# 查看特定命令的帮助
cmake --help-command add_executable
# 查看所有命令列表
cmake --help-command-list
# 查看模块帮助
cmake --help-module FindOpenCV
# 查看属性帮助
cmake --help-property TARGET_NAME
# 查看变量帮助
cmake --help-variable CMAKE_CXX_COMPILER
# 查看生成器帮助
cmake --help-generators4. 配置项目
4.1 基本配置
# 最简单的配置(在当前目录)
cmake .
# 源码外构建(推荐)
mkdir build && cd build
cmake ..
# 使用 -B 和 -S 选项(CMake 3.13+)
cmake -B build -S .4.2 指定生成器
# 列出所有可用生成器
cmake --help
# Unix Makefiles(默认在 Linux/macOS)
cmake -G "Unix Makefiles" ..
# Ninja(快速构建)
cmake -G Ninja ..
# Visual Studio 2022(Windows)
cmake -G "Visual Studio 17 2022" -A x64 ..
cmake -G "Visual Studio 17 2022" -A Win32 ..
cmake -G "Visual Studio 17 2022" -A ARM64 ..
# Visual Studio 2019
cmake -G "Visual Studio 16 2019" -A x64 ..
# Xcode(macOS)
cmake -G Xcode ..
# MinGW Makefiles(Windows + MinGW)
cmake -G "MinGW Makefiles" ..
# MSYS Makefiles
cmake -G "MSYS Makefiles" ..
# Eclipse CDT4 项目文件
cmake -G "Eclipse CDT4 - Unix Makefiles" -DCMAKE_ECLIPSE_VERSION=4.5 ..4.3 设置缓存变量
# 设置构建类型
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
cmake -DCMAKE_BUILD_TYPE=MinSizeRel ..
# 设置安装前缀
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
cmake -DCMAKE_INSTALL_PREFIX=$HOME/local ..
# 设置编译器
cmake -DCMAKE_C_COMPILER=gcc-11 ..
cmake -DCMAKE_CXX_COMPILER=g++-11 ..
cmake -DCMAKE_C_COMPILER=clang ..
cmake -DCMAKE_CXX_COMPILER=clang++ ..
# 设置编译选项
cmake -DCMAKE_C_FLAGS="-Wall -Wextra" ..
cmake -DCMAKE_CXX_FLAGS="-std=c++17 -O2" ..
# 启用/禁用功能
cmake -DBUILD_SHARED_LIBS=ON ..
cmake -DBUILD_TESTING=OFF ..
cmake -DUSE_OPENMP=ON ..
# 生成编译数据库(供 clangd、clang-tidy 等工具使用)
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
# 设置多个变量
cmake -B build -S . \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER=g++-11 \
-DBUILD_TESTING=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON4.4 使用工具链文件
# 交叉编译 ARM
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/arm-linux-gnueabihf.cmake ..
# 使用 vcpkg 工具链
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake ..
# 使用 conan 工具链
cmake -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake ..
# 使用 Android NDK
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-21 \
..
# 使用 iOS 工具链
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/ios.toolchain.cmake \
-DIOS_PLATFORM=OS \
..4.5 查找包路径
# 指定包的查找路径
cmake -DCMAKE_PREFIX_PATH=/custom/install/prefix ..
# 指定多个路径
cmake -DCMAKE_PREFIX_PATH="/opt/qt;/opt/boost" ..
# 指定查找根路径
cmake -DCMAKE_FIND_ROOT_PATH=/sysroot ..
# 指定库路径
cmake -DCMAKE_LIBRARY_PATH=/custom/lib ..
# 指定包含路径
cmake -DCMAKE_INCLUDE_PATH=/custom/include ..4.6 配置选项的高级用法
# 查看所有可配置的变量
cmake -LA .. # 简单列表
cmake -LAH .. # 带帮助的列表
# 强制重新配置
cmake --fresh ..
# 调试模式
cmake --debug-output ..
cmake --trace .. # 跟踪所有 CMake 调用
cmake --trace-expand .. # 展开变量后跟踪
# 指定警告级别
cmake -Wno-dev .. # 关闭开发者警告
cmake -Werror=dev .. # 将开发者警告视为错误
cmake -Wdeprecated .. # 显示弃用警告5. 构建项目
5.1 基本构建
# 在构建目录中
cmake --build .
# 指定构建目录
cmake --build build
# 指定构建配置(用于多配置生成器)
cmake --build . --config Release
cmake --build . --config Debug
# 并行构建
cmake --build . -j 4 # 使用4个核心
cmake --build . -j $(nproc) # Linux: 使用所有核心
cmake --build . -j %NUMBER_OF_PROCESSORS% # Windows
# 详细输出
cmake --build . --verbose5.2 构建特定目标
# 列出所有可构建的目标
cmake --build . --target help
# 构建特定目标
cmake --build . --target myapp
cmake --build . --target mylib
# 构建所有目标
cmake --build . --target all
# 清理构建
cmake --build . --target clean
# 重新构建(清理后构建)
cmake --build . --target rebuild_cache
# 安装
cmake --build . --target install
# 测试
cmake --build . --target test
# 生成文档
cmake --build . --target docs5.3 传递原生构建工具参数
# 传递给 Make
cmake --build . -- -j8
# 传递给 Ninja
cmake --build . -- -j8 -v
# 传递给 MSBuild
cmake --build . -- /m:4 /verbosity:minimal6. 安装项目
6.1 基本安装
# 从构建目录安装
cd build
cmake --install .
# 指定安装目录
cmake --install . --prefix /usr/local
# 指定组件安装
cmake --install . --component runtime
cmake --install . --component development6.2 使用 DESTDIR
# Linux/macOS
DESTDIR=/tmp/staging cmake --install .
# Windows
set DESTDIR=C:\staging
cmake --install .7. CMake 脚本模式
7.1 运行 CMake 脚本
# 运行脚本文件
cmake -P script.cmake
# 传递参数给脚本
cmake -DINPUT=value -P script.cmake7.2 脚本示例
# script.cmake
cmake_minimum_required(VERSION 3.10)
# 输出信息
message(STATUS "Hello from CMake script!")
message(STATUS "INPUT = ${INPUT}")
# 文件操作
file(WRITE output.txt "Generated content\n")
file(APPEND output.txt "More content\n")
# 创建目录
file(MAKE_DIRECTORY output_dir)
# 复制文件
file(COPY ${CMAKE_CURRENT_LIST_FILE}
DESTINATION output_dir)
# 列出文件
file(GLOB SOURCES "src/*.cpp")
message(STATUS "Source files: ${SOURCES}")
# 执行外部命令
execute_process(
COMMAND ls -la
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE LS_OUTPUT
)
message(STATUS "ls output: ${LS_OUTPUT}")
# 数学计算
math(EXPR RESULT "2 + 3 * 4")
message(STATUS "2 + 3 * 4 = ${RESULT}")
# 字符串操作
string(TOUPPER "hello" HELLO)
message(STATUS "Uppercase: ${HELLO}")
# 时间戳
string(TIMESTAMP CURRENT_TIME "%Y-%m-%d %H:%M:%S")
message(STATUS "Current time: ${CURRENT_TIME}")7.3 常用脚本操作
# 文件比较
cmake -E compare_files file1 file2
# 复制文件/目录
cmake -E copy file1 file2
cmake -E copy_directory dir1 dir2
# 创建目录
cmake -E make_directory dir
# 删除文件/目录
cmake -E remove file
cmake -E remove_directory dir
# 重命名
cmake -E rename old new
# 创建符号链接
cmake -E create_symlink target link
# 压缩文件
cmake -E tar cf archive.tar files...
cmake -E tar xf archive.tar
cmake -E tar czf archive.tar.gz files...
cmake -E tar cjf archive.tar.bz2 files...
# 计算哈希
cmake -E md5sum file
cmake -E sha256sum file
# 环境变量操作
cmake -E env VAR=value command
# 执行命令并计时
cmake -E time command
# 改变工作目录
cmake -E chdir dir command
# 比较文件
cmake -E compare_files file1 file28. CMake 预设 (Presets)
8.1 CMakePresets.json 基础
// CMakePresets.json
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "default",
"displayName": "默认配置",
"description": "使用 Ninja 生成器",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_CXX_STANDARD": "17"
}
},
{
"name": "release",
"inherits": "default",
"displayName": "Release 配置",
"description": "Release 构建",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "windows",
"displayName": "Windows 配置",
"description": "使用 Visual Studio 2022",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "17"
}
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default",
"displayName": "默认构建"
},
{
"name": "release",
"configurePreset": "release",
"displayName": "Release 构建"
}
],
"testPresets": [
{
"name": "default",
"configurePreset": "default",
"output": {
"outputOnFailure": true
},
"execution": {
"noTestsAction": "error",
"stopOnFailure": false
}
}
]
}8.2 使用预设
# 列出所有可用的预设
cmake --list-presets
# 列出特定类型的预设
cmake --list-presets=configure
cmake --list-presets=build
cmake --list-presets=test
# 使用配置预设
cmake --preset=default
# 使用构建预设
cmake --build --preset=default
# 使用测试预设
ctest --preset=default
# 覆盖预设中的变量
cmake --preset=release -DCMAKE_CXX_FLAGS="-O3"
# 使用 CMakeUserPresets.json(个人设置)
# CMakeUserPresets.json
{
"version": 3,
"configurePresets": [
{
"name": "my-local",
"inherits": "default",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "/usr/local/bin/g++-11"
}
}
]
}9. CMake 命令行工具
9.1 cmake 命令行工具
# 查看版本
cmake --version
# 查看系统信息
cmake --system-information
cmake --system-information info.txt
# 查找包
cmake --find-package -DNAME=OpenCV -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=EXIST
# 图形界面
cmake-gui .
# 打开帮助
cmake --help-command add_executable
cmake --help-property TARGET_NAME
cmake --help-variable CMAKE_CXX_COMPILER
# 打印 CMake 标准路径
cmake --debug-trycompile ..9.2 ctest 命令
# 运行所有测试
ctest
# 并行运行测试
ctest -j 4
# 显示详细输出
ctest -V
ctest -VV # 更详细
# 运行指定测试
ctest -R test_name # 正则表达式匹配
ctest -I 1,5 # 运行索引1-5的测试
# 重复运行测试
ctest --repeat-until-fail 10 # 最多重复10次直到失败
# 输出为 JUnit 格式
ctest --output-junit test_results.xml
# 指定构建配置
ctest -C Release
# 排除测试
ctest -EXCLUDE test_name
# 设置超时
ctest --timeout 109.3 cpack 命令
# 创建所有包
cpack
# 创建特定类型的包
cpack -G DEB # Debian 包
cpack -G RPM # RPM 包
cpack -G NSIS # Windows 安装程序
cpack -G TGZ # tar.gz 压缩包
cpack -G ZIP # ZIP 压缩包
# 指定配置文件
cpack -C CPackConfig.cmake
# 指定版本
cpack -D CPACK_PACKAGE_VERSION=1.2.3
# 详细输出
cpack -V10. CMake 环境变量
10.1 常用环境变量
# 设置 CMake 模块路径
export CMAKE_MODULE_PATH=/path/to/modules
# 设置前缀路径
export CMAKE_PREFIX_PATH=/custom/install
# 设置生成器
export CMAKE_GENERATOR=Ninja
export CMAKE_GENERATOR_PLATFORM=x64
export CMAKE_GENERATOR_TOOLSET=v142
# 设置构建类型
export CMAKE_BUILD_TYPE=Release
# 设置编译器和标志
export CC=gcc-11
export CXX=g++-11
export CFLAGS="-Wall -O2"
export CXXFLAGS="-Wall -O2 -std=c++17"
export LDFLAGS="-L/custom/lib"
# 设置安装前缀
export CMAKE_INSTALL_PREFIX=/usr/local
# 设置查找路径
export CMAKE_INCLUDE_PATH=/custom/include
export CMAKE_LIBRARY_PATH=/custom/lib
# CMake 输出颜色
export CLICOLOR=1
export CMAKE_COLOR_DIAGNOSTICS=ON10.2 在 CMakeLists.txt 中访问环境变量
# 访问环境变量
message(STATUS "PATH = $ENV{PATH}")
message(STATUS "HOME = $ENV{HOME}")
# 设置环境变量(仅影响子进程)
set(ENV{MY_VAR} "value")11. CMake 与包管理器集成
11.1 与 vcpkg 集成
# 设置 vcpkg 工具链
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake \
..
# 指定 triplet
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=x64-windows-static \
..
# 安装包
vcpkg install fmt boost11.2 与 Conan 集成
# 安装依赖
conan install . --output-folder=build --build=missing
# 使用 Conan 生成的 toolchain
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE=Release \
..
# 使用 CMakeDeps 生成器
conan install . --output-folder=build --build=missing -g CMakeDeps
cmake -B build \
-DCMAKE_PREFIX_PATH=build \
-DCMAKE_BUILD_TYPE=Release \
..11.3 与 Hunter 集成
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# 包含 Hunter
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/hunter-packages/hunter/archive/v0.23.251.tar.gz"
SHA1 "5659f8c64"
)
project(MyProject)
# 使用 Hunter 包
hunter_add_package(Boost COMPONENTS filesystem system)
find_package(Boost CONFIG REQUIRED)12. 高级用法
12.1 自定义命令和目标
# 在构建时生成文件
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.h
COMMAND ${CMAKE_COMMAND} -E echo "// Generated file" > generated.h
COMMAND ${CMAKE_COMMAND} -E echo "#define VERSION 1.0" >> generated.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version.txt
COMMENT "Generating version header"
)
# 添加自定义目标
add_custom_target(generate_files
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated.h
)
# 添加自定义命令到目标
add_executable(myapp main.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated.h)
add_dependencies(myapp generate_files)12.2 外部项目
# 下载和构建外部项目
include(ExternalProject)
ExternalProject_Add(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.11.0
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
INSTALL_COMMAND ""
)
# 使用 FetchContent(CMake 3.11+)
include(FetchContent)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 8.1.1
)
FetchContent_MakeAvailable(fmt)12.3 编译器检测和特性测试
# 检查 C++ 特性
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#include <optional>
int main() {
std::optional<int> o;
return 0;
}
" HAVE_STD_OPTIONAL)
if(HAVE_STD_OPTIONAL)
target_compile_definitions(myapp PRIVATE HAVE_STD_OPTIONAL)
endif()
# 检查编译器支持
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(myapp PRIVATE -Wall -Wextra)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(myapp PRIVATE -Wall -Weverything)
elseif(MSVC)
target_compile_options(myapp PRIVATE /W4)
endif()12.4 生成表达式
# 条件编译
target_compile_definitions(myapp PRIVATE
$<$<CONFIG:Debug>:DEBUG_MODE>
$<$<CONFIG:Release>:NDEBUG>
)
# 条件链接
target_link_libraries(myapp PRIVATE
$<$<PLATFORM_ID:Windows>:ws2_32>
$<$<PLATFORM_ID:Linux>:pthread>
)
# 条件包含目录
target_include_directories(myapp PRIVATE
$<$<BOOL:${USE_OPENGL}>:${OPENGL_INCLUDE_DIR}>
)13. 调试和故障排除
13.1 调试选项
# 详细输出
cmake --debug-output ..
cmake --trace .. # 跟踪所有 CMake 调用
cmake --trace-expand .. # 展开变量后跟踪
cmake --trace-source=CMakeLists.txt .. # 只跟踪特定文件
# 调试 try_compile
cmake --debug-trycompile ..
# 记录日志
cmake --log-level=DEBUG ..
cmake --log-context ..13.2 查看缓存变量
# 列出所有缓存变量
cmake -LA ..
cmake -LAH .. # 带帮助
# 查看特定变量
cmake --system-information | grep CMAKE_CXX_COMPILER13.3 常见问题解决
# 清理缓存
rm -rf build/
mkdir build && cd build
# 或者清除缓存但不删除整个目录
rm -f CMakeCache.txt
rm -rf CMakeFiles/
# 强制重新配置
cmake --fresh ..
# 查看详细的错误信息
cmake .. 2>&1 | tee cmake_error.log
# 检查编译器
cmake --system-information | grep -A5 "CXX"14. 完整实战项目
14.1 项目结构
MyProject/
├── CMakeLists.txt
├── CMakePresets.json
├── README.md
├── .gitignore
├── src/
│ ├── CMakeLists.txt
│ ├── main.cpp
│ └── utils/
│ ├── CMakeLists.txt
│ ├── math_utils.h
│ └── math_utils.cpp
├── include/
│ └── myproject/
│ └── api.h
├── tests/
│ ├── CMakeLists.txt
│ └── test_math.cpp
├── docs/
│ └── Doxyfile.in
├── cmake/
│ ├── FindMyLibrary.cmake
│ └── CompilerOptions.cmake
└── scripts/
└── build.sh14.2 根目录 CMakeLists.txt
# 根目录 CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# 设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
# 包含自定义模块
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# 包含编译器选项
include(CompilerOptions)
# 选项
option(BUILD_TESTS "Build tests" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_DOCS "Enable documentation" OFF)
# 查找依赖
find_package(fmt REQUIRED)
find_package(Boost COMPONENTS filesystem OPTIONAL_COMPONENTS system)
# 添加子目录
add_subdirectory(src)
if(BUILD_TESTS AND CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
enable_testing()
add_subdirectory(tests)
endif()
if(ENABLE_DOCS)
find_package(Doxygen REQUIRED)
add_subdirectory(docs)
endif()
# 打印配置总结
include(FeatureSummary)
feature_summary(WHAT ALL)14.3 cmake/CompilerOptions.cmake
# cmake/CompilerOptions.cmake
# 设置编译器选项
macro(set_compiler_options target)
if(MSVC)
# MSVC 选项
target_compile_options(${target} PRIVATE
/W4
/WX # 警告视为错误
$<$<CONFIG:Release>:/O2>
$<$<CONFIG:Debug>:/Zi /Od>
)
target_link_options(${target} PRIVATE
$<$<CONFIG:Debug>:/DEBUG>
)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# GCC/Clang 选项
target_compile_options(${target} PRIVATE
-Wall
-Wextra
-Wpedantic
-Werror
$<$<CONFIG:Release>:-O3>
$<$<CONFIG:Debug>:-g -O0>
)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(${target} PRIVATE -Weverything)
endif()
endif()
endmacro()
# 设置编译器特性
macro(require_cxx_features target)
target_compile_features(${target} PUBLIC cxx_std_17)
endmacro()14.4 src/CMakeLists.txt
# src/CMakeLists.txt
# 添加子目录
add_subdirectory(utils)
# 创建库
add_library(myproject_lib)
target_sources(myproject_lib PRIVATE
${CMAKE_CURRENT_LIST_DIR}/utils/math_utils.cpp
)
target_include_directories(myproject_lib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(myproject_lib
PUBLIC
fmt::fmt
PRIVATE
myproject_utils
)
# 设置编译选项
set_compiler_options(myproject_lib)
# 创建可执行文件
add_executable(myapp main.cpp)
target_link_libraries(myapp
PRIVATE
myproject_lib
)
set_compiler_options(myapp)
# 安装
install(TARGETS myproject_lib myapp
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../include/
DESTINATION include
FILES_MATCHING PATTERN "*.h"
)14.5 src/utils/CMakeLists.txt
# src/utils/CMakeLists.txt
add_library(myproject_utils STATIC
math_utils.cpp
)
target_include_directories(myproject_utils
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_features(myproject_utils PUBLIC cxx_std_17)
# 这个库不直接安装,会被链接到 myproject_lib14.6 tests/CMakeLists.txt
# tests/CMakeLists.txt
# 查找 GTest
find_package(GTest REQUIRED)
# 添加测试可执行文件
add_executable(test_math test_math.cpp)
target_link_libraries(test_math
PRIVATE
myproject_lib
GTest::gtest_main
)
# 注册测试
add_test(NAME MathTest COMMAND test_math)
# 设置测试属性
set_tests_properties(MathTest PROPERTIES
TIMEOUT 10
ENVIRONMENT "TEST_ENV=1"
)14.7 docs/CMakeLists.txt
# docs/CMakeLists.txt
# 配置 Doxygen 文件
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
@ONLY
)
# 添加文档生成目标
add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)14.8 构建脚本 scripts/build.sh
#!/bin/bash
# scripts/build.sh
set -e # 出错时退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 默认值
BUILD_TYPE="Release"
BUILD_DIR="build"
JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
CLEAN=0
RUN_TESTS=1
INSTALL=0
INSTALL_PREFIX="/usr/local"
print_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
show_help() {
cat << EOF
用法: $0 [选项]
选项:
-h, --help 显示此帮助
-b, --build-type TYPE 构建类型 (Debug, Release, RelWithDebInfo, MinSizeRel)
-d, --build-dir DIR 构建目录 (默认: build)
-j, --jobs N 并行作业数 (默认: 自动检测)
-c, --clean 清理构建目录
-t, --tests 运行测试 (默认: 是)
--no-tests 不运行测试
-i, --install 安装项目
-p, --prefix DIR 安装前缀 (默认: /usr/local)
示例:
$0 -b Debug -j 8
$0 --clean --no-tests
$0 -i -p ~/local
EOF
}
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-b|--build-type)
BUILD_TYPE="$2"
shift 2
;;
-d|--build-dir)
BUILD_DIR="$2"
shift 2
;;
-j|--jobs)
JOBS="$2"
shift 2
;;
-c|--clean)
CLEAN=1
shift
;;
-t|--tests)
RUN_TESTS=1
shift
;;
--no-tests)
RUN_TESTS=0
shift
;;
-i|--install)
INSTALL=1
shift
;;
-p|--prefix)
INSTALL_PREFIX="$2"
shift 2
;;
*)
print_error "未知选项: $1"
show_help
exit 1
;;
esac
done
# 清理
if [[ $CLEAN -eq 1 ]]; then
print_info "清理构建目录 ${BUILD_DIR}..."
rm -rf ${BUILD_DIR}
fi
# 创建构建目录
mkdir -p ${BUILD_DIR}
# 配置
print_info "配置项目 (${BUILD_TYPE})..."
cmake -B ${BUILD_DIR} -S . \
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DBUILD_TESTS=${RUN_TESTS} \
-DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX}
# 构建
print_info "构建项目..."
cmake --build ${BUILD_DIR} -j ${JOBS}
# 测试
if [[ $RUN_TESTS -eq 1 ]]; then
print_info "运行测试..."
cd ${BUILD_DIR}
ctest --output-on-failure
cd ..
fi
# 安装
if [[ $INSTALL -eq 1 ]]; then
print_info "安装项目到 ${INSTALL_PREFIX}..."
cmake --install ${BUILD_DIR} --prefix ${INSTALL_PREFIX}
fi
print_info "完成!"14.9 CMakePresets.json
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "debug",
"displayName": "Debug",
"description": "Debug build with tests",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"BUILD_TESTS": "ON",
"ENABLE_DOCS": "OFF"
}
},
{
"name": "release",
"displayName": "Release",
"description": "Release build",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_TESTS": "OFF",
"ENABLE_DOCS": "OFF"
}
},
{
"name": "windows-vs",
"displayName": "Windows VS 2022",
"description": "Visual Studio 2022 build",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"binaryDir": "${sourceDir}/build/vs2022",
"cacheVariables": {
"BUILD_TESTS": "ON"
}
}
],
"buildPresets": [
{
"name": "debug",
"configurePreset": "debug"
},
{
"name": "release",
"configurePreset": "release"
}
],
"testPresets": [
{
"name": "debug",
"configurePreset": "debug",
"output": {
"outputOnFailure": true
}
}
]
}14.10 使用示例
# 基本构建
./scripts/build.sh
# Debug 构建
./scripts/build.sh -b Debug
# 清理并构建 Release
./scripts/build.sh --clean -b Release -j 8
# 构建并安装到本地
./scripts/build.sh -i -p ~/local
# 使用预设
cmake --preset=debug
cmake --build --preset=debug
ctest --preset=debug
# 直接使用 cmake 命令
mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON
cmake --build . -j 4
ctest
sudo cmake --install .总结
CMake 是一个功能强大的构建系统生成器,掌握它的使用方法对于现代 C++ 开发至关重要。本教程涵盖了从基础到高级的 CMake 命令使用方法,包括:
- 基础命令:配置、构建、安装
- 生成器选择:Make、Ninja、Visual Studio 等
- 变量设置:编译选项、路径配置
- 预设系统:简化常用配置
- 脚本模式:自动化任务
- 包管理器集成:vcpkg、Conan
- 高级特性:自定义命令、外部项目
- 调试技巧:故障排除
通过掌握这些命令和技巧,你可以更高效地管理 C++ 项目的构建过程。
Markdown 是一种轻量级的标记语言,可用于在纯文本文档中添加格式化元素。Markdown 由 John Gruber 于 2004 年创建,如今已成为世界上最受欢迎的标记语言之一。
- 专注于文字内容;
- 纯文本,易读易写,可以方便地纳入版本控制;
- 语法简单,没有什么学习成本,能轻松在码字的同时做出美观大方的排版。
下面有几个可以学习 Markdown 基础语法的网站:


