1234287Sdim//===--- ToolChains.cpp - ToolChain Implementations -----------------------===// 2234287Sdim// 3234287Sdim// The LLVM Compiler Infrastructure 4234287Sdim// 5234287Sdim// This file is distributed under the University of Illinois Open Source 6234287Sdim// License. See LICENSE.TXT for details. 7234287Sdim// 8234287Sdim//===----------------------------------------------------------------------===// 9234287Sdim 10234287Sdim#include "ToolChains.h" 11249423Sdim#include "clang/Basic/CharInfo.h" 12249423Sdim#include "clang/Basic/Version.h" 13234287Sdim#include "clang/Driver/Compilation.h" 14234287Sdim#include "clang/Driver/Driver.h" 15249423Sdim#include "clang/Driver/DriverDiagnostic.h" 16234287Sdim#include "clang/Driver/Options.h" 17263508Sdim#include "llvm/Option/Arg.h" 18263508Sdim#include "llvm/Option/ArgList.h" 19234287Sdim#include "llvm/Support/ErrorHandling.h" 20234287Sdim#include "llvm/Support/Path.h" 21234287Sdim 22234287Sdim// Include the necessary headers to interface with the Windows registry and 23234287Sdim// environment. 24234287Sdim#ifdef _MSC_VER 25234287Sdim #define WIN32_LEAN_AND_MEAN 26234287Sdim #define NOGDI 27234287Sdim #define NOMINMAX 28234287Sdim #include <Windows.h> 29234287Sdim#endif 30234287Sdim 31234287Sdimusing namespace clang::driver; 32234287Sdimusing namespace clang::driver::toolchains; 33234287Sdimusing namespace clang; 34263508Sdimusing namespace llvm::opt; 35234287Sdim 36249423SdimWindows::Windows(const Driver &D, const llvm::Triple& Triple, 37249423Sdim const ArgList &Args) 38249423Sdim : ToolChain(D, Triple, Args) { 39234287Sdim} 40234287Sdim 41249423SdimTool *Windows::buildLinker() const { 42249423Sdim return new tools::visualstudio::Link(*this); 43249423Sdim} 44234287Sdim 45249423SdimTool *Windows::buildAssembler() const { 46249423Sdim if (getTriple().getEnvironment() == llvm::Triple::MachO) 47249423Sdim return new tools::darwin::Assemble(*this); 48263508Sdim getDriver().Diag(clang::diag::err_no_external_assembler); 49249423Sdim return NULL; 50234287Sdim} 51234287Sdim 52234287Sdimbool Windows::IsIntegratedAssemblerDefault() const { 53234287Sdim return true; 54234287Sdim} 55234287Sdim 56234287Sdimbool Windows::IsUnwindTablesDefault() const { 57243830Sdim return getArch() == llvm::Triple::x86_64; 58234287Sdim} 59234287Sdim 60243830Sdimbool Windows::isPICDefault() const { 61243830Sdim return getArch() == llvm::Triple::x86_64; 62234287Sdim} 63234287Sdim 64251662Sdimbool Windows::isPIEDefault() const { 65251662Sdim return false; 66251662Sdim} 67251662Sdim 68243830Sdimbool Windows::isPICDefaultForced() const { 69243830Sdim return getArch() == llvm::Triple::x86_64; 70234287Sdim} 71234287Sdim 72234287Sdim// FIXME: This probably should goto to some platform utils place. 73234287Sdim#ifdef _MSC_VER 74234287Sdim 75234287Sdim/// \brief Read registry string. 76234287Sdim/// This also supports a means to look for high-versioned keys by use 77234287Sdim/// of a $VERSION placeholder in the key path. 78234287Sdim/// $VERSION in the key path is a placeholder for the version number, 79234287Sdim/// causing the highest value path to be searched for and used. 80234287Sdim/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 81234287Sdim/// There can be additional characters in the component. Only the numberic 82234287Sdim/// characters are compared. 83234287Sdimstatic bool getSystemRegistryString(const char *keyPath, const char *valueName, 84234287Sdim char *value, size_t maxLength) { 85234287Sdim HKEY hRootKey = NULL; 86234287Sdim HKEY hKey = NULL; 87234287Sdim const char* subKey = NULL; 88234287Sdim DWORD valueType; 89234287Sdim DWORD valueSize = maxLength - 1; 90234287Sdim long lResult; 91234287Sdim bool returnValue = false; 92234287Sdim 93234287Sdim if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { 94234287Sdim hRootKey = HKEY_CLASSES_ROOT; 95234287Sdim subKey = keyPath + 18; 96234287Sdim } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { 97234287Sdim hRootKey = HKEY_USERS; 98234287Sdim subKey = keyPath + 11; 99234287Sdim } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { 100234287Sdim hRootKey = HKEY_LOCAL_MACHINE; 101234287Sdim subKey = keyPath + 19; 102234287Sdim } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { 103234287Sdim hRootKey = HKEY_CURRENT_USER; 104234287Sdim subKey = keyPath + 18; 105234287Sdim } else { 106234287Sdim return false; 107234287Sdim } 108234287Sdim 109234287Sdim const char *placeHolder = strstr(subKey, "$VERSION"); 110234287Sdim char bestName[256]; 111234287Sdim bestName[0] = '\0'; 112234287Sdim // If we have a $VERSION placeholder, do the highest-version search. 113234287Sdim if (placeHolder) { 114234287Sdim const char *keyEnd = placeHolder - 1; 115234287Sdim const char *nextKey = placeHolder; 116234287Sdim // Find end of previous key. 117234287Sdim while ((keyEnd > subKey) && (*keyEnd != '\\')) 118234287Sdim keyEnd--; 119234287Sdim // Find end of key containing $VERSION. 120234287Sdim while (*nextKey && (*nextKey != '\\')) 121234287Sdim nextKey++; 122234287Sdim size_t partialKeyLength = keyEnd - subKey; 123234287Sdim char partialKey[256]; 124234287Sdim if (partialKeyLength > sizeof(partialKey)) 125234287Sdim partialKeyLength = sizeof(partialKey); 126234287Sdim strncpy(partialKey, subKey, partialKeyLength); 127234287Sdim partialKey[partialKeyLength] = '\0'; 128234287Sdim HKEY hTopKey = NULL; 129263508Sdim lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, 130263508Sdim &hTopKey); 131234287Sdim if (lResult == ERROR_SUCCESS) { 132234287Sdim char keyName[256]; 133234287Sdim int bestIndex = -1; 134234287Sdim double bestValue = 0.0; 135234287Sdim DWORD index, size = sizeof(keyName) - 1; 136234287Sdim for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, 137234287Sdim NULL, NULL, NULL) == ERROR_SUCCESS; index++) { 138234287Sdim const char *sp = keyName; 139249423Sdim while (*sp && !isDigit(*sp)) 140234287Sdim sp++; 141234287Sdim if (!*sp) 142234287Sdim continue; 143234287Sdim const char *ep = sp + 1; 144249423Sdim while (*ep && (isDigit(*ep) || (*ep == '.'))) 145234287Sdim ep++; 146234287Sdim char numBuf[32]; 147234287Sdim strncpy(numBuf, sp, sizeof(numBuf) - 1); 148234287Sdim numBuf[sizeof(numBuf) - 1] = '\0'; 149263508Sdim double dvalue = strtod(numBuf, NULL); 150263508Sdim if (dvalue > bestValue) { 151263508Sdim // Test that InstallDir is indeed there before keeping this index. 152263508Sdim // Open the chosen key path remainder. 153234287Sdim strcpy(bestName, keyName); 154263508Sdim // Append rest of key. 155263508Sdim strncat(bestName, nextKey, sizeof(bestName) - 1); 156263508Sdim bestName[sizeof(bestName) - 1] = '\0'; 157263508Sdim lResult = RegOpenKeyEx(hTopKey, bestName, 0, 158263508Sdim KEY_READ | KEY_WOW64_32KEY, &hKey); 159263508Sdim if (lResult == ERROR_SUCCESS) { 160263508Sdim lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 161263508Sdim (LPBYTE)value, &valueSize); 162263508Sdim if (lResult == ERROR_SUCCESS) { 163263508Sdim bestIndex = (int)index; 164263508Sdim bestValue = dvalue; 165263508Sdim returnValue = true; 166263508Sdim } 167263508Sdim RegCloseKey(hKey); 168263508Sdim } 169234287Sdim } 170234287Sdim size = sizeof(keyName) - 1; 171234287Sdim } 172234287Sdim RegCloseKey(hTopKey); 173234287Sdim } 174234287Sdim } else { 175263508Sdim lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ | KEY_WOW64_32KEY, 176263508Sdim &hKey); 177234287Sdim if (lResult == ERROR_SUCCESS) { 178234287Sdim lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 179234287Sdim (LPBYTE)value, &valueSize); 180234287Sdim if (lResult == ERROR_SUCCESS) 181234287Sdim returnValue = true; 182234287Sdim RegCloseKey(hKey); 183234287Sdim } 184234287Sdim } 185234287Sdim return returnValue; 186234287Sdim} 187234287Sdim 188234287Sdim/// \brief Get Windows SDK installation directory. 189234287Sdimstatic bool getWindowsSDKDir(std::string &path) { 190234287Sdim char windowsSDKInstallDir[256]; 191234287Sdim // Try the Windows registry. 192234287Sdim bool hasSDKDir = getSystemRegistryString( 193234287Sdim "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 194234287Sdim "InstallationFolder", 195234287Sdim windowsSDKInstallDir, 196234287Sdim sizeof(windowsSDKInstallDir) - 1); 197234287Sdim // If we have both vc80 and vc90, pick version we were compiled with. 198234287Sdim if (hasSDKDir && windowsSDKInstallDir[0]) { 199234287Sdim path = windowsSDKInstallDir; 200234287Sdim return true; 201234287Sdim } 202234287Sdim return false; 203234287Sdim} 204234287Sdim 205234287Sdim // Get Visual Studio installation directory. 206234287Sdimstatic bool getVisualStudioDir(std::string &path) { 207234287Sdim // First check the environment variables that vsvars32.bat sets. 208234287Sdim const char* vcinstalldir = getenv("VCINSTALLDIR"); 209234287Sdim if (vcinstalldir) { 210234287Sdim char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); 211234287Sdim if (p) 212234287Sdim *p = '\0'; 213234287Sdim path = vcinstalldir; 214234287Sdim return true; 215234287Sdim } 216234287Sdim 217234287Sdim char vsIDEInstallDir[256]; 218234287Sdim char vsExpressIDEInstallDir[256]; 219234287Sdim // Then try the windows registry. 220234287Sdim bool hasVCDir = getSystemRegistryString( 221234287Sdim "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", 222234287Sdim "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); 223234287Sdim bool hasVCExpressDir = getSystemRegistryString( 224234287Sdim "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", 225234287Sdim "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); 226234287Sdim // If we have both vc80 and vc90, pick version we were compiled with. 227234287Sdim if (hasVCDir && vsIDEInstallDir[0]) { 228234287Sdim char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); 229234287Sdim if (p) 230234287Sdim *p = '\0'; 231234287Sdim path = vsIDEInstallDir; 232234287Sdim return true; 233234287Sdim } 234234287Sdim 235234287Sdim if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { 236234287Sdim char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); 237234287Sdim if (p) 238234287Sdim *p = '\0'; 239234287Sdim path = vsExpressIDEInstallDir; 240234287Sdim return true; 241234287Sdim } 242234287Sdim 243234287Sdim // Try the environment. 244234287Sdim const char *vs100comntools = getenv("VS100COMNTOOLS"); 245234287Sdim const char *vs90comntools = getenv("VS90COMNTOOLS"); 246234287Sdim const char *vs80comntools = getenv("VS80COMNTOOLS"); 247234287Sdim const char *vscomntools = NULL; 248234287Sdim 249234287Sdim // Try to find the version that we were compiled with 250234287Sdim if(false) {} 251234287Sdim #if (_MSC_VER >= 1600) // VC100 252234287Sdim else if(vs100comntools) { 253234287Sdim vscomntools = vs100comntools; 254234287Sdim } 255234287Sdim #elif (_MSC_VER == 1500) // VC80 256234287Sdim else if(vs90comntools) { 257234287Sdim vscomntools = vs90comntools; 258234287Sdim } 259234287Sdim #elif (_MSC_VER == 1400) // VC80 260234287Sdim else if(vs80comntools) { 261234287Sdim vscomntools = vs80comntools; 262234287Sdim } 263234287Sdim #endif 264234287Sdim // Otherwise find any version we can 265234287Sdim else if (vs100comntools) 266234287Sdim vscomntools = vs100comntools; 267234287Sdim else if (vs90comntools) 268234287Sdim vscomntools = vs90comntools; 269234287Sdim else if (vs80comntools) 270234287Sdim vscomntools = vs80comntools; 271234287Sdim 272234287Sdim if (vscomntools && *vscomntools) { 273234287Sdim const char *p = strstr(vscomntools, "\\Common7\\Tools"); 274234287Sdim path = p ? std::string(vscomntools, p) : vscomntools; 275234287Sdim return true; 276234287Sdim } 277234287Sdim return false; 278234287Sdim} 279234287Sdim 280234287Sdim#endif // _MSC_VER 281234287Sdim 282234287Sdimvoid Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 283234287Sdim ArgStringList &CC1Args) const { 284234287Sdim if (DriverArgs.hasArg(options::OPT_nostdinc)) 285234287Sdim return; 286234287Sdim 287234287Sdim if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 288263508Sdim SmallString<128> P(getDriver().ResourceDir); 289263508Sdim llvm::sys::path::append(P, "include"); 290234287Sdim addSystemInclude(DriverArgs, CC1Args, P.str()); 291234287Sdim } 292234287Sdim 293234287Sdim if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 294234287Sdim return; 295234287Sdim 296234287Sdim#ifdef _MSC_VER 297234287Sdim // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. 298234287Sdim if (const char *cl_include_dir = getenv("INCLUDE")) { 299234287Sdim SmallVector<StringRef, 8> Dirs; 300234287Sdim StringRef(cl_include_dir).split(Dirs, ";"); 301234287Sdim int n = 0; 302234287Sdim for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end(); 303234287Sdim I != E; ++I) { 304234287Sdim StringRef d = *I; 305234287Sdim if (d.size() == 0) 306234287Sdim continue; 307234287Sdim ++n; 308234287Sdim addSystemInclude(DriverArgs, CC1Args, d); 309234287Sdim } 310234287Sdim if (n) return; 311234287Sdim } 312234287Sdim 313234287Sdim std::string VSDir; 314234287Sdim std::string WindowsSDKDir; 315234287Sdim 316234287Sdim // When built with access to the proper Windows APIs, try to actually find 317234287Sdim // the correct include paths first. 318234287Sdim if (getVisualStudioDir(VSDir)) { 319234287Sdim addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include"); 320234287Sdim if (getWindowsSDKDir(WindowsSDKDir)) 321234287Sdim addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include"); 322234287Sdim else 323234287Sdim addSystemInclude(DriverArgs, CC1Args, 324234287Sdim VSDir + "\\VC\\PlatformSDK\\Include"); 325234287Sdim return; 326234287Sdim } 327234287Sdim#endif // _MSC_VER 328234287Sdim 329234287Sdim // As a fallback, select default install paths. 330234287Sdim const StringRef Paths[] = { 331234287Sdim "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 332234287Sdim "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 333234287Sdim "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 334234287Sdim "C:/Program Files/Microsoft Visual Studio 8/VC/include", 335234287Sdim "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 336234287Sdim }; 337234287Sdim addSystemIncludes(DriverArgs, CC1Args, Paths); 338234287Sdim} 339234287Sdim 340234287Sdimvoid Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 341234287Sdim ArgStringList &CC1Args) const { 342234287Sdim // FIXME: There should probably be logic here to find libc++ on Windows. 343234287Sdim} 344