-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang] Support --sysroot= for ${arch}-windows-msvc targets #96417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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 |
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 personal repository, it doesn't have any conceptual differences from other sysroots. Perhaps the author should create a tutorial on how to build this sysroot. |
81e49fe
to
690011a
Compare
This patch is extremely useful, I want it can be merged. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
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 Support --sysroot= for ${arch}-windows-msvc targets 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 [clang] update msvc-sysroot.cpp tep to test arm64ec and arm64x [clang] Add arm64ec -windows-msvc support for msvc sysroot by finding libs in the aarch64-unknown-windows-msvc subdir MSVC target needs to include Gnu.h to support libstdc++ [clang] fix formatting issues for MSVC sysroot PR
Hi, I also hope this PR can be merged, but considering the other comments, I don’t think this is the right direction. I think what we might want is not "Support --sysroot= for ${arch}-windows-msvc targets," but a new target, maybe ${arch}-windows-msvcllvm, a.k.a. "MinCW"? This target is supposed to be fully ABI-compatible with MSVC, while it provides the GNU Clang user interface and directory layout. On top of fully ABI-compatible with MSVC, it is supposed to optionally supplement and replace the MSVC CRT/STL with high-quality LLVM runtimes. I believe Chromium might be interested in this, which would greatly simplify their build system. |
I think it is possible to generate this sysroot by providing a Python script that uses the existing WindowsSDK and MSVC toolchain on the local drive, so there is no need to send header files and libraries to users, avoiding licence issues. However, I currently don't have much interest in it because it feels somewhat self-deceptive. In fact, the patch works very well, it not only builds programs correctly but also work well with cmake and clangd without needing any other workarounds. |
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