[comp.lang.c] source for included included files

mveao@cbnews.ATT.COM (eric.a.olson) (08/30/89)

    
    I have a file that needs to include 30 or so other files.
    The original author wrote it to include "all.h" where
    "all.h" includes the other 30 files.

    I am trying to compile it in a Viewpath environment with nmake.
    The preprocessor seems to want to look for the second-level
    included files in the same directory where the "all.h" file 
    was found.  A local copy of a second-level .h file is totally 
    ignored unless "all.h" is in the first view.

    Is this normal behavior?

scs@hstbme.mit.edu (Steve Summit) (09/09/89)

In article <9275@cbnews.ATT.COM> mveao@cbnews.ATT.COM (eric.a.olson) writes:
>    I have a file that needs to include 30 or so other files.
>    The original author wrote it to include "all.h" where
>    "all.h" includes the other 30 files.
>    The preprocessor seems to want to look for the second-level
>    included files in the same directory where the "all.h" file 
>    was found.  A local copy of a second-level .h file is totally 
>    ignored unless "all.h" is in the first view.
>    Is this normal behavior?

Yes.  It is a not-universally-known and possibly surprising fact
that #include with double quotes searches in the directory of the
file doing the #including, not (necessarily) in the current
directory from which the compiler was invoked.

I am currently working on a large project, various versions of
which are compiled in different directories, referencing source
files in one master directory.  So that I can "tune" the builds
with special header files in the various build directories, I
occasionally use angle brackets instead of double quotes:

	#include <tunable.h>	/* <> so copy in directory other than that */
				/* of source file can be selected with -I */

The CFLAGS macro in my Makefile then always contains -I.  (The
trick applies only to a handful of header files for which I wish
multiple versions to exist; most project-related header files are
kept in the master source directory, and #included with double
quotes, making the default behavior for double quote searching
useful and correct.  In fact, that's probably why the behavior
was designed that way.)

The rules for #include file searching can seem capricious at
first, but it's surprising how many useful effects you can
achieve by using them knowingly.

Note that the search behavior is quite implementation-defined.
I have described the Unix behavior; other systems generally try
to emulate it, with varying degrees of success.  The ANSI
standard says, according to K&R II (sec. A12.4), that "a control
line of the form

	#include "filename"

searches first in association with the original source file (a
deliberately implementation-dependent phrase)" and then in
whatever other places that #include <filename> would search.
The pANS does not require that there be the notion of a
directory, nor probably that there be the notion of a "source
file."
                                      Steve Summit

henry@utzoo.uucp (Henry Spencer) (09/10/89)

In article <14172@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>... It is a not-universally-known and possibly surprising fact
>that #include with double quotes searches in the directory of the
>file doing the #including, not (necessarily) in the current
>directory from which the compiler was invoked.

One reason why it isn't universally known is that it's not universally true.

>... The ANSI
>standard says, according to K&R II (sec. A12.4), that "a control
>line of the form
>
>	#include "filename"
>
>searches first in association with the original source file (a
>deliberately implementation-dependent phrase)" ...

Beware, this is one respect in which K&R2 is outdated.  The Oct 88 draft,
more or less definitive, just says "searches in an implementation-defined
manner".  This is an area where implementations differ, partly because
the two major oracles -- K&R1 and the Unix cpp -- disagree.
-- 
V7 /bin/mail source: 554 lines.|     Henry Spencer at U of Toronto Zoology
1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

tneff@bfmny0.UU.NET (Tom Neff) (09/10/89)

I have regularly been inconvenienced by various vendors' #include search
logic.  (Maybe "logic" is too strong a word. :-) )  Most recently I
slapped together a "temp compile" script for use under a client's "vi".
(No mail about EMACS please; I know, I know!)  I wrote the current file
to something in /tmp and ran that through "cc -S".  Boom, quoted
includes blew up.  Fortunately the -I switch in SV3.2 cc handles "x.h"
and not just <x.h> so that circumvented the problem in most cases; but
editing a file in another directory was tougher.

I think it was kind of stupid not to suggest some rules about what a
compiler should do IF directories exist in the host environment.  Even
where they don't, there's often a comparable concept (floppy drives,
account #s, volumes etc).  Real authors distributing real software have
to deal with junk like this.  Guidelines would be nice.
-- 
Annex Canada now!  We need the room,	\)	Tom Neff
    and who's going to stop us.		(\	tneff@bfmny0.UU.NET

henry@utzoo.uucp (Henry Spencer) (09/10/89)

In article <14647@bfmny0.UU.NET> tneff@bfmny0.UU.NET (Tom Neff) writes:
>I think it was kind of stupid not to suggest some rules about what a
>compiler should do IF directories exist in the host environment...

As I recall (I'm at home and my X3J11 stuff is at work), the Rationale
in fact comes right out and says that X3J11 hopes everyone will use
K&R1 search rules.
-- 
V7 /bin/mail source: 554 lines.|     Henry Spencer at U of Toronto Zoology
1989 X.400 specs: 2200+ pages. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

penneyj@servio.UUCP (D. Jason Penney) (09/11/89)

In article <14172@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes:
>
>Yes.  It is a not-universally-known and possibly surprising fact
>that #include with double quotes searches in the directory of the
>file doing the #including, not (necessarily) in the current
>directory from which the compiler was invoked.
>

We also have a large programming project written in C.  One objective in
the design of our programming methodology was to allow a programmer to
check out any set of source files (including .h files) and then do a
"local make", building a variant of the system against standard source
in the "product directory".

For instance, one person may wish to make substantial changes to the
compiler subsystem while another person may be testing user interfaces.
Clearly the first person doesn't want to test with a broken interface and
the second doesn't need a broken compiler.

If we have the following include layout:

/**************************/
/* a.h */
typedef long OopType;
/**************************/
/* b.h */
#include "a.h"
OopType aGlobalVar;
/**************************/
/* x.c */
#include "b.h"
aGlobalVar = 10;
/**************************/

and then, if the user checks out b.h into his local directory and then
compiles x.c in the product directory, the WRONG version of b.h will be
included in the resulting compilation!

Our programming methodology takes Steve Summit's approach one step further:
we NEVER use includes with double-quotes.  We ALWAYS use angle-bracket
includes and specify the search path appropriately in the compile step.

Some veteran C programmers have been astonished by this, but I think this
is yet again another example where "programming in the large" requires a
different approach than programming in the small.

So here is a philosophical question, to which I would appreciate REPLIES
and not FOLLOWUPs:  what is the use of double-quote includes?  I have
followed corporate programming style in my own small programs, and I have
yet seen a situation where the double-quote includes were strictly necessary.
-- 
D. Jason Penney                  Ph: (503) 629-8383
Beaverton, OR 97006              uucp: ...uunet!servio!penneyj
STANDARD DISCLAIMER:  Should I or my opinions be caught or killed, the
company will disavow any knowledge of my actions...

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/13/89)

In article <249@servio.UUCP> penneyj@servio.UUCP (D. Jason Penney) writes:
>So here is a philosophical question, to which I would appreciate REPLIES
>and not FOLLOWUPs:  what is the use of double-quote includes?

Since this information is probably of general interest, I'm posting it:
#include <stuff> officially obtains definitions from the implementation,
while #include "stuff" officially gets them from source files (header
files) provided with the program.  <stuff> can actually be built into
the compiler, for example, and in general may not be something you can
conveniently add to.  There is no C-language requirement for anything
like the UNIX "cc -Iwherever" facility.