Skip to content

0.10 branch: macOS CI fails on macos-latest (macOS 26) with Go 1.20-1.23: missing LC_UUID load command #482

Description

@hajimehoshi

PureGo Version

0.10 branch (v0.10.0)

Operating System

  • Windows
  • macOS
  • Linux
  • FreeBSD
  • NetBSD
  • Android
  • iOS

Go Version (go version)

Go 1.20.x through 1.23.x (reproduced with go1.20.14, go1.22.12 and go1.23.11 on darwin/arm64)

What steps will reproduce the problem?

CI on the 0.10 branch fails now that GitHub's macos-latest label has migrated to macOS 26:
https://github.com/ebitengine/purego/actions/runs/29646451569

The Test with Go 1.22.x on macos-latest job fails in the go test step. Every other error in that run is The operation was canceled. from fail-fast.

Locally, on macOS 26.5 (arm64):

git checkout 0.10
env CGO_ENABLED=1 go1.22.12 test -c -o purego.test .
./purego.test -test.run TestOS

What is the expected result?

The test binary runs, as it did while macos-latest was macOS 15. The same job passed on
https://github.com/ebitengine/purego/actions/runs/26362358247 (2026-05-24), where the runner image was macos-15-arm64 / macOS 15.7.7.

What happens instead?

The binary is rejected by dyld before main runs:

dyld[9810]: missing LC_UUID load command in /var/folders/.../b001/purego.test
dyld[9810]: missing LC_UUID load command
signal: abort trap
FAIL	github.com/ebitengine/purego	0.003s

Anything else you feel useful to add?

Cause

This is not a purego bug. On macOS 26, dyld refuses to exec a Mach-O binary that has no LC_UUID load command when the binary targets the macOS 26 SDK and links CoreFoundation. Go's internal linker only emits LC_UUID when -B is passed, and -B gobuildid became the default only in Go 1.24 (cmd/link/internal/ld/main.go: if *flagHostBuildid == "" && *flagBuildid != "" { *flagHostBuildid = "gobuildid" }, present in go1.24.0, absent in go1.23.12).

CoreFoundation is pulled in by the cgo-enabled net package, which is why CGO_ENABLED=0 passes and CGO_ENABLED=1 fails within the same step. The -race steps fail for the same reason.

Measured on macOS 26.5 with the 0.10 tree:

Go LC_UUID LC_BUILD_VERSION CGO_ENABLED=1 test binary
1.18.10 absent minos 12.0 / sdk 12.3 runs
1.19.13 absent minos 12.x runs
1.20.14 absent minos 26.0 / sdk 26.5 dyld: missing LC_UUID
1.21.x absent (linker has no emission code) expected to fail
1.22.12 absent minos 26.x dyld: missing LC_UUID
1.23.11 absent minos 26.x dyld: missing LC_UUID
1.25.7 / 1.26.5 present minos 26.x runs

Go 1.18/1.19 survive only because their linker stamps an old SDK version in LC_BUILD_VERSION, so dyld applies the pre-26 rules.

Proposed fix

Pin the macOS runner to macos-15 in .github/workflows/test.yml on the 0.10 branch. The branch's supported Go range (1.18–1.26) cannot be narrowed, so the affected toolchains have to keep running on a pre-26 runner. macos-15 is still current and non-deprecated (macos-14 is deprecated), and main continues to exercise macOS 26 with Go 1.25+.

Alternatives that were considered and rejected:

  • -ldflags=-B=gobuildid on the macOS test commands: works for Go 1.22/1.23, but Go 1.20/1.21 reject the flag (-B argument must start with 0x: gobuildid) and cannot emit LC_UUID at all.
  • Dropping Go 1.20–1.23 from the macOS matrix: loses coverage that macos-15 can still provide.

main needs no change: #469 reduced its matrix to Go 1.25+, all of which emit LC_UUID by default. The same commit passed on main and failed on 0.10 on the same day.

Note for users: any Go program built with Go 1.20–1.23 that links CoreFoundation fails to launch on macOS 26, regardless of purego. The workaround is to build with Go 1.24 or later.


Filed by Claude (Claude Code), on behalf of @hajimehoshi.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions