第三章:TGZ格式详解——生成tar.gz压缩包,Linux/Unix下的标配

说到TGZ格式,其实就是tar.gz的缩写。说白了,就是把一堆文件先用tar打包成一个整体,再用gzip压缩一下。我在Linux服务器上折腾了这么多年,这玩意儿几乎天天见。

为什么会这么流行?因为Linux/Unix生态里,tar和gzip是系统自带的,不需要额外装任何东西。你想想看,要是你写了个CMake项目,想让别人在Linux上一键编译,用TGZ格式分发源码,对方直接tar -xzf就解开了,多省事。

3.1 TGZ的核心机制

TGZ其实是个组合拳。tar负责把目录结构、文件权限、时间戳这些元信息保留下来,gzip负责把体积压小。我见过不少新手直接拿zip去Linux上发,结果解出来权限全丢了,还得手动chmod,麻烦得很。

CPack生成TGZ时,内部流程是这样的:

  1. 先构建项目,生成二进制或源码文件
  2. 用tar把文件打包成一个临时归档
  3. 再用gzip压缩,生成最终的.tar.gz文件

嗯,这里要注意一点:CPack生成的TGZ默认会保留文件的可执行权限。我在项目中遇到过,有些脚本打包后到客户机器上直接就能跑,就是因为权限没丢。

3.2 配置参数详解

CPack为TGZ格式提供了一些专用参数。我挑几个最常用的说说:

参数名 作用 我的建议
CPACK_TGZ_COMPRESSION 压缩级别,可选1-9 默认6,兼顾速度和体积
CPACK_TGZ_EXTENSION 自定义后缀名 保持默认.tar.gz就行
CPACK_INCLUDE_TOPLEVEL_DIRECTORY 是否包含顶层目录 建议设为ON,方便用户管理
CPACK_STRIP_FILES 是否剥离调试符号 发布版建议ON,能省不少空间

我个人习惯在CMakeLists.txt里这样配置:

set(CPACK_GENERATOR "TGZ")
set(CPACK_TGZ_COMPRESSION 9)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY ON)
set(CPACK_STRIP_FILES ON)
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-linux-x64")

压缩级别设成9,虽然打包慢一点,但用户下载快啊。我曾经给一个嵌入式设备分发固件,TGZ从6改成9后,体积小了30%,客户那边下载时间直接减半。

3.3 实战案例:发布一个C++命令行工具

假设你写了个叫logparser的小工具,用来分析日志文件。现在要打包成TGZ给Linux用户用。来看看完整的CMake配置:

cmake_minimum_required(VERSION 3.15)
project(logparser VERSION 1.2.0 LANGUAGES CXX)

add_executable(logparser main.cpp parser.cpp)

install(TARGETS logparser DESTINATION bin)
install(FILES README.md LICENSE DESTINATION share/doc/logparser)

# CPack配置
set(CPACK_GENERATOR "TGZ")
set(CPACK_PACKAGE_NAME "logparser")
set(CPACK_PACKAGE_VERSION "1.2.0")
set(CPACK_PACKAGE_VENDOR "MyCompany")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A fast log file parser")

# TGZ专用配置
set(CPACK_TGZ_COMPRESSION 9)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY ON)
set(CPACK_STRIP_FILES ON)

# 安装后执行脚本,确保权限正确
set(CPACK_INSTALL_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/post_install.cmake")

include(CPack)

然后执行打包命令:

mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cpack -G TGZ

你会得到一个logparser-1.2.0-linux-x64.tar.gz文件。用户拿到后,直接解压就能用:

tar -xzf logparser-1.2.0-linux-x64.tar.gz
cd logparser-1.2.0-linux-x64
./bin/logparser --help
小技巧: 如果你想让用户解压后直接运行,可以在post_install.cmake里把可执行文件路径加到PATH。我一般会在安装目录下放个env.sh脚本,用户source一下就能用。

3.4 避坑指南

我曾经在打包一个大型项目时,发现TGZ文件解压后,某些配置文件权限变成了644,导致程序启动报错。排查了半天,原来是install命令没指定权限。

解决方案很简单:

install(FILES config.ini DESTINATION etc PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

另一个坑是符号链接。如果项目里用了软链接,tar默认会保留,但gzip压缩后解压时可能出问题。我建议在打包前用readlink -f把符号链接解析成实际文件。

注意: TGZ不支持分卷压缩。如果你的包超过2GB,建议改用tar.xz或者考虑分发包。我遇到过有人硬塞了4GB的TGZ,结果用户用老版本的tar解压直接报错。

3.5 TGZ vs 其他格式

简单对比一下TGZ和另外两种常见格式:

特性 TGZ DEB RPM
跨发行版 ✅ 通用 ❌ Debian系 ❌ RedHat系
依赖管理 ❌ 无 ✅ 自动处理 ✅ 自动处理
安装复杂度 低(解压即用) 中(需root) 中(需root)
文件权限保留 ✅ 完整 ✅ 完整 ✅ 完整

说白了,如果你的软件是给开发者用的,或者需要跨多个Linux发行版,TGZ是最稳妥的选择。我自己的开源项目一直用TGZ分发,用户反馈从来没出过兼容性问题。

3.6 总结

TGZ格式在Linux/Unix环境下就是标配。配置简单,兼容性好,几乎零学习成本。你只要记住三点:

  • 压缩级别设9,用户下载快
  • 记得保留文件权限,特别是可执行位
  • 包太大时考虑换格式或分卷

下一章我们会聊NSIS格式,那是Windows下的打包利器。到时候对比着看,你会发现不同平台的打包思路差异还挺大的。