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