Skip to content

feat: NetBSD amd64/arm64, platform matrix CI, purego coexistence job - #88

Open
unxed wants to merge 3 commits into
go-webgpu:mainfrom
unxed:feature/platform-matrix
Open

unxed wants to merge 3 commits into
go-webgpu:mainfrom
unxed:feature/platform-matrix

Conversation

@unxed

@unxed unxed commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Step 5 of the split agreed in #76. Depends on #83. This branch contains #83's commit, so review only the last commit. Once #83 is merged I'll rebase and the diff will drop that commit.

NetBSD amd64/arm64, full tier. These reuse the System V and AAPCS64 backends unchanged. The NetBSD-specific parts are dlopen from libc.so and errno via __errno (internal/dl/dl_netbsd.go, internal/syscall/errno_netbsd.go), and netbsd is added to the Unix build constraints. Like FreeBSD, NetBSD needs -gcflags=github.com/go-webgpu/goffi/internal/fakecgo=-std.

One real fix is included. internal/fakecgo/netbsd.go defined environ, __progname and __ps_strings with //go:linkname only. That gives local symbols, but NetBSD's libc.so expects rtld to resolve them from the main program, so the process would die before main. They are now also exported with //go:cgo_export_dynamic, as freebsd.go already does.

scripts/check-platforms.sh replaces the cross-compile job. It covers every target purego supports under CGO_ENABLED=0. For each target it:

  • builds ./... and links a consumer binary, and checks the tier the target claims (full, nocb, load or pending);
  • on targets that use goffi's own assembly callback trampolines, requires ffi.callbackTrampoline to be a text symbol. This is fix: build callback_amd64.s on FreeBSD #83's check-callback-trampolines.sh merged into the new script, now also run on netbsd;
  • expects pending targets (linux 386/arm/loong64/ppc64le/riscv64/s390x) to keep failing. If one starts building while the table still says pending, the script fails.

It also builds the examples.

purego-coexistence job. It builds a CGO_ENABLED=0 -tags nofakecgo program that imports both purego and goffi, calls getpid through each, and compares the results with os.Getpid().

Docs: docs/PLATFORMS.md covers the tiers, the build flags and the purego parity diff. It also records that windows/386 is loader-only (CallFunction returns ErrUnsupportedArchitecture); that target already built, but the docs never said so. Also updated: the README platform table, a ROADMAP section on the remaining Linux architectures, and CHANGELOG.

NetBSD support is checked by cross-compiling and linking only. It has not run on a NetBSD host.

The Android arm64 jobs fail in "Set up Android SDK" before any goffi code runs. That failure is unrelated to this PR and is fixed by #85.

🤖 Generated with Claude Code

Both Android arm64 jobs now fail in "Set up Android SDK", before any goffi
code runs:

    Warning: Failed to find package 'tools'
    Error: The process '/usr/local/lib/android/sdk/cmdline-tools/16.0/bin/sdkmanager' failed with exit code 1

android-actions/setup-android@v3 defaults its `packages` input to
`tools platform-tools` and runs `sdkmanager <pkg>` for each entry. Google's
SDK repository index (repository2-3.xml) no longer contains a `tools`
package, while `platform-tools` and `cmdline-tools` are still listed, so
the `tools` call exits 1. The same breakage is tracked upstream in
android-actions/setup-android#537. The last green run of these jobs on main
was for c8f74c6 on 2026-09-10; the workflow has not changed since, and the
failure is identical on a docs-only PR.

Nothing in this workflow or in scripts/check-android-arm64.sh uses the
`tools` package. Pass `packages: platform-tools`, which keeps everything
the step installed before except the package that no longer exists. The
action still accepts licenses, exports ANDROID_HOME and puts sdkmanager on
PATH, which the following NDK step relies on.
@unxed
unxed requested a review from kolkov as a code owner September 25, 2026 14:16
@codecov

codecov Bot commented Sep 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

unxed and others added 2 commits September 25, 2026 16:31
ffi/callback.go is built for (linux || darwin || freebsd) && amd64, but
ffi/callback_amd64.s, which holds the 2000-entry trampoline table and
callbackDispatcher, was built only for (linux || darwin) && amd64.

The Go side takes the table's address through a placeholder:

    //go:linkname _callbackTrampoline github.com/go-webgpu/goffi/ffi.callbackTrampoline
    var _callbackTrampoline byte

With the assembly excluded, that one-byte variable becomes the definition
of ffi.callbackTrampoline. Nothing fails to compile or link. On a linked
freebsd/amd64 consumer, `go tool nm` reports

    D github.com/go-webgpu/goffi/ffi.callbackTrampoline

and no callbackDispatcher or callbackWrap at all, where linux/amd64 and
freebsd/arm64 report T for all three. NewCallback therefore returns
addresses computed from a data-segment byte, not code.

The dispatcher is plain System V AMD64 (the same ABI FreeBSD uses) and
enters Go through crosscall2, which internal/fakecgo already provides on
FreeBSD, so the fix is adding freebsd to the constraint.

The existing cross-compile job could not catch this: `go build ./...`
links nothing, and the broken build compiles. scripts/check-callback-
trampolines.sh links a small NewCallback consumer for every target whose
callbacks come from goffi's own assembly (linux, darwin, freebsd x amd64,
arm64) and fails unless the symbol is T. Run against the tree before this
change it reports freebsd/amd64 as 'D'; after it, all six targets pass.
The Cross-Compile job now runs it.

Not verified on a FreeBSD host; the evidence is the symbol table of the
cross-linked binaries.

Refs: go-webgpu#76 (review)
NetBSD amd64/arm64 get the full FFI tier, reusing the System V and
AAPCS64 backends unchanged. NetBSD keeps the dlopen family in libc.so and
its errno accessor is __errno (not glibc's __errno_location, not
FreeBSD/macOS __error). netbsd joins the Unix-family build constraints.

NetBSD fakecgo did not export environ/__progname/__ps_strings into the
dynamic symbol table. //go:linkname alone gives a local definition, and
NetBSD's libc.so has undefined references to all three that rtld
resolves against the main object, so the process would have died before
main. Added //go:cgo_export_dynamic, as freebsd.go does.

scripts/check-platforms.sh becomes the source of truth for the platform
table: it builds and links every target purego supports under
CGO_ENABLED=0, asserts the tier each one claims, checks that
ffi.callbackTrampoline links as code on every asm-trampoline target
(absorbing scripts/check-callback-trampolines.sh), and fails if a target
listed as pending starts building. It replaces the cross-compile job.

A purego-coexistence job builds a CGO_ENABLED=0 -tags nofakecgo program
that calls getpid through both purego and goffi and checks the results.

docs/PLATFORMS.md documents the tiers, windows/386 as loader-only (it
already built, it was never stated), and the purego parity diff;
ROADMAP.md gets the plan for the six remaining Linux architectures.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@unxed
unxed force-pushed the feature/platform-matrix branch from 7a796b9 to 6bd8e5d Compare September 25, 2026 16:31
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