Skip to content

fix(build): do not force static linking on non-Linux hosts - #655

Merged
xiaods merged 1 commit into
mainfrom
fix/zig-build-k8e-macos
Oct 19, 2026
Merged

xiaods merged 1 commit into
mainfrom
fix/zig-build-k8e-macos

Conversation

@xiaods

@xiaods xiaods commented Oct 19, 2026

Copy link
Copy Markdown
Owner

这个 PR 修的是什么

zig build k8e 在 macOS 上从来没能成功过,一直卡在链接阶段:

ld: library 'crt0.o' not found

补充:我此前把这个错误归因为「本机缺 Xcode CLT」,那是错的。这台机器上 Xcode 26.6 与 Command Line Tools 都完好(xcode-select -p → /Applications/Xcode.app/Contents/Developer)。装 CLT 解决不了问题,根因在 build.zig。特此纠正。

根因

buildVersionFlags() 对图里每一个 Go 二进制都无条件输出同一套链接参数:

-w -s -extldflags '-static -lm -ldl -lz -lpthread'

这套在 macOS 上一条都不成立:

  • 没有静态 libc,-static 无法满足
  • libdl 和 libpthread 在 macOS 上都不是独立库(都在 libSystem 里)
  • 外部链接器于是去寻找 glibc 的静态启动对象 crt0.o,而 macOS 只有 crt1.o

而 build.zig 里没有任何 Go 构建设置 GOOS —— k8e、containerd、各 shim 全部按 host 编译。所以 Linux 主机(CI 全是)上这组参数是对的,只有 macOS 本地会失败。这就是为什么 CI 一直是绿的。

改法

把 host 系统传进去,按它选择链接参数:

fn buildVersionFlags(allocator, v, staticLink: bool) ![]const u8 {
    ...
    if (staticLink)
        "-w -s -extldflags '-static -lm -ldl -lz -lpthread'"
    else
        "-w -s",

调用处:buildVersionFlags(b.allocator, vi, builtin.os.tag == .linux)。

Linux 上选中的字符串与改动前逐字节一致,发布产物不变;其他平台保留 -w -s,动态链接系统库。

验证

macOS 实测:

命令 ldflags 结果
go build -ldflags "-w -s -extldflags '-static -lm -ldl -lz -lpthread'" 改动前 ❌ ld: library 'crt0.o' not found
go build -ldflags "-w -s" 改动后 mac 路径 ✅ 构建成功(172 MB)

修复后:

  • zig build k8e ✅ 链接成功,bin/k8e 182 MB,./bin/k8e --version → k8e version v1.37.0-20261018-rc1 (721c0c58)
  • zig build sandboxd ✅ 三架构通过
  • go build ./pkg/...、go vet ✅

一个有意为之的取舍

没有顺手跑 zig fmt build.zig。因为 build.zig 在 main 上本身就不符合 zig fmt(我用 stash 对比确认过:改动前后 zig fmt --check 都会报它)。全量格式化会带来几十行对齐噪音,把这两行核心改动埋掉。如果你希望单独提一个 formatting chore PR,我可以另开。

Done By AI

`zig build k8e` has never worked on a macOS host. It fails in the external
link step with:

    ld: library 'crt0.o' not found

buildVersionFlags emitted one linker flag set for every binary the graph
produces, unconditionally:

    -w -s -extldflags '-static -lm -ldl -lz -lpthread'

None of that is satisfiable on macOS. The system has no static libc, and libdl
and libpthread do not exist as separate libraries — both live in libSystem. The
linker therefore goes looking for glibc's static startup object crt0.o, which
macOS does not ship (it has crt1.o), and the build stops.

Nothing in the graph sets GOOS for its Go builds, so k8e, containerd and the
shims all compile for the host. On a Linux host (every CI runner) the flags are
correct, which is why this only ever failed locally.

Pass the host down and select the flag set with it. On Linux the chosen string
is byte-identical to the one this replaces, so release artifacts are unchanged;
elsewhere the binaries keep -w -s and link the system libraries dynamically.

Verified on macOS: `zig build k8e` now links and the resulting binary reports
`k8e version v1.37.0-20261018-rc1 (721c0c5)`; `zig build sandboxd` and the Go
suites still pass. `go build` with the old flags reproduces the crt0.o failure
exactly, and with `-w -s` succeeds, which pins the diagnosis.

build.zig is left as zig fmt --check already reports it on main: reformatting it
would bury this change in alignment noise.
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

977 tests  ±0   950 ✅ ±0   6m 43s ⏱️ -5s
120 suites ±0    27 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit f1e8393. ± Comparison against base commit 51ed878.

@xiaods
xiaods merged commit 5538029 into main Oct 19, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant