r247362 - [Driver] Use UniversalCRT on Windows if available

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 10 17:09:39 PDT 2015


Author: rnk
Date: Thu Sep 10 19:09:39 2015
New Revision: 247362

URL: http://llvm.org/viewvc/llvm-project?rev=247362&view=rev
Log:
[Driver] Use UniversalCRT on Windows if available

Summary:
With Visual Studio 2015 release, a part of runtime library was extracted
and now comes with Windows Kits. This patch enables clang to use
Universal CRT library if  %INCLUDE or %LIB environment varaibles are not
specified.

See also https://llvm.org/bugs/show_bug.cgi?id=24741

Patch by Igor Kudrin

Reviewers: zturner, hans, rnk

Subscribers: ruiu, cfe-commits

Differential Revision: http://reviews.llvm.org/D12695

Modified:
    cfe/trunk/lib/Driver/MSVCToolChain.cpp
    cfe/trunk/lib/Driver/ToolChains.h
    cfe/trunk/lib/Driver/Tools.cpp

Modified: cfe/trunk/lib/Driver/MSVCToolChain.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/MSVCToolChain.cpp?rev=247362&r1=247361&r2=247362&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/MSVCToolChain.cpp (original)
+++ cfe/trunk/lib/Driver/MSVCToolChain.cpp Thu Sep 10 19:09:39 2015
@@ -205,6 +205,21 @@ static bool getSystemRegistryString(cons
 #endif // USE_WIN32
 }
 
+// Convert LLVM's ArchType
+// to the corresponding name of Windows SDK libraries subfolder
+static StringRef getWindowsSDKArch(llvm::Triple::ArchType Arch) {
+  switch (Arch) {
+  case llvm::Triple::x86:
+    return "x86";
+  case llvm::Triple::x86_64:
+    return "x64";
+  case llvm::Triple::arm:
+    return "arm";
+  default:
+    return "";
+  }
+}
+
 /// \brief Get Windows SDK installation directory.
 bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
                                      int &minor) const {
@@ -263,26 +278,75 @@ bool MSVCToolChain::getWindowsSDKLibrary
     if (!found)
       return false;
 
-    llvm::sys::path::append(libPath, "um");
-    switch (getArch()) {
-    case llvm::Triple::x86:
-      llvm::sys::path::append(libPath, "x86");
-      break;
-    case llvm::Triple::x86_64:
-      llvm::sys::path::append(libPath, "x64");
-      break;
-    case llvm::Triple::arm:
-      llvm::sys::path::append(libPath, "arm");
-      break;
-    default:
+    const StringRef archName = getWindowsSDKArch(getArch());
+    if (archName.empty())
       return false;
-    }
+    llvm::sys::path::append(libPath, "um", archName);
   }
 
   path = libPath.str();
   return true;
 }
 
+// Check if the Include path of a specified version of Visual Studio contains
+// specific header files. If not, they are probably shipped with Universal CRT.
+bool clang::driver::toolchains::MSVCToolChain::useUniversalCRT(
+    std::string &VisualStudioDir) const {
+  llvm::SmallString<128> TestPath(VisualStudioDir);
+  llvm::sys::path::append(TestPath, "VC\\include\\stdlib.h");
+
+  return !llvm::sys::fs::exists(TestPath);
+}
+
+bool MSVCToolChain::getUniversalCRTSdkDir(std::string &Path,
+                                          std::string &UCRTVersion) const {
+  // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
+  // for the specific key "KitsRoot10". So do we.
+  if (!getSystemRegistryString(
+          "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
+          Path, nullptr))
+    return false;
+
+  UCRTVersion.clear();
+
+  // Find the most recent version of Universal CRT.
+  // vcvarsqueryregistry.bat sorts entries in the include directory by names and
+  // uses the last one of the list.
+  // So we compare entry names lexicographically to find the greatest one.
+  std::error_code EC;
+  llvm::SmallString<128> IncludePath(Path);
+  llvm::sys::path::append(IncludePath, "Include");
+  for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
+       DirIt != DirEnd && !EC; DirIt.increment(EC)) {
+    if (!llvm::sys::fs::is_directory(DirIt->path()))
+      continue;
+    StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
+    if (CandidateName > UCRTVersion)
+      UCRTVersion = CandidateName;
+  }
+
+  return !UCRTVersion.empty();
+}
+
+bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
+  std::string UniversalCRTSdkPath;
+  std::string UCRTVersion;
+
+  Path.clear();
+  if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
+    return false;
+
+  StringRef ArchName = getWindowsSDKArch(getArch());
+  if (ArchName.empty())
+    return false;
+
+  llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
+  llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
+
+  Path = LibPath.str();
+  return true;
+}
+
 // Get the location to use for Visual Studio binaries.  The location priority
 // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
 // system (as reported by the registry).
@@ -460,6 +524,17 @@ void MSVCToolChain::AddClangSystemInclud
   if (getVisualStudioInstallDir(VSDir)) {
     AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
 
+    if (useUniversalCRT(VSDir)) {
+      std::string UniversalCRTSdkPath;
+      std::string UCRTVersion;
+      if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
+        llvm::SmallString<128> UCRTIncludePath(UniversalCRTSdkPath);
+        llvm::sys::path::append(UCRTIncludePath, "Include", UCRTVersion,
+                                "ucrt");
+        addSystemInclude(DriverArgs, CC1Args, UCRTIncludePath);
+      }
+    }
+
     std::string WindowsSDKDir;
     int major, minor;
     if (getWindowsSDKDir(WindowsSDKDir, major, minor)) {

Modified: cfe/trunk/lib/Driver/ToolChains.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=247362&r1=247361&r2=247362&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.h (original)
+++ cfe/trunk/lib/Driver/ToolChains.h Thu Sep 10 19:09:39 2015
@@ -840,6 +840,10 @@ public:
 
   bool getWindowsSDKDir(std::string &path, int &major, int &minor) const;
   bool getWindowsSDKLibraryPath(std::string &path) const;
+  /// \brief Check if Universal CRT should be used if available
+  bool useUniversalCRT(std::string &visualStudioDir) const;
+  bool getUniversalCRTSdkDir(std::string &path, std::string &ucrtVersion) const;
+  bool getUniversalCRTLibraryPath(std::string &path) const;
   bool getVisualStudioInstallDir(std::string &path) const;
   bool getVisualStudioBinariesFolder(const char *clangProgramPath,
                                      std::string &path) const;

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=247362&r1=247361&r2=247362&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Thu Sep 10 19:09:39 2015
@@ -8948,6 +8948,13 @@ void visualstudio::Linker::ConstructJob(
       }
       CmdArgs.push_back(
           Args.MakeArgString(std::string("-libpath:") + LibDir.c_str()));
+
+      if (MSVC.useUniversalCRT(VisualStudioDir)) {
+        std::string UniversalCRTLibPath;
+        if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
+          CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
+                                               UniversalCRTLibPath.c_str()));
+      }
     }
 
     std::string WindowsSdkLibPath;




More information about the cfe-commits mailing list