Inside niven, I've been using precompiled headers since the first version. Read on for some insights I gained over the years.
The following is written while I was using the Microsoft Visual C++ 8.0 compiler. It is probably also true for earlier versions, but I cannot check that.
niven had precompiled headers right from the beginning. They used to
contain often used internal headers and large parts of the STL
vector, etc.). Over the time, a lot of headers from
Boost found their way into the precompiled
header. The last version I had compiled to a 47 MiB large
Compilation time was roughly one minute for the core library, which was
already pretty good given the size and complexity of the source code.
I've been using the best practices for physically decoupling the code.
This means each header forward declared as much as possible and includes
were delayed so most of the happened in the
.cpp file (where they
should be). In addition, often used headers were put into a single
precompiled header and compiled just once for the application.
The Fast & the Curious
Well, as always, fast was not fast enough for me (1 minute for a full
recompile on my notebook - as if I would have a spare minute :) ). I've
taken a deep look at what should really go into the precompiled header,
commenting everything out first. Step by step, I could strip down
approximately half of my precompiled header, reducing the compile time
down to 37 seconds - now my notebook is just as fast as my desktop
.pch file is now 30 MiB - a 33% reduction.
The most expensive headers are those taking huge parts of the STL and
other template magic with them. For example, including
<boost/bind.hpp> can easily double the compile time per source file!
Compared to this, files with a lot of preprocessor magic (in my case,
<boost/signals.hpp>) don't make a visible difference. I've moved them
out and back of the precompiled header, but I could not measure any
improvement - seems the preprocessor is really fast. Also, be aware that
some headers tend to include stuff you don't think about usually. For
<list> - after removing the
former from the precompiled header, some parts of my code complained
about not finding the latter. An interesting result of this is that
eventually, the compiler is able to process a lot of files per second
now. You don't see individual files popping up in the output window but
batches of three or even more files - woohoo! Link time and precompiled
header generation is now dominating the build time. I presume most of it
is spent in the interprocedural optimization step, as the core library
is linking basically against the bare minimum you have to link
(C-Runtime, C++-Runtime, some Windows specific libraries). As soon as I
get a chance, I'll try with the Intel C++ 9.1 Compiler to see how big
the difference is over there.