Skip to content

[compiler-rt][MSVC][CMake] Wrap Linker flags for ICX #118496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 4, 2024

Conversation

Maetveis
Copy link
Contributor

@Maetveis Maetveis commented Dec 3, 2024

RFC: https://discourse.llvm.org/t/rfc-cmake-linker-flags-need-wl-equivalent-for-intel-c-icx-on-windows/82446

My previous pass missed some flags because I used -Werror=unknown-argument``, but /D, `/I` and `/O` are accepted by clang (even when only linking), but mean different things than intended for `link.exe. Wrapping the linker with a script revealed these flags.

The approach I used to find these is documented as github gist here: https://gist.github.com/Maetveis/00567488f0d6ff74095d91ed306fafc5

RFC: https://discourse.llvm.org/t/rfc-cmake-linker-flags-need-wl-equivalent-for-intel-c-icx-on-windows/82446

My previous pass missed some flags because I used `-Werror=unknown-argument``,
but `/D``, `/I` and `/O` are accepted by clang (even when only linking),
but mean different things than intended for `link.exe``.
Wrapping the linker with a script revealed these flags.
@llvmbot
Copy link
Member

llvmbot commented Dec 3, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Mészáros Gergely (Maetveis)

Changes

RFC: https://discourse.llvm.org/t/rfc-cmake-linker-flags-need-wl-equivalent-for-intel-c-icx-on-windows/82446

My previous pass missed some flags because I used -Werror=unknown-argument``, but /D, `/I` and `/O` are accepted by clang (even when only linking), but mean different things than intended for `link.exe. Wrapping the linker with a script revealed these flags.

The approach I used to find these is documented as github gist here: https://gist.github.com/Maetveis/00567488f0d6ff74095d91ed306fafc5


Full diff: https://github.com/llvm/llvm-project/pull/118496.diff

2 Files Affected:

  • (modified) compiler-rt/CMakeLists.txt (+1-1)
  • (modified) compiler-rt/lib/asan/CMakeLists.txt (+1-1)
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 20054c6e85a407..80d5aaabfd8c3f 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -768,7 +768,7 @@ if (CMAKE_LINKER MATCHES "link.exe$")
   # it, but CMake doesn't seem to have a way to set linker flags for
   # individual static libraries, so we enable the suppression flag for
   # the whole compiler-rt project.
-  set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221")
+  set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${CMAKE_CXX_LINKER_WRAPPER_FLAG}/IGNORE:4221")
 endif()
 
 add_subdirectory(include)
diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index fb3d74283a61e0..5ec995ae159b73 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -141,7 +141,7 @@ append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC
 # LLVM turns /OPT:ICF back on when LLVM_ENABLE_PDBs is set
 # we _REALLY_ need to turn it back off for ASAN, because the way
 # asan emulates weak functions from DLLs requires NOICF
-append_list_if(MSVC "/DEBUG;/OPT:NOICF" ASAN_DYNAMIC_LINK_FLAGS)
+append_list_if(MSVC "LINKER:/DEBUG;LINKER:/OPT:NOICF" ASAN_DYNAMIC_LINK_FLAGS)
 
 set(ASAN_DYNAMIC_LIBS
   ${COMPILER_RT_UNWINDER_LINK_LIBS}

@barcharcraz
Copy link
Contributor

This lgtm, although I don't know if it's actually going to make asan work with the intel toolchain.

What linker do they use?

@Maetveis
Copy link
Contributor Author

Maetveis commented Dec 4, 2024

This lgtm, although I don't know if it's actually going to make asan work with the intel toolchain.

Do you mean will it make an asan runtime library built with the intel toolchain work, or will it make -fsanitize=address work with the intel compiler? I think the answer to both should be yes, but I'm not 100% certain. This change was motivated by our (I'm a developer for ICX) internal testing showing failures for asan unitests.

What linker do they use?

MSVC's link.exe by default, though some compiler options (for example LTO and offloading) implicitly cause lld-link to be used instead, I don't know if -fsanitize=address is among them.

@Maetveis Maetveis merged commit bba2507 into llvm:main Dec 4, 2024
10 of 11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Dec 13, 2024

LLVM Buildbot has detected a new failure on builder clang-s390x-linux-multistage running on systemz-1 while building compiler-rt at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/98/builds/749

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'libFuzzer-s390x-default-Linux :: fuzzer-timeout.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer  /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
RUN: at line 2: /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer  /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/TimeoutEmptyTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutEmptyTest
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/TimeoutEmptyTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutEmptyTest
RUN: at line 3: not  /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 2>&1 | FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=TimeoutTest
+ not /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1
+ FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=TimeoutTest
RUN: at line 12: not  /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/hi.txt 2>&1 | FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=SingleInputTimeoutTest
+ not /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/hi.txt
+ FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=SingleInputTimeoutTest
RUN: at line 16: /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 -timeout_exitcode=0
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 -timeout_exitcode=0
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3469040259
INFO: Loaded 1 modules   (13 inline 8-bit counters): 13 [0x2aa16950e70, 0x2aa16950e7d), 
INFO: Loaded 1 PC tables (13 PCs): 13 [0x2aa16950e80,0x2aa16950f50), 
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2	INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 31Mb
#1581	NEW    cov: 3 ft: 3 corp: 2/2b lim: 17 exec/s: 0 rss: 32Mb L: 1/1 MS: 4 ChangeByte-ChangeByte-ChangeBit-ChangeBit-
#1602	NEW    cov: 4 ft: 4 corp: 3/4b lim: 17 exec/s: 0 rss: 32Mb L: 2/2 MS: 1 CrossOver-
#12568	NEW    cov: 5 ft: 5 corp: 4/6b lim: 122 exec/s: 0 rss: 32Mb L: 2/2 MS: 1 InsertByte-
#12584	NEW    cov: 6 ft: 6 corp: 5/10b lim: 122 exec/s: 0 rss: 32Mb L: 4/4 MS: 1 CrossOver-
#13283	REDUCE cov: 6 ft: 6 corp: 5/9b lim: 128 exec/s: 0 rss: 32Mb L: 3/3 MS: 4 ChangeByte-ChangeByte-ShuffleBytes-EraseBytes-
ALARM: working on the last Unit for 1 seconds
       and the timeout value is 1 (use -timeout=N to change)
MS: 2 InsertByte-EraseBytes-; base unit: bd92224885cdd873ccf2a5e035d00607bf7ccf62
0x48,0x69,0x21,
Hi!
artifact_prefix='./'; Test unit written to ./timeout-c0a0ad26a634840c67a210fefdda76577b03a111
Base64: SGkh
==3609606== ERROR: libFuzzer: timeout after 1 seconds
/home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/stage1/./bin/llvm-symbolizer: error: 'linux-vdso64.so.1': No such file or directory
    #0 0x02aa168c93a5 in __sanitizer_print_stack_trace /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/asan/asan_stack.cpp:87:3
    #1 0x02aa167f8687 in fuzzer::PrintStackTrace() /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerUtil.cpp:210:5
    #2 0x02aa167d3645 in fuzzer::Fuzzer::AlarmCallback() /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:304:5
    #3 0x03ffaddfe47f  (linux-vdso64.so.1+0x47f) (BuildId: fe1a17fa990b2bd35ffa9881eecf3133964c4a96)
    #4 0x02aa167f6051 in Popcountll /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerBuiltins.h:29:54
    #5 0x02aa167f6051 in HandleCmp<unsigned int> /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp:389:30
    #6 0x02aa167f6051 in __sanitizer_cov_trace_const_cmp4 /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp:513:15
    #7 0x02aa1690db61 in LLVMFuzzerTestOneInput /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp:20:16
    #8 0x02aa167d6125 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
    #9 0x02aa167d4845 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7
    #10 0x02aa167d752b in fuzzer::Fuzzer::MutateAndTestOne() /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:765:19
    #11 0x02aa167d8627 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) /home/uweigand/sandbox/buildbot/clang-s390x-linux-multistage/llvm/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:910:5
...

@Maetveis Maetveis deleted the icx-link-flags-compiler-rt branch December 17, 2024 09:21
@BukeBeyond
Copy link

BukeBeyond commented May 17, 2025

These lines in compiler-rt/CMakeLists.txt:763, Break Windows build of compiler-rt with:
llvm-ar.exe: error: -Xlinker; option not supported on non AIX OS

CMAKE_STATIC_LINKER_FLAGS are for Static .lib/.a archives given to llvm-ar , which does not accept "-Xlinker", and thus, terminate the build. CMAKE_CXX_LINKER_WRAPPER_FLAG contains -Xlinker which CMake provides from platform defaults. This is used when going through the Compiler for linking, and should not be included in the Linker flags themselves.

The correct command is:
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4221")

Another problem is:
if (CMAKE_LINKER MATCHES "link.exe$")
which matches both link.exe and lld-link.exe. In Windows, the case of file path does not matter.
Thus, this is more correct:

string(TOLOWER "${CMAKE_LINKER}" LinkerLowercase)
if (LinkerLowercase MATCHES [[(^|[/\\])link\.exe$]])

@Maetveis
Copy link
Contributor Author

CMAKE_CXX_LINKER_WRAPPER_FLAG contains -Xlinker which CMake provides from platform defaults.

Which version of CMake are you using? What exactly is the C++ compiler? At the time of writing this code CMAKE_CXX_LINKER_WRAPPER_FLAG was always empty for clang-cl and cl.exe, and only set for the intel compiler (icx).

@Maetveis
Copy link
Contributor Author

CMAKE_CXX_LINKER_WRAPPER_FLAG contains -Xlinker which CMake provides from platform defaults.

Which version of CMake are you using? What exactly is the C++ compiler? At the time of writing this code CMAKE_CXX_LINKER_WRAPPER_FLAG was always empty for clang-cl and cl.exe, and only set for the intel compiler (icx).

Actually can you file an issue with a full reproducer? I can take a look at it then.

@BukeBeyond
Copy link

CMAKE_CXX_LINKER_WRAPPER_FLAG contains -Xlinker which CMake provides from platform defaults.

Which version of CMake are you using? What exactly is the C++ compiler? At the time of writing this code CMAKE_CXX_LINKER_WRAPPER_FLAG was always empty for clang-cl and cl.exe, and only set for the intel compiler (icx).

Actually can you file an issue with a full reproducer? I can take a look at it then.

I tested with Cmake 3.29.4 and the latest 4.0.2. I also tested with clang and clang-cl as the compiler. Here is the
CMakeCache.txt with the build settings.

Here’s my latest understanding of the issue:

For .exe and .dll builds, CMake lets the Compiler handle the linking. In this case, CMAKE_CXX_LINKER_WRAPPER_FLAG (e.g., -Xlinker) is given to the Compiler, to forward the Linker flags.

However for Static libraries (.lib / .a), CMake directly calls llvm-ar or lib.exe, bypassing the Compiler. Therefore, CMAKE_STATIC_LINKER_FLAGS are passed as-is — and should not include CMAKE_CXX_LINKER_WRAPPER_FLAG, which only makes sense when going through the Compiler.

That’s why this line is incorrect:
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${CMAKE_CXX_LINKER_WRAPPER_FLAG}/IGNORE:4221")
This gives -Xlinker or /link directly to the the static librarian llvm-ar.exe (or lib.exe) causing a build failure.

I suspect that in your testing, either: CMAKE_CXX_LINKER_WRAPPER_FLAG was empty, or The conditional wrapping the above line didn’t fire (perhaps due to CMAKE_LINKER MATCHES "link.exe$" being false).
To help debug this, I would insert the following after the conditional, in compiler-rt/CMakeLists.txt around line 780:

message(STATUS "SAY: ${CMAKE_LINKER}")
message(STATUS "SAY: ${CMAKE_CXX_LINKER_WRAPPER_FLAG}")

Thankfully, running ninja on an already built LLVM, will not retrigger a whole new build, and you can test just the compiler-rt CMake quickly.

@Maetveis
Copy link
Contributor Author

I tested with Cmake 3.29.4 and the latest 4.0.2. I also tested with clang and clang-cl as the compiler. Here is the CMakeCache.txt with the build settings.

Where is LLVM_HOST_TRIPLE=x86_64-pc-win32 coming from? Are you setting that explicitly during configure? I would expect it to be x86_64-pc-windows-msvc.
Normally the runtimes sub-build of compiler-rt would use the newly built clang-cl on windows, and not clang as I suspect what's happening in your case.

However for Static libraries (.lib / .a), CMake directly calls llvm-ar or lib.exe, bypassing the Compiler. Therefore, CMAKE_STATIC_LINKER_FLAGS are passed as-is — and should not include CMAKE_CXX_LINKER_WRAPPER_FLAG, which only makes sense when going through the Compiler.

That differs between compiler to compiler. For clang-cl, MSVC and clang you're correct, but for the Intel Compiler icx, linking static libraries also goes through the compiler.

That said I'm aware that CMAKE_CXX_LINKER_WRAPPER_FLAG is not the correct variable to use in CMAKE_STATIC_LINKER_FLAGS. From CMake 4.0 onwards there is CMAKE_CXX_ARCHIVER_WRAPPER_FLAG, but LLVM's minimum supported version is 3.20.

So this PR I probably broke building compiler-rt with clang (not clang-cl) on Windows, which is not something I was aware of anyone using. I'll see if I can reproduce and fix that.

@Maetveis Maetveis self-assigned this May 19, 2025
@Maetveis
Copy link
Contributor Author

So this PR I probably broke building compiler-rt with clang (not clang-cl) on Windows, which is not something I was aware of anyone using. I'll see if I can reproduce and fix that.

So I can reproduce the linker failure, but I'm also getting other failures too, notably this one for example:

D:/iusers/gergelym/llvm-project/compiler-rt/lib/builtins/mulxc3.c:20:35: error: unknown type name 'xf_float'
   20 | COMPILER_RT_ABI Lcomplex __mulxc3(xf_float __a, xf_float __b, xf_float __c,

I don't think compiler-rt ever compiled cleanly when using clang (instead of clang-cl) on Windows. It is as the rest of LLVM not tested this way. @BukeBeyond I would encourage you to figure out why the runtimes build is being set up this way, instead of trying to fix compiler-rt with clang.

@BukeBeyond
Copy link

I don't think compiler-rt ever compiled cleanly when using clang (instead of clang-cl) on Windows. It is as the rest of LLVM not tested this way. @BukeBeyond I would encourage you to figure out why the runtimes build is being set up this way, instead of trying to fix compiler-rt with clang.

Thank you for your diligence on the matter!

At LLVM 18 and 19, I was using able to build clang, clang-tools-extra and compiler-rt with just clang on windows. In 20 and 21, most executables built, but clangd would run and but crash in vs code. Also the Clspv project, which is heavily based on LLVM, the debug builds were fine, but in the release build, clspv.exe would crash right away (during global variable construction).

We wish LLVM became more independent of MS tools, and would be able to build itself on windows using just clang and lld-link. But that is not the case in V20+. I have tried to replicate the major internal flags of of clang-cl for clang, but have not succeeded yet.

@Maetveis
Copy link
Contributor Author

We wish LLVM became more independent of MS tools, and would be able to build itself on windows using just clang and lld-link. But that is not the case in V20+. I have tried to replicate the major internal flags of of clang-cl for clang, but have not succeeded yet.

I'm not sure I follow exactly, clang-cl shouldn't depend on any more MS tools than clang, it is just a different command line in the end. Anyway if you wish to work on getting llvm buildable with clang instead of clang-cl then I can offer to review patches, this is a topic I had the misfortune of looking at quite a lot :).

@BukeBeyond
Copy link

BukeBeyond commented May 19, 2025

clang-cl shouldn't depend on any more MS tools than clang, it is just a different command line in the end. Anyway if you wish to work on getting llvm buildable with clang instead of clang-cl then I can offer to review patches, this is a topic I had the misfortune of looking at quite a lot :).

Cmake before 3.31, looks for and tests with ms mt.exe during setup, even when not used for LLVM, and now it finds llvm-mt.exe instead!

I also renamed ms link.exe away, and clang-cl seems to be happy without it, using lld-link. So -fuse-ld=lld-link seems unnecessary.

We may finally have ms independance building LLVM for windows!. This is great, because we may build it on a linux machine with just the ms includes and the .lib files. At least in theory, and without the ms marketing and lawyers involved. :-)

Clang-cl behavior seems to be a lot more than the driver translating flags and setting different defaults. Cmake and its scripts behave differently in this mode, and give different flags (like /D_WINDOWS), that Cmake Clang mode does not. It also seems, Clang internals detect IsCLMode() and behave differently more than just the flags. Replicating all these settings to find a clang match is time consuming, because even with successful builds that take a while, produced exes may crash.

It was nice to be able build LLVM upto 19 with Clang only. I like the purity of it, vs all these variant front ends. Relying on clang-cl perpetuates and accumulates archaic complexity going forward. I wish official build tests included LLVM windows with Clang. The problems introduced in 20 and 21 would have been caught early.

-DLLVM_HOST_TRIPLE=x86_64-pc-win32 is still working here, but it seems to be one of those abandoned settings, partially ming, partially msvc, which noone uses! I do remember fixing another compiler-rt problem because of it. I will correct it to x86_64-pc-windows-msvc. Thank you for catching it.

Cmake is horrors as a language from the days before Ninja existed and Python took off. We use a custom builder in Python and Ninja. In an ideal world, LLVM would migrate to something more modern than Cmake.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants