22、CPack变量与高级配置:`CPACK_PACKAGE_ICON`、`CPACK_RESOURCE_FILE_LICENSE`、`CPACK_STRIP_FILES`
说实话,很多人在CMake里折腾了大半年,构建已经玩得挺溜了。但一到打包环节,就卡住了。为什么?因为CPack的变量体系看着简单,实际坑不少。今天我就挑三个最常用、也最容易出问题的变量,跟你好好聊聊。
22.1 先画张图:这三个变量到底管什么?
在动手之前,我习惯先理清脉络。这三个变量分别管三件事:图标、许可证、二进制裁剪。说白了就是:你的安装包长什么样、带什么法律文件、能不能瘦身。
嗯,这张图你看完应该有个整体印象了。下面我们一个一个拆开讲。
22.2 CPACK_PACKAGE_ICON:给你的安装包换个脸
我个人习惯,不管项目大小,都会给安装包配个图标。你想想看,用户下载完双击安装包,看到的是一张默认的空白图标,第一印象就差了。
CPACK_PACKAGE_ICON 这个变量,就是用来指定安装包图标的路径。但这里有个坑——不同生成器对图标格式要求不一样。
| 生成器 | 支持的图标格式 | 备注 |
|---|---|---|
| NSIS (Windows) | .ico | 推荐 32x32 或 48x48 |
| DragNDrop (macOS) | .icns | 需要包含多尺寸 |
| IFW (Qt Installer) | .png / .ico | 看具体配置 |
典型用法:
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources/icon.ico")
# 如果是 macOS,记得用 .icns
if(APPLE)
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources/icon.icns")
endif()
⚠️ 我曾经踩过的坑: 图标路径必须是绝对路径,或者 CMake 变量展开后的完整路径。用相对路径?CPack 会直接忽略,最后生成一个没有图标的安装包。排查了半天才发现是路径问题。
22.3 CPACK_RESOURCE_FILE_LICENSE:法律文件不能省
说实话,很多开源项目对许可证文件不太上心。但如果你做商业软件,或者要发布到 macOS App Store、Windows Store,许可证文件是强制要求的。
CPACK_RESOURCE_FILE_LICENSE 指定的是安装过程中展示给用户的许可证文本。CPack 内置了一个默认的 Copyright.txt,但那东西太简陋了,我建议你用自己的。
💡 我的经验:
- Windows (NSIS):支持 .rtf 格式,可以带格式和换行
- macOS (DragNDrop):支持 .txt 或 .html
- Linux (DEB/RPM):一般用 .txt,但 DEB 有自己的一套 license 机制
# 推荐写法:跨平台兼容
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt")
# 如果你需要针对不同平台用不同格式
if(WIN32)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.rtf")
else()
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt")
endif()
⚠️ 注意: 许可证文件必须存在于源码目录中,CPack 不会帮你生成。另外,文件编码建议用 UTF-8 without BOM,否则 Windows 下可能乱码。我遇到过用户反馈说「你们的协议全是乱码」——其实就是编码问题。
22.4 CPACK_STRIP_FILES:发布前记得瘦身
这个变量,说白了就是告诉 CPack:打包的时候,把二进制文件里的调试符号去掉。
为什么要做这件事?
- 减小体积:调试符号可能占二进制体积的 30%~50%
- 保护代码:去掉符号表,别人逆向你的程序会更困难
- 发布规范:正式发布的版本不应该带调试信息
# 最简单的用法
set(CPACK_STRIP_FILES TRUE)
# 如果你只想 strip 特定文件
set(CPACK_STRIP_FILES
"${CMAKE_INSTALL_PREFIX}/bin/myapp"
"${CMAKE_INSTALL_PREFIX}/lib/libmylib.so"
)
🔧 高级用法: 配合 INSTALL 命令的 STRIP 参数
install(TARGETS myapp
RUNTIME DESTINATION bin
STRIP) # 安装时直接 strip
这样你甚至不需要设置 CPACK_STRIP_FILES,安装过程就已经把符号去掉了。
💡 我个人习惯: 开发阶段用 Debug 模式,调试符号保留。但到了打包阶段,我会在 CMakeLists.txt 里加一个判断:
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CPACK_STRIP_FILES TRUE)
endif()
这样只有 Release 包才会 strip,Debug 包留着方便自己调试。
22.5 三者配合:一个完整的例子
好了,理论讲完了。我们来看一个实际项目中怎么用。这是我之前做的一个桌面工具项目的打包配置片段:
# ---------- 图标 ----------
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/packaging/icon.ico")
if(APPLE)
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/packaging/icon.icns")
endif()
# ---------- 许可证 ----------
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt")
# ---------- Strip ----------
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CPACK_STRIP_FILES TRUE)
message(STATUS "Release build: will strip binaries")
endif()
# ---------- 其他必要变量 ----------
set(CPACK_PACKAGE_NAME "MyTool")
set(CPACK_PACKAGE_VERSION "2.1.0")
set(CPACK_PACKAGE_VENDOR "MyCompany")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A handy desktop tool")
# ---------- 最终 include ----------
include(CPack)
这段配置我用了好几年,基本没出过问题。你直接复制过去,改改项目名就能用。
22.6 避坑指南:我踩过的三个坑
- 图标不显示:路径用了相对路径,或者 .ico 文件本身损坏。解决办法:用绝对路径,并且用专业工具生成 .ico。
- 许可证乱码:文件编码不是 UTF-8 without BOM。Windows 下尤其容易出这个问题。我后来统一用 VS Code 保存为 UTF-8 格式,再没出过乱码。
- Strip 后程序崩溃:如果你用了某些第三方库,strip 可能会把必要的符号也去掉。解决办法:只 strip 自己的二进制,或者用
objcopy --strip-debug手动控制。
总结一下:
CPACK_PACKAGE_ICON— 安装包的门面,别省CPACK_RESOURCE_FILE_LICENSE— 法律合规,必须做CPACK_STRIP_FILES— 发布前瘦身,养成习惯
这三个变量配置好,你的安装包至少从「能用」变成了「专业」。