Обтекание директив #include другими командами препроцессора - PullRequest
1 голос
/ 12 августа 2010

Я работаю над проектом, который использует много внешних библиотек. Теперь мне нравится, когда мои проекты компилируются с наивысшим доступным уровнем предупреждения, который в MSVC равен /W4. Я также использую -Wall в GCC для этого проекта, который должен быть кроссплатформенным.

С /W4 я сталкиваюсь с проблемой: я часто включаю заголовки других библиотек, и эти заголовки не были написаны для соответствия /W4 (то есть они выдают много предупреждений). Я ничего не могу с ними поделать, поэтому я бы предпочел не видеть их. Они просто заканчивают как шум.

В настоящее время я делаю это для временного снижения уровня предупреждения:

#if defined(_MSC_VER)
#   pragma warning( push, 3 )
#endif

#include <SomeExternalHeader.h>

#if defined(_MSC_VER)
#   pragma warning( pop )
#endif

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

INCLUDE_EXTERNAL_HEADER(<SomeExternalHeader.h>)

Это обернет #include необходимыми строками. Это возможно? Мой инстинкт инстинкта подсказывает мне, что это не сработает, потому что это потребует запуска препроцессора дважды.

Как лучше всего решить эту проблему?

Ответы [ 3 ]

3 голосов
/ 12 августа 2010

Я не знаю ни одного однострочного решения, подобного тому, которое вы хотите, но MSVC имеет ключевое слово __pragma , которое вы можете использовать внутри макроса препроцессора.может сделать что-то вроде этого:

#if defined(_MSC_VER)
# define SET_LOWER_WARNING_LEVEL       __pragma(warning(push, 3))
# define RESET_DEFAULT_WARNING_LEVEL   __pragma(warning(pop))
#else 
# define SET_LOWER_WARNING_LEVEL       //gcc directive 
# define RESET_DEFAULT_WARNING_LEVEL   //gcc directive
#endif

SET_LOWER_WARNING_LEVEL
#include "HeaderGeneratingWarnings.h"
RESET_DEFAULT_WARNING_LEVEL

PS: я никогда не использовал форму __pragma, поэтому я не знаю точно, является ли правильный синтаксис директивы pragma выше верным.

1 голос
/ 12 августа 2010

Обернуть ExternalHeader.h в MyExternalHeader.h?

0 голосов
/ 12 августа 2010

К сожалению, я не думаю, что MSVC предоставляет хороший способ справиться с этой проблемой.Я думаю, что вам нужно либо продолжать явно включать / выключать предупреждения, когда эти заголовки включены (возможно, с помощью макросов pragma, чтобы сделать его немного проще , как предложил Преториан ), либо обернуть заголовки в свои собственные заголовки, которыеуправлять уровнем предупреждения.Преимущество второго варианта состоит в том, что его нужно выполнить только один раз.Вы можете сделать это так, чтобы не требовалось изменять каждый файл, который включает в себя исходные заголовки.

Скажите, что HeaderGeneratingWarnings.h находится в каталоге ExtLibDir, который настроен для добавления вашего проекта / make-файлак компилятору включить путь поиска.Одна вещь, которую вы могли бы рассмотреть, это добавить «параллельный» каталог, ExtLibDirWrapper и использовать , что , в конфигурации проекта / make-файла.Пусть он содержит набор заголовков, которые выглядят примерно так:

  • ExtLibDir\HeaderGeneratingWarnings.h:

    #ifndef HEADERGENERATINGWARNINGS_WRAPPER
    #define HEADERGENERATINGWARNINGS_WRAPPER
    
    #if defined(_MSC_VER)
    #   pragma warning( push, 3 )
    #endif
    
    #include "../ExtLibDir/SomeExternalHeader.h"
    
    #if defined(_MSC_VER)
    #   pragma warning( pop )
    #endif
    
    #endif /* HEADERGENERATINGWARNINGS_WRAPPER */
    

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

Кроме того, у GCC есть хороший способ решить эту проблему:

Заголовочные файлы, объявляющие интерфейсы к операционной системе и библиотекам времени выполнения, часто не могут быть записаны в строго соответствующем C. Следовательно, GCC придает коду, найденному в системных заголовках, специальную обработку.Все предупреждения, кроме генерируемых #warning (см. Диагностика), подавляются, пока GCC обрабатывает системный заголовок.Макросы, определенные в системном заголовке, защищены от нескольких предупреждений, где бы они ни были развернуты.Этот иммунитет предоставляется на специальной основе, когда мы обнаруживаем, что предупреждение генерирует много ложных срабатываний из-за кода в макросах, определенных в системных заголовках.

Обычно только заголовки, найденные в определенных каталогах, считаются системнымизаголовки.Эти каталоги определяются при компиляции GCC.Однако есть два способа сделать нормальные заголовки системными заголовками.

Параметр командной строки -isystem добавляет свой аргумент в список каталогов для поиска заголовков, как -I.Любые заголовки, найденные в этом каталоге, будут считаться системными заголовками.

Все каталоги, названные -isystem, ищутся после всех каталогов, названных -I, независимо от их порядка в командной строке.Если один и тот же каталог имеет имена и -I, и -isystem, опция -I игнорируется.GCC выдает информативное сообщение, когда это происходит, если используется -v.

Существует также директива #pragma GCC system_header, которая указывает GCC рассматривать остальную часть текущего включаемого файла как системный заголовок, независимо от того, гдебыло обнаружено.Код, стоящий перед #pragma в файле, не будет затронут.#pragma GCC system_header не влияет на первичный исходный файл.

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