私人 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 同一个构建。
个别软件包构建失败不会阻塞其他成功构建的软件包发布。
构建环境按以下优先级使用依赖:
- CachyOS 仓库(
cachyos-v3、cachyos-extra-v3、cachyos-core-v3、cachyos,使用官方 mirrorlist,容器同时接受x86_64_v3架构) - Arch Linux 官方仓库
- archlinuxcn
- coderkun-aur
- Chaotic-AUR
- 仍未满足的依赖由
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.zstemoeem.db与emoeem.db.tar.zstemoeem.files与emoeem.files.tar.zstSHA256SUMSemoeem.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每天扫描已发布包的 ELFNEEDED,确认每个 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。定时器每六小时:
- 以仓库所有者身份读取私人 GitHub 凭据。
- 强制同步最新的单提交
repo快照。 - 清理 reflog 和旧 Git 对象,避免
.git随构建次数累计。 - 校验软件包 SHA256。
- 只更新 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。仓库必须保持私有,产物仅供
最终用户本人构建和使用,不要公开发布或用于商业用途。
维护工程化状态
当前仓库已完成一轮五阶段维护优化:
- AUR / Overlay:AUR 同步改为事务式 staging,先验证上游、overlay、PKGBUILD 和
.SRCINFO,再替换工作区,避免失败同步破坏现有包。 - PKGBUILD 审计:
scripts/audit-packages.sh对 12 个有效 package base 做元数据、架构、AUR 元数据以及 provider / dependency 一致性审计。 - 构建缓存:CI 复用 pacman、VCS source 和 Cargo 缓存,并让 builder / build 脚本变化自动失效对应缓存。
- Repository 完整性:发布前运行
scripts/verify-repository.sh,校验数据库引用、软件包资产、SHA256 和仓库配置。 - 管理与文档: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








