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