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