发布于 ,更新于 

年轻人的第一个包:不太严谨的 AOSC OS 贡献指南

导语

「我打包?真的假的」

刚刚落下帷幕的 AOSCC 2025 气氛热烈(尽管从一个广为流传的投票来看,似乎参会的半数以上人都没用过 AOSC),相信通过这次盛会,有更多朋友认识了 AOSC OS——这个以「简明可靠」为目标的社区主导型 Linux 发行版。
作为一个充满活力的开源项目,AOSC OS 的每一点进步都离不开社区成员的热情参与。当你下载安装,并亲身体验了一段时间的 AOSC OS 后,心里或许已经萌生了不少想法:你可能对它活跃的社区支持印象深刻,也可能对某些功能有了自己独特的改进点子,甚至……你已经开始摩拳擦掌,想要亲自为这个“共建”的系统添砖加瓦了!
而在遇见 AOSC OS 之前,你也许已经和许多 Linux 发行版打过交道了——从稳重的 CentOS,到流行的 Ubuntu,再到一滚到底的 Arch Linux。大多数时候,你可能只是默默地作为一名用户,看过了一车车繁杂的交互,淹没在了无尽的邮件列表中。于是来到了 AOSC OS ,当有人提到了「打包」这个词后,你的心中或许会产生一些疑问:我能给一个 Linux 发行版贡献软件包,真的假的?

当然可以!本篇文章将会从一个不太严谨的角度,介绍一下如何为 AOSC OS 的软件包添砖加瓦。你会发现,只需通过你熟悉的 GitHub,就能轻松参与其中,并亲眼见证自己的代码通过系统更新,被送到每一位用户手中!

本篇由本人入门经历总结而成,希望能为你提供一份友好的实践向导。更全面和权威的信息,推荐随时查阅 AOSC OS 官方维基

前置知识

参与 AOSC OS 的软件包维护,通常有三条路径:你可以引入一个全新的软件包,为系统拓展功能;可以重构或改进现有软件包,让它变得更好用;当然,你也可以从最常见、最容易上手的更新现有软件包开始。本文将聚焦于最后这一种,它也是感受社区协作、积累贡献经验的绝佳起点。
为了让整个过程更顺利,本篇默认你对 Git 和 GitHub 的基础操作有所了解,已经使用了 AOSC OS 一段时间,具备一定的调试和找代码读日志经验
并且正如上所说,本文将带你走完一次完整的软件包更新流程,并不会涉及过多的软件包新增重构方面的复杂工作。如果你完成了「新手任务」,可以继续参考更详细的 AOSC OS 软件包样式指南 来了解软件包构建这方面的具体细节。

包从哪里来

核心工作流「主题制」

在动手之前,我们需要先了解一下 AOSC OS 管理软件包的独特方式。
首先我们要明白一点:AOSC OS 目前还没有演进到「有社区共识的第三方库」的阶段,因此你一般情况下不会见到类似 PPA 或是 AUR 这样的第三方软件源。所有的包都来自于 AOSC OS 的官方仓库,用户可以通过系统自带的包管理工具(实际上就是 oma)来安装和更新软件。
AOSC 使用 Monorepo 的方式来管理软件构建,所有软件包的构建脚本和配置文件都集中在一个名为 aosc-os-abbs 的仓库中。

其中,你一点仓库就会看到的 stable 分支就是经过审查的 AOSC OS 稳定源,也是你会从软件源中默认获取到的包。而同仓库的其他分支在 AOSC OS 中被称作主题(topic) 。在 AOSC OS 里,主题是更新、重建或修改一个或多个软件包的独立流程。通过创建不同分支的方式,每个主题可以在分支内独立进行调研、讨论、打包、测试和发布,避免与其他更新相互影响。你可以在目前还是英文的AOSC OS 主题制维护指南了解更多细节。

如果你是最终用户,可以通过 oma topics 命令来查看当前可用的测试源主题,并且可以选择性地加入测试,提前尝鲜,并帮助开发者发现问题。(注意:要使用测试源,请保证你的 oma mirrors 选项中包含了至少一个主仓库 AOSC main repository

1
2
3
4
5
6
7
8
9
10
11
12
root@jerry-aosc-vmware [ ~ ] # oma topics
? 打开测试源以获取实验性更新,关闭测试源以回滚到稳定版本:
cmake: update to 4.0.3 (cmake-4.0.3)
······
rocm: add new subpackage (rocm-641-add-package)
······
[PREVIEW] Python 3.14 (python-3.14)
······
f3d: new, 3.0.0 (f3d-new)
AVR Survey (May, 2025) (avr-survey-20250512)
▼ photils-cli: new, 0.4.1 (photils-new)
按 [Space]/[Enter] 切换开关状态,按 [Esc] 应用更改,按 [Ctrl-c] 退出。

而作为开发者如何进行主题制维护,我们将在后续章节中详细介绍。

寻找更新

除了 GitHub 外,你还可以在 https://packages.aosc.io/ 查看目前 AOSC OS 的所有软件包。首页显示了最近被推送到 stable 分支的包更新,点击某个包名可以查看该包的详细信息。在右上角可进行软件包搜索,在下方 Repositories 列表可以按架构查看包的列表。
当然,这肯定是个工具站,仅适用于你明确了想更新哪个软件包的情况下搜索使用。
那么,如果你只是想随便看看,当当扫地机器人,有没有哪个站提供了上游更新的信息呢?
有的有的,请转到 https://anicca.aosc.io/ ,这里会给出由 aosc-findupdate 工具自动生成的 AOSC OS 包更新列表。你可以在这里查看到所有包的最新版本信息,来找找有没有你感兴趣的更新。
注意看 Warnings 里的 Compliance mode enabled,这代表了版本号可能会被合规处理过。根据样式指南,有些来自上游的版本号可能需要进行修改以符合规范,具体的规则我们之后介绍。

善其事,利其器

现在可以把手里的 AOSC OS 终端开起来了,我们将在本节中介绍软件包维护中通常会接触到的工具。
根据 软件包维护入门:基础教程 的介绍,我们可以获知:在软件包维护的过程中总共需要和下面三个工具打交道:

  • Ciel
    • 用于管理独立的 AOSC OS 构建环境(systemd-nspawn(1) 容器)。
  • ACBS
  • Autobuild
    • 用于读取软件包构建配置并执行构建脚本。

通常而言,从打包者的角度来说你只需要接触第一个 Ciel 工具,因为后续的 AutobuildACBS 都会在 Ciel 的调度下在容器中运行。

在你开始软件包维护之前,请务必确保你已经通过各种妙妙的方式,保证你的 AOSC OS 到国际的互联不会产生什么太大的问题。从 AOSC OS 的基础 tarball 镜像、到基于 GitHub 的 abbs 仓库,甚至于软件包构建过程中访问外部代码包,都需要顺畅的国际互联支持,本方面点到为止。

在你配置好自己的网络环境或是确保自己的互联不会出现问题后,请通过 sudo -i 等方式进入 root 用户,然后通过 oma 安装 ciel

1
oma install ciel

然后找一个地方创建一个专门的目录作为 ciel 的工作目录,比如 ~/ciel ,然后在该目录下运行 ciel new 以创建一个新的构建环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@jerry-aosc-vmware [ ~ ] # mkdir ~/ciel/
root@jerry-aosc-vmware [ ~ ] # cd ciel/
root@jerry-aosc-vmware [ ciel ] # ciel new
info: Welcome to ciel!
info: Before continuing, I need to ask you a few questions:
✔ Target Architecture · mainline: amd64
✔ Maintainer Information · abc1763613206 <wowjerry@aosc.io>
✔ Enable DNSSEC · no
✔ Edit sources.list · no
✔ Enable local sources caching · yes
✔ Enable local packages repository · yes
✔ Use different OUTPUT dir for different branches · yes
✔ Use volatile mode for filesystem operations · no
info: Ciel now uses oma as the default package manager for base system updating tasks.
info: You can choose whether to use oma instead of apt while configuring.
✔ Use apt as package manager · no
✔ Do you want to add a new instance now? · yes
✔ Name of the instance · main
info: Understood. `main` will be created after initialization is finished.
info: Initializing workspace...
info: Initializing container OS...

Target Architecture 请根据自己的实际情况选择合适的架构,比如 amd64arm64
然后是该环境的维护者信息,照前面的格式填写即可。实际上现在 AOSC OS 采用 BuildIt! 全自动构建,分发到软件源的包并不会在你的环境上被构建,所以此处填其他的问题也不算太大。
其他选项保持默认即可,但请注意在 Do you want to add a new instance now? 这个问题上选择 yes,并为实例命名,比如 main

如果你很不幸网络条件不佳,可能会在如下的地方卡住或是速度极慢:

1
2
3
info: Searching for latest AOSC OS buildkit release...
info: Ciel has picked buildkit for amd64, released on 20250606
info: Downloading base OS rootfs...

ciel 允许你使用 --from-tarball 的选项来让你从一个第三方源加载 AOSC OS 的根文件系统镜像。
如果你卡得受不了,就可以考虑利用国内开源镜像站的镜像来加速下载了(尽管如此,我还是建议你在进行如下的步骤之前配置好相关的网络工具)
观察如上的 info ,然后来拼出一个 tarball 地址:

1
2
3
4
5
# 比方说这里是 amd64 的 20250606 ,就可以直接使用下面的链接
# 如果修改架构的话,注意需要修改两处地方,注意最终的格式须为 squashfs
https://mirrors.cernet.edu.cn/anthon/aosc-os/os-amd64/buildkit/aosc-os_buildkit_20250606_amd64.squashfs
# 如果 MirrorZ 给你分配的镜像站表现过差,也可以考虑直接指定一个
# https://mirrors.bfsu.edu.cn/anthon/aosc-os/os-amd64/buildkit/aosc-os_buildkit_20250606_amd64.squashfs

然后,将下得极慢的进程给 Ctrl-C 终止掉,删掉整个文件夹里的内容(ciel 在初始化不完整时会报错,恢复空白环境可以规避掉一些问题)。
然后重新运行 ciel new ,这次加上 --from-tarball 选项,并将上面的 tarball 地址粘贴进去,此时会跳过让你选择架构的过程,直接下载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@jerry-aosc-vmware [ ciel ] # rm -rf .ciel * 
root@jerry-aosc-vmware [ ciel ] # ciel new --from-tarball https://mirrors.cernet.edu.cn/anthon/aosc-os/os-amd64/buildkit/aosc-os_buildkit_20250606_amd64.squashfs
info: Welcome to ciel!
info: Before continuing, I need to ask you a few questions:
✔ Maintainer Information · abc1763613206 <wowjerry@aosc.io>
······
✔ Do you want to add a new instance now? · yes
✔ Name of the instance · main
info: Understood. `main` will be created after initialization is finished.
info: Initializing workspace...
info: Initializing container OS...
info: Using custom squashfs from https://mirrors.cernet.edu.cn/anthon/aosc-os/os-amd64/buildkit/aosc-os_buildkit_20250606_amd64.squashfs
info: Downloading base OS rootfs...
info: Initializing ABBS tree...
info: Applying configurations...
info: Configurations applied.
info: Setting up local repository ...
info: Scanning 0 packages...

info: Local repository ready.
info: main: instance initialized.
info: main: filesystem mounted.
info: Scanning 0 packages...

info: main: local repository initialized.

在工作区配置完成后,请首先运行 ciel update-os 来尽可能地更新容器内的系统环境,否则以后在每次构建时都要更新一遍,浪费时间。

1
2
3
4
5
6
7
root@jerry-aosc-vmware [ ciel ] # ciel update-os
info: Updating base OS...
info: update-ce9206ea: instance created.
info: update-ce9206ea: filesystem mounted.
info: update-ce9206ea-7ec908fe: waiting for container to start...
info: update-ce9206ea-7ec908fe: setting up mounts...
INFO Refreshing local database ...

接下来,你就可以使用 ciel build -i main 来构建软件包了,可以像官方 Wiki 那样,打一个 flac 包试一试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
root@jerry-aosc-vmware [ ciel ] # ciel build -i main flac
······
[INFO]: Archiving package(s) ...
[INFO]: Using abpm_aosc_archive as autobuild archiver ...
'flac_1.5.0-0_amd64.deb' -> '/debs/f/flac_1.5.0-0_amd64.deb'
'flac-dbg_1.5.0-0_amd64.deb' -> '/debs/f/flac-dbg_1.5.0-0_amd64.deb'
[INFO]: Asking ciel to refresh repository...
[INFO]: Waiting for ciel to refresh repository...
info: Scanning 2 packages...
..
[INFO]: Ciel finished refreshing repository...

========================================
ACBS Build Successful
========================================

Package(s) built:
flac (amd64 @ 1.5.0-0) 0:00:34.624463

info: main: stopping...
info: main: instance stopped.
info: main: filesystem un-mounted.
info: main: mount point removed.
info: main: rolling back instance...
info: main: instance has been rolled back.
BUILD SUCCESSFUL - 1 packages in 00:00:51

通常而言,看到了 ACBS Build Successful ,就说明构建过程没有问题,可以找到生成的包了。
因为我们没有切换分支,所以我们此时构建的包在 OUTPUT-stable 目录下,具体到 flac 包就是 OUTPUT-stable/debs/f/flac_1.5.0-0_amd64.deb
你可以使用 oma install 命令来亲手试用这个包:

1
oma install OUTPUT-stable/debs/f/flac_1.5.0-0_amd64.deb

小试牛刀

第一个主题

在上一章中,我们已经搭建好了名为 ciel 的工作间,完成了一些说大不大说小不小的准备工作,现在是时候把它投入使用了。
请注意,本节的流程是为首次贡献的朋友们设计的。当你成功提交代码并成为社区贡献者后,部分操作会变得更加简化,我们到时再谈。

使用 ls 命令查看当前目录,通常你现在看到的会类似这样:

1
2
root@jerry-aosc-vmware [ ciel ] # ls
aosc-os_buildkit_20250606_amd64.squashfs CACHE OUTPUT-stable SRCS TREE

注意看那个 TREE 目录,它就是之前我们提到的 aosc-os-abbs,也就是存放构建配置的主仓库。
作为 Newcomer 我们自然还没有向这个仓库推送的权限,因此先去 https://github.com/AOSC-Dev/aosc-os-abbs/fork ,创建一个自己的 Fork ,比如说我的创建后就是 https://github.com/abc1763613206/aosc-os-abbs

然后 cdTREE 目录下,把 origin 暂时指向到自己的 Fork (当然你如果精通 Git 操作的话,形式上创建一个 upstream 是一个更好的实践):

1
2
3
root@jerry-aosc-vmware [ ciel ] # cd TREE
root@jerry-aosc-vmware [ TREE@stable ] # git remote set-url origin https://github.com/abc1763613206/aosc-os-abbs.git
root@jerry-aosc-vmware [ TREE@stable ] # git pull # 更新本地代码

然后就可以挑选包了!我们以写稿时挂在 Anicca 首页的 7-zip 为例:

7-zip
7-zip

可以看到,7-zip 的目录是 app-utils ,当前仓库里的版本是 25.00 ,但是最新版来到了 25.01
确定了目标,我们就可以在「主题制」维护机制下,亲手创建属于自己的第一个主题了。
正如上所说,主题是更新、重建或修改一个或多个软件包的独立流程。参考 AOSC OS 主题制维护指南 ,我们可以总结出如下的主题(对应到 Git 中也就是分支)命名规则:

  • 更新$PKGNAME-$PKGVER(如 nano-5.4)。
  • 非更新PURPOSE 说明意图):$PKGNAME-$PKGVER-$PURPOSE(如 gnome-shell-3.38.1-build-fix)。

还有个复杂的例外:如果一次主题涉及多个软件包、多个版本,并且这些软件包之间没有明确的主从关系或统一版本号时,主题名将使用主包名(或统称)+ -survey + 日期,例如:rime-data-survey-20200928
你可以回到之前那一段,看看 oma topics 的输出,来验证分别属于哪种类型。

对应到我们这个例子,我们要创建的主题名就是 7-zip-25.01
进入到 TREE 目录,使用 git checkout -b 7-zip-25.01 创建一个新的分支,然后开工!

1
2
3
4
root@jerry-aosc-vmware [ ciel ] # cd TREE
root@jerry-aosc-vmware [ TREE@stable ] # git checkout -b 7-zip-25.01
切换到一个新分支 '7-zip-25.01'
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] #

检包、拆包

进入到 TREE ,这个包处在 app-utils/7-zip 目录下,用 tree 命令看一眼这个文件夹的架构:

1
2
3
4
5
6
7
8
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] # tree app-utils/7-zip/
app-utils/7-zip/
├── autobuild
│ ├── build
│ ├── defines
│ └── patches
│ └── 0001-fix-CPP-missing-predefined-compiler-flags.patch
└── spec

通常而言,这个包就代表了大部分最简软件包的架构(当然了,有些顺风顺水的软件包连补丁 patches 文件夹都没有)。
对于软件包的全部细节,请直接参照 AOSC OS 软件包样式指南 ,事实上在打包的全流程中,你应该把这个指南作为参考,在遇到问题时查阅,未覆盖的地方再求助于社区。

我们以实践出真知的精神,来具体看看包里都有啥。

spec

对于 7-zip 而言,spec 文件的内容长这样:

1
2
3
4
VER=25.00
SRCS="git::commit=tags/$VER::https://github.com/ip7z/7zip"
CHKSUMS="SKIP"
CHKUPDATE="anitya::id=17875"

虽然略显简陋,但是构成软件包的必要信息都在这里了。
第一行的 VER 变量定义了软件包的版本号,然后 SRCS 变量定义了软件包的源代码上游,CHKSUMS 变量定义了软件包的校验值,CHKUPDATE 变量定义了软件包的更新来源。
CHKUPDATE 变量是用于给 Anicca 这类工具提供更新信息的,仅在新增软件包时会用到,通常情况下你不需要修改它。我们重点说一下其他三个。

首先是 VER 变量,在 AOSC OS 的软件包中 VER 直接指向软件包的版本号,这就带来了几个问题:

  1. 之前说过的 Compliance mode enabled 怎么回事?
    请参考 AOSC OS 软件包样式指南 里的「软件包版本」一节。通常而言,当上游的版本号只带有半角句号时,可以直接被使用;如果上游的版本号带有其他符号(如 +_ 等),则需要进行规范化处理。具体参见样式指南里的表格。
  2. 如果一个软件包里复合了多个上游软件包,或者说被规范化后的版本号无法直接被下面的 SRCS 变量所使用,怎么办?
    SRCS 不一定非要引用 VER 变量,实际上你可以按需要在 spec 文件中定义任意多个变量来满足你的需求。比如对 lang-golang/go 软件包而言,它复合了多个上游软件包,版本号也比较复杂,因此它的 spec 文件变成了这样:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    UPSTREAM_VER=1.24.2
    # Versions of Golang, net library and Go tools
    GO_VER=${UPSTREAM_VER/\~/}
    TOOLS_VER=0.31.0
    NET_VER=0.38.0
    REL=3

    VER="${UPSTREAM_VER}+tools${TOOLS_VER}+net${NET_VER}"
    SRCS="tbl::https://go.dev/dl/go${GO_VER}.src.tar.gz \
    git::commit=tags/v${TOOLS_VER};rename=tools::https://go.googlesource.com/tools \
    git::commit=tags/v${NET_VER};rename=net::https://github.com/golang/net"
    CHKSUMS="sha256::9dc77ffadc16d837a1bf32d99c624cb4df0647cee7b119edd9e7b1bcc05f2e00 \
    SKIP \
    SKIP"
    CHKUPDATE="anitya::id=1227"
    SUBDIR="go"
    它目前的软件包版本为 1.24.2+tools0.31.0+net0.38.0 ,使用 + 符号复合了不同的来源,在 SRCS 里的不同来源也引用了不同变量。

SRCS 可在 ACBS - Specification Files 文档中查看详情,我们和下面的 CHKSUMS 一起看。
源码的来源一般分为两种情况:

  • 来源于基于 Git 的代码仓库,使用 git::commit=tags/xxx::https://github.com/xxx/xxx 这种形式,这种情况下 CHKSUMS 变量请使用 SKIP
  • 来源于基于 tarball 的代码包,使用 tbl::https://xxx/xxx.tar.gz 这种形式,这种情况下 CHKSUMS 变量需要提供一个校验值,比如说 SHA256。

如果是复合引用的软件包,你通常需要对其他来源进行重命名,这时请在 SRCS 里使用 rename 选项。
此时,你通常可能需要显式指定一个子目录作为构建的主目录,使得 build 构建工作流能够进入正确的文件夹发起构建,此时请在 spec 文件中使用 SUBDIR 变量来指定目录
在如上的 lang-golang 包中,因为有多个上游复合,所以显式指定了 SUBDIR="go" 。这里的指定需要根据不同包的情况灵活变通,通常需要自己打开相关 tarball 查看具体的结构,例如在 nginx 中,这里的值就变成了 SUBDIR="nginx-$NGINX_VER"如果你的源码包只有单个/零个文件夹且没有复合来源的情况,你通常不需要考虑这个值。

除此之外,还有一个如上 spec 文件中没有体现,但仍需要重点说明的变量:REL

REL 变量定义了软件包的修订号,该变量用于处理上游软件包未发生改变,但是在 AOSC OS 生态中需要进行修订的情况(通常是之前适配出现了 BUG 或者应急响应其他补丁)。此变量的默认值为 0,在主版本 (VER) 不变的情况下,每次修订应为该值递增 1。当软件包的主版本(VER)发生变化时,REL 变量应重置为 0,体现在实践中时,你应当直接把含有 REL 变量的行删除。

比如这是一个 ninja 的更新:

1
2
3
4
5
6
- VER=1.12.1
+ VER=1.13.1
SRCS="git::commit=tags/v$VER::https://github.com/ninja-build/ninja"
CHKSUMS="SKIP"
CHKUPDATE="anitya::id=2089"
- REL=1

回到 7-zip 包的 spec 文件,很幸运我们并不需要处理如上大部分复杂的操作,也不存在需要我们删除的 REL 行,所以直接修改一下版本号即可。

1
2
3
4
5
- VER=25.00
+ VER=25.01
SRCS="git::commit=tags/$VER::https://github.com/ip7z/7zip"
CHKSUMS="SKIP"
CHKUPDATE="anitya::id=17875"

autobuild

我们已经仔细研究了软件包的「身份证」 spec,现在,让我们来参观一下它的「引擎室」—— autobuild 目录。这个目录里的文件,共同决定了软件包是如何从一堆源代码,被 Autobuild 一步步加工成可安装文件的。
不过,在开始导览前,请先松一口气:对于大多数常规的版本更新,这个目录里的文件你可能一个字都不用改。 我们即将采用的策略是「先信任,后验证」——首先假设现有的构建流程在新版本上依然有效,只有在后续构建失败时,我们才需要回到这里来排查问题。
首先是 defines 文件,该文件定义软件包的各项核心配置。

1
2
3
4
PKGNAME=7-zip
PKGSEC=utils
PKGDEP="gcc-runtime glibc"
PKGDES="A file archive manager with support for multiple formats"

该文件详细的定义请参考 Wiki 上的入门教程 文档。
通常对于软件包维护更新而言,我们需要关注的是软件包的依赖关系在更新后有没有发生变化,分为构建依赖 BUILDDEP 和运行时依赖 PKGDEP,其中前者是仅在构建过程中需要的。你可以在样式指南查看更多细节,但对于软件包更新而言,一个比较符合直觉的工作流是:通过之后构建时的表现以及最后运行时的测试来验证这些依赖关系是否仍然有效,是否需要添加新的依赖。

patches 目录下存放了软件包的补丁文件,通常用于修复上游代码中的问题或适配 AOSC OS 的特定需求。对于 7-zip 包而言,我们可以看到一个名为 0001-fix-CPP-missing-predefined-compiler-flags.patch 的补丁文件,这个补丁是为了修复编译器预定义标志缺失的问题。
patches 目录下的补丁文件请带序号依次保存,具体制作补丁的方式请参考 AOSC OS 软件包样式指南 。通常而言,建议补丁文件的命名应符合下面的格式:

1
NNNN-$CATEGORY-$CONTENT.patch

其中:

  • NNNN 与前面的示例补丁名称一样,是用于为补丁排序的“序列号”。
  • $CATEGORY 定义了补丁的类别,例如 bugfixfeature 等。
  • $CONTENT 定义了补丁的作用,例如 fix-build-with-openssl-1.1

当然,在软件包更新中,我们经常会遇到因为软件包代码段更新而导致补丁失效的情况。这时,我们需要根据实际情况对补丁进行调整,确保其能够正确应用。
具体而言,你可以拉取下对应的 Git 仓库,参考现有的 patch 文件人工完成相应的修改,然后使用类似 git diff > xxx.patch 的命令生成新的补丁文件。对于有补丁的软件包而言,这是更新过程中经常会遇到的情况。

build 文件定义了软件包构建的具体细节,它被 Autobuild 读取并执行,你可以在Wiki 上的进阶教程中获取一些细节。

1
2
3
4
5
6
7
abinfo "Building 7-zip ..."
cd "${SRCDIR}/CPP/7zip/Bundles/Alone2"
make -f ../../cmpl_gcc.mak

abinfo "Installing 7-zip ..."
install -v -Dm755 "${SRCDIR}/CPP/7zip/Bundles/Alone2/b/g/7zz" "${PKGDIR}/usr/bin/7zz"
install -v -Dm644 "${SRCDIR}/DOC/"* -t "${PKGDIR}/usr/share/doc/${PKGNAME}"

此外,还可能会出现构建前会运行的 prepare 文件,用于初始化一些构建环境;构建后会运行的 beyond 文件,用于打扫一下构建现场。还可能会出现一个 overrides 文件夹,该文件夹存放了一些源代码中不存在,但是对最终软件包有用的文件,通常是一些安装到桌面的文件和预设配置,你可以在 Wiki 上的进阶教程中获取一些细节。

但通常如上文所说,对于大多数软件包的常规更新,autobuild 目录中的配置都相对稳定。因此在实际操作中,我们不必过早陷入 autobuild 目录的全部细节。对于绝大多数增量更新,首要的策略是仅修改 spec 文件中的版本号(VER)与校验和(CHKSUMS),然后大胆尝试构建。除非遇到涉及底层重构的重大版本更迭,否则构建脚本通常能平稳运行。只有当构建失败或是后续测试出现问题时,才有必要回过头来,依据错误信息深入排查 autobuild 目录中的具体配置。

构建一下试试?

我们可以在 ciel 文件夹下的任意目录,使用 ciel build -i main 7-zip 来尝试构建一下我们更新的 7-zip 包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] # ciel build -i main 7-zip
······
[INFO]: Using free-formed build script
[INFO]: Applying patch 0001-fix-CPP-missing-predefined-compiler-flags.patch ...
patching file CPP/7zip/7zip_gcc.mak
······
========================================
ACBS Build Successful
========================================

Package(s) built:
7-zip (amd64 @ 25.01-0) 0:00:37.503451

info: main: stopping...
info: main: instance stopped.
info: main: filesystem un-mounted.
info: main: mount point removed.
info: main: rolling back instance...
info: main: instance has been rolled back.
BUILD SUCCESSFUL - 1 packages in 00:00:53

可以看到,这里的构建过程顺利完成,没有遇到任何问题。
而如果你看到的不是 Build Successful 的信息,那就要专门看一眼日志了。

比如在更新软件包时最常出现的补丁失效情况,本着实验的精神,我们来故意破坏一下 7-zip 目录下的那个补丁,然后重新运行构建:
构建自然会失败,然后你往上翻一翻日志会看见这一段:

1
2
3
4
5
6
7
8
9
10
11
[INFO]:  Applying patch 0001-fix-CPP-missing-predefined-compiler-flags.patch ...
patching file CPP/7zip/7zip_gcc.mak
Hunk #1 FAILED at 44.
1 out of 4 hunks FAILED -- saving rejects to file CPP/7zip/7zip_gcc.mak.rej
In file included from /usr/bin/autobuild:13
from /usr/lib/autobuild4/proc/40-patch.sh:23
/usr/lib/autobuild4/lib/builtin.sh:17: In function `ab_apply_patches':
/usr/lib/autobuild4/lib/builtin.sh:17: error: command exited with 1
16 | abinfo "Applying patch $(basename "$i") ..."
> 17 | patch "${PATCHFLAGS[@]}" -i "$i" || abdie "Applying patch $i failed"
18 | fi

这段日志就具体地告诉了我们哪个补丁应用失败,这时我们就要结合具体情况,考虑人工修改补丁或是重做补丁。
当然这里是我们人工破坏的,玩够了还原回去就好。

重新构建完成后回到 ciel 的根工作目录,我们会发现现在变成了这样:

1
2
root@jerry-aosc-vmware [ ciel ] # ls
aosc-os_buildkit_20250606_amd64.squashfs CACHE OUTPUT-7-zip-25.01 OUTPUT-stable SRCS STATES TREE

可以看到,输出目录多出来了个以主题名命名的 OUTPUT-7-zip-25.01 目录,这个目录下存放了我们刚刚构建的 7-zip 包:

1
2
3
4
5
6
7
8
9
10
11
root@jerry-aosc-vmware [ ciel ] # tree OUTPUT-7-zip-25.01/
OUTPUT-7-zip-25.01/
└── debs
├── 7
│ ├── 7-zip_25.01-0~pre20250807T182427Z~dirty_amd64.deb
│ ├── 7-zip-dbg_25.01-0~pre20250807T182427Z~dirty_amd64.deb
├── fresh.lock
├── Packages
└── Release

3 directories, 7 files

具体到这个软件包,我们可以使用 oma install 来安装它:

1
oma install OUTPUT-7-zip-25.01/debs/7/7-zip_25.01-0~pre20250807T182427Z~dirty_amd64.deb

接着,我们就可以对软件包进行基础的功能测试了,具体到 7-zip 这个包,我们可以直接使用它自带的 7zz b 来首先跑一个 Benchmark:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
root@jerry-aosc-vmware [ ciel ] # 7zz b

7-Zip (z) 25.01 (x64) : Copyright (c) 1999-2025 Igor Pavlov : 2025-08-03
64-bit locale=zh_CN.UTF-8 Threads:128 OPEN_MAX:1024

Compiler: ver:14.3.0 20250523 (AOSC OS, Core) GCC 14.3.0 : SSE2
Linux : 6.14.11-aosc-main : #1 SMP PREEMPT_DYNAMIC Tue Jul 22 02:28:29 UTC 2025 : x86_64 : VMwareVMware : : 0.0.0.0.0.0
PageSize:4KB THP:always hwcap:2 hwcap2:2
12th Gen Intel(R) Core(TM) i7-12700H
(906A3)

1T CPU Freq (MHz): 3992 4019 3887 3878 3861 3891 3874
2T CPU Freq (MHz): 200% 3869 199% 3885
4T CPU Freq (MHz): 362% 3497 357% 3502

RAM size: 3690 MB, # CPU hardware threads: 4 / 128 : 0000000000000000000000000000000F
RAM usage: 889 MB, # Benchmark threads: 4

Compressing | Decompressing
Dict Speed Usage R/U Rating | Speed Usage R/U Rating
KiB/s % MIPS MIPS | KiB/s % MIPS MIPS

22: 28211 356 7708 27445 | 187602 370 4321 16005
23: 20539 320 6546 20928 | 182650 374 4231 15804
24: 16914 296 6141 18187 | 165834 364 4002 14553
25: 15152 307 5629 17300 | 160144 351 4061 14253
---------------------------------- | ------------------------------
Avr: 20204 320 6506 20965 | 174058 365 4154 15154
Tot: 342 5330 18059

测试压缩操作,也没有问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@jerry-aosc-vmware [ ciel ] # 7zz a 7zip.7z OUTPUT-7-zip-25.01/

7-Zip (z) 25.01 (x64) : Copyright (c) 1999-2025 Igor Pavlov : 2025-08-03
64-bit locale=zh_CN.UTF-8 Threads:128 OPEN_MAX:1024

Scanning the drive:
3 folders, 8 files, 21114503 bytes (21 MiB)

Creating archive: 7zip.7z

Add new data to archive: 3 folders, 8 files, 21114503 bytes (21 MiB)


Files read from disk: 8
Archive size: 11040172 bytes (11 MiB)
Everything is Ok

版本也确实是更新后的 25.01 ,本地的测试没有问题,就可以准备发起 PR 了。

发起贡献

在发起构建之前,首先需要了解一下 AOSC OS 中的 Commit 规范:Commit 面向最终用户,通常情况下对于同一个包的所有更改应该在同一条 Commit 中完成
你可以在 软件包样式指南 中找到所有的规范,Commit 的消息通常遵从 <包名>: <动词短语> [附加说明] [; #<issue号>] 的格式,最常用的如下:

  • 引入新包$PKGNAME: new, $PKGVER,比如 cherry-studio: new, 1.5.2
  • 版本更新
    • 普通更新:$PKGNAME: update to $PKGVER,比如 7-zip: update to 25.01
    • 安全更新:$PKGNAME: update to $PKGVER; #NNN,比如 7-zip: update to 25.00; #11761,其中 #NNN 是对应安全通告的 issue 编号。
  • 软件包改动$PKGNAME: $PURPOSE,通常这种情况下之前说过的 REL 也要递增。

如果你的 Commit 干了不止跳版本的一件事,你可以在 Commit 中换行,分条详细说明,参见软件包样式指南

具体到我们这个例子,我们直接添加所有改动,使用 7-zip: update to 25.01 作为 Commit,然后推送即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] # git add .
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] # git status
位于分支 7-zip-25.01
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: app-utils/7-zip/spec
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] # git commit -m "7-zip: update to 25.01"
[7-zip-25.01 aaa13645db] 7-zip: update to 25.01
1 file changed, 1 insertion(+), 1 deletion(-)
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] # git push
致命错误:当前分支 7-zip-25.01 没有对应的上游分支。
为推送当前分支并建立与远程上游的跟踪,使用

git push --set-upstream origin 7-zip-25.01

为了让没有追踪上游的分支自动配置,参见 'git help config' 中的 push.autoSetupRemote。
root@jerry-aosc-vmware [ TREE@7-zip-25.01 ] ! git push --set-upstream origin 7-zip-25.01
枚举对象中: 9, 完成.
对象计数中: 100% (9/9), 完成.
使用 4 个线程进行压缩
压缩对象中: 100% (5/5), 完成.
写入对象中: 100% (5/5), 452 字节 | 452.00 KiB/s, 完成.
总共 5(差异 3),复用 0(差异 0),包复用 0(来自 0 个包)
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
remote:
remote: Create a pull request for '7-zip-25.01' on GitHub by visiting:
remote: https://github.com/abc1763613206/aosc-os-abbs/pull/new/7-zip-25.01
remote:
To https://github.com/abc1763613206/aosc-os-abbs.git
* [new branch] 7-zip-25.01 -> 7-zip-25.01
分支 '7-zip-25.01' 设置为跟踪 'origin/7-zip-25.01'

之后,你就可以回到 GitHub ,参照模板创建一个 Pull Request 了。
在本例之中,模板填写完了长这样:

从这一步之后,你就可以来到 AOSC OS 现有的社区群组 ,发送自己的 Pull Request 链接,来等待贡献者们进行 Review 。
很快,审阅者会为你触发一系列 CI,以验证你的软件包在所有支持的设备架构上都能成功构建。有时,他们可能也会请你在本地环境中进行一些额外的测试(譬如执行类似 oma topics --opt-in 的命令来测试你的包在测试源上的构建表现)。请将你的测试结果以评论的形式回复在 PR 中,并与审阅者保持积极沟通,直到所有的检查项都顺利通过,让下面的 checks 绿起来:

All checks have passed
All checks have passed

从这一刻起,你将从「闭门造车」转向与社区的协同合作。请记住,这并非一场考试,而是一次开放、平等的技术交流。你需要与审阅者积极互动,清晰地解释你的修改思路,回答他们的问题,并根据收到的反馈进行调整。有效的沟通是保证贡献能被顺利合入的关键。

最终,在与审阅者达成共识后,你的 PR 将被合并。你亲手更新的 7-zip 软件包,将很快通过软件源分发到成千上万的用户手中。

在这一刻,你不仅完成了一次版本更新,更成为了 AOSC OS 开源社区的一名贡献者。恭喜你,欢迎加入!

Final Checklist

打包的旅程并非一帆风顺,以下是你在打包过程中可能会遇到的一些情况,在打包提交之前不妨先来看看:

和一条 Commit 打架

前文已经提到,AOSC OS 的 Commit 规范要求每个软件包的更新都应在一条 Commit 中完成。这就自然而然带来两个问题:

  1. 我如果已经提交了多个 Commit,如何合并成一条
  • 一个比较文明的方式是使用 git rebase -i 命令,进入交互式变基模式,然后把所有 Commit 都改成 squash(缩写为 s),然后保存并退出,会弹出另一个编辑器让你修改合并后的 commit message。
    不过这种方式不太适合你本地还有未提交的更改的情况,就通常的 AOSC OS 仓库维护实践而言,我推荐你使用一个不太文明但是简便的方法:
  • 直接使用 git reset --soft HEAD~N 命令(其中 N 是你想要回退的 Commit 数量),然后使用 git commit -a -m "Commit message" 来重新提交所有更改。这样就可以把多个 Commit 合并成一条了。--soft 的选项代表回退到指定的 Commit,但保留所有更改在暂存区中。

不管你执行了哪种操作,都别忘了使用 git push -f 来强制推送你的更改。

  1. 审阅者指出了我的错误,我该如何修改上一条提交过的 Commit
  • 如果您仅需要修改 Commit 的消息内容,可以直接使用 git commit --amend -m "New commit message" 命令来修改最后一次提交的消息。如果您去掉 -m 选项,Git 会打开一个编辑器,让您修改消息内容。
  • 但您如果想修改文件内容,请直接在工作区进行修改,然后直接使用 git add . 来将修改添加到暂存区,最后使用 git commit --amend 来更新这个 Commit。 同样这次会打开一个编辑器,让您修改 Commit 的消息,如果不需要修改消息,可以直接保存并退出,此时修改就会合并到这个 Commit 中。(附加上 --no-edit 选项可以跳过编辑器)
  • 需要修改更早之前的 Commit 涉及到了 rebase 变基,请自行在网络上查找相关资料。

同样的,完成全部修改后使用 git push -f 来强制推送更改。

强制推送会覆盖远程历史,是一项有风险的操作。 如果你在一个多人协作的分支中工作,请务必确保你在推送之前已经与团队成员进行了充分的沟通,并且了解可能带来的影响。

安全更新与 TUM

你可能会注意到,在发起 PR 时的模板中有一个 Security Update? 的小标题,这是用来标识你的更新是否涉及到安全性修复的。
这就意味着,如果你发现你更新的软件包碰巧修复了某个安全漏洞,就应该多做一些工作。

你可以从以下几个途径尝试了解:

  • #oss-security 的邮件列表,你可以在谷歌上通过 site:openwall.com/lists/oss-security/ 后面带关键词来搜索安全通告。
  • 官方 CVE 数据库 上搜索软件包的名称,查看是否有相关的安全漏洞。
  • 观察 Release Notes 或者 Changelog 中是否有提及安全修复。

一旦发现安全漏洞,且你确定你正在更新的软件包会修复该漏洞,你就要在更新软件包之外,额外做安全通报工作。正巧 7-zip25.00 版本出现了这个情况,下面将以这个更新作举例说明:

  1. aosc-os-abbs 中创建一个 Issue,模板选择 Security Vulnerabilities Report,按照指示填写相关信息并提交。(在本例中我创建了 Issue #11761
  2. 回到你更新的软件包的 PR 页面,在 Security Update? 的小标题下方填写 Yes,并附上你刚刚创建的安全通报 Issue 的编号并标注 fixes 以便 PR 合并时自动关闭。(参见 PR #11760
  3. 准备发布一个 TUM(Topic Update Manifest)。这意味着当用户更新到你的软件包时,oma 会提示该软件包修复了什么漏洞。
    TUM 的位置位于 TREE/topics 目录下,你应该创建一个名为 $PKGNAME-$PKGVER.toml 的文件,本例中我们创建了 7-zip-25.00.toml,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
security = true

[name]
default = "7-Zip 25.00"
zh_CN = "7-Zip 25.00"

[caution]
default = "Fixes a heap buffer overflow vulnerability - CVE-2025-53816 (Severity: Medium); Fixes a null pointer dereference vulnerability - CVE-2025-53817 (Severity: Medium)"
zh_CN = "修复一处堆缓冲区溢出漏洞,漏洞编号 CVE-2025-53816(严重性:中);修复一处空指针解引用漏洞,漏洞编号 CVE-2025-53817(严重性:中)"

[packages]
"7-zip" = "25.00"

在完成 TUM 的编写后,请将这个 TUM 单独作为一个 Commit 提交,格式为 topics: add <TUM 文件名>(本例中应为 topics: add 7-zip-25.00.toml,实际上应当加上后面的 .toml

在你如此操作之后,用户在通过 oma 完成 7-zip 的更新后,会看到类似下面的提示:

TUM 提示
TUM 提示

下一步?

再次由衷地恭喜你,你的贡献已正式成为 AOSC OS 的一部分!在你成为 AOSC OS 贡献者之后,你将获得一系列新的权限,旨在让你未来的贡献之旅更加顺畅、高效:

  • 主仓库的写入权限:你将可以直接向官方 aosc-os-abbs 仓库推送你的开发分支。
  • BuildIt! 的调用权限:你将可以使用 AOSC OS 强大的自动化构建与测试系统。你将获得 AOSC OS 构建服务器的访问权限、主仓库的写入权限、构建 CI BuildIt! 的调用权限。

在你开始新的冒险之前,有一个重要的一次性设置需要完成。在确保你加入 AOSC-Dev 组织后,请将你本地 TREE 目录的 Git 远程地址,从你个人的 Fork 仓库修改回 AOSC OS 的主仓库

1
git remote set-url origin https://github.com/AOSC-Dev/aosc-os-abbs.git

从此,你创建的所有新分支都应直接推送到主仓库,而不再需要通过个人 Fork 中转。
以及,以后的发起 PR 与构建操作请通过 BuildIt! 完成,BuildIt! 的主操作接口是 TG 上的 @aosc_buildit_bot。请在完成授权后,发送 /help 查看简要帮助。
通常从贡献者的角度,你需要依次完成如下操作:

  1. 通过 BuildIt! 创建一个 PR:/openpr PR标题;分支名;涉及到的包 ,例如 /openpr 7-zip: update to 25.01;7-zip-25.01;7-zip如果涉及到的包有构建顺序要求,请保证按顺序排列并用空格隔开
  2. 在创建成功后,BuildIt! 会返回对应的 PR 链接。打开链接确认无误后,通过 BuildIt! 触发构建:/pr PR编号,例如 /pr 11760
  3. 监控构建状态,并根据需要进行调整或是重复发起构建。
  4. 在构建完成后进行测试。首先发送 /dickens PR编号 生成自动化报告,例如 /dickens 11760
  5. 如果你作为贡献者发起 PR,此时的构建包将会自动作为主题推送到测试源。请稍等片刻后在自己的系统中,使用 oma topics --opt-in 主题名(主题名也就是分支名)来加入自己构建的测试源,在尽量多的架构进行更新与测试,并附在 PR 之中。
  6. 在 PR 合并后,再次在 BuildIt! 中发送 /pr PR编号 触发构建,此时包将从 stable 发起构建,然后推送到正式的软件源。

掌握这套流程后,你的贡献效率将大大提升。欢迎来到贡献者的新世界,期待你为 AOSC 带来更多精彩!


本指南参考 AOSC OS 官方维基 编写,完稿于 2025 年 8 月 8 日,如果你发现本文描述的情况与维基或是社区实际情况不符,或者遇到了本指南没有覆盖到的情况,请以维基与社区为准,并积极与贡献者们沟通。编写代码、修复 Bug 只是开源贡献的起点,而如何与来自五湖四海的伙伴们有效沟通、协同共进,则是一门更深、也更有魅力的艺术。

*封面与如下 meme 图来自 《天使降临到我身边》 第 12 集的约 13:15 秒处。

REVIEW PLEASE!
REVIEW PLEASE!