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