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/Arg.h" 14234287Sdim#include "clang/Driver/ArgList.h" 15234287Sdim#include "clang/Driver/Compilation.h" 16234287Sdim#include "clang/Driver/Driver.h" 17249423Sdim#include "clang/Driver/DriverDiagnostic.h" 18234287Sdim#include "clang/Driver/Options.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; 34234287Sdim 35249423SdimWindows::Windows(const Driver &D, const llvm::Triple& Triple, 36249423Sdim const ArgList &Args) 37249423Sdim : ToolChain(D, Triple, Args) { 38234287Sdim} 39234287Sdim 40249423SdimTool *Windows::buildLinker() const { 41249423Sdim return new tools::visualstudio::Link(*this); 42249423Sdim} 43234287Sdim 44249423SdimTool *Windows::buildAssembler() const { 45249423Sdim if (getTriple().getEnvironment() == llvm::Triple::MachO) 46249423Sdim return new tools::darwin::Assemble(*this); 47249423Sdim getDriver().Diag(clang::diag::err_no_external_windows_assembler); 48249423Sdim return NULL; 49234287Sdim} 50234287Sdim 51234287Sdimbool Windows::IsIntegratedAssemblerDefault() const { 52234287Sdim return true; 53234287Sdim} 54234287Sdim 55234287Sdimbool Windows::IsUnwindTablesDefault() const { 56243830Sdim return getArch() == llvm::Triple::x86_64; 57234287Sdim} 58234287Sdim 59243830Sdimbool Windows::isPICDefault() const { 60243830Sdim return getArch() == llvm::Triple::x86_64; 61234287Sdim} 62234287Sdim 63251662Sdimbool Windows::isPIEDefault() const { 64251662Sdim return false; 65251662Sdim} 66251662Sdim 67243830Sdimbool Windows::isPICDefaultForced() const { 68243830Sdim return getArch() == llvm::Triple::x86_64; 69234287Sdim} 70234287Sdim 71234287Sdim// FIXME: This probably should goto to some platform utils place. 72234287Sdim#ifdef _MSC_VER 73234287Sdim 74234287Sdim/// \brief Read registry string. 75234287Sdim/// This also supports a means to look for high-versioned keys by use 76234287Sdim/// of a $VERSION placeholder in the key path. 77234287Sdim/// $VERSION in the key path is a placeholder for the version number, 78234287Sdim/// causing the highest value path to be searched for and used. 79234287Sdim/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 80234287Sdim/// There can be additional characters in the component. Only the numberic 81234287Sdim/// characters are compared. 82234287Sdimstatic bool getSystemRegistryString(const char *keyPath, const char *valueName, 83234287Sdim char *value, size_t maxLength) { 84234287Sdim HKEY hRootKey = NULL; 85234287Sdim HKEY hKey = NULL; 86234287Sdim const char* subKey = NULL; 87234287Sdim DWORD valueType; 88234287Sdim DWORD valueSize = maxLength - 1; 89234287Sdim long lResult; 90234287Sdim bool returnValue = false; 91234287Sdim 92234287Sdim if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { 93234287Sdim hRootKey = HKEY_CLASSES_ROOT; 94234287Sdim subKey = keyPath + 18; 95234287Sdim } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { 96234287Sdim hRootKey = HKEY_USERS; 97234287Sdim subKey = keyPath + 11; 98234287Sdim } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { 99234287Sdim hRootKey = HKEY_LOCAL_MACHINE; 100234287Sdim subKey = keyPath + 19; 101234287Sdim } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { 102234287Sdim hRootKey = HKEY_CURRENT_USER; 103234287Sdim subKey = keyPath + 18; 104234287Sdim } else { 105234287Sdim return false; 106234287Sdim } 107234287Sdim 108234287Sdim const char *placeHolder = strstr(subKey, "$VERSION"); 109234287Sdim char bestName[256]; 110234287Sdim bestName[0] = '\0'; 111234287Sdim // If we have a $VERSION placeholder, do the highest-version search. 112234287Sdim if (placeHolder) { 113234287Sdim const char *keyEnd = placeHolder - 1; 114234287Sdim const char *nextKey = placeHolder; 115234287Sdim // Find end of previous key. 116234287Sdim while ((keyEnd > subKey) && (*keyEnd != '\\')) 117234287Sdim keyEnd--; 118234287Sdim // Find end of key containing $VERSION. 119234287Sdim while (*nextKey && (*nextKey != '\\')) 120234287Sdim nextKey++; 121234287Sdim size_t partialKeyLength = keyEnd - subKey; 122234287Sdim char partialKey[256]; 123234287Sdim if (partialKeyLength > sizeof(partialKey)) 124234287Sdim partialKeyLength = sizeof(partialKey); 125234287Sdim strncpy(partialKey, subKey, partialKeyLength); 126234287Sdim partialKey[partialKeyLength] = '\0'; 127234287Sdim HKEY hTopKey = NULL; 128234287Sdim lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey); 129234287Sdim if (lResult == ERROR_SUCCESS) { 130234287Sdim char keyName[256]; 131234287Sdim int bestIndex = -1; 132234287Sdim double bestValue = 0.0; 133234287Sdim DWORD index, size = sizeof(keyName) - 1; 134234287Sdim for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, 135234287Sdim NULL, NULL, NULL) == ERROR_SUCCESS; index++) { 136234287Sdim const char *sp = keyName; 137249423Sdim while (*sp && !isDigit(*sp)) 138234287Sdim sp++; 139234287Sdim if (!*sp) 140234287Sdim continue; 141234287Sdim const char *ep = sp + 1; 142249423Sdim while (*ep && (isDigit(*ep) || (*ep == '.'))) 143234287Sdim ep++; 144234287Sdim char numBuf[32]; 145234287Sdim strncpy(numBuf, sp, sizeof(numBuf) - 1); 146234287Sdim numBuf[sizeof(numBuf) - 1] = '\0'; 147234287Sdim double value = strtod(numBuf, NULL); 148234287Sdim if (value > bestValue) { 149234287Sdim bestIndex = (int)index; 150234287Sdim bestValue = value; 151234287Sdim strcpy(bestName, keyName); 152234287Sdim } 153234287Sdim size = sizeof(keyName) - 1; 154234287Sdim } 155234287Sdim // If we found the highest versioned key, open the key and get the value. 156234287Sdim if (bestIndex != -1) { 157234287Sdim // Append rest of key. 158234287Sdim strncat(bestName, nextKey, sizeof(bestName) - 1); 159234287Sdim bestName[sizeof(bestName) - 1] = '\0'; 160234287Sdim // Open the chosen key path remainder. 161234287Sdim lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey); 162234287Sdim if (lResult == ERROR_SUCCESS) { 163234287Sdim lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 164234287Sdim (LPBYTE)value, &valueSize); 165234287Sdim if (lResult == ERROR_SUCCESS) 166234287Sdim returnValue = true; 167234287Sdim RegCloseKey(hKey); 168234287Sdim } 169234287Sdim } 170234287Sdim RegCloseKey(hTopKey); 171234287Sdim } 172234287Sdim } else { 173234287Sdim lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey); 174234287Sdim if (lResult == ERROR_SUCCESS) { 175234287Sdim lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 176234287Sdim (LPBYTE)value, &valueSize); 177234287Sdim if (lResult == ERROR_SUCCESS) 178234287Sdim returnValue = true; 179234287Sdim RegCloseKey(hKey); 180234287Sdim } 181234287Sdim } 182234287Sdim return returnValue; 183234287Sdim} 184234287Sdim 185234287Sdim/// \brief Get Windows SDK installation directory. 186234287Sdimstatic bool getWindowsSDKDir(std::string &path) { 187234287Sdim char windowsSDKInstallDir[256]; 188234287Sdim // Try the Windows registry. 189234287Sdim bool hasSDKDir = getSystemRegistryString( 190234287Sdim "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 191234287Sdim "InstallationFolder", 192234287Sdim windowsSDKInstallDir, 193234287Sdim sizeof(windowsSDKInstallDir) - 1); 194234287Sdim // If we have both vc80 and vc90, pick version we were compiled with. 195234287Sdim if (hasSDKDir && windowsSDKInstallDir[0]) { 196234287Sdim path = windowsSDKInstallDir; 197234287Sdim return true; 198234287Sdim } 199234287Sdim return false; 200234287Sdim} 201234287Sdim 202234287Sdim // Get Visual Studio installation directory. 203234287Sdimstatic bool getVisualStudioDir(std::string &path) { 204234287Sdim // First check the environment variables that vsvars32.bat sets. 205234287Sdim const char* vcinstalldir = getenv("VCINSTALLDIR"); 206234287Sdim if (vcinstalldir) { 207234287Sdim char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); 208234287Sdim if (p) 209234287Sdim *p = '\0'; 210234287Sdim path = vcinstalldir; 211234287Sdim return true; 212234287Sdim } 213234287Sdim 214234287Sdim char vsIDEInstallDir[256]; 215234287Sdim char vsExpressIDEInstallDir[256]; 216234287Sdim // Then try the windows registry. 217234287Sdim bool hasVCDir = getSystemRegistryString( 218234287Sdim "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", 219234287Sdim "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); 220234287Sdim bool hasVCExpressDir = getSystemRegistryString( 221234287Sdim "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", 222234287Sdim "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); 223234287Sdim // If we have both vc80 and vc90, pick version we were compiled with. 224234287Sdim if (hasVCDir && vsIDEInstallDir[0]) { 225234287Sdim char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); 226234287Sdim if (p) 227234287Sdim *p = '\0'; 228234287Sdim path = vsIDEInstallDir; 229234287Sdim return true; 230234287Sdim } 231234287Sdim 232234287Sdim if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { 233234287Sdim char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); 234234287Sdim if (p) 235234287Sdim *p = '\0'; 236234287Sdim path = vsExpressIDEInstallDir; 237234287Sdim return true; 238234287Sdim } 239234287Sdim 240234287Sdim // Try the environment. 241234287Sdim const char *vs100comntools = getenv("VS100COMNTOOLS"); 242234287Sdim const char *vs90comntools = getenv("VS90COMNTOOLS"); 243234287Sdim const char *vs80comntools = getenv("VS80COMNTOOLS"); 244234287Sdim const char *vscomntools = NULL; 245234287Sdim 246234287Sdim // Try to find the version that we were compiled with 247234287Sdim if(false) {} 248234287Sdim #if (_MSC_VER >= 1600) // VC100 249234287Sdim else if(vs100comntools) { 250234287Sdim vscomntools = vs100comntools; 251234287Sdim } 252234287Sdim #elif (_MSC_VER == 1500) // VC80 253234287Sdim else if(vs90comntools) { 254234287Sdim vscomntools = vs90comntools; 255234287Sdim } 256234287Sdim #elif (_MSC_VER == 1400) // VC80 257234287Sdim else if(vs80comntools) { 258234287Sdim vscomntools = vs80comntools; 259234287Sdim } 260234287Sdim #endif 261234287Sdim // Otherwise find any version we can 262234287Sdim else if (vs100comntools) 263234287Sdim vscomntools = vs100comntools; 264234287Sdim else if (vs90comntools) 265234287Sdim vscomntools = vs90comntools; 266234287Sdim else if (vs80comntools) 267234287Sdim vscomntools = vs80comntools; 268234287Sdim 269234287Sdim if (vscomntools && *vscomntools) { 270234287Sdim const char *p = strstr(vscomntools, "\\Common7\\Tools"); 271234287Sdim path = p ? std::string(vscomntools, p) : vscomntools; 272234287Sdim return true; 273234287Sdim } 274234287Sdim return false; 275234287Sdim} 276234287Sdim 277234287Sdim#endif // _MSC_VER 278234287Sdim 279234287Sdimvoid Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 280234287Sdim ArgStringList &CC1Args) const { 281234287Sdim if (DriverArgs.hasArg(options::OPT_nostdinc)) 282234287Sdim return; 283234287Sdim 284234287Sdim if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 285234287Sdim llvm::sys::Path P(getDriver().ResourceDir); 286234287Sdim P.appendComponent("include"); 287234287Sdim addSystemInclude(DriverArgs, CC1Args, P.str()); 288234287Sdim } 289234287Sdim 290234287Sdim if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 291234287Sdim return; 292234287Sdim 293234287Sdim#ifdef _MSC_VER 294234287Sdim // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. 295234287Sdim if (const char *cl_include_dir = getenv("INCLUDE")) { 296234287Sdim SmallVector<StringRef, 8> Dirs; 297234287Sdim StringRef(cl_include_dir).split(Dirs, ";"); 298234287Sdim int n = 0; 299234287Sdim for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end(); 300234287Sdim I != E; ++I) { 301234287Sdim StringRef d = *I; 302234287Sdim if (d.size() == 0) 303234287Sdim continue; 304234287Sdim ++n; 305234287Sdim addSystemInclude(DriverArgs, CC1Args, d); 306234287Sdim } 307234287Sdim if (n) return; 308234287Sdim } 309234287Sdim 310234287Sdim std::string VSDir; 311234287Sdim std::string WindowsSDKDir; 312234287Sdim 313234287Sdim // When built with access to the proper Windows APIs, try to actually find 314234287Sdim // the correct include paths first. 315234287Sdim if (getVisualStudioDir(VSDir)) { 316234287Sdim addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include"); 317234287Sdim if (getWindowsSDKDir(WindowsSDKDir)) 318234287Sdim addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include"); 319234287Sdim else 320234287Sdim addSystemInclude(DriverArgs, CC1Args, 321234287Sdim VSDir + "\\VC\\PlatformSDK\\Include"); 322234287Sdim return; 323234287Sdim } 324234287Sdim#endif // _MSC_VER 325234287Sdim 326234287Sdim // As a fallback, select default install paths. 327234287Sdim const StringRef Paths[] = { 328234287Sdim "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 329234287Sdim "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 330234287Sdim "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 331234287Sdim "C:/Program Files/Microsoft Visual Studio 8/VC/include", 332234287Sdim "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 333234287Sdim }; 334234287Sdim addSystemIncludes(DriverArgs, CC1Args, Paths); 335234287Sdim} 336234287Sdim 337234287Sdimvoid Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 338234287Sdim ArgStringList &CC1Args) const { 339234287Sdim // FIXME: There should probably be logic here to find libc++ on Windows. 340234287Sdim} 341