El preprocesador de volcado de GCC define

Respuestas:

304

Sí, use -E -dMopciones en lugar de -c. Ejemplo (los envía a stdout):

 gcc -dM -E - < /dev/null

Para C ++

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

Del manual de gcc :

En lugar de la salida normal, genere una lista de directivas `#define 'para todas las macros definidas durante la ejecución del preprocesador, incluidas las macros predefinidas. Esto le brinda una forma de averiguar qué está predefinido en su versión del preprocesador. Suponiendo que no tiene el archivo foo.h, el comando

touch foo.h; cpp -dM foo.h

mostrará todas las macros predefinidas.

Si usa -dM sin la opción -E, -dM se interpreta como sinónimo de -fdump-rtl-mach.

philant
fuente
44
gcc existe en sistemas donde / dev / null no significa nada.
Pavel P
44
@Pavel, entonces puede usar un archivo vacío, ya sea con gcc o el preprocesador - cpp.
frágil
16
Agregué un enfoque más portátil como respuesta alternativa: también echo | gcc -dM -E -funciona en Windows.
Pavel P
44
¿Es posible determinar de dónde (es decir, en qué archivo) provienen esas definiciones?
Edam
2
Alternativamente, en Windows, cpp -dM -E - < NULse puede utilizar.
René Nyffenegger
78

Usualmente lo hago de esta manera:

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

Tenga en cuenta que algunas definiciones de preprocesador dependen de las opciones de la línea de comandos; puede probarlas agregando las opciones relevantes a la línea de comandos anterior. Por ejemplo, para ver qué opciones SSE3 / SSE4 están habilitadas de manera predeterminada:

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

y luego compara esto cuando -msse4se especifica:

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

De forma similar, puede ver qué opciones difieren entre dos conjuntos diferentes de opciones de línea de comandos, por ejemplo, comparar definiciones de preprocesador para niveles de optimización -O0(ninguno) y -O3(completo):

$ 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
fuente
45

Respuesta tardía: las otras respuestas me parecieron útiles, y quería agregar un poco más.


¿Cómo vuelco las macros de preprocesador que provienen de un archivo de encabezado particular?

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

o (gracias a @mymedia por la sugerencia):

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

En particular, quería ver qué SOMAXCONN estaba definido en mi sistema. Sé que podría abrir el archivo de encabezado estándar, pero a veces tengo que buscar un poco para encontrar las ubicaciones del archivo de encabezado. En cambio, solo puedo usar esta línea:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 
Trauma digital
fuente
1
puede usar la opción -incluir compilador para evitar tuberías
mymedia
31

El enfoque simple ( gcc -dM -E - < /dev/null) funciona bien para gcc pero falla para g ++. Recientemente solicité una prueba para una función C ++ 11 / C ++ 14. Las recomendaciones para sus nombres de macro correspondientes se publican en https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations . Pero:

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

siempre falla, porque invoca silenciosamente los controladores C (como si los invocara gcc). Puede ver esto comparando su salida con la de gcc o agregando una opción de línea de comando específica de g ++ como (-std = c ++ 11) que emite el mensaje de error cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Debido a que el gcc (que no es C ++) nunca admitirá "Alias ​​de plantillas" (consulte http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ) debe agregar la -x c++opción a forzar la invocación del compilador de C ++ (los créditos para usar las -x c++opciones en lugar de un archivo ficticio vacío van a yuyichao, ver a continuación):

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

No habrá salida porque g ++ (revisión 4.9.1, por defecto es -std = gnu ++ 98) no habilita las funciones de C ++ 11 de manera predeterminada. Para hacerlo, use

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

que finalmente rinde

#define __cpp_alias_templates 200704

observando que g ++ 4.9.1 admite "Alias ​​de plantillas" cuando se invoca con -std=c++11.

Hermannk
fuente
77
No tiene que usar un archivo ficticio. GCC apoya el -xargumento, por lo que g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppdebería funcionar.
yuyichao
@yuyichao Gracias, esto hace que sea más fácil de usar. No estaba al tanto de la opción -x. Votó su comentario y lo integró en la respuesta original.
hermannk
23

Un enfoque portátil que funciona igualmente bien en Linux o Windows (donde no hay / dev / null):

echo | gcc -dM -E -

Para c ++ puede usar (reemplazar c++11con cualquier versión que use):

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

Funciona diciéndole a gcc que preprocese stdin (que se produce por echo) e imprima todas las definiciones de preprocesador (búsqueda -dletters). Si desea saber qué definiciones se agregan cuando incluye un archivo de encabezado, puede usar la -dDopción que es similar a -dM pero no incluye macros predefinidas:

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

Sin embargo, tenga en cuenta que la entrada vacía aún produce muchas definiciones con la -dDopción.

Pavel P
fuente
66
@rubenvb es irrelevante. el punto es tener una línea cmd que funcione igualmente bien en Windows y Unix al menos. Si lo usa NUL, volverá al punto de partida: no funcionará en sistemas que no lo tengan.
Pavel P
2
agregar respuesta completa para C ++, funciona tanto en Windows como en Linux (aunque se sortcomporta de manera un poco diferente):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous
Esto produce una salida vacía en git-bash.
Lennart Rolland
@LennartRolland ¿tiene gcc? En mi git-bash no puedo ejecutar gcc
Pavel P
@pavel Uso mingw32 gcc que viene con la distribución binaria Qt5 para Windows.
Lennart Rolland
3

Mientras trabaja en un gran proyecto que tiene un sistema de compilación complejo y donde es difícil obtener (o modificar) el comando gcc / g ++ directamente, hay otra forma de ver el resultado de la expansión de macros. Simplemente redefina la macro y obtendrá un resultado similar al siguiente:

file.h: note: this is the location of the previous definition
#define MACRO current_value
Piotr Pałucki
fuente
Estoy buscando qué bandera de advertencia se utiliza para ello. Tú sabes ?
Welgriv