Удалить директиву прекомпилятора из заголовочного файла .h

Я столкнулся с проблемой, которую не знаю, как решить.

Предположим, что в заголовочный файл test.h вложена следующая структура typedef:

typedef struct example_struct {
    #ifdef CONFIG_A
    int A;
    #endif;

    int B;
} example_struct_t;

Я компилирую код, используя этот файл заголовка, передавая CONFIG_A в GCC с параметром -D. Таким образом, я могу включить член A в структуру или удалить, если он не нужен для данного варианта использования.

Теперь предположим, что я создаю общую библиотеку (.so) и хочу ее распространить. Итак, у меня есть библиотека .so и заголовки с директивами прекомпилятора. Проблема в том, что я не хотел бы включать -DCONFIG_A в программу, использующую библиотеку, я имею в виду, что мне нужно было бы сохранить параметры, используемые во время компиляции библиотеки, не только в исходных файлах (.c), но и в заголовок. То есть, если вы компилируете библиотеку с опцией -DCONFIG_A, я полагаю, что программа, использующая библиотеку, не должна включать эту опцию во время компиляции.

Являются ли предварительно скомпилированные заголовки решением этой проблемы или есть какая-либо другая альтернатива (избегая включения заголовка config.h в каждый файл, определяющий директивы прекомпилятора)?

Большое спасибо за руководство.


person A. Moran    schedule 25.10.2016    source источник
comment
Похоже на проблему XY: вопрос, как исправить неправильное решение проблемы. И язык выбрать: C или C ++?   -  person too honest for this site    schedule 25.10.2016
comment
Для C ++ существует правило одного определения (также известное как ODR). Если CONFIG_A определяется при компиляции некоторых единиц перевода, но не для других, у вас есть < i> неопределенное поведение.   -  person Some programmer dude    schedule 25.10.2016
comment
При установке библиотеки вы также можете установить mylibrary.pc файл с соответствующими параметрами препроцессора. Затем проинструктируйте своих пользователей использовать pkg-config --cflags mylibrary.   -  person rodrigo    schedule 25.10.2016
comment
В вопросе в качестве исходного файла упоминается .c - это означает, что это не вопрос С ++.   -  person UKMonkey    schedule 25.10.2016
comment
Первый вопрос, который вам действительно следует задать, - это почему структура должна быть открыта и видима, чтобы вообще использовать ваш общий объект. Раскрытие таких деталей внутренней реализации означает, что вы не можете изменить свою библиотеку, не заставляя каждый двоичный файл, использующий вашу библиотеку, быть перекомпилирован. Это также открывает вам некоторые действительно интересные ошибки, если кто-то скомпилирует структуру таким образом, который приведет к другому размеру и / или выравниванию, чем ожидает ваша библиотека. В идеале такие вещи, как struct определения, не должны быть видны пользователям библиотеки - они должны взаимодействовать только через определенный API.   -  person Andrew Henle    schedule 25.10.2016
comment
Как сказал UKMonkey, это вопрос C. Эндрю. Я полностью согласен с вами, я бы не хотел раскрывать свои структуры в файлах заголовков, чтобы заставить пользователя взаимодействовать с ними через API, но где я могу их определить? Я имею в виду, мне нужно, чтобы они были в файле заголовка, чтобы их можно было включить и использовать в сторонней программе.   -  person A. Moran    schedule 26.10.2016


Ответы (1)


Вы можете «сгенерировать» код для определения структуры и отправить сгенерированное определение вместе с соответствующей библиотекой. Одна из идей - сохранить ваши структуры в заголовке без #includes, и в этом случае вы можете запустить на них препроцессор C, чтобы получить файл без #ifdefs (который затем можно использовать для сборки и доставки).

Другой способ - сделать что-то особенное в вашей системе сборки. Например, CMake имеет #cmakedefine, который вы можете использовать внутри исходного файла C или C ++, а затем сгенерировать из него код.

person John Zwinck    schedule 25.10.2016