Есть ли способ, чтобы gcc/g++ удалял его препроцессор из командной строки?
Я имею в виду такие вещи, как __GNUC__
, __STDC__
и т.д.
Препроцессор дампа GCC определяет
Ответ 1
Да, используйте опции -E -dM
вместо -c.
Пример (выводит их в стандартный вывод):
gcc -dM -E - < /dev/null
Из руководства gcc:
Вместо нормального вывода, сгенерируйте список директив `#define 'для всех макросы, определенные во время выполнение препроцессора, включая предопределенные макросы. Эта дает вам способ узнать, что такое предопределено в вашей версии препроцессор. Предполагая, что у вас нет файл foo.h, команда
touch foo.h; cpp -dM foo.h
отобразит все предопределенные макросы.
Если вы используете -dM без опции -E, -dM интерпретируется как синоним -fdump-rtl-mach.
Ответ 2
Обычно я делаю так:
$ gcc -dM -E - < /dev/null
Обратите внимание, что некоторые параметры препроцессора зависят от параметров командной строки - вы можете протестировать их, добавив соответствующие параметры в приведенную выше командную строку. Например, чтобы увидеть, какие опции SSE3/SSE4 включены по умолчанию:
$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1
а затем сравните это значение, если указано -msse4
:
$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1
Аналогичным образом вы можете видеть, какие опции различаются между двумя различными наборами параметров командной строки, например. сравнить препроцессор для уровней оптимизации -O0
(none) и -O3
(полный):
$ gcc -dM -E -O0 - < /dev/null > /tmp/O0.txt
$ gcc -dM -E -O3 - < /dev/null > /tmp/O3.txt
$ sdiff -s /tmp/O0.txt /tmp/O3.txt
#define __NO_INLINE__ 1 <
> #define __OPTIMIZE__ 1
Ответ 3
Поздний ответ - я нашел другие ответы полезными - и хотел добавить немного лишний.
Как сбрасывать макросы препроцессора из определенного файла заголовка?
echo "#include <sys/socket.h>" | gcc -E -dM -
В частности, мне хотелось узнать, что SOMAXCONN было определено для моей системы. Я знаю, что могу просто открыть стандартный заголовочный файл, но иногда мне приходится немного искать его, чтобы найти расположение файлов заголовков. Вместо этого я могу просто использовать этот однострочный слой:
$ echo "#include <sys/socket.h>" | gcc -E -dM - | grep SOMAXCONN
#define SOMAXCONN 128
$
Ответ 4
Простой подход (gcc -dM -E - < /dev/null
) отлично работает для gcc, но не подходит для g++. Недавно мне потребовался тест для С++ 11/С++ 14. Рекомендации по их соответствующим именам макросов опубликованы в https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations. Но:
g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates
всегда терпит неудачу, потому что он молча вызывает C-драйверы (как будто вызывается gcc
). Вы можете увидеть это, сравнив его вывод с файлом gcc или добавив параметр командной строки g++, подобный (-std = С++ 11), который испускает сообщение об ошибке cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
.
Поскольку (не С++) gcc будет никогда поддерживать "псевдонимы шаблонов" (см. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf), вы должны добавить -x c++
, чтобы принудительно вызвать вызов компилятора С++ (Кредиты для использования опций -x c++
вместо пустого фиктивного файла идут в yuyichao, см. ниже):
g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates
Не будет выхода, потому что g++ (версия 4.9.1, по умолчанию - -std = gnu ++ 98) не включает С++ 11-функции по умолчанию. Для этого используйте
g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates
что, наконец, дает
#define __cpp_alias_templates 200704
отметив, что g++ 4.9.1 поддерживает "псевдонимы шаблонов" при вызове -std=c++11
.
Ответ 5
Портативный подход, который одинаково хорошо работает в Linux или Windows (где нет /dev/null):
echo | gcc -dM -E -
Для c++ вы можете использовать (замените c++11
любой версией, которую вы используете):
echo | gcc -x c++ -std=c++11 -dM -E -
Он работает, указывая gcc на preprocess stdin (который создается эхом) и печатает все препроцессоры (поиск по -dletters
). Если вы хотите знать, какие определения добавляются при включении файла заголовка, вы можете использовать -dD
которая аналогична -dM, но не включает предопределенные макросы:
echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -
Однако обратите внимание, что пустой ввод по-прежнему создает множество -dD
опцией -dD
.
Ответ 6
При работе в большом проекте, который имеет сложную систему сборки и где трудно получить (или изменить) команду gcc/g++, есть еще один способ увидеть результат расширения макроса. Просто переопределите макрос, и вы получите вывод, похожий на следующий:
file.h: note: this is the location of the previous definition
#define MACRO current_value