As long as the variable names to be defined, potentially, are known, then this can be accomplished:
// Define a DEFINE_x macro for each x that might be enabled.
#if defined ENABLE_var1
#define DEFINE_var1 int var1;
#else
#define DEFINE_var1
#endif
#if defined ENABLE_var2
#define DEFINE_var2 int var2;
#else
#define DEFINE_var2
#endif
// Define DECLARE(x) to expand to the corresponding DEFINE_x macro.
#define DECLARE(x) DEFINE_##x
// List potential definitions.
DECLARE(var1)
DECLARE(var2)
If the names are not known, then this kludge works:
#define Comma() ,
#define Argument3c(a, b, c,...) c
#define Argument3b(a, b,...) Argument3c(a, b, __VA_ARGS__)
#define Argument3a(a,...) Argument3b(a, __VA_ARGS__)
#define Nullify1
#define NullifyHelper(x) Nullify##x
#define Nullify(x) NullifyHelper(x)
#define DECLARE(x) Argument3a(Comma Nullify(ENABLE_##x) (), int x;,,)
DECLARE(var1)
DECLARE(var2)
Understanding this requires following the preprocessing in great detail, but I will provide a few notes:
- For
-Dname
, GCC defines name
to be replaced by 1
. The Nullify
macro, with its helpers, causes ENABLE_x
to be replaced by an empty sequence if ENABLE_x
is defined to be 1
and by a non-empty sequence otherwise.
- Then, if an empty sequence has resulted, we have
Comma ()
, which expands to a comma. If it is not an empty sequence, we have Comma something ()
, which does not allow the function-like macro to be expanded, so some sequence not including a comma results.
- Through the remaining macro expansions, this comma or lack thereof determines which argument is where in the argument list, allowing us to pick out either the desired definition or an empty sequence.
I advise against using this in production code. There is likely a better way to accomplish your configuration goal.