What was measured
mcpp's openkal cross-build (3 hosts x 3 targets) workflow builds openkal-llvm-runtime/examples/same-source for x86_64-windows-gnu on a windows-2022 runner with xim:llvm@22.1.8. On 2026-09-13 (mcpp-community/mcpp#629) the job was green at one commit and red at the next on identical sources and the same runner image:
lld: error: unable to find library -lntdll
lld: error: unable to find library -lsynchronization
lld: error: unable to find library -lshell32
lld: error: unable to find library -lkernel32
lld: error: unable to find library -lbcrypt
The only difference between the two runs was the restored ~/.mcpp sandbox cache lineage. A diagnostic step added to the job then showed where the libraries come from when the link succeeds:
$ clang++ --target=x86_64-w64-windows-gnu -print-search-dirs
libraries: =...\xim-x-llvm\22.1.8\lib\clang\22;C:\mingw64\lib\gcc\x86_64-w64-mingw32\14.2.0;C:\mingw64\x86_64-w64-mingw32\lib;...
$ clang++ --target=x86_64-w64-windows-gnu -print-file-name=libntdll.a
C:\mingw64\x86_64-w64-mingw32\lib\libntdll.a
$ command -v x86_64-w64-mingw32-gcc
/c/mingw64/bin/x86_64-w64-mingw32-gcc
Why
build.mcpp returns before generating import libraries when the host is Windows ("on this system they are present, they are the vendor's"), and puts no link_search on the consumer's line. With xim:llvm's clang and --target=x86_64-w64-windows-gnu, the driver derives its sysroot from whichever x86_64-w64-mingw32-gcc it finds on PATH. On GitHub's image that is C:\mingw64; on a machine without one, or with a different one first on PATH (a sandbox that carries a mingw payload), -lntdll and its neighbours are not found. The link therefore depends on the host's state rather than on anything the package declares, which is the shape this package's own header says it exists to remove.
What would answer it
Generate the five import libraries from port/*.def with llvm-dlltool on a Windows host too whenever the compiler family is clang, exactly as on the other hosts, and put their directory on the consumer's link line. -L is searched first, so a project that does have a vendor set would resolve the forty-five names from these stubs; the header argues that is wrong where the vendor's set is present. The alternative that keeps that argument is to declare the payload that carries the vendor's set (xim:mingw-gcc) for cfg(all(windows, not(env = "msvc"))) and read its x86_64-w64-mingw32/lib through xpkg_dir, so the search directory is named rather than found.
The mcpp workflow now prints the search directories before the build so that the next such reading is diagnosed from the log; it does not work around the dependence.
What was measured
mcpp's
openkal cross-build (3 hosts x 3 targets)workflow buildsopenkal-llvm-runtime/examples/same-sourceforx86_64-windows-gnuon awindows-2022runner withxim:llvm@22.1.8. On 2026-09-13 (mcpp-community/mcpp#629) the job was green at one commit and red at the next on identical sources and the same runner image:The only difference between the two runs was the restored
~/.mcppsandbox cache lineage. A diagnostic step added to the job then showed where the libraries come from when the link succeeds:Why
build.mcppreturns before generating import libraries when the host is Windows ("on this system they are present, they are the vendor's"), and puts nolink_searchon the consumer's line. Withxim:llvm's clang and--target=x86_64-w64-windows-gnu, the driver derives its sysroot from whicheverx86_64-w64-mingw32-gccit finds onPATH. On GitHub's image that isC:\mingw64; on a machine without one, or with a different one first onPATH(a sandbox that carries a mingw payload),-lntdlland its neighbours are not found. The link therefore depends on the host's state rather than on anything the package declares, which is the shape this package's own header says it exists to remove.What would answer it
Generate the five import libraries from
port/*.defwithllvm-dlltoolon a Windows host too whenever the compiler family is clang, exactly as on the other hosts, and put their directory on the consumer's link line.-Lis searched first, so a project that does have a vendor set would resolve the forty-five names from these stubs; the header argues that is wrong where the vendor's set is present. The alternative that keeps that argument is to declare the payload that carries the vendor's set (xim:mingw-gcc) forcfg(all(windows, not(env = "msvc")))and read itsx86_64-w64-mingw32/libthroughxpkg_dir, so the search directory is named rather than found.The mcpp workflow now prints the search directories before the build so that the next such reading is diagnosed from the log; it does not work around the dependence.