C расширение макроса, включая переключатели компилятора - PullRequest
0 голосов
/ 26 февраля 2020

Моя текущая реализация определяет пару переменных в зависимости от соответствующих ключей компилятора:

#ifdef ENABLE_var1
int var1;
#endif
#ifdef ENABLE_var2
int var2;
#endif

Ключи компилятора будут установлены с помощью опции -D во время make. Имена всегда будут состоять из одного и того же префикса и имени переменной. Поскольку это всегда одна и та же стратегия, моя идея состоит в том, чтобы заменить это с помощью следующего макроса:

DECLARE(var1)
DECLARE(var2)

Вызов make -DENABLE_var1 должен привести к:

int var1;

Вызов make -DENABLE_var1 - DENABLE_var2 должен привести к:

int var1;
int var2;

Поскольку невозможно использовать #ifdef внутри макроса, есть ли хитрость для достижения этого?

1 Ответ

1 голос
/ 26 февраля 2020

Пока имена переменных, которые должны быть определены, потенциально известны, тогда это может быть выполнено:

//  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)

Если имена неизвестны, то этот кладж работает:

#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)

Понимание этого требует более детального изучения предварительной обработки, но я приведу несколько замечаний:

  • Для -Dname G CC определяет замену name на 1. Макрос Nullify с его помощниками приводит к замене ENABLE_x пустой последовательностью, если ENABLE_x определено как 1, и непустой последовательностью в противном случае.
  • Тогда, если в результате появилась пустая последовательность, у нас есть Comma (), которая расширяется до запятой. Если это не пустая последовательность, у нас есть Comma something (), что не позволяет расширять функционально-подобный макрос, поэтому некоторая последовательность не включает запятую.
  • Через оставшиеся расширения макроса эта запятая или его отсутствие определяет, какой аргумент находится в списке аргументов, что позволяет нам выбрать либо желаемое определение, либо пустую последовательность.

Я не советую использовать это в рабочем коде. Вероятно, есть лучший способ для достижения sh вашей цели конфигурации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...