Odpowiedzi:
Tak, użyj -E -dM
opcji zamiast -c. Przykład (wyprowadza je na standardowe wyjście):
gcc -dM -E - < /dev/null
Dla C ++
g++ -dM -E -x c++ - < /dev/null
Z podręcznika gcc :
Zamiast normalnego wyjścia wygeneruj listę dyrektyw `#define 'dla wszystkich makr zdefiniowanych podczas wykonywania preprocesora, w tym predefiniowanych makr. To pozwala ci dowiedzieć się, co jest wstępnie zdefiniowane w twojej wersji preprocesora. Zakładając, że nie masz pliku foo.h, polecenie
touch foo.h; cpp -dM foo.h
pokaże wszystkie predefiniowane makra.
Jeśli użyjesz -dM bez opcji -E, -dM jest interpretowany jako synonim -fdump-rtl-mach.
echo | gcc -dM -E -
działa również w systemie Windows.
cpp -dM -E - < NUL
można użyć.
Zwykle robię to w ten sposób:
$ gcc -dM -E - < /dev/null
Zauważ, że niektóre definicje preprocesora zależą od opcji wiersza poleceń - możesz je przetestować, dodając odpowiednie opcje do powyższego wiersza poleceń. Na przykład, aby zobaczyć, które opcje SSE3 / SSE4 są domyślnie włączone:
$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1
a następnie porównaj to, gdy -msse4
określono:
$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1
Podobnie możesz zobaczyć, które opcje różnią się między dwoma różnymi zestawami opcji wiersza poleceń, np. Porównaj definicje preprocesora dla poziomów optymalizacji -O0
(brak) i -O3
(pełny):
$ 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
Późna odpowiedź - uznałem inne odpowiedzi za przydatne - i chciałem dodać trochę więcej.
Jak zrzucić makra preprocesora pochodzące z określonego pliku nagłówka?
echo "#include <sys/socket.h>" | gcc -E -dM -
lub (dzięki @mymedia za sugestię):
gcc -E -dM -include sys/socket.h - < /dev/null
W szczególności chciałem zobaczyć, co SOMAXCONN został zdefiniowany w moim systemie. Wiem, że mogłem po prostu otworzyć standardowy plik nagłówka, ale czasami muszę się trochę rozejrzeć, aby znaleźć lokalizację pliku nagłówka. Zamiast tego mogę po prostu użyć tej linijki:
$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$
Proste podejście ( gcc -dM -E - < /dev/null
) działa dobrze w przypadku gcc, ale nie działa w przypadku g ++. Ostatnio wymagałem testu funkcji C ++ 11 / C ++ 14. Zalecenia dotyczące odpowiadających im nazw makr są publikowane na stronie https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations . Ale:
g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates
zawsze kończy się niepowodzeniem, ponieważ po cichu wywołuje sterowniki C (tak jakby były wywoływane przez gcc
). Można to zobaczyć, porównując dane wyjściowe z gcc lub dodając opcję wiersza polecenia specyficzną dla g ++, taką jak (-std = c ++ 11), która emituje komunikat o błędzie cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
.
Ponieważ gcc (inne niż C ++) nigdy nie będzie obsługiwał „Aliasów szablonów” (patrz http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ), musisz dodać -x c++
opcję do -x c++
wymuś wywołanie kompilatora C ++ (Kredyty za korzystanie z opcji zamiast pustego pliku zastępczego przejdź do yuyichao, patrz poniżej):
g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates
Nie będzie danych wyjściowych, ponieważ g ++ (wersja 4.9.1, domyślnie -std = gnu ++ 98) domyślnie nie włącza funkcji C ++ 11. Aby to zrobić, użyj
g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates
co ostatecznie ustępuje
#define __cpp_alias_templates 200704
zauważając, że g ++ 4.9.1 obsługuje po wywołaniu „Alias szablonów” -std=c++11
.
-x
argument, więc g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cpp
powinno działać.
Przenośne podejście, które działa równie dobrze w systemie Linux lub Windows (gdzie nie ma / dev / null):
echo | gcc -dM -E -
W przypadku c ++ możesz użyć (zamień na c++11
dowolną używaną wersję):
echo | gcc -x c++ -std=c++11 -dM -E -
Działa, mówiąc gcc, aby wstępnie przetworzył standardowe wejście (które jest wytwarzane przez echo) i wypisał wszystkie definicje preprocesora (wyszukaj -dletters
). Jeśli chcesz wiedzieć, jakie definicje są dodawane po dołączeniu pliku nagłówka, możesz użyć -dD
opcji podobnej do -dM, ale nie zawierającej predefiniowanych makr:
echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -
Należy jednak pamiętać, że puste dane wejściowe nadal generują wiele definicji z -dD
opcją.
NUL
, wrócisz do punktu wyjścia: nie będzie działać na systemach, które go nie mają.
sort
zachowuje się trochę inaczej):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Podczas pracy w dużym projekcie, który ma złożony system kompilacji i gdzie trudno jest uzyskać (lub zmodyfikować) polecenie gcc / g ++ bezpośrednio, istnieje inny sposób, aby zobaczyć wynik ekspansji makr. Po prostu przedefiniuj makro, a otrzymasz wynik podobny do następującego:
file.h: note: this is the location of the previous definition
#define MACRO current_value