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