[clang] Support --sysroot= for ${arch}-windows-msvc targets - #96417
[clang] Support --sysroot= for ${arch}-windows-msvc targets#96417trcrsired wants to merge 1 commit into
Conversation
|
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
|
@llvm/pr-subscribers-backend-systemz @llvm/pr-subscribers-clang-driver Author: cqwrteur (trcrsired) ChangesI think it is possible to use the same rule for msvc targets with --target= and --sysroot= See Repository: C++ standard library headers: With -stdlib=libc++, headers should be located in include/c++/v1 Libraries For example. on x86_64-windows-msvc, it should find libs in lib/x86_64-windows-msvc Full diff: https://github.com/llvm/llvm-project/pull/96417.diff 5 Files Affected:
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 1f93bd612e9b0..04535a98dd69c 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -95,18 +95,21 @@ class ToolChain {
enum CXXStdlibType {
CST_Libcxx,
- CST_Libstdcxx
+ CST_Libstdcxx,
+ CST_Stl,
};
enum RuntimeLibType {
RLT_CompilerRT,
- RLT_Libgcc
+ RLT_Libgcc,
+ RLT_Vcruntime
};
enum UnwindLibType {
UNW_None,
UNW_CompilerRT,
- UNW_Libgcc
+ UNW_Libgcc,
+ UNW_Vcruntime
};
enum class UnwindTableLevel {
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 40ab2e91125d1..b3ed8fc6de36d 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1091,6 +1091,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 {
@@ -1129,6 +1131,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)
@@ -1152,6 +1156,8 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
cxxStdlibType = ToolChain::CST_Libcxx;
else if (LibName == "libstdc++")
cxxStdlibType = ToolChain::CST_Libstdcxx;
+ else if (LibName == "stl")
+ cxxStdlibType = ToolChain::CST_Stl;
else if (LibName == "platform")
cxxStdlibType = GetDefaultCXXStdlibType();
else {
@@ -1290,6 +1296,9 @@ void ToolChain::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 ca266e3e1d1d3..bf1b6d3b9bc84 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -31,12 +31,12 @@
#include <cstdio>
#ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #define NOGDI
- #ifndef NOMINMAX
- #define NOMINMAX
- #endif
- #include <windows.h>
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
#endif
using namespace clang::driver;
@@ -95,43 +95,52 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// 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.getLastArg(options::OPT__SLASH_vctoolsdir,
- 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.getLastArg(options::OPT__SLASH_winsdkdir,
- options::OPT__SLASH_winsysroot)) {
- if (TC.useUniversalCRT()) {
- std::string UniversalCRTLibPath;
- if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
+ auto SysRoot = TC.getDriver().SysRoot;
+ if (SysRoot.empty()) {
+ 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.getLastArg(options::OPT__SLASH_vctoolsdir,
+ 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.getLastArg(options::OPT__SLASH_winsdkdir,
+ 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));
+ } else {
+ const std::string MultiarchTriple =
+ TC.getMultiarchTriple(TC.getDriver(), TC.getTriple(), SysRoot);
+ std::string SysRootLib = "-libpath:" + SysRoot + "/lib";
+ CmdArgs.push_back(Args.MakeArgString(SysRootLib + '/' + MultiarchTriple));
+ CmdArgs.push_back(Args.MakeArgString(SysRootLib));
}
if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
@@ -207,13 +216,14 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
// Make sure the dynamic runtime thunk is not optimized out at link time
// to ensure proper SEH handling.
- CmdArgs.push_back(Args.MakeArgString(
- TC.getArch() == llvm::Triple::x86
- ? "-include:___asan_seh_interceptor"
- : "-include:__asan_seh_interceptor"));
+ CmdArgs.push_back(
+ Args.MakeArgString(TC.getArch() == llvm::Triple::x86
+ ? "-include:___asan_seh_interceptor"
+ : "-include:__asan_seh_interceptor"));
// Make sure the linker consider all object files from the dynamic runtime
// thunk.
- CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
+ CmdArgs.push_back(Args.MakeArgString(
+ std::string("-wholearchive:") +
TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
} else if (DLL) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
@@ -224,7 +234,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// This is necessary because instrumented dlls need access to all the
// interface exported by the static lib in the main executable.
CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
- TC.getCompilerRT(Args, Lib)));
+ TC.getCompilerRT(Args, Lib)));
}
}
}
@@ -430,6 +440,11 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().Dir);
+ auto SysRoot = getDriver().SysRoot;
+ if (!SysRoot.empty()) {
+ return;
+ }
+
std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
VCToolsDir = A->getValue();
@@ -602,8 +617,8 @@ static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
return Version;
- const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
- nullptr);
+ const DWORD VersionSize =
+ ::GetFileVersionInfoSizeW(ClExeWide.c_str(), nullptr);
if (VersionSize == 0)
return Version;
@@ -620,7 +635,7 @@ static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
return Version;
const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
- const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
+ const unsigned Minor = (FileInfo->dwFileVersionMS) & 0xFFFF;
const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
Version = VersionTuple(Major, Minor, Micro);
@@ -647,6 +662,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);
@@ -763,12 +789,11 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// As a fallback, select default install paths.
// FIXME: Don't guess drives and paths like this on Windows.
const StringRef Paths[] = {
- "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
- "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
- "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
- "C:/Program Files/Microsoft Visual Studio 8/VC/include",
- "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
- };
+ "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
+ "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
+ "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
+ "C:/Program Files/Microsoft Visual Studio 8/VC/include",
+ "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"};
addSystemIncludes(DriverArgs, CC1Args, Paths);
#endif
}
@@ -776,6 +801,24 @@ 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_Stl:
+ addStlIncludePaths(DriverArgs, CC1Args);
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addLibStdCXXIncludePaths(DriverArgs, CC1Args);
+ break;
+ case ToolChain::CST_Libcxx:
+ addLibCxxIncludePaths(DriverArgs, CC1Args);
+ break;
+ default:
+ break;
+ }
}
VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
@@ -877,7 +920,8 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
break;
case '1':
- DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
+ DAL.AddFlagArg(A,
+ Opts.getOption(options::OPT_finline_hint_functions));
break;
case '2':
case '3':
@@ -912,11 +956,10 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
}
if (SupportsForcingFramePointer) {
if (OmitFramePointer)
- DAL.AddFlagArg(A,
- Opts.getOption(options::OPT_fomit_frame_pointer));
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
else
- DAL.AddFlagArg(
- A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
+ DAL.AddFlagArg(A,
+ Opts.getOption(options::OPT_fno_omit_frame_pointer));
} else {
// Don't warn about /Oy- in x86-64 builds (where
// SupportsForcingFramePointer is false). The flag having no effect
@@ -1027,3 +1070,86 @@ void MSVCToolChain::addClangTargetOptions(
if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_marm64x))
A->ignoreTargetSpecific();
}
+
+void MSVCToolChain::addStlIncludePaths(
+ 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++/stl";
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/stl");
+}
+
+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 3950a8ed38e8b..609ce1c738751 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -71,9 +71,7 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
return llvm::DebuggerKind::Default;
}
- unsigned GetDefaultDwarfVersion() const override {
- return 4;
- }
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
llvm::StringRef SubdirParent = "") const;
@@ -100,8 +98,8 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- bool getWindowsSDKLibraryPath(
- const llvm::opt::ArgList &Args, std::string &path) const;
+ bool getWindowsSDKLibraryPath(const llvm::opt::ArgList &Args,
+ std::string &path) const;
bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args,
std::string &path) const;
bool useUniversalCRT() const;
@@ -132,7 +130,23 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
+
private:
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Stl;
+ }
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_Vcruntime;
+ }
+ UnwindLibType GetDefaultUnwindLibType() const override {
+ return ToolChain::UNW_Vcruntime;
+ }
+ void addStlIncludePaths(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<llvm::StringRef> WinSdkDir, WinSdkVersion, WinSysRoot;
std::string VCToolChainPath;
llvm::ToolsetLayout VSLayout = llvm::ToolsetLayout::OlderVS;
diff --git a/clang/test/Driver/msvc-sysroot.cpp b/clang/test/Driver/msvc-sysroot.cpp
new file mode 100644
index 0000000000000..9e58729ec57e9
--- /dev/null
+++ b/clang/test/Driver/msvc-sysroot.cpp
@@ -0,0 +1,11 @@
+// RUN: %clangxx --target=x86_64-unknown-windows-msvc -### --sysroot=%S -fuse-ld=lld %s 2>&1 | FileCheck --check-prefix=COMPILE %s
+// COMPILE: clang{{.*}}" "-cc1"
+// COMPILE: "-isysroot" "[[SYSROOT:[^"]+]]"
+// COMPILE: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/x86_64-unknown-windows-msvc/c++/stl"
+// COMPILE: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/stl"
+
+// RUN: %clangxx --target=aarch64-unknown-windows-msvc -### --sysroot=%S -fuse-ld=lld %s 2>&1 | FileCheck --check-prefix=COMPILE %s
+// COMPILE: clang{{.*}}" "-cc1"
+// COMPILE: "-isysroot" "[[SYSROOT:[^"]+]]"
+// COMPILE: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/aarch64-unknown-windows-msvc/c++/stl"
+// COMPILE: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/stl"
|
zmodem
left a comment
There was a problem hiding this comment.
I've read half the patch so far, but wanted to ask before continuing: would it be possible (and simpler) to extend the /winsysroot support somehow to also handle --sysroot?
(It would also be easier to review if the unrelated formatting changes were removed or split to a separate PR.)
no. i do not use clang-cl. /winsysroot is not sysroot. /winsysroot is for clang-cl. not clang itself sysroot is what the usually the clang and GCC means. That is not a semantics for msvc. I have checked the code first clang does not support /winsysroot, second they have very different meanings which make them incompatible. Just use --sysroot because --sysroot matches the behavior of other platforms, including GNU variants of windows targets like x86_64-windows-gnu. BTW using --sysroot gives the same semantics for build systems like build tools cmake or xmake. |
I have avoided formatting as much as possible. However, the llvm CI does not pass if I do not format it. |
I didn't mean that you should use |
They couldn't. They mean different things.
Other toggles only work when --sysroot is null. This is a completely different setting than winsysroot and many other settings such as environmental variables. winsysroot still references environmental variable, which are completely different behavior. I suggest deprecating winsysroot completely. |
|
@zmodem Looks like clang-formatting makes you harder to review the code, I will try to use the upstream code and avoiding formatting. |
d716838 to
e3f96da
Compare
|
@zmodem Can you review it again? I have removed the formatting part here. Although I disagree with -stdlib=msstl thing. Can you check any other part that is problematic first? Ty |
|
Remove mentioning of repo url in commit |
Me too, but isn't this PR a different idea? This is about using clang with MSVC/Win SDK turned into a Unix-style sysroot, which seems like a much narrower use case. I think it would be better if the driver could work with the MSVC/SDK as-is, rather than forcing the user to change the SDK into a form that the driver likes (even if it's a "standard" form in the sense that other sysroots use it). That would probably require more work, such as supporting case-insensitive includes, but seems like it would be much user friendlier. But I won't block this if there's otherwise strong support for it. |
cross compiling is not a narrow use bro. And this PR will allow using libc++ with microsoft sdk too and unfortunately microsoft puts C headers and MSVC STL headers together. Without a UNIX style sysroot that seperates msvc stl headers into a seperate include/c++/msvcstl there is no way to get it work. |
|
FYI, MinGW can’t keep up with Windows SDK. The reason people still rely on MinGW today is largely because Windows SDK’s directory structure is very complicated for cross-compilation. This PR makes it possible for users who want to move away from MinGW to switch to Windows SDK - there’s huge potential demand in this PR. |
thank you! |
Also WOA's official aarch64-w64-mingw32-g++ is still unavailable although i have made it works. Microsoft devs pushed wrong patches to upstream. |
Yes, exactly. The discussion here conflates a lot of different concepts. It's perfectly possible to use If you want to manually specify an SDK location instead of passing it through the environment, then you can use the This new option isn't about
This already works, as far as I know - through the
Supporting case insensitive includes would indeed be nice.
Just because the PR has been up for a long time isn't a reason for cutting the discussion short - especially for something that defines new public interfaces in how Clang interacts with other toolchain components. |
|
I think the spirit of this MR is useful, allowing However, I agree with @zmodem when he says this:
@trcrsired, I don't think it was said that 'cross-compilation is a narrow scenario', instead it was 'making the Windows SDK and MSVC STL into a Unix-like sysroot' is a narrow scenario, which is broadly true. Shoehorning the Windows SDK and MSVC STL into a Unix-like layout is, in my opinion, too much to ask of the user. We can support this scenario, I won't say no either, but I believe the proper way is to get Clang to accept the layout as-is from the Build Tools installer (for example). Surely The most obvious, first-party way to set up an MSVC ABI + MSVC STL cross-compile environment on Unix-like environments would be to use the above installer on Windows itself or maybe WINE and install it to a case-insensitive FS, mount that filesystem on the Unix-like host, and then write I'm not sure this functionality is present in the current PR, which is what I discussed in the first place. There is a lot of demand for this setup, I agree, but asking the user to do this extra work is not very ergonomic (and now that the links to the external GitHub page and scripts are gone, is less discoverable as well). |
case insensitivity (similar things such as EBCDIC, wchar_t, Big endian) was a historical mistake to begin with. Let's do not make things worse by creating more fragmentations. I have said there are libraries out there (even the linux kernel header files) have case sensitive headers. You cannot really implement this without breaking code. Also the argument of packaing as UNIX style is too much ask would be true for basically any targets over there. You always need to build libc and install it to create a UNIX style sysroot. In fact even llvm itself uses UNIX style sysroot packaging on windows. mingw-w64 does exact the same thing. UNIX style sysroot + case insensitivity. All i did is to match the behavior of mingw-w64 which is exactly what we should be doing. |
But this PR does precisely that, by expecting a non-standard directory layout for If the goal is to get |
Standard clearly means POSIX standard under this context. Even microsoft has to follow POSIX (we had POSIX subsystem back then in windows). and Windows CRT followed POSIX designs too. It is the standard |
|
Even Linus Torvalds agrees with that. Please no more case insensitive mess thanks. |
POSIX is the OS standard for all OSes (including linux, windows, mac, bsd, whatever you call it) not just "for UNIX". Linux is not even UNIX. It is a common misunderstanding. Windows existence does not justifiy POSIX not being the standard for OS. Just like Americans use miles instead of kms do not mean SI is not the standard for all units. Even ISO C++ has to reserve posix namespace because it is the OS standard. |
|
I don't think POSIX or Torvalds' opinions on case insensitivity really matters here. The fact is that the Windows SDK and MSVC STL are written, delivered and expected to be used in a case-insensitive environment. We have a few choices:
|
|
Linus Torvalds @torvalds: |
MinGW is just windows using a different C++ runtime. Cygwin is not, cygwin is more like reimplementing entire user space of windows. When i use --sysroot to a UNIX style sysroot that does not find my headers, that was the real surprise to me. https://github.com/rust-cross/cargo-xwin Jake-Shadle/xwin#138 |
|
https://github.com/rust-cross/cargo-xwin Oh i remembered wrong. it was cargo-xwin that uses my windows-msvc-sysroot. |
Environmental variables to change how the functionalities are also very bad idea. There are so many things that can affect it in a very surprise way. It will also force scripts to guard them (just like a lot of scripts have to use LC_ALL="C.UTF-8" all the time). it is really bad. I really do not see what is the real opposition here giving the fact --sysroot works for both POSIX style standard sysroot and /winsysroot now and it provides libc++ support. Trying to work things around like introducing case insensitive to LLVM is a security hazard and purely just wrong (Linus Torvalds was proven right on this) and they break code (because i have shown you there are different filenames with the same case sensitive filenames in Linux kernels header files). For projects like you said "wil" that has to with their cmake scripts. CMake installs things on POSIX style too (so with llvm) on windows. I do not see what is real argument rather than poorly implemented /winsysroot to begin with. |
It is not true. Or LLVM itself won't package this way on windows. Blocking PR like this proves my point you said "cross compilation is a narrow scenario" since literally this is the only sound solution i have tested. |
But it will get easily compiled with windows-msvc-sysroot which is exactly the point here. |
What world are you living in? There is no sdcard slot on phones any more. In fact Apple is trying to create portless iphone with no ports at all. Users have been gradually losing their rights to their own property. You will own nothing and you will be happy, World economic forum 2030 Also clang/clang++ are not MSVC style (or you won't have clang-cl that accepts MSVC flags). They are GNU style frontend even for target like windows-msvc. It should follow GNU and POSIX style rules not MSVC ones. |
Feel free to have more discussions. But something like how talking about POSIX style sysroot being not the de facto standard and even llvm itself is packaged this way really leads the discussions to nowhere. It is not constructive, it does not contribute to help on i should do. I am the one who does the real hard work and it is a painfull infinite grind for me giving the fact i do not even have a job to feed myself. Case insensitive is something i strongly oppose mainly for it is known to be implemented very buggy and often security flaws. And there are real world code out there (like linux kernel headers i shown here) use header file names differ only by case. |






I think it is possible to use the same rule for msvc targets with --target= and --sysroot=
see:
https://github.com/trcrsired/windows-msvc-sysroot
Headers
Windows + CRT Headers Include Directory: include
C++ standard library headers:
(old: With -stdlib=stl, headers should be located in include/c++/stl)
-stdlib=msstl, headers should be located in include/c++/msstl
With -stdlib=libc++, headers should be located in include/c++/v1
With -stdlib=libstdc++, headers should be located in include/c++/16.0.0 (GCC version)
Libraries
Libraries should be placed in lib/$TRIPLET
Bins
Bins should be placed in bin/$TRIPLET
For example. on x86_64-unknown-windows-msvc, it should find libs in lib/x86_64-unknown-windows-msvc