2010-02-08 27 views
197

Czy istnieje sposób dla polecenia gcc/g ++ do zrzutu jego definicji preprocesora z wiersza poleceń? Mam na myśli rzeczy takie jak __GNUC__, __STDC__ i tak dalej.Procesor zrzutu GCC definiuje

Odpowiedz

235

Tak, użyj opcji -E -dM zamiast -c. Przykład (wysyła je na standardowe wyjście):

gcc -dM -E - < /dev/null 

Z gcc manual:

zamiast normalnego wyjścia, generują listę dyrektyw `#define” dla wszystkich makr określonego w czasie wykonanie preprocesora, , w tym predefiniowane makra. Ten numer pozwala określić, co jest wstępnie zdefiniowane w Twojej wersji preprocesora . Zakładając, że nie masz Foo.h pliku, polecenie

touch foo.h; cpp -dM foo.h 

pokaże wszystkie predefiniowanych makr.

Jeśli użyjesz -dM bez opcji -E, -dM zostanie zinterpretowane jako synonim dla -fdump-rtl-mach.

+2

gcc istnieje w systemach gdzie/dev/null nic nie znaczy. – Pavel

+3

@Pavel to możesz użyć pustego pliku z gcc lub preprocesorem - cpp. – philant

+15

Dodałem bardziej przenośne podejście jako alternatywną odpowiedź: 'echo | gcc -dM -E-'działa również na oknach. – Pavel

71

zwykle zrobić to w ten sposób:

$ gcc -dM -E - < /dev/null 

pamiętać, że niektóre definiuje preprocesora są zależne od opcji wiersza poleceń - można testować je przez dodanie odpowiednich opcji do powyższej linii poleceń. Na przykład, aby zobaczyć, które SSE3/SSE4 opcje są domyślnie włączone:

$ gcc -dM -E - < /dev/null | grep SSE[34] 
#define __SSE3__ 1 
#define __SSSE3__ 1 

a następnie porównać to kiedy -msse4 jest określona:

$ 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żna sprawdzić, które opcje różnią się między dwoma różnymi zestawami opcje wiersza poleceń, np porównać preprocesor definiuje poziomów optymalizacji -O0 (brak) i -O3 (pełna):

$ 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 
35

Późna odpowiedź - Znalazłem inne odpowiedzi użyteczne - i chciał dodać trochę ekstra.


Jak mogę zrzucić makr preprocesora pochodzących z określonego pliku nagłówka?

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

W szczególności chciałem zobaczyć co somaxconn została zdefiniowana w moim systemie. Wiem, że mógłbym otworzyć standardowy plik nagłówkowy, ale czasami muszę trochę przeszukać, aby znaleźć lokalizacje plików nagłówkowych.Zamiast tego można po prostu użyć tego jednego-liner:

$ echo "#include <sys/socket.h>" | gcc -E -dM - | grep SOMAXCONN 
#define SOMAXCONN 128 
$ 
15

bardziej przenośne podejście, które działa równie dobrze na Windows (gdzie nie ma/dev/null) lub Linux:

echo | gcc -dM -E - 
+5

@rubenvb to nieistotne. chodzi o to, żeby mieć linię cmd, która działa równie dobrze na Windowsie i co najmniej w systemie UNIX. Jeśli użyjesz 'NUL', powrócisz do pierwszego: nie będzie działać na systemach, które go nie mają. – Pavel

+0

dodanie pełnej odpowiedzi dla C++, działa zarówno w systemie Windows, jak i Linux (chociaż 'sort' zachowuje się trochę inaczej):' echo | gcc -x C++ -std = C++ 17 -dM -E - | sort' – Xeverous

25

Prosta podejście (gcc -dM -E - < /dev/null) działa poprawnie dla gcc, ale kończy się niepowodzeniem dla g ++. Ostatnio wymagałem testu dla funkcji C++ 11/C++ 14. Zalecenia dotyczące odpowiednich nazw makr są publikowane pod adresem 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ż cicho przywołuje-kierowców C (jeśli wywołany przez gcc). Można to zobaczyć, porównując jego wyniki z wynikami gcc lub dodając opcję wiersza poleceń w języku g ++, jak np. (-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.

Bo (non C++) gcc będzie nigdy wsparcie „Szablony Pseudonimy” (patrz http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf) należy dodać opcję -x c++ wymusić wywołanie kompilatora C++ (kredyty dla używając opcji -x c++ zamiast pustego manekina file iść do yuyichao, patrz niżej):

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

nie będzie wyjście ponieważ g ++ (wersja 4.9.1, domyślnie -std = gnu ++ 98) nie pozwala C++ 11-funkcje domyślnie . Aby to zrobić, należy użyć

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

co ostatecznie daje

#define __cpp_alias_templates 200704 

zauważając, że g ++ 4.9.1 nie obsługuje aliasów "Szablony" przy wywołaniu z -std=c++11.

+6

Nie musisz używać pliku dummy. GCC obsługuje argument '-x', więc' g ++ -x C++ -dM -E -std = C++ 11 - yuyichao

+0

@yuyichao Dziękuję, to ułatwia korzystanie. Nie wiedziałem o opcji -x. Wznowiono komentarz i zintegrowałem go z oryginalną odpowiedzią. – hermannk

0

Podczas pracy w dużym projekcie, który ma skomplikowany system kompilacji i gdzie trudno jest uzyskać (lub zmodyfikować) bezpośrednio polecenie gcc/g ++, istnieje inny sposób, aby zobaczyć wynik rozszerzenia makr. prostu przedefiniować makro, a otrzymasz wyjściowe podobne do następujących:

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