Chapter 5. 基本内容

Table of Contents

5.1. 打包工作流
5.1.1. debhelper 软件包
5.2. Historical perspective of Debian packaging practices
5.3. Future perspective on Debian packaging practices
5.4. 软件包名称和版本
5.5. 原生 Debian 软件包
5.6. debian/rules
5.6.1. dh
5.6.2. 简单的 debian/rules
5.6.3. 自定义 debian/rules
5.6.4. debian/rules 中的变量
5.6.5. 可重现的构建
5.7. debian/control
5.7.1. Debian 二进制软件包的拆分
5.7.1.1. debmake -b
5.7.1.2. 拆包的场景和例子
5.7.1.3. 库软件包名称
5.7.2. Substvar
5.7.3. binNMU 安全
5.8. debian/changelog
5.9. debian/copyright
5.10. debian/patches/*
5.10.1. dpkg-source -x
5.10.2. dquilt 和 dpkg-source
5.11. debian/upstream/signing-key.asc
5.12. debian/watch 和 DFSG
5.13. 其它 debian/* 文件
5.14. Debian 打包的定制化
5.15. 在版本控制系统中进行记录(标准)
5.16. 在版本控制系统中进行记录(备选方案)
5.17. 构建软件包时排除不必要的内容
5.17.1. 使用 debian/rules clean 进行修复
5.17.2. 使用版本控制系统修复
5.17.3. 使用 extend-diff-ignore 修复
5.17.4. 使用 tar-ignore 修复
5.18. 上游构建系统
5.18.1. Autotools
5.18.2. CMake
5.18.3. Meson
5.18.4. Python distutils
5.19. 调试信息
5.19.1. 新的 -dbgsym 软件包(Stretch 9.0 或更新)
5.20. 库软件包
5.20.1. 库符号
5.20.2. 库变迁
5.21. debconf
5.22. 多体系结构
5.22.1. 多架构库路径
5.22.2. 多架构头文件路径
5.22.3. 多架构支持下的 *.pc 文件路径
5.23. 编译加固
5.24. 持续集成
5.25. Other new requirements
5.26. 自举
5.27. 错误报告

这里展示了 Debian 打包工作中针对非原生软件包使用“3.0 (quilt)”格式进行打包所遵循基本规则的一个全局性概览。

[Note] Note

为简明起见,某些细节被有意跳过。请按需查阅对应命令的手册页,例如dpkg-source(1)、dpkg-buildpackage(1)、dpkg(1)、dpkg-deb(1)、deb(5),等等。

Debian 源码包是一组用于构建 Debian 二进制软件包的输入文件,而非单个文件。

Debian 二进制软件包是一个特殊的档案文件,其中包含了一系列可安装的二进制数据及与它们相关的信息。

单个 Debian 源码包可能根据 debian/control 文件定义的内容产生多个 Debian 二进制软件包。

使用 “3.0 (quilt)”格式的非原生 Debian 软件包是最普通的 Debian 源码包格式。

[Note] Note

有许多封装脚本可用。合理使用它们可以帮助您理顺工作流程,但是请确保您能理解它们内部的基本工作原理。

创建 Debian 二进制软件包的 Debian 打包工作流涉及创建数个特定名称的文件(参见 Section 5.4, “软件包名称和版本”),与《Debian 政策手册》的定义保持一致。

一个极其简化的 Debian 打包工作流可以概括为以下十步。

  1. 下载上游源码压缩包(tarball)并命名为 package-version.tar.gz 文件。
  2. 使上游提供的源码压缩包解压缩后的所有文件存储在 package-version/ 目录中。
  3. 上游的源码压缩包被复制(或符号链接)至一个特定的文件名 packagename_version.orig.tar.gz

    • 分隔 packageversion 的符号从 -(连字符)更改为 _(下划线)
    • 文件扩展名添加了 .orig 部分。
  4. Debian 软件包规范文件将被添加至上游源代码中,存放在 package-version/debian/ 目录下。

    • debian/* 目录下的必需技术说明文件:

      debian/rules
      构建 Debian 软件包所需的可执行脚本(参见 Section 5.6, “debian/rules”
      debian/control
      软件包配置文件包含了源码包名称、源码构建依赖、二进制软件包名称、二进制软件包依赖,等等。(参见 Section 5.7, “debian/control”
      debian/changelog
      Debian 软件包历史文件,其中第一行定义了上游软件包版本号和 Debian 修订版本号(参见 Section 5.8, “debian/changelog”
      debian/copyright
      版权和许可证摘要信息(参看 Section 5.9, “debian/copyright”
    • debian/* 下的可选配置文件(参见 Section 5.13, “其它 debian/* 文件”):
    • package-version/ 目录中调用 debmake 命令将会提供这些配置文件的一套模板。

      • 必备的配置文件总会生成,无论是否提供 -x0 选项。
      • debmake 命令永远不会覆写任何已经存在的配置文件。
    • 这些文件必须手工编辑以达到理想状态。请使用《Debian 政策手册》和《Debian 开发者参考》作为编辑依据。
  5. The dpkg-buildpackage command (usually from its wrapper debuild or sbuild) is invoked in the package-version/ directory to make the Debian source and binary packages by invoking the debian/rules script.

    • 当前工作目录会被设为:$(CURDIR)=/path/to/package-version/
    • 使用 dpkg-source(1) 以“3.0 (quilt)”格式创建 Debian 源码包

      • package_version.orig.tar.gzpackage-version.tar.gz 的副本或符号链接)
      • package_version-revision.debian.tar.xzpackage-version/debian/* 的 tar 压缩包,即 tarball)
      • package_version-revision.dsc
    • 使用“debian/rules build”构建源代码并安装到 $(DESTDIR)

      • DESTDIR=debian/binarypackage/(单二进制包)
      • DESTDIR=debian/tmp/(多个二进制包)
    • 使用 dpkg-deb(1)、dpkg-genbuildinfo(1) 和 dpkg-genchanges(1) 创建 Debian 二进制软件包。

      • binarypackage_version-revision_arch.deb
      • ……(可能有多个 Debian 二进制包文件。)
      • package_version-revision_arch.changes
      • package_version-revision_arch.buildinfo
  6. 使用 lintian 命令检查 Debian 软件包的质量。(推荐)

  7. 通过手工安装和运行软件包里的程序,来测试生成的 Debian 二进制软件包的可用性。
  8. After confirming the goodness, prepare files for the normal source-only upload to the Debian archive.
  9. 使用 debsign 命令,用您的 GPG 私钥为 软件包名称_版本-修订版本.dsc 和 '软件包名_版本-修订版本’_*source.changes* 文件进行签名。
  10. 使用 dput 命令向 Debian 仓库上传一套 Debian 源码包文件。

Test building and confirming of the binary package goodness as above is the moral obligation as a diligent Debian developer but there is no physical barrier for people to skip such operations at this moment for the source-only upload.

Under some exceptional situation such as NEW uploads, uploads to the Debian archive may need to include Debian binary package files. For such situation, sign package_version-revision_arch.changes instead of 'package_version-revision’_*source.changes* in the step 9, and upload the set of the Debian source and binary package files in the step 10.

这里,请将文件名中对应的部分使用下面的方式进行替换:

  • package 部分替换为 Debian 源码包名称
  • binarypackage 部分替换为 Debian 二进制软件包名称
  • version 部分替换为上游版本号
  • revision 部分替换为 Debian 修订号
  • arch 部分替换为软件包对应架构

参见 Source-only uploads

[Tip] Tip

有很多种通过实践摸索而得到的补丁管理方法和版本控制系统的使用策略与技巧。您没有必要将它们全部用上。

[Tip] Tip

在“Debian 开发者参考”一文的 第 6 章 最佳打包实践 部分有十分详尽的相关文档。请读一读这些内容。

Let me oversimplify historical perspective of Debian packaging practices.

Debian was started in 1990s when upstream packages were available from public FTP sites such as Sunsite. In those early days, Debian packaging used dpkg-source currently known as "Format: 1.0":

  • Upstream released packages in tar.gz format. They were obtained from some FTP sites.
  • Debian applied "one big patch" as its source distribution and made its binary distribution form it.
  • Many different approaches were adopted by different Debian developers to manage topic patches with custom scripts within the "one big patch". — Chaos!

In order to address issues of old dpkg-source "Format: 1.0", new dpkg-source "Format: 3.0 (quilt)" was invented around 2008:

  • Upstream released packages in tar.gz/tar.bz2/tar.xz format optionally with signature files. They were obtained from some HTTP sites.
  • Most Debian developers adopted patch queue mechanism of "Format: 3.0 (quilt)" to manage topic patches and made Debian packages while keeping files outside of debian/ directory untouched.
  • VCS, especially git, became popular and most Debian developers and started to record this packaging practice in gbp-buildpackage(1) style.
  • The gbp-buildpackage(1) workflow records the exact same content of the upstream tarball to VCS for source files outside of debian/ directory (= patch-unapplied).

The use of Git repositories to distribute upstream packages with signed tags (supported feature since 2011) became very popular.

  • The tarball centric gbp-buildpackage(1) workflow to record changes to VCS was cumbersome for some Debian developers and dgit(1) was invented in 2013.
  • The Git centric dgit-maint-debrebase(7) and dgit-maint-merge(7) workflows to record changes to VCS are gaining popularity among these Debian developers.
  • Source files recorded to VCS by dgit-maint-debrebase(7) and git-maint-merge(7) are modified upstream source files (= patch-applied).
  • Uploaded source packages by dgit-maint-debrebase(7) and git-maint-merge(7) workflows still use dpkg-source "Format: 3.0 (quilt)".

Debian also enforced the source-only upload when developing Debian/11 Bullseye (released in 2021).

In this tutorial, mostly simple tarball based dpkg-source "Format: 3.0 (quilt)" examples are presented as an introductory purpose.

Please assess these VCS usage approaches by yourself later to decide which one to deploy as your preferred one.

Please also read Notes on Debian by Russ Allbery which have best practices such as Using Git for Debian Packaging.

Please look around to understand how Debian packaging practices are evolving and follow the current general trends if possible.

You can also search entire Debian source code by yourself, too.

如果所获取上游源代码的形式为 hello-0.9.12.tar.gz,您可以将 hello 作为上游源代码名称,并将 0.9.12 作为上游版本号。

debmake 的目的是为软件包维护者提供开始工作的模板文件。注释行以 # 开始,其中包含一些教程性文字。您在将软件包上传至 Debian 仓库之前必须删除或者修改这样的注释行。

许可证信息的提取和赋值过程应用了大量启发式操作,因此在某些情况下可能不会正常工作。强烈建议您搭配使用其它工具,例如来自 devscripts 软件包的 licensecheck 工具,以配合 debmake 的使用。

组成 Debian 软件包名称的字符选取存在一定的限制。最明显的限制应当是软件包名称中禁止出现大写字母。这里给出正则表达式形式的规则总结:

  • 上游软件包名称(-p):[-+.a-z0-9]{2,}
  • 二进制软件包名称(-b):[-+.a-z0-9]{2,}
  • 上游版本号(-u):[0-9][-+.:~a-z0-9A-Z]*
  • Debian 修订版本(-r): [0-9][+.~a-z0-9A-Z]*

请在《Debian 政策手册》的 第 5 章 - Control 文件及其字段 一节中查看其精确定义。

debmake 所假设的打包情景是相对简单的。因此,所有与解释器相关的程序都会默认为“Architecture: all”的情况。当然,这个假设并非总是成立。

您必须为 Debian 打包工作适当地调整软件包名称和上游版本号。

为了能有效地使用一些流行的工具(如 aptitude)管理软件包名称和版本信息,最好能将软件包名称保持在 30 字符以下;版本号和修订号加起来最好能不超过 14 个字符。[11]

为了避免命名冲突,对用户可见的二进制软件包名称不应选择任何常用的单词。

如果上游没有使用像 2.30.32 这样正常的版本编号方案,而是使用了诸如 11Apr29 这样包含日期、某些代号或者一个版本控制系统散列值等字符串作为版本号的一部分的话,请在上游版本号中将这些部分移除。这些信息可以稍后在 debian/changelog 文件中进行记录。如果您需要为软件设计一个版本字符串,可以使用 YYYYMMDD 格式,如 20110429 的字符串作为上游版本号。这样能保证 dpkg 命令在升级时能正确地确定版本的先后关系。如果您想要确保万一上游在未来重新采纳正常版本编号方案,例如 0.1 时能够做到顺畅地迁移,可以另行使用 0~YYMMDD 的格式,如 0~110429 作为上游版本号。

版本字符串可以按如下的方式使用 dpkg 命令进行比较。

$ dpkg --compare-versions ver1 op ver2

版本比较的规则可以归纳如下:

  • 字符串按照起始到末尾的顺序进行比较。
  • 字符比数字大。
  • 数字按照整数顺序进行比较。
  • 字符按照 ASCII 编码的顺序进行比较。

对于某些字符,如句点(.)、加号(+)和波浪号(~),有如下的特殊规则。

0.0 < 0.5 < 0.10 < 0.99 < 1 < 1.0~rc1 < 1.0 < 1.0+b1 < 1.0+nmu1 < 1.1 < 2.0

有一个稍需注意的情况,即当上游将 hello-0.9.12-ReleaseCandidate-99.tar.gz 这样的版本当作预发布版本,而将 hello-0.9.12.tar.gz 作为正式版本时。为了确保 Debian 软件包升级能够顺畅进行,您应当修改版本号命名,如将上游源代码压缩包重命名为 hello-0.9.12~rc99.tar.gz

使用“3.0 (quilt)”格式的非原生 Debian 软件包是最常见最标准的 Debian 源码包格式。根据 dpkg-source(1) 的描述,此时的 debian/source/format 文件应当包含“3.0 (quilt) 的文字内容。上述的工作流和接下来给出的打包示例都使用了这种格式。

而原生 Debian 软件包是较罕见的一种 Debian 软件包格式。它通常只用于打包仅对 Debian 项目有价值、有意义的软件。因此,该格式的使用通常不被提倡。

[Caution] Caution

在上游 tarball 源码压缩包无法使用其正确名称 package_version.orig.tar.gzdpkg-buildpackage 获取到的时候,会出现意外地构建了本土 Debian 软件包的情况。这是新手常见的一个错误,通常是因构建中错误地在符号链接名称中使用了“-”字符而非正确的“_”字符。[译注:此处仍然假设打包的场景是已经获取或形成了名为 package-version.tar.gz 的上游源码 tarball。Debian 的打包工作很大程度上是以上游源码 tarball 作为基础的,这一点须时刻牢记在心。]

原生 Debian 软件包不对 上游代码Debian 的修改 进行区分,仅包含以下内容:

  • package_version.tar.gzpackage-version.tar.gz 文件的副本或符号链接,包含 debian/* 的各个文件。)
  • package_version.dsc

如果您需要手动创建原生 Debian 软件包,可以使用 dpkg-source(1) 工具以“3.0 (native)”格式进行创建。

[Tip] Tip

一些人提议,给那些即使只为 Debian 写的程序,也打包成非原生的软件包格式。在标准的打包工作流 Section 5.1, “打包工作流” 前,所需的没有 debian/* 文件的 tarball 压缩包,需要用手工首先生成。[12] 他们声称,使用非原生软件包格式,能够和下游发行版更容易沟通。

[Tip] Tip

如果使用原生软件包格式,没有必要事先创建 tarball 压缩包。要创建一个原生 Debian 软件包,应当将 debian/source/format 文件的内容设置为“3.0 (native)”,适当编写 debian/changelog 文件使得版本号中不包含 Debian 修订号(例如,1.0 而非 1.0-1),最后在源码树中调用“dpkg-source -b .”命令。这样做便可以自动生成包含源代码的 tarball。

debian/rules 脚本是用于实际构建 Debian 软件包的可执行脚本。

  • debian/rules 脚本重新封装了上游的构建系统(参见 Section 5.18, “上游构建系统”)以达到将文件安装至 $(DESTDIR)并将生成的文件存入各个 deb 格式文件中的目的。

    • 这里的 deb 文件用于二进制的文件分发,并将被 dpkg 命令所使用以将软件安装至系统中。
  • dh 命令通常在 debian/rules 脚本中使用,用作构建系统的一个前端。
  • $(DESTDIR) 路径具体值依赖于构建的类型。

    • $(DESTDIR)=debian/binarypackage(单个二进制软件包)
    • $(DESTDIR)=debian/tmp(多个二进制软件包)

受益于 dh 命令对构建目标的抽象化 [13],一个符合 Debian 政策而支持所有必需目标(target)的 debian/rules 文件可以简单地写成如下形式[14]

简单的 debian/rules:. 

#!/usr/bin/make -f
#export DH_VERBOSE = 1

%:
        dh $@

从本质上来看,这里的 dh 命令的作用是作为一个序列化工具,在合适的时候调用所有所需的 dh_* 命令。

[Tip] Tip

设置“export DH_VERBOSE = 1”会输出构建系统中每一条会修改文件内容的命令。它同时会在某些构建系统中启用详细输出构建日志的选项。

通过添加合适的 override_dh_* 目标(target)并编写对应的规则,可以实现对 debian/rules 脚本的灵活定制。

如果需要在 dh 命令调用某些特定的 dh_foo 命令时采取某些特别的操作,则任何自动执行的操作均可以被 debian/rules 中额外添加的 override_dh_foo 这样的 Makefile 目标所覆写。

构建的过程可以使用某些上游提供的接口进行定制化,如使用传递给标准的源代码构建系统的参数。这些构建系统包括但不限于:

  • configure,
  • Makefile,
  • setup.py,或
  • Build.PL

在这种情况下,您应该添加一个 override_dh_auto_build 目标并在其中执行“dh_auto_build -- 自定义参数” 的命令。这样可以在 dh_auto_build 默认传递的参数之后确保将用户给出的 自定义参数 继续传递给那些构建系统。

[Tip] Tip

如果上文提到的构建系统命令已知得到了 dh_auto_build 命令的支持的话,请避免直接调用这些命令(而让 dh_auto_build 自动处理)。

debmake 命令所创建的初始模版文件除了应用了上文提到的简单 debian/rules 文件的优点外,同时为后续可能涉及的软件包加固等情景添加了一些额外的定制选项。您需要先了解整个构建系统背后的工作原理(参见 Section 5.18, “上游构建系统”),之后才能收放自如地定制软件包来处理某些非常规的工作情况。

某些对自定义 debian/rules 有用的变量定义可以在 /usr/share/dpkg/ 目录下的文件中找到。比较重要的包括:

pkg-info.mk
DEB_SOURCE, DEB_VERSION, DEB_VERSION_EPOCH_UPSTREAM, DEB_VERSION_UPSTREAM_REVISION, DEB_VERSION_UPSTREAM, and DEB_DISTRIBUTION variables. These are useful for backport support etc..
vendor.mk
DEB_VENDOR and DEB_PARENT_VENDOR variables; and dpkg_vendor_derives_from macro. These are useful for vendor support (Debian, Ubuntu, …).
architecture.mk
Set DEB_HOST_* and DEB_BUILD_* variables. An alternative method of retrieving those variables is to invoke dpkg-architecture directly and query the value of a single variable. With explicit invocation of dpkg-architecture to retrieve necessary variables, there is no need to include architecture.mk in debian/rules, which would import all architecture-related variables.
buildflags.mk
设置 CFLAGSCPPFLAGSCXXFLAGSOBJCFLAGSOBJCXXFLAGSGCJFLAGSFFLAGSFCFLAGSLDFLAGS 这些构建标志(build flags)。

如果您希望在 debian/rules 中使用其中的某些变量,您可以将相关的代码复制到 debian/rules 文件中,或是重写一份简单的替代实现。总而言之请保持 debian/rules 文件尽量简单。

例如,您按如下的方法在 debian/rules 文件中添加内容,从而为 linux-any 目标架构添加额外的 CONFIGURE_FLAGS

DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
 ...
ifeq ($(DEB_HOST_ARCH_OS),linux)
CONFIGURE_FLAGS += --enable-wayland
endif
[Tip] Tip

历史上对于 debhelper 兼容等级小于等于 8 的情况下,在 debian/rules 文件中包含 buildflags.mk 文件是很有用的,它可以合适地设置一些构建标志,如 CPPFLAGSCFLAGSLDFLAGS 等,同时保证对特定选项,如 DEB_CFLAGS_MAINT_APPENDDEB_BUILD_MAINT_OPTIONS 的合适处理。现在您应当使用的 debhelper 兼容等级大于等于 9,故如无特殊原因,请不要继续包含 buildflags.mk,请交由 dh 命令来处理和设置这些构建标志。

参见 Section 5.22, “多体系结构”dpkg-architecture(1) 和 dpkg-buildflags(1)。

为了做到软件包可重现的构建,这里给出一些相关的建议。

dpkg-genbuildinfo(1) 生成的控制文件 source-name_source-version_arch.buildinfo 记录了构建环境信息。参见 deb-buildinfo(5)

debian/control 文件包含了由空行分隔的数块元信息数据。每块元数据按照如下的顺序定义了下面这些内容:

  • Debian 源码包的元信息数据
  • Debian 二进制软件包的元信息

参见《Debian 政策手册》中的 第 5 章 - Control 文件及其字段 一章以了解每块元信息的具体定义。

[Note] Note

debmake 命令会在 debian/control 文件中写入“Build-Depends: debhelper-compat (= 13)”以设置 debhelper 兼容等级。

[Tip] Tip

If an existing package has lower than debhelper compatibility level 9, probably it’s time to update its packaging.

对行为良好的构建系统来说,对 Debian 二进制包的拆分可以由如下方式实现。

  • 为所有二进制软件包在 debian/control 文件中创建对应的二进制软件包条目。
  • 在对应的 debian/二进制软件包名.install 文件中列出所有文件的路径(相对于 debian/tmp 目录)。

请查看本指南中相关的例子:

debmake 命令的 -b 选项提供了一个符合直觉又灵活的功能,可以用来创建 debian/control 的初始模板文件,其中可以定义多个 Debian 二进制软件包,每节中含有如下字段:

  • Package:
  • Architecture:
  • Multi-Arch:
  • Depends:
  • Pre-Depends:

debmake 命令也会在每个适当的依赖字段中设置合适的变量替换占位符(substvars)。

我们在这里直接引用 debmake 手册页中的相关一部分内容。

-b "二进制软件包名[:type],…", --binaryspec "二进制软件包名[:type],…"

设置二进制软件包的指定类型内容,使用一个用逗号分隔的二进制软件包名:类型成对列表;例如,使用完整形式“foo:bin,foo-doc:doc,libfoo1:lib,libfoo-dev:dev”或者使用短形式,“-doc,libfoo1,libfoo-dev”。

这里,二进制软件包是二进制软件包名称,可选的类型应当从下面的类型值中进行选取:

  • bin:C/C++ 预编译 ELF 二进制代码软件包(any,foreign)(默认,别名:"",即,空字符串
  • data:数据(字体、图像、……)软件包(all,foreign)(别名:da
  • dev:库开发软件包(any,same)(别名:de
  • doc:文档软件包(all,foreign)(别名:do
  • lib:库软件包(any,same)(别名:l
  • perl:Perl 脚本软件包(all,foreign)(别名:pl
  • python3:Python(版本 3)脚本软件包(all,foreign)(别名:py3
  • ruby:Ruby 脚本软件包(all,foreign)(别名:rb
  • nodejs:基于 Node.js 的 JavaScript 软件包(all,foreign)(别名:js
  • script:Shell 脚本软件包(all,foreign)(别名:sh

括号内成对的值,例如(any,foreign),是软件包的架构多架构(Multi-Arch)特性的值,它们将设置在 debian/control 文件中。

大多数情况下,debmake 命令可以有效地从二进制软件包的名称猜测出正确的类型。如果类型的值并不明显,程序将回退到将类型设置为bin。例如,libfoo 设置类型lib,而 font-bar 会令程序设置类型data,……

如果源码树的内容和类型的设置不一致,debmake 命令会发出警告。

我们考虑 libfoo 这个库的上游 tarball 源码压缩包的名字从 libfoo-7.0.tar.gz 更新为了 libfoo-8.0.tar.gz,同时带有一次 SONAME 大版本的跳跃(并因此影响了其它软件包)。

库的二进制软件包将必须从 libfoo7 重命名为 libfoo8 以保持使用 unstable 套件的系统上所有依赖该库的软件包在上传了基于 libfoo-8.0.tar.gz 的新库后仍然能够正常运行。

[Warning] Warning

如果这个二进制库软件包没有得到更名,许多使用 unstable 套件的系统上的各个依赖该库的软件包会在新的库包上传后立刻破损,即便立刻请求进行 binNMU 上传也无法避免这个问题。由于种种原因,binNMU 不可能在上传后立刻开始进行,故无法缓解问题。

-dev 软件包必须遵循以下命名规则:

[Tip] Tip

如果包内数据文件编码方案有所变化(如,从 latin1 变为 utf-8),该场景应比照 API 变化做类似的考虑与处理。

参见 Section 5.20, “库软件包”

debian/control 也定义了软件包的依赖关系,其中变量替换机制(substvar)的功能可以用来将软件包维护者从跟踪(大多数简单的)软件包依赖的重复劳动中解放出来。请参见 deb-substvars(5)。

debmake 命令支持下列变量替换指令:

  • ${misc:Depends},可用于所有二进制软件包
  • ${misc:Pre-Depends},可用于所有 multiarch 软件包
  • ${shlibs:Depends},可用于所有含有二进制可执行文件或库的软件包
  • ${python:Depends},可用于所有 Python 软件包
  • ${python3:Depends},可用于所有 Python3 软件包
  • ${perl:Depends},用于所有 Perl 软件包
  • ${ruby:Depends},用于所有 Ruby 软件包

对共享链接库来说,所需要的依赖库是由运行“objdump -p /path/to/program | grep NEEDED”这样的命令来得到的,由 shlib 占位符进行变量替换。

对于 Python 和其它解释器来说,所需的模块通常由对包含类似“import”、“use”、“require”等等关键字的行进行解析,并会体现在各自对应的变量替换占位符所在位置上。

对其它没有部署属于自己范畴内的变量替换机制的情况,misc 变量替换占位符通常用来覆盖对应的依赖替换需求。

对 POSIX shell 程序来说,并没有简单的办法来验证其依赖关系,substvar 的变量替换也无法自动得出它们的依赖。

对使用动态加载机制,包括 GObject introspection 机制的库和模块来说,现在没有简单的方法可以检查依赖关系,变量替换机制也无法自动推导出所需的依赖。

一个 binNMU(二进制非维护者上传) 是为库迁移或其它目的所作的非维护者软件包上传。在一次 binNMU 上传中,只有“Architecture: any”的软件包会被重构建,其版本号会在末尾附加一个编号(例如,原来版本为 2.3.4-3,新上传的包版本会变成 2.3.4-3+b1)。所有“Architecture: all”的包将不会重新构建。

来自同一个源码包的各个二进制包如果在 debian/control 文件中有互相的依赖关系,这些二进制包通常情况下应当对 binNMU 是安全的(即,进行 binNMU 不会破坏依赖关系)。然而,在“Architecture: any”和“Architecture: all”的软件包同时由同一源码包产出,且互相之间有依赖关系时,需要小心对待所依赖的版本,必要时应做出调整。

  • Architecture: any”的软件包依赖于“Architecture: anyfoo 软件包

    • Depends: foo (= ${binary:Version})
  • Architecture: any”的软件包依赖于“Architecture: allbar 软件包

    • Depends: bar (= ${source:Version})
  • Architecture: all”的软件包依赖于“Architecture: anybaz 软件包

    • Depends: baz (>= ${source:Version}), baz (<< ${source:Version}.0~)

debian/changelog 文件记录了 Debian 软件包的历史并在其第一行定义了上游软件包的版本和 Debian 修订版本。所有改变的内容应当以明确、正式而简明的语言风格进行记录。

  • 即便您在自己独立进行软件包上传,您也必须记录所有较重要、用户可见的变更,例如:

    • 安全相关的漏洞修复。
    • 用户界面变动。
  • 如果您需要他人协助您进行上传,您应当更详尽地记录变更内容,包括所有打包相关的变动,从而方便他人对您的软件包进行审查。

    • 协助上传的人员不应该也通常不会猜测您没有写出来的想法,所以请认真书写变更信息。
    • 通常来说,协助您上传的人的时间比您的时间更宝贵。

debmake 命令会创建初始的模板文件,其中带有上游软件包版本和 Debian 打包修订编号。发行版部分被设置为 UNRELEASED 以避免半成品不小心被上传进入 Debian 仓库。

通常使用 debchange 命令(它具有一个别名,即 dch)对其进行编辑。

[Tip] Tip

您也可以手动使用任何文本编辑器修改 debian/changelog 文件,只要您能够遵循 debchange 命令所使用的特定文本排版格式即可。

[Tip] Tip

debian/changelog 文件使用的日期字符串可以使用“LC_ALL=C date -R”命令手动生成。

该文件将由 dh_installchangelogs 命令安装到 /usr/share/doc/binarypackage 目录,文件名为 changelog.Debian.gz

上游的变更日志则会安装至 /usr/share/doc/binarypackage 目录中,文件名为 changelog.gz

上游的变更日志是由 dh_installchangelogs 程序自动进行搜索和处理的;它会使用大小写不敏感的搜索方式寻找上游代码中特定名称的文件,如 changelogchangeschangelog.txtchanges.txthistoryhistory.txtchangelog.md。除了根目录,程序还会在 doc/ 目录和 docs/ 目录内进行搜索。

当您完成了主要打包工作并验证了其质量之后,请考虑运行“dch -r”命令并将最终完成的 debian/changelog 文件中发行版(distribution)部分进行设置,通常该字段应当使用 unstable[15] 如果您的打包是一次向后移植(backports)、是安全更新或是对长期支持版的上传等等其它情况,请使用相应合适的发行版名称。

Debian 以十分严肃的态度对待版权和许可证信息。《Debian 政策手册》强制规定软件包的 debian/copyright 文件中需要提供相关信息的摘要。

您应当按照 机器可解析的 debian/copyright 文件(DEP-5)对其进行排版。

[Caution] Caution

这里的 debian/copyright 文件中描述的许可证信息匹配信息应当合适地进行排序,以确保越宽泛的文件匹配越靠前。请参见 Section 6.4, “debmake -k”

debmake 命令会以扫描整个源码树的方式创建初步的、兼容 DEP-5 的模板文件。它会内部调用许可证检查工具来对许可证文本进行分类。[16]

除非明确指定(有些严格过头的) -P 选项,debmake 命令会为了实用性而跳过对自动生成的文件的检查与报告,默认它们采用宽松的许可证。

[Note] Note

如果您发现了这个许可证检查工具存在一些问题,请向 debmake 软件包提交缺陷报告并提供包含出现问题的许可证和版权信息在内的相关文本内容。

[Note] Note

debmake 命令专注于在创建 debian/copyright 模板时聚合相同的授权和许可证信息并收录其详细内容。为了在有限的时间内尽可能完成工作,工具将只会提取文件中第一块看起来像授权文本或许可证声明的部分。因此,生成的许可证信息可能并不完美。请同时考虑使用其它工具,如 licensecheck 辅助进行检查。

[Tip] Tip

我们强烈推荐您使用 licensecheck(1) 命令再次检查源码许可证的状态,并在有必要的情况下进行人工代码审查。

构建过程开始之前,debian/patches/ 目录内的 -p1 等级的补丁将会按照在 debian/patches/series 文件中指定的顺序依次应用于上游代码树中。

[Note] Note

原生 Debian 软件包(参见 Section 5.5, “原生 Debian 软件包”)将不使用这些文件。

要准备这一系列 -p1 等级的补丁,有几种不同的方式可供您选择。

  • diff 命令

    • 参见 Section 4.9.1, “使用 diff -u 处理补丁”
    • 原始但万能的方法

      • 补丁的来源多种多样,它可以来自其它发行版、邮件列表中的帖文或是来自上游 git 仓库的拣选补丁,由“git format-patches”生成
    • 不涉及 .pc/ 目录的问题
    • 不修改上游源代码树
    • 手工更新 debian/patches/series 文件
  • dquilt 命令

    • 参见 Section 3.4, “quilt”
    • 基本的便利方案
    • 会以合适方式生成 .pc/ 目录及其中的数据
    • 会修改上游源代码树
  • dpkg-source --commit”命令

  • dpkg-buildpackage 自动生成补丁

  • The gbp pq command

    • 配合 git-buildpackage 工具的基本 git 工作流
    • 不涉及 .pc/ 目录的问题
    • 在可丢弃分支上保存经过修改的上游源码树(patch-queue/master
    • 在 Debian 分支中(常见为 master 分支)存储未经修改的源码树
  • The git-dpm command

    • 配合 git-dpm 软件包的更细致的 git 工作流
    • 不涉及 .pc/ 目录的问题
    • 在补丁分支中(通常命名为 patched/随便啥名字)存储经过修改的上游源码树
    • 在 Debian 分支中(通常命名为 master/随便啥名字)存储未经修改的上游源码树

无论这些补丁的来源如何,都建议使用兼容于 DEP-3 的头部信息对其进行标记。

[Tip] Tip

dgit 软件包提供了另外一套直接使用 git 集成操作 Debian 软件包仓库的工具。

dpkg-source 工具 1.16.1 版本之前,该工具还未提供 --commit 选项对应的功能,此时需要 quilt 命令(或者对它的封装,dquilt 命令)来管理 debian/patches/ 目录中的 -p1 等级的补丁。

在使用 dpkg-source 命令时,补丁应当能够干净地进行应用。因此在补丁行数出现偏移或者其它情况出现时,您不能直接将旧补丁原封不动地复制到新版上游发布对应打包版本的目录中。

与此相对的是 dquilt 命令(参见 Section 3.4, “quilt”)对补丁的处理更加宽容。您可以调用 dquilt 命令对补丁进行正常化。

 $ while dquilt push; do dquilt refresh ; done
 $ dquilt pop -a

使用 dpkg-source 命令比起使用 dquilt 命令来说存在一大优势:dquilt 命令无法自动处理二进制文件出现变更的情况,而 dpkg-source 命令能够探测出现内容变动的二进制文件,并将其列入 debian/source/include-binaries 文件以便在 Debian 打包用压缩包中将文件囊括其中。

某些软件包由 GPG 密钥进行了签名。

例如,GNU hello 可使用 HTTP 协议从 https://ftp.gnu.org/gnu/hello/ 下载。它含有以下文件:

  • hello-version.tar.gz(上游源代码)
  • hello-version.tar.gz.sig(分离的签名)nature)

我们现在来选择最新的版本套装。

$ wget https://ftp.gnu.org/gnu/hello/hello-2.9.tar.gz
 ...
$ wget https://ftp.gnu.org/gnu/hello/hello-2.9.tar.gz.sig
 ...
$ gpg --verify hello-2.9.tar.gz.sig
gpg: Signature made Thu 10 Oct 2013 08:49:23 AM JST using DSA key ID 80EE4A00
gpg: Can't check signature: public key not found

如果您从邮件列表获知上游维护者所使用的 GPG 公钥信息,请将它作为 debian/upstream/signing-key.asc 文件进行存储。否则,请使用 hkp 公钥服务器并经由您的信任网进行验证。

$ gpg --keyserver hkp://keys.gnupg.net --recv-key 80EE4A00
gpg: requesting key 80EE4A00 from hkp server keys.gnupg.net
gpg: key 80EE4A00: public key "Reuben Thomas <rrt@sc3d.org>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1
$ gpg --verify hello-2.9.tar.gz.sig
gpg: Signature made Thu 10 Oct 2013 08:49:23 AM JST using DSA key ID 80EE4A00
gpg: Good signature from "Reuben Thomas <rrt@sc3d.org>"
  ...
Primary key fingerprint: 9297 8852 A62F A5E2 85B2  A174 6808 9F73 80EE 4A00
[Tip] Tip

如果您的网络环境阻挡了对 HKP 11371 端口的访问,请考虑使用“hkp://keyserver.ubuntu.com:80”。

在确认密钥身份 80EE4A00 值得信任之后,应当下载其公钥并将其保存在 debian/upstream/signing-key.asc 文件中。

$ gpg --armor --export 80EE4A00 >debian/upstream/signing-key.asc

之后,应相应地在 debian/watch 文件中做如下的修改。

version=4
pgpsigurlmangle=s/$/.sig/  https://ftp.gnu.org/gnu/hello/ hello-(\d[\d.]*)\.tar\.(?:gz|bz2|xz)

现在 uscan 命令会在扫描时自动使用 GPG 签名验证上游源码包的真实性。

Debian 严肃地对待软件自由,遵循 Debian 自由软件指导方针(DFSG)

在使用 uscan 命令来更新 Debian 打包所用代码时,上游源码包(tarball)中不符合Debian 自由软件指导方针(DFSG)的部分可以利用该工具简单地进行移除。

  • debian/copyright 文件中的 Files-Excluded 一节中列出需要移除的文件。
  • debian/watch 文件中列出下载上游源码包(tarball)所使用的 URL。
  • 运行 uscan 命令以下载新的上游源码包(tarball)。

    • 作为替代方案,您也可以使用“gbp import-orig --uscan --pristine-tar”命令。
  • 最后得到 tarball 的版本编号会附加一个额外的后缀 +dfsg

另外也可以添加一些可选的配置文件并放入 debian/ 目录。它们大多用于控制由 debhelper 软件包提供的 dh_* 命令的行为,但也有一些文件会影响 dpkg-sourcelintiangbp 这些命令。

[Tip] Tip

请检查 debhelper(7) 的内容以了解当前可用的 dh_* 命令列表。

这些 debian/binarypackage.* 的文件提供了设置文件安装路径的强大功能。即使上游源代码没有构建系统,这个软件依然可以利用这里提到的这些文件来进行打包。请参考 Section 8.2, “无 Makefile(shell,命令行界面)” 的示例。

下面列表中出现的“-x[1234]”上标指示了 debmake -x 选项生成对应模板文件所需要的最小值。请参考 debmake(1) 以了解详情。

下面按照字母表顺序列出一些值得注意的可选配置文件。

binarypackage.bug-control -x3
将安装至 binarypackage 软件包的 usr/share/bug/binarypackage/control 位置。另请参考Section 5.27, “错误报告”
binarypackage.bug-presubj -x3
将安装至 binarypackage 软件包的 usr/share/bug/binarypackage/presubj 位置。另请参考Section 5.27, “错误报告”
binarypackage.bug-script -x3
将安装至 binarypackage 软件包的 usr/share/bug/binarypackage or usr/share/bug/binarypackage/script 位置。另请参考Section 5.27, “错误报告”
binarypackage.bash-completion

列出需要安装的 bash 补全脚本。

需要在构建环境和用户环境内均安装 bash-completion 软件包。

另请参考dh_bash-completion(1)。

clean -x2

列出(构建前)未被 dh_auto_clean 命令清理,且需要手工清理的文件。

另请参考 dh_auto_clean(1) 和 dh_clean(1)。

compat -x3

Previously, this set the debhelper compatibility level.

现在,在 debian/control 文件中使用 Build-Depends: debhelper-compat (= 13) 以指定兼容等级。

另请参考 debhelper(8) 中“COMPATIBILITY LEVELS”一节。

binarypackage.conffile

No need for this file now since all files in the etc/ directory are conffiles for recent “compat >= 3”.

如果您正要打包的程序要求每个用户都对 /etc 目录下的配置文件进行修改,可以采取两种常见办法使其不作为 conffile 配置文件出现,避免 dpkg 命令处理软件包时给出不必要的处理选项。

  • /etc 目录下创建一个符号链接,指向 /var 目录下的某些文件;实际存在的文件则使用维护者脚本(maintainer script)予以创建。
  • 使用维护者脚本(maintainer script)在 /etc 目录下创建并维护配置所需的文件。

另请参考 dh_installdeb(1)。

binarypackage.config
这是 debconf config 脚本,用来在配置软件包时向用户询问任何必需的问题。另请参见Section 5.21, “debconf”
binarypackage.cron.hourly -x3

安装至 binarypackage 包内的 etc/cron/hourly/binarypackage 文件。

另请参见 dh_installcron(1) 和 cron(8)。

binarypackage.cron.daily -x3

安装至 binarypackage 包内的 etc/cron/daily/binarypackage 文件。

另请参见 dh_installcron(1) 和 cron(8)。

binarypackage.cron.weekly -x3

安装至 binarypackage 包内的 etc/cron/weekly/binarypackage 文件。

另请参见 dh_installcron(1) 和 cron(8)。

binarypackage.cron.monthly -x3

安装至 binarypackage 包内的 etc/cron/monthly/binarypackage 文件。

另请参见 dh_installcron(1) 和 cron(8)。

binarypackage.cron.d -x3

安装至 binarypackage 包内的 etc/cron.d/binarypackage 文件。

参见 dh_installcron(1)、cron(8) 和 crontab(5)。

binarypackage.default -x3

若该文件存在,它将被安装至 binarypackage 包中的 etc/default/binarypackage 位置。

参见 dh_installinit(1)。

binarypackage.dirs -x3

列出 binarypackage 包中要创建的目录。

参见 dh_installdirs(1)。

通常情况下您并不需要这么做,因为所有的 dh_install* 命令都会自动创建所需的目录。请仅在遇到问题时考虑使用这一工具。

binarypackage.doc-base -x2

作为 binarypackage 包中的 doc-base 控制文件进行安装。

参见 dh_installdocs(1) 和 doc-base 软件包提供的 Debian doc-base 手册

binarypackage.docs -x2

列出要安装在 binarypackage 包中的文档文件。

参见 dh_installdocs(1)。

binarypackage.emacsen-compat -x3

安装至 binarypackage 包中的 usr/lib/emacsen-common/packages/compat/binarypackage 文件。

参见 dh_installemacsen(1)。

binarypackage.emacsen-install -x3

安装至 binarypackage 包中的 usr/lib/emacsen-common/packages/install/binarypackage 文件。

参见 dh_installemacsen(1)。

binarypackage.emacsen-remove -x3

安装至 binarypackage 包中的 usr/lib/emacsen-common/packages/remove/binarypackage 文件。

参见 dh_installemacsen(1)。

binarypackage.emacsen-startup -x3

安装至 binarypackage 包中的 usr/lib/emacsen-common/packages/startup/binarypackage 文件。

参见 dh_installemacsen(1)。

binarypackage.examples -x2

列出要安装至 binarypackage 包中 usr/share/doc/binarypackage/examples/ 位置下的示例文件或目录。

参见 dh_installexamples(1)。

gbp.conf

如果该文件存在,它将作为 gbp 命令的配置文件发挥作用。

参见 gbp.conf(5)、gbp(1) 和 git-buildpackage(1)。

binarypackage.info -x2

列出要安装至 binarypackage 包中的 info 文件。

参见 dh_installinfo(1)。

binarypackage.init -x3

安装至 binarypackage 包中的 etc/init.d/binarypackage 文件。

参见 dh_installinit(1)。

binarypackage.install -x2

列出未被 dh_auto_install 命令安装的其它应当安装的文件。

参见 dh_install(1) 和 dh_auto_install(1)。

license-examples/* -x4

这是 debmake 命令生成的版权声明文件示例,请用它们作为 debian/copyright 文件的参考。

请在最终工作成果中删除这些文件。

binarypackage.links -x2

列出要生成符号链接的源文件和目标文件对。每一对链接均应在单独的一行中列出,源文件和目标文件之间使用空白字符分隔。

参见 dh_link(1)。

binarypackage.lintian-overrides -x3

安装至软件包构建目录的 usr/share/lintian/overrides/binarypackage 位置。该文件用于消除 lintian 错误生成的诊断信息。

参见 dh_lintian(1)、lintian(1) 和 Lintian 用户手册

manpage.* -x3

这些文件是 debmake 命令生成的 man 手册页模板文件。请将其重命名为合适的文件名并更新其内容。

Debian 的政策要求软件包为其包含的每个程序、工具和函数同时提供一份相关的手册页。手册页使用 nroff(1) 语法写成。

如果您不熟悉如何编写用户手册页,请以 manpage.asciidocmanpage.1 为起点。

binarypackage.manpages -x2

列出要安装的 man 手册页。

参见 dh_installman(1)。

binarypackage.menu (已过时,不再安装)

tech-ctte #741573 决定“Debian 应该在合适的情况下使用 .desktop 文件”。

安装至 binarypackage 包中的 usr/share/menu/binarypackage Debian 菜单文件。

参见 menufile(5) 以了解其格式。另请参见 dh_installmenu(1)。

NEWS

安装至 usr/share/doc/binarypackage/NEWS.Debian 文件。

参见 dh_installchangelogs(1)。

patches/*

这是 -p1 补丁文件的集合,它们将在使用源代码构建之前应用在上游源码上。

参见 dpkg-source(1)、Section 3.4, “quilt”Section 4.9, “第三步(备选):修改上游源代码”

debmake 默认不会生成补丁文件。

patches/series -x1
patches/* 补丁文件的应用顺序。
binarypackage.preinst -x2 , binarypackage.postinst -x2 , binarypackage.prerm -x2 , binarypackage.postrm -x2

这些维护者脚本将安装至软件包的 DEBIAN 目录下。

在这些脚本中,#DEBHELPER# 记号将由其它 debhelper 命令进行处理,将其替换为相应的 shell 脚本片段。

参考《Debian 政策手册》的 dh_installdeb(1) 和 第六章 - 软件包维护脚本和安装过程 一节。

参考《Debian 政策手册》的 debconf-devel(7) 和 3.9.1 维护者脚本中的用户交互提示 一节。

README.Debian -x1

安装至 debian/control 文件列出的第一个二进制软件包中的 usr/share/doc/binarypackage/README.Debian 位置。

参见 dh_installdocs(1)。

该文件提供了针对该 Debian 软件包的信息。

binarypackage.service -x3

如果该文件存在,它将被安装到 binarypackage 包下面的 lib/systemd/system/binarypackage.service 位置。

参见 dh_systemd_enable(1)、dh_systemd_start(1) 和 dh_installinit(1)。

source/format -x1

Debian 软件包格式。

  • 使用“3.0 (quilt)”以制作这个非原生软件包(推荐)
  • 使用“3.0 (native)”以制作这个原生软件包

参见 dpkg-source(1) 的“源码包格式”一节。

source/lintian-overridessource.lintian-overrides -x3

这些文件不会最终被安装,但 lintian 会对它们进行扫描以提供源码包的 override 信息。

另请参考 dh_lintian(1) 和 lintian(1)。

source/local-options -x1

dpkg-source 命令使用此内容作为它的选项,比较重要的选项有:

  • unapply-patches
  • abort-on-upstream-changes
  • auto-commit
  • single-debian-patch

该文件不会包含在生成的源码包中,仅对维护者在版本控制系统中维护软件包有意义。

参见 dpkg-source(1) 中的“文件格式”一节。

source/local-patch-header

自由格式的文本,将被包含在自动生成补丁的顶部。

该文件不会包含在生成的源码包中,仅对维护者在版本控制系统中维护软件包有意义。

+ 参见 dpkg-source(1) 的“文件格式”一节。

binarypackage.symbols -x2

这些符号文件如果存在,将交由 dpkg-gensymbols 命令进行处理和安装。

参见 dh_makeshlibs(1) 和 Section 5.20.1, “库符号”

binarypackage.templates
这是 debconf 模板文件,用于在安装过程中向用户询问必需的问题以正确配置软件包。请参阅 Section 5.21, “debconf”
tests/control
这是一个 RFC822 格式的测试元数据文件,定义在 DEP-8。参见 autopkgtest(1) 和Section 5.24, “持续集成”
TODO

安装至 debian/control 文件列出的第一个二进制包中的 usr/share/doc/binarypackage/TODO.Debian 文件。

参见 dh_installdocs(1)。

binarypackage.tmpfile -x3

如果该文件存在,它将被安装至 binarypackage 包中的 usr/lib/tmpfiles.d/binarypackage.conf 文件。

参见 dh_systemd_enable(1)、dh_systemd_start(1) 和 dh_installinit(1)。

binarypackage.upstart -x3

如果该文件存在,它将被安装至软件包构建目录的 etc/init/package.conf 位置。(已弃用)

参见 dh_installinit(1) 和 Section 8.1, “挑选最好的模板”

watch -x1

用于下载最新上游版本的 uscan 命令的控制文件。

该控制文件也可配置以使用其 GPG 签名自动验证上游 tarball 的真实性(参见 Section 5.11, “debian/upstream/signing-key.asc”)。

参见 Section 5.12, “debian/watch 和 DFSG”uscan(1)。

这里给出针对上面列表中信息的一些额外提醒。

  • 对只生成一个二进制包的情况,列表文件名中的 binarypackage. 这一部分可以不出现。
  • 对有多个二进制包的源码包,一个缺少文件名里 binarypackage. 部分的配置文件,会被应用于 debian/control 里列出的第一个二进制包。
  • 在生成多个二进制包的情况下,各个二进制包可以分别指定配置文件;只需在其对应配置文件的文件名之前加上它们各自对应的包名即可,如 package-1.installpackage-2.install 等等。
  • debmake 可能没有自动生成某些模板配置文件。如遇到这种情况,您可以使用文本编辑器手动创建缺失的文件。
  • debmake 命令生成的带额外 .ex 后缀名的配置文件必须在移除这个多余后缀名后才能发挥作用。
  • 您应当删除 .ex 命令生成但对您无用的配置模板文件。
  • 请按需复制配置模板文件以匹配其对应的二进制包名称以及您的需求。

我们来重新归纳一下 Debian 打包定制化的相关内容。

所有对 Debian 软件包进行定制化的数据都存在于 debian/ 目录中。我们在Section 4.7, “第三步:编辑模板文件”这里给出了一个简单的例子。通常情况下,定制化会涉及以下各个项目:

如果以上提到的手段仍然不足以制作满足要求的 Debian 软件包的话,对上游源代码的修改应当使用 -p1 补丁文件存放在打包源码树 debian/patches/ 目录下。这些补丁将按照 debian/patches/series 文件所规定的顺序在构建软件包之前应用(参见 Section 5.10, “debian/patches/*”)。Section 4.9, “第三步(备选):修改上游源代码” 这里给出了一些简单的例子。

您应当以引入最少修改的方式解决打包中出现的根本问题。所生成的软件包应当考虑到未来的更新需求并有一定的健壮性。

[Note] Note

如果补丁对上游有所帮助的话,也请将解决根本问题的补丁反馈给上游作者和维护者。

通常情况下,Debian 打包活动使用 Git 作为版本控制系统(VCS)进行记录;通常会用到下列的分支。

  • master 分支

    • 记录用于 Debian 打包的源代码树。
    • 源码树的上游部分将照原样记录,不做修改。
    • Debian 打包中需要对上游源代码所作的修改记录在 debian/patches/ 目录中,以 -p1 等级的补丁形式存在。
  • upstream 分支

    • 记录从上游发布的 tarball(源码压缩文件)解压缩所得到的源代码树。
[Tip] Tip

添加一个 .gitignore 文件并将 .pc 文件列入其中也是一个好主意。

[Tip] Tip

可以在 debian/source/local-options 文件中添加 unapply-patchesabort-on-upstream-changes 这两行以保持上游源码处于未修改状态。

[Tip] Tip

您也可以使用除 upstream 分支以外其它名称的分支跟踪上游版本控制数据以方便拣选补丁。

您也可以选择不创建 -p1 等级的补丁。这时,您可以使用下列分支来记录 Debian 打包活动。

  • master 分支

    • 记录用于 Debian 打包的源代码树。
    • 源码树的上游部分在应用了为 Debian 打包所作的修改之后进行记录。
  • upstream 分支

    • 记录从上游发布的 tarball(源码压缩文件)解压缩所得到的源代码树。

如下在 debian/ 目录下额外添加一些文件即可达到目的。

 $ tar -xvzf <package-version>.tar.gz
 $ ln -sf <package_version>.orig.tar.gz
 $ cd <package-version>/
 ... hack...hack...
 $ echo "single-debian-patch" >> debian/source/local-options
 $ cat >debian/source/local-patch-header <<END
 This patch contains all the Debian-specific changes mixed
 together. To review them separately, please inspect the VCS
 history at https://git.debian.org/?=collab-maint/foo.git.

如此可让 Debian 打包过程(dpkg-buildpackagedebuild 等)所调用的 dpkg-source 命令自动生成一个 -p1 等级的补丁文件 debian/patches/debian-changes

[Tip] Tip

这种做法可以应用在任何版本控制工具中。这么做会把所有修改合并到同一个补丁文件中而丢失其开发历史,因此请务必保持版本控制系统的数据公开可见。

[Tip] Tip

debian/source/local-optionsdebian/source/local-patch-header 文件只用于在版本控制系统中记录信息。它们不应包含在 Debian 源码包中。

在某些情况下,直接使用自动生成的 Debian 源码包会引入不必要的一些内容。

  • 上游源码树可能由某个版本控制系统进行管理。直接从这个源码树进行构建时,所生成的 Debian 源码包会包含来自版本控制系统的多余文件。
  • 上游源码树可能包含了一些自动生成的文件。当从这个源码树重新构建软件包时,所生成的 Debian 源码包会包含这些自动生成的不必要的文件。

通常情况下,Section 3.5, “devscripts” 中设置的用于 dpkg-source 命令的 -i-I 选项可以避免这些问题。这里 -i 针对非原生软件包而 -I 则针对本土软件包。请参见 dpkg-source(1) 和“dpkg-source --help”的输出。

以下几种方法均可避免引入不必要的内容。

上游的构建系统设计为经过数个步骤以从源码发行文件得到并在系统中安装所生成的二进制文件。

Three typical build systems are described here. The situation of other build systems are very similar to these since debhelper(7) the does most of the work and helps you build a Debian package.

[Tip] Tip

在尝试制作 Debian 软件包之前,您应当熟悉了解上游源代码所使用的构建系统并尝试构建软件。

Debian 软件吧在构建时都会带上调试信息;但打包生成二进制软件包时,这些打包信息会按照《Debian 政策手册》中第十章 - 文件的要求进行剥离。

参见

打包软件库需要您投入更多的工作。下面有一些打包软件库的提醒和建议:

在打包共享库软件之前,请查阅:

如需研究其历史背景,请参见:

Debian lenny(5.0,2009年5月)中引入的 dpkg 符号支持可以帮助我们管理同一共享链接库软件包的向后 ABI 兼容性(backward ABI compatibility)。二进制软件包中的 DEBIAN/symbols 文件提供了每个符号及其对应的最小版本号。

一个极其简化的软件库打包流程大概如下所示。

  • 从前一个二进制软件包中使用“dpkg-deb -e”命令解压缩得到旧有的 DEBIAN/symbols 文件。

    • 或者,mc 命令也可以用来解压得到 DEBIAN/symbols 文件。
  • 将其复制为 debian/binarypackage.symbols 文件。

    • 如果这是第一次打包的话,可以只创建一个空文件。
  • 构建二进制软件包。

    • 如果 dpkg-gensymbols 命令警告添加了新的符号的话:

      • 使用“dpkg-deb -e”命令解压得到更新的 DEBIAN/symbols 文件。
      • 将其中的 Debian 修订版本号,例如 -1,从文件中去除。
      • 将其复制为 debian/binarypackage.symbols 文件。
      • 重新构建二进制软件包。
    • 如果 dpkg-gensymbols 命令不报和新链接符号有关的警告:

      • 您已完成了共享库的打包工作。

如需了解详细信息,您应当阅读下列第一手参考资料。

您也应当查看:

[Tip] Tip

对于 C++ 软件库或者其它一些难以跟踪符号变化的场景,请按照《Debian 政策手册》的 8.6.4 The shlibs system 一节的内容来代替。请确保这样操作时,事先删除 debmake 命令生成的空的 debian/binarypackage.symbols 文件。在这种情况下,应当转而使用 DEBIAN/shlibs 文件。

当您打包新版本的库软件包而且此次更新影响到其它的软件包时,您必须向 release.debian.org 伪软件包提交一个变迁 bug 报告并附带一个 ben 文件;您可以使用 reportbug 工具进行提交。提交后,请等待发行团队的审核批准方可进行下一步。

发行团队提供了变迁跟踪系统。参见 变迁(Transition)

[Caution] Caution

请确保您按照 Section 5.7.1.3, “库软件包名称” 的描述正确地对二进制软件包进行了重命名。

debconf 软件包可以帮助我们在下列两种情况下配置软件包:

  • debian-installer(Debian 安装器)预安装时进行非交互式配置。
  • 使用菜单界面进行交互式配置(对话框(dialog)gnomekde 等等)

    • 软件包安装时:由 dpkg 命令调用
    • 对已安装软件包:由 dpkg-reconfigure 命令调用

软件包安装时的所有用户交互都必须由这里的 debconf 系统进行处理,下列配置文件对这个过程进行控制。

  • debian/binarypackage.config

    • 这是 debconf config 脚本,用于向用户询问对于配置软件包必需的问题。
  • debian/binarypackage.template

    • 这是 debconf templates(模板)文件,用于向用户询问对于配置软件包必需的问题。
  • 软件包配置脚本

    • debian/binarypackage.preinst
    • debian/binarypackage.prerm
    • debian/binarypackage.postinst
    • debian/binarypackage.postrm

参见 dh_installdebconf(1)、debconf(7)、debconf-devel(7) 和《Debian 政策手册》中的 3.9.1 维护者脚本中的用户交互提示

Debian wheezy(7.0,2013年5月)在 dpkgapt 中引入了对跨架构二进制软件包安装的多架构支持(特别是 i386 架构和 amd64 架构,但也支持其它的组合),这部分内容值得我们额外关注。

您应当详细阅读下列参考内容。

多架构支持使用三元组(<triplet>)的值,例如 i386-linux-gnux86_64-linux-gnu;它们出现在共享链接库的安装路径中,例如 /usr/lib/<triplet>/,等等。

  • 三元组 <triplet> 的值由 debhelper 脚本隐式提前设置好,软件包维护者无需担心。
  • 不过,在 debian/rules 文件中用于 override_dh_* 目标的三元组 <triplet> 值需要由维护者手动进行显式设置。三元组 <triplet> 的值可由 $(DEB_HOST_MULTIARCH) 变量在 debian/rules 文件中获取到,具体方法如下:

    DEB_HOST_MULTIARCH = $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
    ...
    override_dh_install:
            mkdir -p package1/lib/$(DEB_HOST_MULTIARCH)
            cp -dR tmp/lib/. package1/lib/$(DEB_HOST_MULTIARCH)

参见:

Debian 政策要求遵守文件系统层级标准。其中 /usr/lib:程序和软件包的库 声明“/usr/lib 包含目标文件、库和其它不应由用户或 shell 脚本直接调用的内部二进制文件。”

Debian 在文件系统层级标准的基础上添加一项例外,即使用 /usr/lib/<triplet>/ 而非 /usr/lib<qual>/(例如,/lib32//lib64/)以对多架构库提供支持。


对基于 Autotools 且由 debhelper (compat>=9)管理的软件包来说,这些路径设置已由 dh_auto_configure 命令自动处理。

对于其它使用不支持的构建系统的软件包,您需要按照下面的方式手动调整安装路径。

  • 如果在 debian/rules 文件中设置了 override_dh_auto_configure 目标且其中手动调用了“./configure”命令,请确保将其替换为“dh_auto_configure --”,这样可以将安装路径从 /usr/lib/ 替换为 /usr/lib/$(DEB_HOST_MULTIARCH)/
  • 请在 debian/foo.install 文件中将所有出现的 /usr/lib/ 字符串替换为 /usr/lib/*/

所有启用多架构的软件包安装至相同路径的文件必须内容完全相同。您必须小心处理,避免数据字节序或者压缩算法等等问题带来的文件内容差异。

[Note] Note

./configure--libexecdir选项指定了由程序而非用户所使用的可执行文件的默认安装路径。其 Autotools 的默认值为 /usr/libexec/ 但在未启用多架构特性的 Debian 系统上其默认值是 /usr/lib/。如果这些可执行程序属于被标记为“Multi-arch: foreign”的软件包,最好还是使用例如 /usr/lib/ 或者 /usr/lib/软件包名 这样的路径而非使用 dh_auto_configure 设置的 /usr/lib/<triplet>/ 路径。GNU 编程规范:7.2.5 用于安装目录的变量libexecdir 的描述是“libexecdir 的定义对所有软件包相同,所以您应当将您的数据安装在其下的一个子目录中。大多数软件包将数据安装至 $(libexecdir)/package-name/ 之中……”(在与 Debian 政策不冲突的前提下,遵守 GNU 的标准总是更好的。)

位于默认路径 /usr/lib//usr/lib/<triplet>/ 的共享库可被自动加载。

对位于其它路径的共享库,必须使用 pkg-config 命令设置 GCC 选项 -l 以正确进行加载。

自 Debian jessie(8.0 开始)的编译器加固支持要求我们在打包时加以注意。

您应当详细阅读下列参考内容。

debmake 命令会向 debian/rules 文件中按需添加 DEB_BUILD_MAINT_OPTIONSDEB_CFLAGS_MAINT_APPENDDEB_LDFLAGS_MAINT_APPEND 的项目(参见 Chapter 4, 简单例子dpkg-buildflags(1))。

DEP-8 定义了 debian/tests/control 文件的格式,它是 RFC822 风格的测试元数据文件,用于 Debian 软件包的持续集成(CI)。

它在完成构建包含 debian/tests/control 文件的源码包、得到二进制包之后发挥作用。在运行 autopkgtest 命令时,所生成的二进制软件包会根据这个文件在虚拟环境中自动进行安装和测试。

See documents in the /usr/share/doc/autopkgtest/ directory and 4. autopkgtest: Automatic testing for packages of the “Ubuntu Packaging Guide”.

[Note] Note

Testing of the binary packages during their building time can be accomodated by dh_auto_test.

您可以在 Debian 系统上探索使用不同的持续集成系统。

  • debci 软件包:建立在 autopkgtest 之上的持续集成平台
  • jenkins 软件包:通用持续集成平台

Debian packaging practices are moving target. Please keep your eyes on DEP - Debian Enhancement Proposals.

Debian 关心对新硬件架构的移植工作。新架构的移植工作对自举(bootstrapping)操作有所要求,以完成对初始最小本地构建系统的交叉编译。为了在自举(bootstrapping)时避免构建依赖成环的问题,需要使用 配置类型(profile) 的构建功能特性来缩减所需构建依赖。

[Tip] Tip

如果一个核心软件包 foo 构建时依赖于 bar 软件包,但后者会引入一长串构建依赖链而且 bar 仅在 footest 目标中使用(即仅用于构建后测试),那么您可以安全地在 foo 软件包的 Build-depends 一栏中将 bar 标记为 <!nocheck> 以规避构建依赖环。

reportbug 命令用于提交 binarypackage 软件包的错误报告;usr/share/bug/binarypackage/ 可以对针对该软件所提交报告的内容进行自定义。

dh_bugfiles 命令将安装以下位于 debian/ 目录中的的模板文件。

  • debian/binarypackage.bug-controlusr/share/bug/binarypackage/control

    • 该文件包含诸如重定向错误报告至其它软件包的一些指导性内容。
  • debian/binarypackage.bug-presubjusr/share/bug/binarypackage/presubj

    • 该文件的内容将由 reportbug 命令向用户展示。
  • debian/binarypackage.bug-scriptusr/share/bug/binarypackage or usr/share/bug/binarypackage/script

    • reportbug 命令运行此脚本以生成错误报告的模板文件。

参见 dh_bugfiles(1) 和 为开发者提供的 reportbug 功能特性

[Tip] Tip

如果您总是需要提醒提交报告的用户某些注意事项或询问他们某些问题,使用这些文件可以将这个过程自动化。



[11] 对九成以上的软件包来说,软件包名称都不会超过 24 个字符;上游版本号通常不超过 10 个字符,而 Debian 修订版本号也通常不超过 3 个字符。

[12] 使用“debmake -t …”命令或者“git deborig -f HEAD”能够帮助这个工作流。参见 Section 6.2, “Snapshot upstream tarball (-d, -t)”dgit-maint-merge(7)。

[13] 这个简化形式在 debhelper 软件包第七版或更新的版本中可用。本指南内容假设您在使用 debhelper 第 13 版或更新的版本。

[14] debmake 命令会产生稍微复杂一些的 debian/rules 文件。虽然如此,其核心结构没有什么变化。

[15] 如果您在使用 vim 编辑器,请确保使用“:wq”命令对内容进行保存。

[16] 程序以前会在内部调用来自 devscripts 软件包的 licensecheck 命令来进行检查。现在的 licensecheck 命令由独立的 licensecheck 软件包所提供,相较从前的实现也有了较大的改进。

[17] 该文档是在 symbols 文件被引入之前写成的。

[18] 第六章 - 开发(-DEV)软件包中,存在强烈的使用含有 SONAME 版本号的 -dev 软件包名而非仅使用 -dev 作为名称的偏好,但前 ftp-master 成员(Steve Langasek)对此有不同意见。请注意该文档在 multiarch 系统和 symbols 引入之前写成,可能有一定程度的过时。

[19] 这个路径和 FHS 兼容。文件系统层级标准:/usr/lib:程序和软件包的库 称“应用程序可以使用 /usr/lib 下的一个子目录。如果一个应用程序使用一个子目录,所有由此程序所使用的架构相关数据均须放置于该子目录下。”