持续维护最后验证:2026-10-03T00:00:00Z

私人 Arch Linux 软件仓库

这个项目把 packages/*/PKGBUILD 自动构建成 Arch Linux x86_64
软件包,并在私有 repo 分支维护标准 pacman 仓库数据库。

当前维护 13 个 package base。

Features

  • 使用真实 Arch Linux base-devel 容器运行 makepkg。
  • Pull Request 和 Push 自动执行 Bash 语法、.SRCINFO、ShellCheck 与 namcap 检查。
  • 只构建发生变化的包;依赖通过 .SRCINFO 的 pkgname / provides 图递归传播。
  • scripts/overlays/<package>.sh 变化只触发对应包;构建基础设施变化触发全量重建。
  • CI 使用可复用 Arch builder image,预装仓库配置、namcap 和 yay,减少重复 bootstrap。
  • Repository integration tests 在真实 Arch 容器中验证 repo-add、删除和 epoch 文件名处理。
  • 成功产物通过 repo-add 更新 repo 分支中的 pacman 仓库。

Packages

Package Arch 说明
ffmpeg-full x86_64 启用大量编解码器、CUDA 和 Whisper 支持的 FFmpeg
ggml-cuda-git x86_64, aarch64 CUDA 优化的 GGML
linuxqq-clipsync-git x86_64 Linux QQ Wayland 剪贴板同步
llama.cpp-cuda x86_64 CUDA 优化的 llama.cpp stable 构建
llama.cpp-cuda-git x86_64 CUDA 优化的 llama.cpp development 构建
scx-scheds-git x86_64 sched_ext 调度器集合
vapoursynth-plugin-mlrt-ncnn-runtime x86_64 VapourSynth MLRT NCNN runtime
mpeghdec x86_64 Fraunhofer MPEG-H 解码器
quirc i686, x86_64 QR 解码库
svt-jpeg-xs-git x86_64 JPEG XS 编解码器
whisper-cpp-cuda-git x86_64, aarch64 CUDA 优化的 Whisper
xclip-git x86_64 X11 剪贴板命令行工具

版本以各目录中的 PKGBUILD 和 .SRCINFO 为准。

Build and CI

check.yml 在 Arch 容器中运行 makepkg --printsrcinfo、ShellCheck 和
namcap,同时运行 build-graph 与 repository integration tests;build.yml
独立负责只构建变更包及其递归依赖,并优先使用 GHCR 中的可复用 builder image。
Artifact 保存。构建成功后发布为滚动 GitHub Release(固定 tag repo),
pacman 直接从 Release 资产下载仓库数据库和软件包。AUR 同步只提交源
文件,提交本身会触发一次构建,不会重复 dispatch 同一个构建。
个别软件包构建失败不会阻塞其他成功构建的软件包发布。

构建环境按以下优先级使用依赖:

  1. CachyOS 仓库(cachyos-v3、cachyos-extra-v3、cachyos-core-v3、
    cachyos,使用官方 mirrorlist,容器同时接受 x86_64_v3 架构)
  2. Arch Linux 官方仓库
  3. archlinuxcn
  4. coderkun-aur
  5. Chaotic-AUR
  6. 仍未满足的依赖由 yay 从 AUR 构建并安装

CachyOS 仓库排在 Arch 官方仓库之前,与目标系统的仓库优先级一致:构建
链接到的是本机 CachyOS 系统实际运行的库版本。若把 CachyOS 排在后面,
Arch 会在同名包冲突时胜出,当 CachyOS 先行替换了某个库(例如 openvino
的小版本更新带来的 soname 变化)时,构建出的包在本机就会出现共享库
找不到的问题。

构建容器保留 Arch 官方仓库的签名校验;未签名的第三方仓库仅在各自的
repository 段落中设置 SigLevel = Never。目标包本身仍由本项目保存的
PKGBUILD 重新构建,不会直接安装同名预编译包。

自动更新

Sync AUR package sources 工作流每天 03:17 UTC 检查一次所有带
.aur-url 的包目录。AUR 脚本发生变化时,它会更新对应的 PKGBUILD、
.SRCINFO、补丁和其他源文件,提交变化到 main,并触发对应软件包构建。

Maintenance 工作流每天 16:17 UTC 运行:清理过期 Artifact,并把已
发布软件包记录的 soname 依赖与当前各仓库比对,发现依赖过时就自动触发
对应软件包重建。

添加 AUR 软件包

在日常使用的目录克隆 main 源码分支:

git clone --single-branch --branch main \
  https://github.com/emoeem/pkgbuild.git \
  ~/pkgbuild-source
cd ~/pkgbuild-source

添加软件包只需要一条命令:

./scripts/add-aur-package.sh package-name

脚本会自动同步 main、下载并校验 AUR 构建文件、提交新包并推送。
推送后 GitHub Actions 会自动构建并更新 repo 分支。默认 AUR 地址是:

https://aur.archlinux.org/package-name.git

也可以传入其他 Git PKGBUILD 仓库:

./scripts/add-aur-package.sh package-name https://example.com/package.git

只想生成本地提交而暂时不推送时:

./scripts/add-aur-package.sh --no-push package-name

完整执行流程见 docs/add-aur-package.md。

自维护脚本只需放入 packages/package-name/,并确保其中同时存在
PKGBUILD 和最新的 .SRCINFO。没有 .aur-url 的目录不会被自动覆盖。

删除软件包

从源码和二进制仓库删除一个 package base:

./scripts/remove-package.sh package-name

脚本从 .SRCINFO 记录该 package base 产生的所有子包,删除源码目录并
推送。GitHub Actions 随后从 repo 分支删除相应软件包并重建 pacman
数据库。只创建本地提交时使用 --no-push。

仓库删除不会自动卸载电脑上已经安装的软件包。删除发布完成后,可以运行
emoeem-update 立即同步本地仓库。

fzf 管理界面

安装 fzf 和 GitHub CLI 后,可以通过一个菜单完成添加、删除、同步、
构建、本地仓库更新和安装:

sudo pacman -S fzf github-cli
./manage.sh

多选软件包时使用 Tab。完整说明见 docs/package-management.md。

构建依赖图、CI builder 和 repository integration tests 的设计见 docs/build-pipeline.md。

构建产物

每个包会生成独立的私有 Actions Artifact。Artifact 使用 tar 作为传输
容器,以便保留 Arch epoch 产生的冒号文件名;发布任务解包后,原始软件包
文件名和内容不会发生变化。所有成功产物随后被合并到 repo 分支的
x86_64/:

  • *.pkg.tar.zst
  • emoeem.db 与 emoeem.db.tar.zst
  • emoeem.files 与 emoeem.files.tar.zst
  • SHA256SUMS
  • emoeem.conf

更新数据库时会删除同一个包的旧版本。repo 分支每次使用 amend 和
force-with-lease 更新,从而避免 Git 历史长期保存所有旧二进制包。

作为 pacman 仓库使用

GitHub 私有仓库不能直接作为匿名 HTTP pacman Server。创建普通用户可写
的目录,再使用已有的 HTTPS 凭据克隆私有 repo 分支:

sudo install -d -o "$USER" -g "$(id -gn)" /var/lib/emoeem-repo
git clone --depth 1 --branch repo \
  https://github.com/emoeem/pkgbuild.git \
  /var/lib/emoeem-repo

将下面内容加入 /etc/pacman.conf:

[emoeem]
SigLevel = Never
Server = file:///var/lib/emoeem-repo/x86_64

SONAME 漂移排查

私有仓库的包由自己构建,不在 Arch 官方 rebuild 范围内。第三方依赖升级换掉
SONAME(libfoo.so.2 → libfoo.so.1)或 ABI 后,已发布的包会立刻变成
「装得上、跑不起来」,典型症状:

mpv: error while loading shared libraries: liboapv.so.2: cannot open shared object file

五步定位:

# 1. 缺哪个库
ldd "$(command -v mpv)" | grep 'not found'

# 2. 这个 SONAME 还有没有主人(报错 = 提供者已经换了 SONAME)
pacman -Qo /usr/lib/liboapv.so.2
pacman -Ql openapv | grep liboapv

# 3. 刚才是谁升级换掉的
grep -iE 'openapv|liboapv' /var/log/pacman.log | tail

# 4. 哪些已安装的包需要重建(AUR + 私人仓库)
LC_ALL=C checkrebuild -i emoeem

# 5. 重建:推送到 main(只重建变化的包及其依赖者),或手动触发
gh workflow run build.yml -f packages=<pkg> -f make_jobs=4 [-f bump_pkgrel=true]

rebuild-detector 自带的 hook 在本机是失效的,两个原因:

  • 它内部用 LANG=C stat --printf "%F" 识别可执行文件,但 LC_MESSAGES
    的优先级高于 LANG,中文环境下 %F 输出「一般文件」而不是
    regular file,于是它扫不到任何文件,永远报告「没有需要重建的包」。
    实测:checkrebuild -i emoeem 无输出,写成 LC_ALL=C checkrebuild -i emoeem
    后立刻列出 emoeem ffmpeg-full。手动调用必须带 LC_ALL=C。
  • checkrebuild 默认只覆盖 AUR(foreign)包和 file:// 仓库,私人仓库
    需要显式 -i emoeem。

安装仓库自带的 hook 覆盖版本,pacman -Syu 结束时会直接列出需要重建的包:

sudo install -Dm644 client/host/rebuild-detector.hook \
  /etc/pacman.d/hooks/rebuild-detector.hook

/etc/pacman.d/hooks/ 中的同名 hook 会覆盖
/usr/share/libalpm/hooks/rebuild-detector.hook;卸载 rebuild-detector
后请同时删除该文件。该版本不使用 NeedsTargets,因此每次事务都会重扫全部
AUR + 私人仓库包(本机实测约 2 秒),也能发现由传递依赖引起的失效。

仓库侧的自动化:

  • 推送 packages/** 或 scripts/overlays/** 时,build.yml 只重建变化的
    包及其依赖者。
  • dependency-drift.yml 每 4 小时比对 .BUILDINFO 里记录的依赖版本与仓库
    当前版本,自动 dispatch 重建。
  • maintenance.yml 每天扫描已发布包的 ELF NEEDED,确认每个 SONAME 仍由
    当前仓库提供;只有源码树里仍存在的包才会被 dispatch 重建,已下架却仍在
    发布的包记为 ORPHAN,而来自 chaotic-aur / archlinuxcn / arch4edu / AUR
    的库记在 scripts/data/external-sonames.txt(文件头部写明更新方法)。

如果依赖提供者自己没声明 provides=('libfoo.so=N-64')(例如 chaotic-aur 的
openapv),pacman 无法阻止不兼容升级,只能依赖上面的自动检测及时重建。

自动更新客户端

从 main 源码目录执行一次:

./client/install.sh

安装器会创建 emoeem-update 命令和 systemd timer。定时器每六小时:

  1. 以仓库所有者身份读取私人 GitHub 凭据。
  2. 强制同步最新的单提交 repo 快照。
  3. 清理 reflog 和旧 Git 对象,避免 .git 随构建次数累计。
  4. 校验软件包 SHA256。
  5. 只更新 pacman 的 emoeem.db 和 emoeem.files 缓存。

也可以随时手动更新:

emoeem-update

查看定时器:

systemctl list-timers emoeem-repo-update.timer

如果把 repo/x86_64 同步到自己的私有 HTTP 服务器,只需把 Server
改成服务器地址,就可以像普通 Arch 仓库一样使用。

仓库签名

默认生成未签名的私人仓库。需要包和数据库签名时,在 GitHub 仓库
Actions Secrets 中设置:

  • REPOSITORY_PRIVATE_KEY:ASCII armored GPG 私钥。
  • REPOSITORY_KEY_PASSPHRASE:私钥密码;无密码时留空。

工作流会签名每个软件包、数据库和 files 数据库,并将公钥导出为
x86_64/emoeem-key.asc。客户端导入并本地信任该密钥后,可改用:

SigLevel = Required DatabaseRequired

建议为 CI 单独创建仅用于仓库签名的 GPG 子密钥。

资源与许可

ffmpeg-full 会下载 CUDA,完整构建仍可能消耗较多时间和磁盘。可以在
仓库的 Actions Variables 中设置 BUILD_RUNNER=self-hosted,改用带
Docker 的 Linux 自托管 runner。

ffmpeg-full 的许可标识是
LicenseRef-nonfree-and-unredistributable。仓库必须保持私有,产物仅供
最终用户本人构建和使用,不要公开发布或用于商业用途。

维护工程化状态

当前仓库已完成一轮五阶段维护优化:

  1. AUR / Overlay:AUR 同步改为事务式 staging,先验证上游、overlay、PKGBUILD 和 .SRCINFO,再替换工作区,避免失败同步破坏现有包。
  2. PKGBUILD 审计:scripts/audit-packages.sh 对 12 个有效 package base 做元数据、架构、AUR 元数据以及 provider / dependency 一致性审计。
  3. 构建缓存:CI 复用 pacman、VCS source 和 Cargo 缓存,并让 builder / build 脚本变化自动失效对应缓存。
  4. Repository 完整性:发布前运行 scripts/verify-repository.sh,校验数据库引用、软件包资产、SHA256 和仓库配置。
  5. 管理与文档:TUI 增加「审计全部软件包」,构建流水线文档同步记录实际维护流程。

推荐的本地维护检查:

./scripts/audit-packages.sh
bash tests/test-package-audit.sh
bash tests/test-build-regressions.sh
python3 tests/test_select_packages.py
bash tests/test_repository.sh
bash -n manage.sh scripts/*.sh client/*.sh tests/*.sh