1. CPack入门:CPack是什么、CPack与CMake的关系、CPack的工作流程、安装与基本配置
1.1 CPack到底是什么?
CPack,说白了就是CMake自带的打包工具。你想想看,我们辛辛苦苦用CMake把项目编译好了,生成了可执行文件、动态库、配置文件……然后呢?怎么把这些东西发给用户?
我刚开始做项目部署时,都是手动打包。把二进制文件拷出来,再写个shell脚本,打个tar.gz包。后来项目多了,版本多了,手动打包简直要命。有一次我忘了更新版本号,结果用户拿到的是旧版本……嗯,从那以后我就开始认真研究CPack了。
CPack能帮你自动完成这些事情:
- 自动收集编译产物
- 生成安装脚本
- 打包成各种格式(tar.gz、deb、rpm、NSIS安装包等)
- 自动处理版本号、许可证信息
一句话总结:CPack = CMake + 打包。你写好CMakeLists.txt,CPack帮你搞定分发。
1.2 CPack与CMake的关系
很多人问我:CPack和CMake到底是什么关系?
其实很简单。CMake负责「构建」,CPack负责「打包」。它们是一对搭档。
我习惯这样理解:
- CMake:把源代码变成二进制文件(编译、链接)
- CPack:把二进制文件变成安装包(压缩、归档、生成安装程序)
CPack是CMake的一部分。你安装了CMake,CPack就自动有了。不需要额外安装什么。
它们之间的数据传递靠的是CPackConfig.cmake和CPackSourceConfig.cmake这两个文件。CMake在构建时会生成这些配置文件,CPack读取它们来知道要打包什么、怎么打包。
我的经验:CMake和CPack的版本最好保持一致。我曾经遇到过CMake 3.16 + CPack 3.20的组合,结果某些变量不兼容,排查了半天。后来我统一用同一个版本的CMake,再也没出过这种问题。
1.3 CPack的工作流程
CPack的工作流程,其实就三步。我画了个图,你看一眼就明白了:
具体来说:
- 配置阶段:运行
cmake ..,CMake会读取你的CMakeLists.txt,生成构建系统,同时也会生成CPack的配置文件(CPackConfig.cmake)。 - 构建阶段:运行
cmake --build .,把源代码编译成可执行文件、库文件等。 - 打包阶段:运行
cpack,CPack读取配置文件,把构建产物打包成你想要的格式。
注意:很多人以为CPack可以跳过构建阶段。不行。CPack打包的是构建产物,不是源代码。你必须先构建成功,再打包。
1.4 安装与基本配置
安装CPack?其实你不需要单独安装。CPack是CMake的一部分。
你只需要安装CMake:
# Ubuntu/Debian
sudo apt-get install cmake
# CentOS/RHEL
sudo yum install cmake
# macOS (Homebrew)
brew install cmake
# Windows
# 去 https://cmake.org/download/ 下载安装包
装好之后,验证一下:
cmake --version
cpack --version
两个命令都能用,说明安装成功了。
1.5 第一个CPack示例
光说不练假把式。我们来写一个最简单的例子。
假设我有一个项目,结构是这样的:
myapp/
├── CMakeLists.txt
└── main.cpp
main.cpp内容:
#include <iostream>
int main() {
std::cout << "Hello CPack!" << std::endl;
return 0;
}
CMakeLists.txt内容:
cmake_minimum_required(VERSION 3.10)
project(MyApp VERSION 1.0.0)
add_executable(myapp main.cpp)
# 安装规则
install(TARGETS myapp DESTINATION bin)
# CPack配置
set(CPACK_PACKAGE_NAME "MyApp")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "My first CPack example")
set(CPACK_GENERATOR "TGZ") # 打包成tar.gz
include(CPack)
然后执行:
mkdir build && cd build
cmake ..
cmake --build .
cpack
你会看到生成了一个MyApp-1.0.0-Linux.tar.gz文件。解压看看:
tar -xzf MyApp-1.0.0-Linux.tar.gz
./MyApp-1.0.0-Linux/bin/myapp
输出:Hello CPack!
搞定!
我的习惯:我一般会在CMakeLists.txt里加上set(CPACK_GENERATOR "TGZ;DEB"),同时生成tar.gz和deb包。这样Linux用户可以直接用deb安装,其他用户可以用tar.gz。一次配置,多种输出,省事。
1.6 常用CPack变量速查
刚开始用CPack,记不住那么多变量。我整理了一份常用列表,你直接拿来用:
| 变量名 | 说明 | 示例 |
|---|---|---|
CPACK_PACKAGE_NAME |
包名 | MyApp |
CPACK_PACKAGE_VERSION |
版本号 | 1.0.0 |
CPACK_PACKAGE_VENDOR |
供应商/作者 | MyCompany |
CPACK_PACKAGE_DESCRIPTION_SUMMARY |
简短描述 | A useful tool |
CPACK_GENERATOR |
打包格式(多个用分号隔开) | TGZ;DEB;RPM |
CPACK_OUTPUT_FILE_PREFIX |
输出目录 | ./dist |
CPACK_PACKAGE_FILE_NAME |
自定义输出文件名 | MyApp-${CPACK_PACKAGE_VERSION} |
避坑指南:我曾经犯过一个错误——忘了在CMakeLists.txt里写include(CPack)。结果运行cpack时,它报错说找不到配置。记住,include(CPack)这行必须写在所有CPack变量设置之后。顺序很重要。
1.7 小结
这一章我们讲了:
- CPack是CMake的打包工具,帮你自动生成安装包
- CPack和CMake的关系:CMake负责构建,CPack负责打包
- 工作流程:配置 → 构建 → 打包,三步走
- 安装:装好CMake就有CPack,不需要额外安装
- 基本配置:设置几个变量,include(CPack),搞定
下一章,我们会深入CPack的生成器,看看怎么打出不同格式的包。到时候我会分享一些我在跨平台打包时踩过的坑,保证有用。