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