Debian 二进制软件包构建 HOWTO

Chr. Clemens Lee


          
        

2002-11-30, $Date: 2005/08/09 20:49:46 $

修订历史
修订 4.02005-08-09修订者: ccl
更新了电子邮件地址,并添加了由 Oguz Yarimtepe 提供的土耳其语翻译链接
修订 3.02003-12-19修订者: ccl
修复了 Claudio Cattazzo 报告的两个拼写错误
修订 2.02003-12-13修订者: ccl
应用了 Frank Lichtenheld 的反馈
修订 1.02003-11-08修订者: ccl
初版

本迷你 HOWTO 展示了如何构建一个最小的 Debian .deb 软件包。


目录
1. 简介
1.1. Web 上的资源
2. 开始
3. 软件包结构
3.1. debian-binary
3.2. data.tar.gz
3.3. control.tar.gz
4. 实战
4.1. control
4.2. dpkg-deb
5. 再次检查
5.1. lintian
5.2. 最简文档
5.3. fakeroot
5.4. 更多文档
6. 总结
7. 其他
8. 致谢
9. 链接

1. 简介

创建新归档的预期用途是仅在您自己的机器上安装它,而不是将其放入官方 Debian 发行版中。要遵循“官方”流程,请学习 Debian 新维护者指南

正常的 Debian 软件包会获得一个合适的源码包,其中包括一个 debian/rules 文件,该文件自动化了创建二进制软件包所涉及的步骤。这里我们仅展示如何将一个简单的 shell 脚本或二进制可执行文件打包成一个小的二进制软件包。

顺便说一句,我假设您知道如何使用 'tar'、'man',以及什么是 '.tar.gz' 文件和 Debian(以及如何使用编辑器 ;-),但我假设您从未接触过 'ar' 或 'dpkg' 之类的程序。


1.1. Web 上的资源

Debian 参考手册 提供了关于所有 Debian 特定内容的优秀概述和详细信息。

创建您自己的 Debian 软件包的官方文档是 Debian 新维护者指南


2. 开始

摘自 Debian 参考手册 2.2.2 2002-11-30:“Debian 二进制软件包格式的内部结构在 deb(5) 手册页中进行了描述。由于这种内部格式可能会发生变化(在 Debian 的主要版本之间),请始终使用 dpkg-deb(8) 来操作 .deb 文件。”

摘自 dpkg-deb 手册页:“dpkg-deb 打包、解包并提供有关 Debian 归档文件的信息。.deb 文件也可以使用artar单独操作(如果必要)。使用 dpkg 从您的系统中安装和删除软件包。”

您可能会在目录 '/var/cache/apt/archives/' 中找到许多示例 .deb 文件。使用 'dpkg-deb -I somepackage.deb' 您可能会获得对该软件包提供的特定内容的总体概述。'dpkg-deb -c somepackage.deb' 列出将要安装的所有文件。

使用 'ar tv somepackage.deb' 列出 .deb 文件的内容。使用 'x' 选项提取文件。


3. 软件包结构

让我们更仔细地检查一个示例软件包。例如,文件 'parted_1.4.24-4_i386.deb' 包含以下三个文件

$ ar tv parted_1.4.24-4_i386.deb
rw-r--r-- 0/0      4 Mar 28 13:46 2002 debian-binary
rw-r--r-- 0/0   1386 Mar 28 13:46 2002 control.tar.gz
rw-r--r-- 0/0  39772 Mar 28 13:46 2002 data.tar.gz

现在我们可以开始提取所有文件,包括 tar 文件的内容。


3.1. debian-binary

此文件的内容是 "2.0\n"。这说明了 deb 文件格式的版本。对于 2.0,所有其他行都将被忽略。


3.2. data.tar.gz

'data.tar.gz' 文件包含所有将要安装的文件及其目标路径

drwxr-xr-x root/root         0 2002-03-28 13:44:57 ./
drwxr-xr-x root/root         0 2002-03-28 13:44:49 ./sbin/
-rwxr-xr-x root/root     31656 2002-03-28 13:44:49 ./sbin/parted
drwxr-xr-x root/root         0 2002-03-28 13:44:38 ./usr/
drwxr-xr-x root/root         0 2002-03-28 13:44:41 ./usr/share/
drwxr-xr-x root/root         0 2002-03-28 13:44:38 ./usr/share/man/
drwxr-xr-x root/root         0 2002-03-28 13:44:52 ./usr/share/man/man8/
-rw-r--r-- root/root      1608 2002-03-28 13:44:37 ./usr/share/man/man8/parted.8.gz
drwxr-xr-x root/root         0 2002-03-28 13:44:41 ./usr/share/doc/
drwxr-xr-x root/root         0 2002-03-28 13:44:52 ./usr/share/doc/parted/
-rw-r--r-- root/root      1880 2002-03-07 14:20:08 ./usr/share/doc/parted/README.Debian
-rw-r--r-- root/root      1347 2002-02-27 01:40:50 ./usr/share/doc/parted/copyright
-rw-r--r-- root/root      6444 2002-03-28 13:37:33 ./usr/share/doc/parted/changelog.Debian.gz
-rw-r--r-- root/root     15523 2002-03-28 02:36:43 ./usr/share/doc/parted/changelog.gz

它必须是 deb 归档文件中的最后一个文件。


3.3. control.tar.gz

在我们的示例中,此文件具有以下内容

-rw-r--r--    1 root     root         1336 Mar 28  2002 control
-rw-r--r--    1 root     root          388 Mar 28  2002 md5sums
-rwxr-xr-x    1 root     root          253 Mar 28  2002 postinst
-rwxr-xr-x    1 root     root          194 Mar 28  2002 prerm

'md5sums' 包含 data.tar.gz 中每个文件的 md5sum。在我们的示例中,内容如下所示

1d15dcfb6bb23751f76a2b7b844d3c57  sbin/parted
4eb9cc2e192f1b997cf13ff0b921af74  usr/share/man/man8/parted.8.gz
2f356768104a09092e26a6abb012c95e  usr/share/doc/parted/README.Debian
a6259bd193f8f150c171c88df2158e3e  usr/share/doc/parted/copyright
7f8078127a689d647586420184fc3953  usr/share/doc/parted/changelog.Debian.gz
98f217a3bf8a7407d66fd6ac8c5589b7  usr/share/doc/parted/changelog.gz

不用担心,'md5sum' 文件以及 'postinst' 和 'prerm' 文件对于您的第一个软件包不是强制性的。但请注意它们的存在,每个合适的官方 Debian 软件包都有它们,这是有充分理由的。

'prerm' 和 'postinst' 似乎负责删除旧的文档文件,并将 doc 链接到 share/doc。

$ cat postinst
#!/bin/sh
set -e
# Automatically added by dh_installdocs
if [ "$1" = "configure" ]; then
  if [ -d /usr/doc -a ! -e /usr/doc/parted -a -d /usr/share/doc/parted ]; then
    ln -sf ../share/doc/parted /usr/doc/parted
  fi
fi
# End automatically added section

$ cat prerm
#!/bin/sh
set -e
# Automatically added by dh_installdocs
if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/parted ]; then
  rm -f /usr/doc/parted
fi
# End automatically added section

最后,是最有趣的文件

$ cat control
Package: parted
Version: 1.4.24-4
Section: admin
Priority: optional
Architecture: i386
Depends: e2fsprogs (>= 1.27-2), libc6 (>= 2.2.4-4), libncurses5 (>= \
5.2.20020112a-1), libparted1.4 (>= 1.4.13+14pre1), libreadline4 (>= \
4.2a-4), libuuid1
Suggests: parted-doc
Conflicts: fsresize
Replaces: fsresize
Installed-Size: 76
Maintainer: Timshel Knoll <timshel@debian.org>
Description: The GNU Parted disk partition resizing program
 GNU Parted is a program that allows you to create, destroy,
 resize, move and copy hard disk partitions. This is useful
 for creating space for new operating systems, reorganizing
 disk usage, and copying data to new hard disks.
 .
 This package contains the Parted binary and manual page.
 .
 Parted currently supports DOS, Mac, Sun, BSD, GPT and PC98
 disklabels/partition tables, as well as a 'loop' (raw disk)
 type which allows use on RAID/LVM. Filesystems supported are
 ext2, ext3, FAT (FAT16 and FAT32) and linux-swap. Parted can
 also detect HFS (Mac OS), JFS, NTFS, ReiserFS, UFS and XFS
 filesystems, but cannot create/remove/resize/check these
 filesystems yet.
 .
 The nature of this software means that any bugs could cause
 massive data loss. While there are no known bugs at the moment,
 they could exist, so please back up all important files before
 running it, and do so at your own risk.

有关 control 文件的更多信息,可以通过 'man 5 deb-control'.


4. 实战

现在是时候亲自动手实践了。我有一个名为 'linuxstatus' 的简单 shell 脚本,我想将其安装为 '/usr/bin/linuxstatus'。因此,首先让我们在文件 'linuxstatus' 旁边创建一个名为 'debian' 的目录。

$ mkdir -p ./debian/usr/bin
$ cp linuxstatus ./debian/usr/bin

4.1. control

让我们从 control 文件开始。版本号必须有一个破折号和一个额外的 Debian 软件包版本号,例如 '1.1-1'。如果您的程序例如仅由可移植的 shell 脚本组成,请使用 'all' 作为其 'Architecture'。

对于 'Depends',您可能需要找出您的新软件包依赖的特定文件或程序属于哪个软件包。您可以使用 'dpkg -S <file>' 来找出这一点,例如

$ dkpg -S /bin/cat
coreutils: /bin/cat

然后要了解有关软件包 'coreutils' 的更多信息,您可以使用命令 'apt-cache showpkg coreutils',它将告诉您,除其他外,系统上安装的当前版本号。

作为旁注,还有两种方法可以找到相同的信息。有一个网页可以搜索 Debian 文件:http://www.debian.org/distrib/packages。转到该页面底部填写 Web 表单。

最后但并非最不重要的一点是,有一个名为 'kpackage' 的不错的 GUI 应用程序,它提供了方便的软件包浏览选项,并且还允许在给定单个文件名称后搜索软件包。

'Suggests'、'Conflicts' 和 'Replaces' 等,如果不需要可以省略。

这是我们的第一个 'control' 文件的结果

Package: linuxstatus
Version: 1.1-1
Section: base
Priority: optional
Architecture: all
Depends: bash (>= 2.05a-11), textutils (>= 2.0-12), awk, procps (>= \
1:2.0.7-8), sed (>= 3.02-8), grep (>= 2.4.2-3), coreutils (>= 5.0-5)
Maintainer: Chr. Clemens Lee <clemens@kclee.de>
Description: Linux system information
 This script provides a broad overview of different
 system aspects.

'control' 文件被复制到另一个 'debian' 目录内名为 'DEBIAN' 的目录中。

$ mkdir -p debian/DEBIAN
$ find ./debian -type d | xargs chmod 755   # this is necessary on Debian Woody, don't ask me why
$ cp control debian/DEBIAN

如果您希望您的软件包在未来有更广泛的受众,那么阅读这篇 编写 Debian 软件包描述 文章可能会有所帮助。


4.2. dpkg-deb

现在几乎完成了。只需输入

$ dpkg-deb --build debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.1-1_all.deb

嗯,这比预期的要容易得多。现在我们只需要在我们的机器上安装这个软件包就完成了

root# dpkg -i ./linuxstatus_1.1-1_all.deb

输入 'linuxstatus' 或 'ls -l /usr/bin/linuxstatus' 以查看它是否有效。如果您不再喜欢您的软件包,只需输入 'dpkg -r linuxstatus' 并再次检查软件包是否已卸载。如果您安装了较新版本,则不必先删除旧版本。

如果您对 Debian 软件包的版本编号方案和命名约定感到好奇,请阅读 此章节Debian 参考手册 中。


5. 再次检查

既然您已经获得了第一印象并构建了自己的二进制软件包,那么是时候变得更加认真,并查看我们生产的软件包的质量了。


5.1. lintian

幸运的是,Debian 项目为我们提供了一个类似 'lint' 的工具来检查 Debian 软件包。此工具名为 'lintian'。如果您尚未在系统上安装它,那么现在是一个好时机(apt-get install lintian).

现在我们在我们的新软件包文件上使用这个小小的宝藏工具

$ lintian linuxstatus_1.1-1_all.deb
E: linuxstatus: binary-without-manpage linuxstatus
E: linuxstatus: no-copyright-file
W: linuxstatus: prerm-does-not-remove-usr-doc-link
W: linuxstatus: postinst-does-not-set-usr-doc-link

嗯,看起来不太完美。我们缺少 man 手册页、版权文件,以及那些 'prerm' 和 'postinst' 脚本。


5.2. 最简文档

这里不是说太多关于编写和创建 man 手册页的地方,有很多书都有一个或另一个章节与此主题相关,并且还有在线的 Linux MAN-PAGE-HOWTO。所以让我们做一个小小的时光倒流,假设您现在在位置./man/man1/linuxstatus.1.

为您的脚本准备了一个完美的 man 手册页。对于 'copyright' 文件也是如此。您可以在/usr/share/doc目录中使用此命令找到足够的示例find /usr/share/doc -name "copyright"

这是我们自己的 'copyright' 文件示例

linuxstatus

Copyright: Chr. Clemens Lee <clemens@kclee.de>

2002-12-07

The home page of linuxstatus is at: 
http://www.kclee.de/clemens/unix/index.html#linuxstatus

The entire code base may be distributed under the terms of the GNU General
Public License (GPL), which appears immediately below.  Alternatively, all
of the source code as any code derived from that code may instead be
distributed under the GNU Lesser General Public License (LGPL), at the
choice of the distributor. The complete text of the LGPL appears at the
bottom of this file.

See /usr/share/common-licenses/(GPL|LGPL)

对于 'prerm' 和 'postinst' 脚本,我们将 示例 从上面的 'parted' 软件包一对一地复制到我们自己的项目目录中同名的文件中。这些文件应该对我们同样有效。

现在我们再次创建 debian 软件包。在 'control' 文件中,我们首先将版本号从 1.1-1 增加到 1.2-1(因为我们编写了一个新的 man 手册页,所以我们增加了内部版本号)。我们还需要将新文件复制到其适当的位置

$ mkdir -p ./debian/usr/share/man/man1
$ mkdir -p ./debian/usr/share/doc/linuxstatus
$ find ./debian -type d | xargs chmod 755
$ cp ./man/man1/linuxstatus.1 ./debian/usr/share/man/man1
$ cp ./copyright ./debian/usr/share/doc/linuxstatus
$ cp ./prerm ./postinst ./debian/DEBIAN
$ gzip --best ./debian/usr/share/man/man1/linuxstatus.1
$
$ dpkg-deb --build debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.2-1_all.deb

Gzip 是必要的,因为 lintian 期望 man 手册页文件尽可能压缩。


5.3. fakeroot

现在让我们看看我们的软件包是否已成为更好的 Debian 公民

$ lintian linuxstatus_1.2-1_all.deb
E: linuxstatus: control-file-has-bad-owner prerm clemens/clemens != root/root
E: linuxstatus: control-file-has-bad-owner postinst clemens/clemens != root/root
E: linuxstatus: bad-owner-for-doc-file usr/share/doc/linuxstatus/ clemens/clemens != root/root
E: linuxstatus: bad-owner-for-doc-file usr/share/doc/linuxstatus/copyright clemens/clemens != root/root
E: linuxstatus: debian-changelog-file-missing

哎呀,新的抱怨。好的,我们不会放弃。实际上,大多数错误似乎都是相同的问题。我们的所有文件都打包为用户和组 'clemens',而我假设大多数人更喜欢将它们安装为 'root/root'。但这可以使用工具 'fakeroot' 轻松修复。所以让我们快速修复并检查一下(同时忽略 changelog 问题)

$ fakeroot dpkg-deb --build debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.2-1_all.deb
$ lintian linuxstatus_1.2-1_all.deb
E: linuxstatus: debian-changelog-file-missing

很好,但我们还有一个文件要添加到软件包中。


5.4. 更多文档

让我提前告诉您,除了 'doc/linuxstatus' 目录中的 'changelog' 文件外,还需要 'changelog.Debian' 文件。两者都应该进行 gzip 压缩。

这是两个示例文件,'changelog'

linuxstatus (1.2-1)

  * Made Debian package lintian clean.

 -- Chr. Clemens Lee <clemens@kclee.de>  2002-12-13

和 'changelog.Debian'

linuxstatus Debian maintainer and upstream author are identical.
Therefore see also normal changelog file for Debian changes.

Debian 策略文件有更多关于 changelog 格式 文件的详细信息。

现在希望我们的最后一步是

$ cp ./changelog ./changelog.Debian ./debian/usr/share/doc/linuxstatus
$ gzip --best ./debian/usr/share/doc/linuxstatus/changelog 
$ gzip --best ./debian/usr/share/doc/linuxstatus/changelog.Debian
$ fakeroot dpkg-deb --build ./debian
dpkg-deb: building package `linuxstatus' in `debian.deb'.
$ mv debian.deb linuxstatus_1.2-1_all.deb
$ lintian linuxstatus_1.2-1_all.deb

啊,我们不再收到抱怨了 :-)。作为 root 用户,您现在可以使用标准 'dpkg -i' 命令在旧版本之上安装此软件包。

root# dpkg -i ./linuxstatus_1.2-1_all.deb
(Reading database ... 97124 files and directories currently installed.)
Preparing to replace linuxstatus 1.1-1 (using linuxstatus_1.2-1_all.deb) ...
Unpacking replacement linuxstatus ...
Setting up linuxstatus (1.2-1) ...

6. 总结

为了不混淆,让我们回顾一下我们构建二进制 Debian 软件包所采取的所有步骤。

先决条件文件

  1. 一个或多个二进制可执行文件或 shell 脚本文件

  2. 每个可执行文件的 man 手册页

  3. 一个 'control' 文件

  4. 一个 'copyright' 文件

  5. 一个 'changelog' 和 'changelog.Debian' 文件

设置临时 'debian' 目录

  1. 创建 'debian/usr/bin' 目录(或您计划放置可执行文件的任何位置)

  2. 创建 'debian/usr/share/man/man1'(或您的 man 手册页所属的任何部分)

  3. 创建 'debian/DEBIAN' 目录

  4. 创建 'debian/usr/share/doc/<软件包名称>'

  5. 确保 'debian' 的所有子目录都具有文件权限 0755

将文件复制到临时 'debian' 树中

  1. 将可执行文件复制到 'debian/usr/bin' 目录(或您计划放置可执行文件的任何位置)

  2. 将 man 手册页文件复制到 'debian/usr/share/man/man1' 目录

  3. 将 'control' 文件复制到 'debian/DEBIAN' 目录

  4. 将 'copyright'、'changelog' 和 'changelog.Debian' 文件复制到 'debian/usr/share/doc/<软件包名称>'

  5. 在临时 'debian' 树中使用选项 '--best' 对 man 手册页、'copyright'、'changelog' 和 'changelog.Debian' 文件进行 gzip 压缩

构建并检查二进制 Debian 软件包

  1. 调用 'dpkg-deb --build' 在 'fakeroot' 上使用 'debian' 目录

  2. 将生成的 'debian.deb' 文件重命名为其最终软件包名称,包括版本和架构信息

  3. 使用 'lintian'


检查生成的 .deb 软件包文件是否符合 Debian 策略

7. 其他

这里没有涵盖许多细节,例如如何分发 Unix 守护进程、配置文件等等。但最重要的是,我想再次强调,对于 Debian 维护者来说,软件包是源码包,而不是二进制软件包。他们从不直接与内部二进制软件包交互。实际上只有 'dpkg-deb' 和 'dpkg

' 的开发者需要知道它们是什么。事实上,不建议这样做。

如果开发者要向某人解释如何构建 Debian 软件包,他肯定会解释如何制作源码包以及如何构建它。

另一方面,并非每个开发者都想(现在)将其软件提交给 Debian,但仍然希望从 'dpkg' 等打包系统提供的优势中获益,而无需发布软件包源代码。就我个人而言,我仍然会将我的免费软件项目作为 tar.gz 文件发布,其中包含所有平台的源代码等,同时我计划为只想安装和使用我的软件的 Debian 用户提供越来越多的 '.deb' 软件包,以方便他们使用。


如果有人想迈出下一步,将软件包提交给 Debian,您必须继续学习 Debian 新维护者指南以及 Debian 策略手册。在您着手创建 Debian 源码包时,还可以查看 debian-mentors 邮件列表,以了解经验丰富的 Debian 开发者和初学者之间的互动,并解决您可能遇到的类似问题。

8. 致谢


Oguz Yarimtepe 将 此 HOWTO 翻译成土耳其语 [2005-08-09]。

9. 链接 Debian 新维护者指南:�
http://www.debian.org/doc/maint-guide/ Debian:�
http://www.debian.org/ Debian 参考手册:�
http://www.debian.org/doc/manuals/reference/reference.en.html Debian 软件包:�
http://www.debian.org/distrib/packages 编写 Debian 软件包描述:�
http://people.debian.org/~walters/descriptions.html Linux MAN-PAGE-HOWTO:�
http://www.tldp.org/HOWTO/mini/Man-Page.html Debian 策略手册:�
http://www.debian.org/doc/debian-policy/ Debian Mentors:�
http://lists.debian.org/debian-mentors/ Linux 文档项目:�
http://www.tldp.org/ Plug: 我自己的 Unix 小页面:�