cpack 生成 deb/rpm 包需严格配置:必须设置 cpack_debian_package_maintainer 和 rpm 必填字段,显式指定 cpack_generator,确保 install() 规则完整且路径正确,避免多生成器混用导致构建失败。

用 CPack 生成 deb 包,关键在 CPACK_GENERATOR 和 CPACK_DEBIAN_PACKAGE_MAINTAINER
不设 CPACK_DEBIAN_PACKAGE_MAINTAINER,cpack -G DEB 会直接报错:CPACK_DEBIAN_PACKAGE_MAINTAINER is not set。这不是可选项,是 deb 构建的硬性要求。
实操建议:
- 在
CMakeLists.txt末尾(project()之后、include(CPack)之前)设置:set(CPACK_DEBIAN_PACKAGE_MAINTAINER "your@email.com")
- 必须显式启用 DEB 生成器:
set(CPACK_GENERATOR "DEB")
,否则cpack默认只走 TGZ -
CPACK_PACKAGE_NAME和CPACK_PACKAGE_VERSION要与 Debian 命名规范兼容:版本号里不能含+或空格,否则dpkg-deb构建失败 - Debian 包默认把文件装到
/usr/local;如需进/usr,得加:set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
并确保CPACK_PACKAGING_INSTALL_PREFIX设为/usr
打包 rpm 时,CPACK_RPM_PACKAGE_LICENSE 和 CPACK_RPM_PACKAGE_GROUP 缺一不可
RPM 构建失败最常见的原因是字段缺失或格式非法。例如 CPACK_RPM_PACKAGE_GROUP 若为空或含空格(如 "Development Tools"),rpmbuild 会拒绝生成 spec 文件。
实操建议:
- 强制指定 RPM 字段(RHEL/CentOS/Fedora 都认):
set(CPACK_RPM_PACKAGE_LICENSE "MIT")<br>set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
-
CPACK_RPM_PACKAGE_ARCHITECTURE别依赖自动探测,显式写成"x86_64"或"noarch",否则跨平台构建可能出错 - 若项目含 systemd service 文件,需用
CPACK_RPM_POST_INSTALL_SCRIPT_FILE指定安装后脚本,否则服务不会启用 - RPM 默认使用
file命令探测文件类型,若二进制无执行权限或缺少 shebang,可能被误标为text,导致安装失败 —— 构建前用chmod +x确保可执行文件权限正确
cpack -G 多目标打包失败?别混用生成器参数
cpack -G "DEB;RPM" 看起来省事,但实际会触发两次独立构建流程,且中间缓存(如 _CPack_Packages/ 目录)互相污染,常见现象是第二个包生成空 .deb 或 .rpm,甚至报 Cannot find package description。
实操建议:
- 每次只打一种包:
cpack -G DEB<br>cpack -G RPM
- 清理中间产物再换目标:
rm -rf _CPack_Packages/<br>cpack -G RPM
- 想自动化多包输出,改用脚本分步调用,而不是靠
-G逗号拼接 - 注意
CPACK_GENERATOR是 CMake 变量,-G是 cpack 命令行参数 —— 两者冲突时,命令行优先级更高,CMake 中设的值会被覆盖
install() 规则没写对,打包出来就是空包
CPack 不读源码,它只打包 make install 实际安装到 CMAKE_INSTALL_PREFIX 的内容。如果 CMakeLists.txt 里漏了 install(TARGETS ...) 或 install(DIRECTORY ...),最终 deb/rpm 里就只有元数据,没有二进制、头文件或配置文件。
实操建议:
- 先手动验证安装路径:
cmake -DCMAKE_INSTALL_PREFIX=/tmp/staging ...<br>make install<br>ls /tmp/staging
—— 确保你要打包的东西真出现在那里 - 动态库必须显式
install(TARGETS ... LIBRARY DESTINATION lib),光有add_library(... SHARED)不会自动打包 - 头文件路径要和用户
#include方式一致,比如install(DIRECTORY include/mylib/ DESTINATION include/mylib),否则 deb 安装后#include <mylib></mylib>会找不到 - Debian 包默认过滤掉
.a静态库(除非加set(CPACK_DEBIAN_<em>PACKAGE</em>SHLIBDEPS OFF)),但 RPM 不过滤 —— 如果不想发静态库,得在install()里用EXCLUDE_FROM_ALL
make install,再谈 CPack。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











