O pré-processador de despejo do GCC define


248

Existe uma maneira de o gcc / g ++ despejar suas definições de pré-processador na linha de comando? I coisas más, como __GNUC__, __STDC__e assim por diante.

Respostas:


304

Sim, use as -E -dMopções em vez de -c. Exemplo (envia-os para stdout):

 gcc -dM -E - < /dev/null

Para C ++

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

No manual do gcc :

Em vez da saída normal, gere uma lista de diretivas `` #define '' para todas as macros definidas durante a execução do pré-processador, incluindo macros predefinidas. Isso fornece uma maneira de descobrir o que é predefinido na sua versão do pré-processador. Supondo que você não possua o arquivo foo.h, o comando

touch foo.h; cpp -dM foo.h

mostrará todas as macros predefinidas.

Se você usar -dM sem a opção -E, -dM será interpretado como sinônimo de -fdump-rtl-mach.


4
O gcc existe em sistemas onde / dev / null não significa nada.
Pavel P

4
@Pavel, então você pode usar um arquivo vazio, com o gcc ou o pré-processador - cpp.
Philant

16
Eu adicionei uma abordagem mais portátil como uma resposta alternativa: echo | gcc -dM -E -funciona também no Windows.
Pavel P

4
É possível determinar de onde (ou seja, em qual arquivo) essas definições vieram?
Edam

2
Como alternativa, no Windows, cpp -dM -E - < NULpode ser usado.
René Nyffenegger

78

Eu costumo fazer assim:

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

Observe que algumas definições do pré-processador dependem das opções da linha de comando - você pode testá-las adicionando as opções relevantes à linha de comando acima. Por exemplo, para ver quais opções SSE3 / SSE4 estão ativadas por padrão:

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

e compare isso quando -msse4for especificado:

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

Da mesma forma, é possível ver quais opções diferem entre dois conjuntos diferentes de opções de linha de comando, por exemplo, comparar as definições do pré-processador para os níveis de otimização -O0(nenhum) e -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

45

Resposta tardia - achei as outras respostas úteis - e queria adicionar um pouco mais.


Como despejo macros de pré-processador provenientes de um arquivo de cabeçalho específico?

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

ou (obrigado a @mymedia pela sugestão):

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

Em particular, eu queria ver o que SOMAXCONN foi definido no meu sistema. Eu sei que poderia abrir o arquivo de cabeçalho padrão, mas às vezes tenho que procurar um pouco para encontrar os locais dos arquivos de cabeçalho. Em vez disso, posso apenas usar esta linha:

$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$ 

1
você pode usar a opção de compilador -include para evitar pipes
mymedia

31

A abordagem simples ( gcc -dM -E - < /dev/null) funciona bem para o gcc, mas falha no g ++. Recentemente, eu exigi um teste para um recurso C ++ 11 / C ++ 14. As recomendações para seus nomes de macro correspondentes estão publicadas em https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations . Mas:

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

sempre falha, porque chama silenciosamente os drivers C (como se invocados por gcc). Você pode ver isso comparando sua saída com a do gcc ou adicionando uma opção de linha de comando específica para g ++ como (-std = c ++ 11) que emite a mensagem de erro cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C.

Como o gcc (que não é C ++) nunca suporta "Aliases de modelos" (consulte http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf ), você deve adicionar a -x c++opção a forçar a invocação do compilador C ++ (créditos para usar as -x c++opções em vez de um arquivo fictício vazio, vá para yuyichao, veja abaixo):

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

Não haverá saída porque o g ++ (revisão 4.9.1, o padrão é -std = gnu ++ 98) não habilita os recursos do C ++ 11 por padrão. Para fazer isso, use

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

que finalmente rende

#define __cpp_alias_templates 200704

observando que o g ++ 4.9.1 suporta "Aliases de modelos" quando chamado com -std=c++11.


7
Você não precisa usar um arquivo fictício. O GCC suporta o -xargumento, portanto g++ -x c++ -dM -E -std=c++11 - < /dev/null | grep cppdeve funcionar.
yuyichao

@yuyichao Obrigado, isso facilita o uso. Eu não estava ciente da opção -x. Promoveu um voto positivo ao seu comentário e o integrou à resposta original.
hermannk

23

Uma abordagem portátil que funciona igualmente bem no Linux ou Windows (onde não há / dev / null):

echo | gcc -dM -E -

Para c ++, você pode usar (substitua c++11pela versão que usar):

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

Ele funciona dizendo ao gcc para pré-processar o stdin (produzido pelo echo) e imprimir todas as definições do pré-processador (procurar -dletters). Se você deseja saber o que define são adicionados quando você inclui um arquivo de cabeçalho, pode usar a -dDopção semelhante a -dM, mas não inclui macros predefinidas:

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

Observe, no entanto, que a entrada vazia ainda produz muitas definições com a -dDopção


6
@rubenvb é irrelevante. o objetivo é ter uma linha cmd que funcione igualmente bem no Windows e no Unix pelo menos. Se você usar NUL, estará de volta à estaca zero: ele não funcionará em sistemas que não o possuem.
Pavel P

2
adicionando resposta completa para C ++, funciona tanto no Windows quanto no Linux (embora sortse comporte um pouco diferente):echo | gcc -x c++ -std=c++17 -dM -E - | sort
Xeverous

Isso produz saída vazia no git-bash.
Lennart Rolland

@LennartRolland tem gcc? Na minha git-festa eu não posso correr gcc
Pavel P

@ pavel Eu uso o mingw32 gcc que vem com a distribuição binária Qt5 para windows.
Lennart Rolland

3

Enquanto trabalhamos em um grande projeto que possui um sistema de compilação complexo e onde é difícil obter (ou modificar) o comando gcc / g ++ diretamente, há outra maneira de ver o resultado da expansão de macro. Redefina simplesmente a macro e você obterá uma saída semelhante à seguinte:

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

Estou procurando qual sinalizador de aviso é usado para isso. Você sabe ?
Welgriv 13/02/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.