Skip to content

Windows arm64, a checked ABI assumption, and a fuller CI matrix - #37

Closed
calvinchengx wants to merge 6 commits into
fpt:mainfrom
calvinchengx:windows-arm64
Closed

calvinchengx wants to merge 6 commits into
fpt:mainfrom
calvinchengx:windows-arm64

Conversation

@calvinchengx

Copy link
Copy Markdown
Contributor

Windows was already supported and CI-tested here; what was missing was arm64, and a check on the assumption the workaround rests on. This adds both, widens the CI matrix to the platforms COMPATIBILITY.md claims, and makes the musl case real.

Every job below is green on my fork: calvinchengx#1

The ABI assumption is now stated and checked

register_result_windows.go registers duckdb_fetch_chunk and duckdb_result_return_type with a pointer argument because a 48-byte aggregate is passed indirectly. That bet was correct but implicit, and if duckdb_result were ever reduced below the threshold the registration would read the wrong memory silently.

  • The threshold is now stated per architecture — 8 bytes on amd64 (Win64), 16 on arm64 (AAPCS64) — in abi_windows_amd64.go and abi_windows_arm64.go.
  • A compile-time assertion fails the build if the struct drops below it. This can only check the Go mirror; the C API offers no way to ask for the real size, so a mirror that has drifted from the C definition is still caught by the tests, not by this. The comment says so.

One deliberate behaviour change worth your judgement: 32-bit Windows (386, arm) now fails to build, with an explanatory type in abi_windows_unsupported.go. Those conventions push large aggregates onto the stack by value, so the workaround is wrong there rather than merely untested — and DuckDB publishes no 32-bit Windows library. Happy to drop this commit if you would rather leave those targets compiling.

windows/arm64

No code change was needed beyond the threshold constant — the existing _windows file already applies to both. It is now exercised on windows-11-arm and passes.

CI matrix

macos-13 has been retired by GitHub, so macOS amd64 was silently uncovered. The matrix is now linux amd64+arm64, macOS arm64 (macos-latest) and amd64 (macos-15-intel), and Windows amd64+arm64 — with the DuckDB asset chosen per target rather than per OS.

musl

The Dockerfile said "Official DuckDB builds require glibc. Not musl." That is no longer true — v1.5.4 publishes libduckdb-linux-{amd64,arm64}-musl.zip. There is now a Dockerfile.musl and a second integration job, and it passes.

It surfaced one thing worth knowing: libduckdb.so links against libstdc++, which an Alpine base does not carry, so the image needs apk add libstdc++. A glibc-only CI would never have shown that, and an Alpine user would have hit it as "failed to load DuckDB library from any standard location".

DLL discovery

Two changes:

  • The executable's own directory is searched first. It is the one location a shipped binary can rely on; the working directory changes with however the program was launched. The working directory is still searched, immediately after.
  • An absolute path now loads via LoadLibraryExW with LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS. That is safer than the legacy search, which reaches the current directory and PATH, and it lets a DuckDB DLL resolve dependencies sitting beside it. A bare name still goes through the standard search including PATH, so anyone relying on that — including this repo's own CI — is unaffected. No new dependency: LoadLibraryExW is reached through syscall.NewLazyDLL, keeping #270 satisfied.

Not addressed

When the library fails to load, driver_test.go continues against a nil handle and panics on a nil pointer dereference rather than failing cleanly. I left it alone as unrelated to this change, but it makes a missing-DLL diagnosis noisier than it needs to be.

@calvinchengx

Copy link
Copy Markdown
Contributor Author

Added one commit since opening: make integ-musl and make integ-musl-arm64 for the Dockerfile.musl this PR introduces. It was an omission on my part — the CI job existed but the command to reproduce a musl failure locally did not. Verified end to end on arm64: builds Alpine, installs the musl libduckdb, suite passes.

Separately, I opened #38 with two Makefile fixes that are independent of this PR (.PHONY listed only integ; make help hid integ-arm64). Kept out of here so this one stays scoped to Windows.

@calvinchengx

Copy link
Copy Markdown
Contributor Author

Already on main. The integ-musl and integ-musl-arm64 targets and their .PHONY entries are all present there (Makefile lines 15 and 43-49), and internal/integ/Dockerfile.musl exists. Closing as landed, not as rejected.

@calvinchengx
calvinchengx deleted the windows-arm64 branch September 9, 2026 23:32
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