clang API Documentation

WindowsToolChain.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 
00012 #include "clang/Driver/Arg.h"
00013 #include "clang/Driver/ArgList.h"
00014 #include "clang/Driver/Compilation.h"
00015 #include "clang/Driver/Driver.h"
00016 #include "clang/Driver/Options.h"
00017 #include "clang/Basic/Version.h"
00018 #include "llvm/Support/ErrorHandling.h"
00019 #include "llvm/Support/Path.h"
00020 
00021 // Include the necessary headers to interface with the Windows registry and
00022 // environment.
00023 #ifdef _MSC_VER
00024   #define WIN32_LEAN_AND_MEAN
00025   #define NOGDI
00026   #define NOMINMAX
00027   #include <Windows.h>
00028 #endif
00029 
00030 using namespace clang::driver;
00031 using namespace clang::driver::toolchains;
00032 using namespace clang;
00033 
00034 Windows::Windows(const Driver &D, const llvm::Triple& Triple)
00035   : ToolChain(D, Triple) {
00036 }
00037 
00038 Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA,
00039                           const ActionList &Inputs) const {
00040   Action::ActionClass Key;
00041   if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
00042     Key = Action::AnalyzeJobClass;
00043   else
00044     Key = JA.getKind();
00045 
00046   bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
00047                                              options::OPT_no_integrated_as,
00048                                              IsIntegratedAssemblerDefault());
00049 
00050   Tool *&T = Tools[Key];
00051   if (!T) {
00052     switch (Key) {
00053     case Action::InputClass:
00054     case Action::BindArchClass:
00055     case Action::LipoJobClass:
00056     case Action::DsymutilJobClass:
00057     case Action::VerifyJobClass:
00058       llvm_unreachable("Invalid tool kind.");
00059     case Action::PreprocessJobClass:
00060     case Action::PrecompileJobClass:
00061     case Action::AnalyzeJobClass:
00062     case Action::MigrateJobClass:
00063     case Action::CompileJobClass:
00064       T = new tools::Clang(*this); break;
00065     case Action::AssembleJobClass:
00066       if (!UseIntegratedAs && getTriple().getEnvironment() == llvm::Triple::MachO)
00067         T = new tools::darwin::Assemble(*this);
00068       else
00069         T = new tools::ClangAs(*this);
00070       break;
00071     case Action::LinkJobClass:
00072       T = new tools::visualstudio::Link(*this); break;
00073     }
00074   }
00075 
00076   return *T;
00077 }
00078 
00079 bool Windows::IsIntegratedAssemblerDefault() const {
00080   return true;
00081 }
00082 
00083 bool Windows::IsUnwindTablesDefault() const {
00084   // FIXME: Gross; we should probably have some separate target
00085   // definition, possibly even reusing the one in clang.
00086   return getArchName() == "x86_64";
00087 }
00088 
00089 const char *Windows::GetDefaultRelocationModel() const {
00090   return "static";
00091 }
00092 
00093 const char *Windows::GetForcedPicModel() const {
00094   if (getArchName() == "x86_64")
00095     return "pic";
00096   return 0;
00097 }
00098 
00099 // FIXME: This probably should goto to some platform utils place.
00100 #ifdef _MSC_VER
00101 
00102 /// \brief Read registry string.
00103 /// This also supports a means to look for high-versioned keys by use
00104 /// of a $VERSION placeholder in the key path.
00105 /// $VERSION in the key path is a placeholder for the version number,
00106 /// causing the highest value path to be searched for and used.
00107 /// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
00108 /// There can be additional characters in the component.  Only the numberic
00109 /// characters are compared.
00110 static bool getSystemRegistryString(const char *keyPath, const char *valueName,
00111                                     char *value, size_t maxLength) {
00112   HKEY hRootKey = NULL;
00113   HKEY hKey = NULL;
00114   const char* subKey = NULL;
00115   DWORD valueType;
00116   DWORD valueSize = maxLength - 1;
00117   long lResult;
00118   bool returnValue = false;
00119 
00120   if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) {
00121     hRootKey = HKEY_CLASSES_ROOT;
00122     subKey = keyPath + 18;
00123   } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) {
00124     hRootKey = HKEY_USERS;
00125     subKey = keyPath + 11;
00126   } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) {
00127     hRootKey = HKEY_LOCAL_MACHINE;
00128     subKey = keyPath + 19;
00129   } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) {
00130     hRootKey = HKEY_CURRENT_USER;
00131     subKey = keyPath + 18;
00132   } else {
00133     return false;
00134   }
00135 
00136   const char *placeHolder = strstr(subKey, "$VERSION");
00137   char bestName[256];
00138   bestName[0] = '\0';
00139   // If we have a $VERSION placeholder, do the highest-version search.
00140   if (placeHolder) {
00141     const char *keyEnd = placeHolder - 1;
00142     const char *nextKey = placeHolder;
00143     // Find end of previous key.
00144     while ((keyEnd > subKey) && (*keyEnd != '\\'))
00145       keyEnd--;
00146     // Find end of key containing $VERSION.
00147     while (*nextKey && (*nextKey != '\\'))
00148       nextKey++;
00149     size_t partialKeyLength = keyEnd - subKey;
00150     char partialKey[256];
00151     if (partialKeyLength > sizeof(partialKey))
00152       partialKeyLength = sizeof(partialKey);
00153     strncpy(partialKey, subKey, partialKeyLength);
00154     partialKey[partialKeyLength] = '\0';
00155     HKEY hTopKey = NULL;
00156     lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey);
00157     if (lResult == ERROR_SUCCESS) {
00158       char keyName[256];
00159       int bestIndex = -1;
00160       double bestValue = 0.0;
00161       DWORD index, size = sizeof(keyName) - 1;
00162       for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL,
00163           NULL, NULL, NULL) == ERROR_SUCCESS; index++) {
00164         const char *sp = keyName;
00165         while (*sp && !isdigit(*sp))
00166           sp++;
00167         if (!*sp)
00168           continue;
00169         const char *ep = sp + 1;
00170         while (*ep && (isdigit(*ep) || (*ep == '.')))
00171           ep++;
00172         char numBuf[32];
00173         strncpy(numBuf, sp, sizeof(numBuf) - 1);
00174         numBuf[sizeof(numBuf) - 1] = '\0';
00175         double value = strtod(numBuf, NULL);
00176         if (value > bestValue) {
00177           bestIndex = (int)index;
00178           bestValue = value;
00179           strcpy(bestName, keyName);
00180         }
00181         size = sizeof(keyName) - 1;
00182       }
00183       // If we found the highest versioned key, open the key and get the value.
00184       if (bestIndex != -1) {
00185         // Append rest of key.
00186         strncat(bestName, nextKey, sizeof(bestName) - 1);
00187         bestName[sizeof(bestName) - 1] = '\0';
00188         // Open the chosen key path remainder.
00189         lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey);
00190         if (lResult == ERROR_SUCCESS) {
00191           lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
00192             (LPBYTE)value, &valueSize);
00193           if (lResult == ERROR_SUCCESS)
00194             returnValue = true;
00195           RegCloseKey(hKey);
00196         }
00197       }
00198       RegCloseKey(hTopKey);
00199     }
00200   } else {
00201     lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey);
00202     if (lResult == ERROR_SUCCESS) {
00203       lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType,
00204         (LPBYTE)value, &valueSize);
00205       if (lResult == ERROR_SUCCESS)
00206         returnValue = true;
00207       RegCloseKey(hKey);
00208     }
00209   }
00210   return returnValue;
00211 }
00212 
00213 /// \brief Get Windows SDK installation directory.
00214 static bool getWindowsSDKDir(std::string &path) {
00215   char windowsSDKInstallDir[256];
00216   // Try the Windows registry.
00217   bool hasSDKDir = getSystemRegistryString(
00218    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
00219                                            "InstallationFolder",
00220                                            windowsSDKInstallDir,
00221                                            sizeof(windowsSDKInstallDir) - 1);
00222     // If we have both vc80 and vc90, pick version we were compiled with.
00223   if (hasSDKDir && windowsSDKInstallDir[0]) {
00224     path = windowsSDKInstallDir;
00225     return true;
00226   }
00227   return false;
00228 }
00229 
00230   // Get Visual Studio installation directory.
00231 static bool getVisualStudioDir(std::string &path) {
00232   // First check the environment variables that vsvars32.bat sets.
00233   const char* vcinstalldir = getenv("VCINSTALLDIR");
00234   if (vcinstalldir) {
00235     char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
00236     if (p)
00237       *p = '\0';
00238     path = vcinstalldir;
00239     return true;
00240   }
00241 
00242   char vsIDEInstallDir[256];
00243   char vsExpressIDEInstallDir[256];
00244   // Then try the windows registry.
00245   bool hasVCDir = getSystemRegistryString(
00246     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
00247     "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
00248   bool hasVCExpressDir = getSystemRegistryString(
00249     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION",
00250     "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1);
00251     // If we have both vc80 and vc90, pick version we were compiled with.
00252   if (hasVCDir && vsIDEInstallDir[0]) {
00253     char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE");
00254     if (p)
00255       *p = '\0';
00256     path = vsIDEInstallDir;
00257     return true;
00258   }
00259 
00260   if (hasVCExpressDir && vsExpressIDEInstallDir[0]) {
00261     char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE");
00262     if (p)
00263       *p = '\0';
00264     path = vsExpressIDEInstallDir;
00265     return true;
00266   }
00267 
00268   // Try the environment.
00269   const char *vs100comntools = getenv("VS100COMNTOOLS");
00270   const char *vs90comntools = getenv("VS90COMNTOOLS");
00271   const char *vs80comntools = getenv("VS80COMNTOOLS");
00272   const char *vscomntools = NULL;
00273 
00274   // Try to find the version that we were compiled with
00275   if(false) {}
00276   #if (_MSC_VER >= 1600)  // VC100
00277   else if(vs100comntools) {
00278     vscomntools = vs100comntools;
00279   }
00280   #elif (_MSC_VER == 1500) // VC80
00281   else if(vs90comntools) {
00282     vscomntools = vs90comntools;
00283   }
00284   #elif (_MSC_VER == 1400) // VC80
00285   else if(vs80comntools) {
00286     vscomntools = vs80comntools;
00287   }
00288   #endif
00289   // Otherwise find any version we can
00290   else if (vs100comntools)
00291     vscomntools = vs100comntools;
00292   else if (vs90comntools)
00293     vscomntools = vs90comntools;
00294   else if (vs80comntools)
00295     vscomntools = vs80comntools;
00296 
00297   if (vscomntools && *vscomntools) {
00298     const char *p = strstr(vscomntools, "\\Common7\\Tools");
00299     path = p ? std::string(vscomntools, p) : vscomntools;
00300     return true;
00301   }
00302   return false;
00303 }
00304 
00305 #endif // _MSC_VER
00306 
00307 void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
00308                                         ArgStringList &CC1Args) const {
00309   if (DriverArgs.hasArg(options::OPT_nostdinc))
00310     return;
00311 
00312   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
00313     llvm::sys::Path P(getDriver().ResourceDir);
00314     P.appendComponent("include");
00315     addSystemInclude(DriverArgs, CC1Args, P.str());
00316   }
00317 
00318   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
00319     return;
00320 
00321 #ifdef _MSC_VER
00322   // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
00323   if (const char *cl_include_dir = getenv("INCLUDE")) {
00324     SmallVector<StringRef, 8> Dirs;
00325     StringRef(cl_include_dir).split(Dirs, ";");
00326     int n = 0;
00327     for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end();
00328          I != E; ++I) {
00329       StringRef d = *I;
00330       if (d.size() == 0)
00331         continue;
00332       ++n;
00333       addSystemInclude(DriverArgs, CC1Args, d);
00334     }
00335     if (n) return;
00336   }
00337 
00338   std::string VSDir;
00339   std::string WindowsSDKDir;
00340 
00341   // When built with access to the proper Windows APIs, try to actually find
00342   // the correct include paths first.
00343   if (getVisualStudioDir(VSDir)) {
00344     addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include");
00345     if (getWindowsSDKDir(WindowsSDKDir))
00346       addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include");
00347     else
00348       addSystemInclude(DriverArgs, CC1Args,
00349                        VSDir + "\\VC\\PlatformSDK\\Include");
00350     return;
00351   }
00352 #endif // _MSC_VER
00353 
00354   // As a fallback, select default install paths.
00355   const StringRef Paths[] = {
00356     "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
00357     "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
00358     "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
00359     "C:/Program Files/Microsoft Visual Studio 8/VC/include",
00360     "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
00361   };
00362   addSystemIncludes(DriverArgs, CC1Args, Paths);
00363 }
00364 
00365 void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
00366                                            ArgStringList &CC1Args) const {
00367   // FIXME: There should probably be logic here to find libc++ on Windows.
00368 }