Home » Linux » What are the pros & cons of pre-compiled headers specifically in a GNU/Linux environment/tool-chain?

What are the pros & cons of pre-compiled headers specifically in a GNU/Linux environment/tool-chain?

Posted by: admin November 30, 2017 Leave a comment


Pre-compiled headers seem like they can save a lot of time in large projects, but also seem to be a pain-in-the-ass that have some gotchas.

What are the pros & cons of using pre-compiled headers, and specifically as it pertains to using them in a Gnu/gcc/Linux environment?


The only potential benefit to precompiled headers is that if your builds are too slow, precompiled headers might speed them up. Potential cons:

  • More Makefile dependencies to get right; if they are wrong, you build the wrong thing fast. Not good.

  • In principle, not every header can be precompiled. (Think about putting some #define’s before a #include.) So which cases does gcc actually get right? How much do you want to trust this bleeding edge feature.

If your builds are fast enough, there is no reason to use precompiled headers. If your builds are too slow, I’d consider

  • Buying faster hardware, which is cheap compared to salaries

  • Using a tool like AT&T nmake or like ccache (Dirk is right on), both of which use trustworthy techniques to avoid recompilations.


I can’t talk to GNU/gcc/linux, but I’ve dealt with pre-compiled headers in vs2005:


  • Saves compile time when you have large headers that lots of modules
  • Works well on headers (say from a third party) that change very


  • If you use them for headers that change a lot,
    it can increase compile time.
  • Can be fiddly to set up and maintain.
  • There are cases where changes to headers are apparently ignored
    if you don’t force the pre-compiled header to compile.

The ccache caching frontend to gcc, g++, gfortran, … works great for me. As its website says

ccache is a compiler cache. It acts as
a caching pre-processor to C/C++
compilers, using the -E compiler
switch and a hash to detect when a
compilation can be satisfied from
cache. This often results in a 5 to 10
times speedup in common compilations.

On Debian / Ubuntu, just do ‘apt-get install ccache‘ and create soft-links in, say, /usr/local/bin with names gcc, g++, gfortran, c++, … that point to /usr/bin/ccache.

[EDIT] To make this more explicit in response to some early comments: This provides essentially pre-compiled headers and sources by caching a larger chunk of the compilation step. So it uses an idea that is similar to pre-compiled headers, and carries it further. The speedups can be dramatic — a factor of 5 to 10 as the website says.


For plain C, I would avoid precompiled headers. As you say, they can potentially cause problems, and preprocessing time is really small compared to the regular compilation.

For C++, precompiled headers can potentially save a lot of time, as C++ headers often contain large template code whose compilation is expensive. I have no practical experience with them, so I recommend you measure how much savings in compilation you get in your project. To so so, compile the entire project with precompiled headers once, then delete a single object file, and measure how long it takes to recompile that file.


The GNU gcc documentation discusses possible pitfalls with pre-compiled headers.


I am using PCH in a Qt project, which uses cmake as build system, and it saves a lot of time. I grabbed some PCH cmake scripts, which needed some tweaking, since they were quite old but it generally was easier to set up than I expected. I have to add, I am not much of a cmake expert.

I am including now a big part of Qt (QtCore, QtGui, QtOpenGL) and a few stable headers at once.


  • For Qt classes,no forward declarations are needed, and of course no includes.
  • Fast.
  • Easy to setup.


  • You can’t include the PCH include in headers. This isn’t much of a problem, exept you use Qt and let the build system translate the moc files seperatly, which happens to be exactly my configuration. In this case, you need to #include the qt headers in your headers, because the mocs are genreted from headers. Solution was to put additional include guards around the #include in the header.