InitHeaderSearch.cpp revision 199990
194380Sdfr//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===// 294380Sdfr// 394380Sdfr// The LLVM Compiler Infrastructure 494380Sdfr// 594380Sdfr// This file is distributed under the University of Illinois Open Source 6313452Sjhb// License. See LICENSE.TXT for details. 794380Sdfr// 894380Sdfr//===----------------------------------------------------------------------===// 9119332Speter// 10119332Speter// This file implements the InitHeaderSearch class. 1194380Sdfr// 1294380Sdfr//===----------------------------------------------------------------------===// 1394380Sdfr 14177613Sjhb#include "clang/Frontend/Utils.h" 15227776Slstewart#include "clang/Basic/FileManager.h" 16164199Sru#include "clang/Basic/LangOptions.h" 17113989Sjhb#include "clang/Frontend/HeaderSearchOptions.h" 18255658Sjilles#include "clang/Lex/HeaderSearch.h" 19113989Sjhb#include "llvm/ADT/SmallString.h" 20161330Sjhb#include "llvm/ADT/SmallPtrSet.h" 21161330Sjhb#include "llvm/ADT/SmallVector.h" 2294380Sdfr#include "llvm/ADT/StringExtras.h" 2394380Sdfr#include "llvm/ADT/Triple.h" 2494380Sdfr#include "llvm/Support/raw_ostream.h" 2594380Sdfr#include "llvm/System/Path.h" 2694380Sdfr#include "llvm/Config/config.h" 2794380Sdfr#include <cstdio> 2894380Sdfr#ifdef _MSC_VER 2994380Sdfr #define WIN32_LEAN_AND_MEAN 1 3094380Sdfr #include <windows.h> 3194380Sdfr#endif 3294380Sdfrusing namespace clang; 3394380Sdfrusing namespace clang::frontend; 3494380Sdfr 3594380Sdfrnamespace { 3694380Sdfr 37232449Sjmallett/// InitHeaderSearch - This class makes it easier to set the search paths of 38205014Snwhitehorn/// a HeaderSearch object. InitHeaderSearch stores several search path lists 39205014Snwhitehorn/// internally, which can be sent to a HeaderSearch object in one swoop. 40119332Speterclass InitHeaderSearch { 4194380Sdfr std::vector<DirectoryLookup> IncludeGroup[4]; 4294380Sdfr HeaderSearch& Headers; 4394380Sdfr bool Verbose; 44100385Speter std::string isysroot; 4594380Sdfr 46151360Spspublic: 47151360Sps 48151360Sps InitHeaderSearch(HeaderSearch &HS, 49151360Sps bool verbose = false, const std::string &iSysroot = "") 50151360Sps : Headers(HS), Verbose(verbose), isysroot(iSysroot) {} 51151360Sps 52151360Sps /// AddPath - Add the specified path to the specified group list. 53151360Sps void AddPath(const llvm::StringRef &Path, IncludeDirGroup Group, 54151360Sps bool isCXXAware, bool isUserSupplied, 55151360Sps bool isFramework, bool IgnoreSysRoot = false); 56151360Sps 57151360Sps /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to suport a gnu 58236027Sed /// libstdc++. 59236027Sed void AddGnuCPlusPlusIncludePaths(const std::string &Base, 60151360Sps const char *ArchDir, 61236027Sed const char *Dir32, 62236027Sed const char *Dir64, 63151360Sps const llvm::Triple &triple); 64302095Sbrooks 65302095Sbrooks /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to suport a MinGW 66302095Sbrooks /// libstdc++. 67151721Speter void AddMinGWCPlusPlusIncludePaths(const std::string &Base, 68151583Sps const char *Arch, 69151583Sps const char *Version); 70119332Speter 71100385Speter /// AddDelimitedPaths - Add a list of paths delimited by the system PATH 72100385Speter /// separator. The processing follows that of the CPATH variable for gcc. 7394380Sdfr void AddDelimitedPaths(const char *String); 74183271Sobrien 75183271Sobrien // AddDefaultCIncludePaths - Add paths that should always be searched. 76183271Sobrien void AddDefaultCIncludePaths(const llvm::Triple &triple); 77183271Sobrien 78183271Sobrien // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when 79119332Speter // compiling c++. 8094380Sdfr void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple); 81236027Sed 82236027Sed /// AddDefaultSystemIncludePaths - Adds the default system include paths so 8394380Sdfr /// that e.g. stdio.h is found. 84226349Smarcel void AddDefaultSystemIncludePaths(const LangOptions &Lang, 85226349Smarcel const llvm::Triple &triple); 86226349Smarcel 87226349Smarcel /// Realize - Merges all search path lists into one list and send it to 88226349Smarcel /// HeaderSearch. 89119332Speter void Realize(); 9094380Sdfr}; 91100385Speter 92100385Speter} 9394380Sdfr 94125171Spetervoid InitHeaderSearch::AddPath(const llvm::StringRef &Path, 95125171Speter IncludeDirGroup Group, bool isCXXAware, 96125171Speter bool isUserSupplied, bool isFramework, 97125171Speter bool IgnoreSysRoot) { 98270692Skib assert(!Path.empty() && "can't handle empty path here"); 99270692Skib FileManager &FM = Headers.getFileMgr(); 100270692Skib 101270692Skib // Compute the actual path, taking into consideration -isysroot. 102270692Skib llvm::SmallString<256> MappedPath; 103119332Speter 10494380Sdfr // Handle isysroot. 10594380Sdfr if (Group == System && !IgnoreSysRoot) { 10694380Sdfr // FIXME: Portability. This should be a sys::Path interface, this doesn't 10794380Sdfr // handle things like C:\ right, nor win32 \\network\device\blah. 108100385Speter if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present. 10994380Sdfr MappedPath.append(isysroot.begin(), isysroot.end()); 110119332Speter } 111100385Speter 11294380Sdfr MappedPath.append(Path.begin(), Path.end()); 11394380Sdfr 114119332Speter // Compute the DirectoryLookup type. 11594380Sdfr SrcMgr::CharacteristicKind Type; 116100385Speter if (Group == Quoted || Group == Angled) 11794380Sdfr Type = SrcMgr::C_User; 118119332Speter else if (isCXXAware) 11994380Sdfr Type = SrcMgr::C_System; 120100385Speter else 12194380Sdfr Type = SrcMgr::C_ExternCSystem; 12294380Sdfr 123119332Speter 12494380Sdfr // If the directory exists, add it. 125100385Speter if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) { 12694380Sdfr IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied, 12794380Sdfr isFramework)); 128119332Speter return; 129100385Speter } 13094380Sdfr 13194380Sdfr // Check to see if this is an apple-style headermap (which are not allowed to 132119332Speter // be frameworks). 13394380Sdfr if (!isFramework) { 134100385Speter if (const FileEntry *FE = FM.getFile(MappedPath.str())) { 13594380Sdfr if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) { 136119332Speter // It is a headermap, add it to the search path. 137100385Speter IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); 138100385Speter return; 13994380Sdfr } 140190622Skib } 141190622Skib } 142190622Skib 143190622Skib if (Verbose) 144119332Speter llvm::errs() << "ignoring nonexistent directory \"" 14594380Sdfr << MappedPath.str() << "\"\n"; 14694380Sdfr} 14794380Sdfr 14894380Sdfr 14994380Sdfrvoid InitHeaderSearch::AddDelimitedPaths(const char *at) { 15094380Sdfr if (*at == 0) // Empty string should not add '.' path. 151119332Speter return; 15294380Sdfr 15394380Sdfr const char* delim = strchr(at, llvm::sys::PathSeparator); 15494380Sdfr while (delim != 0) { 15594380Sdfr if (delim-at == 0) 15694380Sdfr AddPath(".", Angled, false, true, false); 15794380Sdfr else 15894380Sdfr AddPath(llvm::StringRef(at, delim-at), Angled, false, true, false); 159119332Speter at = delim + 1; 160157286Sps delim = strchr(at, llvm::sys::PathSeparator); 161157286Sps } 162157286Sps if (*at == 0) 163157286Sps AddPath(".", Angled, false, true, false); 16494380Sdfr else 165119332Speter AddPath(at, Angled, false, true, false); 16694380Sdfr} 167100385Speter 16894380Sdfrvoid InitHeaderSearch::AddGnuCPlusPlusIncludePaths(const std::string &Base, 169119332Speter const char *ArchDir, 17094380Sdfr const char *Dir32, 171100385Speter const char *Dir64, 17294380Sdfr const llvm::Triple &triple) { 173119332Speter // Add the base dir 17494380Sdfr AddPath(Base, System, true, false, false); 175100385Speter 17694380Sdfr // Add the multilib dirs 177184184Sjhb llvm::Triple::ArchType arch = triple.getArch(); 178184184Sjhb bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64; 179184184Sjhb if (is64bit) 180184184Sjhb AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false); 181184184Sjhb else 182184184Sjhb AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false); 183119332Speter 18494380Sdfr // Add the backward dir 18594380Sdfr AddPath(Base + "/backward", System, true, false, false); 18694380Sdfr} 187236027Sed 18894380Sdfrvoid InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(const std::string &Base, 189236027Sed const char *Arch, 19094380Sdfr const char *Version) { 191154596Sambrisko std::string localBase = Base + "/" + Arch + "/" + Version + "/include"; 192154596Sambrisko AddPath(localBase, System, true, false, false); 193154596Sambrisko AddPath(localBase + "/c++", System, true, false, false); 194154596Sambrisko AddPath(localBase + "/c++/backward", System, true, false, false); 195165406Sjkim} 196165406Sjkim 197165406Sjkim // FIXME: This probably should goto to some platform utils place. 198165406Sjkim#ifdef _MSC_VER 199165406Sjkim 200165406Sjkim // Read registry string. 201165406Sjkim // This also supports a means to look for high-versioned keys by use 202165406Sjkim // of a $VERSION placeholder in the key path. 203165406Sjkim // $VERSION in the key path is a placeholder for the version number, 204165406Sjkim // causing the highest value path to be searched for and used. 205165406Sjkim // I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 206165406Sjkim // There can be additional characters in the component. Only the numberic 207165406Sjkim // characters are compared. 208151358Spsbool getSystemRegistryString(const char *keyPath, const char *valueName, 209151358Sps char *value, size_t maxLength) { 210151358Sps HKEY hRootKey = NULL; 211151358Sps HKEY hKey = NULL; 212151358Sps const char* subKey = NULL; 213151358Sps DWORD valueType; 214151358Sps DWORD valueSize = maxLength - 1; 215151358Sps long lResult; 216151358Sps bool returnValue = false; 217151358Sps if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { 218151358Sps hRootKey = HKEY_CLASSES_ROOT; 219151358Sps subKey = keyPath + 18; 220253531Skib } 221253531Skib else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { 222253531Skib hRootKey = HKEY_USERS; 223253531Skib subKey = keyPath + 11; 224253531Skib } 225253531Skib else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { 226253531Skib hRootKey = HKEY_LOCAL_MACHINE; 227253531Skib subKey = keyPath + 19; 228253531Skib } 229253531Skib else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { 230253531Skib hRootKey = HKEY_CURRENT_USER; 231253531Skib subKey = keyPath + 18; 232253531Skib } 233253531Skib else 234253531Skib return(false); 235140481Sps const char *placeHolder = strstr(subKey, "$VERSION"); 236151356Sps char bestName[256]; 237151356Sps bestName[0] = '\0'; 238140481Sps // If we have a $VERSION placeholder, do the highest-version search. 239253495Skib if (placeHolder) { 240253495Skib const char *keyEnd = placeHolder - 1; 241253495Skib const char *nextKey = placeHolder; 242253495Skib // Find end of previous key. 243253495Skib while ((keyEnd > subKey) && (*keyEnd != '\\')) 244253495Skib keyEnd--; 245185879Sjhb // Find end of key containing $VERSION. 246185879Sjhb while (*nextKey && (*nextKey != '\\')) 247185879Sjhb nextKey++; 248185879Sjhb size_t partialKeyLength = keyEnd - subKey; 249185879Sjhb char partialKey[256]; 250185879Sjhb if (partialKeyLength > sizeof(partialKey)) 251185879Sjhb partialKeyLength = sizeof(partialKey); 252185879Sjhb strncpy(partialKey, subKey, partialKeyLength); 253185879Sjhb partialKey[partialKeyLength] = '\0'; 254185879Sjhb HKEY hTopKey = NULL; 255253531Skib lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey); 256185879Sjhb if (lResult == ERROR_SUCCESS) { 257154587Sambrisko char keyName[256]; 258154587Sambrisko int bestIndex = -1; 259154587Sambrisko double bestValue = 0.0; 260154587Sambrisko DWORD index, size = sizeof(keyName) - 1; 261147814Sjhb for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, 262147814Sjhb NULL, NULL, NULL) == ERROR_SUCCESS; index++) { 263147814Sjhb const char *sp = keyName; 264147814Sjhb while (*sp && !isdigit(*sp)) 265236027Sed sp++; 266236027Sed if (!*sp) 267147814Sjhb continue; 268147814Sjhb const char *ep = sp + 1; 269147814Sjhb while (*ep && (isdigit(*ep) || (*ep == '.'))) 270147814Sjhb ep++; 271147814Sjhb char numBuf[32]; 272236027Sed strncpy(numBuf, sp, sizeof(numBuf) - 1); 273236027Sed numBuf[sizeof(numBuf) - 1] = '\0'; 274147814Sjhb double value = strtod(numBuf, NULL); 275140482Sps if (value > bestValue) { 276140482Sps bestIndex = (int)index; 277140482Sps bestValue = value; 278140482Sps strcpy(bestName, keyName); 279220159Skib } 280220159Skib size = sizeof(keyName) - 1; 281220159Skib } 282220159Skib // If we found the highest versioned key, open the key and get the value. 283185879Sjhb if (bestIndex != -1) { 284185879Sjhb // Append rest of key. 285185879Sjhb strncat(bestName, nextKey, sizeof(bestName) - 1); 286185879Sjhb bestName[sizeof(bestName) - 1] = '\0'; 287185879Sjhb // Open the chosen key path remainder. 288185879Sjhb lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey); 289185879Sjhb if (lResult == ERROR_SUCCESS) { 290185879Sjhb lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 291185879Sjhb (LPBYTE)value, &valueSize); 292185879Sjhb if (lResult == ERROR_SUCCESS) 293185879Sjhb returnValue = true; 294185436Sbz RegCloseKey(hKey); 295185436Sbz } 296185436Sbz } 297163020Sdavidxu RegCloseKey(hTopKey); 298163020Sdavidxu } 299163020Sdavidxu } 300163020Sdavidxu else { 301163020Sdavidxu lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey); 302163020Sdavidxu if (lResult == ERROR_SUCCESS) { 303163020Sdavidxu lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, 304163020Sdavidxu (LPBYTE)value, &valueSize); 305163020Sdavidxu if (lResult == ERROR_SUCCESS) 306185879Sjhb returnValue = true; 307185879Sjhb RegCloseKey(hKey); 308185879Sjhb } 309185879Sjhb } 310119332Speter return(returnValue); 311114988Speter} 312142874Sps#else // _MSC_VER 313114988Speter // Read registry string. 314142874Spsbool getSystemRegistryString(const char *, const char *, char *, size_t) { 315114988Speter return(false); 316142874Sps} 317104739Speter#endif // _MSC_VER 318183189Sobrien 319183189Sobrien // Get Visual Studio installation directory. 320183189Sobrienbool getVisualStudioDir(std::string &path) { 321183189Sobrien char vsIDEInstallDir[256]; 322183189Sobrien // Try the Windows registry first. 323119332Speter bool hasVCDir = getSystemRegistryString( 32494380Sdfr "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", 32594380Sdfr "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); 326236027Sed // If we have both vc80 and vc90, pick version we were compiled with. 327236027Sed if (hasVCDir && vsIDEInstallDir[0]) { 32894380Sdfr char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); 329156115Sps if (p) 33094380Sdfr *p = '\0'; 33194380Sdfr path = vsIDEInstallDir; 33294380Sdfr return(true); 333205328Skib } 334205328Skib else { 335205328Skib // Try the environment. 336205328Skib const char* vs90comntools = getenv("VS90COMNTOOLS"); 337205328Skib const char* vs80comntools = getenv("VS80COMNTOOLS"); 338205328Skib const char* vscomntools = NULL; 339205328Skib // If we have both vc80 and vc90, pick version we were compiled with. 340205328Skib if (vs90comntools && vs80comntools) { 341205328Skib #if (_MSC_VER >= 1500) // VC90 342205328Skib vscomntools = vs90comntools; 343205328Skib #elif (_MSC_VER == 1400) // VC80 344119332Speter vscomntools = vs80comntools; 345114988Speter #else 346114988Speter vscomntools = vs90comntools; 347114988Speter #endif 348114988Speter } 349119332Speter else if (vs90comntools) 350119332Speter vscomntools = vs90comntools; 351119194Speter else if (vs80comntools) 352150632Speter vscomntools = vs80comntools; 353150632Speter if (vscomntools && *vscomntools) { 354150632Speter char *p = (char*)strstr(vscomntools, "\\Common7\\Tools"); 355150632Speter if (p) 356150632Speter *p = '\0'; 357150632Speter path = vscomntools; 358150632Speter return(true); 359150632Speter } 360150632Speter else 361150632Speter return(false); 362205328Skib } 363205328Skib return(false); 364205328Skib} 365205328Skib 366162552Sdavidxu // Get Windows SDK installation directory. 367162552Sdavidxubool getWindowsSDKDir(std::string &path) { 368162552Sdavidxu char windowsSDKInstallDir[256]; 369162537Sdavidxu // Try the Windows registry. 370162537Sdavidxu bool hasSDKDir = getSystemRegistryString( 371162537Sdavidxu "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 372163451Sdavidxu "InstallationFolder", windowsSDKInstallDir, sizeof(windowsSDKInstallDir) - 1); 373162537Sdavidxu // If we have both vc80 and vc90, pick version we were compiled with. 374162537Sdavidxu if (hasSDKDir && windowsSDKInstallDir[0]) { 375162537Sdavidxu path = windowsSDKInstallDir; 376162552Sdavidxu return(true); 377162552Sdavidxu } 378162552Sdavidxu return(false); 379162552Sdavidxu} 380205328Skib 381205328Skibvoid InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple) { 382205328Skib // FIXME: temporary hack: hard-coded paths. 383205328Skib llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS); 384205328Skib if (CIncludeDirs != "") { 385205328Skib llvm::SmallVector<llvm::StringRef, 5> dirs; 386205328Skib CIncludeDirs.split(dirs, ":"); 387205328Skib for (llvm::SmallVectorImpl<llvm::StringRef>::iterator i = dirs.begin(); 388205328Skib i != dirs.end(); 389205328Skib ++i) 390205328Skib AddPath(*i, System, false, false, false); 391205328Skib return; 392205328Skib } 393205328Skib llvm::Triple::OSType os = triple.getOS(); 394205328Skib switch (os) { 395205328Skib case llvm::Triple::Win32: 396205328Skib { 397205328Skib std::string VSDir; 398205328Skib std::string WindowsSDKDir; 399205328Skib if (getVisualStudioDir(VSDir)) { 400205328Skib AddPath(VSDir + "\\VC\\include", System, false, false, false); 401205328Skib if (getWindowsSDKDir(WindowsSDKDir)) 402205328Skib AddPath(WindowsSDKDir, System, false, false, false); 403205328Skib else 404205328Skib AddPath(VSDir + "\\VC\\PlatformSDK\\Include", 405253531Skib System, false, false, false); 406253531Skib } 407253531Skib else { 408253531Skib // Default install paths. 409185879Sjhb AddPath("C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 410185879Sjhb System, false, false, false); 411185879Sjhb AddPath( 412185879Sjhb "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 413205014Snwhitehorn System, false, false, false); 414171214Speter AddPath("C:/Program Files/Microsoft Visual Studio 8/VC/include", 415171214Speter System, false, false, false); 416171214Speter AddPath( 417171214Speter "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include", 418205014Snwhitehorn System, false, false, false); 419236027Sed // For some clang developers. 420236027Sed AddPath("G:/Program Files/Microsoft Visual Studio 9.0/VC/include", 421171214Speter System, false, false, false); 422171214Speter AddPath( 423171214Speter "G:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 424171214Speter System, false, false, false); 425171214Speter } 426205014Snwhitehorn } 427236027Sed break; 428236027Sed case llvm::Triple::MinGW64: 429171214Speter case llvm::Triple::MinGW32: 430171214Speter AddPath("c:/mingw/include", System, true, false, false); 431171214Speter break; 432171214Speter default: 433171214Speter break; 434171214Speter } 435171214Speter 436205014Snwhitehorn AddPath("/usr/local/include", System, false, false, false); 437236027Sed AddPath("/usr/include", System, false, false, false); 438236027Sed} 439171214Speter 440171214Spetervoid InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { 441171214Speter llvm::Triple::OSType os = triple.getOS(); 442205014Snwhitehorn llvm::StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT); 443236027Sed if (CxxIncludeRoot != "") { 444236027Sed llvm::StringRef CxxIncludeArch(CXX_INCLUDE_ARCH); 445171214Speter if (CxxIncludeArch == "") 446171214Speter AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, triple.str().c_str(), 447171214Speter CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple); 448171214Speter else 449205014Snwhitehorn AddGnuCPlusPlusIncludePaths(CxxIncludeRoot, CXX_INCLUDE_ARCH, 450236027Sed CXX_INCLUDE_32BIT_DIR, CXX_INCLUDE_64BIT_DIR, triple); 451236027Sed return; 452171214Speter } 453171214Speter // FIXME: temporary hack: hard-coded paths. 454171214Speter switch (os) { 455205014Snwhitehorn case llvm::Triple::Cygwin: 456236027Sed AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include", 457236027Sed System, true, false, false); 458171214Speter AddPath("/lib/gcc/i686-pc-cygwin/3.4.4/include/c++", 459205014Snwhitehorn System, true, false, false); 460205014Snwhitehorn break; 461205014Snwhitehorn case llvm::Triple::MinGW64: 462205014Snwhitehorn // Try gcc 4.4.0 463205014Snwhitehorn AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0"); 464236027Sed // Try gcc 4.3.0 465236027Sed AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0"); 466205014Snwhitehorn // Fall through. 467205014Snwhitehorn case llvm::Triple::MinGW32: 468205014Snwhitehorn // Try gcc 4.4.0 469205014Snwhitehorn AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0"); 470205014Snwhitehorn // Try gcc 4.3.0 471236027Sed AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.3.0"); 472236027Sed break; 473205014Snwhitehorn case llvm::Triple::Darwin: 474205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", 475205014Snwhitehorn "i686-apple-darwin10", "", "x86_64", triple); 476205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", 477205014Snwhitehorn "i686-apple-darwin8", "", "", triple); 478205014Snwhitehorn break; 479205014Snwhitehorn case llvm::Triple::Linux: 480236027Sed // Ubuntu 7.10 - Gutsy Gibbon 481236027Sed AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.3", 482205014Snwhitehorn "i486-linux-gnu", "", "", triple); 483205014Snwhitehorn // Ubuntu 9.04 484205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.3", 485236027Sed "x86_64-linux-gnu","32", "", triple); 486236027Sed // Ubuntu 9.10 487205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1", 488205014Snwhitehorn "x86_64-linux-gnu", "32", "", triple); 489205014Snwhitehorn // Fedora 8 490205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.1.2", 491236027Sed "i386-redhat-linux", "", "", triple); 492236027Sed // Fedora 9 493205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.0", 494205014Snwhitehorn "i386-redhat-linux", "", "", triple); 495205014Snwhitehorn // Fedora 10 496236027Sed AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.2", 497236027Sed "i386-redhat-linux","", "", triple); 498205014Snwhitehorn 499205014Snwhitehorn // Fedora 11 500205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.1", 501180434Sbrooks "i586-redhat-linux","", "", triple); 502180434Sbrooks 503205014Snwhitehorn // openSUSE 11.1 32 bit 504236027Sed AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", 505236027Sed "i586-suse-linux", "", "", triple); 506180434Sbrooks // openSUSE 11.1 64 bit 507180434Sbrooks AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", 508205014Snwhitehorn "x86_64-suse-linux", "32", "", triple); 509205014Snwhitehorn // openSUSE 11.2 510205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4", 511236027Sed "i586-suse-linux", "", "", triple); 512236027Sed AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4", 513205014Snwhitehorn "x86_64-suse-linux", "", "", triple); 514205014Snwhitehorn // Arch Linux 2008-06-24 515205014Snwhitehorn AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1", 516180434Sbrooks "i686-pc-linux-gnu", "", "", triple); 517180434Sbrooks AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3.1", 518180434Sbrooks "x86_64-unknown-linux-gnu", "", "", triple); 519236027Sed // Gentoo x86 2009.1 stable 520236027Sed AddGnuCPlusPlusIncludePaths( 521180434Sbrooks "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4", 522180434Sbrooks "i686-pc-linux-gnu", "", "", triple); 523180434Sbrooks // Gentoo x86 2009.0 stable 524180434Sbrooks AddGnuCPlusPlusIncludePaths( 525180434Sbrooks "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4", 526236027Sed "i686-pc-linux-gnu", "", "", triple); 527236027Sed // Gentoo x86 2008.0 stable 528180434Sbrooks AddGnuCPlusPlusIncludePaths( 529180434Sbrooks "/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4", 530180434Sbrooks "i686-pc-linux-gnu", "", "", triple); 531180434Sbrooks // Ubuntu 8.10 532180434Sbrooks AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", 533180434Sbrooks "i486-pc-linux-gnu", "", "", triple); 534236027Sed // Ubuntu 9.04 535236027Sed AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", 536180434Sbrooks "i486-linux-gnu","", "", triple); 537180434Sbrooks // Gentoo amd64 stable 538180434Sbrooks AddGnuCPlusPlusIncludePaths( 539177790Skib "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", 540177790Skib "i686-pc-linux-gnu", "", "", triple); 541236027Sed // Exherbo (2009-10-26) 542236027Sed AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", 543177790Skib "x86_64-pc-linux-gnu", "32", "", triple); 544177790Skib AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.4.2", 545177790Skib "i686-pc-linux-gnu", "", "", triple); 546177790Skib break; 547177790Skib case llvm::Triple::FreeBSD: 548177790Skib // DragonFly 549177790Skib AddPath("/usr/include/c++/4.1", System, true, false, false); 550177790Skib // FreeBSD 551177790Skib AddPath("/usr/include/c++/4.2", System, true, false, false); 552177790Skib break; 553177790Skib case llvm::Triple::Solaris: 554177790Skib // Solaris - Fall though.. 555191675Sjamie case llvm::Triple::AuroraUX: 556191675Sjamie // AuroraUX 557191675Sjamie AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4", 558191675Sjamie "i386-pc-solaris2.11", "", "", triple); 559191675Sjamie break; 560191675Sjamie default: 561191675Sjamie break; 562191675Sjamie } 563191675Sjamie} 564191675Sjamie 565194919Sjhbvoid InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, 566194919Sjhb const llvm::Triple &triple) { 567194919Sjhb if (Lang.CPlusPlus) 568194919Sjhb AddDefaultCPlusPlusIncludePaths(triple); 569194919Sjhb 570194919Sjhb AddDefaultCIncludePaths(triple); 571194919Sjhb 572194919Sjhb // Add the default framework include paths on Darwin. 573194919Sjhb if (triple.getOS() == llvm::Triple::Darwin) { 574194919Sjhb AddPath("/System/Library/Frameworks", System, true, false, true); 575194919Sjhb AddPath("/Library/Frameworks", System, true, false, true); 576194919Sjhb } 577194919Sjhb} 578194919Sjhb 579194919Sjhb/// RemoveDuplicates - If there are duplicate directory entries in the specified 580194919Sjhb/// search list, remove the later (dead) ones. 581198512Skibstatic void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, 582198512Skib bool Verbose) { 583198512Skib llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs; 584198512Skib llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs; 585198512Skib llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps; 586198512Skib for (unsigned i = 0; i != SearchList.size(); ++i) { 587198512Skib unsigned DirToRemove = i; 588198512Skib 589250854Skib const DirectoryLookup &CurEntry = SearchList[i]; 590220792Smdf 591220792Smdf if (CurEntry.isNormalDir()) { 592250854Skib // If this isn't the first time we've seen this dir, remove it. 593226365Sjhb if (SeenDirs.insert(CurEntry.getDir())) 594226365Sjhb continue; 595226365Sjhb } else if (CurEntry.isFramework()) { 596226365Sjhb // If this isn't the first time we've seen this framework dir, remove it. 597220792Smdf if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir())) 598227071Sjhb continue; 599227071Sjhb } else { 600250854Skib assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?"); 601227071Sjhb // If this isn't the first time we've seen this headermap, remove it. 602227071Sjhb if (SeenHeaderMaps.insert(CurEntry.getHeaderMap())) 603227071Sjhb continue; 604227071Sjhb } 605227071Sjhb 606227071Sjhb // If we have a normal #include dir/framework/headermap that is shadowed 607242959Skib // later in the chain by a system include location, we actually want to 608242959Skib // ignore the user's request and drop the user dir... keeping the system 609250854Skib // dir. This is weird, but required to emulate GCC's search path correctly. 610250854Skib // 611250854Skib // Since dupes of system dirs are rare, just rescan to find the original 612242959Skib // that we're nuking instead of using a DenseMap. 613242959Skib if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) { 614242959Skib // Find the dir that this is the same of. 615242959Skib unsigned FirstDir; 616242959Skib for (FirstDir = 0; ; ++FirstDir) { 617250854Skib assert(FirstDir != i && "Didn't find dupe?"); 618250854Skib 619250854Skib const DirectoryLookup &SearchEntry = SearchList[FirstDir]; 620250854Skib 621250854Skib // If these are different lookup types, then they can't be the dupe. 622250854Skib if (SearchEntry.getLookupType() != CurEntry.getLookupType()) 623250854Skib continue; 624250854Skib 625250854Skib bool isSame; 626250854Skib if (CurEntry.isNormalDir()) 627250854Skib isSame = SearchEntry.getDir() == CurEntry.getDir(); 628250854Skib else if (CurEntry.isFramework()) 629250854Skib isSame = SearchEntry.getFrameworkDir() == CurEntry.getFrameworkDir(); 630250854Skib else { 631250854Skib assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?"); 632250854Skib isSame = SearchEntry.getHeaderMap() == CurEntry.getHeaderMap(); 633250854Skib } 634250854Skib 635250854Skib if (isSame) 636250854Skib break; 637250854Skib } 638250854Skib 639250854Skib // If the first dir in the search path is a non-system dir, zap it 640250854Skib // instead of the system one. 641250854Skib if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User) 642250854Skib DirToRemove = FirstDir; 643254482Spjd } 644254482Spjd 645254482Spjd if (Verbose) { 646254482Spjd fprintf(stderr, "ignoring duplicate directory \"%s\"\n", 647254482Spjd CurEntry.getName()); 648254482Spjd if (DirToRemove != i) 649254482Spjd fprintf(stderr, " as it is a non-system directory that duplicates" 650254482Spjd " a system directory\n"); 651254482Spjd } 652254482Spjd 653251527Sglebius // This is reached if the current entry is a duplicate. Remove the 654251527Sglebius // DirToRemove (usually the current dir). 655251527Sglebius SearchList.erase(SearchList.begin()+DirToRemove); 656255709Sjhb --i; 657255709Sjhb } 658255709Sjhb} 659255709Sjhb 660255709Sjhb 661255709Sjhbvoid InitHeaderSearch::Realize() { 662255709Sjhb // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList. 663255709Sjhb std::vector<DirectoryLookup> SearchList; 664255709Sjhb SearchList = IncludeGroup[Angled]; 665255709Sjhb SearchList.insert(SearchList.end(), IncludeGroup[System].begin(), 666255709Sjhb IncludeGroup[System].end()); 667255709Sjhb SearchList.insert(SearchList.end(), IncludeGroup[After].begin(), 668255709Sjhb IncludeGroup[After].end()); 669255709Sjhb RemoveDuplicates(SearchList, Verbose); 670255709Sjhb RemoveDuplicates(IncludeGroup[Quoted], Verbose); 671255709Sjhb 672255709Sjhb // Prepend QUOTED list on the search list. 673255709Sjhb SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), 674274463Sdchagin IncludeGroup[Quoted].end()); 675274463Sdchagin 676274463Sdchagin 677274463Sdchagin bool DontSearchCurDir = false; // TODO: set to true if -I- is set? 678274463Sdchagin Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(), 679274463Sdchagin DontSearchCurDir); 680277611Sjilles 681277611Sjilles // If verbose, print the list of directories that will be searched. 682277611Sjilles if (Verbose) { 683277611Sjilles fprintf(stderr, "#include \"...\" search starts here:\n"); 684277611Sjilles unsigned QuotedIdx = IncludeGroup[Quoted].size(); 685277611Sjilles for (unsigned i = 0, e = SearchList.size(); i != e; ++i) { 686277611Sjilles if (i == QuotedIdx) 687277611Sjilles fprintf(stderr, "#include <...> search starts here:\n"); 688277611Sjilles const char *Name = SearchList[i].getName(); 689277611Sjilles const char *Suffix; 690232449Sjmallett if (SearchList[i].isNormalDir()) 691205014Snwhitehorn Suffix = ""; 692205014Snwhitehorn else if (SearchList[i].isFramework()) 693119332Speter Suffix = " (framework directory)"; 694151360Sps else { 695151360Sps assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup"); 696151360Sps Suffix = " (headermap)"; 697119332Speter } 698183271Sobrien fprintf(stderr, " %s%s\n", Name, Suffix); 699119332Speter } 700226349Smarcel fprintf(stderr, "End of search list.\n"); 701119332Speter } 702125171Speter} 703270692Skib 704119332Spetervoid clang::ApplyHeaderSearchOptions(HeaderSearch &HS, 705119332Speter const HeaderSearchOptions &HSOpts, 706119332Speter const LangOptions &Lang, 707119332Speter const llvm::Triple &Triple) { 708119332Speter InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot); 709119332Speter 710119332Speter // Add the user defined entries. 711119332Speter for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) { 712190622Skib const HeaderSearchOptions::Entry &E = HSOpts.UserEntries[i]; 713119332Speter Init.AddPath(E.Path, E.Group, false, E.IsUserSupplied, E.IsFramework, 714119332Speter false); 715119332Speter } 716119332Speter 717119332Speter // Add entries from CPATH and friends. 718119332Speter Init.AddDelimitedPaths(HSOpts.EnvIncPath.c_str()); 719184184Sjhb if (Lang.CPlusPlus && Lang.ObjC1) 720119332Speter Init.AddDelimitedPaths(HSOpts.ObjCXXEnvIncPath.c_str()); 721154596Sambrisko else if (Lang.CPlusPlus) 722165406Sjkim Init.AddDelimitedPaths(HSOpts.CXXEnvIncPath.c_str()); 723165406Sjkim else if (Lang.ObjC1) 724151358Sps Init.AddDelimitedPaths(HSOpts.ObjCEnvIncPath.c_str()); 725151358Sps else 726151358Sps Init.AddDelimitedPaths(HSOpts.CEnvIncPath.c_str()); 727253531Skib 728253531Skib if (!HSOpts.BuiltinIncludePath.empty()) { 729253531Skib // Ignore the sys root, we *always* look for clang headers relative to 730140481Sps // supplied path. 731253495Skib Init.AddPath(HSOpts.BuiltinIncludePath, System, 732185879Sjhb false, false, false, /*IgnoreSysRoot=*/ true); 733185879Sjhb } 734185879Sjhb 735154587Sambrisko if (HSOpts.UseStandardIncludes) 736147814Sjhb Init.AddDefaultSystemIncludePaths(Lang, Triple); 737147814Sjhb 738140482Sps Init.Realize(); 739220159Skib} 740185879Sjhb