InitHeaderSearch.cpp revision 0b9e736308af5397f558ffc8e780c438c2fdb563
1//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===//
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// This file implements the InitHeaderSearch class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Driver/InitHeaderSearch.h"
15#include "clang/Lex/HeaderSearch.h"
16#include "clang/Basic/FileManager.h"
17#include "clang/Basic/LangOptions.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/SmallPtrSet.h"
20#include "llvm/System/Path.h"
21#include "llvm/Config/config.h"
22#include <vector>
23
24using namespace clang;
25
26void InitHeaderSearch::AddPath(const std::string &Path, IncludeDirGroup Group,
27                               bool isCXXAware, bool isUserSupplied,
28                               bool isFramework) {
29  assert(!Path.empty() && "can't handle empty path here");
30  FileManager &FM = Headers.getFileMgr();
31
32  // Compute the actual path, taking into consideration -isysroot.
33  llvm::SmallString<256> MappedPath;
34
35  // Handle isysroot.
36  if (Group == System) {
37    // FIXME: Portability.  This should be a sys::Path interface, this doesn't
38    // handle things like C:\ right, nor win32 \\network\device\blah.
39    if (isysroot.size() != 1 || isysroot[0] != '/') // Add isysroot if present.
40      MappedPath.append(isysroot.begin(), isysroot.end());
41  }
42
43  MappedPath.append(Path.begin(), Path.end());
44
45  // Compute the DirectoryLookup type.
46  SrcMgr::Characteristic_t Type;
47  if (Group == Quoted || Group == Angled)
48    Type = SrcMgr::C_User;
49  else if (isCXXAware)
50    Type = SrcMgr::C_System;
51  else
52    Type = SrcMgr::C_ExternCSystem;
53
54
55  // If the directory exists, add it.
56  if (const DirectoryEntry *DE = FM.getDirectory(&MappedPath[0],
57                                                 &MappedPath[0]+
58                                                 MappedPath.size())) {
59    IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
60                                                  isFramework));
61    return;
62  }
63
64  // Check to see if this is an apple-style headermap (which are not allowed to
65  // be frameworks).
66  if (!isFramework) {
67    if (const FileEntry *FE = FM.getFile(&MappedPath[0],
68                                         &MappedPath[0]+MappedPath.size())) {
69      if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
70        // It is a headermap, add it to the search path.
71        IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
72        return;
73      }
74    }
75  }
76
77  if (Verbose)
78    fprintf(stderr, "ignoring nonexistent directory \"%s\"\n", Path.c_str());
79}
80
81
82void InitHeaderSearch::AddEnvVarPaths(const char *Name) {
83  const char* at = getenv(Name);
84  if (!at)
85    return;
86
87  const char* delim = strchr(at, llvm::sys::PathSeparator);
88  while (delim != 0) {
89    if (delim-at == 0)
90      AddPath(".", Angled, false, true, false);
91    else
92      AddPath(std::string(at, std::string::size_type(delim-at)), Angled, false,
93              true, false);
94    at = delim + 1;
95    delim = strchr(at, llvm::sys::PathSeparator);
96  }
97  if (*at == 0)
98    AddPath(".", Angled, false, true, false);
99  else
100    AddPath(at, Angled, false, true, false);
101}
102
103
104void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) {
105  // FIXME: temporary hack: hard-coded paths.
106  // FIXME: get these from the target?
107
108#ifdef LLVM_ON_WIN32
109  if (Lang.CPlusPlus) {
110    // Mingw32 GCC version 4
111    AddPath("c:/mingw/lib/gcc/mingw32/4.3.0/include/c++", System, true, false, false);
112    AddPath("c:/mingw/lib/gcc/mingw32/4.3.0/include/c++/mingw32", System, true, false, false);
113    AddPath("c:/mingw/lib/gcc/mingw32/4.3.0/include/c++/backward", System, true, false, false);
114  }
115
116  // Mingw32 GCC version 4
117  AddPath("C:/mingw/lib/gcc/mingw32/4.3.0/include", System, false, false, false);
118  AddPath("C:/mingw/include", System, false, false, false);
119#else
120
121  if (Lang.CPlusPlus) {
122    AddPath("/usr/include/c++/4.2.1", System, true, false, false);
123    AddPath("/usr/include/c++/4.2.1/i686-apple-darwin10", System, true, false,
124        false);
125    AddPath("/usr/include/c++/4.2.1/backward", System, true, false, false);
126
127    AddPath("/usr/include/c++/4.0.0", System, true, false, false);
128    AddPath("/usr/include/c++/4.0.0/i686-apple-darwin8", System, true, false,
129        false);
130    AddPath("/usr/include/c++/4.0.0/backward", System, true, false, false);
131
132    // Ubuntu 7.10 - Gutsy Gibbon
133    AddPath("/usr/include/c++/4.1.3", System, true, false, false);
134    AddPath("/usr/include/c++/4.1.3/i486-linux-gnu", System, true, false,
135        false);
136    AddPath("/usr/include/c++/4.1.3/backward", System, true, false, false);
137
138    // Fedora 8
139    AddPath("/usr/include/c++/4.1.2", System, true, false, false);
140    AddPath("/usr/include/c++/4.1.2/i386-redhat-linux", System, true, false,
141        false);
142    AddPath("/usr/include/c++/4.1.2/backward", System, true, false, false);
143
144    // Fedora 9
145    AddPath("/usr/include/c++/4.3.0", System, true, false, false);
146    AddPath("/usr/include/c++/4.3.0/i386-redhat-linux", System, true, false,
147        false);
148    AddPath("/usr/include/c++/4.3.0/backward", System, true, false, false);
149
150    // Arch Linux 2008-06-24
151    AddPath("/usr/include/c++/4.3.1", System, true, false, false);
152    AddPath("/usr/include/c++/4.3.1/i686-pc-linux-gnu", System, true, false,
153        false);
154    AddPath("/usr/include/c++/4.3.1/backward", System, true, false, false);
155    AddPath("/usr/include/c++/4.3.1/x86_64-unknown-linux-gnu", System, true,
156        false, false);
157
158    // DragonFly
159    AddPath("/usr/include/c++/4.1", System, true, false, false);
160  }
161
162  AddPath("/usr/local/include", System, false, false, false);
163
164  AddPath("/usr/lib/gcc/i686-apple-darwin10/4.2.1/include", System,
165      false, false, false);
166  AddPath("/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/include",
167      System, false, false, false);
168
169  // leopard
170  AddPath("/usr/lib/gcc/i686-apple-darwin9/4.0.1/include", System,
171      false, false, false);
172  AddPath("/usr/lib/gcc/powerpc-apple-darwin9/4.0.1/include",
173      System, false, false, false);
174  AddPath("/usr/lib/gcc/powerpc-apple-darwin9/"
175      "4.0.1/../../../../powerpc-apple-darwin0/include",
176      System, false, false, false);
177
178  // tiger
179  AddPath("/usr/lib/gcc/i686-apple-darwin8/4.0.1/include", System,
180      false, false, false);
181  AddPath("/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/include",
182      System, false, false, false);
183  AddPath("/usr/lib/gcc/powerpc-apple-darwin8/"
184      "4.0.1/../../../../powerpc-apple-darwin8/include",
185      System, false, false, false);
186
187  // Ubuntu 7.10 - Gutsy Gibbon
188  AddPath("/usr/lib/gcc/i486-linux-gnu/4.1.3/include", System,
189      false, false, false);
190
191  // Fedora 8
192  AddPath("/usr/lib/gcc/i386-redhat-linux/4.1.2/include", System,
193      false, false, false);
194
195  // Fedora 9
196  AddPath("/usr/lib/gcc/i386-redhat-linux/4.3.0/include", System,
197      false, false, false);
198
199  //Debian testing/lenny x86
200  AddPath("/usr/lib/gcc/i486-linux-gnu/4.2.3/include", System,
201      false, false, false);
202
203  //Debian testing/lenny amd64
204  AddPath("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include", System,
205      false, false, false);
206
207  // Arch Linux 2008-06-24
208  AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.1/include", System,
209      false, false, false);
210  AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.3.1/include-fixed", System,
211      false, false, false);
212  AddPath("/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include", System,
213      false, false, false);
214  AddPath("/usr/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/include-fixed",
215      System, false, false, false);
216
217  // Debian testing/lenny ppc32
218  AddPath("/usr/lib/gcc/powerpc-linux-gnu/4.2.3/include", System,
219      false, false, false);
220
221  // Gentoo x86 stable
222  AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include", System,
223      false, false, false);
224
225  // DragonFly
226  AddPath("/usr/libdata/gcc41", System, true, false, false);
227
228  AddPath("/usr/include", System, false, false, false);
229  AddPath("/System/Library/Frameworks", System, true, false, true);
230  AddPath("/Library/Frameworks", System, true, false, true);
231
232#endif
233}
234
235void InitHeaderSearch::AddDefaultEnvVarPaths(const LangOptions &Lang) {
236  AddEnvVarPaths("CPATH");
237  if (Lang.CPlusPlus && Lang.ObjC1)
238    AddEnvVarPaths("OBJCPLUS_INCLUDE_PATH");
239  else if (Lang.CPlusPlus)
240    AddEnvVarPaths("CPLUS_INCLUDE_PATH");
241  else if (Lang.ObjC1)
242    AddEnvVarPaths("OBJC_INCLUDE_PATH");
243  else
244    AddEnvVarPaths("C_INCLUDE_PATH");
245}
246
247
248/// RemoveDuplicates - If there are duplicate directory entries in the specified
249/// search list, remove the later (dead) ones.
250static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
251                             bool Verbose) {
252  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
253  llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
254  llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
255  for (unsigned i = 0; i != SearchList.size(); ++i) {
256    unsigned DirToRemove = i;
257
258    if (SearchList[i].isNormalDir()) {
259      // If this isn't the first time we've seen this dir, remove it.
260      if (SeenDirs.insert(SearchList[i].getDir()))
261        continue;
262
263      // If we have a normal #include dir that is shadowed later in the chain
264      // by a system include dir, we actually want to ignore the user's request
265      // and drop the user dir... keeping the system dir.  This is weird, but
266      // required to emulate GCC's search path correctly.
267      //
268      // Since dupes of system dirs are rare, just rescan to find the original
269      // that we're nuking instead of using a DenseMap.
270      if (SearchList[i].getDirCharacteristic() != SrcMgr::C_User) {
271        // Find the dir that this is the same of.
272        unsigned FirstDir;
273        for (FirstDir = 0; ; ++FirstDir) {
274          assert(FirstDir != i && "Didn't find dupe?");
275          if (SearchList[FirstDir].getDir() == SearchList[i].getDir())
276            break;
277        }
278
279        // If the first dir in the search path is a non-system dir, zap it
280        // instead of the system one.
281        if (SearchList[FirstDir].getDirCharacteristic() == SrcMgr::C_User)
282          DirToRemove = FirstDir;
283      }
284
285      if (Verbose) {
286        fprintf(stderr, "ignoring duplicate directory \"%s\"\n",
287                SearchList[i].getDir()->getName());
288        if (DirToRemove != i)
289          fprintf(stderr, "  as it is a non-system directory that duplicates"
290                  " a system directory\n");
291      }
292    } else if (SearchList[i].isFramework()) {
293      // If this isn't the first time we've seen this framework dir, remove it.
294      if (SeenFrameworkDirs.insert(SearchList[i].getFrameworkDir()))
295        continue;
296
297      if (Verbose)
298        fprintf(stderr, "ignoring duplicate framework \"%s\"\n",
299                SearchList[i].getFrameworkDir()->getName());
300
301    } else {
302      assert(SearchList[i].isHeaderMap() && "Not a headermap or normal dir?");
303      // If this isn't the first time we've seen this headermap, remove it.
304      if (SeenHeaderMaps.insert(SearchList[i].getHeaderMap()))
305        continue;
306
307      if (Verbose)
308        fprintf(stderr, "ignoring duplicate directory \"%s\"\n",
309                SearchList[i].getDir()->getName());
310    }
311
312    // This is reached if the current entry is a duplicate.  Remove the
313    // DirToRemove (usually the current dir).
314    SearchList.erase(SearchList.begin()+DirToRemove);
315    --i;
316  }
317}
318
319
320void InitHeaderSearch::Realize() {
321  // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList.
322  std::vector<DirectoryLookup> SearchList;
323  SearchList = IncludeGroup[Angled];
324  SearchList.insert(SearchList.end(), IncludeGroup[System].begin(),
325                    IncludeGroup[System].end());
326  SearchList.insert(SearchList.end(), IncludeGroup[After].begin(),
327                    IncludeGroup[After].end());
328  RemoveDuplicates(SearchList, Verbose);
329  RemoveDuplicates(IncludeGroup[Quoted], Verbose);
330
331  // Prepend QUOTED list on the search list.
332  SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(),
333                    IncludeGroup[Quoted].end());
334
335
336  bool DontSearchCurDir = false;  // TODO: set to true if -I- is set?
337  Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(),
338                         DontSearchCurDir);
339
340  // If verbose, print the list of directories that will be searched.
341  if (Verbose) {
342    fprintf(stderr, "#include \"...\" search starts here:\n");
343    unsigned QuotedIdx = IncludeGroup[Quoted].size();
344    for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
345      if (i == QuotedIdx)
346        fprintf(stderr, "#include <...> search starts here:\n");
347      const char *Name = SearchList[i].getName();
348      const char *Suffix;
349      if (SearchList[i].isNormalDir())
350        Suffix = "";
351      else if (SearchList[i].isFramework())
352        Suffix = " (framework directory)";
353      else {
354        assert(SearchList[i].isHeaderMap() && "Unknown DirectoryLookup");
355        Suffix = " (headermap)";
356      }
357      fprintf(stderr, " %s%s\n", Name, Suffix);
358    }
359    fprintf(stderr, "End of search list.\n");
360  }
361}
362
363