您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (28)

2010-04-15 09:46 423 查看

4.1.1. Finish the setup of search path

GCC looks in several different places for headers. On a normal Unix system, if you do not instruct it otherwise, it will look for headers requested with `#include <FILE>' in:
/usr/local/include
LIBDIR/gcc/TARGET/VERSION/include
/usr/TARGET/include
/usr/include
For C++ programs, it will also look in `/usr/include/g++-v3', first. In the above, TARGET is the canonical name of the system GCC was configured to compile code for; often but not always the same as the canonical name of the system it runs on. VERSION is the version of GCC in use.
You can add to this list with the `-IDIR' command line option. All the directories named by `-I' are searched, in left-to-right order, before the default directories. The only exception is when `dir' is already searched by default. In this case, the option is ignored and the search order for system directories remains unchanged.
Duplicate directories are removed from the quote and bracket search chains before the two chains are merged to make the final search chain. Thus, it is possible for a directory to occur twice in the final search chain if it was specified in both the quote and bracket chains.
You can prevent GCC from searching any of the default directories with the `-nostdinc' option. This is useful when you are compiling an operating system kernel or some other program that does not use the standard C library facilities, or the standard C library itself. `-I' options are not ignored as described above when `-nostdinc' is in effect.
GCC looks for headers requested with `#include "FILE"' first in the directory containing the current file, then in the same places it would have looked for a header requested with angle brackets. For example, if `/usr/include/sys/stat.h' contains `#include "types.h"', GCC looks for `types.h' first in `/usr/include/sys', then in its usual search path.
`#line' does not change GCC's idea of the directory containing the current file.
You may put `-I-' at any point in your list of `-I' options. This has two effects. First, directories appearing before the `-I-' in the list are searched only for headers requested with quote marks. Directories after `-I-' are searched for all headers. Second, the directory containing the current file is not searched for anything, unless it happens to be one of the directories named by an `-I' switch.
`-I. -I-' is not the same as no `-I' options at all, and does not cause the same behavior for `<>' includes that `""' includes get with no special options. `-I.' searches the compiler's current working directory for header files. That may or may not be the same as the directory containing the current file.
If you need to look for headers in a directory named `-', write `-I./-'.
In previous section, we have seen the processing of “–I” options. Now the compiler will finish the setup of the search path. Here, parameter sysroot is the global variable sysroot which is set by option –isysroot to indicate the root of system searching directory. And parameter iprefix is the global variable iprefix which is set by option –iprefix to stand for the prefix of the searching directory.

335 void
336 register_include_chains (cpp_reader *pfile, const char *sysroot, in c-incpath.c
337 const char *iprefix, int stdinc, int cxx_stdinc,
338 int verbose)
339 {
340 static const char *const lang_env_vars[] =
341 { "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH",
342 "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH" };
343 cpp_options *cpp_opts = cpp_get_options (pfile);
344 size_t idx = (cpp_opts->objc ? 2: 0);
345
346 if (cpp_opts->cplusplus)
347 idx++;
348 else
349 cxx_stdinc = false;
350
351 /* CPATH and language-dependent environment variables may add to the
352 include chain. */
353 add_env_var_paths ("CPATH", BRACKET);
354 add_env_var_paths (lang_env_vars[idx], SYSTEM);
355
356 /* Finally chain on the standard directories. */
357 if (stdinc)
358 add_standard_paths (sysroot, iprefix, cxx_stdinc);
359
360 merge_include_chains (pfile, verbose);
361
362 cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET],
363 quote_ignores_source_dir);
364 }

Searching directories can also be added by environment variables, which include CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH and OBJC_INCLUDE_PATH.
Each variable's value is a list of directories separated by a special character, much like `PATH', in which to look for header files. The special character, `PATH_SEPARATOR', is target-dependent and determined at GCC build time. For Microsoft Windows-based targets it is a semicolon, and for almost all other targets it is a colon.
`CPATH' specifies a list of directories to be searched as if specified with `-I', but after any paths given with `-I' options on the command line. This environment variable is used regardless of which language is being preprocessed.
The remaining environment variables apply only when preprocessing the particular language indicated. Each specifies a list of directories to be searched as if specified with `-isystem', but after any paths given with `-isystem' options on the command line.
In all these variables, an empty element instructs the compiler to search its current working directory. Empty elements can appear at the beginning or end of a path. For instance, if the value of `CPATH' is `:/special/include', that has the same effect as `-I. -I/special/include'.
These pathes are added by add_env_var_paths.

90 static void
91 add_env_var_paths (const char *env_var, int chain) in c-incpath.c
92 {
93 char *p, *q, *path;
94
95 GET_ENVIRONMENT (q, env_var);
96
97 if (!q)
98 return;
99
100 for (p = q; *q; p = q + 1)
101 {
102 q = p;
103 while (*q != 0 && *q != PATH_SEPARATOR)
104 q++;
105
106 if (p == q)
107 path = xstrdup (".");
108 else
109 {
110 path = xmalloc (q - p + 1);
111 memcpy (path, p, q - p);
112 path[q - p] = '/0';
113 }
114
115 add_path (path, chain, chain == SYSTEM);
116 }
117 }

Note that stdinc at line 357 in register_include_chains comes from global variable std_inc which gets its value from option –nonstdinc (by default is 1), and cxx_stdinc comes from std_cxx_inc which is set by –nonstdinc++ (by default is 1). Then, if searching for header files in the standard system directories is not prohibited, appends the standard include chain into heads lists by add_standard_paths

120 static void
121 add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc) in c-incpath.c
122 {
123 const struct default_include *p;
124 size_t len;
125
126 if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0)
127 {
128 /* Look for directories that start with the standard prefix.
129 "Translate" them, ie. replace /usr/local/lib/gcc... with
130 IPREFIX and search them first. */
131 for (p = cpp_include_defaults; p->fname; p++)
132 {
133 if (!p->cplusplus || cxx_stdinc)
134 {
135 /* Should we be translating sysrooted dirs too? Assume
136 that iprefix and sysroot are mutually exclusive, for
137 now. */
138 if (sysroot && p->add_sysroot)
139 continue;
140 if (!strncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))
141 {
142 char *str = concat (iprefix, p->fname + len, NULL);
143 add_path (str, SYSTEM, p->cxx_aware);
144 }
145 }
146 }
147 }
148
149 for (p = cpp_include_defaults; p->fname; p++)
150 {
151 if (!p->cplusplus || cxx_stdinc)
152 {
153 char *str;
154
155 /* Should this directory start with the sysroot? */
156 if (sysroot && p->add_sysroot)
157 str = concat (sysroot, p->fname, NULL);
158 else
159 str = update_path (p->fname, p->component);
160
161 add_path (str, SYSTEM, p->cxx_aware);
162 }
163 }
164 }

Structure default_include holds the information of the default list of directories to search for include files. It may be overridden by the various -I and -ixxx options. All these directories are treated as `system' include directories (they are not subject to pedantic warnings in some cases).

35 struct default_include in cppdefault.h
36 {
37 const char *const fname; /* The name of the directory. */
38 const char *const component; /* The component containing the directory
39 (see update_path in prefix.c) */
40 const char cplusplus; /* Only look here if we're compiling C++. */
41 const char cxx_aware; /* Includes in this directory don't need to
42 be wrapped in extern "C" when compiling
43 C++. */
44 const char add_sysroot; /* FNAME should be prefixed by
45 cpp_SYSROOT. */
46 };

On Linux platform, cpp_GCC_INCLUDE_DIR is empty, so cpp_GCC_INCLUDE_DIR_len is 0. For cpp_include_defaults at line 149 above, upon my machine (Linux), it just contains following content. These paths are considered as SYSTEM.

44 const struct default_include cpp_include_defaults[] in cppdefault.c
48 = {
66 { "/localdisk/data/gcc346/include", 0, 0, 1, 0 },
86 { "/include", 0, 0, 0, 1 },
88 { 0, 0, 0, 0, 0 }
89 };

After adding all header file searching paths, it needs merge the four include chains together in the order of quote, bracket, system, after into one chain, during which removes duplicate directories. It is done by merge_include_chains.

247 static void
248 merge_include_chains (cpp_reader *pfile, int verbose) in c-incpath.c
249 {
250 /* Join the SYSTEM and AFTER chains. Remove duplicates in the
251 resulting SYSTEM chain. */
252 if (heads[SYSTEM])
253 tails[SYSTEM]->next = heads[AFTER];
254 else
255 heads[SYSTEM] = heads[AFTER];
256 heads[SYSTEM] = remove_duplicates (pfile, heads[SYSTEM], 0, 0, verbose);
257
258 /* Remove duplicates from BRACKET that are in itself or SYSTEM, and
259 join it to SYSTEM. */
260 heads[BRACKET] = remove_duplicates (pfile, heads[BRACKET], heads[SYSTEM],
261 heads[SYSTEM], verbose);
262
263 /* Remove duplicates from QUOTE that are in itself or SYSTEM, and
264 join it to BRACKET. */
265 heads[QUOTE] = remove_duplicates (pfile, heads[QUOTE], heads[SYSTEM],
266 heads[BRACKET], verbose);
267
268 /* If verbose, print the list of dirs to search. */
269 if (verbose)
270 {
271 struct cpp_dir *p;
272
273 fprintf (stderr, _("#include /".../" search starts here:/n"));
274 for (p = heads[QUOTE];; p = p->next)
275 {
276 if (p == heads[BRACKET])
277 fprintf (stderr, _("#include <...> search starts here:/n"));
278 if (!p)
279 break;
280 fprintf (stderr, " %s/n", p->name);
281 }
282 fprintf (stderr, _("End of search list./n"));
283 }
284 }

In remove_duplicates, for each duplicate path in chain head, keep just the first one. Remove each path in chain head that also exists in chain system. Set the next pointer of the last path in the resulting chain to join, unless it duplicates join in which case the last path is removed (for the case, the node next to the last becomes the last, and repeating the step till no duplicate node in join is found, so concatenates head and join). This shows that in head and join chain, duplicate path can present unless join is system.

172 static struct cpp_dir *
173 remove_duplicates (cpp_reader *pfile, struct cpp_dir *head, in c-incpath.c
174 struct cpp_dir *system, struct cpp_dir *join,
175 int verbose)
176 {
177 struct cpp_dir **pcur, *tmp, *cur;
178 struct stat st;
179
180 for (pcur = &head; *pcur; )
181 {
182 int reason = REASON_QUIET;
183
184 cur = *pcur;
185
186 if (stat (cur->name, &st))
187 {
188 /* Dirs that don't exist are silently ignored, unless verbose. */
189 if (errno != ENOENT)
190 cpp_errno (pfile, CPP_DL_ERROR, cur->name);
191 else
192 reason = REASON_NOENT;
193 }
194 else if (!S_ISDIR (st.st_mode))
195 cpp_error_with_line (pfile, CPP_DL_ERROR, 0, 0,
196 "%s: not a directory", cur->name);
197 else
198 {
199 INO_T_COPY (cur->ino, st.st_ino);
200 cur->dev = st.st_dev;
201
202 /* Remove this one if it is in the system chain. */
203 reason = REASON_DUP_SYS;
204 for (tmp = system; tmp; tmp = tmp->next)
205 if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev)
206 break;
207
208 if (!tmp)
209 {
210 /* Duplicate of something earlier in the same chain? */
211 reason = REASON_DUP;
212 for (tmp = head; tmp != cur; tmp = tmp->next)
213 if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev)
214 break;
215
216 if (tmp == cur
217 /* Last in the chain and duplicate of JOIN? */
218 && !(cur->next == NULL && join
219 && INO_T_EQ (cur->ino, join->ino)
220 && cur->dev == join->dev))
221 {
222 /* Unique, so keep this directory. */
223 pcur = &cur->next;
224 continue;
225 }
226 }
227 }
228
229 /* Remove this entry from the chain. */
230 *pcur = cur->next;
231 free_path (cur, verbose ? reason: REASON_QUIET);
232 }
233
234 *pcur = join;
235 return head;
236 }

In register_include_chains, after executing merge_include_chains, now searching sequence of header files is set as quote, bracket, system, then after. Notice that below, parameters quote refers to include path of quote header files, bracket refers to include path of bracket header files. Then cpp_set_include_chains sets parse_in – object of parser, accordingly.

1083 void
1084 cpp_set_include_chains (cpp_reader *pfile, cpp_dir *quote, in cppfiles.c
1085 cpp_dir *bracket, int quote_ignores_source_dir)
1086 {
1087 pfile->quote_include = quote;
1088 pfile->bracket_include = quote;
1089 pfile->quote_ignores_source_dir = quote_ignores_source_dir;
1090
1091 for (; quote; quote = quote->next)
1092 {
1093 quote->name_map = NULL;
1094 quote->len = strlen (quote->name);
1095 if (quote == bracket)
1096 pfile->bracket_include = bracket;
1097 }
1098 }

See that only using –I- switch, can appear nonempty quote chain (refer to split_quote_chain, and description of -I-). Otherwise, in parser object, quote_include and bracket_include are same.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: