CPM.cmake轻量级包管理器

CPM.cmake 是一个轻量级、现代化的 CMake 包管理器,它基于 CMake 的 FetchContent 模块构建,允许你在 CMake 项目中以声明式方式引入第三方依赖。与传统的包管理器(如 vcpkg、Conan)不同,CPM 不需要额外安装工具,只需在 CMakeLists.txt 中包含一个脚本即可使用。


1. 什么是 CPM.cmake?

  • 全称:CMake Package Manager
  • 特点
    • 无需外部依赖(仅需 CMake ≥ 3.14)
    • 自动下载、配置、构建和链接依赖
    • 支持 Git、URL、本地路径等多种来源
    • 依赖可被多个项目共享(通过缓存)
    • 与 CMake 原生集成,语法简洁

GitHub 仓库:https://github.com/cpm-cmake/CPM.cmake


2. 快速开始

2.1 安装 CPM.cmake

在你的项目根目录的 CMakeLists.txt 文件开头添加以下代码:

cmake 复制代码
# 下载并包含 CPM.cmake
include(FetchContent)
FetchContent_Declare(
  CPM
  GIT_REPOSITORY https://github.com/cpm-cmake/CPM.cmake.git
  GIT_TAG        v1.10.0  # 检查最新版本:https://github.com/cpm-cmake/CPM.cmake/releases
)
FetchContent_MakeAvailable(CPM)

✅ 推荐:将 CPM.cmake下载到项目中的cmake/CPM.cmake 并通过 include(cmake/CPM.cmake) 引入,便于版本锁定和离线使用。https://github.com/cpm-cmake/CPM.cmake/releases/


2.2 添加第一个依赖

例如,添加 fmt 库:

cmake 复制代码
CPMAddPackage("gh:fmtlib/fmt@10.2.1")

这行代码会:

  • 从 GitHub 克隆 fmtlib/fmt 仓库
  • 切换到 10.2.1 标签
  • 自动调用 add_subdirectory() 将其加入构建系统

之后你就可以直接链接:

cmake 复制代码
target_link_libraries(your_target PRIVATE fmt::fmt)

3. CPMAddPackage 语法详解

CPMAddPackage() 支持多种参数形式:

3.1 简写形式(推荐)

cmake 复制代码
CPMAddPackage("gh:user/repo@version")      # GitHub
CPMAddPackage("gl:user/repo@version")      # GitLab
CPMAddPackage("bb:user/repo@version")      # Bitbucket

示例:

cmake 复制代码
CPMAddPackage("gh:nlohmann/json@v3.11.2")

3.2 完整参数形式

cmake 复制代码
CPMAddPackage(
  NAME          your_dep_name       # 可选,默认为 repo 名
  GITHUB_REPOSITORY "user/repo"
  VERSION       "1.2.3"
  GIT_TAG       "v1.2.3"            # 优先于 VERSION
  OPTIONS       "OPTION1 ON" "OPTION2 OFF"
  EXCLUDE_FROM_ALL TRUE               # 不自动构建(仅配置)
)

3.3 从 URL 或本地路径添加

cmake 复制代码
CPMAddPackage(
  NAME mylib
  URL https://example.com/mylib.zip
  URL_HASH SHA256=abc123...
)

# 或本地路径(用于调试或私有库)
CPMAddPackage(
  NAME local_lib
  SOURCE_DIR "${CMAKE_SOURCE_DIR}/third_party/mylib"
)

4. 高级用法

4.1 条件性添加依赖(避免重复)

CPM 会自动检测是否已添加同名包,但你也可以显式检查:

cmake 复制代码
if(NOT TARGET nlohmann_json::nlohmann_json)
  CPMAddPackage("gh:nlohmann/json@v3.11.2")
endif()

4.2 传递 CMake 选项给依赖

有些库支持自定义构建选项(如 BUILD_SHARED_LIBS):

cmake 复制代码
CPMAddPackage(
  NAME fmt
  GITHUB_REPOSITORY fmtlib/fmt
  GIT_TAG 10.2.1
  OPTIONS
    "FMT_INSTALL OFF"
    "FMT_DOC OFF"
)

4.3 共享缓存(加速 CI 和多项目构建)

CPM 默认使用 CMake 的全局缓存目录(通常为 ~/.cache/CMake/CPM),多个项目会共享已下载的依赖,避免重复克隆。

可通过环境变量自定义缓存路径:

bash 复制代码
export CPM_SOURCE_CACHE=/path/to/shared/cache

5. 完整示例项目

目录结构:

复制代码
my_project/
├── CMakeLists.txt
├── main.cpp
└── cmake/
    └── CPM.cmake   # (可选)本地副本

CMakeLists.txt:

cmake 复制代码
cmake_minimum_required(VERSION 3.14)
project(MyApp LANGUAGES CXX)

# 引入 CPM
include(cmake/CPM.cmake)  # 或使用 FetchContent 方式在线获取

# 添加依赖
CPMAddPackage("gh:fmtlib/fmt@10.2.1")
CPMAddPackage("gh:gabime/spdlog@v1.13.0")

# 创建可执行文件
add_executable(app main.cpp)

# 链接依赖
target_link_libraries(app PRIVATE fmt::fmt spdlog::spdlog)
target_compile_features(app PRIVATE cxx_std_17)

main.cpp:

cpp 复制代码
#include <fmt/core.h>
#include <spdlog/spdlog.h>

int main() {
    fmt::print("Hello from fmt!\n");
    spdlog::info("Hello from spdlog!");
    return 0;
}

构建命令:

bash 复制代码
mkdir build && cd build
cmake ..
cmake --build .
./app

6. 最佳实践

  • 固定版本号:始终指定明确的 Git Tag 或 Commit,避免意外更新。
  • 使用简写语法gh:user/repo@tag 更简洁且不易出错。
  • 避免在函数/宏中调用 CPMAddPackage:可能导致作用域问题。
  • CI 中启用缓存 :设置 CPM_SOURCE_CACHE 加快构建速度。
  • 不要混合 CPM 与其他包管理器:可能引起冲突。

7. 常见问题

Q: CPM 和 vcpkg/Conan 有什么区别?

A: CPM 是"源码嵌入式"管理器,直接将依赖作为子项目编译;而 vcpkg/Conan 通常预编译二进制。CPM 更适合希望完全控制构建过程的项目。

Q: 如何离线使用?

A: 将 CPM.cmake 脚本和依赖源码缓存到本地,或使用 SOURCE_DIR 指向本地副本。

Q: 支持私有仓库吗?

A: 支持!只要 Git 可访问(如配置 SSH 密钥),即可使用完整 Git URL:

cmake 复制代码
CPMAddPackage(
  GIT_REPOSITORY git@github.com:your/private-repo.git
  GIT_TAG v1.0.0
)

8. 参考资料


📌 提示:截至 2026 年,CPM.cmake 已成为许多现代 C++ 项目的首选依赖管理方案,尤其适合中小型项目和快速原型开发。

相关推荐
绿浪19842 小时前
C#与C++高效互操作指南
c++·c#
CSDN_RTKLIB2 小时前
std::string打印原始字节查看是否乱码
c++
shilei_c2 小时前
qt qDebug无输出问题解决
开发语言·c++·算法
一切尽在,你来2 小时前
C++ 零基础教程 - 第4讲-实现简单计算器
开发语言·c++
是店小二呀2 小时前
Visual Studio C++ 工程架构深度解析:从 .vcxproj 到 Qt MOC 的文件管理实录
c++·qt·visual studio
枫叶丹42 小时前
【Qt开发】Qt系统(十二)-> Qt视频
c语言·开发语言·c++·qt·音视频
浅念-2 小时前
C语言文件操作
c语言·c++·经验分享·笔记·学习
Ivanqhz2 小时前
向量化计算
开发语言·c++·后端·算法·支持向量机·rust
一切尽在,你来2 小时前
C++ 零基础教程 - 第 7 讲 bool运算符和选择结构教程
c++