Skip to content

Commit 36b70d0

Browse files
Fix Windows build with LLVM 21 by matching the dynamic C runtime
The clang-builder LLVM 21 Windows libraries are built against the dynamic UCRT, so their objects reference the C runtime through __imp_* import stubs. DMD links the static CRT (libcmt) by default, so those stubs went unresolved (LNK2019 on fputs, _write, _read, round, rand, ...), failing the link with LNK1120. LDC already defaults to the dynamic runtime, which is why only DMD failed to link. - Link DMD against the dynamic runtime on Windows (-mscrtlib=msvcrt) and add ntdll.lib for RtlGetLastNtStatus, referenced by LLVMSupport. - Drop the LLVM execution engine / interpreter / JIT libraries from the static libclang link. libclang never uses them, and they pulled their own C runtime dependencies in (e.g. LLVMInterpreter's fputs/scanf). - Move the Windows CI jobs back to LLVM 21.1.8 to exercise the fix. The include-resolution unit test difference under libclang 21 is a separate issue and is not addressed here.
1 parent d52c4f5 commit 36b70d0

3 files changed

Lines changed: 16 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ jobs:
3737
- os:
3838
host: windows-latest
3939
target_triple: x86_64-pc-windows-msvc
40-
# libclang 21 breaks the Windows build: DMD fails to link
41-
# LLVMSupport against the C runtime, and an include-order unit test
42-
# differs under LDC. Keep Windows on 15 until those are resolved.
43-
llvm: '15.0.7'
4440

4541
- os:
4642
target: freebsd
@@ -57,15 +53,15 @@ jobs:
5753

5854
include:
5955
- compiler: dmd-latest
60-
llvm: '15.0.7'
56+
llvm: '21.1.8'
6157
arch: x86_64
6258
data:
6359
os:
6460
host: windows-latest
6561
target_triple: x86_64-pc-windows-msvc
6662

6763
- compiler: dmd-beta
68-
llvm: '15.0.7'
64+
llvm: '21.1.8'
6965
arch: x86_64
7066
nightly: nightly
7167
data:
@@ -83,7 +79,7 @@ jobs:
8379
docker: true
8480

8581
- compiler: dmd-master
86-
llvm: '15.0.7'
82+
llvm: '21.1.8'
8783
arch: x86_64
8884
nightly: nightly
8985
data:
@@ -145,7 +141,6 @@ jobs:
145141
- os:
146142
host: windows-latest
147143
target_triple: x86_64-pc-windows-msvc
148-
llvm: '15.0.7'
149144
release_platform: windows-x64
150145

151146
- os:

configure

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,10 +546,20 @@ private:
546546
*/
547547
auto llvmFlags()
548548
{
549+
// libclang doesn't use the LLVM execution engine, interpreter or JIT.
550+
// Linking them drags their C runtime and ntdll dependencies into the
551+
// static link (e.g. LLVMInterpreter's fputs/scanf, LLVMSupport talking
552+
// to the JIT), which breaks the DMD link on Windows with LLVM 21.
553+
static immutable unusedLibraries = [
554+
"ExecutionEngine", "Interpreter", "MCJIT", "OrcJIT", "OrcShared",
555+
"OrcTargetProcess", "OrcDebugging", "RuntimeDyld", "JITLink"
556+
];
557+
549558
const result = dirEntries(llvmLibPath, "*LLVM*.{a,lib}", SpanMode.shallow)
550559
.map!(e => e.name)
551560
// exclude import library which causes a dynamic link on Windows
552561
.filter!(e => !e.endsWith("LLVM-C.lib"))
562+
.filter!(e => !unusedLibraries.any!(lib => e.baseName.canFind(lib)))
553563
.array;
554564

555565
const findAllSymbolsPath = llvmLibPath.buildPath("libfindAllSymbols.a");

dub.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
],
2121

2222
"lflags": ["@$PACKAGE_DIR/linker_flags.txt"],
23-
"libs-windows": ["version"],
23+
"libs-windows": ["version", "ntdll"],
24+
25+
"dflags-windows-dmd": ["-mscrtlib=msvcrt"],
2426

2527
"buildTypes": {
2628
"release": {

0 commit comments

Comments
 (0)