Prekompilowane nagłówki z GCC

91

Czy ktoś odniósł sukces w uzyskaniu prekompilowanych nagłówków przy współpracy z GCC? Nie miałem szczęścia w moich próbach i nie widziałem wielu dobrych przykładów, jak to skonfigurować. Próbowałem na cygwin gcc 3.4.4 i używam 4.0 na Ubuntu.

Lee Baldwin
źródło
Wypróbowałem to i miałem optymalny przypadek użycia prekompilowanych nagłówków, ponieważ moje źródło c jest generowane przez kompilator, a nie napisane przez użytkownika. Sun Studio, a zwłaszcza Visual Studio, znacznie poprawiły czas kompilacji. Na gcc było jeszcze gorzej bez prekompilowanych nagłówków. To było z wersją 3.4 nie testet z 4.x, ale prędkość i gcc wykluczają się wzajemnie.
Lothar
@Lothar jaki był kod? Uważam, że g ++ jest około 10 razy szybszy niż najnowsze kompilatory Visual Studio, na niektórych mocno szablonowych kodach.
świnia
Nie używam szablonów w moim kodzie C ++. To tylko obsługa wyjątków w C + + ładne rozszerzenia C ++. Nawet teraz, 6 lat po tym pytaniu, VS2010 jest o wielkość szybsza. Ale w międzyczasie mam 16 rdzeni, więc mogę z tym żyć.
Lothar

Odpowiedzi:

59

Zdecydowanie odniosłem sukces. Najpierw użyłem następującego kodu:


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

To był po prostu świat powitania Boost Xpressive (link poniżej). Najpierw skompilowałem z -Hopcją w gcc. Pokazał ogromną listę używanych przez siebie nagłówków. Następnie przyjrzałem się flagom kompilacji, które tworzyło moje IDE (code :: blocks) i zobaczyłem coś takiego:

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

Napisałem więc polecenie skompilowania pliku Xpressive.hpp z dokładnie tymi samymi flagami:

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

Ponownie skompilowałem oryginalny kod -Hi otrzymałem następujące dane wyjściowe:

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

The! oznacza, że ​​kompilator mógł użyć prekompilowanego nagłówka. Znak x oznacza, że ​​nie mógł go użyć. Używanie odpowiednich flag kompilatora jest kluczowe. Zdjąłem -H i przeprowadziłem kilka testów szybkości. Wstępnie skompilowany nagłówek miał poprawę z 14 do 11 sekund. Nieźle, ale nie świetnie.

Uwaga: Oto link do przykładu: http://www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples Nie udało mi się go uruchomić w Poczta.

BTW: używam następującego g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Użytkownik1
źródło
20
Dodanie -Winvalid-pch pomoże ci debugować, jeśli i dlaczego coś pójdzie nie tak w użyciu PCH.
lefticus
Prekompilowane nagłówki „niezłe, ale nie świetne” są przydatne, gdy masz wiele nagłówków, które ponownie łączą się ze sobą, więc skracają czas kompilacji w bardzo dużym projekcie, który używa dużych bibliotek lub wielu bibliotek.
jokoon
4
„Nieźle, ale nie świetnie”: przy użyciu gcc 4.4.7, 136 plików .cpp, całkowity rozmiar 35,5 Mb, pliki .h 148, całkowity rozmiar 5,5 Mb, plik .gch ma 48 Mb, kompilacja debugowania zajmuje 2'20 "(w porównaniu z 2 '14 "non-pch), kompilacja zoptymalizowana pod kątem -O2 zajmuje 4'30" (w porównaniu z 5'33 "non-pch) Efekt byłby oczekiwany w pobliżu kompilacji debugowania, ale to tylko zoptymalizowana kompilacja, która korzysta z prekompilacji ... Nie pewny dlaczego. Prekompilowanie jest o wiele bardziej dramatyczne w systemie Windows!
Andreas Vergison
1
(cd.) Odpowiednie pliki wyjściowe pch / non-pch mają dokładnie taki sam rozmiar w bajtach, to dobrze. Powyższe czasy wydają się różnić podczas powtarzania kompilacji, na przykład -O2 non-pch waha się między 3'45 "a 5'33", więc nie jest to ścisła nauka, być może ze względu na działanie w VMware. W każdym razie, gcc pch wcale nie wygląda na korzystne w moim przypadku. Porównaj to z tym samym kodem bazowym w systemie Windows VS2012 (x64, kompilacja jednowątkowa): debugowanie 46 "pch, 2'50" non-pch, release 2'13 "pch, 5'02" non-pch. I oczywiście nawet dużo szybciej, gdy włączysz wieloprocesor ...
Andreas Vergison,
@AndreasVergison - Czy próbowałeś użyć, -Winvalid-pchaby upewnić się, że prekompilowany nagłówek jest prawidłowo używany? Zauważamy dużą poprawę w używaniu pch do naszych kompilacji debugowania, więc zastanawiam się, czy jest problem z twoją konfiguracją.
Josh Kelley,
52

Po pierwsze, zapoznaj się z dokumentacją tutaj .

Kompilujesz nagłówki jak każdy inny plik, ale umieszczasz wynik wewnątrz pliku z przyrostkiem .gch.

Na przykład, jeśli prekompilujesz stdafx.h, będziesz miał prekompilowany nagłówek, który będzie automatycznie wyszukiwany za stdafx.h.gchkażdym razem, gdy dołączyszstdafx.h

Przykład:

stdafx.h:

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

a.cpp:

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

Następnie skompiluj jako:

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

Twoja kompilacja będzie działać, nawet jeśli usuniesz stdafx.h po kroku 1.

Brian R. Bondy
źródło
8

Specyfikatorem -xprekompilowanych nagłówków C ++ -x c++-headernie jest -x c++. Poniżej przedstawiono przykładowe użycie 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.

Wygeneruj PCH w ten sposób:

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

pch.h.gchMusi być w tym samym katalogu co pch.hżeby być używany, więc upewnij się, że wykonanie powyższego polecenia z katalogu, w którym pch.hjest.

psaghelyi
źródło
3
To powinno być -c pch.h, nie -c pch.cpp?
MM
7

W przeszłości udało mi się uzyskać prekompilowane nagłówki działające pod gcc i pamiętam, że wtedy też miałem problemy. Należy pamiętać, że gcc zignoruje plik (header.h.gch lub podobny), jeśli nie zostaną spełnione określone warunki, których listę można znaleźć na stronie dokumentacji prekompilowanego nagłówka gcc .

Ogólnie najbezpieczniej jest, aby system kompilacji kompilował plik .gch jako pierwszy krok, z tymi samymi opcjami wiersza poleceń i plikiem wykonywalnym, co reszta źródła. Dzięki temu plik jest aktualny i nie ma żadnych subtelnych różnic.

Prawdopodobnie dobrym pomysłem jest również uruchomienie go najpierw z wymyślonym przykładem, aby usunąć możliwość, że twoje problemy są specyficzne dla kodu źródłowego w twoim projekcie.

Paweł
źródło
7

Wywołaj gcc tak samo, jak wywołujesz go dla pliku źródłowego, ale z plikiem nagłówkowym.

na przykład

g++ $(CPPFLAGS) test.h

generuje to plik o nazwie test.h.gch

Za każdym razem, gdy gcc szuka test.h, najpierw szuka test.h.gch i jeśli je znajdzie, używa go automatycznie.

Więcej informacji można znaleźć w sekcji Prekompilowane nagłówki GCC

Szymon
źródło
Używam gcc 3.4 i linia g ++ stdafx.h nie skompiluje się, pojawia się błąd „g ++: zażądano kompilacji pliku nagłówkowego”, ale to się skompiluje, ale nie jestem pewien, czy tego chcę: „g ++ -c -x c ++ stdafx.h -o
stdafx.h.pch
1

Upewnij się -include your_header.h

W ten sposób wstępnie skompilowałem i użyłem bits/stdc++.h kolekcji.

Kod

#include <bits/stdc++.h>

Następnie zlokalizowałem bibliotekę, kompilując mój plik z -H i patrząc na wyjście

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

gdzie widziałem

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

Więc utworzyłem nowy katalog bitswewnątrz obecnego i skopiowałem stdc++.hstamtąd.

Potem uciekłem

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

który wygenerował bits/stdc++.gch

Zwykle skompilowałem swój kod za pośrednictwem

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

, ale musiałem to zmienić na

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

ponieważ zdecydowano się tylko .gchzłożyć plik zamiast .hz -include bits/stdc++.h To było dla mnie kluczowe. Inną rzeczą, o której musisz pamiętać, jest to, że musisz skompilować *.hplik nagłówkowy z prawie takimi samymi parametrami, jak kompilujesz plik *.cpp. Kiedy nie uwzględniłem -O3lub -pthreadzignorowałem *.gchprekompilowany nagłówek.

Aby sprawdzić, czy wszystko jest w porządku, możesz zmierzyć różnicę czasu, porównując wynik

time g++ sol.cpp ...

lub biegnij

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

ponownie i poszukaj ścieżek nagłówka, a jeśli masz teraz !na przykład ścieżkę do biblioteki

! ./bits/stdc++.h.gch
....
Íhor Mé
źródło