Cabeçalhos pré-compilados com GCC

91

Alguém teve algum sucesso em conseguir cabeçalhos pré-compilados trabalhando com o GCC? Não tive sorte em minhas tentativas e não vi muitos bons exemplos de como configurá-lo. Eu tentei no cygwin gcc 3.4.4 e usando 4.0 no Ubuntu.

Lee Baldwin
fonte
Eu tentei e tive o caso de uso ideal para cabeçalhos pré-compilados porque meu código-fonte c é gerado pelo compilador e não escrito pelo usuário. O Sun Studio e especialmente o Visual Studio melhoraram muito o tempo de construção. No gcc estava ficando ainda pior do que sem cabeçalhos pré-compilados. Isso foi com o 3.4 não testado com o 4.x, mas a velocidade e o gcc são mutuamente exclusivos.
Lothar
@Lothar qual era o código? Acho o g ++ cerca de 10 vezes mais rápido do que os compiladores do Visual Studio recentes, em alguns códigos fortemente modelados.
o suíno de
Não estou usando modelos no meu código C ++. É apenas tratamento de exceção C + + extensões C ++ agradáveis. Mesmo agora, 6 anos após esta questão, o VS2010 é muito mais rápido. Mas enquanto isso eu tenho 16 núcleos, então posso viver com isso.
Lothar

Respostas:

58

Definitivamente tive sucesso. Primeiro, usei o seguinte código:


#include <boost/xpressive/xpressive.hpp>
#include <iostream>

using namespace std;
using namespace boost::xpressive;

//A simple regex test
int main()
{
    std::string hello( "hello world!" );

    sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
    smatch what;

    if( regex_match( hello, what, rex ) )
    {
        std::cout << what[0] << '\n'; // whole match
        std::cout << what[1] << '\n'; // first capture
        std::cout << what[2] << '\n'; // second capture
    }
    return 0;
}

Este foi apenas um hello world da Boost Xpressive (veja o link abaixo). Primeiro, compilei com a -Hopção do gcc. Ele mostrou uma lista enorme de cabeçalhos usados. Então, eu dei uma olhada nos sinalizadores de compilação que meu IDE (code :: blocks) estava produzindo e vi algo assim:

g++ -Wall -fexceptions -g -c main.cpp -o obj/Debug/main.o

Então, escrevi um comando para compilar o arquivo Xpressive.hpp com exatamente as mesmas sinalizações:

sudo g++ -Wall -fexceptions -g /usr/local/include/boost/xpressive/xpressive.hpp

Compilei o código original novamente com o -He obtive esta saída:

g ++ -Wall -fexceptions -H -g -c main.cpp -o obj / Debug / main.o
! /usr/local/include/boost/xpressive/xpressive.hpp.gch
main.cpp
. /usr/include/c++/4.4/iostream
.. /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++config.h
.. /usr/include/c++/4.4/ostream
.. /usr/include/c++/4.4/istream
main.cpp

O ! significa que o compilador foi capaz de usar o cabeçalho pré-compilado. Um x significa que não foi possível usá-lo. Usar os sinalizadores de compilador apropriados é crucial. Tirei o -H e fiz alguns testes de velocidade. O cabeçalho pré-compilado teve uma melhora de 14 segundos para 11 segundos. Não é ruim, mas não é ótimo.

Observação: aqui está o link para o exemplo: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Não consegui fazê-lo funcionar no postar.

BTW: estou usando o seguinte g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Usuário1
fonte
20
Adicionar -Winvalid-pch o ajudará a depurar se e por que algo deu errado no uso do PCH.
esquerda de
Os cabeçalhos pré-compilados "nada mal, mas não muito" são úteis quando você tem muitos cabeçalhos que se ligam novamente, então eles irão reduzir o tempo de compilação em projetos muito grandes que usam grandes bibliotecas ou muitas bibliotecas.
Jokoon
4
"não é ruim, mas não é ótimo": usando gcc 4.4.7, 136 arquivos .cpp de tamanho total de 35,5 Mb, 148 arquivos .h de tamanho total de 5,5 Mb, o arquivo .gch tem 48 Mb, a compilação de depuração leva 2'20 "(vs 2 '14 "sem pch), compilação otimizada -O2 leva 4'30" (vs 5'33 "sem pch) O efeito seria esperado perto de compilações de depuração, mas é apenas a compilação otimizada que lucra com a pré-compilação ... Não sei por quê. A pré-compilação é muito mais dramática no Windows!
Andreas Vergison
1
(continuação) Os arquivos de saída pch / não pch correspondentes têm exatamente o mesmo tamanho de byte, isso é bom. Os tempos acima parecem variar ao repetir as compilações, por exemplo -O2 sem pch varia entre 3'45 "e 5'33", então não é uma ciência exata, talvez devido à execução no VMware. De qualquer forma, o gcc pch não parece nada benéfico no meu caso. Compare-o com a mesma base de código no Windows VS2012 (x64, compilação de thread único): debug 46 "pch, 2'50" sem pch, release 2'13 "pch, 5'02" sem pch. E, claro, ainda mais rápido ao habilitar o multiprocessador ...
Andreas Vergison
@AndreasVergison - Você tentou usar o -Winvalid-pchpara certificar-se de que o cabeçalho pré-compilado está sendo usado corretamente? Notamos uma grande melhoria usando pch para nossas compilações de depuração, então eu me pergunto se há um problema com sua configuração.
Josh Kelley
52

Em primeiro lugar, consulte a documentação aqui .

Você compila cabeçalhos como qualquer outro arquivo, mas coloca a saída dentro de um arquivo com o sufixo .gch.

Então, por exemplo, se você pré-compilar stdafx.h, você terá um cabeçalho pré-compilado que será automaticamente procurado, chamado stdafx.h.gchsempre que você incluirstdafx.h

Exemplo:

stdafx.h:

#include <string>
#include <stdio.h>

a.cpp:

#include "stdafx.h"
int main(int argc, char**argv)
{
  std::string s = "Hi";
  return 0;
}

Em seguida, compile como:

> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out

Sua compilação funcionará mesmo se você remover stdafx.h após a etapa 1.

Brian R. Bondy
fonte
8

O -xespecificador para cabeçalhos pré-compilados C ++ é -x c++-header, não -x c++. Segue-se um exemplo de uso de PCH.

pch.h:

// Put your common include files here: Boost, STL as well as your project's headers.

main.cpp:

#include "pch.h"
// Use the PCH here.

Gere o PCH assim:

$ g++ -x c++-header -o pch.h.gch -c pch.h

O pch.h.gchdeve estar no mesmo diretório que o pch.hpara ser usado, portanto, certifique-se de executar o comando acima no diretório onde pch.hestá.

psaghelyi
fonte
3
Isso deveria ser -c pch.h, não -c pch.cpp?
MM
7

Consegui fazer com que cabeçalhos pré-compilados funcionassem sob gcc uma vez no passado, e lembro-me de ter tido problemas também. A coisa a lembrar é que o gcc irá ignorar o arquivo (header.h.gch ou similar) se certas condições não forem atendidas, uma lista das quais pode ser encontrada na página de documentação do cabeçalho pré-compilado do gcc .

Geralmente, é mais seguro fazer com que seu sistema de compilação compile o arquivo .gch como uma primeira etapa, com as mesmas opções de linha de comando e executáveis ​​do resto de sua fonte. Isso garante que o arquivo esteja atualizado e que não haja diferenças sutis.

Provavelmente também é uma boa ideia fazê-lo funcionar com um exemplo inventado primeiro, apenas para remover a possibilidade de que seus problemas sejam específicos ao código-fonte do seu projeto.

Paulo
fonte
7

Chame o gcc da mesma maneira que o chama para o arquivo de origem, mas com um arquivo de cabeçalho.

por exemplo

g++ $(CPPFLAGS) test.h

isso gera um arquivo chamado test.h.gch

Cada vez que o gcc procura por test.h, ele procura primeiro por test.h.gch e, se o encontrar, o usa automaticamente.

Mais informações podem ser encontradas em Cabeçalhos pré-compilados do GCC

simon
fonte
Estou usando o gcc 3.4 e a linha g ++ stdafx.h não compilará, você obtém o erro "g ++: compilação do arquivo de cabeçalho solicitada", mas ele compilará, mas não tenho certeza se é isso que eu quero: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB
0

Tenha certeza de -include your_header.h

É assim que eu pré-compilei e usei a bits/stdc++.hcoleção.

Código

#include <bits/stdc++.h>

Então eu localizei a lib compilando meu arquivo com -H e olhando a saída

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

onde eu vi

. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h

Então criei um novo diretório bitsdentro do atual e copiei stdc++.hde lá.

Então eu corri

g++ bits/stdc++.h -O3 -std=c++14  -pthread

que gerou bits/stdc++.gch

Normalmente eu compilei meu código via

g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable

, mas eu tive que modificar isso para

g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable

já que só resolveu .gcharquivar em vez de .hcom -include bits/stdc++.h Isso foi fundamental para mim. Outra coisa a se manter em mente é que você deve compilar o *.harquivo de cabeçalho com quase os mesmos parâmetros que compila o seu *.cpp. Quando não incluí -O3ou -pthreadignorei o *.gchcabeçalho pré - compilado.

Para verificar se tudo está correto, você pode medir a diferença de tempo comparando o resultado de

time g++ sol.cpp ...

ou correr

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

novamente e procure por caminhos de cabeçalho e se agora você obtiver !antes do caminho da biblioteca, por exemplo

! ./bits/stdc++.h.gch
....
Íhor Mé
fonte