Vorkompilierte Header mit GCC

91

Hat jemand Erfolg damit gehabt, vorkompilierte Header mit GCC zu arbeiten? Ich hatte kein Glück bei meinen Versuchen und ich habe nicht viele gute Beispiele für die Einrichtung gesehen. Ich habe Cygwin GCC 3.4.4 und 4.0 unter Ubuntu ausprobiert.

Lee Baldwin
quelle
Ich habe es versucht und hatte den optimalen Anwendungsfall für vorkompilierte Header, da meine c-Quelle vom Compiler generiert und nicht vom Benutzer geschrieben wurde. Sun Studio und insbesondere Visual Studio haben die Erstellungszeit erheblich verbessert. Auf gcc wurde es noch schlimmer als ohne vorkompilierte Header. Dies war mit 3.4 nicht mit 4.x getestet, aber Geschwindigkeit und gcc schließen sich gegenseitig aus.
Lothar
@ Lothar was war der Code? Ich finde g ++ ungefähr 10x schneller als die jüngsten Visual Studio-Compiler, auf Code mit starken Vorlagen.
Das Schwein
Ich verwende keine Vorlagen in meinem C ++ - Code. Es ist nur C + Ausnahmebehandlung + nette C ++ - Erweiterungen. Selbst jetzt, 6 Jahre nach dieser Frage, ist VS2010 eine Größenordnung schneller. Aber in der Zwischenzeit habe ich 16 Kerne, damit ich damit leben kann.
Lothar

Antworten:

58

Ich habe definitiv Erfolg gehabt. Zuerst habe ich den folgenden Code verwendet:


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

Dies war nur eine Hallo-Welt von Boost Xpressive (Link siehe unten). Zuerst habe ich mit der -HOption in gcc kompiliert . Es zeigte eine enorme Liste der verwendeten Header. Dann habe ich mir die Kompilierungsflags angesehen, die meine IDE (code :: blocks) erzeugt hat, und so etwas gesehen:

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

Also habe ich einen Befehl geschrieben, um die Xpressive.hpp-Datei mit genau denselben Flags zu kompilieren:

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

Ich habe den Originalcode erneut mit dem kompiliert -Hund diese Ausgabe erhalten:

g ++ -Wand -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

Das ! bedeutet, dass der Compiler den vorkompilierten Header verwenden konnte. Ein x bedeutet, dass es nicht verwendet werden konnte. Die Verwendung der entsprechenden Compiler-Flags ist von entscheidender Bedeutung. Ich nahm den -H ab und führte einige Geschwindigkeitstests durch. Der vorkompilierte Header hatte eine Verbesserung von 14 Sekunden auf 11 Sekunden. Nicht schlecht, aber nicht großartig.

Hinweis: Hier ist der Link zum Beispiel: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Ich konnte es nicht zum Laufen bringen Post.

Übrigens: Ich benutze das folgende g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Benutzer1
quelle
20
Das Hinzufügen von -Winvalid-pch hilft Ihnen beim Debuggen, ob und warum bei der Verwendung des PCH etwas schief geht.
Lefticus
"nicht schlecht, aber nicht großartig" vorkompilierte Header sind nützlich, wenn Sie viele, viele Header haben, die sich gegenseitig verknüpfen, sodass sie die Kompilierungszeit bei sehr großen Projekten reduzieren, die große Bibliotheken oder viele Bibliotheken verwenden.
Jokoon
4
"nicht schlecht, aber nicht großartig": unter Verwendung von gcc 4.4.7, 136 .cpp-Dateien 35,5 MB Gesamtgröße, 148 .h-Dateien 5,5 MB Gesamtgröße, die .gch-Datei ist 48 MB, Debug-Build dauert 2'20 "(vs 2) '14 "non-pch), -O2-optimierter Build benötigt 4'30" (vs 5'33 "non-pch) Der Effekt wäre in der Nähe von Debug-Builds zu erwarten, aber es ist nur der optimierte Build, der von der Vorkompilierung profitiert .... Nicht sicher warum. Das Vorkompilieren ist unter Windows viel dramatischer!
Andreas Vergison
1
(Fortsetzung) Entsprechende pch / non-pch-Ausgabedateien haben genau die gleiche Bytegröße, das ist gut. Die oben genannten Zeitpunkte scheinen zu variieren, wenn die Builds wiederholt werden. Beispielsweise variiert -O2 non-pch zwischen 3'45 "und 5'33", sodass dies keine exakte Wissenschaft ist, möglicherweise aufgrund der Ausführung in VMware. Wie auch immer, gcc pch sieht in meinem Fall überhaupt nicht vorteilhaft aus. Vergleichen Sie es mit derselben Codebasis unter Windows VS2012 (x64, Single-Threaded-Kompilierung): Debuggen Sie 46 "pch, 2'50" non-pch, Release 2'13 "pch, 5'02" non-pch. Und natürlich noch viel schneller, wenn
Multiprozessor
@AndreasVergison - Haben Sie versucht -Winvalid-pch, sicherzustellen, dass der vorkompilierte Header ordnungsgemäß verwendet wird? Wir bemerken eine große Verbesserung bei der Verwendung von pch für unsere Debug-Builds, daher frage ich mich, ob es ein Problem mit Ihrem Setup gibt.
Josh Kelley
52

Lesen Sie zunächst die Dokumentation hier .

Sie kompilieren Header wie jede andere Datei, aber Sie fügen die Ausgabe in eine Datei mit dem Suffix von ein .gch.

Wenn Sie beispielsweise stdafx.h vorkompilieren, haben Sie einen vorkompilierten Header, nach dem automatisch gesucht wird, stdafx.h.gchwenn Sie ihn einschließenstdafx.h

Beispiel:

stdafx.h:

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

a.cpp:

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

Dann kompilieren als:

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

Ihre Kompilierung funktioniert auch dann, wenn Sie stdafx.h nach Schritt 1 entfernen.

Brian R. Bondy
quelle
8

Der -xBezeichner für vorkompilierte C ++ - Header ist -x c++-headernicht -x c++. Es folgt eine beispielhafte Verwendung von 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.

Generieren Sie den PCH wie folgt:

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

Das pch.h.gchmuss sich im selben Verzeichnis wie das befinden pch.h, um verwendet zu werden. Stellen Sie daher sicher, dass Sie den obigen Befehl in dem Verzeichnis ausführen, in dem sich das Verzeichnis pch.hbefindet.

Psaghelyi
quelle
3
Das sollte -c pch.hnicht sein -c pch.cpp?
MM
7

Ich habe es in der Vergangenheit einmal geschafft, vorkompilierte Header unter gcc zum Laufen zu bringen, und ich erinnere mich, dass ich damals auch Probleme hatte. Beachten Sie, dass gcc die Datei (header.h.gch oder ähnliches) ignoriert, wenn bestimmte Bedingungen nicht erfüllt sind. Eine Liste davon finden Sie auf der Dokumentationsseite des vorkompilierten gcc-Headers .

Im Allgemeinen ist es am sichersten, wenn Ihr Build-System die .gch-Datei als ersten Schritt mit denselben Befehlszeilenoptionen kompiliert und ausführbar ist wie der Rest Ihrer Quelle. Dies stellt sicher, dass die Datei auf dem neuesten Stand ist und keine subtilen Unterschiede bestehen.

Es ist wahrscheinlich auch eine gute Idee, es zuerst mit einem erfundenen Beispiel zum Laufen zu bringen, um die Möglichkeit auszuschließen, dass Ihre Probleme spezifisch für den Quellcode in Ihrem Projekt sind.

Paul
quelle
7

Rufen Sie gcc genauso auf, wie Sie es für Ihre Quelldatei aufrufen, jedoch mit einer Header-Datei.

z.B

g++ $(CPPFLAGS) test.h

Dadurch wird eine Datei mit dem Namen test.h.gch generiert

Jedes Mal, wenn gcc nach test.h sucht, sucht es zuerst nach test.h.gch und wenn es es findet, verwendet es es automatisch.

Weitere Informationen finden Sie unter Vorkompilierte GCC-Header

Simon
quelle
Ich verwende gcc 3.4 und die Zeile g ++ stdafx.h wird nicht kompiliert. Sie erhalten die Fehlermeldung "g ++: Kompilierung der angeforderten Header-Datei", aber dies wird kompiliert, nicht sicher, ob ich das möchte: "g ++ -c -x c ++ stdafx.h -o stdafx.h.pch "
stefanB
0

Stellen Sie sicher, dass -include your_header.h

So habe ich die bits/stdc++.hSammlung vorkompiliert und verwendet .

Code

#include <bits/stdc++.h>

Dann habe ich die Bibliothek gefunden, indem ich meine Datei mit -H kompiliert und die Ausgabe betrachtet habe

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

wo ich gesehen habe

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

Also habe ich ein neues Verzeichnis bitsinnerhalb des aktuellen erstellt und stdc++.hvon dort kopiert .

Dann rannte ich

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

welches erzeugt bits/stdc++.gch

Normalerweise habe ich meinen Code über kompiliert

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

, aber ich musste das ändern

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

da es sich nur entschied, .gchstatt .hmit zu -include bits/stdc++.h archivieren, war das der Schlüssel für mich. Eine andere Sache, die Sie beachten sollten, ist, dass Sie die *.hHeader-Datei mit fast den gleichen Parametern kompilieren müssen, mit denen Sie Ihre kompilieren *.cpp. Wenn ich den vorkompilierten Header nicht aufgenommen -O3oder -pthreadignoriert habe *.gch.

Um zu überprüfen, ob alles korrekt ist, können Sie den Zeitunterschied messen, indem Sie das Ergebnis von vergleichen

time g++ sol.cpp ...

oder laufe

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

Suchen Sie erneut nach Header-Pfaden und suchen Sie !beispielsweise vor dem Bibliothekspfad

! ./bits/stdc++.h.gch
....
Mhor Mé
quelle