views:

621

answers:

6

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?

+1  A: 

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.

Dirk Eddelbuettel
-1: I'm not sure this has anything to do with pre-compiled headers.
quamrana
This has nothing to do with precompiled headers.
Martin v. Löwis
@Martin: It just renderes precompiled headers useless. Speeds up compilation, even without pre-compiled headers.
elcuco
Nonsense. I avoids recompilations, which is fine, but something different. In single project it usually saves you __nothing__ if your build system is halfway decent. PCH speeds up compilation itself.
drhirsch
I'm sure you're right about `ccache`, it was used on a project I worked on, and so your answer might be great if it were answering a question like 'Which is better pre-compiled headers or ccache?', or 'Are there any alternatives to pre-compiled headers for speeding up compilation?'. But not this question.
quamrana
Honestly I think it *is* relevant even if it doesn't answer the specific question.
Catskul
+2  A: 

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

Pros:

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

Cons:

  • 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.
quamrana
The OP asked about GNU/Linux.
Dirk Eddelbuettel
Nevertheless, the pro and cons also apply to gcc.
Soo Wei Tan
+3  A: 

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.

Martin v. Löwis
+4  A: 

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.

Norman Ramsey
Actually gcc handles PCH pretty well. If a #define exists before you include the pch, the pch is simply not used and the normal includes are used. You might also want to consider updating yourself somewhat, PCH exist now for some five years in gcc and isn't exactly bleeding edge anymore.
drhirsch
On top of ccache, one can also use distcc across a number of machines.
Dirk Eddelbuettel
@drhirsch: I'm a cautious gcc user. Every time there's a new release, something breaks. For me, five years is still bleeding edge.
Norman Ramsey
@drhirsch: what about the case of #ifndef FOO_H; #define FOO_H; #include <stdio.h>; ...; #endif ??? Will headers be precompiled?
Norman Ramsey
This case is handled without any error and transparent to the user, but you would never use PCHs this way, execpt <cstdio> is all you ever need. Sorry, but you seem to lack even basic understanding of PCH. I recommend reading http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html .
drhirsch
A: 

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.

Pros:

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

Cons:

  • 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.
drhirsch
From almost everyone I've talked to, "Easy to setup" is about as far from the consensus as you can get. Can you elaborate?
Catskul
Sorry, but I can't format comments, so this comes wrapped.In CMakeLists.txt I added two lines 'include(PCHSupport)' and 'ADD_PRECOMPILED_HEADER(myprojectname ${CMAKE_SOURCE_DIR}/pch.h)'. In the implementation files of the project I use a '#include <pch.h>' at the beginning. Because of the sepcialities of the qt build systems using automoc, I have to include pch.h in the headers to, this works with additional include guards. The latter was actually the hardest part to figure out, but I had it working in less than an hour, so I consider it to be "easy".
drhirsch
+1  A: 

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

Dirk Eddelbuettel