GCC дамп-препроцесор визначає


248

Чи є спосіб для gcc / g ++ скинути свій препроцесор, визначений з командного рядка? Я маю в виду такі речі , як __GNUC__, __STDC__і так далі.

Відповіді:


304

Так, використовуйте -E -dMпараметри замість -c. Приклад (виводить їх у stdout):

 gcc -dM -E - < /dev/null

Для C ++

 g++ -dM -E -x c++ - < /dev/null

З посібника з gcc :

Замість нормального виводу створіть список директив `#define 'для всіх макросів, визначених під час виконання препроцесора, включаючи попередньо визначені макроси. Це дає вам змогу з’ясувати, що визначено у вашій версії препроцесора. Припустимо, що у вас немає файлу foo.h, команда

touch foo.h; cpp -dM foo.h

покаже всі попередньо визначені макроси

Якщо ви використовуєте -dM без параметра -E, -dM інтерпретується як синонім -fdump-rtl-mach.


4
gcc існує в системах, де / dev / null нічого не означає.
Павло П

4
@Pavel, тоді ви можете використовувати порожній файл, або з gcc, або з препроцесором - cpp.
благодійник

16
Як альтернативну відповідь я додав більш портативний підхід: echo | gcc -dM -E -працює і на Windows.
Павло П

4
Чи можна визначити, звідки (тобто, у якому файлі) ці визначення взяли?
edam

2
Крім того, у Windows cpp -dM -E - < NULможна використовувати.
Рене Ніффенеггер

78

Я зазвичай роблю це так:

$ 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(немає) та -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

45

Пізня відповідь - я знайшов інші відповіді корисними - і хотів додати трохи зайвих.


Як скинути макроси препроцесора, що надходять із певного заголовкового файлу?

echo "#include <sys/socket.h>" | gcc -E -dM -

або (спасибі @mymedia за пропозицію):

gcc -E -dM -include sys/socket.h - < /dev/null

Зокрема, я хотів побачити, для чого визначено SOMAXCONN у моїй системі. Я знаю, що міг би просто відкрити стандартний файл заголовка, але іноді мені доводиться трохи обшукати, щоб знайти розташування файлів заголовка. Натомість я можу просто використовувати цей однопластовий:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 

1
ви можете використовувати -include компілятор варіант, щоб уникнути труб
mymedia

31

Простий підхід ( gcc -dM -E - < /dev/null) працює чудово для gcc, але не вдається для g ++. Нещодавно мені знадобився тест на функцію C ++ 11 / C ++ 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 = c ++ 11), який видає повідомлення про помилку cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Оскільки (не для C ++) gcc ніколи не підтримує "Шаблони Псевдоніми" (див. Http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ), ви повинні додати -x c++параметр до змусити -x c++викликати компілятор C ++ (Кредити для використання опцій замість порожнього макетного файлу перейдіть до yuyichao, див. нижче):

g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates

Виведення не буде, оскільки g ++ (версія 4.9.1, за замовчуванням до -std = gnu ++ 98) не дозволяє за замовчуванням функцій C ++ 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.


7
Не потрібно використовувати фіктивний файл. GCC підтримує -xаргумент, так що g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppмає працювати.
yuyichao

@yuyichao Дякую, це полегшує використання. Мені не було відомо про варіант -x. Оголосив ваш коментар і інтегрував його в оригінальну відповідь.
hermannk

23

Портативний підхід, який однаково добре працює в Linux або Windows (де немає / dev / null):

echo | gcc -dM -E -

Для c ++ ви можете використовувати (замінити c++11будь-якою версією, яку ви використовуєте):

echo | gcc -x c++ -std=c++11 -dM -E -

Він працює, повідомляючи gcc попередньому обробці stdin (який виробляється echo) та друкує всі визначені препроцесором (пошук -dletters). Якщо ви хочете знати, що визначені дані додаються при включенні файлу заголовка, ви можете використовувати -dDпараметр, схожий на -dM, але не включає попередньо визначені макроси:

echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -

Однак зауважте, що порожній вхід все ще виробляє багато визначень з -dDопцією.


6
@rubenvb це не має значення. сенс у тому, щоб мати cmd-лінію, яка однаково добре працює як мінімум на windows та unix. Якщо ви користуєтеся NUL, ви повертаєтеся до квадратного: він не працюватиме в системах, у яких його немає.
Павло П

2
додавши повну відповідь на C ++, працює і в Windows, і в Linux (хоча sortповодиться трохи інакше):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous

Це дає порожній вихід у git-bash.
Леннарт Ролланд

@LennartRolland в ньому є gcc? У своєму git-bash я не можу запустити gcc
Pavel P

@pavel Я використовую mingw32 gcc, який постачається з бінарним розподілом Qt5 для Windows.
Леннарт Ролланд

3

Працюючи у великому проекті, який має складну систему збирання і де важко отримати (або змінити) команду gcc / g ++ безпосередньо, є інший спосіб побачити результат розширення макросу. Просто переозначте макрос, і ви отримаєте вихід подібний наступному:

file.h: note: this is the location of the previous definition
#define MACRO current_value

Я шукаю, який попереджувальний прапор використовується для нього. Чи ти знаєш ?
Welgriv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.