What to add to precompiled headers

c++, compilation, include, precompiled-headers

Solution

There is no 100% exact answer to this as it depends on your project. Best thing is to try it yourself and see what happens.

However,

"So, do I literally include every third party library? "

No, basically you include headers, which:

- Are used often by your sources. "Often" however is not quite defined, but let's say it's used by more then 10% of your source files. (I picked the number randomly, however. Maybe it should be bigger.)

- Are not changed the most of the time (because change of single header means you need to recompile all your sources). Third party libraries are not expected to be changed, so they're best candidate, but you can also use headers from your own project, too, if you're sure they will be changed rarely or in exceptional cases.

But don't "just" include all headers of a library. Include ones you're using.

"If I use a map in three source files, do I add it?"

See above. There is no clear answer to this, but personally I think three source files is too little.

"What if I use it one, do I add it?"

(I understand the question as it would be "What if I use a header file in single source and add it to precompiled header?")

Nothing what would break your application. But it will make:

- Compilation of precompiled header longer.

- Precompiled header file bigger.

- Compilation of source files slower.

In case of single header it's completely insignificant if the header is of average size. However if you add hundreds of such headers, you slow down whole compilation.

"Do I need to remove the old direct include or are the ifdef and pragma once directives still working?"

You probably could do such thing, but I highly recommend NOT to do it. You're not required to do so, however.

You can imagine that precompiled header is nothing but just include of the header at beginning of your all sources. Example:

precompiled.h

#include <iostream>
#include <string>

MyClass.cpp

#include "MyClass.h"

MyClass::MyClass()
{
// etc.

Now let's say you enable precompiled header. For source file it's same as if you would write:

#include "precompiled.h"
#include "MyClass.h"

MyClass::MyClass()
{
// etc. 

Can you do that normally? Yes, you can! Precompiled header acts like that (but it's faster), which means:

- Yes, macros are preserved. Whatever is defined in precompiled headers is defined in all source files, which means:

- Guards are working normally.

- If there is a library which detects OS, all the macros are still defined and available.

- If there is other macro defined (for example MIN (although using std::min is now recommended)) you can still use it normally.

- I don't know about pragma, but I believe it works normally, too.

About removing includes in sources: as I stated above, I'm highly against it. Reason is simple: what if you would need to turn off precompiled headers in future? (In fact, I personally turn off the precompiled header from time to time to see whether my code still compiles. My personal reason is that if you release the code, some users will not use your project/make files but they will create their own project (for example if they use different IDE like Code::Blocks or QtCreator) and so I try to make my project in such way that all you need is to add source files, configure correct include path, link correct libraries and it should compile.)

"Are there any third party libraries you wouldn't add?"

I can't think of any...

On the other hand, I can think of some which are IMHO best to be added (if you use them) - for example boost. It uses, most of the time, templates - and to according my personal experience, templates are slowing compilation the most, because you need to include not onlu declarations, but also definitions. IMHO that's the biggest weakness of C++ templates.

"Doesn't the precompiled header then get massive? "

They can. That's why you need to find the best subset of header files (and not to include blindly everything) to get optimal result. Mine is about 50MB big, but still speeding up the compilation very much. (Whole minutes as I use templates quite a lot.)

"As in, isn't there an overhead of having all these headers included everywhere all of a sudden, even in precompiled form?"

If you use precompiled header, you prepare some set of headers and include them to all source files. This means, from point of single source file, that you include some headers which are not needed by the source file. That is the overhead. However, inclusion of precompiled headers is much faster, so if you include a few unneeded headers, it will be still faster. However when you cross some limit (let's say that in case when for more than 90% sources more than 90% included headers are unneeded) when using precompiled headers starts slow down the compilation. That's why you need to include headers which are used mostly and avoid inclusion of headers which are included only in few source files (or not used at all).

Generally, using precompiled headers increase needed space on disk (in these times, absolutely insignificantly) and needed space in RAM (again, in these times not much important). It's perfect example of "getting more speed at the cost of memory".

The last advice is simple: try it yourself. Check what happens when you add headers and when you feel your compilation is slow, check whether you include something which is mostly not used.

Problem

I am new to precompiled headers, and am just wondering what to include. Our project has about 200 source files. So, do I literally include every third party library? If I use a map in three source files, do I add it? What if I use it one, do I add it? Do I need to remove the old direct include or are the ifdef and pragma once directives still working? Are there any third party libraries you wouldn't add? Doesn't the precompiled header then get massive? As in, isn't there an overhead of having all these headers included everywhere all of a sudden, even in precompiled form? EDIT: I found some information on clang: A precompiled header implementation improves performance when: - Loading the PCH file is significantly faster than re-parsing the bundle of headers stored within the PCH file. Thus, a precompiled header design attempts to minimize the cost of reading the PCH file. Ideally, this cost should not vary with the size of the precompiled header file. - The cost of generating the PCH file initially is not so large that it counters the per-source-file performance improvement due to eliminating the need to parse the bundled headers in the first place. This is particularly important on multi-core systems, because PCH file generation serializes the build when all compilations require the PCH file to be up-to-date. Clang's precompiled headers are designed with a compact on-disk representation, which minimizes both PCH creation time and the time required to initially load the PCH file. The PCH file itself contains a serialized representation of Clang's abstract syntax trees and supporting data structures, stored using the same compressed bitstream as LLVM's bitcode file format. Clang's precompiled headers are loaded "lazily" from disk. When a PCH file is initially loaded, Clang reads only a small amount of data from the PCH file to establish where certain important data structures are stored. The amount of data read in this initial load is independent of the size of the PCH file, such that a larger PCH file does not lead to longer PCH load times. The actual header data in the PCH file--macros, functions, variables, types, etc.--is loaded only when it is referenced from the user's code, at which point only that entity (and those entities it depends on) are deserialized from the PCH file. With this approach, the cost of using a precompiled header for a translation unit is proportional to the amount of code actually used from the header, rather than being proportional to the size of the header itself. To me this seems to indicate that at least clang: - has taken care to make load times of precompiled headers independent of size. - Use times of precompiled headers are independent of precompiled header size, and are proportional to amount of used information - Contrary to answers given so far, this seems to indicate that even when included an external file (say `<map>`) just once, it is worthwhile including it in the precompiled headers (will still speed up re-compilation of that sourcefile) There must be some sort of map to map out all the info. This map might get larger, but maybe that isn't so important? Not sure whether I got this right though, or whether it applies to all compilers...

Original source

Related problems