I was having troubles getting pre-compiled headers to work, so I came up with the following minimal-working-example.
This is the header file foo.h
#include <iostream>
using namespace std;
void hello() {
cout << "Hello World" << endl;
}
I compile this as g++ -c foo.h
gives me a compiled header foo.gch
. I expect that when I compile the following source file that includes foo.h
, it should pick the header foo.h.gch
and I am good.
// test.cpp
#include <cstdio> // Swap ordering later
#include "foo.h" // ------------------
int main() {
hello();
}
But surprisingly, this does not compile using foo.h.gch
, but rather uses foo.h
. To verify you can compile this as g++ -H test.cpp
However, if I change the order of included header files as follows:
// test.cpp
#include "foo.h" // ------------------
#include <cstdio> // Ordering swapped
int main() {
hello();
}
Now if I compile using g++ -H test.cpp
, it compiles from foo.h.gch
, whew!
So I was wondering if this is a bug in GCC or are we supposed to use pre-compiled headers like that? In either case I think its useful to know..
In a nutshell, the precompiled header thing works thus:
When you request to create a '.pch' file, the compiler processes the source file as usual. While it does so, its internal structures (mostly, name tables and all associated data) are populated. At the end, it makes a snapshot of these internal structures and saves it to the '.pch' file.
Later, when compiling a source file that includes a header for which a '.pch' file exists, the compiler can omit the expensive processing of the header file and load the ready-for-use snapshot from the '.pch' file instead.
Obviously, this can be done without affecting the semantics only if:
Anything that comes before the inclusion directive may:
Therefore, in this case, loading the snapshot of internal data structures would be wrong because there'd be no guarantee that it would leave these structures in the same state as after the normal processing of the header.
With GCC, precompiled headers work only if they are the only header, and if they are included first (without any previous header).
This answer explains more why it is so. See also the Precompiled headers chapter of GCC documentation, which says:
BTW, it could happen that pre-compiling some large header (notably in C++) is not worth the effort. YMMV.
From the GCC manual pages:
So including
<cstdio>
in your precompiled header or including it first will work.