Using macro inside an include statement

E

Eyal

Hi,

I develop in an environment of "system of systems" where each such
system / tool is consistent with their fine names and class names. My
problem is that we don't have this uniqueness at the "system of
systems" level.

So when I do

#include "Tdb/TdbFactory.h"

the include file can be taken from a root of TOOL1 or from a root of
TOOL2 which are both in the include path.

Hence what I would like to do is something like:
#define TOOL1 /nfs/TOOL1 // which may be different across sites
and needs to stay at a macro level
#include "TOOL1/Tdb/TdbFactory.h" and by this "force" the include from
the correct location. Mind you that include order isn't enough for the
situation that both tools DOES have the same include file and
directory (real life problem in my work...).

Unfortunately this doesn't work with the C/C++ preprocessor.
Any suggestion?

Thanks,
Eyal
 
A

Alf P. Steinbach

* Eyal:
I develop in an environment of "system of systems" where each such
system / tool is consistent with their fine names and class names. My
problem is that we don't have this uniqueness at the "system of
systems" level.

So when I do

#include "Tdb/TdbFactory.h"

the include file can be taken from a root of TOOL1 or from a root of
TOOL2 which are both in the include path.

Hence what I would like to do is something like:
#define TOOL1 /nfs/TOOL1 // which may be different across sites
and needs to stay at a macro level
#include "TOOL1/Tdb/TdbFactory.h" and by this "force" the include from
the correct location. Mind you that include order isn't enough for the
situation that both tools DOES have the same include file and
directory (real life problem in my work...).

Unfortunately this doesn't work with the C/C++ preprocessor.
Any suggestion?

Best is to fix this outside language, by e.g. *nix symbolic links or something.

E.g. make a symbolic link 'tool1' that maps to the parent directory of the
relevant 'Tdb' directory.

One problem is that in Windows it's a bit difficult to directly link a directory
to a directory (they can be easily mapped to physical drives, but it's a bit
difficult to map them to directories), so in Windows you'd in practice have to
do this on a file-by-file basis, not whole directories at a time.

If you can't fix it that way outside the language, then use preprocessor token
pasting and perhaps also stringifying.

The rule for that is that after macro replacement, the resulting text must be a
valid "" or <> include directive.


Cheers & hth.,

- Alf
 
V

Vladyslav Lazarenko

Hi,

I develop in an environment of "system of systems" where each such
system / tool is consistent with their fine names and class names. My
problem is that we don't have this uniqueness at the "system of
systems" level.

So when I do

#include "Tdb/TdbFactory.h"

the include file can be taken from a root of TOOL1 or from a root of
TOOL2 which are both in the include path.

Hence what I would like to do is something like:
#define TOOL1 /nfs/TOOL1     // which may be different across sites
and needs to stay at a macro level
#include "TOOL1/Tdb/TdbFactory.h" and by this "force" the include from
the correct location. Mind you that include order isn't enough for the
situation that both tools DOES have the same include file and
directory (real life problem in my work...).

Unfortunately this doesn't work with the C/C++ preprocessor.
Any suggestion?

Thanks,
Eyal

Check out this example (tested with GCC 4.3.2):

#define FACTORY_HEADER db/TdbFactory.h

#define TOOL1_DIR /nfs/TOOL1/
#define TOOL2_DIR /nfs/TOOL2/

#define EXPAND(x) x
#define CONCAT_STR(x, y) EXPAND(x)y

#define TOOL1_FACTORY_HEADER <CONCAT_STR(EXPAND(TOOL1_DIR), EXPAND
(FACTORY_HEADER))>
#define TOOL2_FACTORY_HEADER <CONCAT_STR(EXPAND(TOOL2_DIR), EXPAND
(FACTORY_HEADER))>

#include TOOL1_FACTORY_HEADER
#include TOOL2_FACTORY_HEADER

Hope it helps.
 
J

James Kanze

On 2009-04-02 12:43:56 -0400, Eyal <[email protected]> said:

[...]
If the text following a #include is a quoted string, that
string is used as the identifier for the include file. So you
need to push the quotes down:
#define PATH "/nfs/TOOL1"
#include PATH
Here, since the text after #include doesn't match "..." and
doesn't match <...>, it's expanded as a macro, and then used
as the identifier for the #include directive.
Of course, this example doesn't solve the actual problem you
described. But that extra level of indirection is what you
need. You'll also probably need yet another level of
indirection to add the quotes around the actual identifier
once you create it.

Note that if token pasting is involved (as it could be in his
case), this can become tricky; the result of pasting two tokens
must be a token, and at least one compiler (g++) enforces this.
I use the following to handle my various system dependent
directories:

#define GB_string2( s ) # s
#define GB_stringize( s ) GB_string2( s )
#define GB_paste2( a, b ) a ## b
#define GB_paste( a, b ) GB_paste2( a,b )
#define GB_dependentInclude(variant,file) \
GB_stringize( GB_paste(GB_include_,variant)(file) )

// ...

#define GB_depends_path "sparc-solaris-suncc"
#define GB_include_conf( file ) conf/sparc-solaris-suncc/file
#define GB_include_arch( file ) arch-sparc/file
#define GB_include_syst( file ) syst-posix/file
#define GB_include_comp( file ) comp-suncc/file

followed by things like:

#include GB_dependentInclude(arch,SomeHeader.hh)

I'm not too sure about the conformance of all this---according
to the standard, the pre-processor operator # generates a string
literal, and #include doesn't take a string literal, but
"q-char-sequence", so technically, I think it's a syntax error.
But all of the compilers I've tried do accept it, at least as
long as there are no "funny" characters in the string. (The
reason for the distinction between string literals and
q-char-sequences is, of course, that the treatment of things
like \n can be different in them. If one of your targets is
Windows, and you want to do this, use '/' as the separator
between directories, and not '\'.)

Depending on his needs, he could define something like the
GB_include_xxx on his command line, in order to choose one
variant or the other.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,824
Latest member
Nater888

Latest Threads

Top