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/Option/Arg.h"
     18 #include "llvm/Option/ArgList.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Support/Path.h"
     21 
     22 // Include the necessary headers to interface with the Windows registry and
     23 // environment.
     24 #ifdef _MSC_VER
     25   #define WIN32_LEAN_AND_MEAN
     26   #define NOGDI
     27   #define NOMINMAX
     28   #include <Windows.h>
     29 #endif
     30 
     31 using namespace clang::driver;
     32 using namespace clang::driver::toolchains;
     33 using namespace clang;
     34 using namespace llvm::opt;
     35 
     36 Windows::Windows(const Driver &D, const llvm::Triple& Triple,
     37                  const ArgList &Args)
     38   : ToolChain(D, Triple, Args) {
     39 }
     40 
     41 Tool *Windows::buildLinker() const {
     42   return new tools::visualstudio::Link(*this);
     43 }
     44 
     45 Tool *Windows::buildAssembler() const {
     46   if (getTriple().getEnvironment() == llvm::Triple::MachO)
     47     return new tools::darwin::Assemble(*this);
     48   getDriver().Diag(clang::diag::err_no_external_windows_assembler);
     49   return NULL;
     50 }
     51 
     52 bool Windows::IsIntegratedAssemblerDefault() const {
     53   return true;
     54 }
     55 
     56 bool Windows::IsUnwindTablesDefault() const {
     57   return getArch() == llvm::Triple::x86_64;
     58 }
     59 
     60 bool Windows::isPICDefault() const {
     61   return getArch() == llvm::Triple::x86_64;
     62 }
     63 
     64 bool Windows::isPIEDefault() const {
     65   return false;
     66 }
     67 
     68 bool Windows::isPICDefaultForced() const {
     69   return getArch() == llvm::Triple::x86_64;
     70 }
     71 
     72 // FIXME: This probably should goto to some platform utils place.
     73 #ifdef _MSC_VER
     74 
     75 /// \brief Read registry string.
     76 /// This also supports a means to look for high-versioned keys by use
     77 /// of a $VERSION placeholder in the key path.
     78 /// $VERSION in the key path is a placeholder for the version number,
     79 /// causing the highest value path to be searched for and used.
     80 /// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
     81 /// There can be additional characters in the component.  Only the numberic
     82 /// characters are compared.
     83 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
     84                                     char *value, size_t maxLength) {
     85   HKEY hRootKey = NULL;
     86   HKEY hKey = NULL;
     87   const char* subKey = NULL;
     88   DWORD valueType;
     89   DWORD valueSize = maxLength - 1;
     90   long lResult;
     91   bool returnValue = false;
     92 
     93   if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
     94     hRootKey = HKEY_CLASSES_ROOT;
     95     subKey = keyPath + 18;
     96   } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
     97     hRootKey = HKEY_USERS;
     98     subKey = keyPath + 11;
     99   } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
    100     hRootKey = HKEY_LOCAL_MACHINE;
    101     subKey = keyPath + 19;
    102   } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
    103     hRootKey = HKEY_CURRENT_USER;
    104     subKey = keyPath + 18;
    105   } else {
    106     return false;
    107   }
    108 
    109   const char *placeHolder = strstr(subKey, "$VERSION");
    110   char bestName[256];
    111   bestName[0] = '\0';
    112   // If we have a $VERSION placeholder, do the highest-version search.
    113   if (placeHolder) {
    114     const char *keyEnd = placeHolder - 1;
    115     const char *nextKey = placeHolder;
    116     // Find end of previous key.
    117     while ((keyEnd > subKey) && (*keyEnd != '\\'))
    118       keyEnd--;
    119     // Find end of key containing $VERSION.
    120     while (*nextKey && (*nextKey != '\\'))
    121       nextKey++;
    122     size_t partialKeyLength = keyEnd - subKey;
    123     char partialKey[256];
    124     if (partialKeyLength > sizeof(partialKey))
    125       partialKeyLength = sizeof(partialKey);
    126     strncpy(partialKey, subKey, partialKeyLength);
    127     partialKey[partialKeyLength] = '\0';
    128     HKEY hTopKey = NULL;
    129     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
    130     if (lResult == ERROR_SUCCESS) {
    131       char keyName[256];
    132       int bestIndex = -1;
    133       double bestValue = 0.0;
    134       DWORD index, size = sizeof(keyName) - 1;
    135       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
    136           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
    137         const char *sp = keyName;
    138         while (*sp && !isDigit(*sp))
    139           sp++;
    140         if (!*sp)
    141           continue;
    142         const char *ep = sp + 1;
    143         while (*ep && (isDigit(*ep) || (*ep == '.')))
    144           ep++;
    145         char numBuf[32];
    146         strncpy(numBuf, sp, sizeof(numBuf) - 1);
    147         numBuf[sizeof(numBuf) - 1] = '\0';
    148         double value = strtod(numBuf, NULL);
    149         if (value > bestValue) {
    150           bestIndex = (int)index;
    151           bestValue = value;
    152           strcpy(bestName, keyName);
    153         }
    154         size = sizeof(keyName) - 1;
    155       }
    156       // If we found the highest versioned key, open the key and get the value.
    157       if (bestIndex != -1) {
    158         // Append rest of key.
    159         strncat(bestName, nextKey, sizeof(bestName) - 1);
    160         bestName[sizeof(bestName) - 1] = '\0';
    161         // Open the chosen key path remainder.
    162         lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
    163         if (lResult == ERROR_SUCCESS) {
    164           lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
    165             (LPBYTE)value, &valueSize);
    166           if (lResult == ERROR_SUCCESS)
    167             returnValue = true;
    168           RegCloseKey(hKey);
    169         }
    170       }
    171       RegCloseKey(hTopKey);
    172     }
    173   } else {
    174     lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
    175     if (lResult == ERROR_SUCCESS) {
    176       lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
    177         (LPBYTE)value, &valueSize);
    178       if (lResult == ERROR_SUCCESS)
    179         returnValue = true;
    180       RegCloseKey(hKey);
    181     }
    182   }
    183   return returnValue;
    184 }
    185 
    186 /// \brief Get Windows SDK installation directory.
    187 static bool getWindowsSDKDir(std::string &path) {
    188   char windowsSDKInstallDir[256];
    189   // Try the Windows registry.
    190   bool hasSDKDir = getSystemRegistryString(
    191    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
    192                                            "InstallationFolder",
    193                                            windowsSDKInstallDir,
    194                                            sizeof(windowsSDKInstallDir) - 1);
    195     // If we have both vc80 and vc90, pick version we were compiled with.
    196   if (hasSDKDir && windowsSDKInstallDir[0]) {
    197     path = windowsSDKInstallDir;
    198     return true;
    199   }
    200   return false;
    201 }
    202 
    203   // Get Visual Studio installation directory.
    204 static bool getVisualStudioDir(std::string &path) {
    205   // First check the environment variables that vsvars32.bat sets.
    206   const char* vcinstalldir = getenv("VCINSTALLDIR");
    207   if (vcinstalldir) {
    208     char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
    209     if (p)
    210       *p = '\0';
    211     path = vcinstalldir;
    212     return true;
    213   }
    214 
    215   char vsIDEInstallDir[256];
    216   char vsExpressIDEInstallDir[256];
    217   // Then try the windows registry.
    218   bool hasVCDir = getSystemRegistryString(
    219     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
    220     "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
    221   bool hasVCExpressDir = getSystemRegistryString(
    222     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
    223     "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
    224     // If we have both vc80 and vc90, pick version we were compiled with.
    225   if (hasVCDir && vsIDEInstallDir[0]) {
    226     char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
    227     if (p)
    228       *p = '\0';
    229     path = vsIDEInstallDir;
    230     return true;
    231   }
    232 
    233   if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
    234     char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
    235     if (p)
    236       *p = '\0';
    237     path = vsExpressIDEInstallDir;
    238     return true;
    239   }
    240 
    241   // Try the environment.
    242   const char *vs100comntools = getenv("VS100COMNTOOLS");
    243   const char *vs90comntools = getenv("VS90COMNTOOLS");
    244   const char *vs80comntools = getenv("VS80COMNTOOLS");
    245   const char *vscomntools = NULL;
    246 
    247   // Try to find the version that we were compiled with
    248   if(false) {}
    249   #if (_MSC_VER >= 1600)  // VC100
    250   else if(vs100comntools) {
    251     vscomntools = vs100comntools;
    252   }
    253   #elif (_MSC_VER == 1500) // VC80
    254   else if(vs90comntools) {
    255     vscomntools = vs90comntools;
    256   }
    257   #elif (_MSC_VER == 1400) // VC80
    258   else if(vs80comntools) {
    259     vscomntools = vs80comntools;
    260   }
    261   #endif
    262   // Otherwise find any version we can
    263   else if (vs100comntools)
    264     vscomntools = vs100comntools;
    265   else if (vs90comntools)
    266     vscomntools = vs90comntools;
    267   else if (vs80comntools)
    268     vscomntools = vs80comntools;
    269 
    270   if (vscomntools && *vscomntools) {
    271     const char *p = strstr(vscomntools, "\\Common7\\Tools");
    272     path = p ? std::string(vscomntools, p) : vscomntools;
    273     return true;
    274   }
    275   return false;
    276 }
    277 
    278 #endif // _MSC_VER
    279 
    280 void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
    281                                         ArgStringList &CC1Args) const {
    282   if (DriverArgs.hasArg(options::OPT_nostdinc))
    283     return;
    284 
    285   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
    286     SmallString<128> P(getDriver().ResourceDir);
    287     llvm::sys::path::append(P, "include");
    288     addSystemInclude(DriverArgs, CC1Args, P.str());
    289   }
    290 
    291   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
    292     return;
    293 
    294 #ifdef _MSC_VER
    295   // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
    296   if (const char *cl_include_dir = getenv("INCLUDE")) {
    297     SmallVector<StringRef, 8> Dirs;
    298     StringRef(cl_include_dir).split(Dirs, ";");
    299     int n = 0;
    300     for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
    301          I != E; ++I) {
    302       StringRef d = *I;
    303       if (d.size() == 0)
    304         continue;
    305       ++n;
    306       addSystemInclude(DriverArgs, CC1Args, d);
    307     }
    308     if (n) return;
    309   }
    310 
    311   std::string VSDir;
    312   std::string WindowsSDKDir;
    313 
    314   // When built with access to the proper Windows APIs, try to actually find
    315   // the correct include paths first.
    316   if (getVisualStudioDir(VSDir)) {
    317     addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
    318     if (getWindowsSDKDir(WindowsSDKDir))
    319       addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
    320     else
    321       addSystemInclude(DriverArgs, CC1Args,
    322                        VSDir + "\\VC\\PlatformSDK\\Include");
    323     return;
    324   }
    325 #endif // _MSC_VER
    326 
    327   // As a fallback, select default install paths.
    328   const StringRef Paths[] = {
    329     "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
    330     "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
    331     "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
    332     "C:/Program Files/Microsoft Visual Studio 8/VC/include",
    333     "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
    334   };
    335   addSystemIncludes(DriverArgs, CC1Args, Paths);
    336 }
    337 
    338 void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
    339                                            ArgStringList &CC1Args) const {
    340   // FIXME: There should probably be logic here to find libc++ on Windows.
    341 }
    342