From e3dd50c14f79dca0d28e482f707849c92ec0df76 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 18 Jul 2025 01:02:00 +0000 Subject: [PATCH] [Driver][MinGW] Always put libc argument last, even if non-standard I was attempting to build openblas with clang in msys2's `ucrt64` environment (I'm aware of the `clang64` environment, but I wanted libstdc++). The openblas link failed with the following: ``` clang -march=native -mtune=native -m64 -O2 -fno-asynchronous-unwind-tables -O2 -DSMALL_MATRIX_OPT -DMS_ABI -DMAX_STACK_ALLOC=2048 -Wall -m64 -DF_INTERFACE_GFORT -DDYNAMIC_ARCH -DSMP_SERVER -DNO_WARMUP -DMAX_CPU_NUMBER=512 -DMAX_PARALLEL_NUMBER=1 -DBUILD_SINGLE=1 -DBUILD_DOUBLE=1 -DBUILD_COMPLEX=1 -DBUILD_COMPLEX16=1 -DVERSION=\"0.3.29\" -UASMNAME -UASMFNAME -UNAME -UCNAME -UCHAR_NAME -UCHAR_CNAME -DASMNAME= -DASMFNAME=_ -DNAME=_ -DCNAME= -DCHAR_NAME=\"_\" -DCHAR_CNAME=\"\" -DNO_AFFINITY -I.. libopenblas64_.def dllinit.obj \ -shared -o ../libopenblas64_.dll -Wl,--out-implib,../libopenblas64_.dll.a \ -Wl,--whole-archive ../libopenblas64_p-r0.3.29.a -Wl,--no-whole-archive -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0 -LC:/msys64/ucrt64/bin/../lib/gcc -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../.. -lgfortran -lmingwex -lmsvcrt -lquadmath -lm -lpthread -lmingwex -lmsvcrt -defaultlib:advapi32 -lgfortran -defaultlib:advapi32 -lgfortran C:/msys64/ucrt64/bin/ld: C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-pseudo-reloc.o): in function `__report_error': D:/W/B/src/mingw-w64/mingw-w64-crt/crt/pseudo-reloc.c:157:(.text+0x59): undefined reference to `abort' C:/msys64/ucrt64/bin/ld: C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-tlsthrd.o): in function `___w64_mingwthr_add_key_dtor': D:/W/B/src/mingw-w64/mingw-w64-crt/crt/tlsthrd.c:48:(.text+0xa5): undefined reference to `calloc' C:/msys64/ucrt64/bin/ld: C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-pesect.o): in function `_FindPESectionByName': D:/W/B/src/mingw-w64/mingw-w64-crt/crt/pesect.c:79:(.text+0xfd): undefined reference to `strncmp' ``` These symbols come from the `-lmingw32` dep that the driver added and are ordinarily found in `-lmsvcrt`, which got skipped here, because openblas passed `-lmsvcrt` explicitly. Since we always add these libraries at the end here, I think that clang is "at fault" (as opposed to a user or packaging mistake) and should have added some crt here. To preserve the intent of letting the user override which crt is chosen, duplicate the (first) user chosen crt `-l` into this position, although we should perhaps consider an explicit `-mcrtdll` like gcc has as well. --- clang/lib/Driver/ToolChains/MinGW.cpp | 11 +++++++++-- clang/test/Driver/mingw-msvcrt.c | 8 ++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 7d093d20b3dd9..58c59aa7f2237 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, CmdArgs.push_back("-lmoldname"); CmdArgs.push_back("-lmingwex"); - for (auto Lib : Args.getAllArgValues(options::OPT_l)) + for (auto Lib : Args.getAllArgValues(options::OPT_l)) { if (StringRef(Lib).starts_with("msvcr") || StringRef(Lib).starts_with("ucrt") || - StringRef(Lib).starts_with("crtdll")) + StringRef(Lib).starts_with("crtdll")) { + Lib = (llvm::Twine("-l") + Lib).str(); + // Respect the user's chosen crt variant, but still provide it + // again as the last linker argument, because some of the libraries + // we added above may depend on it. + CmdArgs.push_back(Args.MakeArgStringRef(Lib)); return; + } + } CmdArgs.push_back("-lmsvcrt"); } diff --git a/clang/test/Driver/mingw-msvcrt.c b/clang/test/Driver/mingw-msvcrt.c index 340ce1f57b0f8..e1648630476a0 100644 --- a/clang/test/Driver/mingw-msvcrt.c +++ b/clang/test/Driver/mingw-msvcrt.c @@ -7,10 +7,10 @@ // CHECK_DEFAULT: "-lmingwex" "-lmsvcrt" "-ladvapi32" // CHECK_DEFAULT-SAME: "-lmsvcrt" "-lkernel32" "{{.*}}crtend.o" // CHECK_MSVCR120: "-lmsvcr120" -// CHECK_MSVCR120-SAME: "-lmingwex" "-ladvapi32" +// CHECK_MSVCR120-SAME: "-lmingwex" "-lmsvcr120" "-ladvapi32" // CHECK_UCRTBASE: "-lucrtbase" -// CHECK_UCRTBASE-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRTBASE-SAME: "-lmingwex" "-lucrtbase" "-ladvapi32" // CHECK_UCRT: "-lucrt" -// CHECK_UCRT-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRT-SAME: "-lmingwex" "-lucrt" "-ladvapi32" // CHECK_CRTDLL: "-lcrtdll" -// CHECK_CRTDLL-SAME: "-lmingwex" "-ladvapi32" +// CHECK_CRTDLL-SAME: "-lmingwex" "-lcrtdll" "-ladvapi32"