Working with patches

Working with patches

https://openwrt.org/docs/guide-developer/toolchain/use-patches-with-buildsystem

 

The build system integrates quilt for easy patch management. This document outlines some common patching tasks like adding a new patch or editing existing ones.

In order to let quilt create patches in the preferred format, a configuration file .quiltrc containing common diff and patch options must be created in the local home directory.

cat << EOF > ~/.quiltrc
QUILT_DIFF_ARGS="--no-timestamps --no-index -p ab --color=auto"
QUILT_REFRESH_ARGS="--no-timestamps --no-index -p ab"
QUILT_SERIES_ARGS="--color=auto"
QUILT_PATCH_OPTS="--unified"
QUILT_DIFF_OPTS="-p"
EDITOR="nano"
EOF
  • EDITOR specifies the preferred editor for interactive patch editing
  • The other variables control the patch format property like a/, b/ directory names and no timestamps
  • FreeBSD does not support the --color=auto option and -pab must be written as -p ab
  •  -p ab is working with quilt 0.63 on Linux and is documented in man page.

To add a completely new patch to an existing package example start with preparing the source directory:

make package/example/{clean,prepare} V=s QUILT=1

For host-side packages, you may want to detail the make target:

make package/example/host/{clean,prepare} V=s QUILT=1

This unpacks the source tarball and prepares existing patches as quilt patch series (if any). The verbose output will show where the source got extracted.

Change to the prepared source directory.

cd build_dir/target-*/example-*

Note: It can happen that you need to go one level lower as the source is extracted in build_dir/target-*/BUILD_VARIANT/example-*. This happens when multiple build variants of a package are defined in the Makefile.

Apply all existing patches using quilt push.

quilt push -a

At this point, we can either import an upstream patch or we can create a new patch by hand. The advantage of importing an upstream patch is that the data associated with it is maintained in the project (upstream's git header, author of the patch, why it is necessary, and if it was upstreamed etc). As an aside, both github and gitlab offer the ability to easily create a patch from a given commit in their respective web interfaces. To do so simply browse to a commit and edit the URL appending a literal “.patch” to it.

To import a patch, download it to a temp directory, and give it a name according to these guidelines:

  • The name should start with a number, followed by a hyphen and a very short description of what is changed
  • The chosen number should be higher than any existing patch - use quilt series to see the list of patches
  • The patch file name should be short but descriptive
quilt import /path/to/010-main_code_fix.patch

To simply create a new, empty patch file without importing an existing one:

quilt new 010-main_code_fix.patch

After creating the empty patch, files to edit must be associated with it. The quilt add command can be used for that - once the file got added it can be edited as usual.

A shortcut for both adding a file and open it in an editor is the quilt edit command:

quilt edit src/main.c
  • src/main.c gets added to 010-main_code_fix.patch
  • The file is opened in the editor specified with EDITOR in .quiltrc

Repeat that for any file that needs to be edited.

After the changes are finished, they can be reviewed with the quilt diff command.

quilt diff

If the diff looks okay, proceed with quilt refresh to update the 010-main_code_fix.patch file with the changes made.

quilt refresh

Change back to the toplevel directory of the buildroot.

cd ../../..

To move the new patch file over to the buildroot, run update on the package:

make package/example/update V=s

Finally rebuild the package to test the changes:

make package/example/{clean,compile} package/index V=s

If problems occur, the patch needs to be edited again to solve the issues. Refer to the section below to learn how to edit existing patches.

Start with preparing the source directory:

make package/example/{clean,prepare} V=s QUILT=1

Change to the prepared source directory.

cd build_dir/target-*/example-*

List the patches available:

quilt series

Advance to the patch that needs to be edited:

quilt push 010-main_code_fix.patch
  • When passing a valid patch filename to pushquilt will only apply the series until it reaches the specified patch.
  • If unsure, use quilt series to see existing patches and quilt top to see the current position.
  • If the current position is beyound the desired patch, use quilt pop to remove patches in the reverse order.
  • You can use the “force” push option (e.g. quilt push -f 010-main_code_fix.patch) to interactively apply a broken (i.e. has rejects) patch.

Edit the patched files using the quilt edit command, repeat for every file that needs changes.

quilt edit src/main.c

Check which files are to be included in the patch:

quilt files

Review the changes with quilt diff.

quilt diff

If the diff looks okay, proceed with quilt refresh to update the current patch with the changes made.

quilt refresh

Change back to the toplevel diretory of the buildroot.

cd ../../../

To move the updated patch file over to the buildroot, run update on the package:

make package/example/update V=s

Finally rebuild the package to test the changes:

make package/example/{clean,compile} package/index V=s

To prepare the kernel tree, use:

make target/linux/{clean,prepare} V=s QUILT=1

The source tree is in the target-architecture subdirectory (potentially with a subarch):

cd build_dir/target-*/linux-*/linux-*

The process for modifying kernel patches is the same as for packages, only the make targets and directories differ.

 For the kernel, an additional subdirectory for patches is used, generic/ contains patches common to all architectures and platform/ contains patches specific to the current target (the latter are found in the target/linux/<arch_name>/patches-* folder in the source).

So, you should first choose where the patch belongs, this is for patches in generic folder:

quilt new generic/010-main_code_fix.patch

patches in platform folder instead should be made with

quilt new platform/010-main_code_fix.patch

And in case you are editing files, it works like for packages but as you saw with the command to make the new patch you need to add the folder name before the name of the patch you are working on.

After you made your changes and saved your patch with quilt refresh, you can go back to top level directory:

cd ../../../..

And then you can move the patches you created in these temporary directories back to main source tree:

make target/linux/update package/index V=s

You can also simply copy the patch files over from the local work folder of quilt here (target/linux/<arch_name>/<linux-version>/patches/generic or target/linux/<arch_name>/<linux-version>/patches) to the source folder (target/linux/generic/patches-* or target/linux/<arch_name>/patches-*)

the process might fail with an error that looks like this

bash: line 3: /run/media/alby/data_xeon_btrfs/source_code/my_LEDE_fork/source/staging_dir/host/bin/usign: No such file or directory

and you can safely ignore it, as it just means that you haven't run a compile yet so the “usign” tool used to sign packages does not yet exist. Since you are just working with source, it's irrelevant.

( Patches should be named with the correct prefix, platform/000-abc.patch or generic/000-abc.patch. If not the update may not work correctly.)

Afterwards, if we want to verify whether our patch is applied or not, we can go to the top level directory with

cd ../../../../

and preparing again the linux folder for some modification with

make target/linux/{clean,prepare} V=s QUILT=1

During this process all the applied patched will be shown, ours being among them, preceeded by generic or platform depending on what directory we placed the patch. Another way of retrieving the applied patches is through

quilt series

as explained on the previous sections, after having made make target/linux/{clean,prepare} ...

For example, gcc:

To prepare the tool tree, use:

make toolchain/gcc/{clean,prepare} V=99 QUILT=1

The source tree depends on chosen lib and gcc :

cd build_dir/toolchain-mips_r2_gcc-4.3.3+cs_uClibc-0.9.30.1/gcc-4.3.3

Refreshing the patches is done with:

make toolchain/gcc/update V=99

valid for target/linux/generic and <arch>:

The patches-* subdirectories contain the kernel patches applied for every OpenWrt target.
All patches should be named 'NNN-lowercase_shortname.patch' and sorted into the following categories:

0xx - upstream backports
1xx - code awaiting upstream merge
2xx - kernel build / config / header patches
3xx - architecture specific patches
4xx - mtd related patches (subsystem and drivers)
5xx - filesystem related patches
6xx - generic network patches
7xx - network / phy driver patches
8xx - other drivers
9xx - uncategorized other patches

ALL patches must be in a way that they are potentially upstreamable, meaning:

- they must contain a proper subject
- they must contain a proper commit message explaining what they change
- they must contain a valid Signed-off-by line

from: PATCHES

When a patched package (or kernel) is updated to a newer version, existing patches might not apply cleanly anymore and patch will report fuzz when applying them. To rebase the whole patch series the refresh make target can be used:

make package/example/refresh V=s

For kernels, use:

make target/linux/refresh V=s

When implementing new changes, it is often required to edit patches multiple times. To speed up the process, it is possible to retain the prepared source tree between edit operations.

  1. Initially prepare the source tree as documented above
  2. Change to the prepared source directory
  3. Advance to the patch needing changes
  4. Edit the files and refresh the patch
  5. Fully apply the remaining patches using quilt push -a (if any)
  6. From the toplevel directory, run make package/example/{compile,install} or make target/linux/{compile,install} for kernels
  7. Test the binary
  8. If further changes are needed, repeat from step 2.
  9. Finally run make package/example/update or make target/linux/update for kernels to copy the changes back to build system

 

==========

使用补丁

构建系统集成了 quilt 以轻松管理补丁。 本文档概述了一些常见的修补任务,例如添加新补丁或编辑现有补丁。

为了让 quilt 以首选格式创建补丁,必须在本地主目录中创建一个包含常见 diff 和 patch 选项的配置文件。.quiltrc

cat << EOF > ~/.quiltrc
QUILT_DIFF_ARGS="--no-timestamps --no-index -p ab --color=auto"
QUILT_REFRESH_ARGS="--no-timestamps --no-index -p ab"
QUILT_SERIES_ARGS="--color=auto"
QUILT_PATCH_OPTS="--unified"
QUILT_DIFF_OPTS="-p"
EDITOR="nano"
EOF
  • EDITOR指定交互式 Patch 编辑的首选编辑器
  • 其他变量控制 patch 格式属性,如 a/、b/ 目录名称,并且没有时间戳
  • FreeBSD 不支持该选项,必须写成--color=auto-pab-p ab
  • -p ab在 Linux 上使用 quilt 0.63,并记录在手册页中。

要向现有软件包示例添加全新的补丁,请先准备源目录:

make package/example/{clean,prepare} V=s QUILT=1

对于主机端软件包,您可能需要详细说明 make 目标:

make package/example/host/{clean,prepare} V=s QUILT=1

这将解压缩源 tarball 并将现有补丁准备为 quilt patch 系列(如果有)。 详细输出将显示源的提取位置。

切换到准备好的源目录。

cd build_dir/target-*/example-*

注: 由于 源是在 中提取的,因此可能需要降低一个级别。 当在 Makefile 中定义了软件包的多个 build 变体时,会发生这种情况。build_dir/target-*/BUILD_VARIANT/example-*

使用 quilt push 应用所有现有面片。

quilt push -a

此时,我们可以导入上游补丁,也可以手动创建新补丁。导入上游补丁的优点是,与其关联的数据在项目中维护(上游的 git 头、补丁的作者、为什么需要补丁以及它是否被上游化等)。 顺便说一句,github 和 gitlab 都提供了在各自的 Web 界面中从给定提交轻松创建补丁的能力。为此,只需浏览到一个提交并编辑 URL,并在其后附加一个文本 “.patch” 即可。

要导入补丁,请将其下载到临时目录,并根据以下准则为其命名:

  • 名称应以数字开头,后跟连字符和对更改内容的非常简短的描述
  • 所选数字应高于任何现有色块 - 使用面组系列查看色块列表
  • 补丁文件名应简短但具有描述 性
quilt import /path/to/010-main_code_fix.patch

要简单地创建一个新的空补丁文件而不导入现有补丁文件:

quilt new 010-main_code_fix.patch

创建空补丁后,要编辑的文件必须与它关联。 可以使用 quilt add 命令 - 一旦文件被添加,就可以像往常一样编辑它。

添加文件和在编辑器中打开文件的快捷方式是面组编辑命令:

quilt edit src/main.c
  • src/main.c被添加到010-main_code_fix.patch
  • 文件将在 中指定的编辑器中打开EDITOR.quiltrc

对需要编辑的任何文件重复此操作。

更改完成后,可使用 quilt diff 命令对其进行查看。

quilt diff

如果差异看起来正常,请继续进行面组刷新,以使用所做的更改更新文件。010-main_code_fix.patch

quilt refresh

更改回 buildroot 的 toplevel 目录。

cd ../../..

要将新的补丁文件移动到 buildroot,请在包上运行 update

make package/example/update V=s

最后,重新构建包以测试更改:

make package/example/{clean,compile} package/index V=s

如果出现问题,则需要再次编辑补丁以解决问题。 请参阅以下部分以了解如何编辑现有补丁。

从准备源目录开始:

make package/example/{clean,prepare} V=s QUILT=1

切换到准备好的源目录。

cd build_dir/target-*/example-*

列出可用的补丁:

quilt series

前进到需要编辑的补丁:

quilt push 010-main_code_fix.patch
  • 当传递有效的 patch 文件名进行推送时,quilt 将仅应用该系列,直到它到达指定的 patch。
  • 如果不确定,请使用 quilt series 查看现有补丁,使用 quilt top 查看当前位置。
  • 如果当前位置位于所需色块之间,则使用 quilt pop 以相反的顺序删除色块。
  • 您可以使用 “force” 推送选项(例如 )以交互方式应用损坏的(即有拒绝)补丁。quilt push -f 010-main_code_fix.patch

使用 quilt edit 命令编辑已修补的文件,对需要更改的每个文件重复上述步骤。

quilt edit src/main.c

检查补丁中要包含哪些文件:

quilt files

使用 quilt diff 查看更改。

quilt diff

如果差异看起来正常,请继续进行面组刷新,以使用所做的更改更新当前补丁。

quilt refresh

更改回 buildroot 的顶层目录。

cd ../../../

要将更新的补丁文件移动到 buildroot,请在包上运行 update

make package/example/update V=s

最后,重新构建包以测试更改:

make package/example/{clean,compile} package/index V=s

要准备内核树,请使用:

make target/linux/{clean,prepare} V=s QUILT=1

源树位于 target-architecture 子目录中(可能带有子架构):

cd build_dir/target-*/linux-*/linux-*

修改内核补丁的过程与软件包相同,只是 make 目标和目录不同。

对于内核,使用一个额外的 patches 子目录,其中包含所有架构通用的补丁,并包含特定于当前目标的补丁(后者位于源的文件夹中)。generic/platform/target/linux/<arch_name>/patches-*

所以,你应该首先选择补丁的所属位置,这是针对 generic 文件夹中的补丁的:

quilt new generic/010-main_code_fix.patch

相反,平台文件夹中的补丁应该使用

quilt new platform/010-main_code_fix.patch

如果您正在编辑文件,它的工作方式与包类似,但正如您在创建新补丁的命令中看到的那样,您需要在您正在处理的补丁名称之前添加文件夹名称。

在你做了更改并使用 保存了你的补丁后,你可以回到顶级目录:quilt refresh

cd ../../../..

然后,您可以将在这些临时目录中创建的补丁移回主源代码树:

make target/linux/update package/index V=s

您也可以简单地将补丁文件从 quilt 的本地工作文件夹复制到此处(target/linux/<arch_name>/<linux-version>/patches/generic 或 target/linux/<arch_name>/<linux-version>/patches)到源文件夹(target/linux/generic/patches-* 或 target/linux/<arch_name>/patches-*)

该过程可能会失败,并显示如下所示的错误

bash: line 3: /run/media/alby/data_xeon_btrfs/source_code/my_LEDE_fork/source/staging_dir/host/bin/usign: No such file or directory

你可以放心地忽略它,因为它只是意味着你还没有运行编译,所以用于对包进行签名的 “usign” 工具还不存在。 因为你只是在处理 source,所以这无关紧要。

(补丁应使用正确的前缀命名,即 platform/000-abc.patch 或 generic/000-abc.patch。 否则,更新可能无法正常工作。

之后,如果我们想验证我们的补丁是否被应用,我们可以转到 top 级目录

cd ../../../../

并再次准备 Linux 文件夹以进行一些修改

make target/linux/{clean,prepare} V=s QUILT=1

在此过程中,将显示所有已应用的补丁,我们的补丁就在其中,前面是 generic 或 platform,具体取决于我们放置补丁的目录。 检索已应用补丁的另一种方法是通过

quilt series

如前几节所述,在使 make target/linux/{clean,prepare} ...

例如,gcc:

要准备工具树,请使用:

make toolchain/gcc/{clean,prepare} V=99 QUILT=1

源代码树取决于所选的 lib 和 gcc :

cd build_dir/toolchain-mips_r2_gcc-4.3.3+cs_uClibc-0.9.30.1/gcc-4.3.3

刷新补丁是通过以下方式完成的:

make toolchain/gcc/update V=99

对 target/linux/generic 和 <arch> 有效:

The patches-* subdirectories contain the kernel patches applied for every OpenWrt target.
All patches should be named 'NNN-lowercase_shortname.patch' and sorted into the following categories:

0xx - upstream backports
1xx - code awaiting upstream merge
2xx - kernel build / config / header patches
3xx - architecture specific patches
4xx - mtd related patches (subsystem and drivers)
5xx - filesystem related patches
6xx - generic network patches
7xx - network / phy driver patches
8xx - other drivers
9xx - uncategorized other patches

ALL patches must be in a way that they are potentially upstreamable, meaning:

- they must contain a proper subject
- they must contain a proper commit message explaining what they change
- they must contain a valid Signed-off-by line

发件人: PATCHES

当修补后的软件包(或内核)更新到较新版本时,现有补丁可能不再干净地应用,并且补丁在应用它们时将报告 fuzz。 要对整个补丁系列进行变基,可以使用 refresh make 目标:

make package/example/refresh V=s

对于内核,请使用:

make target/linux/refresh V=s

实施新更改时,通常需要多次编辑补丁。 为了加快该过程,可以在编辑操作之间保留准备好的源代码树。

  1. 最初按照上面记录的准备源代码树
  2. 更改准备好的源目录
  3. 前进到需要更改的补丁
  4. 编辑文件并刷新补丁
  5. 使用 quilt push -a(如果有)完全应用剩余的补丁
  6. 从顶级目录,运行 或 for kernelsmake package/example/{compile,install}make target/linux/{compile,install}
  7. 测试二进制文件
  8. 如果需要进一步更改,请从步骤 2 开始重复。
  9. 最后运行 or 让内核将更改复制回构建系统make package/example/updatemake target/linux/update

 

========== End

 

posted @ 2024-11-12 10:58  lsgxeva  阅读(8)  评论(0编辑  收藏  举报