在Debian系统上修改开源软件源代码制作patch
整个过程可以分为以下几个主要步骤:
- 准备环境: 安装编译工具和
blueman
的编译依赖。 - 获取源码: 下载
blueman
的Debian源码包。 - 修改代码并创建Patch: 使用Debian推荐的
quilt
工具进行修改和补丁管理。 - 编译打包: 将你的修改和源码一起编译成一个新的
.deb
安装包。 - 安装和验证: 安装你新编译的包,并验证修改是否生效。
详细步骤
第1步:准备环境
首先,你需要确保你的系统已经准备好进行软件编译。
启用源码仓库
你需要编辑/etc/apt/sources.list
文件,确保每一行deb
地址后面都有一行对应的deb-src
地址。这是为了让apt
能够下载源代码。打开文件:
sudo nano /etc/apt/sources.list
例如,如果你的文件中有这样一行:
deb http://deb.debian.org/debian/ bookworm main
请确保它下面有对应的
deb-src
行:deb-src http://deb.debian.org/debian/ bookworm main
保存文件后,更新你的包列表:
sudo apt update
安装必要的编译工具
这些是Debian打包必备的工具。sudo apt install build-essential devscripts quilt
build-essential
: 包含编译器(gcc/g++)、make等基础工具。devscripts
: 包含一系列用于Debian打包的脚本,如debuild
。quilt
: Debian官方推荐的补丁管理工具,非常强大。
安装
blueman
的编译依赖apt
有一个非常方便的命令,可以自动安装某个软件包编译时所需的所有依赖。sudo apt-get build-dep blueman
这个命令会读取
blueman
源码包的控制文件,并安装所有列出的编译依赖项。
第2步:获取源码
现在,你的环境准备好了,可以下载blueman
的源码了。
创建一个工作目录,并进入该目录:
mkdir ~/blueman-dev cd ~/blueman-dev
下载
blueman
的源码包:apt source blueman
这个命令会下载三个文件(一个
.orig.tar.gz
原始源码包,一个.debian.tar.xz
Debian特定修改包,一个.dsc
描述文件),并自动解压到一个以版本号命名的目录中,例如blueman-2.3.5
。进入解压后的源码目录:
cd blueman-2.3.5/ # 注意:版本号可能不同,请使用你实际解压出的目录名
第3步:修改代码并创建Patch
这是最核心的一步。我们将使用 quilt
来管理我们的修改,这样可以保持源码树的干净,并轻松生成补丁文件。debian/patches/
目录存放了所有应用于源码的补丁。
创建一个新的补丁 (Patch)
给你的补丁起一个有意义的名字,比如my-connection-fix.patch
。quilt new my-connection-fix.patch
告诉
quilt
你要修改哪个文件
假设你要修改的文件是plugins/mechanism/Mechanism.py
。quilt add plugins/mechanism/Mechanism.py
重要提示: 你可以添加多个文件到同一个patch中。在你修改任何文件之前,都要先用
quilt add
命令把它加进来。修改代码
现在,用你喜欢的编辑器打开这个文件并进行修改。nano plugins/mechanism/Mechanism.py
进行你想要的修改,比如修复连接失败的逻辑,然后保存并关闭文件。
生成/刷新补丁
在你完成所有修改后,使用以下命令,quilt
会自动比较你修改过的文件和原始文件的差异,并把这些差异保存到你之前创建的my-connection-fix.patch
文件中。quilt refresh
现在,你可以去
debian/patches/
目录下查看,会发现多了一个my-connection-fix.patch
文件,里面就是你的代码改动。同时,debian/patches/series
文件里也会自动添加这一行的名字,确保编译时这个补丁会被应用。(可选)为你的补丁添加描述头
这是一个好习惯,可以说明这个补丁是做什么的。quilt header -e
这会打开一个编辑器,让你填写
Description
和Author
等信息。
第4步:编译打包
现在你的补丁已经准备好了,可以开始编译生成 .deb
文件了。
(可选,推荐)更新changelog
为了区分你编译的版本和官方版本,最好在debian/changelog
文件中增加一个条目。这可以防止你的包被官方更新覆盖。dch -i
或者使用
dch -l local
来添加一个本地版本后缀:dch -l local "My local build with connection fix."
这会自动用编辑器打开
debian/changelog
文件,在顶部生成一个新的版本条目,比如2.3.5-2+local1
。你只需要确认信息无误并保存即可。开始编译
在源码的根目录(blueman-2.3.5/
)下,运行编译命令:dpkg-buildpackage -us -uc -b
-us
: 不对源码包进行签名 (Don’t sign source package)。-uc
: 不对.changes
文件进行签名 (Don’t sign changes file)。-b
: 只编译二进制包(即我们需要的.deb
文件)。
编译过程需要一些时间。如果一切顺利,你不会看到任何错误。
查找编译好的
.deb
文件
编译完成后,新的.deb
文件会生成在上一级目录,也就是~/blueman-dev/
目录中。ls ../*.deb
你应该能看到类似
blueman_2.3.5-2+local1_amd64.deb
这样的文件。
第5步:安装和验证
卸载旧版本
为了避免冲突,最好先卸载掉系统里通过apt
安装的blueman
。sudo apt remove blueman
安装你的新包
使用dpkg
来安装你刚刚编译好的包。sudo dpkg -i ../blueman_*.deb
注意:
dpkg
不会自动处理依赖关系。如果在上一步build-dep
都已安装,这里通常不会有问题。万一提示缺少依赖,可以运行以下命令来修复:sudo apt-get -f install
防止你的包被自动更新覆盖
这是非常重要的一步!否则下次你运行sudo apt upgrade
时,你的自定义版本会被官方仓库里的新版本覆盖掉。sudo apt-mark hold blueman
当你不再需要这个自定义版本时,可以用
unhold
命令解除锁定:sudo apt-mark unhold blueman
验证
重启blueman服务或直接重启电脑,然后测试你的蓝牙连接功能,看你的修改是否解决了问题。killall blueman-applet blueman-applet &
清理
使用 quilt push 命令。这个命令会应用当前正在工作的补丁(my-connection-fix.patch),并让你准备好处理下一个补丁。
清理编译文件
dpkg-buildpackage -T clean
这个命令会执行 debian/rules
文件中定义的 clean
目标,它会做以下事情:
- 撤销所有
quilt
补丁,让源码树恢复到原始状态。 - 删除所有由
configure
或meson setup
等命令生成的 Makefile 和配置文件。 - 删除所有编译生成的中间文件(
.o
,.pyc
等)。 - 删除上一次编译留下的所有临时目录和文件。
执行完后,你的源码目录就回到了一个干净的、可以重新开始编译的状态。
管理补丁
- 如果要修改现有的补丁,比如
my-connection-fix.patch
,先用quilt pop
回退到它,然后编辑,最后quilt refresh
。 - 如果要添加新补丁,用
quilt push -a
应用所有现有补丁,然后quilt new ...
开始新的修改。
总结
整个流程可以简化为:apt source
-> quilt new
-> quilt add
-> 编辑代码 -> quilt refresh
-> dpkg-buildpackage
-> dpkg -i
-> apt-mark hold
。
这个过程不仅适用于blueman
,也适用于Debian/Ubuntu仓库中的绝大多数软件包。祝你成功解决问题!如果你的补丁是通用的修复,也欢迎你向 blueman
的上游项目(GitHub)提交一个Pull Request,为开源社区做出贡献。
在Debian系统上修改开源软件源代码、制作patch并重新编译打包
补充
- 常用 quilt 命令:
quilt series: 查看所有补丁的列表以及它们的应用状态。
quilt push: 应用下一个补丁。
quilt pop: “弹出”并撤销上一个应用的补丁,使其变为当前活动补丁,方便你重新编辑它。
quilt push -a: 应用所有补丁。
quilt pop -a: 撤销所有补丁,让源码树恢复到最原始的状态。
quilt top: 查看栈顶(最新应用)的补丁。
quilt previous: 切换到上一个补丁。
quilt next: 切换到下一个补丁。 - 当更新相关软件时会设计依赖,可能会报错且update/upgrade后也无效,请检查相关包是否被锁定
apt-mark showhold xxx //根据报错提示