wtorek, 26 maja 2009

Precompiled header

Budowanie mojego projektu przekroczyło 150.000 ms. Postanowiłem, więc skorzystać z tej techniki, aby nieco skrócić czas oczekiwania.
Zysk jest całkiem spory, różnica 36 sekund, czyli około 20 %.

A teraz jak uzyskać pre kompilowane nagłówki pod Eclipsem ?
Eclispe z CDT nie posiada narzędzi do obsługi tej techniki, więc zapomnijcie o magicznym przełączniku. Wszystko trzeba zrobić samemu.
Na szczęście GCC automatycznie wykorzystuje pch, o ile one istnieją. Sami budujemy nagłówek i umieszczamy pch w odpowiednim miejscu, a kompilator go znajdzie i wykorzysta.

Jak zrobić nagłówek?
Tworzymy zwykły plik .h i włączamy w nim wszystkie potrzebne pliki nagłówkowe.
Przykład:
#ifndef STD_H_
#define STD_H_

#include <string>
#include <fstream>
#include <sstream>
#include <map>
#include <deque>
#include <vector>

#endif /* STD_H_ */


Jak zbudować nagłówek ?
Do zbudowania nagłówka wywołujemy z linii komend "g++ -opcje -xc++-header -otest.h.gch test.h". W efekcie powinniśmy otrzymać plik test.h.gch.
- test.h to rzecz jasna nazwa pliku
- teoretycznie flaga -x nie jest potrzebna, bo gcc zna rozszerzenie .h, ale jakoś nie za bardzo bez niej chciało działać
- opcje powinny być takie same jak projektu korzystającego z nagłówka

Jak z nagłówka skorzystać ?
- pch zostanie wykorzystany automatycznie
- gcc wykorzysta ten plik, który znajdzie pierwszy, przy czym najpierw sprawdza czy w danym katalogu jest pch, dopiero potem czy jest zwykły plik. Najprościej oba pliki umieścić w tym samym katalogu
- projekt powinien mieć te same opcje co pch
- pch może być tylko jeden na raz

Co zrobić z błędem "calling fdopen: Bad file descriptor" ?
Pch może zostać użyte tylko raz podczas kompilacji. Jeżeli mamy sytuację w której plik pch zostanie włączony dwa razy, zobaczymy taki właśnie błąd. Przykładowo mamy:
foo.h włącza "std.h"
bar.h włącza "std.h"
foobar.cpp włącza "foo.h" i "bar.h"
Nie wiem jak to rozwiązują inni, ja po prostu opatrzyłem dyrektywę strażnikiem:
//Precompiled header
#ifndef STD_H_
#include "std.h"
#endif


Warto przeczytać: gcc/Precompiled-Headers