-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
[clang] Support --sysroot= for ${arch}-windows-msvc targets #96417
base: main
Are you sure you want to change the base?
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-clang @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"
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
Backing up a bit, where is the sysroot directory that this I thought this was for pointing clang to an MSVC installation, similar to clang-cl's /winsysroot, but it looks like the code is doing something else. |
https://github.com/trcrsired/windows-msvc-sysroot/tree/main I extract all files from msvc installations and windows SDK and put them in the format of what a normal sysroot would do on other platforms. Basically, unify the behavior with another platform. |
Isn't it better to point Clang at MSVC and the Windows SDK as they're normally installed? This patch seems specific to your custom setup, not something that would be useful for others. |
Windows SDK is not portable since it does not follow the Unix naming convention. I need to cross-compile Windows Binaries from Linux. Using Windows SDK is completely useless. Plus, the headers and libs are uppercase in Windows SDK, which is not the same header name as mingw-w64 and wine's headers. This creates huge headaches since the Linux filesystem is case-sensitive while Windows is not. Windows SDK is pointless. No. I just create the same file structure as clang usually uses. Plus clang itself does not support libc++ because there is no place to put LLVM libc++
Windows SDK file structure is much more complicated. Not just you need to put windows-sdk, you also have to put MSVC installation path which means I have to emulate entire This is the same rule as other triplets. I don't see how that is not useful because every other triplet, for example, x86_64-windows-gnu, x86_64-linux-gnu, wasm(32/64)-wasip1, aarch64-linux-android{version} are doing exactly the same. For example wasm:
If you look at this rust cross-compiling thing. They are doing precisely the same; they need to repackage the libs since they are useless due to case insensitive on Windows. I am just putting the final results so that people could go and clone the sysroot repository to use it.
|
1458330
to
4dc119b
Compare
no. I do not want that complicated file structure. I just want normal GNU style's sysroot. x86_64-windows-msvc sysroot should have exact the same file struct as x86_64-windows-gnu. winsysroot is a terrible idea. |
x86_64-windows-gnu https://github.com/trcrsired/llvm-releases/releases Try yourself. All of them follow the same rule |
The -msvc triples are designed to work with libraries from MSVC and the Windows SDK. We can't change how those are organized. |
There is no "--sysroot" for msvc and windows SDK. Also, there is no support for libc++ in that directory and that is a huge issue. My definition is correct to make clang --sysroot work the same way as other platforms. If you don't like it, you can continue using winsysroot. winsysroot isn't --sysroot Also, without a GNU style --sysroot=, users cannot even compile and use their libraries. Microsoft compiler was supposed to ask you to add dependencies to their IDE manually. That is not an option for cross compiling. |
@zmodem ok. let me explain to me why using the same file structure of msvc does not work. MSVC's built-in headers conflict with Clang's built-in headers so clang cannot use its headers any more. Every of these issue need tweaking. You cannot just download windows sdk and use them on none windows platforms. They don't work. |
57a0c49
to
1760857
Compare
I strongly oppose making These setups are overly complex and lack support for libc++, making them practically useless. A GNU-style sysroot would solve everything, but Rust enthusiasts have complicated things by bringing in Cargo and micro-dependencies like xwin. I doubt xwin works well, especially since Microsoft's headers need fixes for case-sensitive filesystems—something that requires effort Microsoft isn't directly providing. The last time I checked, even the Windows SDK has C headers mixed with standard C++ headers, making it impossible to use with LLVM void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// FIXME: There should probably be logic here to find libc++ on Windows.
} I guess xwin is maintained by rust people who have very little knowledge on how things really work for C and C++, so you end up with even larger mess. I strongly oppose to introduce any rust engineering work outside their own bubble since you end up with mess like wasip2. https://kerkour.com/webassembly-wasi-preview2 This issue is exactly an example why just using microsoft's one does not work since basic all language compilers using the GNU's style sysroot rule and microsoft headers need manually fix up when things don't compile. |
This patch is useful. This is a simple way to get rid of the huge Visual Studio installation. I use the following command line to configure my project with cmake and use libc++ as the standard library on Windows: cmake -G Ninja -D "CMAKE_C_COMPILER=D:\Projects\clang\llvm\bin\clang.exe" -D "CMAKE_CXX_COMPILER=D:\Projects\clang\llvm\bin\clang++.exe" -D "CMAKE_C_FLAGS=--target=x86_64-windows-msvc --sysroot=D:\Projects\windows-msvc-sysroot -fuse-ld=lld" -D "CMAKE_CXX_FLAGS=--target=x86_64-windows-msvc --sysroot=D:\Projects\windows-msvc-sysroot -fuse-ld=lld -stdlib=libc++" .. By changing -stdlib=libc++ to -stdlib=stl, I can use stl as the C++ standard library. Due to cmake incorrectly using msvc-style lld-link instead of lld when using gnu-sysroot, manual compilation is currently the only way to use gnu-sysroot: clang++ --target=x86_64-windows-gnu --sysroot=D:\Projects\clang\x86_64-windows-gnu -rtlib=compiler-rt --unwindlib=libunwind -fuse-ld=lld -stdlib=libc++ -lc++abi -lunwind -std=c++23 examples.cpp Overall, I believe this patch is effective, although windows-msvc-sysroot is a private repository, it doesn't have any conceptual differences from other sysroots. Perhaps the author should create a tutorial on how to build this system root. |
I think it is possible to use the same rule for msvc targets with --target= and --sysroot= See Repository: https://github.com/trcrsired/windows-msvc-sysroot Add sysroot support for msvc MSVC.cpp needs getDriver before using D add stl in parser for -stdlib= Add Vcruntime to runtime list and unwind list MSVC add default runtime lib type and default unwind lib type add a msvc sysroot test use %S instead of /foo Fix test for msvc-sysroot Also add a pesudo implementation for WebAssembly and maybe Microsoft STL could be ported to more targets in the future Fix the toggle of wasm that prevents -stdlib=stl passed into Avoid clang-formatting in MSVC.cpp Add some comments to ToolChain avoid indent the if block Add back space before winsysroot line use instead of arch in the comment remove FIXME for libc++ since we have added the logic here Remove MSVC.h formatting Remove default cases in WebAssembly add back the empty line before the Sysroot line fix msvc-sysroot typo for libc++ loongarch Fix : missing in CST_Stl case
I think it is possible to use the same rule for msvc targets with --target= and --sysroot=
See Repository:
https://github.com/trcrsired/windows-msvc-sysroot
Headers
Windows + CRT Headers Include Directory: include
C++ standard library headers:
With -stdlib=stl, headers should be located in include/c++/stl
With -stdlib=libc++, headers should be located in include/c++/v1
Libraries
Libraries should be placed in lib/$TRIPLET
For example. on x86_64-windows-msvc, it should find libs in lib/x86_64-windows-msvc