¿Hay alguna manera para que gcc / g ++ descargue su preprocesador definido desde la línea de comando? Me refiero a cosas como __GNUC__
, __STDC__
etc.
¿Hay alguna manera para que gcc / g ++ descargue su preprocesador definido desde la línea de comando? Me refiero a cosas como __GNUC__
, __STDC__
etc.
Respuestas:
Sí, use -E -dM
opciones 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.
echo | gcc -dM -E -
funciona en Windows.
cpp -dM -E - < NUL
se puede utilizar.
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 -msse4
se 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
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
$
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
.
-x
argumento, por lo que g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cpp
debería funcionar.
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++11
con 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 -dD
opció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 -dD
opción.
NUL
, volverá al punto de partida: no funcionará en sistemas que no lo tengan.
sort
comporta de manera un poco diferente):echo | gcc -x c++ -std=c++17 -dM -E - | sort
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