En-têtes précompilés avec GCC

91

Quelqu'un a-t-il réussi à obtenir des en-têtes précompilés fonctionnant avec GCC? Je n'ai pas eu de chance dans mes tentatives et je n'ai pas vu beaucoup de bons exemples sur la façon de le configurer. J'ai essayé cygwin gcc 3.4.4 et en utilisant 4.0 sur Ubuntu.

Lee Baldwin
la source
Je l'ai essayé et j'ai eu le cas d'utilisation optimal pour les en-têtes précompilés car ma source c est générée par un compilateur et non écrite par l'utilisateur. Sun Studio et en particulier Visual Studio ont beaucoup amélioré le temps de construction. Sur gcc, cela empirait encore sans les en-têtes précompilés. C'était avec 3.4 pas testet avec 4.x mais speed et gcc sont mutuellement exclusifs.
Lothar
@Lothar quel était le code? Je trouve g ++ environ 10 fois plus rapide que les compilateurs Visual Studio récents, sur du code fortement basé sur des modèles.
le porc
Je n'utilise pas de modèles dans mon code C ++. C'est juste la gestion des exceptions C + + de belles extensions C ++. Même maintenant, 6 ans après cette question, VS2010 est une magnitude plus rapide. Mais en attendant, j'ai 16 cœurs pour pouvoir vivre avec.
Lothar

Réponses:

58

J'ai certainement eu du succès. Tout d'abord, j'ai utilisé le code suivant:


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

C'était juste un bonjour le monde de Boost Xpressive (voir ci-dessous pour le lien). Tout d'abord, j'ai compilé avec l' -Hoption dans gcc. Il montrait une énorme liste d'en-têtes qu'il utilisait. Ensuite, j'ai regardé les indicateurs de compilation que mon IDE (code :: blocks) produisait et j'ai vu quelque chose comme ceci:

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

J'ai donc écrit une commande pour compiler le fichier Xpressive.hpp avec exactement les mêmes indicateurs:

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

J'ai compilé à nouveau le code original avec le -Het j'ai obtenu cette sortie:

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

Le ! signifie que le compilateur a pu utiliser l'en-tête précompilé. Un x signifie qu'il n'a pas pu l'utiliser. L'utilisation des indicateurs de compilateur appropriés est cruciale. J'ai enlevé le -H et ai fait quelques tests de vitesse. L'en-tête précompilé avait une amélioration de 14 secondes à 11 secondes. Pas mal, mais pas génial.

Remarque: voici le lien vers l'exemple: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Je n'ai pas pu le faire fonctionner dans le Publier.

BTW: J'utilise le g ++ suivant

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Utilisateur1
la source
20
L'ajout de -Winvalid-pch vous aidera à déboguer si et pourquoi quelque chose ne va pas dans l'utilisation du PCH.
lefticus
Les en-têtes précompilés "pas mal mais pas super" sont utiles lorsque vous avez beaucoup d'en-têtes qui se relient les uns les autres, donc ils réduiront le temps de compilation sur de très gros projets qui utilisent de grandes bibliothèques ou de nombreuses bibliothèques.
jokoon
4
"pas mal mais pas génial": en utilisant gcc 4.4.7, 136 fichiers .cpp 35,5 Mo de taille totale, 148 fichiers .h 5,5 Mo de taille totale, le fichier .gch est de 48 Mo, la compilation de débogage prend 2'20 "(contre 2 '14 "non-pch), -O2 optimisé la construction prend 4'30" (vs 5'33 "non-pch) L'effet serait attendu près des versions de débogage, mais c'est juste la construction optimisée qui profite de la précompilation .... Pas certain de pourquoi. La précompilation est bien plus dramatique sous Windows!
Andreas Vergison
1
(suite) Les fichiers de sortie pch / non-pch correspondants ont exactement la même taille d'octet, c'est bien. Les délais ci-dessus semblent varier lors de la répétition des builds, par exemple -O2 non-pch varie entre 3'45 "et 5'33", donc ce n'est pas une science exacte, peut-être à cause de l'exécution sous VMware. Quoi qu'il en soit, gcc pch ne semble pas du tout bénéfique dans mon cas. Comparez-le à la même base de code sur Windows VS2012 (x64, compilation à un seul thread): débogage 46 "pch, 2'50" non-pch, release 2'13 "pch, 5'02" non-pch. Et bien sûr encore beaucoup plus rapide lors de l'activation du multi-processeur ...
Andreas Vergison
@AndreasVergison - Avez-vous essayé d'utiliser -Winvalid-pchpour vous assurer que l'en-tête précompilé est correctement utilisé? Nous remarquons une grande amélioration en utilisant pch pour nos versions de débogage, donc je me demande s'il y a un problème avec votre configuration.
Josh Kelley
52

Tout d'abord, consultez la documentation ici .

Vous compilez les en-têtes comme n'importe quel autre fichier, mais vous placez la sortie dans un fichier avec un suffixe .gch.

Ainsi, par exemple, si vous précompilez stdafx.h, vous aurez un en-tête précompilé qui sera automatiquement recherché et appelé à stdafx.h.gchchaque fois que vous incluezstdafx.h

Exemple:

stdafx.h:

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

a.cpp:

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

Puis compilez comme:

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

Votre compilation fonctionnera même si vous supprimez stdafx.h après l'étape 1.

Brian R. Bondy
la source
8

Le -xspécificateur pour les en-têtes précompilés C ++ est -x c++-header, not -x c++. Voici un exemple d'utilisation 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.

Générez le PCH comme ceci:

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

Le pch.h.gchdoit être dans le même répertoire que pch.hpour être utilisé, assurez-vous donc d'exécuter la commande ci-dessus à partir du répertoire où se pch.htrouve.

psaghelyi
la source
3
Cela devrait être -c pch.h, non -c pch.cpp?
MM
7

J'ai réussi à faire fonctionner des en-têtes précompilés sous gcc une fois dans le passé, et je me souviens aussi avoir eu des problèmes à l'époque. La chose à retenir est que gcc ignorera le fichier (header.h.gch ou similaire) si certaines conditions ne sont pas remplies, dont une liste peut être trouvée sur la page de documentation des en-têtes précompilés de gcc .

En règle générale, il est plus sûr que votre système de construction compile le fichier .gch dans un premier temps, avec les mêmes options de ligne de commande et le même exécutable que le reste de votre source. Cela garantit que le fichier est à jour et qu'il n'y a pas de différences subtiles.

C'est probablement aussi une bonne idée de le faire fonctionner d'abord avec un exemple artificiel, juste pour éliminer la possibilité que vos problèmes soient spécifiques au code source de votre projet.

Paul
la source
7

Appelez gcc de la même manière que vous l'appelez pour votre fichier source mais avec un fichier d'en-tête.

par exemple

g++ $(CPPFLAGS) test.h

cela génère un fichier appelé test.h.gch

Chaque fois que gcc recherche test.h, il recherche d'abord test.h.gch et s'il le trouve, il l'utilise automatiquement.

Plus d'informations peuvent être trouvées sous GCC Precompiled Headers

Simon
la source
J'utilise gcc 3.4 et la ligne g ++ stdafx.h ne compilera pas, vous obtenez l'erreur "g ++: compilation du fichier d'en-tête demandé", mais cela compilera, je ne sais pas si c'est ce que je veux cependant: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB
1

Assurez-vous de -include your_header.h

C'est ainsi que j'ai précompilé et utilisé la bits/stdc++.hcollection.

Code

#include <bits/stdc++.h>

Ensuite, j'ai localisé la bibliothèque en compilant mon fichier avec -H et en regardant la sortie

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

où j'ai vu

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

J'ai donc créé un nouveau répertoire bitsdans le répertoire actuel et copié à stdc++.hpartir de là.

Puis j'ai couru

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

qui a généré bits/stdc++.gch

Normalement, j'ai compilé mon code via

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

, mais j'ai dû modifier cela pour

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

car il a seulement résolu de .gchdéposer au lieu de .havec -include bits/stdc++.h Cela a été la clé pour moi. Une autre chose à garder à l'esprit est que vous devez compiler le *.hfichier d'en-tête avec presque les mêmes paramètres que vous compilez votre fichier *.cpp. Quand je n'ai pas inclus -O3ou -pthreadqu'il a ignoré l'en- *.gchtête précompilé.

Pour vérifier si tout est correct, vous pouvez mesurer le décalage horaire en comparant le résultat de

time g++ sol.cpp ...

ou courir

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

à nouveau et recherchez les chemins d'en-tête et si vous obtenez maintenant le !chemin de la bibliothèque, par exemple

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