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/ADT/StringExtras.h" 18 #include "llvm/Config/llvm-config.h" 19 #include "llvm/Option/Arg.h" 20 #include "llvm/Option/ArgList.h" 21 #include "llvm/Support/ErrorHandling.h" 22 #include "llvm/Support/FileSystem.h" 23 #include "llvm/Support/Process.h" 24 #include <cstdio> 25 26 // Include the necessary headers to interface with the Windows registry and 27 // environment. 28 #if defined(LLVM_ON_WIN32) 29 #define USE_WIN32 30 #endif 31 32 #ifdef USE_WIN32 33 #define WIN32_LEAN_AND_MEAN 34 #define NOGDI 35 #ifndef NOMINMAX 36 #define NOMINMAX 37 #endif 38 #include <windows.h> 39 #endif 40 41 using namespace clang::driver; 42 using namespace clang::driver::toolchains; 43 using namespace clang; 44 using namespace llvm::opt; 45 46 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple, 47 const ArgList &Args) 48 : ToolChain(D, Triple, Args) { 49 getProgramPaths().push_back(getDriver().getInstalledDir()); 50 if (getDriver().getInstalledDir() != getDriver().Dir) 51 getProgramPaths().push_back(getDriver().Dir); 52 } 53 54 Tool *MSVCToolChain::buildLinker() const { 55 return new tools::visualstudio::Link(*this); 56 } 57 58 Tool *MSVCToolChain::buildAssembler() const { 59 if (getTriple().isOSBinFormatMachO()) 60 return new tools::darwin::Assemble(*this); 61 getDriver().Diag(clang::diag::err_no_external_assembler); 62 return nullptr; 63 } 64 65 bool MSVCToolChain::IsIntegratedAssemblerDefault() const { 66 return true; 67 } 68 69 bool MSVCToolChain::IsUnwindTablesDefault() const { 70 // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms 71 // such as ARM and PPC actually require unwind tables, but LLVM doesn't know 72 // how to generate them yet. 73 return getArch() == llvm::Triple::x86_64; 74 } 75 76 bool MSVCToolChain::isPICDefault() const { 77 return getArch() == llvm::Triple::x86_64; 78 } 79 80 bool MSVCToolChain::isPIEDefault() const { 81 return false; 82 } 83 84 bool MSVCToolChain::isPICDefaultForced() const { 85 return getArch() == llvm::Triple::x86_64; 86 } 87 88 #ifdef USE_WIN32 89 static bool readFullStringValue(HKEY hkey, const char *valueName, 90 std::string &value) { 91 // FIXME: We should be using the W versions of the registry functions, but 92 // doing so requires UTF8 / UTF16 conversions similar to how we handle command 93 // line arguments. The UTF8 conversion functions are not exposed publicly 94 // from LLVM though, so in order to do this we will probably need to create 95 // a registry abstraction in LLVMSupport that is Windows only. 96 DWORD result = 0; 97 DWORD valueSize = 0; 98 DWORD type = 0; 99 // First just query for the required size. 100 result = RegQueryValueEx(hkey, valueName, NULL, &type, NULL, &valueSize); 101 if (result != ERROR_SUCCESS || type != REG_SZ) 102 return false; 103 std::vector<BYTE> buffer(valueSize); 104 result = RegQueryValueEx(hkey, valueName, NULL, NULL, &buffer[0], &valueSize); 105 if (result == ERROR_SUCCESS) 106 value.assign(reinterpret_cast<const char *>(buffer.data())); 107 return result; 108 } 109 #endif 110 111 /// \brief Read registry string. 112 /// This also supports a means to look for high-versioned keys by use 113 /// of a $VERSION placeholder in the key path. 114 /// $VERSION in the key path is a placeholder for the version number, 115 /// causing the highest value path to be searched for and used. 116 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 117 /// There can be additional characters in the component. Only the numeric 118 /// characters are compared. This function only searches HKLM. 119 static bool getSystemRegistryString(const char *keyPath, const char *valueName, 120 std::string &value, std::string *phValue) { 121 #ifndef USE_WIN32 122 return false; 123 #else 124 HKEY hRootKey = HKEY_LOCAL_MACHINE; 125 HKEY hKey = NULL; 126 long lResult; 127 bool returnValue = false; 128 129 const char *placeHolder = strstr(keyPath, "$VERSION"); 130 std::string bestName; 131 // If we have a $VERSION placeholder, do the highest-version search. 132 if (placeHolder) { 133 const char *keyEnd = placeHolder - 1; 134 const char *nextKey = placeHolder; 135 // Find end of previous key. 136 while ((keyEnd > keyPath) && (*keyEnd != '\\')) 137 keyEnd--; 138 // Find end of key containing $VERSION. 139 while (*nextKey && (*nextKey != '\\')) 140 nextKey++; 141 size_t partialKeyLength = keyEnd - keyPath; 142 char partialKey[256]; 143 if (partialKeyLength > sizeof(partialKey)) 144 partialKeyLength = sizeof(partialKey); 145 strncpy(partialKey, keyPath, partialKeyLength); 146 partialKey[partialKeyLength] = '\0'; 147 HKEY hTopKey = NULL; 148 lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, 149 &hTopKey); 150 if (lResult == ERROR_SUCCESS) { 151 char keyName[256]; 152 double bestValue = 0.0; 153 DWORD index, size = sizeof(keyName) - 1; 154 for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, 155 NULL, NULL, NULL) == ERROR_SUCCESS; index++) { 156 const char *sp = keyName; 157 while (*sp && !isDigit(*sp)) 158 sp++; 159 if (!*sp) 160 continue; 161 const char *ep = sp + 1; 162 while (*ep && (isDigit(*ep) || (*ep == '.'))) 163 ep++; 164 char numBuf[32]; 165 strncpy(numBuf, sp, sizeof(numBuf) - 1); 166 numBuf[sizeof(numBuf) - 1] = '\0'; 167 double dvalue = strtod(numBuf, NULL); 168 if (dvalue > bestValue) { 169 // Test that InstallDir is indeed there before keeping this index. 170 // Open the chosen key path remainder. 171 bestName = keyName; 172 // Append rest of key. 173 bestName.append(nextKey); 174 lResult = RegOpenKeyEx(hTopKey, bestName.c_str(), 0, 175 KEY_READ | KEY_WOW64_32KEY, &hKey); 176 if (lResult == ERROR_SUCCESS) { 177 lResult = readFullStringValue(hKey, valueName, value); 178 if (lResult == ERROR_SUCCESS) { 179 bestValue = dvalue; 180 if (phValue) 181 *phValue = bestName; 182 returnValue = true; 183 } 184 RegCloseKey(hKey); 185 } 186 } 187 size = sizeof(keyName) - 1; 188 } 189 RegCloseKey(hTopKey); 190 } 191 } else { 192 lResult = 193 RegOpenKeyEx(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); 194 if (lResult == ERROR_SUCCESS) { 195 lResult = readFullStringValue(hKey, valueName, value); 196 if (lResult == ERROR_SUCCESS) 197 returnValue = true; 198 if (phValue) 199 phValue->clear(); 200 RegCloseKey(hKey); 201 } 202 } 203 return returnValue; 204 #endif // USE_WIN32 205 } 206 207 /// \brief Get Windows SDK installation directory. 208 bool MSVCToolChain::getWindowsSDKDir(std::string &path, int &major, 209 int &minor) const { 210 std::string sdkVersion; 211 // Try the Windows registry. 212 bool hasSDKDir = getSystemRegistryString( 213 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 214 "InstallationFolder", path, &sdkVersion); 215 if (!sdkVersion.empty()) 216 std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor); 217 return hasSDKDir && !path.empty(); 218 } 219 220 // Gets the library path required to link against the Windows SDK. 221 bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const { 222 std::string sdkPath; 223 int sdkMajor = 0; 224 int sdkMinor = 0; 225 226 path.clear(); 227 if (!getWindowsSDKDir(sdkPath, sdkMajor, sdkMinor)) 228 return false; 229 230 llvm::SmallString<128> libPath(sdkPath); 231 llvm::sys::path::append(libPath, "Lib"); 232 if (sdkMajor <= 7) { 233 switch (getArch()) { 234 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. 235 case llvm::Triple::x86: 236 break; 237 case llvm::Triple::x86_64: 238 llvm::sys::path::append(libPath, "x64"); 239 break; 240 case llvm::Triple::arm: 241 // It is not necessary to link against Windows SDK 7.x when targeting ARM. 242 return false; 243 default: 244 return false; 245 } 246 } else { 247 // Windows SDK 8.x installs libraries in a folder whose names depend on the 248 // version of the OS you're targeting. By default choose the newest, which 249 // usually corresponds to the version of the OS you've installed the SDK on. 250 const char *tests[] = {"winv6.3", "win8", "win7"}; 251 bool found = false; 252 for (const char *test : tests) { 253 llvm::SmallString<128> testPath(libPath); 254 llvm::sys::path::append(testPath, test); 255 if (llvm::sys::fs::exists(testPath.c_str())) { 256 libPath = testPath; 257 found = true; 258 break; 259 } 260 } 261 262 if (!found) 263 return false; 264 265 llvm::sys::path::append(libPath, "um"); 266 switch (getArch()) { 267 case llvm::Triple::x86: 268 llvm::sys::path::append(libPath, "x86"); 269 break; 270 case llvm::Triple::x86_64: 271 llvm::sys::path::append(libPath, "x64"); 272 break; 273 case llvm::Triple::arm: 274 llvm::sys::path::append(libPath, "arm"); 275 break; 276 default: 277 return false; 278 } 279 } 280 281 path = libPath.str(); 282 return true; 283 } 284 285 // Get the location to use for Visual Studio binaries. The location priority 286 // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on 287 // system (as reported by the registry). 288 bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath, 289 std::string &path) const { 290 path.clear(); 291 292 SmallString<128> BinDir; 293 294 // First check the environment variables that vsvars32.bat sets. 295 llvm::Optional<std::string> VcInstallDir = 296 llvm::sys::Process::GetEnv("VCINSTALLDIR"); 297 if (VcInstallDir.hasValue()) { 298 BinDir = VcInstallDir.getValue(); 299 llvm::sys::path::append(BinDir, "bin"); 300 } else { 301 // Next walk the PATH, trying to find a cl.exe in the path. If we find one, 302 // use that. However, make sure it's not clang's cl.exe. 303 llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH"); 304 if (OptPath.hasValue()) { 305 const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; 306 SmallVector<StringRef, 8> PathSegments; 307 llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); 308 309 for (StringRef PathSegment : PathSegments) { 310 if (PathSegment.empty()) 311 continue; 312 313 SmallString<128> FilePath(PathSegment); 314 llvm::sys::path::append(FilePath, "cl.exe"); 315 if (llvm::sys::fs::can_execute(FilePath.c_str()) && 316 !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) { 317 // If we found it on the PATH, use it exactly as is with no 318 // modifications. 319 path = PathSegment; 320 return true; 321 } 322 } 323 } 324 325 std::string installDir; 326 // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the 327 // registry then we have no choice but to fail. 328 if (!getVisualStudioInstallDir(installDir)) 329 return false; 330 331 // Regardless of what binary we're ultimately trying to find, we make sure 332 // that this is a Visual Studio directory by checking for cl.exe. We use 333 // cl.exe instead of other binaries like link.exe because programs such as 334 // GnuWin32 also have a utility called link.exe, so cl.exe is the least 335 // ambiguous. 336 BinDir = installDir; 337 llvm::sys::path::append(BinDir, "VC", "bin"); 338 SmallString<128> ClPath(BinDir); 339 llvm::sys::path::append(ClPath, "cl.exe"); 340 341 if (!llvm::sys::fs::can_execute(ClPath.c_str())) 342 return false; 343 } 344 345 if (BinDir.empty()) 346 return false; 347 348 switch (getArch()) { 349 case llvm::Triple::x86: 350 break; 351 case llvm::Triple::x86_64: 352 llvm::sys::path::append(BinDir, "amd64"); 353 break; 354 case llvm::Triple::arm: 355 llvm::sys::path::append(BinDir, "arm"); 356 break; 357 default: 358 // Whatever this is, Visual Studio doesn't have a toolchain for it. 359 return false; 360 } 361 path = BinDir.str(); 362 return true; 363 } 364 365 // Get Visual Studio installation directory. 366 bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const { 367 // First check the environment variables that vsvars32.bat sets. 368 const char *vcinstalldir = getenv("VCINSTALLDIR"); 369 if (vcinstalldir) { 370 path = vcinstalldir; 371 path = path.substr(0, path.find("\\VC")); 372 return true; 373 } 374 375 std::string vsIDEInstallDir; 376 std::string vsExpressIDEInstallDir; 377 // Then try the windows registry. 378 bool hasVCDir = 379 getSystemRegistryString("SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", 380 "InstallDir", vsIDEInstallDir, nullptr); 381 if (hasVCDir && !vsIDEInstallDir.empty()) { 382 path = vsIDEInstallDir.substr(0, vsIDEInstallDir.find("\\Common7\\IDE")); 383 return true; 384 } 385 386 bool hasVCExpressDir = 387 getSystemRegistryString("SOFTWARE\\Microsoft\\VCExpress\\$VERSION", 388 "InstallDir", vsExpressIDEInstallDir, nullptr); 389 if (hasVCExpressDir && !vsExpressIDEInstallDir.empty()) { 390 path = vsExpressIDEInstallDir.substr( 391 0, vsIDEInstallDir.find("\\Common7\\IDE")); 392 return true; 393 } 394 395 // Try the environment. 396 const char *vs120comntools = getenv("VS120COMNTOOLS"); 397 const char *vs100comntools = getenv("VS100COMNTOOLS"); 398 const char *vs90comntools = getenv("VS90COMNTOOLS"); 399 const char *vs80comntools = getenv("VS80COMNTOOLS"); 400 401 const char *vscomntools = nullptr; 402 403 // Find any version we can 404 if (vs120comntools) 405 vscomntools = vs120comntools; 406 else if (vs100comntools) 407 vscomntools = vs100comntools; 408 else if (vs90comntools) 409 vscomntools = vs90comntools; 410 else if (vs80comntools) 411 vscomntools = vs80comntools; 412 413 if (vscomntools && *vscomntools) { 414 const char *p = strstr(vscomntools, "\\Common7\\Tools"); 415 path = p ? std::string(vscomntools, p) : vscomntools; 416 return true; 417 } 418 return false; 419 } 420 421 void MSVCToolChain::AddSystemIncludeWithSubfolder(const ArgList &DriverArgs, 422 ArgStringList &CC1Args, 423 const std::string &folder, 424 const char *subfolder) const { 425 llvm::SmallString<128> path(folder); 426 llvm::sys::path::append(path, subfolder); 427 addSystemInclude(DriverArgs, CC1Args, path); 428 } 429 430 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 431 ArgStringList &CC1Args) const { 432 if (DriverArgs.hasArg(options::OPT_nostdinc)) 433 return; 434 435 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 436 SmallString<128> P(getDriver().ResourceDir); 437 llvm::sys::path::append(P, "include"); 438 addSystemInclude(DriverArgs, CC1Args, P); 439 } 440 441 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 442 return; 443 444 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. 445 if (const char *cl_include_dir = getenv("INCLUDE")) { 446 SmallVector<StringRef, 8> Dirs; 447 StringRef(cl_include_dir) 448 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 449 for (StringRef Dir : Dirs) 450 addSystemInclude(DriverArgs, CC1Args, Dir); 451 if (!Dirs.empty()) 452 return; 453 } 454 455 std::string VSDir; 456 457 // When built with access to the proper Windows APIs, try to actually find 458 // the correct include paths first. 459 if (getVisualStudioInstallDir(VSDir)) { 460 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, VSDir, "VC\\include"); 461 462 std::string WindowsSDKDir; 463 int major, minor; 464 if (getWindowsSDKDir(WindowsSDKDir, major, minor)) { 465 if (major >= 8) { 466 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 467 "include\\shared"); 468 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 469 "include\\um"); 470 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 471 "include\\winrt"); 472 } else { 473 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 474 "include"); 475 } 476 } else { 477 addSystemInclude(DriverArgs, CC1Args, VSDir); 478 } 479 return; 480 } 481 482 // As a fallback, select default install paths. 483 // FIXME: Don't guess drives and paths like this on Windows. 484 const StringRef Paths[] = { 485 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 486 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 487 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 488 "C:/Program Files/Microsoft Visual Studio 8/VC/include", 489 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 490 }; 491 addSystemIncludes(DriverArgs, CC1Args, Paths); 492 } 493 494 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 495 ArgStringList &CC1Args) const { 496 // FIXME: There should probably be logic here to find libc++ on Windows. 497 } 498