Home | History | Annotate | Download | only in Driver
      1 //===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "ToolChains.h"
     11 #include "clang/Basic/CharInfo.h"
     12 #include "clang/Basic/Version.h"
     13 #include "clang/Driver/Compilation.h"
     14 #include "clang/Driver/Driver.h"
     15 #include "clang/Driver/DriverDiagnostic.h"
     16 #include "clang/Driver/Options.h"
     17 #include "llvm/ADT/StringExtras.h"
     18 #include "llvm/Config/llvm-config.h"
     19 #include "llvm/Option/Arg.h"
     20 #include "llvm/Option/ArgList.h"
     21 #include "llvm/Support/ErrorHandling.h"
     22 #include "llvm/Support/FileSystem.h"
     23 #include "llvm/Support/Process.h"
     24 #include <cstdio>
     25 
     26 // Include the necessary headers to interface with the Windows registry and
     27 // environment.
     28 #if defined(LLVM_ON_WIN32)
     29 #define USE_WIN32
     30 #endif
     31 
     32 #ifdef USE_WIN32
     33   #define WIN32_LEAN_AND_MEAN
     34   #define NOGDI
     35   #ifndef NOMINMAX
     36     #define NOMINMAX
     37   #endif
     38   #include <windows.h>
     39 #endif
     40 
     41 using namespace clang::driver;
     42 using namespace clang::driver::toolchains;
     43 using namespace clang;
     44 using namespace llvm::opt;
     45 
     46 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
     47                              const ArgList &Args)
     48   : ToolChain(D, Triple, Args) {
     49   getProgramPaths().push_back(getDriver().getInstalledDir());
     50   if (getDriver().getInstalledDir() != getDriver().Dir)
     51     getProgramPaths().push_back(getDriver().Dir);
     52 }
     53 
     54 Tool *MSVCToolChain::buildLinker() const {
     55   return new tools::visualstudio::Link(*this);
     56 }
     57 
     58 Tool *MSVCToolChain::buildAssembler() const {
     59   if (getTriple().isOSBinFormatMachO())
     60     return new tools::darwin::Assemble(*this);
     61   getDriver().Diag(clang::diag::err_no_external_assembler);
     62   return nullptr;
     63 }
     64 
     65 bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
     66   return true;
     67 }
     68 
     69 bool MSVCToolChain::IsUnwindTablesDefault() const {
     70   // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
     71   // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
     72   // how to generate them yet.
     73   return getArch() == llvm::Triple::x86_64;
     74 }
     75 
     76 bool MSVCToolChain::isPICDefault() const {
     77   return getArch() == llvm::Triple::x86_64;
     78 }
     79 
     80 bool MSVCToolChain::isPIEDefault() const {
     81   return false;
     82 }
     83 
     84 bool MSVCToolChain::isPICDefaultForced() const {
     85   return getArch() == llvm::Triple::x86_64;
     86 }
     87 
     88 #ifdef USE_WIN32
     89 static bool readFullStringValue(HKEY hkey, const char *valueName,
     90                                 std::string &value) {
     91   // FIXME: We should be using the W versions of the registry functions, but
     92   // doing so requires UTF8 / UTF16 conversions similar to how we handle command
     93   // line arguments.  The UTF8 conversion functions are not exposed publicly
     94   // from LLVM though, so in order to do this we will probably need to create
     95   // a registry abstraction in LLVMSupport that is Windows only.
     96   DWORD result = 0;
     97   DWORD valueSize = 0;
     98   DWORD type = 0;
     99   // First just query for the required size.
    100   result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize);
    101   if (result != ERROR_SUCCESS || type != REG_SZ)
    102     return false;
    103   std::vector<BYTE> buffer(valueSize);
    104   result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize);
    105   if (result == ERROR_SUCCESS)
    106     value.assign(reinterpret_cast<const char *>(buffer.data()));
    107   return result;
    108 }
    109 #endif
    110 
    111 /// \brief Read registry string.
    112 /// This also supports a means to look for high-versioned keys by use
    113 /// of a $VERSION placeholder in the key path.
    114 /// $VERSION in the key path is a placeholder for the version number,
    115 /// causing the highest value path to be searched for and used.
    116 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
    117 /// There can be additional characters in the component.  Only the numeric
    118 /// characters are compared.  This function only searches HKLM.
    119 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
    120                                     std::string &value, std::string *phValue) {
    121 #ifndef USE_WIN32
    122   return false;
    123 #else
    124   HKEY hRootKey = HKEY_LOCAL_MACHINE;
    125   HKEY hKey = NULL;
    126   long lResult;
    127   bool returnValue = false;
    128 
    129   const char *placeHolder = strstr(keyPath, "$VERSION");
    130   std::string bestName;
    131   // If we have a $VERSION placeholder, do the highest-version search.
    132   if (placeHolder) {
    133     const char *keyEnd = placeHolder - 1;
    134     const char *nextKey = placeHolder;
    135     // Find end of previous key.
    136     while ((keyEnd > keyPath) && (*keyEnd != '\\'))
    137       keyEnd--;
    138     // Find end of key containing $VERSION.
    139     while (*nextKey && (*nextKey != '\\'))
    140       nextKey++;
    141     size_t partialKeyLength = keyEnd - keyPath;
    142     char partialKey[256];
    143     if (partialKeyLength > sizeof(partialKey))
    144       partialKeyLength = sizeof(partialKey);
    145     strncpy(partialKey, keyPath, partialKeyLength);
    146     partialKey[partialKeyLength] = '\0';
    147     HKEY hTopKey = NULL;
    148     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
    149                            &hTopKey);
    150     if (lResult == ERROR_SUCCESS) {
    151       char keyName[256];
    152       double bestValue = 0.0;
    153       DWORD index, size = sizeof(keyName) - 1;
    154       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
    155           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
    156         const char *sp = keyName;
    157         while (*sp && !isDigit(*sp))
    158           sp++;
    159         if (!*sp)
    160           continue;
    161         const char *ep = sp + 1;
    162         while (*ep && (isDigit(*ep) || (*ep == '.')))
    163           ep++;
    164         char numBuf[32];
    165         strncpy(numBuf, sp, sizeof(numBuf) - 1);
    166         numBuf[sizeof(numBuf) - 1] = '\0';
    167         double dvalue = strtod(numBuf, NULL);
    168         if (dvalue > bestValue) {
    169           // Test that InstallDir is indeed there before keeping this index.
    170           // Open the chosen key path remainder.
    171           bestName = keyName;
    172           // Append rest of key.
    173           bestName.append(nextKey);
    174           lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0,
    175                                  KEY_READ | KEY_WOW64_32KEY, &hKey);
    176           if (lResult == ERROR_SUCCESS) {
    177             lResult = readFullStringValue(hKey, valueName, value);
    178             if (lResult == ERROR_SUCCESS) {
    179               bestValue = dvalue;
    180               if (phValue)
    181                 *phValue = bestName;
    182               returnValue = true;
    183             }
    184             RegCloseKey(hKey);
    185           }
    186         }
    187         size = sizeof(keyName) - 1;
    188       }
    189       RegCloseKey(hTopKey);
    190     }
    191   } else {
    192     lResult =
    193         RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
    194     if (lResult == ERROR_SUCCESS) {
    195       lResult = readFullStringValue(hKey, valueName, value);
    196       if (lResult == ERROR_SUCCESS)
    197         returnValue = true;
    198       if (phValue)
    199         phValue->clear();
    200       RegCloseKey(hKey);
    201     }
    202   }
    203   return returnValue;
    204 #endif // USE_WIN32
    205 }
    206 
    207 /// \brief Get Windows SDK installation directory.
    208 bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major,
    209                                      int &minor) const {
    210   std::string sdkVersion;
    211   // Try the Windows registry.
    212   bool hasSDKDir = getSystemRegistryString(
    213       "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
    214       "InstallationFolder", path, &sdkVersion);
    215   if (!sdkVersion.empty())
    216     std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
    217   return hasSDKDir && !path.empty();
    218 }
    219 
    220 // Gets the library path required to link against the Windows SDK.
    221 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
    222   std::string sdkPath;
    223   int sdkMajor = 0;
    224   int sdkMinor = 0;
    225 
    226   path.clear();
    227   if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor))
    228     return false;
    229 
    230   llvm::SmallString<128> libPath(sdkPath);
    231   llvm::sys::path::append(libPath, "Lib");
    232   if (sdkMajor <= 7) {
    233     switch (getArch()) {
    234     // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
    235     case llvm::Triple::x86:
    236       break;
    237     case llvm::Triple::x86_64:
    238       llvm::sys::path::append(libPath, "x64");
    239       break;
    240     case llvm::Triple::arm:
    241       // It is not necessary to link against Windows SDK 7.x when targeting ARM.
    242       return false;
    243     default:
    244       return false;
    245     }
    246   } else {
    247     // Windows SDK 8.x installs libraries in a folder whose names depend on the
    248     // version of the OS you're targeting.  By default choose the newest, which
    249     // usually corresponds to the version of the OS you've installed the SDK on.
    250     const char *tests[] = {"winv6.3", "win8", "win7"};
    251     bool found = false;
    252     for (const char *test : tests) {
    253       llvm::SmallString<128> testPath(libPath);
    254       llvm::sys::path::append(testPath, test);
    255       if (llvm::sys::fs::exists(testPath.c_str())) {
    256         libPath = testPath;
    257         found = true;
    258         break;
    259       }
    260     }
    261 
    262     if (!found)
    263       return false;
    264 
    265     llvm::sys::path::append(libPath, "um");
    266     switch (getArch()) {
    267     case llvm::Triple::x86:
    268       llvm::sys::path::append(libPath, "x86");
    269       break;
    270     case llvm::Triple::x86_64:
    271       llvm::sys::path::append(libPath, "x64");
    272       break;
    273     case llvm::Triple::arm:
    274       llvm::sys::path::append(libPath, "arm");
    275       break;
    276     default:
    277       return false;
    278     }
    279   }
    280 
    281   path = libPath.str();
    282   return true;
    283 }
    284 
    285 // Get the location to use for Visual Studio binaries.  The location priority
    286 // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on
    287 // system (as reported by the registry).
    288 bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
    289                                                   std::string &path) const {
    290   path.clear();
    291 
    292   SmallString<128> BinDir;
    293 
    294   // First check the environment variables that vsvars32.bat sets.
    295   llvm::Optional<std::string> VcInstallDir =
    296       llvm::sys::Process::GetEnv("VCINSTALLDIR");
    297   if (VcInstallDir.hasValue()) {
    298     BinDir = VcInstallDir.getValue();
    299     llvm::sys::path::append(BinDir, "bin");
    300   } else {
    301     // Next walk the PATH, trying to find a cl.exe in the path.  If we find one,
    302     // use that.  However, make sure it's not clang's cl.exe.
    303     llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
    304     if (OptPath.hasValue()) {
    305       const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
    306       SmallVector<StringRef, 8> PathSegments;
    307       llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
    308 
    309       for (StringRef PathSegment : PathSegments) {
    310         if (PathSegment.empty())
    311           continue;
    312 
    313         SmallString<128> FilePath(PathSegment);
    314         llvm::sys::path::append(FilePath, "cl.exe");
    315         if (llvm::sys::fs::can_execute(FilePath.c_str()) &&
    316             !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) {
    317           // If we found it on the PATH, use it exactly as is with no
    318           // modifications.
    319           path = PathSegment;
    320           return true;
    321         }
    322       }
    323     }
    324 
    325     std::string installDir;
    326     // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the
    327     // registry then we have no choice but to fail.
    328     if (!getVisualStudioInstallDir(installDir))
    329       return false;
    330 
    331     // Regardless of what binary we're ultimately trying to find, we make sure
    332     // that this is a Visual Studio directory by checking for cl.exe.  We use
    333     // cl.exe instead of other binaries like link.exe because programs such as
    334     // GnuWin32 also have a utility called link.exe, so cl.exe is the least
    335     // ambiguous.
    336     BinDir = installDir;
    337     llvm::sys::path::append(BinDir, "VC", "bin");
    338     SmallString<128> ClPath(BinDir);
    339     llvm::sys::path::append(ClPath, "cl.exe");
    340 
    341     if (!llvm::sys::fs::can_execute(ClPath.c_str()))
    342       return false;
    343   }
    344 
    345   if (BinDir.empty())
    346     return false;
    347 
    348   switch (getArch()) {
    349   case llvm::Triple::x86:
    350     break;
    351   case llvm::Triple::x86_64:
    352     llvm::sys::path::append(BinDir, "amd64");
    353     break;
    354   case llvm::Triple::arm:
    355     llvm::sys::path::append(BinDir, "arm");
    356     break;
    357   default:
    358     // Whatever this is, Visual Studio doesn't have a toolchain for it.
    359     return false;
    360   }
    361   path = BinDir.str();
    362   return true;
    363 }
    364 
    365 // Get Visual Studio installation directory.
    366 bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
    367   // First check the environment variables that vsvars32.bat sets.
    368   const char *vcinstalldir = getenv("VCINSTALLDIR");
    369   if (vcinstalldir) {
    370     path = vcinstalldir;
    371     path = path.substr(0, path.find("\\VC"));
    372     return true;
    373   }
    374 
    375   std::string vsIDEInstallDir;
    376   std::string vsExpressIDEInstallDir;
    377   // Then try the windows registry.
    378   bool hasVCDir =
    379       getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
    380                               "InstallDir", vsIDEInstallDir, nullptr);
    381   if (hasVCDir && !vsIDEInstallDir.empty()) {
    382     path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE"));
    383     return true;
    384   }
    385 
    386   bool hasVCExpressDir =
    387       getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
    388                               "InstallDir", vsExpressIDEInstallDir, nullptr);
    389   if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) {
    390     path = vsExpressIDEInstallDir.substr(
    391         0, vsIDEInstallDir.find("\\Common7\\IDE"));
    392     return true;
    393   }
    394 
    395   // Try the environment.
    396   const char *vs120comntools = getenv("VS120COMNTOOLS");
    397   const char *vs100comntools = getenv("VS100COMNTOOLS");
    398   const char *vs90comntools = getenv("VS90COMNTOOLS");
    399   const char *vs80comntools = getenv("VS80COMNTOOLS");
    400 
    401   const char *vscomntools = nullptr;
    402 
    403   // Find any version we can
    404   if (vs120comntools)
    405     vscomntools = vs120comntools;
    406   else if (vs100comntools)
    407     vscomntools = vs100comntools;
    408   else if (vs90comntools)
    409     vscomntools = vs90comntools;
    410   else if (vs80comntools)
    411     vscomntools = vs80comntools;
    412 
    413   if (vscomntools && *vscomntools) {
    414     const char *p = strstr(vscomntools, "\\Common7\\Tools");
    415     path = p ? std::string(vscomntools, p) : vscomntools;
    416     return true;
    417   }
    418   return false;
    419 }
    420 
    421 void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs,
    422                                                   ArgStringList &CC1Args,
    423                                                   const std::string &folder,
    424                                                   const char *subfolder) const {
    425   llvm::SmallString<128> path(folder);
    426   llvm::sys::path::append(path, subfolder);
    427   addSystemInclude(DriverArgs, CC1Args, path);
    428 }
    429 
    430 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    431                                               ArgStringList &CC1Args) const {
    432   if (DriverArgs.hasArg(options::OPT_nostdinc))
    433     return;
    434 
    435   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
    436     SmallString<128> P(getDriver().ResourceDir);
    437     llvm::sys::path::append(P, "include");
    438     addSystemInclude(DriverArgs, CC1Args, P);
    439   }
    440 
    441   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
    442     return;
    443 
    444   // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
    445   if (const char *cl_include_dir = getenv("INCLUDE")) {
    446     SmallVector<StringRef, 8> Dirs;
    447     StringRef(cl_include_dir)
    448         .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
    449     for (StringRef Dir : Dirs)
    450       addSystemInclude(DriverArgs, CC1Args, Dir);
    451     if (!Dirs.empty())
    452       return;
    453   }
    454 
    455   std::string VSDir;
    456 
    457   // When built with access to the proper Windows APIs, try to actually find
    458   // the correct include paths first.
    459   if (getVisualStudioInstallDir(VSDir)) {
    460     AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include");
    461 
    462     std::string WindowsSDKDir;
    463     int major, minor;
    464     if (getWindowsSDKDir(WindowsSDKDir, major, minor)) {
    465       if (major >= 8) {
    466         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
    467                                       "include\\shared");
    468         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
    469                                       "include\\um");
    470         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
    471                                       "include\\winrt");
    472       } else {
    473         AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
    474                                       "include");
    475       }
    476     } else {
    477       addSystemInclude(DriverArgs, CC1Args, VSDir);
    478     }
    479     return;
    480   }
    481 
    482   // As a fallback, select default install paths.
    483   // FIXME: Don't guess drives and paths like this on Windows.
    484   const StringRef Paths[] = {
    485     "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
    486     "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
    487     "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
    488     "C:/Program Files/Microsoft Visual Studio 8/VC/include",
    489     "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
    490   };
    491   addSystemIncludes(DriverArgs, CC1Args, Paths);
    492 }
    493 
    494 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
    495                                                  ArgStringList &CC1Args) const {
    496   // FIXME: There should probably be logic here to find libc++ on Windows.
    497 }
    498