What to put in precompiled header? (MSVC) - c++

What are the best candidates for a precompiled header file? Can I put STL and Boost headers there, even though they have templates? And will that reduce compile times?
Also, what are the best IDE settings to reduce compile times?

The quick answer: the STL and Boost headers do indeed belong in the precompiled header file, even though these header files define template classes.
When generating a precompiled header file, a compiler parses the header text (a significant task!), and converts it into a binary format that is optimised for the compiler's benefit.
Even though the template classes will be instantiated when other .cpp files are compiled, they will be instantiated from information in the precompiled header, which is significantly faster for the compiler to read.
(later addition)
One thing that you should not include in a precompiled header are files that are part of your project and are changed frequently, even if every single .CPP file includes these files.
The reason is this - the generation of the precompiled header can take a long time, because the boost, stl and windows libraries are very large.
You might have a simple file (eg "StringDefs.h") that everything uses. If StringDefs.h is included in stdafx.h, and one developer touches StringDefs.h, then every developer has to wait until the entire precompiled header recompiles. It would be much faster if StringDefs.h was left out of the precompiled header, and parsed along with each .CPP file.

One addition to Andrew Shepherd's answer. Use the precompiled header for header files that are external to your project, for files that change infrequently. If you're changing the header files in the current project all the time, it's probably not worth precompiling them.

I've written an article on techniques that reduce the compilation time. Among these techniques a post on precompiled header and its application can be found here. It also has a section on best practices that you may find interesting. CMake scripts that handle it transparently are included.

Put anything in the precompiled header that most of the .cpp files in that project would include anyway. This goes for any header file, really. This allows the compiler to parse these files once, and then reuse that information in all .cpp files in the same project.

Related

Every C++ header in a project as a precompiled header

The usual approach is to have one precompiled header in a project that contains the most common includes.
The problem is, that it is either too small or two big. When it is too small, it doesn't cover all the used headers so these have to be processed over and over in every module. When it is too large, it slows down the compilation too much for two reasons:
The project needs to be recompiled too often when you change something in header contained in the precompiled header.
The precompiled header is too large, so including it in every file actually slows down compilation.
What if I made all of the header files in a project precompiled. This would add some additional compiler work to precompile them, but then it would work very nicely, as no header would have to be processed twice (even preparing the precompiled header would use precompiled headers recursively), no extra stuff would have to be put into modules and only modules that are actually needed to be recompiled would be recompiled. In other words, for extra work O(N) complexity I would (theoretically) optimise O(n^2) comlexity of C++ includes. The precosseor to O(N), the processing of precompiled data would still be O(N^2), but at least minimised.
Did anyone tried this? Can it boost compile times in real life scenarios?
With GCC, the reliable way to use precompiled headers is to have one single (big) header (which #include-s many standard headers ...), and perhaps include some small header after the precompiled one.
See this answer for a more detailed explanation (for GCC specifically).
My own experience with GCC and Clang with precompiled headers is that you only can give a single pre-compiled header per compilation. See also the GCC documentation, I quote:
A precompiled header file can be used only when these conditions apply:
Only one precompiled header can be used in a particular compilation.
...
In practice, it's possible to compile every header to a precompiled header. (Recommended if you want to verify if everything is included, not recommended if you want to speed up compilation)
Based on your code, you can decide to use a different precompiled header based on the code that needs to be compiled. However, in general, it's a balancing act between compile time of the headers, compile-time of the CPP files and maintenance.
Adding a simple precompiled header that already contains several standard headers like string, vector, map, utility ... can already speed up your compilation with a remarkable percentage. (A long time ago, I've noticed a 15-20% on a small project)
The main gain you get from precompiled headers is that it:
only have to read 1 file instead of more, which improves on disk access
reads a binary format that's optimized for reading instead of plain text
it doesn't need to do all of the error checking as this was already done on creation
Even if you add a few headers that you don't use everywhere, it can still be much faster.
Lately, I also found the Clang build analyzer, it ain't ideal for big projects (see issue on github), though, it can give you some insights on where the time is being spent and what it can improve. (Or what you can improve in the codebase)
In all fairness, I don't use precompiled headers at this point in time. However, I do want to see it enabled on the project I'm working on.
Some other interesting reads:
https://medium.com/#unicorn_dev/speeding-up-the-build-of-c-and-c-projects-453ce85dd0e1
https://llunak.blogspot.com/2019/05/why-precompiled-headers-do-not-improve.html
https://www.bitsnbites.eu/faster-c-builds/

Visual studio forces to include precompiled header file in all compilation units of the project?

When compiler compiles source (e.g. *.cpp) file, it creates object file (e.g. *.o), so that later it will be linked to other .o and .so (.lib files for Windows) files and will constitute the executable file.
Now for analogical situation for not compiling header files each time it creates some .pch files so that it will be linked it by the linker then.
Now if in the scope of a Visula Studio project it is defined a precompiled header, then why Visual Studio complains with an error (e.g. **fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?**) that the header file is not included into the .cpp file.
By summarizing, here are my questions:
Why in each .cpp file the precompiled header of the project is
necessary?
How does the requirement of presence of precompiled header in each compilation unit optimizes the compilation process? In other words, what is the benefit of this requirement? (It could be up to the user to decide where to include, where not!)
If precompiled header is included into a .cpp file, which uses only 2% of what is in .pch file, then the remaining 98% will be added to corresponding .o file to?
Why in each .cpp file the precompiled header of the project is necessary?
Because you asked for it. If you don't want to use it then you need to change the option for the .cpp file. Right-click it, Properties, C/C++, Precompiled Headers, "Create/Use" = "Not using precompiled headers". The default setting is "Use". There's little point in doing this.
How does the precompiled header in each compilation unit optimizes the compilation process?
By not having to parse the #includes. Particularly useful when you #include <windows.h>. Time saved is in the order of seconds, on large projects with hundreds of .cpp files that adds up to many minutes. It is by far the cheapest way to speed up the compiler with no loss of quality on the generated code.
then the remaining 98% will be added to corresponding .o file to?
Of course not.
It's not actually necessary to include the precompiled header in every compilation unit. You can set the "not using precompiled header" setting for a single file in the C/C++->Precompiled Headers properties section for that file. This is a lot of work though, and I've never known anyone to do it in production code.
The optimization is that the precompiled header is built just once and the whole shebang is reused for all compilation units without recompiling / re-including (sort of). If you have a set of files that are included a lot of times this can save much compilation time. See The Care And Feeding of Precompiled Headers too.
No, you don't get superfluous file contents, just like you don't when static-linking.
I guess your question means "why can't the compiler assume that this header is always there if it is mandatory". The reason is that VS does not want to deviate from the standard so much. If your .cpp file is using something from a header file, it must include it. This way your file will compile exactly the same even if you turn off precompiled headers (only it will take longer).
As others have said, you can explicitly disable precompiled headers for individual files if you want. The idea is that you should only include in the precompiled header those elements that you are using in most, if not all of your files.
No, the resulting object code should be the same regardless of the header being precompiled or not.

What difference it will make, if we have uniform extension (.c/.cpp) for all C/C++ files?

In C/C++ project, mostly the file can be of either types .h or .c/.cpp. Apart from their naming difference such as header and implementation files; is there any functionality difference ?
In other words: if in a working C/C++ project what difference it makes if we change all files with .c or .cpp extension ?
[Note: We can also have #include guards for .c/.cpp files. We can skip their compilation if they are observed as headers.]
Edit:
Debate is not intended for this as I don't have any solid use case. Rather I wanted to know, that allowing to give .h,.hxx,.i extensions are just a facility or a rule. e.g. One functionality difference I see is that .cxx files can have their likable object files.
What difference does it make? The compiler is perfectly happy about it. To it, it's just files.
But to you? You makes a lot of difference:
you're no longer able to immediately figure out which one is the header and which one is the implementation;
you can no longer give header and implementation the same name;
If you are using gcc, and you try and compile a bunch of C++ files labled with a .c extension, it's going to try and compile your file as-if it were a C-language file, which is going to create a ton of errors.
There's also project sanity as well ... this is why many times you'll see projects actually label C++ headers as .hpp rather than just .h so that it's easier to create a distinction between C-language source-code and headers, and C++ source-code and headers.
Header files generally must not be compiled directly but instead #included in a file that is directly compiled. By giving these two groups of files their own extension it makes it a lot easier to determine which to compile.
Make and IDE's and other tools normally expect the conventions of .c/.cpp for source and h/hpp for header. Compiler normally goes a step further and defaults to C compilation for .c and c++ compilation for .cpp
Hence, a bad idea to give your headers the same extension as the the source files.

Precompiled headers: do's and don'ts?

I know precompiled headers are used for speeding up compilations, but are there any do's and don'ts to what files I should include in them? For example, I have a project that uses a lot of boost libs so I just include the boost header files in stdafx.h (I'm using VS2008). Should I include every standard header file in them, too? Will this increase the size of my executeable even if I, for example, include <vector> but never use std::vector? Is it a bad idea to include my own project's header files in stdafx.h?
Generally speaking, every header file that you use across the application and that doesn't change often should go into the precompiled header file. This will speed up compilation because the precompiled header file gets compiled only once.
If you add a header file which changes often, you'll miss the point of the precompiled header file, because this often-changing header file will cause your whole project to recompile, possibly unnecessarily.
Specifically, defines a template class, so if you won't use std::vector, the overhead will not be big. However, I would advise against adding header files - however standard and generic - if you don't really need them. There IS some overhead to the compilation time, the binary size, and it could cause conflicts later in the project, so why add something if you don't really need it?
Pre-compiled headers don't affect the size of your executable, only the compilation speed. Since they are pre-compiled, they don't have to be re-compiled all the time. Windows.h is the primary beneficiary of this feature.
It's a good idea to include the c++ standard header-files and the boost library headers and any other headers from third party libraries that you frequently use. This will not affect the size of your executable.
However, you should not include headers from your own project, since the whole project needs to be rebuild whenever you make changes in these headers.

Pre-Compiled Header Design Question

I have code that uses a pre-compiled header. (previously done by someone else)
In it, they are including several .h files.
If I have classes that use common .h files that are not currently in the existing pre-compiled header, would tossing them in there be of any real benefit? Maybe compilation speed, but I was thinking it would clean up the classes/headers a bit too?
What are do's and don't with pre-compiled headers?
DO NOT rely on headers being included by your precompiled header for "code cleanup" by removing those headers from your other source files. This creates a nightmare if you ever want to stop using PCH. You always want your dependencies to be explicit in every source file. Just include them in both places -- there is no harm in it (assuming you have appropriate include guards in place).
A header file that is included by multiple source files is a good candidate for inclusion in the PCH (particularly if it is lengthy). I find that I don't take the advice too seriously to only put headers that rarely change into the PCH. But, this depends on your overall project structure. If you frequently do full builds, definitely avoid this advice. If you want to minimize the work in incremental rebuilds, then it's a consideration. In my experience, rebuilding the PCH is relatively fast, and the cost of this is far outweighed by the overall speedup of compilation in general (in most cases). I'm not sure if all PCH systems are smart enough to figure out that every source file does not need to be rebuilt when a header included in the PCH changes (VC++ is), but explictly #includeing everything you need in every translation unit will surely facilitate this (another reason you should not rely on what is included by your PCH)
If your compiler supports an option to show the #include tree for each file during compilation, this can be a great help to identify headers that should be included in the PCH (the ones that show up the most). I recently went through this on a project I'm working on (which was already using PCH, but not optimally) and sped up the build of 750K lines of C++ from roughly 1.5 hours to 15 minutes.
Put non-changing system includes into the precompiled header. That will speed up compilation. Don't put any of your own header files that you might change into the precompiled header, because each time you change them you will have to rebuild the entire precompiled header.
It is a trade-off: system/library headers definitely go in the PCH, for ones in your project it depends.
Our project has a large amount of generated code that is changed much less frequently that other parts of the project. These headers go in the PCH because they take a lot of time to process in each individual file. If you change them it is expensive, but you have to weigh that cost against the more frequent smaller savings of having them in the file.