Le préprocesseur de vidage GCC définit

Réponses:

304

Oui, utilisez des -E -dMoptions au lieu de -c. Exemple (les renvoie vers stdout):

 gcc -dM -E - < /dev/null

Pour C ++

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

Depuis le manuel de gcc :

Au lieu de la sortie normale, générez une liste de directives `#define 'pour toutes les macros définies lors de l'exécution du préprocesseur, y compris les macros prédéfinies. Cela vous permet de découvrir ce qui est prédéfini dans votre version du préprocesseur. En supposant que vous n'avez pas de fichier foo.h, la commande

touch foo.h; cpp -dM foo.h

affichera toutes les macros prédéfinies.

Si vous utilisez -dM sans l'option -E, -dM est interprété comme synonyme de -fdump-rtl-mach.

philant
la source
4
gcc existe sur les systèmes où / dev / null ne signifie rien.
Pavel P
4
@Pavel vous pouvez alors utiliser un fichier vide, soit avec gcc soit avec le préprocesseur - cpp.
philant
16
J'ai ajouté une approche plus portable comme réponse alternative: echo | gcc -dM -E -fonctionne également sur Windows.
Pavel P
4
Est-il possible de déterminer d'où (c'est-à-dire dans quel fichier) ces définitions provenaient?
edam
2
Alternativement, sous Windows, cpp -dM -E - < NULpeut être utilisé.
René Nyffenegger
78

Je le fais généralement de cette façon:

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

Notez que certaines définitions de préprocesseur dépendent des options de ligne de commande - vous pouvez les tester en ajoutant les options pertinentes à la ligne de commande ci-dessus. Par exemple, pour voir quelles options SSE3 / SSE4 sont activées par défaut:

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

puis comparer ceci quand -msse4est spécifié:

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

De même, vous pouvez voir quelles options diffèrent entre deux ensembles différents d'options de ligne de commande, par exemple comparer les définitions de préprocesseur pour les niveaux d'optimisation -O0(aucun) et -O3(complet):

$ 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
la source
45

Réponse tardive - j'ai trouvé les autres réponses utiles - et je voulais en ajouter un peu plus.


Comment vider les macros de préprocesseur provenant d'un fichier d'en-tête particulier?

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

ou (merci à @mymedia pour la suggestion):

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

En particulier, je voulais voir à quoi SOMAXCONN était défini sur mon système. Je sais que je pourrais simplement ouvrir le fichier d'en-tête standard, mais parfois je dois chercher un peu pour trouver les emplacements du fichier d'en-tête. Au lieu de cela, je peux simplement utiliser ce one-liner:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 
Traumatisme numérique
la source
1
vous pouvez utiliser l' option de compilation -include pour éviter les tuyaux
mymedia
31

L'approche simple ( gcc -dM -E - < /dev/null) fonctionne bien pour gcc mais échoue pour g ++. Récemment, j'ai eu besoin d'un test pour une fonctionnalité C ++ 11 / C ++ 14. Les recommandations pour leurs noms de macro correspondants sont publiées sur https://isocpp.org/std/stand-documents/sd-6-sg10-feature-test-recommendations . Mais:

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

échoue toujours, car il appelle silencieusement les pilotes C (comme s'il était appelé par gcc). Vous pouvez le voir en comparant sa sortie avec celle de gcc ou en ajoutant une option de ligne de commande spécifique à g ++ comme (-std = c ++ 11) qui émet le message d'erreur cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Parce que (le non C ++) gcc ne prendra jamais en charge les "alias de modèles" (voir http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ), vous devez ajouter l' -x c++option à forcer l'invocation du compilateur C ++ (les crédits pour l'utilisation des -x c++options au lieu d'un fichier factice vide vont à yuyichao, voir ci-dessous):

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

Il n'y aura pas de sortie car g ++ (révision 4.9.1, par défaut -std = gnu ++ 98) n'active pas les fonctionnalités C ++ 11 par défaut. Pour ce faire, utilisez

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

qui donne finalement

#define __cpp_alias_templates 200704

notant que g ++ 4.9.1 prend en charge les "alias de modèles" lorsqu'il est appelé avec -std=c++11.

Hermannk
la source
7
Vous n'avez pas besoin d'utiliser un fichier factice. GCC soutient l' -xargument et g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppdevrait donc fonctionner.
yuyichao
@yuyichao Merci, cela facilite son utilisation. Je n'étais pas au courant de l'option -x. A voté pour votre commentaire et l'a intégré à la réponse d'origine.
hermannk
23

Une approche portable qui fonctionne aussi bien sous Linux ou Windows (où il n'y a pas / dev / null):

echo | gcc -dM -E -

Pour c ++, vous pouvez utiliser (remplacer c++11par la version que vous utilisez):

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

Il fonctionne en disant à gcc de prétraiter stdin (qui est produit par echo) et d' imprimer toutes les définitions de préprocesseur (rechercher -dletters). Si vous voulez savoir quelles définitions sont ajoutées lorsque vous incluez un fichier d'en-tête, vous pouvez utiliser une -dDoption similaire à -dM mais qui n'inclut pas de macros prédéfinies:

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

Notez cependant que l'entrée vide produit toujours beaucoup de définitions avec -dDoption.

Pavel P
la source
6
@rubenvb ce n'est pas pertinent. le point est d'avoir une ligne cmd qui fonctionne aussi bien sur windows et unix au moins. Si vous utilisez NUL, vous êtes de retour à la case départ: cela ne fonctionnera pas sur les systèmes qui ne l'ont pas.
Pavel P
2
l'ajout de la réponse complète pour C ++, fonctionne à la fois sur Windows et Linux (bien qu'il sortse comporte peu différemment):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous
Cela produit une sortie vide dans git-bash.
Lennart Rolland
@LennartRolland at-il gcc? Dans mon git-bash, je ne peux pas exécuter gcc
Pavel P
@pavel J'utilise mingw32 gcc fourni avec la distribution binaire Qt5 pour Windows.
Lennart Rolland
3

Tout en travaillant dans un grand projet qui a un système de construction complexe et où il est difficile d'obtenir (ou de modifier) ​​directement la commande gcc / g ++, il existe une autre façon de voir le résultat de l'expansion des macros. Redéfinissez simplement la macro et vous obtiendrez une sortie similaire à la suivante:

file.h: note: this is the location of the previous definition
#define MACRO current_value
Piotr Pałucki
la source
Je cherche quel drapeau d'avertissement est utilisé pour cela. Savez-vous ?
Welgriv