Альтернативы/инструменты для #define hell C/C++

В нашем проекте C/C++ мы используем заголовок конфигурации (~ 1000 строк), который полон #ifdef и #define.

#if (defined(HW_1) || defined(SOME_TECHNOLOGY_SUPPORTED)) && defined(OTHER_TECHNOLOGY_SUPPORTED)
 #define SOME_FEATURE_AVAILABLE
#endif

В нашей конфигурации сборки мы предварительно определяем некоторые определения, которые передаются компилятору. Это приводит к различным определениям (например, SOME_FEATURE_AVEILABLE) в нашем заголовке конфигурации.

Поскольку наш заголовок конфигурации довольно большой, в нем тоже есть некоторый беспорядок.

Есть ли альтернативы этому #define аду?

Или есть какие-нибудь инструменты, которые помогают увидеть, в каком случае установлены определения.

Мы разрабатываем встроенную прошивку, поэтому мы не можем заменить условную компиляцию условиями выполнения.


person woodtluk    schedule 08.08.2013    source источник
comment
На какой системе вы компилируете. Для какой операционной системы? Ищите autoconf и autotools ....   -  person Basile Starynkevitch    schedule 08.08.2013
comment
Если вы придерживаетесь ANSI C89 и ISO C++ 98, то вам не нужен ни один из них.   -  person    schedule 08.08.2013
comment
Тем не менее, компилятор может оптимизировать, если условия, если вы определяете static const booleans.   -  person    schedule 08.08.2013
comment
Я бы искал cmake, особенно команду configure_file.   -  person arne    schedule 08.08.2013
comment
Вы уверены, что в некоторых случаях не выполняете преждевременную оптимизацию при использовании #define вместо условий выполнения?   -  person    schedule 08.08.2013
comment
Поскольку ваша система сборки в основном уже решает, что возможно, а что нет, не можете ли вы также позволить вашей системе сборки позаботиться о включении/исключении определенных источников? И для заголовков: я серьезно сомневаюсь, что вам нужно знать, везде ли определено SOME_FEATURE_AVAILABLE. Вы можете начать с разделения мега-заголовка на несколько более целенаправленных.   -  person stijn    schedule 08.08.2013
comment
Я поддерживаю предложение cmake. С cmake у меня также есть определения, уже установленные системой сборки (в некоторых случаях). У меня даже cmake не включает файлы cpp и заголовков, которые не понадобятся, если какой-либо параметр отключен.   -  person drescherjm    schedule 08.08.2013
comment
Я рекомендую cmake. У него есть полезная команда для управления определениями: stackoverflow.com/a/9640357/763394   -  person hich9n    schedule 08.08.2013
comment
Спасибо за ваши ответы. Мы строим с помощью IAR (для целевого оборудования) и Visual Studio (для моделирования). Я знаю cmake, но мы не можем его использовать, так как он не поддерживает создание файлов проекта IAR. Они нужны нам для отладки на целевом оборудовании.   -  person woodtluk    schedule 08.08.2013
comment
@ H2CO3: Если вам сойдет с рук придерживаться ANSI C89 (эквивалентно ISO C90) и ISO C++98, это здорово, но тогда есть много специфичных для системы вещей, которые вы не сможете сделать. Например, весь POSIX будет недоступен.   -  person Keith Thompson    schedule 26.08.2013
comment
@KeithThompson, к сожалению. Но иногда это просто неизбежно. Обычно меня не волнует Windows и ее глупость без POSIX и C99, но мой текущий любимый проект написан на строгом C89 ради максимальной переносимости.   -  person    schedule 26.08.2013


Ответы (2)


В случае, если все ваши #define находятся в одном файле конфигурации, вы можете попробовать выполнить компиляцию только для препроцессора, а затем найти все определенные макросы. Например.,

$ gcc -DFEATURE1 -DFEATURE2 -E configuration.h | grep '#define'
person Subhasis Das    schedule 09.08.2013

Возможно, вы захотите прочитать и рассмотреть проектирование на основе политик C++ (http://en.wikipedia.org/wiki/Policy-based_design), представленный Александреску в его книге «Современный дизайн C++».

person JohnB    schedule 25.08.2013
comment
Я предпочитаю шаблон моста проектированию на основе политик: он достигает той же цели без шаблонов или множественного наследования. - person Michael; 25.08.2013
comment
Я предполагаю, что мост берет на себя некоторые накладные расходы во время выполнения (?). Дизайн на основе политик (с использованием шаблонов) не работает. Множественное наследование здесь не вызывает проблем, поскольку вы не обрабатываете объекты как объекты базового класса (не обрабатываете их полиморфно). - person JohnB; 25.08.2013