Connecting Tech Pros Worldwide Forums | Help | Site Map

Recursing macro preprocessing?

Henrik Goldman
Guest
 
Posts: n/a
#1: Oct 21 '06
I have an application which compiles on a number of different platforms. Now
I'm trying to incorporate an external library which is only available to a
subset of the platforms that my application support.
This is ok as it will give increased usability on some platforms but not
all.

The problem however is to remove code at compiletime when my application is
compiled on a platform which does not support this library.

Using the preprocessor I can enumerate all the platforms on which this
library support like:

#if (defined(_WIN32) && defined(_M_IX86)) || \

(defined(_WIN64) && defined(_M_AMD64)) || \

(defined(__APPLE__) && defined(__ppc__)) || \

(defined(__APPLE__) && defined(__i386__)) || \

....

#endif

However in those places of my application where the support code to use the
library is defined I'd like to condtionally enable the code on a platform
where support is present.

More specifically I'd like to do:



INCLUDE_MY_LIB_SUPPORT_START

printf("This platform has library support\n");

INCLUDE_MY_LIB_SUPPORT_END

On platforms with library support it the macro would expand to nothing. On
unsupported platforms it would expand to #if 0 and #endif and thus removed
by the compiler.

The first few tests showed however that this is not easily possible. The
alternative is then something like:

#ifdef INCLUDE_MY_LIB_SUPPORT

printf("This platform has library support\n");

#endif

This is not as good however as one can easily forget to include the needed
header file and then you get no warning but code on supported platforms will
still be removed.

Is there a way to solve this? One other thing is to define it at compile
time through a switch like -DMY_LIB_SUPPORT but I'd like to keep down the
number of switches on commandline.

Thanks.

-- Henrik



Kaz Kylheku
Guest
 
Posts: n/a
#2: Oct 21 '06

re: Recursing macro preprocessing?


Henrik Goldman wrote:
Quote:
On platforms with library support it the macro would expand to nothing. On
unsupported platforms it would expand to #if 0 and #endif and thus removed
by the compiler.
Not possible. It is not possible to produce a preprocessing directive
using preprocessing. If you produce the tokens ``#if 0'', they will not
be treated as a preprocessing directive, even though they look like
one.
Quote:
The first few tests showed however that this is not easily possible. The
alternative is then something like:
>
#ifdef INCLUDE_MY_LIB_SUPPORT
>
printf("This platform has library support\n");
>
#endif
>
This is not as good however as one can easily forget to include the needed
header file and then you get no warning but code on supported platforms will
still be removed.
Use integer values, instead of testing for symbol existence:

#if INCLUDE_MY_LIB_SUPPORT
#endif

Now you either have

#define INCLUDE_MY_SUPPORT 0

or

#define INCLUDE_MY_SUPPORT 1

If you forget to define it, then the #if is ill-formed, having no
expression.

Chris Thomasson
Guest
 
Posts: n/a
#3: Oct 22 '06

re: Recursing macro preprocessing?


Perhaps this can help:

http://groups.google.com/group/comp....382dc9a40439c7


Greg Comeau
Guest
 
Posts: n/a
#4: Oct 22 '06

re: Recursing macro preprocessing?


In article <1161464042.327302.203290@i42g2000cwa.googlegroups .com>,
Kaz Kylheku <kkylheku@gmail.comwrote:
Quote:
#if INCLUDE_MY_LIB_SUPPORT
#endif
>
>Now you either have
>
#define INCLUDE_MY_SUPPORT 0
>
>or
>
#define INCLUDE_MY_SUPPORT 1
>
>If you forget to define it, then the #if is ill-formed, having no
>expression.
Fairly certain in the case above it is well formed as any ids
not replaced become replaced by a 0 token.
--
Greg Comeau / 20 years of Comeauity! Intel Mac Port now in beta!
Comeau C/C++ ONLINE == http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Kaz Kylheku
Guest
 
Posts: n/a
#5: Oct 22 '06

re: Recursing macro preprocessing?


Greg Comeau wrote:
Quote:
In article <1161464042.327302.203290@i42g2000cwa.googlegroups .com>,
Kaz Kylheku <kkylheku@gmail.comwrote:
Quote:
#if INCLUDE_MY_LIB_SUPPORT
#endif
[ snip ]
Quote:
Quote:
If you forget to define it, then the #if is ill-formed, having no
expression.
>
Fairly certain in the case above it is well formed as any ids
not replaced become replaced by a 0 token.
Ah crap, right.

Then, to defeat all this defaulting, you can to impose an enumeration.
For instance, the rule that two symbols must be defined:

#if defined INCLUDE_MY_SUPPORT
...
#elif !defined NO_INCLUDE_MY_SUPPORT
#error must explicitly request no support
#endif

The obvious alternative way to solve the original problem is to create
an API which is always defined, and always called. On the subset of the
platforms that have the special library, the API calls the library. On
the platforms where it doesn't, the API is just stubs that do the right
kind of nothing for each function.

// In the header file

#if .. test for all the platforms where library is supported ...
// #include or otherwise define the library API
int library_function();
#else
// define dummy version of the API which does nothing, using inline
functions
inline int library_function() { return 0; }
// or, using macros:
#define library_function() ((int) 0)
#endif

And so now there is no special dance to repeat in the sources, where
you simply call the function:

library_function(); // might do nothing if not supported

This also takes care of the forgotten header include.

Closed Thread