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的工作流程,其实就三步。我画了个图,你看一眼就明白了:

步骤1:配置 cmake .. 生成CPack配置 步骤2:构建 cmake --build . 编译生成二进制 步骤3:打包 cpack 生成安装包 输出:.tar.gz / .deb / .rpm

具体来说:

  1. 配置阶段:运行cmake ..,CMake会读取你的CMakeLists.txt,生成构建系统,同时也会生成CPack的配置文件(CPackConfig.cmake)。
  2. 构建阶段:运行cmake --build .,把源代码编译成可执行文件、库文件等。
  3. 打包阶段:运行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的生成器,看看怎么打出不同格式的包。到时候我会分享一些我在跨平台打包时踩过的坑,保证有用。