Alcatel-Lucent nmake C Preprocessor:
The -I- and prefixinclude Features
Popular C and C++ compilers interpret the quoted include directive
(#include "path") to mean that the specified path should be searched
first in the directory of the including file. If not found there,
these files are next searched as if they were included using
the angle bracketed include directive (#include <...>).
Typically, compilers interpret ``directory of the including file'' to mean
either or both of the directory of the file containing the #include, and the
directory of the top level (primary) source file. Note that this
interpretation of the quoted include directive is not specified in the
C standard, that standard only states that quoted include files are to
be searched for in an ``implementation-defined manner.'' (ISO/IEC
9899-1990(E) 6.8.2)
In a viewpathing
situation, searching only in the directory of the
including file is no longer sufficient, because the including file may
be in a viewpath node that is ``up the viewpath''; according to
viewpathing semantics, a file in this directory may be overridden by a
file in the corresponding directory in a ``closer'' viewpath node.
-I- and prefixinclude generalize the concept of ``directory of
including file'' to support viewpathing.
For example, say a
viewpath
of ``node1:node2'' is being used.
With this, files in node1 have precedence over files in node2.
Files in node1 should be used when they exist, otherwise the file
will be picked up from node2. If a source file, a.c, is
in node2, and an included file, a.h(node2), is in
the same directory, and a newer a.h(node1) exists in
node1, then the compiler will include a.h(node2)
and ignore the newer a.h(node1), thus violating the
viewpath. This can also occur when a header file includes another header
file.
Effectively, the -I- option replaces the single ``directory of the
including file'' with a series of directories, which are specified
using -I options appearing before the the -I- option on
the compiler command line. We will call this directory sequence ``the local
include search path.'' Instead of looking only in the ``directory of
the including file'' for files specified using the #include "..."
directive, the -I- option specifies that the compiler should search
the local include search path. The -I- search scheme is sufficient
to handle the case where the ``directory of the including file'' is
directly on the search path specified by the -I options.
There may be no more than one -I- flag on the command line.
To summarize, the -I- flag does the following:
- Turns on an alternate include file search algorithm.
For #include "..." files, the directory of the including
file is not searched first. The search for include files strictly
follows the -I command line flags, then the default standard
include directories.
- Defines different search paths for quoted and bracketed files.
#include "..." files are searched for in all -I
directories (before and after -I-).
#include <...> files are
searched for in the -I directories following
-I- on the command line.
The standard include directories are always searched last for both
include file forms.
Example:
$ cc -I. -I/bld/src/myproj -I../../include -I/bld/include -I../inclu
de -I/bld/src/include -I- -I/opt/A/include -I/opt/B/include -c main.c
- Search for #include "..." files:
- .
- /bld/src/myproj
- ../../include
- /bld/include
- ../include
- /bld/src/include
- /opt/A/include
- /opt/B/include
- standard include directories
- Search for #include <...> files:
- /opt/A/include
- /opt/B/include
- standard include directories
The -I- option is not sufficient to handle the case involving a
quoted include from a parent file which is not directly on the quoted or
bracketed search paths. prefixinclude provides additional support for
the case where, due to use of directory prefixes in #include
directives in parent including files, the ``directory of the including
file'' is no longer directly on the include search list. In the non
-I- case, use of directory prefixes in parent #include directives
causes the compiler to look in some directory offset from the
directory of the top-level source file. Analogously, in the -I-
case, use of directory prefixes in parent include files in effect define an
offset relative to the directories on the search list. This is
equivalent to explicitly specifying the directory prefix explicitly in
the child #include "..." directive. In fact, modifying the source
#include directive in this way would allow the intended included file
to be found without requiring prefixinclude support in the
preprocessor.
Here's an example of the problem:
$ ls -l
total 16
-rw-r--r-- 1 fjb1 fjb1 20 Jul 26 08:08 a.c
drwxr-xr-x 2 fjb1 fjb1 4096 Jul 26 06:33 incl
-rwxr-xr-x 1 fjb1 fjb1 241 Jul 26 2000 mk
$ ls -l incl
total 0
-rw-r--r-- 1 fjb1 fjb1 35 Jul 26 06:44 f.h
-rw-r--r-- 1 fjb1 fjb1 7 Jul 26 06:24 x.h
-rw-r--r-- 1 fjb1 fjb1 7 Jul 26 06:32 y.h
$ cat a.c
#include "incl/f.h"
$ cat incl/f.h
#include "incl/y.h"
#include "x.h"
$ cat incl/x.h
int x;
$ cat incl/y.h
int y;
$ CC -c -I. a.c
$ CC -c -I. -I- -I. a.c
"./incl/f.h", line 2: Error: Could not open include file "x.h".
1 Error(s) detected.
See that a.c compiles fine with `-I.' but
with `-I. -I- -I.' it fails to find x.h.
With the prefixinclude feature in effect, the subdirectory prefix is inherited
from the including file for #include "..." style includes. So, if an
including file was included as "prefix/includer"
or <prefix/includer> then a file "includee" included by
"prefix/includer" is first searched for using
"prefix/includee", and, if that fails, is next searched for
using "includee".
Note that adding additional -I options for each sub include directory
is not correct, since include files having the same name may appear in
different subdirectories of the include search path. The
prefixinclude approach provides the correct behavior by maintaining
the association between the file name being searched and the offset of
the parent directory from the include search path.
Consider the case where there are 2 include directories, say incl1/
and incl2/. A top-level file a.c includes files in both
of these subdirectories, say incl1/f1.h and incl2/f2.h.
Suppose incl1/f1.h includes a file "x.h", and
incl2/f2.h also includes a file "x.h". By
normal C include semantics, we want incl1/f1.h to pick up
incl1/x.h, and incl2/f2.h to pick up incl2/x.h.
There is no sequence of -I options that will cause
incl1/f1.h to always pick up incl1/x.h, and
incl2/f2.h to always pick up incl2/x.h. If we say
``-Iincl1 -Iincl2'', then both incl1/f1.h and
incl2/f2.h would end up getting incl1/x.h, not what we want.
The prefixinclude feature takes care of this by inheriting the directory
prefix from the parent. When processing incl1/f1.h the include
of "x.h" causes a search for "incl1/x.h", and if that
fails then a search for "x.h". Likewise, when processing
incl2/f2.h the search is for "incl2/x.h", and if that
fails, then "x.h".
Searches for #include <...> files are not affected by
prefixinclude, only #include "..." file searches are enhanced.
Example:
Contents of main.c:
#include "incl/f1.h"
Contents of incl/f1.h:
#include "x.h"
Compile command line:
$ cc -I../include -I/bld/ofc/include -I- -I/opt/pkgs/include -c main.c
Searching for x.h:
- First search for x.h in the following order:
- ../include/incl/x.h
- /bld/ofc/include/incl/x.h
- /opt/pkgs/include/incl/x.h
- /usr/include/incl/x.h (standard include directories)
- If x.h is not found, then search for the following:
- ../include/x.h
- /bld/ofc/include/x.h
- /opt/pkgs/include/x.h
- /usr/include/x.h (standard include directories)
<<cpp index
Last Update: Wednesday,20-Dec-06 13:22:03 CST
|