[clang] [clang] Support --sysroot= for ${arch}-windows-msvc targets (PR #96417)
Yaxun Liu via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 24 07:08:03 PDT 2026
================
@@ -1216,3 +1363,121 @@ void MSVCToolChain::addClangTargetOptions(
if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_marm64x))
A->ignoreTargetSpecific();
}
+
+void MSVCToolChain::addMsvcstlIncludePaths(
+ 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, getTripleWithUnknownVendor(*this), SysRoot);
+
+ std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/msvcstl";
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/msvcstl");
+}
+
+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, getTripleWithUnknownVendor(*this), 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, getTripleWithUnknownVendor(*this), 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");
+}
+
+llvm::SmallVector<std::string> MSVCToolChain::getCXXStdlibIncludeDirs(
+ const llvm::opt::ArgList &DriverArgs) const {
+ auto cxxStdlibType = GetCXXStdlibType(DriverArgs);
+ if (cxxStdlibType == ToolChain::CST_MSVCSTL) {
+ llvm::SmallVector<std::string> vec;
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc))
----------------
yxsamliu wrote:
Could this also handle `-nostdinc++`? Before this change, `--print-cxx-stdlib-include-dirs -nostdinc++` printed no paths. The updated test now expects the MSVC include path instead. Please preserve the old behavior and keep the test expecting no output.
https://github.com/llvm/llvm-project/pull/96417
More information about the cfe-commits
mailing list