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.


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


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.


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á.


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.


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


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
....
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.