Відповіді:
Так, використовуйте -E -dM
параметри замість -c. Приклад (виводить їх у stdout):
gcc -dM -E - < /dev/null
Для C ++
g++ -dM -E -x c++ - < /dev/null
Замість нормального виводу створіть список директив `#define 'для всіх макросів, визначених під час виконання препроцесора, включаючи попередньо визначені макроси. Це дає вам змогу з’ясувати, що визначено у вашій версії препроцесора. Припустимо, що у вас немає файлу foo.h, команда
touch foo.h; cpp -dM foo.h
покаже всі попередньо визначені макроси
Якщо ви використовуєте -dM без параметра -E, -dM інтерпретується як синонім -fdump-rtl-mach.
echo | gcc -dM -E -
працює і на Windows.
cpp -dM -E - < NUL
можна використовувати.
Я зазвичай роблю це так:
$ 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
Пізня відповідь - я знайшов інші відповіді корисними - і хотів додати трохи зайвих.
Як скинути макроси препроцесора, що надходять із певного заголовкового файлу?
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
$
Простий підхід ( 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
.
-x
аргумент, так що g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cpp
має працювати.
Портативний підхід, який однаково добре працює в 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
опцією.
NUL
, ви повертаєтеся до квадратного: він не працюватиме в системах, у яких його немає.
sort
поводиться трохи інакше):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Працюючи у великому проекті, який має складну систему збирання і де важко отримати (або змінити) команду gcc / g ++ безпосередньо, є інший спосіб побачити результат розширення макросу. Просто переозначте макрос, і ви отримаєте вихід подібний наступному:
file.h: note: this is the location of the previous definition
#define MACRO current_value