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