clang API Documentation
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 }