diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 5745e4b38b826..359de8042833a 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -5457,3 +5457,76 @@ Restrictions and Limitations compared to Clang Strict aliasing (TBAA) is always off by default in clang-cl whereas in clang, strict aliasing is turned on by default for all optimization levels. For more details, see :ref:`Strict aliasing `. + +Using clang/clang++ with MSVC Targets +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While ``clang-cl`` emulates the MSVC compiler interface, users may prefer to invoke ``clang`` or ``clang++`` directly for greater control and platform consistency. When targeting MSVC environments, Clang supports the use of ``--target=`` and ``--sysroot=`` following the same conventions as Unix-style cross-compilation. + +This approach avoids reliance on a Windows environment, Wine, or environmental variables, instead using a predictable and portable sysroot layout: + +Headers +------- + +- Windows + CRT headers: ``include/`` + +- C++ standard library headers (selected via ``-stdlib=``): + + - ``-stdlib=msstl`` → ``include/c++/msstl`` + Microsoft STL (MSVC's standard library implementation) + + - ``-stdlib=libc++`` → ``include/c++/v1`` + LLVM libc++ (Clang's standard library implementation) + + - ``-stdlib=libstdc++`` → ``include/c++/`` (e.g. ``16.0.0``) + GNU libstdc++ (GCC's standard library implementation) + +Library Naming Conventions +-------------------------- + +When targeting ``${cpu}-unknown-windows-msvc``, the naming of runtime libraries differs from GNU-style targets: + +- **LLVM libc++**: + - MSVC target: ``c++.dll``, ``c++.lib`` + - GNU target: ``libc++.dll``, ``libc++.a`` + +- **GNU libstdc++**: + - MSVC target: ``stdc++-6.dll``, ``stdc++.lib`` + - GNU target: ``libstdc++-6.dll``, ``libstdc++.a`` + +These naming conventions reflect platform-specific linker and runtime expectations. The MSVC target omits the ``lib`` prefix and uses `.lib` import libraries, while GNU targets retain the traditional Unix-style naming. + +Libraries +--------- + +The sysroot must contain libraries in the following fallback order: + +1. ``lib/${cpu}-unknown-windows-msvc`` +2. ``lib/`` + +Example for ``x86_64-unknown-windows-msvc``: +``lib/x86_64-unknown-windows-msvc`` → ``lib/`` + +This structure allows toolchains to support both target-specific and shared libraries, enabling clean fallback behavior and simplifying multi-target packaging. + +Binaries +-------- + +The sysroot must also contain binaries in the following fallback order: + +1. ``bin/${cpu}-unknown-windows-msvc`` +2. ``bin/`` + +Example for ``x86_64-unknown-windows-msvc``: +``bin/x86_64-unknown-windows-msvc`` → ``bin/`` + +This layout supports future scenarios such as universal binaries and ensures consistent tool resolution across architectures. + +Case Sensitivity +---------------- + +All header and library paths must use lowercase file names. This ensures compatibility across case-sensitive filesystems such as Linux and macOS, and matches the behavior of ``mingw-w64-crt``. Windows itself is case-insensitive, but relying on mixed-case paths can lead to portability issues. + +This layout is fully compatible with Clang’s standard sysroot resolution logic and requires no MSVC-specific flags. It enables clean cross-compilation workflows and portable toolchain packaging. + +For a reference implementation, see `windows-msvc-sysroot `_. diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 1425714d34110..89b7728836420 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -94,20 +94,14 @@ class ToolChain { using path_list = SmallVector; enum CXXStdlibType { - CST_Libcxx, - CST_Libstdcxx + CST_Libcxx, // LLVM libc++ + CST_Libstdcxx, // GNU libstdc++ + CST_Msstl, // MSVC STL }; - enum RuntimeLibType { - RLT_CompilerRT, - RLT_Libgcc - }; + enum RuntimeLibType { RLT_CompilerRT, RLT_Libgcc, RLT_Vcruntime }; - enum UnwindLibType { - UNW_None, - UNW_CompilerRT, - UNW_Libgcc - }; + enum UnwindLibType { UNW_None, UNW_CompilerRT, UNW_Libgcc, UNW_Vcruntime }; enum class UnwindTableLevel { None, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 40ea513e85427..fecc95746d87b 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2588,6 +2588,8 @@ bool Driver::HandleImmediateArgs(Compilation &C) { case ToolChain::RLT_Libgcc: llvm::outs() << GetFilePath("libgcc.a", TC) << "\n"; break; + default: + break; } return false; } @@ -6609,6 +6611,48 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const { return std::string(Name); } +static std::optional +CxxModulePathEvaluate(const Driver &D, const ToolChain &TC, + ToolChain::CXXStdlibType cxxstdlib, const char *library) { + const char *modulejsonfilename = "modules.json"; + switch (cxxstdlib) { + case ToolChain::CST_Libcxx: { + // Note when there are multiple flavours of libc++ the module json needs + // to look at the command-line arguments for the proper json. These + // flavours do not exist at the moment, but there are plans to provide a + // variant that is built with sanitizer instrumentation enabled. + + // For example + // const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs()); + // if (Sanitize.needsAsanRt()) + // modulejsonfilename = "libc++.modules-asan.json"; + // modulejsonfilename = "libc++.modules.json"; + modulejsonfilename = "libc++.modules.json"; + break; + } + case ToolChain::CST_Libstdcxx: { + modulejsonfilename = "libstdc++.modules.json"; + break; + } + default: { + break; + } + } + + if (library == nullptr) { + library = modulejsonfilename; + } + std::string lib = D.GetFilePath(library, TC); + + SmallString<128> path(lib.begin(), lib.end()); + llvm::sys::path::remove_filename(path); + llvm::sys::path::append(path, modulejsonfilename); + if (TC.getVFS().exists(path)) + return static_cast(path); + + return {}; +} + std::string Driver::GetStdModuleManifestPath(const Compilation &C, const ToolChain &TC) const { std::string error = ""; @@ -6616,56 +6660,30 @@ std::string Driver::GetStdModuleManifestPath(const Compilation &C, if (C.getArgs().hasArg(options::OPT_nostdlib)) return error; - switch (TC.GetCXXStdlibType(C.getArgs())) { + auto cxxstdlib = TC.GetCXXStdlibType(C.getArgs()); + switch (cxxstdlib) { case ToolChain::CST_Libcxx: { - auto evaluate = [&](const char *library) -> std::optional { - std::string lib = GetFilePath(library, TC); - - // Note when there are multiple flavours of libc++ the module json needs - // to look at the command-line arguments for the proper json. These - // flavours do not exist at the moment, but there are plans to provide a - // variant that is built with sanitizer instrumentation enabled. - - // For example - // StringRef modules = [&] { - // const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs()); - // if (Sanitize.needsAsanRt()) - // return "libc++.modules-asan.json"; - // return "libc++.modules.json"; - // }(); - - SmallString<128> path(lib.begin(), lib.end()); - llvm::sys::path::remove_filename(path); - llvm::sys::path::append(path, "libc++.modules.json"); - if (TC.getVFS().exists(path)) - return static_cast(path); - - return {}; - }; - - if (std::optional result = evaluate("libc++.so"); result) + if (std::optional result = + CxxModulePathEvaluate(*this, TC, cxxstdlib, "libc++.so"); + result) return *result; - return evaluate("libc++.a").value_or(error); + return CxxModulePathEvaluate(*this, TC, cxxstdlib, "libc++.a") + .value_or(error); } case ToolChain::CST_Libstdcxx: { - auto evaluate = [&](const char *library) -> std::optional { - std::string lib = GetFilePath(library, TC); - - SmallString<128> path(lib.begin(), lib.end()); - llvm::sys::path::remove_filename(path); - llvm::sys::path::append(path, "libstdc++.modules.json"); - if (TC.getVFS().exists(path)) - return static_cast(path); - - return {}; - }; - - if (std::optional result = evaluate("libstdc++.so"); result) + if (std::optional result = + CxxModulePathEvaluate(*this, TC, cxxstdlib, "libstdc++.so"); + result) return *result; - return evaluate("libstdc++.a").value_or(error); + return CxxModulePathEvaluate(*this, TC, cxxstdlib, "libstdc++.a") + .value_or(error); + } + + default: { + return CxxModulePathEvaluate(*this, TC, cxxstdlib, nullptr).value_or(error); } } diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 3d5cac62afe01..c3cc664536cdf 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1330,6 +1330,8 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( runtimeLibType = ToolChain::RLT_CompilerRT; else if (LibName == "libgcc") runtimeLibType = ToolChain::RLT_Libgcc; + else if (LibName == "vcruntime") + runtimeLibType = ToolChain::RLT_Vcruntime; else if (LibName == "platform") runtimeLibType = GetDefaultRuntimeLibType(); else { @@ -1368,6 +1370,8 @@ ToolChain::UnwindLibType ToolChain::GetUnwindLibType( unwindLibType = ToolChain::UNW_CompilerRT; } else if (LibName == "libgcc") unwindLibType = ToolChain::UNW_Libgcc; + else if (LibName == "vcruntime") + unwindLibType = ToolChain::UNW_Vcruntime; else { if (A) getDriver().Diag(diag::err_drv_invalid_unwindlib_name) @@ -1391,6 +1395,8 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ cxxStdlibType = ToolChain::CST_Libcxx; else if (LibName == "libstdc++") cxxStdlibType = ToolChain::CST_Libstdcxx; + else if (LibName == "msstl") + cxxStdlibType = ToolChain::CST_Msstl; else if (LibName == "platform") cxxStdlibType = GetDefaultCXXStdlibType(); else { @@ -1546,6 +1552,10 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, case ToolChain::CST_Libstdcxx: CmdArgs.push_back("-lstdc++"); break; + + case ToolChain::CST_Msstl: + // MSVC STL does not need to add -l + break; } } diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 066b59305fe3f..9cd1e956a30cf 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -457,6 +457,8 @@ void AIX::AddClangCXXStdlibIncludeArgs( CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__"); return; } + default: + break; } llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); @@ -473,9 +475,11 @@ void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, CmdArgs.push_back("-lc++experimental"); CmdArgs.push_back("-lc++abi"); return; + default: + break; } - llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); + llvm_unreachable("Unexpected C++ library type"); } // This function processes all the mtocdata options to build the final diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index 9b7f58c392885..cb996ea8d64f1 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -477,10 +477,14 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, AddCXXIncludePath(P); break; } - case ToolChain::CST_Libstdcxx: + case ToolChain::CST_Libstdcxx: { addLibStdCxxIncludePaths(DriverArgs, CC1Args); break; } + default: { + break; + } + } std::string SysRootDir(computeSysRoot()); if (SysRootDir.empty()) @@ -526,6 +530,8 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } break; } + default: + break; } } } @@ -648,6 +654,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, TC.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object); break; } + default: + return; } CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTBegin))); } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 16cc1db0a2235..d270bb3513ba5 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2398,6 +2398,8 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-lunwind"); } break; + default: + break; } if (AsNeeded) @@ -2446,6 +2448,8 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, } else AddLibgcc(TC, D, CmdArgs, Args); break; + default: + break; } // On Android, the unwinder uses dl_iterate_phdr (or one of diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index d2356ebdfa86c..ac31eeec9cb0e 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -26,6 +26,7 @@ #include "llvm/TargetParser/TargetParser.h" #include "llvm/TargetParser/Triple.h" #include // ::getenv +#include using namespace clang::driver; using namespace clang::driver::tools; @@ -2748,8 +2749,11 @@ void AppleMachO::AddClangCXXStdlibIncludeArgs( llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); - switch (GetCXXStdlibType(DriverArgs)) { - case ToolChain::CST_Libcxx: { + auto cxxstdlib = GetCXXStdlibType(DriverArgs); + switch (cxxstdlib) { + case ToolChain::CST_Libcxx: + [[fallthrough]]; + case ToolChain::CST_Msstl: { // On Darwin, libc++ can be installed in one of the following places: // 1. Alongside the compiler in /../include/c++/v1 // 2. In a SDK (or a custom sysroot) in /usr/include/c++/v1 @@ -2763,8 +2767,14 @@ void AppleMachO::AddClangCXXStdlibIncludeArgs( // Get from '/bin' to '/include/c++/v1'. // Note that InstallBin can be relative, so we use '..' instead of // parent_path. + std::string_view cxxstrname; + if (cxxstdlib == CST_Msstl) { + cxxstrname = "msstl"; + } else { + cxxstrname = "v1"; + } llvm::SmallString<128> InstallBin(getDriver().Dir); // /bin - llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); + llvm::sys::path::append(InstallBin, "..", "include", "c++", cxxstrname); if (getVFS().exists(InstallBin)) { addSystemInclude(DriverArgs, CC1Args, InstallBin); return; @@ -2775,7 +2785,7 @@ void AppleMachO::AddClangCXXStdlibIncludeArgs( // Otherwise, check for (2) llvm::SmallString<128> SysrootUsr = Sysroot; - llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1"); + llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", cxxstrname); if (getVFS().exists(SysrootUsr)) { addSystemInclude(DriverArgs, CC1Args, SysrootUsr); return; @@ -2788,10 +2798,11 @@ void AppleMachO::AddClangCXXStdlibIncludeArgs( break; } - case ToolChain::CST_Libstdcxx: + case ToolChain::CST_Libstdcxx: { AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args); break; } + } } void AppleMachO::AddGnuCPlusPlusIncludePaths( @@ -2885,6 +2896,9 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args, // Otherwise, let the linker search. CmdArgs.push_back("-lstdc++"); break; + + default: + break; } } diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 146dc8bbd5313..1ee885244c021 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -467,7 +467,7 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args, CmdArgs.push_back("-lc++experimental"); break; - case ToolChain::CST_Libstdcxx: + default: llvm_unreachable("invalid stdlib name"); } } diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 7616076847a2c..5252762e5f3af 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -3207,6 +3207,9 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, case ToolChain::CST_Libstdcxx: addLibStdCxxIncludePaths(DriverArgs, CC1Args); break; + + default: + break; } } diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp index 9f8b676fc7dc2..812601e7ba178 100644 --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -644,6 +644,9 @@ void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args, case ToolChain::CST_Libstdcxx: CmdArgs.push_back("-lstdc++"); break; + + default: + break; } } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index bb469ff095cd4..0da264d833e9d 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -8,6 +8,7 @@ #include "MSVC.h" #include "Darwin.h" +#include "Gnu.h" #include "clang/Config/config.h" #include "clang/Driver/CommonArgs.h" #include "clang/Driver/Compilation.h" @@ -91,50 +92,70 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-defaultlib:oldnames"); } - // If the VC environment hasn't been configured (perhaps because the user - // did not run vcvarsall), try to build a consistent link environment. If - // the environment variable is set however, assume the user knows what - // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that - // over env vars. - if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir, - options::OPT__SLASH_winsysroot)) { - // cl.exe doesn't find the DIA SDK automatically, so this too requires - // explicit flags and doesn't automatically look in "DIA SDK" relative - // to the path we found for VCToolChainPath. - llvm::SmallString<128> DIAPath(A->getValue()); - if (A->getOption().getID() == options::OPT__SLASH_winsysroot) - llvm::sys::path::append(DIAPath, "DIA SDK"); - - // The DIA SDK always uses the legacy vc arch, even in new MSVC versions. - llvm::sys::path::append(DIAPath, "lib", - llvm::archToLegacyVCArch(TC.getArch())); - CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath)); - } - if (!llvm::sys::Process::GetEnv("LIB") || - Args.hasArg(options::OPT__SLASH_vctoolsdir, - options::OPT__SLASH_vctoolsversion, - options::OPT__SLASH_winsysroot)) { - CmdArgs.push_back(Args.MakeArgString( - Twine("-libpath:") + - TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib))); - CmdArgs.push_back(Args.MakeArgString( - Twine("-libpath:") + - TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc"))); - } - if (!llvm::sys::Process::GetEnv("LIB") || - Args.hasArg(options::OPT__SLASH_winsdkdir, - options::OPT__SLASH_winsdkversion, - options::OPT__SLASH_winsysroot)) { - if (TC.useUniversalCRT()) { - std::string UniversalCRTLibPath; - if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) + auto SysRoot = TC.getDriver().SysRoot; + if (!SysRoot.empty()) { + // If we have --sysroot, then we ignore all other setings + // libpath is $SYSROOT/lib and $SYSROOT/lib/${ARCH}-unknown-windows-msvc + // For ARM64EC, the ARCH is aarch64 instead + auto triple = TC.getTriple(); + const std::string MultiarchTriple = + TC.getMultiarchTriple(TC.getDriver(), triple, SysRoot); + std::string SysRootLib = "-libpath:" + SysRoot + "/lib"; + CmdArgs.push_back(Args.MakeArgString(SysRootLib + '/' + MultiarchTriple)); + if (triple.isWindowsArm64EC()) { + triple.setArch(triple.getArch()); + const std::string NoSubArchMultiarchTriple = + TC.getMultiarchTriple(TC.getDriver(), triple, SysRoot); + CmdArgs.push_back( + Args.MakeArgString(SysRootLib + '/' + NoSubArchMultiarchTriple)); + } + CmdArgs.push_back(Args.MakeArgString(SysRootLib)); + } else { + // If the VC environment hasn't been configured (perhaps because the user + // did not run vcvarsall), try to build a consistent link environment. If + // the environment variable is set however, assume the user knows what + // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that + // over env vars. + if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir, + options::OPT__SLASH_winsysroot)) { + // cl.exe doesn't find the DIA SDK automatically, so this too requires + // explicit flags and doesn't automatically look in "DIA SDK" relative + // to the path we found for VCToolChainPath. + llvm::SmallString<128> DIAPath(A->getValue()); + if (A->getOption().getID() == options::OPT__SLASH_winsysroot) + llvm::sys::path::append(DIAPath, "DIA SDK"); + + // The DIA SDK always uses the legacy vc arch, even in new MSVC versions. + llvm::sys::path::append(DIAPath, "lib", + llvm::archToLegacyVCArch(TC.getArch())); + CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath)); + } + if (!llvm::sys::Process::GetEnv("LIB") || + Args.hasArg(options::OPT__SLASH_vctoolsdir, + options::OPT__SLASH_vctoolsversion, + options::OPT__SLASH_winsysroot)) { + CmdArgs.push_back(Args.MakeArgString( + Twine("-libpath:") + + TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib))); + CmdArgs.push_back(Args.MakeArgString( + Twine("-libpath:") + + TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc"))); + } + if (!llvm::sys::Process::GetEnv("LIB") || + Args.hasArg(options::OPT__SLASH_winsdkdir, + options::OPT__SLASH_winsdkversion, + options::OPT__SLASH_winsysroot)) { + if (TC.useUniversalCRT()) { + std::string UniversalCRTLibPath; + if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) + CmdArgs.push_back( + Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); + } + std::string WindowsSdkLibPath; + if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) CmdArgs.push_back( - Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); + Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); } - std::string WindowsSdkLibPath; - if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) - CmdArgs.push_back( - Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); } if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) @@ -435,6 +456,12 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, RocmInstallation(D, Triple, Args), SYCLInstallation(D, Triple, Args) { getProgramPaths().push_back(getDriver().Dir); + auto SysRoot = getDriver().SysRoot; + if (!SysRoot.empty()) { + // We have sysroot so we ignore all VCTools settings + return; + } + std::optional VCToolsDir, VCToolsVersion; if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) VCToolsDir = A->getValue(); @@ -657,6 +684,17 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, "include"); } + auto SysRoot = getDriver().SysRoot; + if (!SysRoot.empty()) { + const Driver &D = getDriver(); + const std::string MultiarchTriple = + getMultiarchTriple(D, getTriple(), SysRoot); + addSystemInclude(DriverArgs, CC1Args, + SysRoot + "/include/" + MultiarchTriple); + addSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); + return; + } + // Add %INCLUDE%-like directories from the -imsvc flag. for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc)) addSystemInclude(DriverArgs, CC1Args, Path); @@ -788,7 +826,22 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - // FIXME: There should probably be logic here to find libc++ on Windows. + if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, + options::OPT_nostdincxx)) + return; + if (getDriver().SysRoot.empty()) + return; + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Msstl: + addMsstlIncludePaths(DriverArgs, CC1Args); + break; + case ToolChain::CST_Libstdcxx: + addLibStdCXXIncludePaths(DriverArgs, CC1Args); + break; + case ToolChain::CST_Libcxx: + addLibCxxIncludePaths(DriverArgs, CC1Args); + break; + } } VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, @@ -1040,3 +1093,86 @@ void MSVCToolChain::addClangTargetOptions( if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_marm64x)) A->ignoreTargetSpecific(); } + +void MSVCToolChain::addMsstlIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + std::string LibPath = SysRoot + "/include"; + const std::string MultiarchTriple = + getMultiarchTriple(D, getTriple(), SysRoot); + + std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/msstl"; + addSystemInclude(DriverArgs, CC1Args, TargetDir); + + // Second add the generic one. + addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/msstl"); +} + +void MSVCToolChain::addLibCxxIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + std::string LibPath = SysRoot + "/include"; + const std::string MultiarchTriple = + getMultiarchTriple(D, getTriple(), SysRoot); + + std::string Version = detectLibcxxVersion(LibPath); + if (Version.empty()) + return; + + std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/" + Version; + addSystemInclude(DriverArgs, CC1Args, TargetDir); + + // Second add the generic one. + addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version); +} + +void MSVCToolChain::addLibStdCXXIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + // We cannot use GCCInstallationDetector here as the sysroot usually does + // not contain a full GCC installation. + // Instead, we search the given sysroot for /usr/include/xx, similar + // to how we do it for libc++. + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + std::string LibPath = SysRoot + "/include"; + const std::string MultiarchTriple = + getMultiarchTriple(D, getTriple(), SysRoot); + + // This is similar to detectLibcxxVersion() + std::string Version; + { + std::error_code EC; + Generic_GCC::GCCVersion MaxVersion = + Generic_GCC::GCCVersion::Parse("0.0.0"); + SmallString<128> Path(LibPath); + llvm::sys::path::append(Path, "c++"); + for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + if (VersionText[0] != 'v') { + auto Version = Generic_GCC::GCCVersion::Parse(VersionText); + if (Version > MaxVersion) + MaxVersion = Version; + } + } + if (MaxVersion.Major > 0) + Version = MaxVersion.Text; + } + + if (Version.empty()) + return; + + std::string TargetDir = LibPath + "/c++/" + Version + "/" + MultiarchTriple; + addSystemInclude(DriverArgs, CC1Args, TargetDir); + + // Second add the generic one. + addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version); + // Third the backward one. + addSystemInclude(DriverArgs, CC1Args, + LibPath + "/c++/" + Version + "/backward"); +} diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h index 5c17edce087c7..d992798e02d50 100644 --- a/clang/lib/Driver/ToolChains/MSVC.h +++ b/clang/lib/Driver/ToolChains/MSVC.h @@ -137,6 +137,21 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain { Tool *buildLinker() const override; Tool *buildAssembler() const override; private: + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Msstl; + } + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_Vcruntime; + } + UnwindLibType GetDefaultUnwindLibType() const override { + return ToolChain::UNW_Vcruntime; + } + void addMsstlIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + void addLibStdCXXIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; std::optional WinSdkDir, WinSdkVersion, WinSysRoot; std::string VCToolChainPath; llvm::ToolsetLayout VSLayout = llvm::ToolsetLayout::OlderVS; diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 1bb9bcfe6aab2..705b0bf6dce80 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/VirtualFileSystem.h" +#include #include using namespace clang::diag; @@ -781,22 +782,30 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( StringRef Slash = llvm::sys::path::get_separator(); - switch (GetCXXStdlibType(DriverArgs)) { - case ToolChain::CST_Libcxx: { - std::string TargetDir = (Base + "include" + Slash + getTripleString() + - Slash + "c++" + Slash + "v1") - .str(); + auto cxxstdlib = GetCXXStdlibType(DriverArgs); + switch (cxxstdlib) { + case ToolChain::CST_Libcxx: + [[fallthrough]]; + case ToolChain::CST_Msstl: { + std::string cxxincludedir = (Slash + "c++" + Slash).str(); + std::string_view cxxstrname; + if (cxxstdlib == CST_Msstl) { + cxxstrname = "msstl"; + } else { + cxxstrname = "v1"; + } + cxxincludedir.append(cxxstrname); + std::string TargetDir = + (Base + "include" + Slash + getTripleString() + cxxincludedir).str(); if (getDriver().getVFS().exists(TargetDir)) addSystemInclude(DriverArgs, CC1Args, TargetDir); addSystemInclude(DriverArgs, CC1Args, - Base + SubdirName + Slash + "include" + Slash + "c++" + - Slash + "v1"); - addSystemInclude(DriverArgs, CC1Args, - Base + "include" + Slash + "c++" + Slash + "v1"); + Base + SubdirName + Slash + "include" + cxxincludedir); + addSystemInclude(DriverArgs, CC1Args, Base + "include" + cxxincludedir); break; } - case ToolChain::CST_Libstdcxx: + case ToolChain::CST_Libstdcxx: { llvm::SmallVector, 7> CppIncludeBases; CppIncludeBases.emplace_back(Base); llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); @@ -824,6 +833,7 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( } break; } + } } static bool testTriple(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp index 00991504e97a8..b323ec523e4eb 100644 --- a/clang/lib/Driver/ToolChains/OHOS.cpp +++ b/clang/lib/Driver/ToolChains/OHOS.cpp @@ -266,8 +266,8 @@ void OHOS::AddCXXStdlibLibArgs(const ArgList &Args, CmdArgs.push_back("-lunwind"); break; - case ToolChain::CST_Libstdcxx: - llvm_unreachable("invalid stdlib name"); + default: + break; } } diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index 5054868b5ff4d..4716e255870c6 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -463,6 +463,8 @@ WebAssembly::GetCXXStdlibType(const ArgList &Args) const { return ToolChain::CST_Libcxx; else if (Value == "libstdc++") return ToolChain::CST_Libstdcxx; + else if (Value == "msstl") + return ToolChain::CST_Msstl; else getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); @@ -521,6 +523,9 @@ void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, case ToolChain::CST_Libstdcxx: addLibStdCXXIncludePaths(DriverArgs, CC1Args); break; + case ToolChain::CST_Msstl: + addMsstlIncludePaths(DriverArgs, CC1Args); + break; } } @@ -537,6 +542,8 @@ void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, case ToolChain::CST_Libstdcxx: CmdArgs.push_back("-lstdc++"); break; + default: + break; } } @@ -560,6 +567,26 @@ Tool *WebAssembly::buildLinker() const { return new tools::wasm::Linker(*this); } +void WebAssembly::addMsstlIncludePaths( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + std::string LibPath = SysRoot + "/include"; + const std::string MultiarchTriple = + getMultiarchTriple(D, getTriple(), SysRoot); + bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS); + + // First add the per-target include path if the OS is known. + if (IsKnownOs) { + std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/msstl"; + addSystemInclude(DriverArgs, CC1Args, TargetDir); + } + + // Second add the generic one. + addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/msstl"); +} + void WebAssembly::addLibCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { diff --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h index 76e0ca39bd748..2978f15dae49d 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.h +++ b/clang/lib/Driver/ToolChains/WebAssembly.h @@ -79,6 +79,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssembly final : public ToolChain { const llvm::Triple &TargetTriple, StringRef SysRoot) const override; + void addMsstlIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; void addLibStdCXXIncludePaths(const llvm::opt::ArgList &DriverArgs, diff --git a/clang/lib/Driver/ToolChains/ZOS.cpp b/clang/lib/Driver/ToolChains/ZOS.cpp index 57bcb3c306cef..5f98410eb6220 100644 --- a/clang/lib/Driver/ToolChains/ZOS.cpp +++ b/clang/lib/Driver/ToolChains/ZOS.cpp @@ -245,6 +245,8 @@ void ZOS::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, CmdArgs.push_back( Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQUNW)'")); } break; + default: + break; } } @@ -338,9 +340,9 @@ void ZOS::AddClangCXXStdlibIncludeArgs( TryAddIncludeFromPath(InstallBin, DriverArgs, CC1Args); break; } - case ToolChain::CST_Libstdcxx: + default: llvm::report_fatal_error( - "picking up libstdc++ headers is unimplemented on z/OS"); + "picking up non libc++ headers is unimplemented on z/OS"); break; } } diff --git a/clang/test/Driver/msvc-sysroot.cpp b/clang/test/Driver/msvc-sysroot.cpp new file mode 100644 index 0000000000000..29e74033e6d35 --- /dev/null +++ b/clang/test/Driver/msvc-sysroot.cpp @@ -0,0 +1,90 @@ +// RUN: %clangxx --target=x86_64-unknown-windows-msvc -### \ +// RUN: --sysroot=%S -fuse-ld=lld %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_X86_64_MSSTL %s +// COMPILE_X86_64_MSSTL: clang{{.*}}" "-cc1" +// COMPILE_X86_64_MSSTL: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_X86_64_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/x86_64-unknown-windows-msvc/c++/msstl" +// COMPILE_X86_64_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/msstl" +// COMPILE_X86_64_MSSTL: lld-link{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/x86_64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=x86_64-unknown-windows-msvc -### \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/usr -stdlib=libc++ -fuse-ld=lld %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_X86_64_LIBCXX %s +// COMPILE_X86_64_LIBCXX: clang{{.*}}" "-cc1" +// COMPILE_X86_64_LIBCXX: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_X86_64_LIBCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/x86_64-unknown-windows-msvc/c++/v1" +// COMPILE_X86_64_LIBCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/v1" +// COMPILE_X86_64_LIBCXX: lld-link{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/x86_64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx -### --target=x86_64-unknown-windows-msvc --stdlib=libstdc++ %s 2>&1 \ +// RUN: -fuse-ld=lld --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr \ +// RUN: | FileCheck -check-prefix=COMPILE_X86_64_LIBSTDCXX %s +// COMPILE_X86_64_LIBSTDCXX: "-cc1" +// COMPILE_X86_64_LIBSTDCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]" +// COMPILE_X86_64_LIBSTDCXX: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_X86_64_LIBSTDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/4.8/x86_64-unknown-windows-msvc" +// COMPILE_X86_64_LIBSTDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/4.8" +// COMPILE_X86_64_LIBSTDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/4.8/backward" +// COMPILE_X86_64_LIBSTDCXX: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" +// COMPILE_X86_64_LIBSTDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/x86_64-unknown-windows-msvc" +// COMPILE_X86_64_LIBSTDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include" +// COMPILE_X86_64_LIBSTDCXX: lld-link{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/x86_64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=aarch64-unknown-windows-msvc -### \ +// RUN: --sysroot=%S -fuse-ld=lld %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_AARCH64_MSSTL %s +// COMPILE_AARCH64_MSSTL: clang{{.*}}" "-cc1" +// COMPILE_AARCH64_MSSTL: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_AARCH64_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/aarch64-unknown-windows-msvc/c++/msstl" +// COMPILE_AARCH64_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/msstl" +// COMPILE_AARCH64_MSSTL: lld-link{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/aarch64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=arm64ec-unknown-windows-msvc -### \ +// RUN: --sysroot=%S -fuse-ld=lld %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_ARM64EC_MSSTL %s +// COMPILE_ARM64EC_MSSTL: clang{{.*}}" "-cc1" +// COMPILE_ARM64EC_MSSTL: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_ARM64EC_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/arm64ec-unknown-windows-msvc/c++/msstl" +// COMPILE_ARM64EC_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/msstl" +// COMPILE_ARM64EC_MSSTL: lld-link{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/arm64ec-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib/aarch64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=loongarch64-unknown-windows-msvc -stdlib=msstl -### \ +// RUN: --sysroot=%S -fuse-ld=lld %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_LOONGARCH64_MSSTL %s +// COMPILE_LOONGARCH64_MSSTL: clang{{.*}}" "-cc1" +// COMPILE_LOONGARCH64_MSSTL: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_LOONGARCH64_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/loongarch64-unknown-windows-msvc/c++/msstl" +// COMPILE_LOONGARCH64_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/msstl" +// COMPILE_LOONGARCH64_MSSTL: lld-link{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/loongarch64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=x86_64-unknown-windows-msvc -stdlib=msstl -### \ +// RUN: --sysroot=%S %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_X86_64_MSSTL_LINK %s +// COMPILE_X86_64_MSSTL_LINK: clang{{.*}}" "-cc1" +// COMPILE_X86_64_MSSTL_LINK: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_X86_64_MSSTL_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/x86_64-unknown-windows-msvc/c++/msstl" +// COMPILE_X86_64_MSSTL_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/msstl" +// COMPILE_X86_64_MSSTL_LINK: link.exe{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/x86_64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=loongarch64-unknown-windows-msvc -stdlib=libc++ -### \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/usr %s 2>&1 \ +// RUN: | FileCheck --check-prefix=COMPILE_LOONGARCH64_LIBCXX_LINK %s +// COMPILE_LOONGARCH64_LIBCXX_LINK: clang{{.*}}" "-cc1" +// COMPILE_LOONGARCH64_LIBCXX_LINK: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_LOONGARCH64_LIBCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/loongarch64-unknown-windows-msvc/c++/v1" +// COMPILE_LOONGARCH64_LIBCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/v1" +// COMPILE_LOONGARCH64_LIBCXX_LINK: link.exe{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/loongarch64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" + +// RUN: %clangxx --target=riscv64-unknown-windows-msvc -### --stdlib=libstdc++ %s 2>&1 \ +// RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree/usr \ +// RUN: | FileCheck -check-prefix=COMPILE_RISCV64_LIBSTDCXX_LINK %s +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-cc1" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/4.8/riscv64-unknown-windows-msvc" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/4.8" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/4.8/backward" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/riscv64-unknown-windows-msvc" +// COMPILE_RISCV64_LIBSTDCXX_LINK: "-internal-isystem" "[[SYSROOT:[^"]+]]/include" +// COMPILE_RISCV64_LIBSTDCXX_LINK: link.exe{{.*}}" "-libpath:[[SYSROOT:[^"]+]]/lib/riscv64-unknown-windows-msvc" "-libpath:[[SYSROOT:[^"]+]]/lib" diff --git a/clang/test/Driver/wasm-toolchain.cpp b/clang/test/Driver/wasm-toolchain.cpp index d7ff76cedfd10..344ec777100ad 100644 --- a/clang/test/Driver/wasm-toolchain.cpp +++ b/clang/test/Driver/wasm-toolchain.cpp @@ -111,3 +111,15 @@ // COMPILE_WALI_STDCXX: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" // COMPILE_WALI_STDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-linux-muslwali" // COMPILE_WALI_STDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include" + +// RUN: %clangxx -### --target=wasm32-wasi --stdlib=msstl %s 2>&1 \ +// RUN: --sysroot=%S \ +// RUN: | FileCheck -check-prefix=COMPILE_MSSTL %s +// COMPILE_MSSTL: "-cc1" +// COMPILE_MSSTL: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]" +// COMPILE_MSSTL: "-isysroot" "[[SYSROOT:[^"]+]]" +// COMPILE_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/c++/msstl" +// COMPILE_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/msstl" +// COMPILE_MSSTL: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include" +// COMPILE_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi" +// COMPILE_MSSTL: "-internal-isystem" "[[SYSROOT:[^"]+]]/include"