I would like to have include file paths dynamically created by a macro for a target-configuration-dependent part of my program.
for example, I would like to construct a macro that would be invoked like this:
#include TARGET_PATH_OF(header.h)
Which will expand to a something like this:
#include "corefoundation/header.h"
when the source is configured (in this case) for OSX
So far all attempts have failed. I'm hoping someone out there has done this before?
example of what does not work:
#include <iostream>
#include <boost/preprocessor.hpp>
#define Dir directory/
#define File filename.h
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
#define MyPath MakePath(File)
using namespace std;
int main() {
// this is a test - yes I know I could just concatenate strings here
// but that is not the case for #include
cout << MyPath << endl;
}
errors:
./enableif.cpp:31:13: error: pasting formed '/filename', an invalid preprocessing token
cout << MyPath << endl;
^
./enableif.cpp:26:16: note: expanded from macro 'MyPath'
#define MyPath MakePath(File)
^
./enableif.cpp:25:40: note: expanded from macro 'MakePath'
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
^
/usr/local/include/boost/preprocessor/cat.hpp:22:32: note: expanded from macro 'BOOST_PP_CAT'
# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
^
/usr/local/include/boost/preprocessor/cat.hpp:29:36: note: expanded from macro 'BOOST_PP_CAT_I'
# define BOOST_PP_CAT_I(a, b) a ## b
^
1 error generated.
I tend to agree with the comment in utnapistim's answer that you shouldn't do this even though you can. But, in fact, you can, with standard-conformant C compilers. [Note 1]
There are two issues to overcome. The first one is that you cannot use the ## operator to create something which is not a valid preprocessor token, and pathnames do not qualify as valid preprocessor tokens because they include / and . characters. (The . would be ok if the token started with a digit, but the / will never work.)
You don't actually need to concatenate tokens in order to stringify them with the # operator, since that operator will stringify an entire macro argument, and the argument may consist of multiple tokens. However, stringify respects whitespace [Note 2], so STRINGIFY(Dir File) won't work; it will result in "directory/ filename.h" and the extraneous space in the filename will cause the #include to fail. So you need to concate Dir and File without any whitespace.
The following solves the second problem by using a function-like macro which just returns its argument:
#define IDENT(x) x
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define PATH(x,y) STR(IDENT(x)IDENT(y))
#define Dir sys/
#define File socket.h
#include PATH(Dir,File)
Warning: (Thanks to #jed for passing on this issue.) If the strings being concatenated contain identifiers which are defined elsewhere as macros, then unexpected macro substitution will occur here. Caution should be taken to avoid this scenario, particularly if Dir and/or File are not controlled (for example, by being defined as a command-line parameter in the compiler invocation).
You need to also be aware than some implementations may define words which are likely to show up in a token-like fashion in a file path. For example, GCC may define macros with names like unix and linux unless it is invoked with an explicit C standard (which is not the default). That could be triggered by paths like platform/linux/my-header.h or even linux-specific/my-header.h.
To avoid these issues, I'd recommend that if you use this hack:
you use a C (or C11) standards-conformant compiler setting, and
you place the sequence very early in your source file, ideally before including any other header, or at least any header outside of the standard library.
Also, you wouldn't need the complication of the IDENT macro if you could write the concatenation without spaces. For example:
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define Dir sys
#define File socket.h
#include STR(Dir/File)
Notes
I tried it with clang, gcc and icc, as available on godbolt. I don't know if it works with Visual Studio.
More accurately, it semi-respects whitespace: whitespace is converted to a single space character.
I would like to have include file paths dynamically created by a macro for a target-configuration-dependent part of my program.
You should be unable to (and if you are able to do so, you probably shouldn't do this).
You are effectively trying to do the compiler's job in a source file, which does not make much sense. If you want to change include paths based on the machine you compile on, this is a solved problem (but not solved in a header file).
Canonical solution:
Use an IF in your Makefile or CMakeLists.txt, use custom property pages depending on the build configuration in Visual Studio (or simply set the particular settings for your build in the OS environment for your user).
Then, write the include directive as:
#include <filename.h> // no path here
and rely on the environment/build system to make the path available when the compiler is invoked.
This works for VS2013. (It can be done easier, ofcourse.)
#define myIDENT(x) x
#define myXSTR(x) #x
#define mySTR(x) myXSTR(x)
#define myPATH(x,y) mySTR(myIDENT(x)myIDENT(y))
#define myLIBAEdir D:\\Georgy\\myprojects\\LibraryAE\\build\\native\\include\\ //here whitespace!
#define myFile libae.h
#include myPATH(myLIBAEdir,myFile)
From your description, it sound like you discovered that not every "" is a string. In particular, #include "corefoundation/header.h" looks like an ordinary string but it isn't. Grammatically, quoted text outside preprocessor directives are intended for the compiler, and compile to null terminated string literals. Quoted text in preprocessor directives is interpreted by the preprocessor in an implementation-defined way.
That said, the error in your example is because Boost pasted the second and third token : / and filename. The first, fourth and fifth token (directory, . and h) are left unchanged. This is not what you wanted, obviously.
It's a lot easier to rely on automatic string concatenation. "directory/" "filename" is the same string literal as "directory/filename" Note that there is no + between the two fragments.
This question already has answers here:
Escaping a # symbol in a #define macro?
(8 answers)
Closed 5 years ago.
I want to use a macro to define another macro in C++. Were the macro to define the macro has two arguments, one the name of a macro to do an "#ifdef" test on, the other the name of the new macro to #define. This example is pared down. The real situation is complicated which is why I want to factor it out.
#define TEST_ME // or NOT
#define DEFINE_A_MACRO( _test_me_, _define_me_ ) \
\
#ifdef (actual value of)_test_me_ \
#define (actual value of _define_me_) One Thing \
#else \
#define (actual value of _define_me_) Another Thing \
#endif
...
DEFINE_A_MACRO( TEST_ME, DEFINE_ME )
Is there any way to do this ?
I doubt it but might as well pose the question :)
No. while the preprocessor can support multiple levels of token replacement (one macro may reference another), this only applies to tokens. You can't generate new preprocessor directives.
In other words, you solve this by
#ifdef TEST_ME
#define THING ONETHING
#else
#define THING ANOTHERTHING
#endif
#define DEFINE_ME THING
(Or by writing C++ code - macro's are really unnecessary these days)
We have a profiling framework which can be enabled and disabled at compile time.
All the various calls to the framework are done through macros, eg:
PROFILE_START(msg)
PROFILE_END(msg)
The macros then resolve to the actual profiler call when profiling is enabled, and to nothing when disabled
#ifdef PROFILING_ENABLED
# define PROFILE_START(msg) currentProfiler().start(msg)
# define PROFILE_END(msg) currentProfiler().end(msg)
#else
# define PROFILE_START(msg)
# define PROFILE_END(msg)
#endif
We have various different components in our framework, and I want to enable profiling in each component.
I'd like to be able to selectively enable profiling in each component.
My idea is to prefix all the profiler macros with the component's name, eg:
FOO_PROFILE_START(msg)
FOO_PROFILE_END(msg)
BAR_PROFILE_START(msg)
BAR_PROFILE_END(msg)
I could manually create
#ifdef ENABLE_FOO_PROFILING
# define FOO_PROFILE_START(msg) PROFILE_START(msg)
# define FOO_PROFILE_END(msg) PROFILE_END(msg)
#else
# define FOO_PROFILE_START(msg)
# define FOO_PROFILE_END(msg)
#endif
#ifdef ENABLE_BAR_PROFILING
# define BAR_PROFILE_START(msg) PROFILE_START(msg)
# define BAR_PROFILE_END(msg) PROFILE_END(msg)
#else
# define BAR_PROFILE_START(msg)
# define BAR_PROFILE_END(msg)
#endif
However, this is both tedious and error-prone.
Any time a new feature is added to the profiling framework I would have to find all my component specific macros and add a new macro to each of them.
What I'm looking for is a way to automatically generate the component-prefixed macros.
#ifdef ENABLE_FOO_PROFILING
ADD_PREFIX_TO_ENABLED_PROFILING_MACROS(FOO)
#else
ADD_PREFIX_TO_DISABLED_PROFILING_MACROS(FOO)
#endif
The net result of the above would be to create all the FOO_PROFILE_XXX macros I would have done manually.
Questions:
Is such a helper macro possible?
Is there a better way of achieving what I'm looking for?
I'm happy to use BOOST_PP if necessary.
Before posting this question I tried figuring this out myself, and the code I came up with follows, which may serve to show the road I was going down
#include <stdio.h>
#define PROFILE_START(msg) printf("start(%s)\n", msg);
#define PROFILE_END(msg) printf("end(%s)\n", msg);
#define ENABLE(prefix) \
#define prefix ## _PROFILE_START PROFILE_START \
#define prefix ## _PROFILE_END PROFILE_END
#define DISABLE(prefix) \
#define prefix ## _PROFILE_START \
#define prefix ## _PROFILE_END
#define ENABLE_FOO
#ifdef ENABLE_FOO
ENABLE(FOO)
#else
DISABLE(FOO)
#endif
#ifdef ENABLE_BAR
ENABLE(BAR)
#else
DISABLE(BAR)
#endif
int main()
{
FOO_PROFILE_START("foo");
FOO_PROFILE_END("foo");
BAR_PROFILE_START("bar");
BAR_PROFILE_END("bar");
return 0;
}
Is such a helper macro possible?
No. With the exception of pragmas, you cannot execute a preprocessing directive in a macro.
You can do something very similar using pattern matching. By taking the varying parts out of the macro name, and putting it inside the macro itself, you can make a form that allows enabling/disabling for arbitrary names.
This requires a tiny bit of preprocessor metaprogramming (which is a constant overhead; i.e., doesn't vary as you add modules), so bear with me.
Part 1: A C preprocessor solution
Using this set of macros:
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
#define SWITCH(PREFIX_,PATTERN_,DEFAULT_) SECOND(GLUE(PREFIX_,PATTERN_),DEFAULT_)
#define EAT(...)
#define PROFILER_UTILITY(MODULE_) SWITCH(ENABLE_PROFILER_FOR_,MODULE_,DISABLED)
#define PROFILER_IS_DISABLED ,EAT
#define PROFILE_START_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START)(msg)
#define PROFILE_END_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_END)(msg)
...which you can include in each module, you will gain the ability to do this:
PROFILE_START_FOR(FOO,msg)
PROFILE_END_FOR(FOO,msg)
PROFILE_START_FOR(BAR,msg)
PROFILE_END_FOR(BAR,msg)
PROFILE_START_FOR(BAZ,msg)
PROFILE_END_FOR(BAZ,msg)
All of these macros, by default, expand to nothing; you can change this by defining ENABLE_PROFILER_FOR_xxx for any subset of FOO, BAR, or BAZ to expand to , (or ,ON if that looks better), in which case the corresponding macros will expand (initially, before your own macros come in) to PROFILE_START(msg)/PROFILE_END(msg); and the rest will continue expanding to nothing.
Using the FOO module as an example, you can do this with a "control file": #define ENABLE_PROFILER_FOR_FOO ,ON; the command line: ... -DENABLE_PROFILER_FOR_FOO=,ON; or in a makefile; CFLAGS += -DENABLE_PROFILER_FOR_FOO=,ON.
Part 2a: how it works; the SWITCH macro
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
#define SWITCH(PREFIX_,PATTERN_,DEFAULT_) SECOND(GLUE(PREFIX_,PATTERN_),DEFAULT_)
GLUE here is your typical indirect paste macro (allowing arguments to expand). SECOND is an indirect variadic macro returning the second argument.
SWITCH is the pattern matcher. The first two arguments are pasted together, comprising the pattern. By default, this pattern is discarded; but due to the indirection, if that pattern is an object like macro, and that pattern's expansion contains a comma, it will shift a new second argument in. For example:
#define ORDINAL(N_) GLUE(N_, SWITCH(ORDINAL_SUFFIX_,N_,th))
#define ORDINAL_SUFFIX_1 ,st
#define ORDINAL_SUFFIX_2 ,nd
#define ORDINAL_SUFFIX_3 ,rd
ORDINAL(1) ORDINAL(2) ORDINAL(3) ORDINAL(4) ORDINAL(5) ORDINAL(6)
...will expand to:
1st 2nd 3rd 4th 5th 6th
In this manner, the SWITCH macro behaves analogous to a switch statement; whose "cases" are object-like macros with matching prefixes, and which has a default value.
Note that pattern matching in the preprocessor works with shifting arguments, hence the comma (the main trick being that of discarding unmatched tokens by ignoring an argument, and applying matched tokens by shifting a desired replacement in). Also for the most general case with this SWITCH macro, you need at a minimum to ensure that all PREFIX_/PATTERN_ arguments are pasteable (even if that token isn't seen, it has to be a valid token).
Part 2b: combined switches for safety
A lone switch works like a case statement, allowing you to shove anything in; but when the situation calls for a binary choice (like "enable" or "disable"), it helps to nest one SWITCH in another. That makes the pattern matching a bit less fragile.
In this case, the implementation:
#define PROFILER_UTILITY(MODULE_) SWITCH(ENABLE_PROFILER_FOR_,MODULE_,DISABLED)
#define PROFILER_IS_DISABLED ,EAT
#define PROFILE_START_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START)(msg)
#define PROFILE_END_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_END)(msg)
...uses PROFILER_UTILITY as the inner switch. By default, this expands to DISABLED. That makes the pattern in SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START) by default be PROFILER_IS_DISABLED, which shoves in EAT. In the non-default case of PROFILER_UTILITY, the outer switch kicks in making it expand to PROFILE_START. PROFILE_END_FOR works analogously.
The EAT macro takes (msg) in both cases to nothing; otherwise, the original macro's called.
Is there a better way of achieving what I'm looking for?
Depends on what you're looking for. This approach shows what's possible with the C preprocessor.
I personally would go for something like
#include <stdio.h>
#define FOO_ENABLED 1
#define BAR_ENABLED 0
#define PROFILE_START(FLAG, msg) \
{ if (FLAG) printf("start(%s)\n", msg); }
int main()
{
PROFILE_START(FOO_ENABLED, "foo")
PROFILE_START(BAR_ENABLED, "bar")
return 0;
}
Any decent compiler would not generate any instructions for the if statement anyway.
Is such a helper macro possible?
No. As was covered in comments, you cannot generate macro definitions via macros.*
Is there a better way of achieving what I'm looking for?
Since the macro idea won't work,* any alternative that does work is better. Basically, you're looking for a code generator -- a program that will take as input a list of modules and produce as output C source (maybe a header) containing definitions of all the profiling macros for all the modules. You could write such a program in pretty much any language -- C, python, perl, shell script, whatever. Depending on your technology preferences and project context, you might even go with something like XSLT.
Each source file that wants to get the profiling macros then just #includes the generated header.
*In fact, you could use the C preprocessor, by performing a separate, standalone run on a different, for-purpose input file. But you cannot generate the macros in-place when you compile the source file(s) that wants to use them.
I have a bunch of source code that uses double-parentheses for a bunch of macro calls where the 2nd arg and forward is a varargs for a print statement.
DEBUG((1,"here is a debug"))
DEBUG((1,"here is %d and %d",42,43))
etc..
I want to write a macro that can print args 2-..., but I can't figure out how to remove the extra parentheses so I can access the args.
I.e., this obviously does not work:
#define DEBUG(ignore,...) fprintf(stderr,__VA_ARGS__)
And the following attempt to be sneaky also fails (with 'DEBUG2 not defined'):
#define DEBUG2(ignore,...) fprintf(stderr,__VA_ARGS__)
#define DEBUG(...) DEBUG2
Without editing all the macro calls to remove parens, how can I define a macro that will do this?
You may do:
#define PRINTF(unused, ...) fprintf(stderr, __VA_ARGS__)
#define DEBUG(arg) PRINTF arg
This question already has answers here:
Creating C macro with ## and __LINE__ (token concatenation with positioning macro)
(3 answers)
Closed 7 years ago.
In a macro I want to generate a variable with a different name and try to use __LINE__ as a way to differentiate them. A simplified sample:
#define UNIQUE_INT int prefix##__LINE__
UNIQUE_INT;
UNIQUE_INT;
But it seems that __LINE__ is not expanding as I get "int prefix__LINE__' : redefinition" in the second one.
I suppose that __LINE__ can not be used in a macro definition as if it expanded would do to the line number of the #definition rather than the line of the invocation of the macro, but let me ask just in case someone has something to say.
The problem is that in the preprocessor, the ## takes place before __LINE__ is expanded. If you add another layer of indirection, you can get the desired result.
For technical reasons you actually need two macros (sometimes if you use this in an existing macro you don't need the second one, it seems...):
#define TOKEN_PASTE(x, y) x##y
#define CAT(x,y) TOKEN_PASTE(x,y)
#define UNIQUE_INT \
int CAT(prefix, __LINE__)
UNIQUE_INT;
UNIQUE_INT;