clang API Documentation

MSVCToolChain.cpp
Go to the documentation of this file.
00001 //===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "ToolChains.h"
00011 #include "clang/Basic/CharInfo.h"
00012 #include "clang/Basic/Version.h"
00013 #include "clang/Driver/Compilation.h"
00014 #include "clang/Driver/Driver.h"
00015 #include "clang/Driver/DriverDiagnostic.h"
00016 #include "clang/Driver/Options.h"
00017 #include "llvm/ADT/StringExtras.h"
00018 #include "llvm/Config/llvm-config.h"
00019 #include "llvm/Option/Arg.h"
00020 #include "llvm/Option/ArgList.h"
00021 #include "llvm/Support/ErrorHandling.h"
00022 #include "llvm/Support/FileSystem.h"
00023 #include "llvm/Support/Process.h"
00024 
00025 // Include the necessary headers to interface with the Windows registry and
00026 // environment.
00027 #if defined(LLVM_ON_WIN32)
00028 #define USE_WIN32
00029 #endif
00030 
00031 #ifdef USE_WIN32
00032   #define WIN32_LEAN_AND_MEAN
00033   #define NOGDI
00034   #define NOMINMAX
00035   #include <windows.h>
00036 #endif
00037 
00038 using namespace clang::driver;
00039 using namespace clang::driver::toolchains;
00040 using namespace clang;
00041 using namespace llvm::opt;
00042 
00043 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
00044                              const ArgList &Args)
00045   : ToolChain(D, Triple, Args) {
00046 }
00047 
00048 Tool *MSVCToolChain::buildLinker() const {
00049   return new tools::visualstudio::Link(*this);
00050 }
00051 
00052 Tool *MSVCToolChain::buildAssembler() const {
00053   if (getTriple().isOSBinFormatMachO())
00054     return new tools::darwin::Assemble(*this);
00055   getDriver().Diag(clang::diag::err_no_external_assembler);
00056   return nullptr;
00057 }
00058 
00059 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
00060   return true;
00061 }
00062 
00063 bool MSVCToolChain::IsUnwindTablesDefault() const {
00064   // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
00065   // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
00066   // how to generate them yet.
00067   return getArch() == llvm::Triple::x86_64;
00068 }
00069 
00070 bool MSVCToolChain::isPICDefault() const {
00071   return getArch() == llvm::Triple::x86_64;
00072 }
00073 
00074 bool MSVCToolChain::isPIEDefault() const {
00075   return false;
00076 }
00077 
00078 bool MSVCToolChain::isPICDefaultForced() const {
00079   return getArch() == llvm::Triple::x86_64;
00080 }
00081 
00082 #ifdef USE_WIN32
00083 static bool readFullStringValue(HKEY hkey, const char *valueName,
00084                                 std::string &value) {
00085   // FIXME: We should be using the W versions of the registry functions, but
00086   // doing so requires UTF8 / UTF16 conversions similar to how we handle command
00087   // line arguments.  The UTF8 conversion functions are not exposed publicly
00088   // from LLVM though, so in order to do this we will probably need to create
00089   // a registry abstraction in LLVMSupport that is Windows only.
00090   DWORD result = 0;
00091   DWORD valueSize = 0;
00092   DWORD type = 0;
00093   // First just query for the required size.
00094   result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize);
00095   if (result != ERROR_SUCCESS || type != REG_SZ)
00096     return false;
00097   std::vector<BYTE> buffer(valueSize);
00098   result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize);
00099   if (result == ERROR_SUCCESS)
00100     value.assign(reinterpret_cast<const char *>(buffer.data()));
00101   return result;
00102 }
00103 #endif
00104 
00105 /// \brief Read registry string.
00106 /// This also supports a means to look for high-versioned keys by use
00107 /// of a $VERSION placeholder in the key path.
00108 /// $VERSION in the key path is a placeholder for the version number,
00109 /// causing the highest value path to be searched for and used.
00110 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
00111 /// There can be additional characters in the component.  Only the numeric
00112 /// characters are compared.  This function only searches HKLM.
00113 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
00114                                     std::string &value, std::string *phValue) {
00115 #ifndef USE_WIN32
00116   return false;
00117 #else
00118   HKEY hRootKey = HKEY_LOCAL_MACHINE;
00119   HKEY hKey = NULL;
00120   long lResult;
00121   bool returnValue = false;
00122 
00123   const char *placeHolder = strstr(keyPath, "$VERSION");
00124   std::string bestName;
00125   // If we have a $VERSION placeholder, do the highest-version search.
00126   if (placeHolder) {
00127     const char *keyEnd = placeHolder - 1;
00128     const char *nextKey = placeHolder;
00129     // Find end of previous key.
00130     while ((keyEnd > keyPath) && (*keyEnd != '\\'))
00131       keyEnd--;
00132     // Find end of key containing $VERSION.
00133     while (*nextKey && (*nextKey != '\\'))
00134       nextKey++;
00135     size_t partialKeyLength = keyEnd - keyPath;
00136     char partialKey[256];
00137     if (partialKeyLength > sizeof(partialKey))
00138       partialKeyLength = sizeof(partialKey);
00139     strncpy(partialKey, keyPath, partialKeyLength);
00140     partialKey[partialKeyLength] = '\0';
00141     HKEY hTopKey = NULL;
00142     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
00143                            &hTopKey);
00144     if (lResult == ERROR_SUCCESS) {
00145       char keyName[256];
00146       double bestValue = 0.0;
00147       DWORD index, size = sizeof(keyName) - 1;
00148       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
00149           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
00150         const char *sp = keyName;
00151         while (*sp && !isDigit(*sp))
00152           sp++;
00153         if (!*sp)
00154           continue;
00155         const char *ep = sp + 1;
00156         while (*ep && (isDigit(*ep) || (*ep == '.')))
00157           ep++;
00158         char numBuf[32];
00159         strncpy(numBuf, sp, sizeof(numBuf) - 1);
00160         numBuf[sizeof(numBuf) - 1] = '\0';
00161         double dvalue = strtod(numBuf, NULL);
00162         if (dvalue > bestValue) {
00163           // Test that InstallDir is indeed there before keeping this index.
00164           // Open the chosen key path remainder.
00165           bestName = keyName;
00166           // Append rest of key.
00167           bestName.append(nextKey);
00168           lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0,
00169                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
00170           if (lResult == ERROR_SUCCESS) {
00171             lResult = readFullStringValue(hKey, valueName, value);
00172             if (lResult == ERROR_SUCCESS) {
00173               bestValue = dvalue;
00174               if (phValue)
00175                 *phValue = bestName;
00176               returnValue = true;
00177             }
00178             RegCloseKey(hKey);
00179           }
00180         }
00181         size = sizeof(keyName) - 1;
00182       }
00183       RegCloseKey(hTopKey);
00184     }
00185   } else {
00186     lResult =
00187         RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
00188     if (lResult == ERROR_SUCCESS) {
00189       lResult = readFullStringValue(hKey, valueName, value);
00190       if (lResult == ERROR_SUCCESS)
00191         returnValue = true;
00192       if (phValue)
00193         phValue->clear();
00194       RegCloseKey(hKey);
00195     }
00196   }
00197   return returnValue;
00198 #endif // USE_WIN32
00199 }
00200 
00201 /// \brief Get Windows SDK installation directory.
00202 bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
00203                                      int &minor) const {
00204   std::string sdkVersion;
00205   // Try the Windows registry.
00206   bool hasSDKDir = getSystemRegistryString(
00207       "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
00208       "InstallationFolder", path, &sdkVersion);
00209   if (!sdkVersion.empty())
00210     ::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
00211   return hasSDKDir && !path.empty();
00212 }
00213 
00214 // Gets the library path required to link against the Windows SDK.
00215 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
00216   std::string sdkPath;
00217   int sdkMajor = 0;
00218   int sdkMinor = 0;
00219 
00220   path.clear();
00221   if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor))
00222     return false;
00223 
00224   llvm::SmallString<128> libPath(sdkPath);
00225   llvm::sys::path::append(libPath, "Lib");
00226   if (sdkMajor <= 7) {
00227     switch (getArch()) {
00228     // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
00229     case llvm::Triple::x86:
00230       break;
00231     case llvm::Triple::x86_64:
00232       llvm::sys::path::append(libPath, "x64");
00233       break;
00234     case llvm::Triple::arm:
00235       // It is not necessary to link against Windows SDK 7.x when targeting ARM.
00236       return false;
00237     default:
00238       return false;
00239     }
00240   } else {
00241     // Windows SDK 8.x installs libraries in a folder whose names depend on the
00242     // version of the OS you're targeting.  By default choose the newest, which
00243     // usually corresponds to the version of the OS you've installed the SDK on.
00244     const char *tests[] = {"winv6.3", "win8", "win7"};
00245     bool found = false;
00246     for (const char *test : tests) {
00247       llvm::SmallString<128> testPath(libPath);
00248       llvm::sys::path::append(testPath, test);
00249       if (llvm::sys::fs::exists(testPath.c_str())) {
00250         libPath = testPath;
00251         found = true;
00252         break;
00253       }
00254     }
00255 
00256     if (!found)
00257       return false;
00258 
00259     llvm::sys::path::append(libPath, "um");
00260     switch (getArch()) {
00261     case llvm::Triple::x86:
00262       llvm::sys::path::append(libPath, "x86");
00263       break;
00264     case llvm::Triple::x86_64:
00265       llvm::sys::path::append(libPath, "x64");
00266       break;
00267     case llvm::Triple::arm:
00268       llvm::sys::path::append(libPath, "arm");
00269       break;
00270     default:
00271       return false;
00272     }
00273   }
00274 
00275   path = libPath.str();
00276   return true;
00277 }
00278 
00279 // Get the location to use for Visual Studio binaries.  The location priority
00280 // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
00281 // system (as reported by the registry).
00282 bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
00283                                                   std::string &path) const {
00284   path.clear();
00285 
00286   SmallString<128> BinDir;
00287 
00288   // First check the environment variables that vsvars32.bat sets.
00289   llvm::Optional<std::string> VcInstallDir =
00290       llvm::sys::Process::GetEnv("VCINSTALLDIR");
00291   if (VcInstallDir.hasValue()) {
00292     BinDir = VcInstallDir.getValue();
00293     llvm::sys::path::append(BinDir, "bin");
00294   } else {
00295     // Next walk the PATH, trying to find a cl.exe in the path.  If we find one,
00296     // use that.  However, make sure it's not clang's cl.exe.
00297     llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
00298     if (OptPath.hasValue()) {
00299       const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
00300       SmallVector<StringRef, 8> PathSegments;
00301       llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
00302 
00303       for (StringRef PathSegment : PathSegments) {
00304         if (PathSegment.empty())
00305           continue;
00306 
00307         SmallString<128> FilePath(PathSegment);
00308         llvm::sys::path::append(FilePath, "cl.exe");
00309         if (llvm::sys::fs::can_execute(FilePath.c_str()) &&
00310             !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
00311           // If we found it on the PATH, use it exactly as is with no
00312           // modifications.
00313           path = PathSegment;
00314           return true;
00315         }
00316       }
00317     }
00318 
00319     std::string installDir;
00320     // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
00321     // registry then we have no choice but to fail.
00322     if (!getVisualStudioInstallDir(installDir))
00323       return false;
00324 
00325     // Regardless of what binary we're ultimately trying to find, we make sure
00326     // that this is a Visual Studio directory by checking for cl.exe.  We use
00327     // cl.exe instead of other binaries like link.exe because programs such as
00328     // GnuWin32 also have a utility called link.exe, so cl.exe is the least
00329     // ambiguous.
00330     BinDir = installDir;
00331     llvm::sys::path::append(BinDir, "VC", "bin");
00332     SmallString<128> ClPath(BinDir);
00333     llvm::sys::path::append(ClPath, "cl.exe");
00334 
00335     if (!llvm::sys::fs::can_execute(ClPath.c_str()))
00336       return false;
00337   }
00338 
00339   if (BinDir.empty())
00340     return false;
00341 
00342   switch (getArch()) {
00343   case llvm::Triple::x86:
00344     break;
00345   case llvm::Triple::x86_64:
00346     llvm::sys::path::append(BinDir, "amd64");
00347     break;
00348   case llvm::Triple::arm:
00349     llvm::sys::path::append(BinDir, "arm");
00350     break;
00351   default:
00352     // Whatever this is, Visual Studio doesn't have a toolchain for it.
00353     return false;
00354   }
00355   path = BinDir.str();
00356   return true;
00357 }
00358 
00359 // Get Visual Studio installation directory.
00360 bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
00361   // First check the environment variables that vsvars32.bat sets.
00362   const char *vcinstalldir = getenv("VCINSTALLDIR");
00363   if (vcinstalldir) {
00364     path = vcinstalldir;
00365     path = path.substr(0, path.find("\\VC"));
00366     return true;
00367   }
00368 
00369   std::string vsIDEInstallDir;
00370   std::string vsExpressIDEInstallDir;
00371   // Then try the windows registry.
00372   bool hasVCDir =
00373       getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
00374                               "InstallDir", vsIDEInstallDir, nullptr);
00375   if (hasVCDir && !vsIDEInstallDir.empty()) {
00376     path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
00377     return true;
00378   }
00379 
00380   bool hasVCExpressDir =
00381       getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
00382                               "InstallDir", vsExpressIDEInstallDir, nullptr);
00383   if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
00384     path = vsExpressIDEInstallDir.substr(
00385         0, vsIDEInstallDir.find("\\Common7\\IDE"));
00386     return true;
00387   }
00388 
00389   // Try the environment.
00390   const char *vs120comntools = getenv("VS120COMNTOOLS");
00391   const char *vs100comntools = getenv("VS100COMNTOOLS");
00392   const char *vs90comntools = getenv("VS90COMNTOOLS");
00393   const char *vs80comntools = getenv("VS80COMNTOOLS");
00394 
00395   const char *vscomntools = nullptr;
00396 
00397   // Find any version we can
00398   if (vs120comntools)
00399     vscomntools = vs120comntools;
00400   else if (vs100comntools)
00401     vscomntools = vs100comntools;
00402   else if (vs90comntools)
00403     vscomntools = vs90comntools;
00404   else if (vs80comntools)
00405     vscomntools = vs80comntools;
00406 
00407   if (vscomntools && *vscomntools) {
00408     const char *p = strstr(vscomntools, "\\Common7\\Tools");
00409     path = p ? std::string(vscomntools, p) : vscomntools;
00410     return true;
00411   }
00412   return false;
00413 }
00414 
00415 void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs,
00416                                                   ArgStringList &CC1Args,
00417                                                   const std::string &folder,
00418                                                   const char *subfolder) const {
00419   llvm::SmallString<128> path(folder);
00420   llvm::sys::path::append(path, subfolder);
00421   addSystemInclude(DriverArgs, CC1Args, path.str());
00422 }
00423 
00424 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
00425                                               ArgStringList &CC1Args) const {
00426   if (DriverArgs.hasArg(options::OPT_nostdinc))
00427     return;
00428 
00429   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
00430     SmallString<128> P(getDriver().ResourceDir);
00431     llvm::sys::path::append(P, "include");
00432     addSystemInclude(DriverArgs, CC1Args, P.str());
00433   }
00434 
00435   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
00436     return;
00437 
00438   // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
00439   if (const char *cl_include_dir = getenv("INCLUDE")) {
00440     SmallVector<StringRef, 8> Dirs;
00441     StringRef(cl_include_dir)
00442         .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
00443     for (StringRef Dir : Dirs)
00444       addSystemInclude(DriverArgs, CC1Args, Dir);
00445     if (!Dirs.empty())
00446       return;
00447   }
00448 
00449   std::string VSDir;
00450 
00451   // When built with access to the proper Windows APIs, try to actually find
00452   // the correct include paths first.
00453   if (getVisualStudioInstallDir(VSDir)) {
00454     AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
00455 
00456     std::string WindowsSDKDir;
00457     int major, minor;
00458     if (getWindowsSDKDir(WindowsSDKDir, major, minor)) {
00459       if (major >= 8) {
00460         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
00461                                       "include\\shared");
00462         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
00463                                       "include\\um");
00464         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
00465                                       "include\\winrt");
00466       } else {
00467         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
00468                                       "include");
00469       }
00470     } else {
00471       addSystemInclude(DriverArgs, CC1Args, VSDir);
00472     }
00473     return;
00474   }
00475 
00476   // As a fallback, select default install paths.
00477   // FIXME: Don't guess drives and paths like this on Windows.
00478   const StringRef Paths[] = {
00479     "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
00480     "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
00481     "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
00482     "C:/Program Files/Microsoft Visual Studio 8/VC/include",
00483     "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
00484   };
00485   addSystemIncludes(DriverArgs, CC1Args, Paths);
00486 }
00487 
00488 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
00489                                                  ArgStringList &CC1Args) const {
00490   // FIXME: There should probably be logic here to find libc++ on Windows.
00491 }