r311391 - [Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.

Stephan T. Lavavej via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 21 15:19:33 PDT 2017


Author: stl_msft
Date: Mon Aug 21 15:19:33 2017
New Revision: 311391

URL: http://llvm.org/viewvc/llvm-project?rev=311391&view=rev
Log:
[Driver] Recognize DevDiv internal builds of MSVC, with a different directory structure.

This is a reasonably non-intrusive change, which I've verified
works for both x86 and x64 DevDiv-internal builds.

The idea is to change `bool IsVS2017OrNewer` into a 3-state
`ToolsetLayout VSLayout`. Either a build is DevDiv-internal,
released VS 2017 or newer, or released VS 2015 or older. When looking at
the directory structure, if instead of `"VC"` we see `"x86ret"`, `"x86chk"`,
`"amd64ret"`, or `"amd64chk"`, we recognize this as a DevDiv-internal build.

After we get past the directory structure validation, we use this knowledge
to regenerate paths appropriately. `llvmArchToDevDivInternalArch()` knows how
we use `"i386"` subdirectories, and `MSVCToolChain::getSubDirectoryPath()`
uses that. It also knows that DevDiv-internal builds have an `"inc"`
subdirectory instead of `"include"`.

This may still not be the "right" fix in any sense, but I believe that it's
non-intrusive in the sense that if the special directory names aren't found,
no codepaths are affected. (`ToolsetLayout::OlderVS` and
`ToolsetLayout::VS2017OrNewer` correspond to `IsVS2017OrNewer` being `false`
or `true`, respectively.) I searched for all references to `IsVS2017OrNewer`,
which are places where Clang cares about VS's directory structure, and the
only one that isn't being patched is some logic to deal with
cross-compilation. I'm fine with that not working for DevDiv-internal builds
for the moment (we typically test the native compilers), so I added a comment.

Fixes D36860.

Modified:
    cfe/trunk/lib/Driver/ToolChains/MSVC.cpp
    cfe/trunk/lib/Driver/ToolChains/MSVC.h

Modified: cfe/trunk/lib/Driver/ToolChains/MSVC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/MSVC.cpp?rev=311391&r1=311390&r2=311391&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/MSVC.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/MSVC.cpp Mon Aug 21 15:19:33 2017
@@ -76,7 +76,7 @@ static bool getSystemRegistryString(cons
 
 // Check various environment variables to try and find a toolchain.
 static bool findVCToolChainViaEnvironment(std::string &Path,
-                                          bool &IsVS2017OrNewer) {
+                                          MSVCToolChain::ToolsetLayout &VSLayout) {
   // These variables are typically set by vcvarsall.bat
   // when launching a developer command prompt.
   if (llvm::Optional<std::string> VCToolsInstallDir =
@@ -84,7 +84,7 @@ static bool findVCToolChainViaEnvironmen
     // This is only set by newer Visual Studios, and it leads straight to
     // the toolchain directory.
     Path = std::move(*VCToolsInstallDir);
-    IsVS2017OrNewer = true;
+    VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
     return true;
   }
   if (llvm::Optional<std::string> VCInstallDir =
@@ -94,7 +94,7 @@ static bool findVCToolChainViaEnvironmen
     // so this check has to appear second.
     // In older Visual Studios, the VC directory is the toolchain.
     Path = std::move(*VCInstallDir);
-    IsVS2017OrNewer = false;
+    VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
     return true;
   }
 
@@ -134,9 +134,16 @@ static bool findVCToolChainViaEnvironmen
       }
       if (IsBin) {
         llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
-        if (llvm::sys::path::filename(ParentPath) == "VC") {
+        llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
+        if (ParentFilename == "VC") {
           Path = ParentPath;
-          IsVS2017OrNewer = false;
+          VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
+          return true;
+        }
+        if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
+          || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
+          Path = ParentPath;
+          VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
           return true;
         }
 
@@ -165,7 +172,7 @@ static bool findVCToolChainViaEnvironmen
           ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
 
         Path = ToolChainPath;
-        IsVS2017OrNewer = true;
+        VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
         return true;
       }
 
@@ -181,7 +188,7 @@ static bool findVCToolChainViaEnvironmen
 // This is the preferred way to discover new Visual Studios, as they're no
 // longer listed in the registry.
 static bool findVCToolChainViaSetupConfig(std::string &Path,
-                                          bool &IsVS2017OrNewer) {
+                                          MSVCToolChain::ToolsetLayout &VSLayout) {
 #if !defined(USE_MSVC_SETUP_API)
   return false;
 #else
@@ -263,7 +270,7 @@ static bool findVCToolChainViaSetupConfi
     return false;
 
   Path = ToolchainPath.str();
-  IsVS2017OrNewer = true;
+  VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
   return true;
 #endif
 }
@@ -272,7 +279,7 @@ static bool findVCToolChainViaSetupConfi
 // a toolchain path. VS2017 and newer don't get added to the registry.
 // So if we find something here, we know that it's an older version.
 static bool findVCToolChainViaRegistry(std::string &Path,
-                                       bool &IsVS2017OrNewer) {
+                                       MSVCToolChain::ToolsetLayout &VSLayout) {
   std::string VSInstallPath;
   if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
                               "InstallDir", VSInstallPath, nullptr) ||
@@ -284,7 +291,7 @@ static bool findVCToolChainViaRegistry(s
       llvm::sys::path::append(VCPath, "VC");
 
       Path = VCPath.str();
-      IsVS2017OrNewer = false;
+      VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
       return true;
     }
   }
@@ -475,6 +482,7 @@ void visualstudio::Linker::ConstructJob(
     // native target bin directory.
     // e.g. when compiling for x86 on an x64 host, PATH should start with:
     // /bin/HostX64/x86;/bin/HostX64/x64
+    // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
     if (TC.getIsVS2017OrNewer() &&
         llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
       auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
@@ -677,9 +685,9 @@ MSVCToolChain::MSVCToolChain(const Drive
   // what they want to use.
   // Failing that, just try to find the newest Visual Studio version we can
   // and use its default VC toolchain.
-  findVCToolChainViaEnvironment(VCToolChainPath, IsVS2017OrNewer) ||
-      findVCToolChainViaSetupConfig(VCToolChainPath, IsVS2017OrNewer) ||
-      findVCToolChainViaRegistry(VCToolChainPath, IsVS2017OrNewer);
+  findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
+      findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
+      findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
 }
 
 Tool *MSVCToolChain::buildLinker() const {
@@ -766,6 +774,21 @@ static const char *llvmArchToLegacyVCArc
   }
 }
 
+// Similar to the above function, but for DevDiv internal builds.
+static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
+  using ArchType = llvm::Triple::ArchType;
+  switch (Arch) {
+  case ArchType::x86:
+    return "i386";
+  case ArchType::x86_64:
+    return "amd64";
+  case ArchType::arm:
+    return "arm";
+  default:
+    return "";
+  }
+}
+
 // Get the path to a specific subdirectory in the current toolchain for
 // a given target architecture.
 // VS2017 changed the VC toolchain layout, so this should be used instead
@@ -773,26 +796,40 @@ static const char *llvmArchToLegacyVCArc
 std::string
 MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
                                    llvm::Triple::ArchType TargetArch) const {
+  const char *SubdirName;
+  const char *IncludeName;
+  switch (VSLayout) {
+  case ToolsetLayout::OlderVS:
+    SubdirName = llvmArchToLegacyVCArch(TargetArch);
+    IncludeName = "include";
+    break;
+  case ToolsetLayout::VS2017OrNewer:
+    SubdirName = llvmArchToWindowsSDKArch(TargetArch);
+    IncludeName = "include";
+    break;
+  case ToolsetLayout::DevDivInternal:
+    SubdirName = llvmArchToDevDivInternalArch(TargetArch);
+    IncludeName = "inc";
+    break;
+  }
+
   llvm::SmallString<256> Path(VCToolChainPath);
   switch (Type) {
   case SubDirectoryType::Bin:
-    if (IsVS2017OrNewer) {
-      bool HostIsX64 =
+    if (VSLayout == ToolsetLayout::VS2017OrNewer) {
+      const bool HostIsX64 =
           llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
-      llvm::sys::path::append(Path, "bin", (HostIsX64 ? "HostX64" : "HostX86"),
-                              llvmArchToWindowsSDKArch(TargetArch));
-
-    } else {
-      llvm::sys::path::append(Path, "bin", llvmArchToLegacyVCArch(TargetArch));
+      const char *const HostName = HostIsX64 ? "HostX64" : "HostX86";
+      llvm::sys::path::append(Path, "bin", HostName, SubdirName);
+    } else { // OlderVS or DevDivInternal
+      llvm::sys::path::append(Path, "bin", SubdirName);
     }
     break;
   case SubDirectoryType::Include:
-    llvm::sys::path::append(Path, "include");
+    llvm::sys::path::append(Path, IncludeName);
     break;
   case SubDirectoryType::Lib:
-    llvm::sys::path::append(
-        Path, "lib", IsVS2017OrNewer ? llvmArchToWindowsSDKArch(TargetArch)
-                                     : llvmArchToLegacyVCArch(TargetArch));
+    llvm::sys::path::append(Path, "lib", SubdirName);
     break;
   }
   return Path.str();

Modified: cfe/trunk/lib/Driver/ToolChains/MSVC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/MSVC.h?rev=311391&r1=311390&r2=311391&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/MSVC.h (original)
+++ cfe/trunk/lib/Driver/ToolChains/MSVC.h Mon Aug 21 15:19:33 2017
@@ -92,7 +92,12 @@ public:
     return getSubDirectoryPath(Type, getArch());
   }
 
-  bool getIsVS2017OrNewer() const { return IsVS2017OrNewer; }
+  enum class ToolsetLayout {
+    OlderVS,
+    VS2017OrNewer,
+    DevDivInternal,
+  };
+  bool getIsVS2017OrNewer() const { return VSLayout == ToolsetLayout::VS2017OrNewer; }
 
   void
   AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -130,7 +135,7 @@ protected:
   Tool *buildAssembler() const override;
 private:
   std::string VCToolChainPath;
-  bool IsVS2017OrNewer = false;
+  ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
   CudaInstallationDetector CudaInstallation;
 };
 




More information about the cfe-commits mailing list