Показывать сообщение #pragma в заголовке только один раз во время сборки

У меня есть куча #pragma message("A message") в заголовке config.h, который включается во многие места проекта; цель состоит в том, чтобы сообщить, какие параметры конфигурации выбраны во время сборки. Заголовок защищен заголовком в стиле #ifndef #define. Проблема в том, что каждый раз, когда этот заголовок включается, сообщение печатается. Есть ли лучший способ сделать это, чтобы сообщение печаталось только один раз во время сборки?

Редактировать: я понимаю, что параметры сборки обычно манипулируются и просматриваются с помощью инструментов сборки, таких как cmake, qmake, autotools и т. д., но на самом деле у меня нет выбора инструментов сборки из-за характера проект.


person Ayberk Özgür    schedule 08.06.2016    source источник
comment
Насколько я знаю, это невозможно с #pragma message   -  person Hatted Rooster    schedule 08.06.2016
comment
Вы должны иметь возможность передавать информацию о том, что сообщение было напечатано, между различными единицами компиляции. Это кажется неоправданно сложным. Я бы предпочел написать скрипт для фильтрации повторяющихся строк из вывода.   -  person Lærne    schedule 08.06.2016
comment
@GillBates, какое может быть другое решение, позволяющее печатать параметры конфигурации во время сборки?   -  person Ayberk Özgür    schedule 08.06.2016
comment
Так что же такое есть инструменты сборки? Например, это не очень сложно с GNU make, или даже если система сборки представляет собой просто сценарий оболочки. Возможно, уточнить ваши теги?   -  person Mike Kinghan    schedule 08.06.2016
comment
@MikeKinghan Инструменты сборки являются собственностью Microchip и уже довольно сломаны и нестабильны. Я бы не осмелился изолировать или состряпать сценарии для собственного использования, которые интегрируют их инструменты. Я согласен с тем, что, возможно, любой (частичный) ответ на эту конкретную проблему не будет полезен в целом или даже ситуация ничем не поможет, поскольку печать этого типа сообщения не является задачей компилятора.   -  person Ayberk Özgür    schedule 21.06.2016


Ответы (2)


Вы можете поместить #pragma message в отдельный файл, который вы включаете только один раз из config.h. gcc может печатать эти прагмы, даже находясь внутри ложного условного выражения, но он не будет включать файл из ложного условного выражения. Итак, что-то вроде этого:

/* config.h */
#ifndef CONFIG_H
#define CONFIG_H

#ifndef CONFIG_MESSAGE_PRINTED
#define CONFIG_MESSAGE_PRINTED
#include "config_message.h"
#endif

/* ... */
#endif /* CONFIG_H */

In config_message.h:

#pragma message("A message")
person fuz    schedule 08.06.2016
comment
Почему CONFIG_MESSAGE_PRINTED include guard ведет себя не так, как CONFIG_H? - person Karsten Koop; 08.06.2016
comment
@KarstenKoop Это не так, но директивы include внутри ложных условий игнорируются. - person fuz; 08.06.2016
comment
Я думаю, что его проблема заключается не в нескольких включениях из одной и той же единицы компиляции, а в том, что разные единицы компиляции с одним и тем же включением создают одно и то же сообщение. Но поскольку из вопроса не совсем ясно, он также может иметь в виду ту же единицу компиляции, и в этом случае ваш ответ может быть полезен. - person Karsten Koop; 08.06.2016
comment
Мой ответ гарантирует, что файл, содержащий прагму сообщения, включается только один раз. Это гарантирует, что он будет напечатан только один раз. - person fuz; 08.06.2016
comment
@FUZxxl Я думаю, проблема в нескольких единицах компиляции, потому что это не работает, сообщения по-прежнему печатаются несколько раз. - person Ayberk Özgür; 08.06.2016
comment
@AyberkÖzgür Да, каждый вызов компилятора выводит сообщение один раз. Что ты ожидал? - person fuz; 08.06.2016

Вдохновленный @fuz, возможно, мы можем написать #pragma message в отдельном файле .c. Вот пример:

/* config.h */
#ifndef CONFIG_H
#define CONFIG_H

#define CONFIG_OPTION_A
#define CONFIG_OPTION_B

#endif /* CONFIG_H */

Записывайте сообщения в файл .c:

/* config_msg.c */
#include "config.h"

#ifdef CONFIG_OPTION_A
#pragma message "Config option A is enabled!"
#endif

#ifdef CONFIG_OPTION_C
#pragma message "Config option C is enabled!"
#endif

Наконец, добавьте зависимость компиляции в Makefile (то есть config_msg.o):

/* Makefile */
.PHONY: all
%.o: %.c
    gcc -c -o $@ $<
config_msg.o: config_msg.c config.h
    gcc -c -o $@ $<
all: main.o config_msg.o
    gcc -o main $^

Пока config.h изменяется, config_msg.o будет перекомпилироваться и печатать содержащиеся в нем сообщения. (Добавление config.h к зависимостям Rule config_msg.o необходимо. И это также зависит от более высокого приоритета Rule config_msg.o, чем Rule %.o. Поправьте меня, если я ошибаюсь.)

Вот тест:

$ make all
gcc -c -o main.o main.c
gcc -c -o config_msg.o config_msg.c
config_msg.c:4:9: warning: Config option A is enabled! [-W#pragma-messages]
#pragma message "Config option A is enabled!"
        ^
1 warning generated.
gcc -o main main.o config_msg.o
$ make all
gcc -o main main.o config_msg.o

Выполнить после добавления #define CONFIG_OPTION_C к config.h:

$ make all
gcc -c -o config_msg.o config_msg.c
config_msg.c:4:9: warning: Config option A is enabled! [-W#pragma-messages]
#pragma message "Config option A is enabled!"
        ^
config_msg.c:8:9: warning: Config option C is enabled! [-W#pragma-messages]
#pragma message "Config option C is enabled!"
        ^
2 warnings generated.
gcc -o main main.o config_msg.o

Я не думаю, что это идеальное решение. Но надеюсь поможет. :)

person mkvoya    schedule 20.12.2016