Skip to content

windows: perry.exe cannot link against the official LLVM 22 release — /MT vs /MD, bundled rpmalloc, and missing inkwell target backends #7985

Description

@proggeramlug

Summary

Linking perry.exe on windows-latest against the pinned C:\llvm (the official
clang+llvm-22.1.3-x86_64-pc-windows-msvc tarball installed by
.github/actions/setup-llvm22) fails with three independent link.exe
errors
. This is the windows-latest arm of gc-native-roots (#7970), and it is
a real build breakage, not a harness problem.

It is very likely also latent in test.yml's windows-build. That job builds
the same -p perry with the same action, but it has been dying at its first
step since #7977 (cp1252 decode), so its build step has not executed on any recent
PR. Expect this to surface there the moment #7977 lands — please read the two
together.

Evidence

Run 31405431962, job native-roots-rs4gc (windows-latest, x86-64, PE),
LLVM_SYS_221_PREFIX: C:\llvm, step "Build compiler and static runtime":

error: linking with `link.exe` failed: exit code: 1120

1. CRT model mismatch (mimalloc /MD vs llvm-sys /MT)

liblibmimalloc_sys-*.rlib(mimalloc-static.o) : error LNK2038: mismatch detected for
'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease'
in libllvm_sys-*.rlib(Core.cpp.obj)
LINK : warning LNK4098: defaultlib 'libcmt.lib' conflicts with use of other libs

The official LLVM Windows release is built /MT (static CRT); Rust's msvc target
and libmimalloc-sys use /MD. They cannot be linked into one image as-is.

2. Allocator symbol collision (LLVM release bundles rpmalloc)

ucrt.lib(api-ms-win-crt-heap-l1-1-0.dll) : error LNK2005: calloc  already defined in libllvm_sys-*.rlib(rpmalloc.c.obj)
...                                                     free     already defined in ... rpmalloc.c.obj
...                                                     malloc   already defined in ... rpmalloc.c.obj
...                                                     realloc  already defined in ... rpmalloc.c.obj

build_llvm_release.bat links rpmalloc into the Windows release to speed up
LLD. Those definitions come along through llvm-sys and collide with the UCRT —
and, separately, Perry already has its own allocator (mimalloc), so there would be
two.

3. Missing target backends inkwell references

libinkwell-*.rlib : error LNK2019: unresolved external symbol LLVMInitializeMipsTarget
                                   ... LLVMInitializeLanaiTarget
                                   ... LLVMInitializeSparcTarget
                                   ... LLVMInitializeMSP430Target
                                   ... LLVMInitializeXCoreTarget       (and the
   matching TargetInfo / AsmPrinter / AsmParser / Disassembler / TargetMC symbols)

inkwell's Target::initialize_* surface expects experimental targets the official
Windows release does not build.

Why it was invisible

gc-native-roots has never had a green run (#7970), and is not in branch
protection's required contexts, so a red result there is indistinguishable from
the queue noise. The only other Windows job, windows-build, has been failing
27 s in at an unrelated step (#7977). Between them, nothing has successfully
linked perry.exe on Windows in CI for some time.

The xml2s.lib comment block in .github/actions/setup-llvm22/action.yml says
this became fatal when #7353 made the in-process LLVM backend the default and
statically linked, and explicitly notes that "test.yml's windows-build and
gc-native-roots.yml's PE arm fail identically". That comment is about a
previous instance of the same class; these three errors are past it.

Directions (not a recommendation — this needs a Windows-toolchain decision)

  • Build the perry Windows job against an LLVM built /MD without rpmalloc
    (e.g. a self-built or vcpkg LLVM), rather than the official release tarball.
  • Or /NODEFAULTLIB + /FORCE:MULTIPLE surgery, which trades a link error for
    an allocator whose behaviour nobody has characterised — probably worse.
  • Or build perry on Windows without the default llvm-inprocess feature, so
    llvm-sys/inkwell are not linked at all, and keep the in-process backend to
    the platforms it is actually exercised on. This is the smallest change and the
    one most consistent with the feature's current CI coverage (macOS only, and see
    PERRY_LLVM_INPROCESS=native cannot build RS4GC ptr addrspace(1) roots; the unit corpora froze 151 codegen commits ago #7982).

Separately fixed

The same job then failed a second time (exit 2) at the Windows LLVM download:

tar (child): Cannot connect to D: resolve failed
xz: (stdin): File format not recognized

Git-bash GNU tar reads $RUNNER_TEMP (D:\a\_temp) as a remote host:path.
That one is a workflow bug and is fixed in the #7970 PR with tar --force-local
plus a post-extraction check. It is noted here only so the log is not confusing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions