Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

VC++ and recursive search of include paths

97 views
Skip to first unread message

Stephen Baxter

unread,
Aug 10, 1999, 3:00:00 AM8/10/99
to
Hi,

I'm a Mac programmer new to VC++. We have a lot of cross platform code, all
neatly organised into directories. In Codewarrior (the Mac compiler), you
just specify the top level directory and it will recursively find any
include files and libraries in that directory or below.

I don't seem to be able to do this in VC++ - you have to *manually* specify
every single wretched directory. Is it really this hard? Is there any way
to make this work in VC++? Are you really meant to have all your thousands
of source files in a single directory?

Cheers,

Steve.

--
Stephen Baxter
Development Manager
Improvision
st...@improvision.com
Tel:+44-1203-692229
Fax:+44-1203-690091

Erik Funkenbusch

unread,
Aug 10, 1999, 3:00:00 AM8/10/99
to
Nope. Just select "Find in files" choose your search string and click "Look
in subfolders"

Stephen Baxter <st...@improvision.com> wrote in message
news:934280845.2574.0...@news.demon.co.uk...

Wessel Troost

unread,
Aug 10, 1999, 3:00:00 AM8/10/99
to
Hmm... if you're asking if you have to manually specify
in which directories your libraries and header files
are, the answer is yes.

You can add them in Tools -> Options -> Directories
rather than Project -> Settings -> ...
That way, the compiler will look in those directories
for all projects you have.

If you were looking for a way to find specific files,
then Erik is right of course :)

Erik Funkenbusch <er...@visi.com> wrote in message
news:eq1x74x4#GA.297@cppssbbsa04...

Jesse Jones

unread,
Aug 10, 1999, 3:00:00 AM8/10/99
to
In article <934280845.2574.0...@news.demon.co.uk>,
Stephen Baxter <st...@improvision.com> wrote:

> Hi,
>
> I'm a Mac programmer new to VC++. We have a lot of cross platform code, all
> neatly organised into directories. In Codewarrior (the Mac compiler), you
> just specify the top level directory and it will recursively find any
> include files and libraries in that directory or below.
>
> I don't seem to be able to do this in VC++ - you have to *manually* specify
> every single wretched directory. Is it really this hard? Is there any way
> to make this work in VC++? Are you really meant to have all your thousands
> of source files in a single directory?

AFAIK there's no good way to handle this in MSVC which is rather
astounding. I know of three ways to specify include paths:

1) You can type them all into MSVC's tiny settings dialog textboxes.

2) You can use the Tools menu which will give you a nicer interface and
a scrollable list. Unfortunately these includes are used with every
project.

3) You can use the "@" compile flag to specify a text file containing a
list of includes. This is a lot less painful than option 1, but still
awfully clumsy.

-- Jesse

Doug Harrison

unread,
Aug 11, 1999, 3:00:00 AM8/11/99
to
Stephen Baxter wrote:

>I'm a Mac programmer new to VC++. We have a lot of cross platform code, all
>neatly organised into directories. In Codewarrior (the Mac compiler), you
>just specify the top level directory and it will recursively find any
>include files and libraries in that directory or below.

I think that's rather unconventional. In every compiler I"ve used, you add a
folder to the include path, and if it contains subfolders, you refer to
files contained therein as:

// a's parent folder is on the include path
#include <a/a.h>
#include <a/b/b.h>
#include <a/b/b2.h>
#include <a/c/c.h>

and so on. This isn't standardized, but it's a common, sensible approach
that corresponds closely to namespaces. Note that if b.h #included b2.h, it
could simply say:

#include "b2.h"

because b2.h is in the same directory, and in VC, the quoted form of the
#include directive first looks in the folder containing the file making the
#include. Similarly, if a.h wanted to #include b.h, it could use:

#include "b/b.h"

It sounds like CodeWarrior basically flattens the directory structure; in
namespace terms, it issues a bunch of using directives, which is frowned on
by most. How does CodeWarrior handle files that have the same name? Does the
outer-most file win? And what about files with the same name that are at the
same level in the directory hierarchy but in different folders? In the
example above, if a/c contained a file named b.h, and you said #include
<b.h>, what would CodeWarrior do? Would it choose a/b/b.h, because a/b
precedes a/c in alphabetical order? I would prefer an error, because that's
no basis for choosing one file over another, but that would mean doing an
exhaustive, recursive enumeration of all the #include folders. Ick.

--
Doug Harrison
dHar...@worldnet.att.net
Visual C++ MVP


Jesse Jones

unread,
Aug 12, 1999, 3:00:00 AM8/12/99
to
In article <emkumiE5#GA.297@cppssbbsa04>, Doug Harrison
<dHar...@worldnet.att.net> wrote:

> Stephen Baxter wrote:
>
> >I'm a Mac programmer new to VC++. We have a lot of cross platform code, all
> >neatly organised into directories. In Codewarrior (the Mac compiler), you
> >just specify the top level directory and it will recursively find any
> >include files and libraries in that directory or below.
>
> I think that's rather unconventional. In every compiler I"ve used, you add a
> folder to the include path, and if it contains subfolders, you refer to
> files contained therein as:

Just because most compilers require you to enumerate all your include
directories doesn't mean it's a good idea. For example, I do most of my
work using a framework that has 48 include paths on Windows. With
CodeWarrior I can tell it to recursively search the Source directory
and it will automagically find my files. With MSVC I have to list each
damned directory. Even worse each of my apps has to do this which is a
serious maintenance head-ache. So, to get around this they all point to
one @ file which hard-codes the full paths. This works but causes
problems for other people using my framework.

From my POV CodeWarrior's handling of includes is *far* better than
MSVC's.

> It sounds like CodeWarrior basically flattens the directory structure; in
> namespace terms, it issues a bunch of using directives, which is frowned on
> by most. How does CodeWarrior handle files that have the same name? Does the
> outer-most file win? And what about files with the same name that are at the
> same level in the directory hierarchy but in different folders? In the
> example above, if a/c contained a file named b.h, and you said #include
> <b.h>, what would CodeWarrior do? Would it choose a/b/b.h, because a/b
> precedes a/c in alphabetical order? I would prefer an error, because that's
> no basis for choosing one file over another, but that would mean doing an
> exhaustive, recursive enumeration of all the #include folders. Ick.

This is a problem even without recursive directory searchs. Supporting
recursion may make this a bit more of a problem, but not by much. Note
that with CodeWarrior recursive searches are completely optional...

-- Jesse

Doug Harrison

unread,
Aug 12, 1999, 3:00:00 AM8/12/99
to
Jesse Jones wrote:

>Just because most compilers require you to enumerate all your include
>directories doesn't mean it's a good idea.

That's why I compared VC's approach with namespaces, and pointed out
problems with CodeWarrior's method that VC's method doesn't have.

>For example, I do most of my
>work using a framework that has 48 include paths on Windows.

That's way too many! IMO, this is the best way to organize headers:

Define a master include directory, separate from your compiler's include
directory. Don't place any headers in this directory. Instead, for each
company or library whose headers you use, create directories named after
each. For example:

d:\include
CompanyA
headers and subdirectories
LibA
headers and subdirectories
...

Add d:\include to the front of your include path. Then you can include
headers by saying:

#include <CompanyA/hdr.h>
#include <LibA/hdr.h>

This way, there's no danger of conflicts. CompanyA can define memory.h if it
wants, without fear of:

#include <memory.h>

picking it up. That's a real problem in many libraries. For example, the SGI
STL's deque.h contains the following:

#include <alloc.h>

alloc.h is a non-standard header name, and this is an unacceptable way to
#include it, because it demands that the SGI STL path appear before any
other path, which also contains an alloc.h, in the include order. And if
your system headers have an alloc.h, it totally messes things up.

It's a shame the standards don't go ahead and define the search order for
#include directives analogously to namespaces, as VC does, because the two
name lookup problems are essentially the same, and namespaces work. Instead,
the standards leave the search order implementation-defined, which causes
many problems. It's a bad thing to refer to a non-system header with:

#include <leafname>

Unfortunately, many libraries do just that, stepping all over the header
file namespace.

>With CodeWarrior I can tell it to recursively search the Source directory
>and it will automagically find my files. With MSVC I have to list each
>damned directory.

No, you don't. If you have:

d:\project
a.cpp
a.h
inc
b.h

a.cpp includes a.h by saying:

#include "a.h"

a.cpp includes b.h by saying:

#include "inc/b.h"

You don't have to add any include directories to do this.

>Even worse each of my apps has to do this which is a
>serious maintenance head-ache. So, to get around this they all point to
>one @ file which hard-codes the full paths. This works but causes
>problems for other people using my framework.
>
>From my POV CodeWarrior's handling of includes is *far* better than
>MSVC's.

CodeWarrior's approach is a facile solution that encourages dependence on an
unconventional implementation, and that's what's really biting you right
now. It may be superficially attractive, but as I described in my last
message, it implies a set of new problems that IMO doesn't constitute a good
trade-off. And it's horribly non-portable; you'd be facing the same problem
in every other compiler I know of that you're now facing in VC++. Even gcc,
which has to be the most extended compiler ever, doesn't appear to implement
recursive directory searches for included files.

>> It sounds like CodeWarrior basically flattens the directory structure; in
>> namespace terms, it issues a bunch of using directives, which is frowned on
>> by most. How does CodeWarrior handle files that have the same name? Does the
>> outer-most file win? And what about files with the same name that are at the
>> same level in the directory hierarchy but in different folders? In the
>> example above, if a/c contained a file named b.h, and you said #include
>> <b.h>, what would CodeWarrior do? Would it choose a/b/b.h, because a/b
>> precedes a/c in alphabetical order? I would prefer an error, because that's
>> no basis for choosing one file over another, but that would mean doing an
>> exhaustive, recursive enumeration of all the #include folders. Ick.
>
>This is a problem even without recursive directory searchs.

With VC, you get to specify the directory search order, and you can
completely avoid such problems. In VC, if I introduce a new header with the
same name as an existing header, there's no danger whatsoever of conflicting
with the old header, provided I follow the method I described above.
However, with a recursive directory search, there's ambiguity.

>Supporting recursion may make this a bit more of a problem, but not by much.

Going from "no problem at all" to "problem" is a pretty big increase. :)

I'm still curious how CodeWarrior deals with the ambiguities I asked about
in my last message...

>Note that with CodeWarrior recursive searches are completely optional...

That's always good. It would also be nice for them to detail the
disadvantages and portability concerns that arise from "taking advantage" of
this optional behavior.

P.S. VC's not quite perfect in a related area. To try to speed dependency
checking, VC defines a couple of files, MSVCINCL.DAT and SYSINCL.DAT, which
contain the names of system headers that should be excluded from dependency
checking. Unfortunately, the decision to exclude a header is based solely on
the header's leaf name, without regard to its location. This means that if
you give a header the same name as one of the 1300+ files in SYSINCL.DAT, it
will be excluded from dependency checking. I recommend deleting these DAT
files until this problem is fixed. In my experience, there is a negligible
impact on build speeds. Flattening directory structure just doesn't work.

Jesse Jones

unread,
Aug 13, 1999, 3:00:00 AM8/13/99
to
In article <OKxJUiU5#GA.294@cppssbbsa05>, Doug Harrison
<dHar...@worldnet.att.net> wrote:

> Jesse Jones wrote:
>
> >Just because most compilers require you to enumerate all your include
> >directories doesn't mean it's a good idea.
>
> That's why I compared VC's approach with namespaces, and pointed out
> problems with CodeWarrior's method that VC's method doesn't have.
>
> >For example, I do most of my
> >work using a framework that has 48 include paths on Windows.
>
> That's way too many! IMO, this is the best way to organize headers:

Tastes differ. Once you get more than a few hundred files I find that
adding a bit of structure to the directory layout makes it much easier
to find files. Making it difficult to use a lot of include paths is IMO
a very bad idea, especially for large projects.

> >With CodeWarrior I can tell it to recursively search the Source directory
> >and it will automagically find my files. With MSVC I have to list each
> >damned directory.
>
> No, you don't. If you have:
>
> d:\project
> a.cpp
> a.h
> inc
> b.h
>
> a.cpp includes a.h by saying:
>
> #include "a.h"
>
> a.cpp includes b.h by saying:
>
> #include "inc/b.h"
>
> You don't have to add any include directories to do this.

This may work OK for simple cases, but IMO it quickly become unwieldy.
I, for example, have a directory structure that looks something like
this:

Source
High Level
...
Core
...
Foundation
Containers
Debug
Threads
...

This would require me to type things like: <Foundation/Debug/XDebug.h>.
This would be doable, but it would be a pain to remember the path for
every single include and moving a file could require touching a lot of
files.

> CodeWarrior's approach is a facile solution that encourages dependence on an
> unconventional implementation, and that's what's really biting you right
> now. It may be superficially attractive, but as I described in my last
> message, it implies a set of new problems that IMO doesn't constitute a good
> trade-off. And it's horribly non-portable; you'd be facing the same problem
> in every other compiler I know of that you're now facing in VC++. Even gcc,
> which has to be the most extended compiler ever, doesn't appear to implement
> recursive directory searches for included files.

It's not non-portable. The only problem with it is that it makes it
easy to design rather complex directory layouts. In general this is a
good thing however with other compilers you may need to explicitly list
each include path. MSVC unfortunately makes this rather difficult.

> With VC, you get to specify the directory search order, and you can
> completely avoid such problems. In VC, if I introduce a new header with the
> same name as an existing header, there's no danger whatsoever of conflicting
> with the old header, provided I follow the method I described above.
> However, with a recursive directory search, there's ambiguity.

There may not be any ambiguity, but there's still potential for
problems (eg you use the same file names in two directories without
realizing that the compiler is loading the other file).

CodeWarrior, of course, also lets you specify the directory search
order however I don't know if it does recursive searches in
alphabetical order.

-- Jesse

Doug Harrison

unread,
Aug 15, 1999, 3:00:00 AM8/15/99
to
Jesse Jones wrote:

>Tastes differ. Once you get more than a few hundred files I find that
>adding a bit of structure to the directory layout makes it much easier
>to find files. Making it difficult to use a lot of include paths is IMO
>a very bad idea, especially for large projects.
>

>This may work OK for simple cases, but IMO it quickly become unwieldy.
>I, for example, have a directory structure that looks something like
>this:
>
>Source
> High Level
> ...
> Core
> ...
> Foundation
> Containers
> Debug
> Threads
> ...
>
>This would require me to type things like: <Foundation/Debug/XDebug.h>.
>This would be doable, but it would be a pain to remember the path for
>every single include and moving a file could require touching a lot of
>files.

I organize my library headers in a similar way; I have a root include
directory containing 10 subdirectories, one of which has two subdirectories
of its own. I find the trouble it saves me, which I talked about in my
earlier messages, is well worth the extra typing. You're right that moving a
header is a minor pain; I've done that a handful of times to refine the
library structure. Hopefully, one can get this part of the design right
before shipping to users, but really, most every aspect of library design is
subject to this sort of problem. In my case, each directory immediately off
the root corresponds to a single library, most of which are DLLs, and for
the most part, I haven't found it desirable to subdivide a library directory
by adding subdirectories to its primary include directory.

To use my libraries, I add one include path.

>It's not non-portable.

It's very non-portable. When you rely on a non-standard feature, you're
non-portable. Unfortunately, there's really no standard behavior here, so
all you can do is look for a de facto standard, and recursive directory
search ain't it.

>The only problem with it is that it makes it
>easy to design rather complex directory layouts.

I'd say it makes it easy to pretend the complex directory layout doesn't
exist. I'd say it makes it easy to throw away valuable information.

>In general this is a
>good thing however with other compilers you may need to explicitly list
>each include path. MSVC unfortunately makes this rather difficult.

VC's search rules are commonly implemented, and emulating CodeWarrior's
rules in VC is no more difficult than in any other compiler I've used.

>> With VC, you get to specify the directory search order, and you can
>> completely avoid such problems. In VC, if I introduce a new header with the
>> same name as an existing header, there's no danger whatsoever of conflicting
>> with the old header, provided I follow the method I described above.
>> However, with a recursive directory search, there's ambiguity.
>

>There may not be any ambiguity, but there's still potential for
>problems (eg you use the same file names in two directories without
>realizing that the compiler is loading the other file).

Not really. If you provide a file that uses the non-standard header name
alloc.h in MyLib, and the user says:

#include <alloc.h>

when he meant:

#include <MyLib/alloc.h>

he made a mistake.

But if the user tries to use your flattened library in his existing code,
and he has a system header he includes with:

#include <alloc.h>

and your library expects to be at the front of the search path, and worse,
expects to include its own alloc.h with:

#include <alloc.h>

as SGI's STL does, the library has invalidated the user's existing code and
created a real problem for the user. This problem simply doesn't arise with
the method I've described.

>CodeWarrior, of course, also lets you specify the directory search
>order however I don't know if it does recursive searches in
>alphabetical order.

Well, unless all your header files have different names, it sounds like
you'll have a difficult time figuring out how to add all your directories to
the search path. I'm sorry you've encountered this problem, but I think it's
unfair to criticize VC or any other compiler for not providing CodeWarrior's
unusual recursive directory search.

0 new messages