August 25, 2026 in 开发工具与云服务3 minutes
介绍使用Cmake和vcpkg进行开发的基础知识
CMake 不是编译器,也不是构建工具(如 Make/Ninja)。它是一个 构建系统生成器:
CMakeLists.txt.sln/Ninja,Linux 上生成 Makefile/Ninja)CMakeLists.txt → CMake → Ninja/Makefile/VS Solution → 编译器 → 可执行文件
| 特点 | 说明 |
|---|---|
| 跨平台 | 同一份 CMakeLists.txt 可在 Windows/Linux/macOS/Android/iOS 上构建 |
| 语言无关 | 支持 C, C++, Fortran, CUDA, Objective-C 等 |
| 依赖管理 | 内置 find_package() 机制查找系统/第三方库 |
| IDE 集成 | VS Code, CLion, Visual Studio, Qt Creator 均原生支持 |
| 模块化 | 通过 Module/Config 模式扩展查找逻辑 |
| 测试/打包 | 内置 CTest(测试)、CPack(安装包生成) |
| Presets | CMakePresets.json 统一配置多环境构建参数 |
cmake_minimum_required(VERSION 3.20)
project(my_app VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(my_app src/main.cpp src/utils.cpp)# 查找库
find_package(fmt CONFIG REQUIRED)
find_package(OpenCV CONFIG REQUIRED)
# 链接(推荐 target 级别,避免全局污染)
target_link_libraries(my_app PRIVATE
fmt::fmt
opencv_core
opencv_imgproc
)add_subdirectory(src/core) # 子目录有自己的 CMakeLists.txt
add_subdirectory(src/network)
add_subdirectory(tests)if(WIN32)
target_compile_definitions(my_app PRIVATE PLATFORM_WINDOWS)
elseif(UNIX)
target_compile_definitions(my_app PRIVATE PLATFORM_LINUX)
endif()⚠️ 最重要的一条:一切以 Target 为中心,避免使用全局命令
| ❌ 旧式(避免) | ✅ 现代(推荐) |
|---|---|
include_directories(...) |
target_include_directories(my_app ...) |
link_libraries(...) |
target_link_libraries(my_app ...) |
add_definitions(...) |
target_compile_definitions(my_app ...) |
set(CMAKE_CXX_FLAGS ...) |
target_compile_options(my_app ...) |
原因:Target 级别的属性具有传播性(PRIVATE/PUBLIC/INTERFACE),不会污染其他目标,支持多目标共存。
# 配置(生成构建系统)
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
# 构建
cmake --build build --config Release -j8
# 安装
cmake --install build --prefix ./install
# 运行测试
ctest --test-dir build --output-on-failure
# 清理缓存重新配置
rm -rf build && cmake -S . -B buildvcpkg 是一个 源码级包管理器:
| 特点 | 说明 |
|---|---|
| 源码编译 | 不下载预编译二进制,避免 ABI 不兼容问题 |
| Triplet 机制 | 精确控制目标架构:x64-windows, x64-linux, arm64-android 等 |
| Manifest Mode | 项目级 vcpkg.json,依赖版本锁定,可复现构建 |
| Classic Mode | 全局安装,适合快速原型验证 |
| CMake 原生集成 | 设置 toolchain file 后 find_package() 自动生效 |
| 丰富的生态 | 2000+ 开源库,社区活跃维护 |
| Binary Caching | 编译过一次后缓存二进制,后续安装秒级完成 |
| Overlay Ports | 自定义/修改 port,满足特殊需求 |
| Classic Mode | Manifest Mode ✅推荐 | |
|---|---|---|
| 依赖声明 | vcpkg install xxx 命令行 |
项目根目录 vcpkg.json |
| 作用域 | 全局共享 | 项目隔离 |
| 版本控制 | 手动管理 | 可指定版本/baseline |
| 团队协作 | ❌ 不可复现 | ✅ 完全可复现 |
| CI/CD | 困难 | 天然支持 |
| 适用场景 | 学习、临时实验 | 正式项目 |
{
"name": "my-project",
"version-semver": "1.0.0",
"builtin-baseline": "a1b2c3d4e5f6...",
"dependencies": [
{ "name": "fmt", "version>=": "10.2.1" },
{ "name": "spdlog", "version>=": "1.13.0" },
{
"name": "opencv",
"default-features": false,
"features": ["jpeg", "png"]
},
{
"name": "boost-asio",
"platform": "!uwp"
}
],
"overrides": [
{ "name": "nlohmann-json", "version": "3.11.3" }
]
}关键字段说明:
builtin-baseline: vcpkg 仓库的 git commit hash,锁定所有未显式指定版本的依赖版本version>=: 最低版本约束features: 启用库的可选功能platform: 条件依赖(!uwp = 非 UWP 平台才安装)overrides: 强制指定某个依赖的确切版本# 只需正常 find_package,vcpkg toolchain 会自动处理
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(OpenCV CONFIG REQUIRED COMPONENTS jpeg png)
target_link_libraries(my_app PRIVATE
fmt::fmt
spdlog::spdlog
opencv_core opencv_imgcodecs
)# 搜索可用库
vcpkg search json
# 查看库的详细信息(含可用 features)
vcpkg show nlohmann-json
# Classic Mode 安装
vcpkg install fmt:x64-windows spdlog:x64-windows-static
# 更新 baseline(获取最新库版本)
cd vcpkg && git pull
vcpkg x-update-baseline --add-initial-baseline
# 导出已安装列表
vcpkg list
# 清理不再需要的包
vcpkg remove --outdated| Triplet | 说明 |
|---|---|
x64-windows |
Windows x64, 动态链接 CRT |
x64-windows-static |
Windows x64, 静态链接 CRT + 库 |
x64-mingw-dynamic |
MinGW GCC, 动态链接 |
x64-linux |
Linux x64 |
arm64-osx |
Apple Silicon macOS |
x64-android |
Android NDK x64 |
┌─────────────────────────────────────────────┐
│ 开发者工作流 │
│ │
│ 1. 编写 vcpkg.json (声明依赖) │
│ ↓ │
│ 2. 编写 CMakeLists.txt (find_package) │
│ ↓ │
│ 3. cmake configure (自动触发 vcpkg 安装) │
│ ↓ │
│ 4. cmake build (编译项目+依赖) │
│ ↓ │
│ 5. ctest (运行测试) │
└─────────────────────────────────────────────┘
关键点:配置阶段 CMake 通过 -DCMAKE_TOOLCHAIN_FILE=vcpkg.cmake 将 vcpkg 注入整个构建流程,find_package() 会优先在 vcpkg 安装目录中查找,无需手动指定路径。
| 场景 | 建议 |
|---|---|
| 新项目 | CMake + vcpkg Manifest Mode |
| 已有 Makefile 老项目 | 逐步迁移到 CMake,或先用 vcpkg Classic Mode |
| 纯 Windows + VS IDE | 可用 NuGet/vcpkg,但 CMake 更利于未来跨平台 |
| 嵌入式/交叉编译 | CMake + vcpkg 自定义 triplet |
| 需要极致构建速度 | 考虑 Conan(有预编译二进制),但 vcpkg binary caching 也已大幅改善 |
| 团队统一工具链 | CMakePresets.json + vcpkg manifest + CI 自动化 |
这套组合是目前 C++ 生态中标准化程度最高、文档最全、IDE 支持最好的方案,掌握后可以显著降低 C++ 项目的依赖管理和跨平台构建痛苦。