使用 dpkg-deb 打包 - 记一次 tmux 编译
本文大部分翻译自 Building binary deb packages: a practical guide
背景故事:
我想要用 C++20 的
constexpr std::string
,最新的 GCC 12.1 才支持。Ubuntu 20.04 肯定是没有的,它连 GCC 11 都没有。Ubuntu 22.04 有个 gcc-12 的包,但其实是 12.0.1 版本。*.0.1 的都是 experimental 版本,我就没用,而且我想试试编译 GCC。
于是参考了这个
回答
编译了 GCC 12,为了方便管理、删除,用了之前就听说过的
checkinstall
,这个工具通过检测
make install
里产生的文件,自动生成、安装一个 deb 包,然后就可以(理论上)用
apt remove <pkg>
来优雅地删除。
然而我删除的时候不知为什么提示要删除 300 多 M,我以为确实安装了这么大就没注意,结果删完就炸了。
/usr/bin
里的程序全都用不了,错误提示都是
bash: error cannot find command
,但是其实文件都还在,也不知道是哪出了问题,我也不想深究了,我只劝读者朋友吸取这个血妈教训,不要再用
checkinstall
了 (事实上它也很久没更新了),用标准的
dpkg-deb
或
dpkg-buildpackage
,走正规的 deb packaging 流程。事实上没有想象中那么复杂,本文就是对这个打包流程的翻译介绍。
.deb 简介
.deb 文件是一个标准的 Unix
ar
archive,里面包含了你的包要安装的内容和 deb 包本身的一些 meta 信息,其中最重要的也是我们主要关注的是 control 文件。
一个 deb 包(注意不是生成的 .deb 包,而是打包时创建的文件夹)包含了一系列 *nux 文件系统下标准的文件夹,如
/usr/local
、
/usr
、
/opt
等,包含在这些文件夹中的文件最后就会被安装到对应的 *nux 文件夹下。
tmux_3.3a-1masquue_amd64
├── DEBIAN
│ └── control
└── usr
└── local
├── bin
│ └── tmux
└── share
└── man
└── man1
└── tmux.1
比如上面这个包目录,就会在安装时安装
/usr/local/bin/tmux
、
/usr/local/share/man/man1/tmux.1
这两个文件。
每个 deb 包及最后产生的 .deb 都遵循这个命名规则:
<name>_<version>-<revision>_<architecture>.deb
其中:
-
<name>
:包的名字 -
<version>
:版本号,一般以.
分隔 -
<revision>
:用于区分同一 upstream 版本的不同版本 -
<architecture>
:现在一般都是 amd64
本文以编译安装 tmux 3.3a 为例(Ubuntu 22.04 中的 tmux 是 3.2a),upstream 版本就是 3.3a。
revision 一般以数字开头,并且从1开始计数。我这里加上 maintainer 的名字。
最后结果就是 tmux_3.3a-1masquue_amd64 。
打包 deb
创建目录
$ pwd
.../tmux-3.3a
$ mkdir build && cd build
$ mkdir tmux_3.3a-1masquue_amd64
创建安装文件
本文主要用于创建安装本地编译结果的包。
一般开源软件安装时都用这个命令:
./configure
make && make install
但是我们希望不要直接安装到系统里,而是先安装到创建的 deb 目录。
假设最终希望安装到
/usr/local
,这也是自行编译的程序推荐的目录,参考
回答
。
mkdir -p tmux_3.3a-1masquue_amd64/usr/local
../configure --prefix="$(realpath tmux_3.3a-1masquue_amd64/usr/local)"
make && make install # no sudo
configure
一般接受
--prefix
参数,指定最后安装目录的前缀(注意需要绝对地址)。如果你要编译安装的项目没有使用
configure
,那你就要直接修改
Makefile
或是想其他办法了。
创建 control 文件
创建一个名为 control 的文件在 DEBIAN 目录中。注意必须是大写的 DEBIAN,大写的表示 binary package,小写的表示 source package,我们创建的是安装编译结果的二进制包,所以是大写。
mkdir tmux_3.3a-1masquue_amd64/DEBIAN
touch tmux_3.3a-1masquue_amd64/DEBIAN/control
control 文件每行包含一个 data field,对于 binary package,必须包含下面这些 field:
-
Package
:包的名字 -
Version
:版本号,包含了 revision,对这个例子就是 3.3a-1masquue -
Architecture
:和前面一样, 一般是 amd64 -
Maintainer
:维护者的名字和邮箱,格式为name <name at mail.com>
-
Description
:包的一句话描述。如果要包含更详细的描述,在这一行之后每行用一个空格开头继续。
最后完整的 control 像这样:
Package: tmux
Version: 3.3a-1masquue