Intestazioni precompilate con GCC


91

Qualcuno ha avuto successo nel far funzionare intestazioni precompilate con GCC? Non ho avuto fortuna nei miei tentativi e non ho visto molti buoni esempi su come configurarlo. Ho provato su cygwin gcc 3.4.4 e utilizzando 4.0 su Ubuntu.


L'ho provato e ho avuto il caso d'uso ottimale per le intestazioni precompilate perché la mia sorgente c è generata dal compilatore e non scritta dall'utente. Sun Studio e in particolare Visual Studio hanno migliorato molto il tempo di compilazione. Su gcc stava peggiorando anche senza gli header precompilati. Questo era con 3.4 non testato con 4.x ma velocità e gcc si escludono a vicenda.
Lothar

@ Lothar qual era il codice? Trovo g ++ circa 10 volte più veloce dei recenti compilatori Visual Studio, su un codice fortemente basato su modelli.
il suino

Non sto usando modelli nel mio codice C ++. È solo C + gestione delle eccezioni + belle estensioni C ++. Anche adesso, 6 anni dopo questa domanda, VS2010 è molto più veloce. Ma nel frattempo ho 16 core così posso conviverci.
Lothar

Risposte:


58

Ho sicuramente avuto successo. Innanzitutto, ho usato il seguente codice:


#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;
}

Questo era solo un ciao mondo da Boost Xpressive (vedi sotto per il link). Per prima cosa, ho compilato con l' -Hopzione in gcc. Mostrava un enorme elenco di intestazioni che utilizzava. Quindi, ho dato un'occhiata ai flag di compilazione che il mio IDE (codice :: blocchi) stava producendo e ho visto qualcosa del genere:

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

Quindi ho scritto un comando per compilare il file Xpressive.hpp con gli stessi identici flag:

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

Ho compilato di nuovo il codice originale con -He ho ottenuto questo output:

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

Il ! significa che il compilatore è stato in grado di utilizzare l'intestazione precompilata. Una x significa che non è stato in grado di usarlo. L'utilizzo dei flag appropriati del compilatore è fondamentale. Ho tolto la -H e ho eseguito alcuni test di velocità. L'intestazione precompilata ha avuto un miglioramento da 14 secondi a 11 secondi. Non male ma non eccezionale.

Nota: ecco il collegamento all'esempio: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Non sono riuscito a farlo funzionare in inviare.

BTW: sto usando il seguente g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3


20
L'aggiunta di -Winvalid-pch ti aiuterà a eseguire il debug se e perché qualcosa va storto nell'uso del PCH.
lefticus

Le intestazioni precompilate "non male ma non eccezionale" sono utili quando si hanno molte molte intestazioni che si ricollegano tra loro, quindi ridurranno il tempo di compilazione su progetti molto grandi che utilizzano grandi librerie o molte librerie.
jokoon

4
"non male ma non eccezionale": utilizzando gcc 4.4.7, 136 file .cpp 35,5 Mb di dimensione totale, 148 file .h 5,5 Mb di dimensione totale, il file .gch è di 48 Mb, la build di debug richiede 2'20 "(contro 2 '14 "non-pch), la compilazione ottimizzata -O2 richiede 4'30" (contro 5'33 "non-pch) L'effetto ci si aspetterebbe vicino alle build di debug, ma è solo la build ottimizzata che trae vantaggio dalla precompilazione ... Non so perché. La precompilazione è molto più drammatica su Windows!
Andreas Vergison

1
(continua) I file di output pch / non-pch corrispondenti hanno esattamente la stessa dimensione in byte, questo è un bene. I tempi di cui sopra sembrano variare quando si ripetono le build, ad esempio -O2 non-pch varia tra 3'45 "e 5'33", quindi non è scienza esatta, forse a causa dell'esecuzione in VMware. Ad ogni modo, gcc pch non sembra affatto vantaggioso nel mio caso. Confrontalo con lo stesso codice di base su Windows VS2012 (x64, compilazione a thread singolo): debug 46 "pch, 2'50" non-pch, rilascio 2'13 "pch, 5'02" non-pch. E ovviamente anche molto più velocemente quando si abilita il multiprocessore ...
Andreas Vergison

@AndreasVergison - Hai provato a utilizzare -Winvalid-pchper assicurarti che l'intestazione precompilata venga utilizzata correttamente? Notiamo un grande miglioramento usando pch per le nostre build di debug, quindi mi chiedo se ci sia un problema con la tua configurazione.
Josh Kelley

52

In primo luogo, vedere la documentazione qui .

Compili le intestazioni proprio come qualsiasi altro file, ma metti l'output all'interno di un file con suffisso .gch.

Quindi, ad esempio, se precompili stdafx.h avrai un'intestazione precompilata che verrà cercata automaticamente chiamata stdafx.h.gchogni volta che includistdafx.h

Esempio:

stdafx.h:

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

a.cpp:

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

Quindi compila come:

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

La tua compilation funzionerà anche se rimuovi stdafx.h dopo il passaggio 1.


8

Lo -xspecificatore per le intestazioni precompilate C ++ è -x c++-header, non -x c++. Segue un esempio di utilizzo di 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.

Genera il PCH in questo modo:

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

Il pch.h.gchdeve essere nella stessa directory pch.hdi per essere utilizzato, quindi assicurati di eseguire il comando precedente dalla directory in cui si pch.htrova.


3
Questo dovrebbe essere -c pch.h, no -c pch.cpp?
MM

7

Sono riuscito a far funzionare le intestazioni precompilate con gcc una volta in passato, e ricordo di aver avuto problemi anche allora. La cosa da ricordare è che gcc ignorerà il file (header.h.gch o simile) se alcune condizioni non sono soddisfatte, un elenco delle quali può essere trovato nella pagina di documentazione dell'intestazione precompilata di gcc .

In genere è più sicuro che il tuo sistema di compilazione compili il file .gch come primo passaggio, con le stesse opzioni della riga di comando ed eseguibile del resto del codice sorgente. Ciò garantisce che il file sia aggiornato e che non vi siano sottili differenze.

Probabilmente è anche una buona idea farlo funzionare prima con un esempio artificioso, solo per rimuovere la possibilità che i tuoi problemi siano specifici del codice sorgente nel tuo progetto.


7

Chiama gcc nello stesso modo in cui lo chiami per il tuo file sorgente ma con un file di intestazione.

per esempio

g++ $(CPPFLAGS) test.h

questo genera un file chiamato test.h.gch

Ogni volta che gcc cerca test.h cerca prima test.h.gch e se lo trova lo usa automaticamente.

Ulteriori informazioni sono disponibili in Intestazioni precompilate GCC


Sto usando gcc 3.4 e la riga g ++ stdafx.h non si compila, viene visualizzato l'errore "g ++: compilazione del file di intestazione richiesta", ma questo verrà compilato, non sono sicuro se è quello che voglio però: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB

1

Assicurati che -include your_header.h

Ecco come ho precompilato e utilizzato la bits/stdc++.hraccolta.

Codice

#include <bits/stdc++.h>

Quindi ho individuato la libreria compilando il mio file con -H e guardando l'output

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

dove ho visto

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

Quindi ho creato una nuova directory bitsall'interno di quella corrente e ho copiato stdc++.hda lì.

Poi ho corso

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

che ha generato bits/stdc++.gch

Normalmente ho compilato il mio codice tramite

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

, ma ho dovuto modificarlo in

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

poiché ha risolto solo il .gchfile invece che .hcon -include bits/stdc++.h Quella era la chiave per me. Un'altra cosa da tenere a mente è che devi compilare il *.hfile di intestazione con quasi gli stessi parametri con cui compili il tuo *.cpp. Quando non ho incluso -O3o -pthreadignorato l' *.gchintestazione precompilata.

Per verificare se tutto è corretto, puoi misurare la differenza di orario confrontando il risultato di

time g++ sol.cpp ...

o corri

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

di nuovo e cerca i percorsi di intestazione e se ora ottieni !prima del percorso della libreria, ad esempio

! ./bits/stdc++.h.gch
....
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.