Author: rnk Date: Thu Feb 2 13:36:22 2017 New Revision: 293924 URL: http://llvm.org/viewvc/llvm-project?rev=293924&view=rev Log: Revert "[Driver] Updated for Visual Studio 2017"
This reverts commit r293923. It causes test failures on Linux that need time to debug. Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td cfe/trunk/lib/Driver/MSVCToolChain.cpp cfe/trunk/lib/Driver/ToolChains.h cfe/trunk/lib/Driver/Tools.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=293924&r1=293923&r2=293924&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Thu Feb 2 13:36:22 2017 @@ -281,8 +281,4 @@ def warn_drv_ps4_sdk_dir : Warning< def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">; def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">; def err_drv_defsym_invalid_symval : Error<"Value is not an integer: %0">; - -def err_drv_msvc_not_found : Error< - "unable to find a Visual Studio installation; " - "try running Clang from a developer command prompt">; } Modified: cfe/trunk/lib/Driver/MSVCToolChain.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/MSVCToolChain.cpp?rev=293924&r1=293923&r2=293924&view=diff ============================================================================== --- cfe/trunk/lib/Driver/MSVCToolChain.cpp (original) +++ cfe/trunk/lib/Driver/MSVCToolChain.cpp Thu Feb 2 13:36:22 2017 @@ -23,23 +23,16 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include <cstdio> +// Include the necessary headers to interface with the Windows registry and +// environment. #if defined(LLVM_ON_WIN32) - #define USE_WIN32 - - // FIXME: Make this configurable with cmake when the final version of the API - // has been released. - #if 0 - #define USE_VS_SETUP_CONFIG - #endif +#define USE_WIN32 #endif -// Include the necessary headers to interface with the Windows registry and -// environment. #ifdef USE_WIN32 #define WIN32_LEAN_AND_MEAN #define NOGDI @@ -49,265 +42,20 @@ #include <windows.h> #endif -// Include the headers needed for the setup config COM stuff and define -// smart pointers for the interfaces we need. -#ifdef USE_VS_SETUP_CONFIG - #include "clang/Basic/VirtualFileSystem.h" - #include "llvm/Support/COM.h" - #include <comdef.h> - #include <Setup.Configuration.h> - _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration)); - _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2)); - _COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper)); - _COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances)); - _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance)); - _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2)); -#endif - using namespace clang::driver; using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; -// Defined below. -// Forward declare this so there aren't too many things above the constructor. -static bool getSystemRegistryString(const char *keyPath, const char *valueName, - std::string &value, std::string *phValue); - -// Check various environment variables to try and find a toolchain. -static bool findVCToolChainViaEnvironment(std::string &Path, - bool &IsVS2017OrNewer) { - // These variables are typically set by vcvarsall.bat - // when launching a developer command prompt. - if (llvm::Optional<std::string> VCToolsInstallDir = - llvm::sys::Process::GetEnv("VCToolsInstallDir")) { - // This is only set by newer Visual Studios, and it leads straight to - // the toolchain directory. - Path = std::move(*VCToolsInstallDir); - IsVS2017OrNewer = true; - return true; - } - if (llvm::Optional<std::string> VCInstallDir = - llvm::sys::Process::GetEnv("VCINSTALLDIR")) { - // If the previous variable isn't set but this one is, then we've found - // an older Visual Studio. This variable is set by newer Visual Studios too, - // so this check has to appear second. - // In older Visual Studios, the VC directory is the toolchain. - Path = std::move(*VCInstallDir); - IsVS2017OrNewer = false; - return true; - } - - // We couldn't find any VC environment variables. Let's walk through PATH and - // see if it leads us to a VC toolchain bin directory. If it does, pick the - // first one that we find. - if (llvm::Optional<std::string> PathEnv = - llvm::sys::Process::GetEnv("PATH")) { - llvm::SmallVector<llvm::StringRef, 8> PathEntries; - llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator); - for (llvm::StringRef PathEntry : PathEntries) { - if (PathEntry.empty()) - continue; - - llvm::SmallString<256> ExeTestPath; - - // If cl.exe doesn't exist, then this definitely isn't a VC toolchain. - ExeTestPath = PathEntry; - llvm::sys::path::append(ExeTestPath, "cl.exe"); - if (!llvm::sys::fs::exists(ExeTestPath)) - continue; - - // cl.exe existing isn't a conclusive test for a VC toolchain; clang also - // has a cl.exe. So let's check for link.exe too. - ExeTestPath = PathEntry; - llvm::sys::path::append(ExeTestPath, "link.exe"); - if (!llvm::sys::fs::exists(ExeTestPath)) - continue; - - // whatever/VC/bin --> old toolchain, VC dir is toolchain dir. - if (llvm::sys::path::filename(PathEntry) == "bin") { - llvm::StringRef ParentPath = llvm::sys::path::parent_path(PathEntry); - if (llvm::sys::path::filename(ParentPath) == "VC") { - Path = ParentPath; - IsVS2017OrNewer = false; - return true; - } - } else { - // This could be a new (>=VS2017) toolchain. If it is, we should find - // path components with these prefixes when walking backwards through - // the path. - // Note: empty strings match anything. - llvm::StringRef ExpectedPrefixes[] = - { "", "Host", "bin", "", "MSVC", "Tools", "VC" }; - - llvm::sys::path::reverse_iterator - It = llvm::sys::path::rbegin(PathEntry), - End = llvm::sys::path::rend(PathEntry); - for (llvm::StringRef Prefix : ExpectedPrefixes) { - if (It == End) goto NotAToolChain; - if (!It->startswith(Prefix)) goto NotAToolChain; - ++It; - } - - // We've found a new toolchain! - // Back up 3 times (/bin/Host/arch) to get the root path. - llvm::StringRef ToolChainPath(PathEntry); - for (int i = 0; i < 3; ++i) - ToolChainPath = llvm::sys::path::parent_path(ToolChainPath); - - Path = ToolChainPath; - IsVS2017OrNewer = true; - return true; - } - - NotAToolChain: - continue; - } - } - return false; -} - -// Query the Setup Config server for installs, then pick the newest version -// and find its default VC toolchain. -// 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) { -#ifndef USE_VS_SETUP_CONFIG - return false; -#else - llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded); - HRESULT HR; - - // _com_ptr_t will throw a _com_error if a COM calls fail. - // The LLVM coding standards forbid exception handling, so we'll have to - // stop them from being thrown in the first place. - // The destructor will put the regular error handler back when we leave - // this scope. - struct SuppressCOMErrorsRAII { - SuppressCOMErrorsRAII() { - _set_com_error_handler([](HRESULT, IErrorInfo *) { }); - } - ~SuppressCOMErrorsRAII() { - _set_com_error_handler(_com_raise_error); - } - } COMErrorSuppressor; - - ISetupConfigurationPtr Query; - HR = Query.CreateInstance(__uuidof(SetupConfiguration)); - if (FAILED(HR)) return false; - - IEnumSetupInstancesPtr EnumInstances; - HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances); - if (FAILED(HR)) return false; - - ISetupInstancePtr Instance; - HR = EnumInstances->Next(1, &Instance, nullptr); - if (HR != S_OK) return false; - - ISetupInstancePtr NewestInstance(Instance); - uint64_t NewestVersionNum; - { - bstr_t VersionString; - HR = NewestInstance->GetInstallationVersion(VersionString.GetAddress()); - if (FAILED(HR)) return false; - HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, - &NewestVersionNum); - if (FAILED(HR)) return false; - } - - while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK) { - bstr_t VersionString; - uint64_t VersionNum; - HR = Instance->GetInstallationVersion(VersionString.GetAddress()); - if (FAILED(HR)) continue; - HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, - &VersionNum); - if (FAILED(HR)) continue; - if (VersionNum > NewestVersionNum) { - NewestInstance = Instance; - NewestVersionNum = VersionNum; - } - } - - bstr_t VCPathWide; - HR = NewestInstance->ResolvePath(L"VC", - VCPathWide.GetAddress()); - if (FAILED(HR)) return false; - - std::string VCRootPath; - llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath); - - llvm::SmallString<256> ToolsVersionFilePath(VCRootPath); - llvm::sys::path::append(ToolsVersionFilePath, - "Auxiliary", - "Build", - "Microsoft.VCToolsVersion.default.txt"); - - auto ToolsVersionFile = - clang::vfs::getRealFileSystem()->getBufferForFile(ToolsVersionFilePath); - if (!ToolsVersionFile) - return false; - - llvm::SmallString<256> ToolchainPath(VCRootPath); - llvm::sys::path::append(ToolchainPath, - "Tools", - "MSVC", - ToolsVersionFile->get()->getBuffer().rtrim()); - if (!llvm::sys::fs::is_directory(ToolchainPath)) - return false; - - Path = ToolchainPath.str(); - IsVS2017OrNewer = true; - return true; -#endif /*USE_VS_SETUP_CONFIG*/ -} - -// Look in the registry for Visual Studio installs, and use that to get -// 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) { - std::string VSInstallPath; - if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)", - "InstallDir", VSInstallPath, nullptr) || - getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)", - "InstallDir", VSInstallPath, nullptr)) { - if (!VSInstallPath.empty()) { - llvm::SmallString<256> - VCPath(llvm::StringRef(VSInstallPath.c_str(), - VSInstallPath.find(R"(\Common7\IDE)"))); - llvm::sys::path::append(VCPath, "VC"); - - Path = VCPath.str(); - IsVS2017OrNewer = false; - return true; - } - } - return false; -} - -MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple, +MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); - - // Check the environment first, since that's probably the user telling us - // 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); } Tool *MSVCToolChain::buildLinker() const { - if (VCToolChainPath.empty()) { - getDriver().Diag(clang::diag::err_drv_msvc_not_found); - return nullptr; - } return new tools::visualstudio::Linker(*this); } @@ -355,77 +103,6 @@ void MSVCToolChain::printVerboseInfo(raw CudaInstallation.print(OS); } -// Windows SDKs and VC Toolchains group their contents into subdirectories based -// on the target architecture. This function converts an llvm::Triple::ArchType -// to the corresponding subdirectory name. -static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) { - using ArchType = llvm::Triple::ArchType; - switch (Arch) { - case ArchType::x86: - return "x86"; - case ArchType::x86_64: - return "x64"; - case ArchType::arm: - return "arm"; - default: - return ""; - } -} - -// Similar to the above function, but for Visual Studios before VS2017. -static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) { - using ArchType = llvm::Triple::ArchType; - switch (Arch) { - case ArchType::x86: - // x86 is default in legacy VC toolchains. - // e.g. x86 libs are directly in /lib as opposed to /lib/x86. - return ""; - 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 -// of hardcoding paths. -std::string - MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, - llvm::Triple::ArchType TargetArch) const { - llvm::SmallString<256> Path(VCToolChainPath); - switch (Type) { - case SubDirectoryType::Bin: - if (IsVS2017OrNewer) { - 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)); - } - break; - case SubDirectoryType::Include: - llvm::sys::path::append(Path, "include"); - break; - case SubDirectoryType::Lib: - llvm::sys::path::append(Path, - "lib", - IsVS2017OrNewer - ? llvmArchToWindowsSDKArch(TargetArch) - : llvmArchToLegacyVCArch(TargetArch)); - break; - } - return Path.str(); -} - #ifdef USE_WIN32 static bool readFullStringValue(HKEY hkey, const char *valueName, std::string &value) { @@ -555,12 +232,27 @@ 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 ""; + } +} + // Find the most recent version of Universal CRT or Windows 10 SDK. // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include // directory by name and uses the last one of the list. // So we compare entry names lexicographically to find the greatest one. -static bool getWindows10SDKVersionFromPath(const std::string &SDKPath, - std::string &SDKVersion) { +static bool getWindows10SDKVersion(const std::string &SDKPath, + std::string &SDKVersion) { SDKVersion.clear(); std::error_code EC; @@ -584,9 +276,9 @@ static bool getWindows10SDKVersionFromPa } /// \brief Get Windows SDK installation directory. -static bool getWindowsSDKDir(std::string &Path, int &Major, - std::string &WindowsSDKIncludeVersion, - std::string &WindowsSDKLibVersion) { +bool MSVCToolChain::getWindowsSDKDir(std::string &Path, int &Major, + std::string &WindowsSDKIncludeVersion, + std::string &WindowsSDKLibVersion) const { std::string RegistrySDKVersion; // Try the Windows registry. if (!getSystemRegistryString( @@ -618,7 +310,7 @@ static bool getWindowsSDKDir(std::string return !WindowsSDKLibVersion.empty(); } if (Major == 10) { - if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion)) + if (!getWindows10SDKVersion(Path, WindowsSDKIncludeVersion)) return false; WindowsSDKLibVersion = WindowsSDKIncludeVersion; return true; @@ -641,14 +333,9 @@ bool MSVCToolChain::getWindowsSDKLibrary llvm::SmallString<128> libPath(sdkPath); llvm::sys::path::append(libPath, "Lib"); - if (sdkMajor >= 8) { - llvm::sys::path::append(libPath, - windowsSDKLibVersion, - "um", - llvmArchToWindowsSDKArch(getArch())); - } else { + if (sdkMajor <= 7) { switch (getArch()) { - // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. + // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. case llvm::Triple::x86: break; case llvm::Triple::x86_64: @@ -660,6 +347,11 @@ bool MSVCToolChain::getWindowsSDKLibrary default: return false; } + } else { + const StringRef archName = getWindowsSDKArch(getArch()); + if (archName.empty()) + return false; + llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", archName); } path = libPath.str(); @@ -668,22 +360,24 @@ bool MSVCToolChain::getWindowsSDKLibrary // 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 MSVCToolChain::useUniversalCRT() const { - llvm::SmallString<128> TestPath(getSubDirectoryPath(SubDirectoryType::Include)); - llvm::sys::path::append(TestPath, "stdlib.h"); +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); } -static bool getUniversalCRTSdkDir(std::string &Path, - std::string &UCRTVersion) { +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)) + "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10", + Path, nullptr)) return false; - return getWindows10SDKVersionFromPath(Path, UCRTVersion); + return getWindows10SDKVersion(Path, UCRTVersion); } bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const { @@ -694,7 +388,7 @@ bool MSVCToolChain::getUniversalCRTLibra if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) return false; - StringRef ArchName = llvmArchToWindowsSDKArch(getArch()); + StringRef ArchName = getWindowsSDKArch(getArch()); if (ArchName.empty()) return false; @@ -705,18 +399,104 @@ bool MSVCToolChain::getUniversalCRTLibra return true; } -static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) { +// 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). +bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath, + std::string &path) const { + path.clear(); + + SmallString<128> BinDir; + + // First check the environment variables that vsvars32.bat sets. + llvm::Optional<std::string> VcInstallDir = + llvm::sys::Process::GetEnv("VCINSTALLDIR"); + if (VcInstallDir.hasValue()) { + BinDir = VcInstallDir.getValue(); + llvm::sys::path::append(BinDir, "bin"); + } else { + // Next walk the PATH, trying to find a cl.exe in the path. If we find one, + // use that. However, make sure it's not clang's cl.exe. + llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH"); + if (OptPath.hasValue()) { + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; + SmallVector<StringRef, 8> PathSegments; + llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); + + for (StringRef PathSegment : PathSegments) { + if (PathSegment.empty()) + continue; + + SmallString<128> FilePath(PathSegment); + llvm::sys::path::append(FilePath, "cl.exe"); + // Checking if cl.exe exists is a small optimization over calling + // can_execute, which really only checks for existence but will also do + // extra checks for cl.exe.exe. These add up when walking a long path. + if (llvm::sys::fs::exists(FilePath.c_str()) && + !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) { + // If we found it on the PATH, use it exactly as is with no + // modifications. + path = PathSegment; + return true; + } + } + } + + std::string installDir; + // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the + // registry then we have no choice but to fail. + if (!getVisualStudioInstallDir(installDir)) + return false; + + // Regardless of what binary we're ultimately trying to find, we make sure + // that this is a Visual Studio directory by checking for cl.exe. We use + // cl.exe instead of other binaries like link.exe because programs such as + // GnuWin32 also have a utility called link.exe, so cl.exe is the least + // ambiguous. + BinDir = installDir; + llvm::sys::path::append(BinDir, "VC", "bin"); + SmallString<128> ClPath(BinDir); + llvm::sys::path::append(ClPath, "cl.exe"); + + if (!llvm::sys::fs::can_execute(ClPath.c_str())) + return false; + } + + if (BinDir.empty()) + return false; + + switch (getArch()) { + case llvm::Triple::x86: + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(BinDir, "amd64"); + break; + case llvm::Triple::arm: + llvm::sys::path::append(BinDir, "arm"); + break; + default: + // Whatever this is, Visual Studio doesn't have a toolchain for it. + return false; + } + path = BinDir.str(); + return true; +} + +VersionTuple MSVCToolChain::getMSVCVersionFromTriple() const { unsigned Major, Minor, Micro; - Triple.getEnvironmentVersion(Major, Minor, Micro); + getTriple().getEnvironmentVersion(Major, Minor, Micro); if (Major || Minor || Micro) return VersionTuple(Major, Minor, Micro); return VersionTuple(); } -static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) { +VersionTuple MSVCToolChain::getMSVCVersionFromExe() const { VersionTuple Version; #ifdef USE_WIN32 - SmallString<128> ClExe(BinDir); + std::string BinPath; + if (!getVisualStudioBinariesFolder("", BinPath)) + return Version; + SmallString<128> ClExe(BinPath); llvm::sys::path::append(ClExe, "cl.exe"); std::wstring ClExeWide; @@ -749,6 +529,62 @@ static VersionTuple getMSVCVersionFromEx return Version; } +// Get Visual Studio installation directory. +bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const { + // First check the environment variables that vsvars32.bat sets. + if (llvm::Optional<std::string> VcInstallDir = + llvm::sys::Process::GetEnv("VCINSTALLDIR")) { + path = std::move(*VcInstallDir); + path = path.substr(0, path.find("\\VC")); + return true; + } + + std::string vsIDEInstallDir; + std::string vsExpressIDEInstallDir; + // Then try the windows registry. + bool hasVCDir = + getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", + "InstallDir", vsIDEInstallDir, nullptr); + if (hasVCDir && !vsIDEInstallDir.empty()) { + path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE")); + return true; + } + + bool hasVCExpressDir = + getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION", + "InstallDir", vsExpressIDEInstallDir, nullptr); + if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) { + path = vsExpressIDEInstallDir.substr( + 0, vsIDEInstallDir.find("\\Common7\\IDE")); + return true; + } + + // Try the environment. + std::string vcomntools; + if (llvm::Optional<std::string> vs120comntools = + llvm::sys::Process::GetEnv("VS120COMNTOOLS")) + vcomntools = std::move(*vs120comntools); + else if (llvm::Optional<std::string> vs100comntools = + llvm::sys::Process::GetEnv("VS100COMNTOOLS")) + vcomntools = std::move(*vs100comntools); + else if (llvm::Optional<std::string> vs90comntools = + llvm::sys::Process::GetEnv("VS90COMNTOOLS")) + vcomntools = std::move(*vs90comntools); + else if (llvm::Optional<std::string> vs80comntools = + llvm::sys::Process::GetEnv("VS80COMNTOOLS")) + vcomntools = std::move(*vs80comntools); + + // Find any version we can. + if (!vcomntools.empty()) { + size_t p = vcomntools.find("\\Common7\\Tools"); + if (p != std::string::npos) + vcomntools.resize(p); + path = std::move(vcomntools); + return true; + } + return false; +} + void MSVCToolChain::AddSystemIncludeWithSubfolder( const ArgList &DriverArgs, ArgStringList &CC1Args, const std::string &folder, const Twine &subfolder1, const Twine &subfolder2, @@ -787,14 +623,14 @@ void MSVCToolChain::AddClangSystemInclud return; } + std::string VSDir; + // When built with access to the proper Windows APIs, try to actually find // the correct include paths first. - if (!VCToolChainPath.empty()) { - addSystemInclude(DriverArgs, - CC1Args, - getSubDirectoryPath(SubDirectoryType::Include)); + if (getVisualStudioInstallDir(VSDir)) { + AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include"); - if (useUniversalCRT()) { + if (useUniversalCRT(VSDir)) { std::string UniversalCRTSdkPath; std::string UCRTVersion; if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) { @@ -825,8 +661,9 @@ void MSVCToolChain::AddClangSystemInclud AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, "include"); } + } else { + addSystemInclude(DriverArgs, CC1Args, VSDir); } - return; } @@ -853,10 +690,8 @@ VersionTuple MSVCToolChain::computeMSVCV const ArgList &Args) const { bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args); - if (MSVT.empty()) - MSVT = getMSVCVersionFromTriple(getTriple()); - if (MSVT.empty() && IsWindowsMSVC) - MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin)); + if (MSVT.empty()) MSVT = getMSVCVersionFromTriple(); + if (MSVT.empty() && IsWindowsMSVC) MSVT = getMSVCVersionFromExe(); if (MSVT.empty() && Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, IsWindowsMSVC)) { Modified: cfe/trunk/lib/Driver/ToolChains.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.h?rev=293924&r1=293923&r2=293924&view=diff ============================================================================== --- cfe/trunk/lib/Driver/ToolChains.h (original) +++ cfe/trunk/lib/Driver/ToolChains.h Thu Feb 2 13:36:22 2017 @@ -1141,11 +1141,6 @@ public: }; class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain { - std::string VCToolChainPath; - bool IsVS2017OrNewer; - - CudaInstallationDetector CudaInstallation; - public: MSVCToolChain(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); @@ -1160,22 +1155,6 @@ public: bool isPIEDefault() const override; bool isPICDefaultForced() const override; - enum class SubDirectoryType { - Bin, - Include, - Lib, - }; - std::string getSubDirectoryPath(SubDirectoryType Type, - llvm::Triple::ArchType TargetArch) const; - - // Convenience overload. - // Uses the current target arch. - std::string getSubDirectoryPath(SubDirectoryType Type) const { - return getSubDirectoryPath(Type, getArch()); - } - - bool getIsVS2017OrNewer() const { return IsVS2017OrNewer; } - void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; @@ -1186,10 +1165,17 @@ public: void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + bool getWindowsSDKDir(std::string &path, int &major, + std::string &windowsSDKIncludeVersion, + std::string &windowsSDKLibVersion) const; bool getWindowsSDKLibraryPath(std::string &path) const; /// \brief Check if Universal CRT should be used if available - bool useUniversalCRT() const; + 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; VersionTuple computeMSVCVersion(const Driver *D, const llvm::opt::ArgList &Args) const override; @@ -1210,6 +1196,11 @@ protected: Tool *buildLinker() const override; Tool *buildAssembler() const override; +private: + VersionTuple getMSVCVersionFromTriple() const; + VersionTuple getMSVCVersionFromExe() const; + + CudaInstallationDetector CudaInstallation; }; class LLVM_LIBRARY_VISIBILITY CrossWindowsToolChain : public Generic_GCC { Modified: cfe/trunk/lib/Driver/Tools.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=293924&r1=293923&r2=293924&view=diff ============================================================================== --- cfe/trunk/lib/Driver/Tools.cpp (original) +++ cfe/trunk/lib/Driver/Tools.cpp Thu Feb 2 13:36:22 2017 @@ -10888,12 +10888,19 @@ void dragonfly::Linker::ConstructJob(Com // making sure that whatever executable that's found is not a same-named exe // from clang itself to prevent clang from falling back to itself. static std::string FindVisualStudioExecutable(const ToolChain &TC, - const char *Exe) { + const char *Exe, + const char *ClangProgramPath) { const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); - SmallString<128> FilePath(MSVC.getSubDirectoryPath(toolchains::MSVCToolChain - ::SubDirectoryType::Bin)); - llvm::sys::path::append(FilePath, Exe); - return (llvm::sys::fs::can_execute(FilePath) ? FilePath.str() : Exe); + std::string visualStudioBinDir; + if (MSVC.getVisualStudioBinariesFolder(ClangProgramPath, + visualStudioBinDir)) { + SmallString<128> FilePath(visualStudioBinDir); + llvm::sys::path::append(FilePath, Exe); + if (llvm::sys::fs::can_execute(FilePath.c_str())) + return FilePath.str(); + } + + return Exe; } void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -10902,7 +10909,7 @@ void visualstudio::Linker::ConstructJob( const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; - auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain()); + const ToolChain &TC = getToolChain(); assert((Output.isFilename() || Output.isNothing()) && "invalid output"); if (Output.isFilename()) @@ -10918,20 +10925,37 @@ void visualstudio::Linker::ConstructJob( // did not run vcvarsall), try to build a consistent link environment. If // the environment variable is set however, assume the user knows what // they're doing. - CmdArgs.push_back(Args.MakeArgString( - std::string("-libpath:") - + TC.getSubDirectoryPath(toolchains::MSVCToolChain - ::SubDirectoryType::Lib))); - - if (TC.useUniversalCRT()) { - std::string UniversalCRTLibPath; - if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath)) - CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") - + UniversalCRTLibPath)); + std::string VisualStudioDir; + const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); + if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) { + SmallString<128> LibDir(VisualStudioDir); + llvm::sys::path::append(LibDir, "VC", "lib"); + switch (MSVC.getArch()) { + case llvm::Triple::x86: + // x86 just puts the libraries directly in lib + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(LibDir, "amd64"); + break; + case llvm::Triple::arm: + llvm::sys::path::append(LibDir, "arm"); + break; + default: + break; + } + 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)); + } } std::string WindowsSdkLibPath; - if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath)) + if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath)) CmdArgs.push_back( Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); } @@ -11055,7 +11079,8 @@ void visualstudio::Linker::ConstructJob( // If we're using the MSVC linker, it's not sufficient to just use link // from the program PATH, because other environments like GnuWin32 install // their own link.exe which may come first. - linkPath = FindVisualStudioExecutable(TC, "link.exe"); + linkPath = FindVisualStudioExecutable(TC, "link.exe", + C.getDriver().getClangProgramPath()); } else { linkPath = Linker; llvm::sys::path::replace_extension(linkPath, "exe"); @@ -11188,7 +11213,9 @@ std::unique_ptr<Command> visualstudio::C Args.MakeArgString(std::string("/Fo") + Output.getFilename()); CmdArgs.push_back(Fo); - std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe"); + const Driver &D = getToolChain().getDriver(); + std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe", + D.getClangProgramPath()); return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits