Skip to content

fix(r): build the Windows import library without objdump - #392

Merged
kingchenc merged 1 commit into
mainfrom
fix/r-winarm64-import-lib
Aug 18, 2026
Merged

fix(r): build the Windows import library without objdump#392
kingchenc merged 1 commit into
mainfrom
fix/r-winarm64-import-lib

Conversation

@kingchenc

Copy link
Copy Markdown
Collaborator

Problem

r-universe/wickra-lib/wickra/deploy has been failing on main since 2026-08-01. The R-devel and R-release jobs for Windows arm64 fail in configure.win; every other platform (Linux x86_64/arm64, macOS x86_64/arm64, Windows x86_64, Wasm) passes.

wickra: downloading C ABI aarch64-pc-windows-msvc for v0.9.9
C:\mingw64\bin\objdump.exe: src/wickra_abi.dll: file format not recognized
ERROR: configuration failed for package 'wickra'

configure.win dumped the export list out of the staged wickra_abi.dll with objdump. The objdump that resolves on that runner is the image's x86_64 mingw copy at C:\mingw64 — not Rtools45-aarch64 — and it carries no aarch64 PE backend, so it cannot read an arm64 DLL. Resolving the tool through ${CC} -print-prog-name=objdump returned the same x64 copy, which is why the previous attempt did not fix it.

Change

Derive the .def from the staged header instead of dumping the DLL. The cbindgen header declares exactly the exported symbols, so no binutils is involved in building the export list at all. Verified against the v0.9.9 release artifacts by parsing the PE export tables directly:

source symbols
wickra.h (header-derived) 3951
wickra-c-x86_64-pc-windows-msvc/lib/wickra.dll export table 3951
wickra-c-aarch64-pc-windows-msvc/lib/wickra.dll export table 3951
previous objdump-generated .def 3951

All four sets are identical — no symbol in one and not the others, in either direction.

Pass the target machine to dlltool explicitly and try the tools R can point at first. dlltool is still needed for the import library and has the same blind spot. A binutils build without the requested PE backend fails outright rather than silently emitting a wrong-architecture archive:

$ dlltool -m arm64 --input-def wickra_abi.def ...
dlltool.exe: Can't create .lib file: invalid bfd target

That loud failure is what makes an ordered candidate list safe: the first candidate that succeeds is by construction one that can target this architecture. The list is $WICKRA_DLLTOOL, ${BINPREF}llvm-dlltool, ${BINPREF}dlltool, llvm-dlltool, dlltoolBINPREF is R's own pointer at the matching Rtools toolchain, and the clang-based aarch64 Rtools ships llvm-dlltool, which carries every backend. If no candidate works the build stops and prints every attempt with its error, instead of failing later at link time.

Architecture detection moved above the dev-override branch, since the target machine is now needed on both paths.

Verification

Exercised locally on x86_64 against the real header and the released DLLs:

  • Header-derived export list == PE export table == previous objdump output (3951/3951, both directions).
  • New pipeline → dlltool → import library: same size, same 3951 symbols, same referenced DLL (wickra_abi.dll) as the one the old script produced. Only the archive member timestamps differ.
  • arm64 path on a host without an arm64-capable dlltool: every candidate fails, the diagnostic lists all attempts, configure.win exits 1.
  • sh -n / bash -n clean; no bashisms.

The repo's own CI cannot cover this — it has no Windows arm64 R job, which is why 1444a379 went green on all 98 checks while r-universe stayed red. The r-universe rebuild triggered by merging this is the real check.

R CMD INSTALL failed on Windows/arm64 in configure.win. The export list was
dumped from the staged wickra_abi.dll with objdump, but the objdump that
resolves there is the runner image's x86_64 mingw copy at C:\mingw64, which
carries no aarch64 PE backend and rejects the DLL with "file format not
recognized". Asking the compiler for a matching tool via -print-prog-name
returned that same x64 copy, so the previous attempt did not help.

Take the export list from the staged cbindgen header instead. The header
declares exactly the exported symbols -- it and the PE export table agree on
all 3951 entries, for both the x86_64 and the aarch64 release artifact -- so
producing the .def needs no binutils at all.

dlltool is still required for the import library itself and has the same blind
spot, so pass the target machine explicitly and try the candidates R can point
at (BINPREF, llvm-dlltool) ahead of the bare name. A binutils build without the
requested PE backend fails outright ("invalid bfd target") rather than quietly
emitting a wrong-architecture archive, so the first candidate that succeeds is
by construction one that can target this architecture; if none can, the build
stops with the full list of attempts. On x86_64 the resulting import library is
unchanged: same 3951 symbols, same referenced DLL.
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kingchenc
kingchenc merged commit 17792aa into main Aug 18, 2026
56 checks passed
@kingchenc
kingchenc deleted the fix/r-winarm64-import-lib branch August 18, 2026 19:53
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