GCC-Dump-Präprozessor definiert

Antworten:

304

Ja, verwenden Sie -E -dMOptionen anstelle von -c. Beispiel (gibt sie an stdout aus):

 gcc -dM -E - < /dev/null

Für C ++

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

Aus dem gcc-Handbuch :

Generieren Sie anstelle der normalen Ausgabe eine Liste der Direktiven "#define" für alle Makros, die während der Ausführung des Präprozessors definiert wurden, einschließlich vordefinierter Makros. Auf diese Weise können Sie herausfinden, was in Ihrer Version des Präprozessors vordefiniert ist. Angenommen, Sie haben keine Datei foo.h, den Befehl

touch foo.h; cpp -dM foo.h

zeigt alle vordefinierten Makros an.

Wenn Sie -dM ohne die Option -E verwenden, wird -dM als Synonym für -fdump-rtl-mach interpretiert.

Philant
quelle
4
gcc existiert auf Systemen, auf denen / dev / null nichts bedeutet.
Pavel P
4
@Pavel dann können Sie eine leere Datei verwenden, entweder mit gcc oder dem Präprozessor - cpp.
Philant
16
Als alternative Antwort habe ich einen portableren Ansatz hinzugefügt: Funktioniert auch echo | gcc -dM -E -unter Windows.
Pavel P
4
Ist es möglich festzustellen, woher (dh in welcher Datei) diese Definitionen stammen?
Edam
2
Alternativ kann unter Windows cpp -dM -E - < NULverwendet werden.
René Nyffenegger
78

Normalerweise mache ich das so:

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

Beachten Sie, dass einige Präprozessordefinitionen von Befehlszeilenoptionen abhängen. Sie können diese testen, indem Sie die entsprechenden Optionen zur obigen Befehlszeile hinzufügen. So sehen Sie beispielsweise, welche SSE3 / SSE4-Optionen standardmäßig aktiviert sind:

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

und vergleichen Sie dies dann, wenn -msse4angegeben:

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

In ähnlicher Weise können Sie sehen, welche Optionen sich zwischen zwei verschiedenen Sätzen von Befehlszeilenoptionen unterscheiden, z. B. Präprozessordefinitionen für Optimierungsstufen vergleichen -O0(keine) und -O3(vollständig):

$ 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
Paul R.
quelle
45

Späte Antwort - ich fand die anderen Antworten nützlich - und wollte ein bisschen mehr hinzufügen.


Wie speichere ich Präprozessor-Makros, die aus einer bestimmten Header-Datei stammen?

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

oder (danke an @mymedia für den Vorschlag):

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

Insbesondere wollte ich sehen, wofür SOMAXCONN auf meinem System definiert ist. Ich weiß, dass ich einfach die Standard-Header-Datei öffnen könnte, aber manchmal muss ich ein bisschen suchen, um die Speicherorte der Header-Dateien zu finden. Stattdessen kann ich nur diesen Einzeiler verwenden:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 
Digitales Trauma
quelle
1
Sie können die Compiler-Option -include verwenden , um Pipes zu vermeiden
mymedia
31

Der einfache Ansatz ( gcc -dM -E - < /dev/null) funktioniert gut für gcc, schlägt jedoch für g ++ fehl. Kürzlich habe ich einen Test für eine C ++ 11 / C ++ 14-Funktion benötigt. Empfehlungen für die entsprechenden Makronamen werden unter https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations veröffentlicht . Aber:

g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates

schlägt immer fehl, weil es stillschweigend die C-Treiber aufruft (als ob von aufgerufen gcc). Sie können dies sehen, indem Sie die Ausgabe mit der von gcc vergleichen oder eine g ++ - spezifische Befehlszeilenoption wie (-std = c ++ 11) hinzufügen, die die Fehlermeldung ausgibt cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Da (nicht C ++) gcc niemals "Templates Aliases" unterstützt (siehe http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ), müssen Sie die -x c++Option hinzufügen Erzwingen Sie den Aufruf des C ++ - Compilers (Credits für die Verwendung der -x c++Optionen anstelle einer leeren Dummy-Datei gehen an yuyichao, siehe unten):

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

Es erfolgt keine Ausgabe, da g ++ (Version 4.9.1, standardmäßig -std = gnu ++ 98) standardmäßig keine C ++ 11-Funktionen aktiviert. Verwenden Sie dazu

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

was schließlich ergibt

#define __cpp_alias_templates 200704

Beachten Sie, dass g ++ 4.9.1 "Templates Aliases" unterstützt, wenn es mit aufgerufen wird -std=c++11.

hermannk
quelle
7
Sie müssen keine Dummy-Datei verwenden. GCC unterstützt das -xArgument, g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppsollte also funktionieren.
Yuyichao
@yuyichao Vielen Dank, dies erleichtert die Verwendung. Die Option -x war mir nicht bekannt. Hat Ihren Kommentar positiv bewertet und in die ursprüngliche Antwort integriert.
Hermannk
23

Ein portabler Ansatz, der unter Linux oder Windows gleich gut funktioniert (wo es kein / dev / null gibt):

echo | gcc -dM -E -

Für c ++ können Sie Folgendes verwenden (durch eine c++11beliebige Version ersetzen ):

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

Es funktioniert, indem gcc angewiesen wird, stdin (das von echo erzeugt wird) vorzuverarbeiten und alle Präprozessordefinitionen auszudrucken (Suche nach -dletters). Wenn Sie wissen möchten, welche Definitionen hinzugefügt werden, wenn Sie eine Header-Datei -dDeinfügen, können Sie eine Option verwenden, die -dM ähnelt, jedoch keine vordefinierten Makros enthält:

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

Beachten Sie jedoch, dass leere Eingaben immer noch viele Definitionen mit -dDOption erzeugen .

Pavel P.
quelle
6
@rubenvb es ist irrelevant. Der Punkt ist, eine cmd-Linie zu haben, die unter Windows und Unix mindestens gleich gut funktioniert. Wenn Sie verwenden NUL, sind Sie wieder auf dem ersten Platz: Es funktioniert nicht auf Systemen, die es nicht haben.
Pavel P
2
Das Hinzufügen einer vollständigen Antwort für C ++ funktioniert sowohl unter Windows als auch unter Linux (obwohl es sortsich kaum unterscheidet):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous
Dies erzeugt eine leere Ausgabe in Git-Bash.
Lennart Rolland
@ LennartRolland hat es gcc? In meinem Git-Bash kann ich gcc nicht ausführen
Pavel P
@pavel Ich verwende mingw32 gcc, das mit der Qt5-Binärverteilung für Windows geliefert wird.
Lennart Rolland
3

Während Sie in einem großen Projekt arbeiten, das über ein komplexes Build-System verfügt und bei dem es schwierig ist, den Befehl gcc / g ++ direkt abzurufen (oder zu ändern), gibt es eine andere Möglichkeit, das Ergebnis der Makroerweiterung anzuzeigen. Definieren Sie das Makro einfach neu, und Sie erhalten eine Ausgabe ähnlich der folgenden:

file.h: note: this is the location of the previous definition
#define MACRO current_value
Piotr Pałucki
quelle
Ich suche, welche Warnflagge dafür verwendet wird. Wissen Sie ?
Welgriv