Patching packages (简体中文) - ArchWiki

Jump to content

# Patching packages (简体中文)

From ArchWiki

相关文章

- Arch Build System

翻译状态：本文是 Patching packages 的翻译。上次翻译日期：2022-02-15。如果英文版本有所更改，则您可以帮助同步翻译。

本文涵盖了如何在 Arch Build System (ABS) 中为软件包创建和应用补丁。

补丁 描述了一个或多个文件的行更改。补丁通常用于自动更改源代码。

## 创建补丁

注意： 如果你只是想要更改一两行，你可能会想使用 sed。

diff 工具逐行比较文件。将它的输出保存下来你就得到了一个补丁，如 `diff --unified --recursive --text foo bar > patch`， 如果你传递了目录， diff 会比较它们包含的文件。

1. 如果你已将构建了软件包，请删除 `src` 目录。
2. 运行 `makepkg --nobuild` 会下载并提取，但不会构建 `PKGBUILD` 中声明的源文件。如果你正在创建补丁的系统上没有必要的依赖，你可能需要运行 `makepkg --nobuild --nodeps` 作为替代。
3. 在 `src` 目录中创建两份提取的目录的副本，一个作为原始版本，一个作为你修改过的版本，将他们称为 `package.orig` 和 `package.new`。
4. 在 `package.new` 目录中进行你的更改。
5. 运行 `diff --unified --recursive --text package.orig package.new --color` 并检查补丁是否看起来良好。
6. 运行 `diff --unified --recursive --text package.orig package.new > package.patch` 来生成补丁。
7. 进入 `package.orig` 目录并使用 `patch --strip=1 < ../package.patch` 命令来应用补丁。运行 `makepkg --noextract --install` 命令构建并安装更改后的软件包来验证补丁是否正常工作。

注意： 你也可以使用 Git 的 `git diff` 命令或者 `git format-patch` 命令 [1]。

更多信息参见 diff(1) 和 git-diff(1)。

## 应用补丁

本节概述如何在 `PKGBUILD` 的 `prepare()` 函数中应用你创建或从网络下载的补丁。请遵循以下步骤：

1. 为补丁文件在 `PKGBUILD` 的 `source` 数组中添加一个条目，将该条目与原始源 url 之间用空格隔开。如果该文件可在网上获得，你可以提供完整的 URL ，它将被自动下载并放在 `src` 目录中。如果它是你自己创建的补丁，则应将补丁文件与 `PKGBUILD` 文件放在同一目录中，并只需将文件名添加到 `source` 数组中，以便将其复制到 `src` 目录中。如果你重新发布 `PKGBUILD`，你应该在 `PKGBUILD` 中包含补丁。
2. 然后使用 `makepkg -g >> PKGBUILD` 或者 `updpkgsums` (来自于 pacman-contrib) 来更新 `sha512sums` 数组。 或者手动添加一个条目到 `sha512sums` 数组； 你可以使用 sha512sum 工具来生成你的补丁的校验和。
3. 如果 `PKGBUILD` 还没有 `prepare()` 函数就创建它。
4. 第一步是进入到需要被打补丁的目录（在 `prepare()` 函数中，不是你的终端！你希望自动化打补丁这一过程）。 也可以通过 `cd "$srcdir/$pkgname-$pkgver"` 完成。 `$pkgname-$pkgver` 通常是解包一个下载源文件的目录名，但并不总是这样。
5. 现在你只需要从这个目录里面应用补丁。这可以通过添加 `patch --strip=1 --input=pkgname.patch` 到你的 `prepare()` 函数就能简单完成。 将 `pkgname.patch` 改成包含 diff 的文件的名字（因为在 `PKGBUILD` 的 `source` 数组中而被自动复制到 `src` 的文件）。

一个 prepare 函数示例：

    prepare() {
        cd "$pkgname-$pkgver"
        patch --forward --strip=1 --input="${srcdir}/eject.patch"
    }

或者不先 cd,直接使用 `patch` 的 `--directory` 参数：

    prepare() {
        patch --directory="$pkgname-$pkgver" --forward --strip=1 --input="${srcdir}/eject.patch"
    }

从终端运行 `makepkg`， 如果一切顺利，补丁会被自动应用，并且你的新软件包会包含补丁中的更改。如果不是这样的话，你可能需要试验一下补丁的 `--strip` 选项。 在试验的时候，你会发现 `--dry-run`, `--reverse` 或者 `--verbose` 选项会有用。更多信息参见 patch(1)。

基本上它的工作原理如下。如果 diff 文件被创建来将补丁应用到 `myversion/` 中的文件，那么 diff 文件将被应用于 `myversion/file`。你正在 `yourversion/` 目录中运行它（因为你会 cd 到 `PKGBUILD` 中的目录），因此当补丁应用该文件时，你希望它将其应用到 `file` 文件，并从 `myversion/` 部分中取出。 `--strip=1` 通过从路径中删除一个目录来实现这一点。但是，如果开发者在 `myfiles/myversion` 中修补，则需要删除两个目录，因此你使用 `--strip=2`。

如果你不应用一个 `--strip` 选项，它将会去掉所有目录结构。如果所有文件都在基础目录中的时候是可以的。但是如果补丁是在 `myversion/` 上创建的，并且有一个被编辑的文件是 `myversion/src/file`，当你从 `yourversion` 目录以不带 `--strip` 参数的方式运行补丁的时候，它会尝试为一个名为 `yourversion/file` 的文件打补丁。

大多数开发者从被打补丁的目录的父目录创建补丁，因此 `--strip=1` 通常是正确的。

## 使用 quilt

一个更简单的创建补丁的方法是使用 quilt，它为管理许多补丁提供了更好的支持，例如应用补丁，刷新补丁和将打补丁的文件回退到原始状态。Debian 使用 quilt 来管理他们的补丁。quilt 生成和应用补丁、回退打补丁的文件的基本用法的基本信息可参考 使用 Quilt。

## 另见

- http://www.kegel.com/academy/opensource.html — 有关修补文件的有用信息

Category:

- Package management (简体中文)