Topic: Header file inclusion and multiple directories


Author: John Max Skaller <maxtal@suphys.physics.su.oz.au>
Date: 1995/11/08
Raw View
matt@cyclops5.berkeley.edu (Matt Austern) wrote:
>
>Consider a project that spans several directories.

[directory lookup problems]

>So my challenge: can anyone think of an acceptable replacement for
>"The named source file is searched for in an implementation-defined
>manner" that would provide a bit more of a guarantee of reasonable
>behavior?

Yes. GET RID OF #include ALTOGETHER. <grin>

The way to do this is to have a system
where you can "use" modules in the source code.

To _find_ the modules, an implementation specific
control file, menu, or whatever is used: I'd
start with a file of pairs (module name, filename)
plus some defaults and autosearch instructions.

The point is that editing this control file
is INDEPENDENT of the code source files.
So it means the source code does NOT
have to be edited when files are moved around
(including on the developers system)

For a given (working) project, one can produce a list
of all the modules and their files -- which
aids in porting the project (How do you know
you shipped ALL the source files needed??)

--
John Max Skaller               voice: 61-2-566-2189
81 Glebe Point Rd              fax:   61-2-660-0850
GLEBE NSW 2037                 email: maxtal@suphys.physics.oz.au
AUSTRALIA                      email: skaller@maxtal.com.au
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: John Max Skaller <maxtal@suphys.physics.su.oz.au>
Date: 1995/11/08
Raw View
matt@cyclops5.berkeley.edu (Matt Austern) wrote:
>
>Consider a project that spans several directories.

>So my challenge: can anyone think of an acceptable replacement for
>"The named source file is searched for in an implementation-defined
>manner" that would provide a bit more of a guarantee of reasonable
>behavior?

A second answer to this question:

// filelist.h
#define MYFILE "myfile.h"
#define YOURFILE "../yourfile.h"
#define HISFILE "/root/lib/include/system/project/hisfile.hpp"

// main.cc
#include "filelist.h" // current directory!
#include MYFILE       // wherever they live
#include YOURFILE
#include HISFILE
#include HERFILE
main() { ..}

This minimises the changes required to the
file "filelist.h", and imposes only the
requirement that IT be found by

#include "filelist.h"

Its contents may need to be edited when moving things,
which is a pain, but at least it is a localised pain.

--
John Max Skaller               voice: 61-2-566-2189
81 Glebe Point Rd              fax:   61-2-660-0850
GLEBE NSW 2037                 email: maxtal@suphys.physics.oz.au
AUSTRALIA                      email: skaller@maxtal.com.au
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/11/09
Raw View
John Max Skaller <maxtal@suphys.physics.su.oz.au> writes:

>matt@cyclops5.berkeley.edu (Matt Austern) wrote:
>>
>>So my challenge: can anyone think of an acceptable replacement for
>>"The named source file is searched for in an implementation-defined
>>manner" that would provide a bit more of a guarantee of reasonable
>>behavior?
>
>Yes. GET RID OF #include ALTOGETHER. <grin>
>
>The way to do this is to have a system
>where you can "use" modules in the source code.
>
>To _find_ the modules, an implementation specific
>control file, menu, or whatever is used: I'd
>start with a file of pairs (module name, filename)
>plus some defaults and autosearch instructions.

I agree that separating module names from file names is a good idea,
but -- as recent discussion on comp.lang.ada indicates -- if you leave
the mapping as implementation specific, different implementations will
adopt different conventions, and so while you will have just simplified
the problem, you won't have solved it.

--
Fergus Henderson              WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au               PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Dick Menninger <Dick.Menninger@daytonoh.attgis.com>
Date: 1995/11/10
Raw View
I tried to reply to this back before my server removed
its head from the sand so this is out of sequence (and
not precisely what I said then, anyway).  It was not
completely clear whether or not the experiments insured
that no "project definition" supplied the places to look
and whether they were always searched in a given order.

The language distinguishes between <...> and "..."
header file specification.  Now a compiler could provide
a means of specifying a search path for <...> and another
one for "..." that would precede the other path.
However, to do that with full flexibility a compiler would
need to provide a means of refering to the including
file's directory and to the original source file's directory
and to all of the intermediate directories (a deep nest
of includes).

How you want to control source and override files with
more "local" copies varies greatly among environments
and projects and even stages within a project.  I have
used many variants on this and have seen even more.
Answering all needs is hard.

But you seemed to want a method that was internal
to the source file (rather than involving compiler options).
The issue was whether and when you searched the
local directories of the files in the current include stack.
Since the include is a preprocessing directive, such a
solution would have to be a preprocessing directive.
In the time since my original post went to oblivion,
some people have suggested various tricky macro
mechanisms.  Those were both somewhat obscure
and somewhat inadequate.  If you did this, each
header would want a say that lasted while it was
on the include stack.  But should it permanently
change the search path or have its opinion disappear
with it off the include stack?  Whatever the method,
it needs to be much easier to understand at a glance
than some of those macros were if you expect any
large project to use the approach.

I can conceive of some preprocessing directives
that could be added to provide some control of
the search paths.  But how do you override specific
system (<...>) files that must be included only at
their appropriate place in the include stack processing?

The more I look at this, the more it it seems to
have the visage of a can of worms.  Are you sure
you want to open it?

Good Day
Dick
Dick.Menninger@DaytonOH.ATTGIS.COM
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: matt@cyclops5.berkeley.edu (Matt Austern)
Date: 1995/11/02
Raw View
Consider a project that spans several directories.  In particular,
let's suppose it has the files project/d1/base.h,
project/d1/derived.h, and project/d2/main.cc.  Here are some code
fragments.

// project/d1/base.h
class B {/* ... */};


// project/d1/derived.h
#include "base.h"

class D : public B { /* ... */ };


// project/d2/main.cc
#include "../d1/derived.h"

int main() { /* ... */ }


The question: what happens when you compile main.cc?  I've tried it
with a few of the popular compilers; the answer is that some compilers
will include derived.h and then in turn include base.h, while some
compilers will include derived.h, search for base.h in d2, then fail
because they can't find d2/base.h.

Each of these behaviors is, of course, standard conforming: section
16.2 of the draft standard simply says that "The named source file is
searched for in an implementation-defined manner."

This is frustrating for two reasons.  The first is simply one of
portability: multi-directory programs are common, and this lack of
specification makes it hard to do this portably.  Second, it seems
clear to me that, in this case, a compiler that searches for base.h in
d1 is more useful than one that searches in d2.  It's a pity that both
are equally valid according to the standard.

Now I can certainly understand why the standard leaves this as
implementation defined: not all platforms have hierarchical file
systems (or even file systems at all in a conventional sense), so it
would be difficult to say anything useful that didn't make
impermissible assumptions about the platform.  It's still frustrating,
though.

So my challenge: can anyone think of an acceptable replacement for
"The named source file is searched for in an implementation-defined
manner" that would provide a bit more of a guarantee of reasonable
behavior?
--
  Matt Austern                             He showed his lower teeth.  "We
  matt@physics.berkeley.edu                all have flaws," he said, "and
  http://dogbert.lbl.gov/~matt             mine is being wicked."

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Marco Dalla Gasperina <Marco_Dalla-Gasperina@HP-Vancouver-om1.om.hp.com>
Date: 1995/11/03
Raw View
matt@cyclops5.berkeley.edu (Matt Austern) wrote:
>
>Consider a project that spans several directories.  In particular,
>let's suppose it has the files project/d1/base.h,
>project/d1/derived.h, and project/d2/main.cc.  Here are some code
>fragments.
>
>// project/d1/base.h
>class B {/* ... */};
>
>
>// project/d1/derived.h
>#include "base.h"
>
>class D : public B { /* ... */ };
>
>
>// project/d2/main.cc
>#include "../d1/derived.h"
>
>int main() { /* ... */ }

How about leaving it up to the invocation of the compiler?

// project/d2/main.cc
#include "derived.h"

int main() { /* ... */ }

cc -c -I ../d1 main.cc

marco

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: ajay@lehman.com (Ajay Kamdar)
Date: 1995/11/03
Raw View
In article <MATT.95Nov2152444@cyclops5.berkeley.edu>,
Matt Austern <matt@physics.berkeley.edu> wrote:

>So my challenge: can anyone think of an acceptable replacement for
>"The named source file is searched for in an implementation-defined
>manner" that would provide a bit more of a guarantee of reasonable
>behavior?


A change in the WP in not necessary to get a guaranteed reasonable
behavior across multiple platforms and multiple compilers.

a) Use the < and > delimiters to include _all_ the header files.
   16.2.1 guarantees an implementation defined sequence of places
   is searched to find the desired header file.

b) Use the implemenation defined syntax to specify the search order
   so that all the directories from which header files are to be
   included are listed in the search list.

   All C++ compilers that I know of on all systems I have used
   invariably provide either a -I compiler option or some equivalent
   switch to set up the search order for header files.

c) Always specify the current directory (-I. if your compiler supports
   the -I option) as the *first* directory to search for header files.
   This results in a behavior similar to using the "" delimiters minus
   the unpredictability associated with that other syntax.

Hence making the following change to your example:

// project/d2/main.cc
#include <derived.h>     // Now using < and > delimiters

and compiling as follows (assuming -I is the implementation dependent
                          method of setting up the header search order
                          and that the compiler goes in the order in
                          which the -I options are specified)

   CC -I. -I../d1 main.c

will always work with any C++ compiler and find the base.h header file.

--
Ajay Kamdar        |    Email: ajay@lehman.com    |    Standard Disclaimer
Lehman Brothers    |    Phone: (201) 524-5048     |

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: ebiederm@cse.unl.edu (Eric Biederman)
Date: 1995/11/04
Raw View
   Consider a project that spans several directories.  In particular,
   let's suppose it has the files project/d1/base.h,
   project/d1/derived.h, and project/d2/main.cc.  Here are some code
   fragments.

[snip]

   So my challenge: can anyone think of an acceptable replacement for
   "The named source file is searched for in an implementation-defined
   manner" that would provide a bit more of a guarantee of reasonable
   behavior?

I think I can, I'll let you be the judge.
Create a header file that you know you can include,
in it have something line

#define STR__(X) #X
#define STR(X) STR__(X)
#define CAT__(A,B) A##B
#define CAT(A,B) CAT__(A,B)

#define ROOT_DIR /home/someone/project/
#define NAME(X) STR(CAT(ROOT_DIR,X))

#define BASE NAME(d1/base.h)
#define DERIVED NAME(d2/derived.h)

then say something like
#include "includes.h"
#include DERIVED

Then all you have to have is includes.h simply reachable from every file,
say a copy in every directory and it should work fine.

Of course for a really strange system the includes.h file needs to be
seriously changed but nothing else does.

Hope that helps Matt,
Eric


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]