-Werror заставляет компилятор останавливаться на #warning. Что я могу сделать, чтобы предотвратить это?
Прежде всего, я хочу остановиться на предупреждениях. Но я также хочу распечатать некоторые информативные сообщения (например, "Вернись и реализуй это!").
К сожалению, мой компилятор не поддерживает #info
, #message
, #pragma message()
, так далее.
Я знаю, что есть -Wno-error=<something>
, но мой Google-Foo слаб, и я не могу выяснить, <something>
за #warning
, я пробовал -Wno-error=warning
и это просто говорит "нет -Wwarning
"То же самое с"warn
".
Какие-либо предложения?
Для чего это стоит, я использую компилятор Tensilica xtensa, xt-xcc, который, кажется, является производным от gnu, или, по крайней мере, использует внешний интерфейс gnu. Это версия 8.0.0.
7 ответов
Я не знаком с компилятором Tensilica xtensa (xt-xcc
), но со стандартным gcc
ты можешь использовать
#pragma GCC diagnostic warning "-Wcpp"
делать #warning
вопрос простого предупреждения (не ошибка из-за -Werror
). Чтобы сделать эффект временным, вы можете принять это #pragma
и #warning
между #pragma GCC diagnostic push
а также #pragma GCC diagnostic pop
,
Когда я компилирую файл, содержащий следующее
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wcpp"
#warning one
#pragma GCC diagnostic pop
#warning two
с -Werror
с помощью gcc
4.6.1 (команда gcc -c -Werror warning-test.c
), Я получаю следующий вывод:
warning-test.c:3:2: warning: #warning one [-Wcpp]
warning-test.c:6:2: error: #warning two [-Werror=cpp]
cc1: all warnings being treated as errors
Когда я удаляю второй #warning
Компиляция не прервана по ошибке.
Вы также можете заменить свой -Werror
параметры компилятора с -Werror -Wno-error=cpp
, Я не знаю, какие еще последствия cpp
категория предупреждений включает в себя (и вы можете иметь законный #warning
в другом месте, которое вы хотите отловить как ошибку), поэтому временно отключите ошибку для определенного #warning
и восстановление настроек сразу после этого кажется более точным способом удовлетворения ваших требований.
Редактировать (2016): Использование gcc
версии 4.8.4 и 4.9.2 обеспечивают почти то же самое поведение (дополнительно выводится только исходная строка). Но используя gcc
версия 5.0.1 (предварительная версия включена в Ubuntu 15.04) выдаст два предупреждения, если не выбрана опция -Werror=cpp
также включен. Так что кажется, что -Werror
с более новым gcc больше не подразумевается -Werror=cpp
как прежде, и это должно быть предоставлено отдельно при желании.
Десять лет спустя правильный способ выдачи предупреждений и предотвращения этих дополнительных сообщений/ошибок от -Wpedantic заключается в использовании
#pragma message
. GCC поддерживает этот синтаксис, по крайней мере, с GCC 4.5 , а Clang, по крайней мере, с Clang6.
Современные версии этих компиляторов даже поддерживают
#pragma GCC error "message"
и
#pragma GCC warning "message"
( GCC 9 , уже поддерживается в Clang 6).
К сожалению, нет ответа на мой конкретный набор инструментов, или так говорят инженеры Tensilica. Они не поддерживают #message, #pramga message() и не знают, как подавить #warning как ошибку при наличии -Werror.
Набор инструментов GCC позволяет использовать -Wno-error=[code], чтобы сказать "это предупреждение НЕ ошибка", но я не нашел список, который #warning соответствует любому коду, который это примет (или даже список коды это могло быть)
Я могу попытаться найти время, чтобы вникнуть в стандартные командные строки GCC и исходный код препроцессора, чтобы попытаться найти список того, чему может быть равен -Wno-error =, или есть или нет код -Werror=, который соответствует # предупреждению. Если я это сделаю, я вернусь и обновлю ответ.
Учитывая, что #warning предположительно обрабатывается препроцессором, вы можете запустить препроцессор отдельно без -Werror, а затем запустить компилятор с предварительной обработкой, запрещенной на выходе препроцессора.
Для этого запустите файл.c через препроцессор со всеми обычными параметрами, кроме -Werror, и сгенерируйте вывод в виде файла.i (.ii для C++). Компилятор распознает эти файлы как не подлежащие предварительной обработке, поэтому вы можете скомпилировать их с помощью -Werror, и при условии, что препроцессор отбрасывает #warning и он не обрабатывается самим компилятором, это может решить вашу проблему.
Я не проверял это; когда я столкнулся с той же проблемой, я просто решил жить с ней и не использовать -Werror. Решение казалось более сложным, чем проблема!
Что случилось с:
#warning "Come back and implement this"
#warning "Do not do that!"
#warning "Must fix this before release"
Обычно компилятор включает аргумент (ы) до - или материал после - #warning
в сообщении об ошибке или предупреждении.
И, как правило, если компилятор обнаруживает что-то, что оправдывает предупреждение, он сообщает об этом довольно четко.
Учитывая требования, я думаю, что единственный способ справиться с этим - защитить #warning
директивы...
#ifdef DO_WARNINGS
#warning "Some warning"
#endif /* DO_WARNINGS */
Большую часть времени вы компилируете без -DDO_WARNINGS
; когда вам нужно проверить на #warning
предупреждения (с -Werror
), то вы включаете -DDO_WARNINGS
в конце концов, принимая, что компиляция не удастся. Помни что make -k
будет делать как можно больше даже при наличии отдельных ошибок компиляции.
Раздел 5.52.9 руководства GCC 4.4.1 гласит (частично):
5.52.9 Диагностические Прагмы
GCC позволяет пользователю выборочно включать или отключать определенные типы диагностики и изменять вид диагностики. Например, политика проекта может требовать, чтобы все источники компилировались с "-Werror", но в некоторых файлах могут быть исключения, допускающие определенные типы предупреждений. Или проект может выборочно включить диагностику и рассматривать ее как ошибки, в зависимости от того, какие макросы препроцессора определены.
#pragma GCC diagnostic kind option
Изменяет расположение диагностики. Обратите внимание, что не все диагностики могут быть изменены; на данный момент можно контролировать только предупреждения (обычно контролируемые "-W..."), но не все из них. Используйте '-fdiagnostics-show-option', чтобы определить, какие диагностики являются управляемыми, а какая опция управляет ими. kind - это "error", чтобы рассматривать эту диагностику как ошибку, "warning", чтобы рассматривать ее как предупреждение (даже если действует "-Werror"), или "ignored", если диагностика должна игнорироваться. option - это строка в двойных кавычках, которая соответствует опции командной строки.
#pragma GCC diagnostic warning "-Wformat" #pragma GCC diagnostic error "-Wformat" #pragma GCC diagnostic ignored "-Wformat"
Обратите внимание, что эти прагмы переопределяют любые параметры командной строки. Кроме того, хотя синтаксически допустимо размещать эти прагмы в любом месте ваших источников, единственное поддерживаемое расположение для них - до того, как будут определены какие-либо данные или функции. В противном случае это может привести к непредсказуемым результатам в зависимости от того, как оптимизатор управляет вашими источниками. Если один и тот же параметр указан несколько раз, последним указанным является действующий. Эта прагма предназначена не для универсальной замены опций командной строки, а для строгого контроля над политиками проекта.
GCC также предлагает простой механизм для печати сообщений во время компиляции.
#pragma message string
Печатает строку как сообщение компилятора при компиляции. Сообщение носит исключительно информационный характер и не является ни предупреждением компиляции, ни ошибкой.
#pragma message "Compiling " __FILE__ "..."
Строка может быть заключена в скобки и напечатана с информацией о местоположении.
Я не уверен, хотите ли вы редактировать свой #warning
линии в #pragma message
линий. Это поможет вам решить проблему - и это только хуже, чем добавление условной компиляции вокруг #warning
в этом #pragma message
может поддерживаться меньшим количеством компиляторов. Это зависит от ваших требований к мобильности.
Если ваш компилятор поддерживает это, вы можете попробовать использовать constructor
Атрибут function для определения функции, которая запускается при запуске программы (до main
) который выводит сообщение на стандартный вывод:
#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
#define TOKENPASTE2(x, y) x ## y
#define WARNING(message) \
static void TOKENPASTE(_print_warning, __LINE__)() __attribute__((constructor)); \
static void TOKENPASTE(_print_warning, __LINE__)() \
{ \
puts(message); \
}
WARNING("fix this before ship") // prints out a message at runtime before main
Это приводит к тому, что сообщение выводится во время выполнения, а не во время компиляции, что почти так же хорошо, особенно если у вас нет других вариантов. Единственное ограничение заключается в том, что вы должны использовать это в глобальной области действия вне определения функции.
G++ (11 и 12) не поддерживает эквивалент и предлагает использовать
Единственная проблема может заключаться в том, чтобы ваш инструмент сборки обработал хэш, чтобы он попал в компилятор...