22、CPack变量与高级配置:`CPACK_PACKAGE_ICON`、`CPACK_RESOURCE_FILE_LICENSE`、`CPACK_STRIP_FILES`

说实话,很多人在CMake里折腾了大半年,构建已经玩得挺溜了。但一到打包环节,就卡住了。为什么?因为CPack的变量体系看着简单,实际坑不少。今天我就挑三个最常用、也最容易出问题的变量,跟你好好聊聊。

22.1 先画张图:这三个变量到底管什么?

在动手之前,我习惯先理清脉络。这三个变量分别管三件事:图标许可证二进制裁剪。说白了就是:你的安装包长什么样、带什么法律文件、能不能瘦身。

CPack 高级配置三剑客 CPACK_PACKAGE_ICON 安装包图标 .ico / .icns NSIS / DragNDrop 让安装包有辨识度 CPACK_RESOURCE_FILE_LICENSE 许可证文件 .txt / .rtf 安装时展示 法律合规必备 CPACK_STRIP_FILES 剥离调试符号 ON / OFF 减小体积 发布前必做 三者配合:图标 + 许可证 + 裁剪 = 专业级安装包

嗯,这张图你看完应该有个整体印象了。下面我们一个一个拆开讲。

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 避坑指南:我踩过的三个坑

  1. 图标不显示:路径用了相对路径,或者 .ico 文件本身损坏。解决办法:用绝对路径,并且用专业工具生成 .ico。
  2. 许可证乱码:文件编码不是 UTF-8 without BOM。Windows 下尤其容易出这个问题。我后来统一用 VS Code 保存为 UTF-8 格式,再没出过乱码。
  3. Strip 后程序崩溃:如果你用了某些第三方库,strip 可能会把必要的符号也去掉。解决办法:只 strip 自己的二进制,或者用 objcopy --strip-debug 手动控制。

总结一下:

  • CPACK_PACKAGE_ICON — 安装包的门面,别省
  • CPACK_RESOURCE_FILE_LICENSE — 法律合规,必须做
  • CPACK_STRIP_FILES — 发布前瘦身,养成习惯

这三个变量配置好,你的安装包至少从「能用」变成了「专业」。


公众号:蓝海资料掘金营,微信 deep3321