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

cmake之旅(12)

cmake之旅(12)

  • cmake之旅(12):CPack 打包与发布
  • 1 CPack 是什么
  • 2 最简单的 CPack 配置
  • 3 配置 CPack
    • 3.1 基本信息
    • 3.2 选择打包格式
  • 4 生成 DEB 包
  • 5 生成 RPM 包
  • 6 完整示例
  • 7 组件化打包
  • 8 source 包
  • 9 本篇命令速查表
  • 10 总结与下一篇预告

同系列文章:
cmake之旅(1):构建的过程
cmake之旅(2):CMakeLists.txt 核心语法
cmake之旅(3):多目录项目管理
cmake之旅(4):静态库与动态库
cmake之旅(5):函数、宏与 .cmake 模块
cmake之旅(6):查找和使用第三方库
cmake之旅(7):编译选项与条件编译
cmake之旅(8):Modern CMake 与 target 思维
cmake之旅(9):安装与导出
cmake之旅(10):自动化测试与 CTest
cmake之旅(11):交叉编译与工具链文件
cmake之旅(12):CPack 打包与发布

cmake之旅(12):CPack 打包与发布

上一篇我们学会了交叉编译,让程序可以在不同平台上运行。但把编译好的程序分发给最终用户,总不能给他一堆.so文件和一个可执行文件,让他自己放到正确的目录里吧。

我们需要把项目打包成标准的安装包——Linux 上是.deb(Debian/Ubuntu)或.rpm(CentOS/Fedora),Windows 上是.exe安装程序或.zip,macOS 上是.dmg

CMake 内置的CPack工具正好解决这个问题。

1 CPack 是什么

CPack 是 CMake 配套的打包工具。它复用install()命令定义的安装规则,把要安装的文件打包成各种格式的安装包。

换句话说,如果你已经在第九篇中写好了install()规则,那 CPack 几乎是"零成本"使用的——它直接利用已有的安装规则来决定哪些文件需要打包。

2 最简单的 CPack 配置

在 CMakeLists.txt 的末尾加上两行就行:

# 引入 CPack 模块(必须放在所有 install 命令之后) include(CPack)

然后构建并打包:

mkdirbuild&&cdbuild cmake..makecpack

cpack命令默认会生成一个.tar.gz压缩包和一个.sh自解压脚本。

不过默认的配置比较粗糙。我们来看看如何自定义打包行为。

3 配置 CPack

CPack 的配置通过一系列CPACK_xxx变量来控制。这些变量必须在include(CPack)之前设置

3.1 基本信息

# 包的基本信息 set(CPACK_PACKAGE_NAME "Calculator") set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "一个简单的计算器库") set(CPACK_PACKAGE_VENDOR "MyCompany") set(CPACK_PACKAGE_CONTACT "dev@example.com") # 许可协议文件 set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") # 输出文件名(不含后缀) set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}") include(CPack)

3.2 选择打包格式

通过CPACK_GENERATOR指定要生成的包格式:

# 指定一种或多种打包格式 set(CPACK_GENERATOR "TGZ;DEB;RPM")

常用的打包格式:

生成器格式适用系统
TGZ.tar.gz通用
ZIP.zip通用
DEB.debDebian / Ubuntu
RPM.rpmCentOS / Fedora
NSIS.exe 安装程序Windows
WIX.msi 安装程序Windows
DragNDrop.dmgmacOS
STGZ.sh 自解压脚本Linux

也可以在命令行中指定:

cpack-GDEB# 只生成 .deb 包cpack-GZIP# 只生成 .zip 包

4 生成 DEB 包

Debian/Ubuntu 的.deb包是 Linux 上最常见的安装包格式之一。

# DEB 包特有的配置 set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Your Name <your@email.com>") set(CPACK_DEBIAN_PACKAGE_SECTION "devel") # 分类 set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)") # 运行时依赖 include(CPack)

构建并打包:

cmake..makecpack-GDEB

生成的.deb文件可以直接用dpkg安装:

sudodpkg-iCalculator-1.0.0-Linux.deb

安装后,可执行文件会出现在/usr/local/bin/,库文件出现在/usr/local/lib/,头文件出现在/usr/local/include/——这些路径就是你在install()命令中指定的。

卸载:

sudodpkg-rcalculator

5 生成 RPM 包

CentOS/Fedora 系统使用 RPM 包。需要先安装rpmbuild工具:

sudoapt-getinstallrpm# Ubuntu 上安装 rpm 工具

CMake 配置:

# RPM 包特有的配置 set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries") set(CPACK_RPM_PACKAGE_REQUIRES "glibc >= 2.17") # 运行时依赖 include(CPack)
cpack-GRPM

6 完整示例

我们基于 Calculator 项目,写一个完整的支持打包的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.14) project(Calculator VERSION 1.0.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) include(GNUInstallDirs) # ---- 构建 ---- add_library(calc_lib src/add.cpp src/de.cpp ) target_include_directories(calc_lib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ) add_executable(calculator src/main.cpp) target_link_libraries(calculator PRIVATE calc_lib) # ---- 安装 ---- install(TARGETS calc_lib calculator EXPORT CalcLibTargets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) # 安装 CMake 配置文件(可选,供其他 CMake 项目使用) install(EXPORT CalcLibTargets FILE CalcLibTargets.cmake NAMESPACE CalcLib:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CalcLib ) # ---- CPack 打包配置 ---- set(CPACK_PACKAGE_NAME "Calculator") set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "一个简单的计算器库和工具") set(CPACK_PACKAGE_VENDOR "MyCompany") set(CPACK_PACKAGE_CONTACT "dev@example.com") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") # 安装路径前缀 set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) # 输出文件名 set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") # DEB 配置 set(CPACK_DEBIAN_PACKAGE_MAINTAINER "dev@example.com") set(CPACK_DEBIAN_PACKAGE_SECTION "devel") # RPM 配置 set(CPACK_RPM_PACKAGE_LICENSE "MIT") # 引入 CPack(必须在所有 CPACK_ 变量设置之后) include(CPack)

构建和打包:

mkdirbuild&&cdbuild cmake..make# 生成所有配置的格式cpack# 或者只生成特定格式cpack-GTGZ cpack-GDEB cpack-GZIP

7 组件化打包

对于复杂的项目,你可能不想把所有东西打成一个包。比如,用户可能只想安装运行时文件(可执行文件 + 动态库),不想安装开发文件(头文件 + 静态库 + CMake 配置)。

CPack 支持组件化打包——把安装内容分成多个组件,每个组件可以单独打包。

# 运行时组件 install(TARGETS calculator RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ) install(TARGETS calc_lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime ) # 开发组件 install(TARGETS calc_lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT development ) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT development ) # 启用组件化打包 set(CPACK_DEB_COMPONENT_INSTALL ON) # 组件描述 set(CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "运行时文件") set(CPACK_COMPONENT_RUNTIME_DESCRIPTION "可执行文件和动态库") set(CPACK_COMPONENT_DEVELOPMENT_DISPLAY_NAME "开发文件") set(CPACK_COMPONENT_DEVELOPMENT_DESCRIPTION "头文件、静态库和 CMake 配置") set(CPACK_COMPONENT_DEVELOPMENT_DEPENDS runtime) # 开发组件依赖运行时组件

这样 CPack 会生成两个独立的包:

Calculator-1.0.0-Linux-runtime.deb Calculator-1.0.0-Linux-development.deb

用户可以按需安装:

# 只安装运行时sudodpkg-iCalculator-1.0.0-Linux-runtime.deb# 如果需要开发(编写依赖此库的代码),再装开发包sudodpkg-iCalculator-1.0.0-Linux-development.deb

8 source 包

除了打包编译后的二进制文件,CPack 还可以打包源码:

# 打包源码cpack--configCPackSourceConfig.cmake

默认会包含所有源文件。可以通过CPACK_SOURCE_IGNORE_FILES排除不需要的文件:

set(CPACK_SOURCE_IGNORE_FILES "/build/" "/\\.git/" "\\.gitignore" "/\\.vscode/" ) set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")

9 本篇命令速查表

CPack 常用变量:

变量含义
CPACK_PACKAGE_NAME包名
CPACK_PACKAGE_VERSION版本号
CPACK_PACKAGE_DESCRIPTION_SUMMARY简短描述
CPACK_PACKAGE_VENDOR厂商/作者
CPACK_PACKAGE_CONTACT联系方式
CPACK_GENERATOR打包格式列表
CPACK_PACKAGE_FILE_NAME输出文件名
CPACK_RESOURCE_FILE_LICENSE许可协议文件

cpack 命令行参数:

参数作用
-G <generator>指定打包格式
-C <config>指定构建配置(Debug/Release)
--config <file>使用指定的配置文件
-V详细输出

10 总结与下一篇预告

这一篇我们学习了 CPack 的使用方法,包括基本配置、DEB/RPM 包的生成、组件化打包、以及源码打包。CPack 最大的优势是复用已有的 install() 规则,几乎不需要额外的工作就能生成标准化的安装包。

到这里,我们已经完整地走过了 CMake 从入门到进阶的所有核心知识点。最后一篇,我们用一个完整的实战项目把这 12 篇的知识全部串起来,让你看到一个"生产级"的 CMake 项目是什么样子的。

下一篇——cmake之旅(13):实战项目总结,整个系列的收官之作。

http://www.jsqmd.com/news/624829/

相关文章:

  • Qwen2.5-VL-Chord生产环境:7×24小时稳定运行30天故障率为0实录
  • 智能车竞赛极速越野组:从GPS导航到多线程控制的实战经验分享
  • 2025届毕业生推荐的五大AI论文网站横评
  • 拒绝流量焦虑:无锡GEO优化哪家强?深度对比TOP6服务商
  • CentOS vs Ubuntu:主流Linux发行版对比
  • 虚拟DOM算法:Diff策略与Key属性的作用原理
  • Motrix WebExtension快速上手:浏览器下载管理终极解决方案
  • Matlab算法原型与Qwen3-0.6B-FP8自然语言接口的联动
  • 新钛云服邀您共赴 CDIE 2026,解锁云与安全管理新范式!
  • 微信小程序iOS操作系统BLE适配问题总结
  • 帝国CMS vs DEDECMS:全面对比解析
  • 3个场景告诉你:为什么HMCL是Minecraft玩家的最佳选择
  • 二手车金融风控实战:如何用OBD数据+机器学习降低不良率(附完整代码)
  • 别再死记硬背开关表了!用Matlab/Simulink手把手教你理解DTC扇区划分与矢量选择
  • [具身智能-347]:MCP Client是用户、大模型、MCP Server的桥梁,更是AI Agent的orchestrator(编排者)
  • 终极指南:如何快速免费恢复加密压缩包密码
  • 用nc命令模拟一个简单的TCP-UDP客户端和服务端
  • 手把手教你定制Zotero笔记:从Better Notes模板语法到Ethereal Style样式调校(v4.9.8实战)
  • OpenClaw低代码方案:Qwen3.5-9B-AWQ-4bit+简道云集成
  • 当版图同学只给GDS文件时,我是这样用Calibre PEX和Cadence做后仿真的(保姆级避坑)
  • AI开发-python-langchain框架(--串行流程 )窖
  • 2026平航wp
  • cmake之旅(11)
  • Kd-tree在三维点云中的5个常见误区及解决方案
  • SDD基于规范编程-OpenSpec及SuperPowers们
  • 如何用Flight Review从飞行数据中快速发现无人机问题?5步诊断指南
  • 从零实现一个轻量级数据库——MYDB的核心架构解析
  • PDF Arranger:免费开源PDF编辑工具,让你的文档管理效率提升300%
  • [具身智能-348]:MCP Client代码示例
  • GLM-4.1V-9B-Base部署指南:supervisor日志轮转+磁盘空间自动清理