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/Arg.h" 14 #include "clang/Driver/ArgList.h" 15 #include "clang/Driver/Compilation.h" 16 #include "clang/Driver/Driver.h" 17 #include "clang/Driver/Options.h" 18 #include "llvm/Support/ErrorHandling.h" 19 #include "llvm/Support/Path.h" 20 21 // Include the necessary headers to interface with the Windows registry and 22 // environment. 23 #ifdef _MSC_VER 24 #define WIN32_LEAN_AND_MEAN 25 #define NOGDI 26 #define NOMINMAX 27 #include <Windows.h> 28 #endif 29 30 using namespace clang::driver; 31 using namespace clang::driver::toolchains; 32 using namespace clang; 33 34 Windows::Windows(const Driver &D, const llvm::Triple& Triple, 35 const ArgList &Args) 36 : ToolChain(D, Triple, Args) { 37 } 38 39 Tool *Windows::constructTool(Action::ActionClass AC) const { 40 switch (AC) { 41 case Action::InputClass: 42 case Action::BindArchClass: 43 case Action::LipoJobClass: 44 case Action::DsymutilJobClass: 45 case Action::VerifyJobClass: 46 case Action::PreprocessJobClass: 47 case Action::PrecompileJobClass: 48 case Action::AnalyzeJobClass: 49 case Action::MigrateJobClass: 50 case Action::CompileJobClass: 51 return new tools::Clang(*this); 52 case Action::AssembleJobClass: 53 if (!useIntegratedAs() && 54 getTriple().getEnvironment() == llvm::Triple::MachO) 55 return new tools::darwin::Assemble(*this); 56 else 57 return new tools::ClangAs(*this); 58 break; 59 case Action::LinkJobClass: 60 return new tools::visualstudio::Link(*this); 61 } 62 } 63 64 bool Windows::IsIntegratedAssemblerDefault() const { 65 return true; 66 } 67 68 bool Windows::IsUnwindTablesDefault() const { 69 return getArch() == llvm::Triple::x86_64; 70 } 71 72 bool Windows::isPICDefault() const { 73 return getArch() == llvm::Triple::x86_64; 74 } 75 76 bool Windows::isPICDefaultForced() const { 77 return getArch() == llvm::Triple::x86_64; 78 } 79 80 // FIXME: This probably should goto to some platform utils place. 81 #ifdef _MSC_VER 82 83 /// \brief Read registry string. 84 /// This also supports a means to look for high-versioned keys by use 85 /// of a $VERSION placeholder in the key path. 86 /// $VERSION in the key path is a placeholder for the version number, 87 /// causing the highest value path to be searched for and used. 88 /// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 89 /// There can be additional characters in the component. Only the numberic 90 /// characters are compared. 91 static bool getSystemRegistryString(const char *keyPath, const char *valueName, 92 char *value, size_t maxLength) { 93 HKEY hRootKey = NULL; 94 HKEY hKey = NULL; 95 const char* subKey = NULL; 96 DWORD valueType; 97 DWORD valueSize = maxLength - 1; 98 long lResult; 99 bool returnValue = false; 100 101 if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { 102 hRootKey = HKEY_CLASSES_ROOT; 103 subKey = keyPath + 18; 104 } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { 105 hRootKey = HKEY_USERS; 106 subKey = keyPath + 11; 107 } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { 108 hRootKey = HKEY_LOCAL_MACHINE; 109 subKey = keyPath + 19; 110 } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { 111 hRootKey = HKEY_CURRENT_USER; 112 subKey = keyPath + 18; 113 } else { 114 return false; 115 } 116 117 const char *placeHolder = strstr(subKey, "$VERSION"); 118 char bestName[256]; 119 bestName[0] = '\0'; 120 // If we have a $VERSION placeholder, do the highest-version search. 121 if (placeHolder) { 122 const char *keyEnd = placeHolder - 1; 123 const char *nextKey = placeHolder; 124 // Find end of previous key. 125 while ((keyEnd > subKey) && (*keyEnd != '\\')) 126 keyEnd--; 127 // Find end of key containing $VERSION. 128 while (*nextKey && (*nextKey != '\\')) 129 nextKey++; 130 size_t partialKeyLength = keyEnd - subKey; 131 char partialKey[256]; 132 if (partialKeyLength > sizeof(partialKey)) 133 partialKeyLength = sizeof(partialKey); 134 strncpy(partialKey, subKey, partialKeyLength); 135 partialKey[partialKeyLength] = '\0'; 136 HKEY hTopKey = NULL; 137 lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey); 138 if (lResult == ERROR_SUCCESS) { 139 char keyName[256]; 140 int bestIndex = -1; 141 double bestValue = 0.0; 142 DWORD index, size = sizeof(keyName) - 1; 143 for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, 144 NULL, NULL, NULL) == ERROR_SUCCESS; index++) { 145 const char *sp = keyName; 146 while (*sp && !isDigit(*sp)) 147 sp++; 148 if (!*sp) 149 continue; 150 const char *ep = sp + 1; 151 while (*ep && (isDigit(*ep) || (*ep == '.'))) 152 ep++; 153 char numBuf[32]; 154 strncpy(numBuf, sp, sizeof(numBuf) - 1); 155 numBuf[sizeof(numBuf) - 1] = '\0'; 156 double value = strtod(numBuf, NULL); 157 if (value > bestValue) { 158 bestIndex = (int)index; 159 bestValue = value; 160 strcpy(bestName, keyName); 161 } 162 size = sizeof(keyName) - 1; 163 } 164 // If we found the highest versioned key, open the key and get the value. 165 if (bestIndex != -1) { 166 // Append rest of key. 167 strncat(bestName, nextKey, sizeof(bestName) - 1); 168 bestName[sizeof(bestName) - 1] = '\0'; 169 // Open the chosen key path remainder. 170 lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey); 171 if (lResult == ERROR_SUCCESS) { 172 lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 173 (LPBYTE)value, &valueSize); 174 if (lResult == ERROR_SUCCESS) 175 returnValue = true; 176 RegCloseKey(hKey); 177 } 178 } 179 RegCloseKey(hTopKey); 180 } 181 } else { 182 lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey); 183 if (lResult == ERROR_SUCCESS) { 184 lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 185 (LPBYTE)value, &valueSize); 186 if (lResult == ERROR_SUCCESS) 187 returnValue = true; 188 RegCloseKey(hKey); 189 } 190 } 191 return returnValue; 192 } 193 194 /// \brief Get Windows SDK installation directory. 195 static bool getWindowsSDKDir(std::string &path) { 196 char windowsSDKInstallDir[256]; 197 // Try the Windows registry. 198 bool hasSDKDir = getSystemRegistryString( 199 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 200 "InstallationFolder", 201 windowsSDKInstallDir, 202 sizeof(windowsSDKInstallDir) - 1); 203 // If we have both vc80 and vc90, pick version we were compiled with. 204 if (hasSDKDir && windowsSDKInstallDir[0]) { 205 path = windowsSDKInstallDir; 206 return true; 207 } 208 return false; 209 } 210 211 // Get Visual Studio installation directory. 212 static bool getVisualStudioDir(std::string &path) { 213 // First check the environment variables that vsvars32.bat sets. 214 const char* vcinstalldir = getenv("VCINSTALLDIR"); 215 if (vcinstalldir) { 216 char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); 217 if (p) 218 *p = '\0'; 219 path = vcinstalldir; 220 return true; 221 } 222 223 char vsIDEInstallDir[256]; 224 char vsExpressIDEInstallDir[256]; 225 // Then try the windows registry. 226 bool hasVCDir = getSystemRegistryString( 227 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", 228 "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); 229 bool hasVCExpressDir = getSystemRegistryString( 230 "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", 231 "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); 232 // If we have both vc80 and vc90, pick version we were compiled with. 233 if (hasVCDir && vsIDEInstallDir[0]) { 234 char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); 235 if (p) 236 *p = '\0'; 237 path = vsIDEInstallDir; 238 return true; 239 } 240 241 if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { 242 char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); 243 if (p) 244 *p = '\0'; 245 path = vsExpressIDEInstallDir; 246 return true; 247 } 248 249 // Try the environment. 250 const char *vs100comntools = getenv("VS100COMNTOOLS"); 251 const char *vs90comntools = getenv("VS90COMNTOOLS"); 252 const char *vs80comntools = getenv("VS80COMNTOOLS"); 253 const char *vscomntools = NULL; 254 255 // Try to find the version that we were compiled with 256 if(false) {} 257 #if (_MSC_VER >= 1600) // VC100 258 else if(vs100comntools) { 259 vscomntools = vs100comntools; 260 } 261 #elif (_MSC_VER == 1500) // VC80 262 else if(vs90comntools) { 263 vscomntools = vs90comntools; 264 } 265 #elif (_MSC_VER == 1400) // VC80 266 else if(vs80comntools) { 267 vscomntools = vs80comntools; 268 } 269 #endif 270 // Otherwise find any version we can 271 else if (vs100comntools) 272 vscomntools = vs100comntools; 273 else if (vs90comntools) 274 vscomntools = vs90comntools; 275 else if (vs80comntools) 276 vscomntools = vs80comntools; 277 278 if (vscomntools && *vscomntools) { 279 const char *p = strstr(vscomntools, "\\Common7\\Tools"); 280 path = p ? std::string(vscomntools, p) : vscomntools; 281 return true; 282 } 283 return false; 284 } 285 286 #endif // _MSC_VER 287 288 void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 289 ArgStringList &CC1Args) const { 290 if (DriverArgs.hasArg(options::OPT_nostdinc)) 291 return; 292 293 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 294 llvm::sys::Path P(getDriver().ResourceDir); 295 P.appendComponent("include"); 296 addSystemInclude(DriverArgs, CC1Args, P.str()); 297 } 298 299 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 300 return; 301 302 #ifdef _MSC_VER 303 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. 304 if (const char *cl_include_dir = getenv("INCLUDE")) { 305 SmallVector<StringRef, 8> Dirs; 306 StringRef(cl_include_dir).split(Dirs, ";"); 307 int n = 0; 308 for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end(); 309 I != E; ++I) { 310 StringRef d = *I; 311 if (d.size() == 0) 312 continue; 313 ++n; 314 addSystemInclude(DriverArgs, CC1Args, d); 315 } 316 if (n) return; 317 } 318 319 std::string VSDir; 320 std::string WindowsSDKDir; 321 322 // When built with access to the proper Windows APIs, try to actually find 323 // the correct include paths first. 324 if (getVisualStudioDir(VSDir)) { 325 addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include"); 326 if (getWindowsSDKDir(WindowsSDKDir)) 327 addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include"); 328 else 329 addSystemInclude(DriverArgs, CC1Args, 330 VSDir + "\\VC\\PlatformSDK\\Include"); 331 return; 332 } 333 #endif // _MSC_VER 334 335 // As a fallback, select default install paths. 336 const StringRef Paths[] = { 337 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 338 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 339 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 340 "C:/Program Files/Microsoft Visual Studio 8/VC/include", 341 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 342 }; 343 addSystemIncludes(DriverArgs, CC1Args, Paths); 344 } 345 346 void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 347 ArgStringList &CC1Args) const { 348 // FIXME: There should probably be logic here to find libc++ on Windows. 349 } 350