We are using Visual Studio 2003 (VC71) for compilation.
In order to reduce the compile time we changed the build script such that it generates the precompiled header (.pch) file for each CPP file.
The option used in makefile:
/Yc"StdAfx.h"
/Fp"StdAfx.pch"
With this the compile time for the target got reduced by 30%. But could anyone help me to understand how is it reducing the compiler time even when the pch file is getting generated every time for compilation of each CPP file.
Also, is it the right approach? Should we use Yc and Yu combination ?
I cannot use /Yu option as the pch file should be genrated at least once.
The problem
Let's say you have a list of headers you use that you know won't change. For example, the C headers, or the C++ headers, or Boost headers, etc..
Reading them for each CPP file compilation takes time, and this is not productive time as the compiler is reading the same headers, again and again, and producing the same compilation result for those same headers, again and again.
There should be some way to tell the compiler those headers are always the same, and cache their compiled result instead of recompiling them again and again, no?
The solution
The Pre-Compiled Headers takes that into account, so all you need is to:
Put all those common and unchanging includes in one header file (say, StdAfx.h)
Have one empty CPP file (say, StdAfx.cpp) including only this one header file
And now, what you need is tell the compiler that StdAfx.cpp is the empty source that includes the common and unchanging headers.
This is where the flags /Yc and /Yu are used:
Compile the StdAfx.cpp file with the /Yc flag
Compile all the others CPP files with the /Yu flag
And the compiler will generate (when needed) a pre-compiled header file from the StdAfx.cpp file, and then reuse this pre-compiled header file for all other files marked with /Yu.
Note
When you create a new project, old versions of Visual C++ (6 and 2003, if I remember correctly) would activate the precompiled headers by default. Recent ones offer the choice of activating them of not.
You should create a new VC++ project with the PCH activated to have a working version of PCH-enabled project, and study the compilation options.
For more information about PCH, you can visit the following URL:
http://msdn.microsoft.com/en-us/library/szfdksca.aspx
/Yc should only be used on one of your .cpp modules. This specifies to VS to create the precompiled header with that module.
For all others in your project, use /Yu. This specifies that they are to simply use the pch.
The MSDN entry for it is here: http://msdn.microsoft.com/en-us/library/szfdksca(v=VS.71).aspx
Related
This question already has answers here:
What is "stdafx.h" used for in Visual Studio?
(5 answers)
Closed 5 years ago.
What is the purpose of the file stdafx.h and what is meant by precompiled headers?
stdafx.h is a file, generated by
Microsoft Visual Studio IDE wizards,
that describes both standard system
and project specific include files
that are used frequently but hardly
ever change.
Compatible compilers (for example,
Visual C++ 6.0 and newer) will
pre-compile this file to reduce
overall compile times.
Visual C++ will
not compile anything before the
#include "stdafx.h" in the source file, unless the compile option
/Yu'stdafx.h' is unchecked (by
default); it assumes all code in the
source up to and including that line
is already compiled.
http://en.wikipedia.org/wiki/Precompiled_header
To expand on the other excellent answers:
stdafx.h is the file that includes all of the commonly used headers for a single project. This would include all of the Windows definitions, for example. Because this file includes so much stuff, the compiler gets a bit slow when processing it. By precompiling it, the compiler can skip much of the processing and reuse it over and over again; as long as none of the files included by it change, the precompiled result doesn't need to change either.
The name stdafx.h is just a convention. You could easily rename it to something else if you changed all your sources to include the new file instead.
To produce the actual precompiled header file, you need one source file in the project that has special compile flags to produce precompiled output. By convention this file is named stdafx.cpp, and if you inspect the settings for that source file you will see how it is different.
It's typically used for the name of precompiled headers. Although using that exact name is not required, just the default. I explain more about pre-compiled headers on VC++ and g++ here.
You use precompiled headers for faster compilation.
The idea is that you put any header file that will not change, and that you use in several source files inside your precompiled header. Then the compiler will not need to reprocess those headers for each compilation unit.
It's a precompiled header, to reduce compilation times.
This question already has answers here:
What is "stdafx.h" used for in Visual Studio?
(5 answers)
Closed 5 years ago.
What is the purpose of the file stdafx.h and what is meant by precompiled headers?
stdafx.h is a file, generated by
Microsoft Visual Studio IDE wizards,
that describes both standard system
and project specific include files
that are used frequently but hardly
ever change.
Compatible compilers (for example,
Visual C++ 6.0 and newer) will
pre-compile this file to reduce
overall compile times.
Visual C++ will
not compile anything before the
#include "stdafx.h" in the source file, unless the compile option
/Yu'stdafx.h' is unchecked (by
default); it assumes all code in the
source up to and including that line
is already compiled.
http://en.wikipedia.org/wiki/Precompiled_header
To expand on the other excellent answers:
stdafx.h is the file that includes all of the commonly used headers for a single project. This would include all of the Windows definitions, for example. Because this file includes so much stuff, the compiler gets a bit slow when processing it. By precompiling it, the compiler can skip much of the processing and reuse it over and over again; as long as none of the files included by it change, the precompiled result doesn't need to change either.
The name stdafx.h is just a convention. You could easily rename it to something else if you changed all your sources to include the new file instead.
To produce the actual precompiled header file, you need one source file in the project that has special compile flags to produce precompiled output. By convention this file is named stdafx.cpp, and if you inspect the settings for that source file you will see how it is different.
It's typically used for the name of precompiled headers. Although using that exact name is not required, just the default. I explain more about pre-compiled headers on VC++ and g++ here.
You use precompiled headers for faster compilation.
The idea is that you put any header file that will not change, and that you use in several source files inside your precompiled header. Then the compiler will not need to reprocess those headers for each compilation unit.
It's a precompiled header, to reduce compilation times.
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.
I ran into precompiled headers today for the first time..forever changing my life. I can't believe compiling my C++ code could be that fast. It makes total sense now..
Anyway, one thing that is confusing me is that from what I've read so far, pre-compiled headers only should be added to source files( cpp? ).
In Visual Studio, there is an option under Project Properties->C/C++->Advanced to "Force Include File". I set that compiler option to stdafx.h.
After doing this..I no longer require to include the headers I have added to my stdafx.h, even inside my header files ( source files are supposed to automatically include stdafx.h ). Is this expected behaviour?
I can't find a place that's clear in the distinction between header/source files.
If it does..great but I'm afraid it's another one of those things VC++ lets you get away with but will break in GCC. And yes..it needs to be portable; at least between GCC and VC++.
StdAfx.h really should only be included in source files, not headers. I would suggest you #include "StdAfx.h" first in every cpp and not use the "Force Include File" option. Thats how I do it with my cross-platform projects. For the record, I don't actually use precompiled headers in GCC I just build it normally and it works well.
For some background. The compiler only looks at source files (ie, *.cpp, *.c, etc) and so when it compiles them it has to include every header and compile any code found in the headers as well. The precompiled headers option allows for compiling all of that code (ie, the globally include'd code in StdAfx.h) once so that you don't have to do it all of the time. Thats what StdAfx.cpp is for. The compiler compiles StdAfx.cpp with all of the code included in StdAfx.h once instead of having to do it every time you build.
So, since you include StdAfx.h in every source file as the first item, it doesn't make sense to include it in any of the headers since they will be included AFTER StdAfx.h and thus will have access to all of the code in StdAfx.h. Plus you can then use those headers in other projects without having to worry about having a StdAfx.h around or including the wrong one.
Yes, it is expected behaviour. The Project Properties->C/C++->Advanced to "Force Include File" setting controls Visual C++ compiler option /FI:
This option has the same effect as specifying the file with double
quotation marks in an #include directive on the first line of every
source file
So, it frees you from including the stdafx.h manually.
Although, you can use precompiled headers with GCC and other compilers
The Visual C++'s shortcut behaviour is not portable across other compilers. So, check How to handle stdafx.h in cross-platform code? where ideas for portable solutions are discussed.
Long story short, include stdafx.h manually in your .cpp source files and you should be fine also with GCC (assuming, you will configure your build for GCC to use precompiled headers).
Do not use the "Force Include File" setting (/FI) as it breaks Edit & Continue !
(and MS doesn't seem to want to fix this issue)
See
https://connect.microsoft.com/VisualStudio/feedback/details/668339/vs-2010-sp1-c-edit-and-continue-fails-with-fi
and
https://connect.microsoft.com/VisualStudio/feedback/details/342441/visual-studio-2005-force-includes-breaks-edit-and-continue-with-pre-compiled-headers
#include "stdafx.h" should only be found as the first non-comment line in your source files, not in header files.
This question already has answers here:
What is "stdafx.h" used for in Visual Studio?
(5 answers)
Closed 5 years ago.
What is the purpose of the file stdafx.h and what is meant by precompiled headers?
stdafx.h is a file, generated by
Microsoft Visual Studio IDE wizards,
that describes both standard system
and project specific include files
that are used frequently but hardly
ever change.
Compatible compilers (for example,
Visual C++ 6.0 and newer) will
pre-compile this file to reduce
overall compile times.
Visual C++ will
not compile anything before the
#include "stdafx.h" in the source file, unless the compile option
/Yu'stdafx.h' is unchecked (by
default); it assumes all code in the
source up to and including that line
is already compiled.
http://en.wikipedia.org/wiki/Precompiled_header
To expand on the other excellent answers:
stdafx.h is the file that includes all of the commonly used headers for a single project. This would include all of the Windows definitions, for example. Because this file includes so much stuff, the compiler gets a bit slow when processing it. By precompiling it, the compiler can skip much of the processing and reuse it over and over again; as long as none of the files included by it change, the precompiled result doesn't need to change either.
The name stdafx.h is just a convention. You could easily rename it to something else if you changed all your sources to include the new file instead.
To produce the actual precompiled header file, you need one source file in the project that has special compile flags to produce precompiled output. By convention this file is named stdafx.cpp, and if you inspect the settings for that source file you will see how it is different.
It's typically used for the name of precompiled headers. Although using that exact name is not required, just the default. I explain more about pre-compiled headers on VC++ and g++ here.
You use precompiled headers for faster compilation.
The idea is that you put any header file that will not change, and that you use in several source files inside your precompiled header. Then the compiler will not need to reprocess those headers for each compilation unit.
It's a precompiled header, to reduce compilation times.