From c9ecba776f9afa8403849e4f313a52a39b77a920 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Wed, 22 Oct 2014 20:40:43 +0000 Subject: [PATCH] Make a good guess about where MSVC and Windows SDK libraries are for linking. When a user has not configured a standard Visual Studio environment by running vcvarsall, clang tries its best to find Visual Studio include files and executables anyway. This patch makes clang also try to find system and Windows SDK libraries for linking against, as well. Reviewed by: Hans Wennborg Differential Revision: http://reviews.llvm.org/D5873 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220425 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/MSVCToolChain.cpp | 65 ++++++++++++++++++++++++++++++++++++ lib/Driver/ToolChains.h | 1 + lib/Driver/Tools.cpp | 33 ++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp index 6470841927..a2f5e83984 100644 --- a/lib/Driver/MSVCToolChain.cpp +++ b/lib/Driver/MSVCToolChain.cpp @@ -212,6 +212,71 @@ bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major, return hasSDKDir && !path.empty(); } +// Gets the library path required to link against the Windows SDK. +bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const { + std::string sdkPath; + int sdkMajor = 0; + int sdkMinor = 0; + + path.clear(); + if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor)) + return false; + + llvm::SmallString<128> libPath(sdkPath); + llvm::sys::path::append(libPath, "Lib"); + if (sdkMajor <= 7) { + switch (getArch()) { + // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. + case llvm::Triple::x86: + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(libPath, "x64"); + break; + case llvm::Triple::arm: + // It is not necessary to link against Windows SDK 7.x when targeting ARM. + return false; + default: + return false; + } + } else { + // Windows SDK 8.x installs libraries in a folder whose names depend on the + // version of the OS you're targeting. By default choose the newest, which + // usually corresponds to the version of the OS you've installed the SDK on. + char *tests[] = {"winv6.3", "win8", "win7"}; + bool found = false; + for (char *test : tests) { + llvm::SmallString<128> testPath(libPath); + llvm::sys::path::append(testPath, test); + if (llvm::sys::fs::exists(testPath.c_str())) { + libPath = testPath; + found = true; + break; + } + } + + 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: + return false; + } + } + + 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). diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index dbacccab0f..525a7d29a4 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -746,6 +746,7 @@ public: llvm::opt::ArgStringList &CC1Args) const override; bool getWindowsSDKDir(std::string &path, int &major, int &minor) const; + bool getWindowsSDKLibraryPath(std::string &path) const; bool getVisualStudioInstallDir(std::string &path) const; bool getVisualStudioBinariesFolder(const char *clangProgramPath, std::string &path) const; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 1c0a6ff4a4..6e7060fedd 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -7854,6 +7854,39 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-defaultlib:libcmt"); } + if (!llvm::sys::Process::GetEnv("LIB")) { + // If the VC environment hasn't been configured (perhaps because the user + // did not run vcvarsall), try to build a consistent link environment. If + // the environment variable is set however, assume the user knows what he's + // doing. + std::string VisualStudioDir; + const auto &MSVC = static_cast(getToolChain()); + 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())); + } + + std::string WindowsSdkLibPath; + if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath)) + CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + + WindowsSdkLibPath.c_str())); + } + CmdArgs.push_back("-nologo"); if (Args.hasArg(options::OPT_g_Group)) { -- 2.40.0