-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang][MinGW] Implement -mcrtdll option to switch crt choice #149469
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
base: main
Are you sure you want to change the base?
Conversation
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.
This implements the mingw `-mcrtdll` option recently added to gcc. This option is useful for having the compiler be in charge of crt version selection while only shipping a single copy of mingw for a multi-ABI toolchain. That said, there are various ABI dependent compiler libraries (e.g. libstdc++), so a certain degree of ABI awareness is nevertheless required in order to use this option correctly. See also llvm#149434
@llvm/pr-subscribers-clang-driver Author: Keno Fischer (Keno) ChangesThis implements the mingw See also #149434 (which this branch includes, since it touches the same code). Full diff: https://github.com/llvm/llvm-project/pull/149469.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 8a8db27490f06..3de97a0ec3955 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -393,6 +393,9 @@ def warn_hlsl_langstd_minimal :
"recommend using %1 instead">,
InGroup<HLSLDXCCompat>;
+def err_unknown_crtdll : Error<"unknown Windows/MinGW C runtime library '%0'">,
+ DefaultFatal;
+
// ClangIR frontend errors
def err_cir_to_cir_transform_failed : Error<
"CIR-to-CIR transformation failed">, DefaultFatal;
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index e43238ba683f2..46f03982a041b 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -493,6 +493,9 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
+ENUM_LANGOPT(MinGWCRTDll, WindowsCRTDLLVersion, 4, WindowsCRTDLLVersion::CRTDLL_Default, NotCompatible,
+ "MinGW specific. Controls the __MSVCRT_VERSION and related preprocessor defines.")
+
#undef LANGOPT
#undef ENUM_LANGOPT
#undef VALUE_LANGOPT
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 4c642c9e10c91..a0160017b6813 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -164,6 +164,23 @@ class LangOptionsBase {
MSVC2022_9 = 1939,
};
+ enum WindowsCRTDLLVersion {
+ CRTDLL_Default,
+ CRTDLL,
+ MSVCRT10,
+ MSVCRT20,
+ MSVCRT40,
+ MSVCRTD,
+ MSVCR70,
+ MSVCR71,
+ MSVCR80,
+ MSVCR90,
+ MSVCR100,
+ MSVCR110,
+ MSVCR120,
+ UCRT
+ };
+
enum SYCLMajorVersion {
SYCL_None,
SYCL_2017,
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d0b54a446309b..6ad978c525812 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1625,6 +1625,12 @@ defm auto_import : BoolFOption<"auto-import",
PosFlag<SetTrue, [], [], "MinGW specific. Enable code generation support for "
"automatic dllimport, and enable support for it in the linker. "
"Enabled by default.">>;
+def mcrtdll_EQ : Joined<["-"], "mcrtdll=">,
+ Group<m_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"MinGW specific. Changes preprocessor flags and "
+ "linker options to use the"
+ "specified C runtime library.">;
} // let Flags = [TargetSpecific]
// In the future this option will be supported by other offloading
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp
index e744e84a5b079..8e48228d1220f 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -141,8 +141,54 @@ static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
DefineStd(Builder, "WIN64", Opts);
Builder.defineMacro("__MINGW64__");
}
- Builder.defineMacro("__MSVCRT__");
Builder.defineMacro("__MINGW32__");
+ if (Opts.getMinGWCRTDll() == LangOptions::WindowsCRTDLLVersion::CRTDLL) {
+ Builder.defineMacro("__CRTDLL__");
+ } else {
+ Builder.defineMacro("__MSVCRT__");
+ switch (Opts.getMinGWCRTDll()) {
+ case LangOptions::WindowsCRTDLLVersion::CRTDLL_Default:
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRT10:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x100");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRT20:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x200");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRT40:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x400");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRTD:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x600");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR70:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x700");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR71:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x701");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR80:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x800");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR90:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x900");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR100:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0xA00");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR110:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0xB00");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR120:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0xC00");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::UCRT:
+ Builder.defineMacro("_UCRT");
+ break;
+ default:
+ llvm_unreachable("Unknown MinGW CRT version");
+ }
+ }
addCygMingDefines(Opts, Builder);
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fe1865888bdd0..79344f4e760d9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5970,6 +5970,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Triple.isWindowsGNUEnvironment()) {
Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
options::OPT_fno_auto_import);
+ Args.addLastArg(CmdArgs, options::OPT_mcrtdll_EQ);
}
if (Args.hasFlag(options::OPT_fms_volatile, options::OPT_fno_ms_volatile,
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 7d093d20b3dd9..7223cda83fa70 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -85,12 +85,24 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex");
- for (auto Lib : Args.getAllArgValues(options::OPT_l))
- if (StringRef(Lib).starts_with("msvcr") ||
- StringRef(Lib).starts_with("ucrt") ||
- StringRef(Lib).starts_with("crtdll"))
- return;
- CmdArgs.push_back("-lmsvcrt");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mcrtdll_EQ)) {
+ std::string mcrtdll = (Twine("-l") + A->getValue()).str();
+ CmdArgs.push_back(Args.MakeArgStringRef(mcrtdll));
+ } else {
+ for (auto Lib : Args.getAllArgValues(options::OPT_l))
+ if (StringRef(Lib).starts_with("msvcr") ||
+ StringRef(Lib).starts_with("ucrt") ||
+ 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");
+ }
}
void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b9f75796ecc16..26d05bc419ccb 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4705,6 +4705,44 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}
+ // Process MinGW -mcrtdll option
+ if (Arg *A = Args.getLastArg(OPT_mcrtdll_EQ)) {
+ Opts.MinGWCRTDll =
+ llvm::StringSwitch<enum LangOptions::WindowsCRTDLLVersion>(
+ A->getValue())
+ .StartsWithLower("crtdll",
+ LangOptions::WindowsCRTDLLVersion::CRTDLL)
+ .StartsWithLower("msvcrt10",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT10)
+ .StartsWithLower("msvcrt20",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT20)
+ .StartsWithLower("msvcrt40",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT40)
+ .StartsWithLower("msvcr40",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT40)
+ .StartsWithLower("msvcrtd",
+ LangOptions::WindowsCRTDLLVersion::MSVCRTD)
+ .StartsWithLower("msvcr70",
+ LangOptions::WindowsCRTDLLVersion::MSVCR70)
+ .StartsWithLower("msvcr71",
+ LangOptions::WindowsCRTDLLVersion::MSVCR71)
+ .StartsWithLower("msvcr80",
+ LangOptions::WindowsCRTDLLVersion::MSVCR80)
+ .StartsWithLower("msvcr90",
+ LangOptions::WindowsCRTDLLVersion::MSVCR90)
+ .StartsWithLower("msvcr100",
+ LangOptions::WindowsCRTDLLVersion::MSVCR100)
+ .StartsWithLower("msvcr110",
+ LangOptions::WindowsCRTDLLVersion::MSVCR110)
+ .StartsWithLower("msvcr120",
+ LangOptions::WindowsCRTDLLVersion::MSVCR120)
+ .StartsWithLower("ucrt", LangOptions::WindowsCRTDLLVersion::UCRT)
+ .Default(LangOptions::WindowsCRTDLLVersion::CRTDLL_Default);
+ if (Opts.MinGWCRTDll == LangOptions::WindowsCRTDLLVersion::CRTDLL_Default) {
+ Diags.Report(diag::err_unknown_crtdll) << A->getValue();
+ }
+ }
+
return Diags.getNumErrors() == NumErrorsBefore;
}
diff --git a/clang/test/Driver/mingw-mcrtdll.c b/clang/test/Driver/mingw-mcrtdll.c
new file mode 100644
index 0000000000000..4558628766169
--- /dev/null
+++ b/clang/test/Driver/mingw-mcrtdll.c
@@ -0,0 +1,30 @@
+// RUN: %clang -v --target=x86_64-w64-mingw32 -### %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=msvcr90 -### %s 2>&1 | FileCheck -check-prefix=MSVCR90 %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=msvcr90_suffix -### %s 2>&1 | FileCheck -check-prefix=MSVCR90_SUFFIX %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=ucrt -### %s 2>&1 | FileCheck -check-prefix=UCRT %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=ucrtbase -### %s 2>&1 | FileCheck -check-prefix=UCRTBASE %s
+
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 %s 2>&1 | FileCheck -check-prefix=DEFINE_DEFAULT %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=msvcr90 %s 2>&1 | FileCheck -check-prefix=DEFINE_MSVCR90 %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=msvcr90_suffix %s 2>&1 | FileCheck -check-prefix=DEFINE_MSVCR90 %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=ucrt %s 2>&1 | FileCheck -check-prefix=DEFINE_UCRT %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=ucrtbase %s 2>&1 | FileCheck -check-prefix=DEFINE_UCRT %s
+// RUN: not %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=bad %s 2>&1 | FileCheck -check-prefix=BAD %s
+
+// DEFAULT: "-lmingwex" "-lmsvcrt"
+// DEFINE_DEFAULT: #define __MSVCRT__
+// MSVCR90: "-lmingwex" "-lmsvcr90"
+// DEFINE_MSVCR90: #define __MSVCRT_VERSION__ 0x900
+// DEFINE_MSVCR90: #define __MSVCRT__
+// MSVCR90-NOT: "-lmsvcrt"
+// MSVCR90_SUFFIX: "-lmingwex" "-lmsvcr90_suffix"
+// MSVCR90_SUFFIX-NOT: "-lmsvcrt"
+// UCRT: "-lmingwex" "-lucrt"
+// DEFINE_UCRT: #define _UCRT
+// DEFINE_UCRT-NOT: #define __MSVCRT_VERSION__
+// UCRT-NOT: "-lmsvcrt"
+// UCRTBASE: "-lmingwex" "-lucrtbase"
+// UCRTBASE-NOT: "-lmsvcrt"
+// DEFINE_CRTDLL: #define __CRTDLL__
+// DEFINE_CRTDLL-NOT: #define __MSVCRT__
+// BAD: error: unknown Windows/MinGW C runtime library 'bad'
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"
|
@llvm/pr-subscribers-clang Author: Keno Fischer (Keno) ChangesThis implements the mingw See also #149434 (which this branch includes, since it touches the same code). Full diff: https://github.com/llvm/llvm-project/pull/149469.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 8a8db27490f06..3de97a0ec3955 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -393,6 +393,9 @@ def warn_hlsl_langstd_minimal :
"recommend using %1 instead">,
InGroup<HLSLDXCCompat>;
+def err_unknown_crtdll : Error<"unknown Windows/MinGW C runtime library '%0'">,
+ DefaultFatal;
+
// ClangIR frontend errors
def err_cir_to_cir_transform_failed : Error<
"CIR-to-CIR transformation failed">, DefaultFatal;
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index e43238ba683f2..46f03982a041b 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -493,6 +493,9 @@ LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
+ENUM_LANGOPT(MinGWCRTDll, WindowsCRTDLLVersion, 4, WindowsCRTDLLVersion::CRTDLL_Default, NotCompatible,
+ "MinGW specific. Controls the __MSVCRT_VERSION and related preprocessor defines.")
+
#undef LANGOPT
#undef ENUM_LANGOPT
#undef VALUE_LANGOPT
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 4c642c9e10c91..a0160017b6813 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -164,6 +164,23 @@ class LangOptionsBase {
MSVC2022_9 = 1939,
};
+ enum WindowsCRTDLLVersion {
+ CRTDLL_Default,
+ CRTDLL,
+ MSVCRT10,
+ MSVCRT20,
+ MSVCRT40,
+ MSVCRTD,
+ MSVCR70,
+ MSVCR71,
+ MSVCR80,
+ MSVCR90,
+ MSVCR100,
+ MSVCR110,
+ MSVCR120,
+ UCRT
+ };
+
enum SYCLMajorVersion {
SYCL_None,
SYCL_2017,
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d0b54a446309b..6ad978c525812 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1625,6 +1625,12 @@ defm auto_import : BoolFOption<"auto-import",
PosFlag<SetTrue, [], [], "MinGW specific. Enable code generation support for "
"automatic dllimport, and enable support for it in the linker. "
"Enabled by default.">>;
+def mcrtdll_EQ : Joined<["-"], "mcrtdll=">,
+ Group<m_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"MinGW specific. Changes preprocessor flags and "
+ "linker options to use the"
+ "specified C runtime library.">;
} // let Flags = [TargetSpecific]
// In the future this option will be supported by other offloading
diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp
index e744e84a5b079..8e48228d1220f 100644
--- a/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/clang/lib/Basic/Targets/OSTargets.cpp
@@ -141,8 +141,54 @@ static void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
DefineStd(Builder, "WIN64", Opts);
Builder.defineMacro("__MINGW64__");
}
- Builder.defineMacro("__MSVCRT__");
Builder.defineMacro("__MINGW32__");
+ if (Opts.getMinGWCRTDll() == LangOptions::WindowsCRTDLLVersion::CRTDLL) {
+ Builder.defineMacro("__CRTDLL__");
+ } else {
+ Builder.defineMacro("__MSVCRT__");
+ switch (Opts.getMinGWCRTDll()) {
+ case LangOptions::WindowsCRTDLLVersion::CRTDLL_Default:
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRT10:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x100");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRT20:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x200");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRT40:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x400");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCRTD:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x600");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR70:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x700");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR71:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x701");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR80:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x800");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR90:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0x900");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR100:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0xA00");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR110:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0xB00");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::MSVCR120:
+ Builder.defineMacro("__MSVCRT_VERSION__", "0xC00");
+ break;
+ case LangOptions::WindowsCRTDLLVersion::UCRT:
+ Builder.defineMacro("_UCRT");
+ break;
+ default:
+ llvm_unreachable("Unknown MinGW CRT version");
+ }
+ }
addCygMingDefines(Opts, Builder);
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fe1865888bdd0..79344f4e760d9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5970,6 +5970,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Triple.isWindowsGNUEnvironment()) {
Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
options::OPT_fno_auto_import);
+ Args.addLastArg(CmdArgs, options::OPT_mcrtdll_EQ);
}
if (Args.hasFlag(options::OPT_fms_volatile, options::OPT_fno_ms_volatile,
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 7d093d20b3dd9..7223cda83fa70 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -85,12 +85,24 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex");
- for (auto Lib : Args.getAllArgValues(options::OPT_l))
- if (StringRef(Lib).starts_with("msvcr") ||
- StringRef(Lib).starts_with("ucrt") ||
- StringRef(Lib).starts_with("crtdll"))
- return;
- CmdArgs.push_back("-lmsvcrt");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mcrtdll_EQ)) {
+ std::string mcrtdll = (Twine("-l") + A->getValue()).str();
+ CmdArgs.push_back(Args.MakeArgStringRef(mcrtdll));
+ } else {
+ for (auto Lib : Args.getAllArgValues(options::OPT_l))
+ if (StringRef(Lib).starts_with("msvcr") ||
+ StringRef(Lib).starts_with("ucrt") ||
+ 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");
+ }
}
void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b9f75796ecc16..26d05bc419ccb 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4705,6 +4705,44 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
}
+ // Process MinGW -mcrtdll option
+ if (Arg *A = Args.getLastArg(OPT_mcrtdll_EQ)) {
+ Opts.MinGWCRTDll =
+ llvm::StringSwitch<enum LangOptions::WindowsCRTDLLVersion>(
+ A->getValue())
+ .StartsWithLower("crtdll",
+ LangOptions::WindowsCRTDLLVersion::CRTDLL)
+ .StartsWithLower("msvcrt10",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT10)
+ .StartsWithLower("msvcrt20",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT20)
+ .StartsWithLower("msvcrt40",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT40)
+ .StartsWithLower("msvcr40",
+ LangOptions::WindowsCRTDLLVersion::MSVCRT40)
+ .StartsWithLower("msvcrtd",
+ LangOptions::WindowsCRTDLLVersion::MSVCRTD)
+ .StartsWithLower("msvcr70",
+ LangOptions::WindowsCRTDLLVersion::MSVCR70)
+ .StartsWithLower("msvcr71",
+ LangOptions::WindowsCRTDLLVersion::MSVCR71)
+ .StartsWithLower("msvcr80",
+ LangOptions::WindowsCRTDLLVersion::MSVCR80)
+ .StartsWithLower("msvcr90",
+ LangOptions::WindowsCRTDLLVersion::MSVCR90)
+ .StartsWithLower("msvcr100",
+ LangOptions::WindowsCRTDLLVersion::MSVCR100)
+ .StartsWithLower("msvcr110",
+ LangOptions::WindowsCRTDLLVersion::MSVCR110)
+ .StartsWithLower("msvcr120",
+ LangOptions::WindowsCRTDLLVersion::MSVCR120)
+ .StartsWithLower("ucrt", LangOptions::WindowsCRTDLLVersion::UCRT)
+ .Default(LangOptions::WindowsCRTDLLVersion::CRTDLL_Default);
+ if (Opts.MinGWCRTDll == LangOptions::WindowsCRTDLLVersion::CRTDLL_Default) {
+ Diags.Report(diag::err_unknown_crtdll) << A->getValue();
+ }
+ }
+
return Diags.getNumErrors() == NumErrorsBefore;
}
diff --git a/clang/test/Driver/mingw-mcrtdll.c b/clang/test/Driver/mingw-mcrtdll.c
new file mode 100644
index 0000000000000..4558628766169
--- /dev/null
+++ b/clang/test/Driver/mingw-mcrtdll.c
@@ -0,0 +1,30 @@
+// RUN: %clang -v --target=x86_64-w64-mingw32 -### %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=msvcr90 -### %s 2>&1 | FileCheck -check-prefix=MSVCR90 %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=msvcr90_suffix -### %s 2>&1 | FileCheck -check-prefix=MSVCR90_SUFFIX %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=ucrt -### %s 2>&1 | FileCheck -check-prefix=UCRT %s
+// RUN: %clang -v --target=x86_64-w64-mingw32 -mcrtdll=ucrtbase -### %s 2>&1 | FileCheck -check-prefix=UCRTBASE %s
+
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 %s 2>&1 | FileCheck -check-prefix=DEFINE_DEFAULT %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=msvcr90 %s 2>&1 | FileCheck -check-prefix=DEFINE_MSVCR90 %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=msvcr90_suffix %s 2>&1 | FileCheck -check-prefix=DEFINE_MSVCR90 %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=ucrt %s 2>&1 | FileCheck -check-prefix=DEFINE_UCRT %s
+// RUN: %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=ucrtbase %s 2>&1 | FileCheck -check-prefix=DEFINE_UCRT %s
+// RUN: not %clang -dM -E --target=x86_64-w64-mingw32 -mcrtdll=bad %s 2>&1 | FileCheck -check-prefix=BAD %s
+
+// DEFAULT: "-lmingwex" "-lmsvcrt"
+// DEFINE_DEFAULT: #define __MSVCRT__
+// MSVCR90: "-lmingwex" "-lmsvcr90"
+// DEFINE_MSVCR90: #define __MSVCRT_VERSION__ 0x900
+// DEFINE_MSVCR90: #define __MSVCRT__
+// MSVCR90-NOT: "-lmsvcrt"
+// MSVCR90_SUFFIX: "-lmingwex" "-lmsvcr90_suffix"
+// MSVCR90_SUFFIX-NOT: "-lmsvcrt"
+// UCRT: "-lmingwex" "-lucrt"
+// DEFINE_UCRT: #define _UCRT
+// DEFINE_UCRT-NOT: #define __MSVCRT_VERSION__
+// UCRT-NOT: "-lmsvcrt"
+// UCRTBASE: "-lmingwex" "-lucrtbase"
+// UCRTBASE-NOT: "-lmsvcrt"
+// DEFINE_CRTDLL: #define __CRTDLL__
+// DEFINE_CRTDLL-NOT: #define __MSVCRT__
+// BAD: error: unknown Windows/MinGW C runtime library 'bad'
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"
|
This implements the mingw
-mcrtdll
option recently added to gcc.This option is useful for having the compiler be in charge of crt
version selection while only shipping a single copy of mingw for a
multi-ABI toolchain. That said, there are various ABI dependent compiler
libraries (e.g. libstdc++), so a certain degree of ABI awareness is
nevertheless required in order to use this option correctly.
See also #149434 (which this branch includes, since it touches the same code).