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