改用 musl 全静态构建,零依赖跨发行版
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,14 +4,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 仓库性质
|
||||
|
||||
本仓库**只包含构建与打包基础设施**,不含 mond 源码。源码在编译时从外部仓库克隆(见 [docker/Dockerfile.ubuntu](docker/Dockerfile.ubuntu)):
|
||||
本仓库**只包含构建与打包基础设施**,不含 mond 源码。源码在编译时从外部仓库克隆(见 [docker/Dockerfile](docker/Dockerfile)):
|
||||
|
||||
- 源码仓库:`github.com/monero-project/monero.git`(**Monero 官方仓库**,非换名仓库)
|
||||
- 发布仓库:Gitea `gitea.bcde.io` 下 `wangdefa/mond` 的 Generic / Debian 包仓库
|
||||
|
||||
mond 是 Monero 守护进程 `monerod` 的定制换名构建。换名通过 [init.sh](init.sh) 在编译期对源码做 `sed` 改写完成:`project(monero)→project(mond)`、二进制 `OUTPUT_NAME monerod→mond`、`MONERO_VERSION_*` 宏 → `MOND_VERSION_*`、用户可见字符串 `Monero→Mond`。**改动版本宏或显示字符串相关逻辑时,改 init.sh 而非源码**(源码每次构建都重新克隆)。
|
||||
mond 是 Monero 守护进程 `monerod` 的定制换名构建。换名通过 [init.sh](init.sh) 在编译期对源码做 `sed` 改写完成:`project(monero)→project(mond)`、二进制 `OUTPUT_NAME monerod→mond`、`MONERO_VERSION_*` 宏 → `MOND_VERSION_*`、用户可见字符串 `Monero→Mond`。**改动版本宏或显示字符串相关逻辑时,改 init.sh 而非源码**(源码每次构建都重新克隆)。init.sh 末尾还含 musl 纯静态所需的 CMakeLists patch(见下「为何 patch」)。
|
||||
|
||||
> **与同目录 `gitea-xxxig` / `gitea-xxxig-proxy` 的关键差异**:那两个项目源码来自 `wangdefaa`(双 a)换名仓库;mond 直接克隆 Monero 官方仓库,靠 init.sh 现场改名。三者共享同一套 CI / build-deb / debian 打包骨架,但 mond 的构建方式(官方 depends 系统)和版本号格式(四段 `0.18.5.0`)不同。
|
||||
> **与同目录 `gitea-xxxig` / `gitea-xxxig-proxy` 的关键差异**:那两个项目源码来自 `wangdefaa`(双 a)换名仓库;mond 直接克隆 Monero 官方仓库,靠 init.sh 现场改名。三者共享同一套 CI / build-deb / debian 打包骨架,且均为 **musl fully-static** 构建;mond 的版本号格式为四段 `0.18.5.0`。
|
||||
|
||||
## 整体架构:单二进制
|
||||
|
||||
@@ -21,15 +21,17 @@ mond 是 Monero 守护进程 `monerod` 的定制换名构建。换名通过 [ini
|
||||
|
||||
[.gitea/workflows/ci.yaml](.gitea/workflows/ci.yaml) 是 Gitea Actions 流水线:
|
||||
|
||||
1. **build-and-test**(矩阵 `arch=[amd64,arm64]`,跑在对应架构原生 runner):用 `docker buildx` 按 [docker/Dockerfile.ubuntu](docker/Dockerfile.ubuntu) 原生编译 → 打成 tar.gz → 解包冒烟测试(`mond --version` + `ldd` 纯静态校验)→ 调 `debian/build-deb.sh` 打 .deb → 上传 artifact。
|
||||
1. **build-and-test**(矩阵 `arch=[amd64,arm64]`,跑在对应架构原生 runner):用 `docker buildx` 按 [docker/Dockerfile](docker/Dockerfile) 原生编译 → 打成 tar.gz → 解包冒烟测试(`mond --version` + `ldd` 纯静态校验)→ 调 `debian/build-deb.sh` 打 .deb → 上传 artifact。
|
||||
2. **release**(仅 tag 触发):下载 artifact,上传 tar.gz 到 Generic Package Registry、上传 .deb 到 Debian Registry(stable/main),并用 `jq` 生成描述创建 Gitea Release。
|
||||
|
||||
关键点:
|
||||
- **只构建 ubuntu,不做 alpine**(刻意取舍):mond 用 Monero **官方 depends 系统**(`make depends target=…`)交叉编译,将 boost/openssl/zmq 等第三方依赖全部静态链入,**运行时仅动态依赖 glibc**(`ldd` 仍列出 libc/libm/libpthread/ld-linux —— 并非纯静态,故 Alpine/musl 系统无法直接运行)。主分发渠道是面向 Debian/Ubuntu 的 .deb(`Depends: libc6 (>= 2.31)`);单次构建耗时 30–60 分钟,加 distro 维度会让 CI 翻倍。若要支持 Alpine 须改用 musl + `-static-pie` 真静态构建(当前未做)。
|
||||
- **版本号约定**:包版本硬编码在 ci.yaml 的 `PACKAGE_VERSION: "0.18.5.0"`(**纯数字、无 v**,符合 Debian 版本规范)。**关键分界**:上游 Monero git tag 带 `v`,故 build job 用 `MONERO_VERSION=v${PACKAGE_VERSION}` 补回 v 传给 Dockerfile `git checkout`;tar.gz / deb / registry 路径 / Release 标题等包版本一律直接用 `${PACKAGE_VERSION}`;release job 用 `VERSION="${TAG#v}"` 归一(tag 带不带 v 都兼容)。CI 触发条件为 `tags: ['*']`,发版改 `PACKAGE_VERSION` 并打对应 tag(纯数字,如 `0.18.5.0`)。
|
||||
- **依赖精简**:depends 系统已将 boost/openssl/zmq/unbound/sodium/unwind 静态链入,故 [debian/control.template](debian/control.template) 仅 `Depends: libc6`,无需列动态库。
|
||||
- 架构名映射:Dockerfile 内 `arm64→aarch64-linux-gnu`、`amd64→x86_64-linux-gnu` 作为 depends target。
|
||||
- tar.gz 下载 URL 形如 `https://gitea.bcde.io/api/packages/wangdefa/generic/mond/{version}/mond-{arch}-ubuntu-{version}.tar.gz`(version 为纯数字)。
|
||||
- **musl fully-static(Alpine 构建,勿改回 glibc)**:[docker/Dockerfile](docker/Dockerfile) 在 `alpine:3.23` 下手动源码编译 5 个静态库(OpenSSL 3.0.16 / libsodium / libzmq / expat / unbound——Alpine 仓库只有 `.so`/缺 `.a`,须 `--disable-shared` 自编),编出 **static-pie 纯静态**二进制:`ldd` = `statically linked`、零外部依赖,**glibc/musl 任意发行版直接运行**(实测 musl 产物在 Debian 13 上正常运行)。`make daemon` 约 7 分钟/架构(5 库命中 Docker 层缓存后),远快于原 glibc depends 系统的 30–60 分钟。
|
||||
- **为何用 musl 而非 glibc 全静态**:glibc 的 `getaddrinfo` 依赖运行时 `dlopen` NSS 模块,`-static` 全静态后无法加载 → DNS 解析失败(`DNS error: resource busy or locked`);musl 的 `getaddrinfo` 自带实现,全静态也能正常解析。与 `gitea-xxxig`/`gitea-xxxig-proxy` 一致。曾用的 glibc(ubuntu) depends 构建线已删除。
|
||||
- **为何 patch monero 源码([init.sh](init.sh) 末尾,勿删)**:monero 官方明确「不支持 fully static」——`CMakeLists.txt` 中 `STATIC=ON` 在 Linux 只加 `-static-libgcc -static-libstdc++`(非真 `-static`),且强制追加 `-pie` 安全加固,会让链接结果带 musl interpreter、退化成动态。故 init.sh 用 `sed` 去掉 `-pie`、把 Linux 的 `STATIC_FLAGS` 改成真 `-static`。Alpine gcc 默认 PIE,`-static` 自动产出 static-pie(零外部依赖)。
|
||||
- **版本号约定**:包版本硬编码在 ci.yaml 的 `PACKAGE_VERSION: "0.18.5.0"`(**纯数字、无 v**,符合 Debian 版本规范)。**关键分界**:上游 Monero git tag 带 `v`,故 build job 用 `MONERO_VERSION=v${PACKAGE_VERSION}` 补回 v 传给 Dockerfile `git clone --branch`;tar.gz / deb / registry 路径 / Release 标题等包版本一律直接用 `${PACKAGE_VERSION}`;release job 用 `VERSION="${TAG#v}"` 归一(tag 带不带 v 都兼容)。CI 触发条件为 `tags: ['*']`,发版改 `PACKAGE_VERSION` 并打对应 tag(纯数字,如 `0.18.5.0`)。
|
||||
- **依赖精简**:5 个静态库 + libstdc++/libgcc 全部静态链入(真 `-static`),故 [debian/control.template](debian/control.template) **无 `Depends` 字段**(纯静态,连 libc6 都不需要)。
|
||||
- 架构映射:Dockerfile 内 `arm64→ARCH=armv8-a / BUILD_TAG=linux-armv8`、`amd64→ARCH=x86-64 / BUILD_TAG=linux-x64`(传给 monero cmake);OpenSSL target `aarch64→linux-aarch64`、`x86_64→linux-x86_64`。
|
||||
- tar.gz 下载 URL 形如 `https://gitea.bcde.io/api/packages/wangdefa/generic/mond/{version}/mond-{arch}-linux-static-{version}.tar.gz`(version 为纯数字)。
|
||||
|
||||
## 本地常用命令
|
||||
|
||||
@@ -38,16 +40,16 @@ mond 是 Monero 守护进程 `monerod` 的定制换名构建。换名通过 [ini
|
||||
docker buildx build --platform linux/amd64 \
|
||||
--build-arg MONERO_VERSION=v0.18.5.0 \
|
||||
--output type=local,dest=./output \
|
||||
-f docker/Dockerfile.ubuntu .
|
||||
-f docker/Dockerfile .
|
||||
|
||||
# 用已有 tar.gz 打 .deb 包(注意第三个参数是 tar.gz,不是目录)
|
||||
./debian/build-deb.sh amd64 0.18.5.0 mond-amd64-ubuntu-0.18.5.0.tar.gz
|
||||
./debian/build-deb.sh amd64 0.18.5.0 mond-amd64-linux-static-0.18.5.0.tar.gz
|
||||
|
||||
# 改 shell 脚本后做静态检查(需自行安装 shellcheck)
|
||||
shellcheck debian/*.sh
|
||||
```
|
||||
|
||||
无单元测试;CI 中唯一的冒烟测试是解包后跑 `mond --version`,并用 `ldd` 校验运行时仅依赖 glibc(无第三方动态库)。
|
||||
无单元测试;CI 中唯一的冒烟测试是解包后跑 `mond --version`(musl 纯静态二进制可在 glibc 的 CI runner 直接运行),并用 `ldd` 校验为 `statically linked`(纯静态、无任何动态依赖)。
|
||||
|
||||
## Debian 包布局与服务
|
||||
|
||||
|
||||
Reference in New Issue
Block a user