当前位置: 首页 > news >正文

CPM:CMake 包管理详细介绍

CPM(CMake Package Manager)是一个专为 CMake 设计的轻量级依赖管理工具。它本质上是一个跨平台的 CMake 脚本,充当 CMake FetchContent 模块的薄包装器,提供了版本控制、缓存、简单 API 等功能,被誉为“CMake 缺失的包管理器”。CPM 旨在实现无设置、跨平台、可重现的依赖管理,帮助开发者轻松处理 C++ 项目中的外部依赖,而无需额外的安装步骤。

CPM 的工作原理

CPM 在 CMake 的配置阶段(configure stage)获取和配置依赖项。它利用 FetchContent 下载项目或资源,对于现代 CMake 项目,它会自动配置;对于其他项目,则允许手动创建目标。依赖项通过 Git 提交或标签进行版本控制,确保构建的可重现性。

  • 递归依赖处理:CPM 确保依赖项不会重复添加,并以最低所需版本添加。
  • 离线构建支持:如果源已缓存,CPM 会覆盖 CMake 的下载命令,实现离线配置。
  • 自动浅克隆:在使用版本标签和源缓存时,进行浅克隆以提高速度并减少存储。
  • 覆盖机制:可以通过 find_package 覆盖依赖,使用系统包管理器集成。

CPM 不处理预构建二进制文件,而是从源代码下载并构建依赖,这使得它适合需要精确控制的环境。

安装 CPM

安装 CPM 非常简单,无需全局安装。只需将 CPM 脚本添加到项目中:

  1. 在项目目录中创建 cmake 文件夹。

  2. 下载最新版本的 get_cpm.cmake 或直接 CPM.cmake

    mkdir -p cmake
    wget -O cmake/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
    

或者,在项目的 CMakeLists.txt 中直接下载 CPM:

include(FetchContent)
FetchContent_Declare(_cpmURL https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
)
FetchContent_MakeAvailable(_cpm)
include(${_cpm_SOURCE_DIR}/CPM.cmake)

这种方式确保 CPM 与项目一起分发,无需额外设置。

使用示例

CPM 的核心函数是 CPMAddPackage,它接受命名参数来声明依赖。

完整 CMakeLists.txt 示例

cmake_minimum_required(VERSION 3.14 FATAL_ERROR)# 创建项目
project(MyProject)# 添加可执行文件
add_executable(main main.cpp)# 包含 CPM
include(cmake/CPM.cmake)# 添加依赖
CPMAddPackage("gh:fmtlib/fmt#7.1.3")
CPMAddPackage("gh:nlohmann/json@3.10.5")
CPMAddPackage("gh:catchorg/Catch2@3.4.0")# 链接依赖
target_link_libraries(main fmt::fmt nlohmann_json::nlohmann_json Catch2::Catch2WithMain)

这个示例展示了如何添加 fmt、json 和 Catch2 库,并链接到主目标。

CPMAddPackage 函数参数

参数描述示例
NAME依赖的唯一名称(应为导出的目标名称)NAME fmt
VERSION依赖的最低版本(可选,默认 0)VERSION 7.1.3
PATCHES要应用的补丁文件序列(使用 patch 命令)PATCHES fix1.patch fix2.patch
OPTIONS传递给依赖的配置选项OPTIONS "JSON_BuildTests OFF"
DOWNLOAD_ONLY只下载项目,不配置(可选)DOWNLOAD_ONLY YES
GIT_REPOSITORYGit 仓库 URL(或其他来源,如直接 URL)GIT_REPOSITORY https://github.com/fmtlib/fmt
GIT_TAGGit 标签或提交哈希(默认 v(VERSION))GIT_TAG 7.1.3

简写语法示例:

  • Git 包:CPMAddPackage("gh:fmtlib/fmt@7.1.3")
  • 带标签:CPMAddPackage("gh:fmtlib/fmt#v7.1.3")
  • 存档包:CPMAddPackage("https://example.com/my-package-1.2.3.zip")

添加后,可访问变量如 <dependency>_SOURCE_DIRCPM_LAST_PACKAGE_NAME 等。

特定库示例

  • Catch2

    CPMAddPackage("gh:catchorg/Catch2@2.5.0")
    
  • yaml-cpp(指定版本以匹配异常标签格式):

    CPMAddPackage("gh:jbeder/yaml-cpp#yaml-cpp-0.6.3@0.6.3")
    
  • Boost(使用源存档加速):

    CPMAddPackage(NAME BoostVERSION 1.84.0URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xzURL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0eOPTIONS "BOOST_ENABLE_CMAKE ON"
    )
    
  • Lua(手动创建目标,因为无 CMake 支持):

    CPMAddPackage(NAME luaGIT_REPOSITORY https://github.com/lua/lua.gitVERSION 5.3.5DOWNLOAD_ONLY YES
    )if (lua_ADDED)FILE(GLOB lua_sources ${lua_SOURCE_DIR}/*.c)list(REMOVE_ITEM lua_sources "${lua_SOURCE_DIR}/lua.c" "${lua_SOURCE_DIR}/luac.c")add_library(lua STATIC ${lua_sources})target_include_directories(lua PUBLIC $<BUILD_INTERFACE:${lua_SOURCE_DIR}>)
    endif()
    

优势

CPM 的主要优势包括:

  1. 小型且可重用项目:处理所有依赖,让开发者专注于创建小型、测试良好的库。
  2. 跨平台:在配置阶段添加项目,兼容所有 CMake 工具链和生成器。
  3. 可重现构建:通过 Git 版本控制确保项目始终可构建。
  4. 即插即用:无需安装,只需添加脚本即可。
  5. 无需打包:直接添加外部源作为依赖。
  6. 简单源分发:简化包含源文件和依赖的项目,减少对单头文件或 Git 子模块的需求。
  7. 离线和缓存支持:使用 CPM_SOURCE_CACHE 避免重复下载。

特性

  • 版本检查:如果依赖需要更新的版本,会发出警告。
  • 包锁定文件:管理传递依赖,而不修改 CMakeLists.txt。使用 CPMUsePackageLock(package-lock.cmake) 并通过目标更新。
  • 本地包覆盖:通过 CMake 选项如 -DCPM_<dependency>_SOURCE=/path/to/dep 覆盖依赖。
  • 补丁支持:顺序应用补丁文件。
  • 选项传递:自定义依赖配置。
  • 私有仓库支持:在 CI 中使用 Git 配置重写 URL 以添加令牌。
  • 变量和标志:如 EXCLUDE_FROM_ALLSYSTEMFIND_PACKAGE_ARGUMENTS
  • 自定义缓存键:用于使用外部文件的补丁。

配置选项如 CPM_USE_LOCAL_PACKAGES(优先 find_package)、CPM_DOWNLOAD_ALL(强制下载以实现可重现性)等。

与其他工具的比较

与 find_package 比较

find_package 依赖系统安装的库,版本不明确,可能导致不可预测构建。CPM 从源构建依赖,确保一致性,但不暴露如 <PackageName>_LIBRARIES 的变量(需手动处理)。

与 vcpkg 或 Conan 比较

vcpkg 和 Conan 是更全面的包管理器,支持预构建二进制和安装步骤,适合复杂项目。CPM 是无设置的,仅在配置时添加,不处理二进制。CPM 可以与它们集成,通过 CPM_USE_LOCAL_PACKAGES 使用 find_package。CPM 更轻量,适合快速启动,而 vcpkg/Conan 提供更多功能如二进制缓存。

与纯 FetchContent / ExternalProject 比较

CPM 是 FetchContent 的包装器,添加了简单 API、版本检查、离线构建、浅克隆、包锁定等功能。ExternalProject 在构建时添加,复杂化工具链和嵌套依赖;FetchContent 在配置时,但缺少 CPM 的扩展。

限制

  • 无预构建二进制:每次新构建目录都从源构建依赖。建议使用 CPM_SOURCE_CACHE 和 ccache 缓解。
  • 依赖 CMakeLists 质量:许多库的 CMakeLists 不适合子项目,需要手动配置。
  • 菱形依赖:使用第一个添加的版本,如果冲突则警告;需手动解决。
  • 策略设置:将某些 CMake 策略设为 NEW(如 CMP0077),如果需要 OLD 则需调整代码。

最近更新与版本

CPM 的最新版本可从 GitHub Releases 下载。示例中使用如 Catch2@3.4.0、Boost 1.84.0 等,显示与近期库兼容。社区讨论(如 Reddit 和 Discourse)显示 CPM 仍在活跃维护,2024 年有新视频和文章讨论其优势。作为开源项目,建议定期更新脚本以获取改进。

总体而言,CPM 特别适合小型项目、快速原型和跨平台开发,是 CMake 生态中一个高效的依赖管理解决方案。如果项目复杂,考虑结合 vcpkg 或 Conan 以获得更多功能。

http://www.dtcms.com/a/490056.html

相关文章:

  • D3.js + SVG:数据可视化领域的黄金搭档,绘制动态交互图表。
  • 【个人成长笔记】在 QT 中 SkipEmptyParts 编译错误信息及其解决方案
  • 设计模式篇之 备忘录模式 Memento
  • dw做的网站放文件夹网页生成桌面快捷方式
  • 2017流行的网站风格随州网站建设价格
  • 鸿蒙:使用媒体查询监听屏幕方向、切换横竖屏
  • 8.list的使用
  • 网页跳转github镜像
  • 安灯系统(Andon)如何为汽车工厂打造零延迟响应
  • C++(条件判断与循环)
  • 温州建设局网站首页中国企业名录黄页
  • linux/centos迁移conda文件夹
  • Quill 富文本编辑器 功能介绍,使用场景说明,使用示例演示
  • 网站生成器怎么做网站建设与管理实训主要内容
  • 网站信用认证可以自己做吗稀奇古怪好玩有用的网站
  • MySQL 基础语句
  • Linux中CPU初始化和调度器初始化函数的实现
  • MATLAB基于ST-CNN-SVM的轴承故障诊断,S变换和卷积神经网络结合支持向量机
  • 在优豆云免费云服务器上初探SSH与SCP的便捷操作
  • MySQL数据库:软件、相关知识和基本操作
  • Bahdanau注意力
  • 重生之我在大学自学鸿蒙开发第七天-《AI语音朗读》
  • Spring AI 1.0 GA 深度解析:Java生态的AI革命已来
  • Linux网络之----TCP网络编程
  • 【零基础学习CAPL语法】——writeLineEx() 函数
  • 计算机网络数据链路层
  • 做网站选什么专业门户网站开发步骤博客
  • 论文写作 24: 全文保持同样的节奏
  • 洛谷 P1438 无聊的数列 题解
  • iOS混淆与IPA加固实战手记,如何构建苹果应用防反编译体系