Precompiled headers - necessary to remove all precompiled headers from all other files - c++

I have a very big project and for the sake of compilation speed I started to test precompiled headers.
I've setup everything now:
enable precompiled headers in VS (use them for the project, create it for the StdAfx.honly)
use multi processor compilation for all but for the StdAfx.h
automatically include the StdAfx.h in all my files via the force include of VS
The question that occurs now is following:
Do I need to remove all includes of all project files that I've added to the StdAfx.h file or is this unnecessary? Will the compiler skip any include automatically because he knows it's part of the StdAfx.h or should I remove them from each .h/.cpp file manually?

The good practice is to make each file include all the headers directly required by this file. This way changing includes in particular file should effect only this file. If you start depending on headers included somewhere else it will make your project structure extremely fragile. And the single "common includes" file is an extreme case of such scenario. Use of precompiled header supposed to speedup compilation by prebuilding commonly included header files, but project files should never assume that something is already included there. So there is no need need to remove includes from ".h/.cpp", actually there are some tools that will populate precompiled header based on includes in project files. Compiler will skip files already included in precompiled header (or in other headers) because of header guards.

Related

referencing the precompiled header from a subfolder causes build to fail [duplicate]

With "Show all files" option on in VS, i added a folder and created a new class in that folder. Since i'm using precompiled headers i also need to include the stdafx.h that's in the root directory relative to the new class file.
In my cpp file i have
#include "..\stdafx.h"
Yet I get the following error:
error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
My understanding is, that the .. should instruct the compiler to go one directory level up ?
Visual C++ allows you to define several ways of setting up precompiled header files. The most common is to enable it for ALL source files at the project configuration level, Under Configuration Properties/C++/Precompiled Headers, setting "Precompiled Header", select "Use". The same location, setting "Precompiled Header File", is usually "stdafx.h". All files will get this setting (thus the configuration at the project) EXCEPT....
One file is responsible for generating the PCH file. That file is typically the stdafx.cpp file in your project, and it typically has nothing in it except #include "stdafx.h". Configuring Precompiled Headers for THAT ONE FILE, switch from "Use" to "Create". This ensures that if the prime-header for PCH gets out of synch stdafx.cpp is ALWAYS compiled first to regenerate the PCH data file. There are other ways of configuring PCH setting in Visual Studio, but this is the most common.
That being said, your problem is definitely irritating. The filename used to prime the PCH system and specified on both the "Use..." and "Create..." setting above MUST MATCH THE TEXT IN YOUR #include EXACTLY.
Therefore, it is highly likely you can address your problem by adding ".." to your project include directories and removing the ".." from your #include statement. you could also change it at the project-configuration level to be "..\stdafx.h" as the through-header, but that might be a problem if you have source files in multiple folders hierarchically.
Oh, and if it wasn't clear to you while perusing the PCH configuration settings, if you do NOT want to use PCH for any specific source file (and there are reasons not to sometimes) you can turn it OFF for specific source files, otherwise be sure to always have #include "your-pch-include-file.h" at the head of every source file (c/cpp,etc).
Hope you catch a break.
I generally also like to have a hierarchical order in my projects, and I've found there are two simple ways to include a precompiled header:
Either
Put the directory where stdafx.h lies into the compiler's include directories.
(Properties - VC++ Directories - Include Directories: Add $(ProjectDir))
Or
If there aren't too many subdirectories, a simple way to circumvent the error message is like this:
Put an stdafx.h file into each of your subdirectories which only includes the top-level stdafx.h:
#include "..\stdafx.h"
Write #include "stdafx.h" as first line of all source files in your subdirectories, instead of including the top-level file there.
This way, all your code files use the same precompiled header file, and there is no other complicated setup to do.
It's interesting that the trick that I use isn't in the answers:
Create stdafx.h and stdafx.cpp in the root folder of the project.
Go to project properties -> precompiled headers. Change to "use".
Go to stdafx.cpp, right-click properties -> precompiled headers. Change to "create".
Go to project properties -> advanced; change "Force include files" to stdafx.h;%(ForcedIncludeFiles)
Don't change any CPP file; keep your header files as they are. Build as-is.
No typing, no RSI, no hassle with include paths, no other pain and misery. And the beauty is that it will still work when you move your solution to another platform. Awesome.
You can adjust the precompiled header settings on a per-file basis.
In Solution Explorer right click on the .cpp file, select "Properties".
I'd strongly recommend selecting "All Configurations" in the Configuration drop down List item.
Browse to "C/C++" - "Precompiled Headers".
Adjust the "Precompiled Header File" from "stdafx.h" to whatever you need (in your case for example "../stdafx.h").
Note this is tedious and error prone since it's done on a per-file basis, and future developers adding files to your project will have to follow the same steps. If they don't they will be faced with warnings and errors such as:
warning C4627: '#include "<path>"': skipped when looking for
precompiled header use.
and
fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
which don't give much indication as to this or any other approach.
I guess they'll eventually turn to StackOverflow and end up here... Hello, thanks for reading.
On that basis, it's worth going with alternatives, such as putting $(ProjectDir) on the C++ Include path (under C++\General) but then that can cause confusion when including other header files.
PCH files are wierd, and even moreso in Visual Studio. When compiling a .cpp file that uses a PCH, VS expects the first non-comment/whitespace text to be #include "PCH_NAME_HERE". The PCH_NAME_HERE is exactly the PCH's name. No directories, nothing. Just the PCH's name as specified in the compiler options.
If you're going to do this directory fudging, then you need to modify your compiler settings so that the directory where the PCH is is in the directory search path. That way, you don't need to have the ..\ part.
I would suggest to use:
$(ProjectDir)/pch/my_pch.h
as "Precompiled Header File"
and "Advanced > Force Include File"
This will auto include pch for your .cpp files in the beginning, so nothing needs to be changed in the .cpp files.
And this is better than changing the include directory, because sometimes you might have multiple pch files in the include directories, and then you can't tell which one has been used.
The cause of the confusion is that Visual Studio treats the include directive that includes the precompiled header differently to other include directives. Specifically it does not look for the precompiled header using the normal path lookup approach, instead it simply attempts to match the include directive to that defined in the project configuration by simple string comparison.
Precompiler header configuration is set gobally but can be overridden per file. The normal global config (accessed via Project Properties -> Configuration Properties -> C/C++ -> Precompiled Headers) is:
Precompiled Header: Use (/Yu)
Precompiled Header File: stdafx.h
Precompiled Header Output File: $(IntDir)$(TargetName).pch
This configuration is applied to all files in the project by default. However the config for stdafx.cpp is set at the file level and overrides the Precompiled Header value to:
Precompiled Header: Create (/Yuc)
The effect of this is that for any source file configured to use the precompiled header (which by default is all of them except stdafx.cpp) VS will look for an include directive that matches the configured Precompiled Header File value. e.g.
#include "stdafx.h"
Because the check uses a simple string comparison instead of any kind of directory search, then (irrespective of the location of the source file relative to the project root directory or the location of the stdafx.h file) the path and filename used in the include directive must match exactly that used by the project's Precompiled Header File configuration setting. The unexpected side effect of this is that if you have a project subdirectory containing various source files, in those files you do not need to reference the stdafx.h file using a relative path like ..\stdafx.h (and if you do VS will raise an error stating that it encountered the end of file while looking for the precompiled header).
Just use the unadorned #include "stdafx.h" and it will work fine because VS will then recognise this as the directive to use the precompiled header, and it already knows where the correct precompiled header is because of stdafx.cpp Precompiled Header configuration being set to "Create (/Yc)".
If .cpp and .h files of your project live in different subdirectories (not plainly in the directory of the project), it would be a good coding style to use include paths relative to the solution directory (if you don't use a dedicated include directory). Particularly if you have multiple projects in a solution and need to share include files (e.g. for interoperability between projects, e.g. an .exe and a .dll).
To refactor your project you need to do the following:
In each project specify additional include directory
$(SolutionDir) : right-click on project, click "Properties", go to
"Configuration Properties"->"C/C++"->"General" (to do this for all
configurations at once, select "All Configurations" from the
"Configuration" dropdown)
Go to "C/C++"->"Precompiled Headers"
and change "Precompiled Header File" value to the path relative to
the solution directory, e.g. PROJECT_NAME/stdafx.h
In your .cpp
files include "PROJECT_NAME/stdafx.h", instead of just "stdafx.h"
In your .h and .cpp files, when including something, use path as
"PROJECT_NAME/dir1/dir2/file.h", except when including file from the
same directory
Using quotes means it is a header file you own use <> means it is a system header file if I am not mistaken just use #include <stdafx.h> and let the compiler find it

Visual Studio C++ able to compile with compile errors (red underlines)

I am having a problem of getting compile errors (red underlines) like:
Error: cannot open source file "stdafx.h"
Here an edited screenshot of the environment:
On the LEFT is my Visual Studio Solution Directory list with the "Show All Files" off.
I am working on a school project, and each Folder are the source files of different parts of the project with different people who are in-charge of them.
For example, Student A and B are incharge of AST and PARSER folders (we will call them sub-projects).
We have an API for each sub-project so other sub-projects know what to call.
At the TOP-CENTER, we have my Source File for a class QueryProcessor. (just the first few lines)
Below it, is the Output for the Build Success.
The red lines are all over all the classes, mainly cause the #include "stdafx.h" cannot be opened by the environment.
On the RIGHT, that is the stdafx.h where we include all the different sub-projects so we save the trouble of each project having a different stdafx.h
However, I am able to build the project. I am pretty sure I am doing this directory/linking wrongly.
This should work
Right click on the solution file
Click Open in Windows Explorer
Find file stdfx.h in explorer and copy the path of the folder
In visual studio solution explorer, Right click on the project file
Click properties-> C/C++ -> General
In the Additional Include Directories paste the path
Combining folders and virtual folders in VC is from my point of view messy because the virtual folders indicate that all files are in one directory and the folders created on the harddrive obviously indicate that all files are in different directories. You can combine it if you know what's going on but in your case I would not recommend it.
I assume you missunderstand the purpose of stdafx.h The purpose of this header file is NOT to put all header filles into it and then just include it to all other files. Here is a SO question about this Purpose of stdafx.h
After cleaning up your stdafx.h file include as many header files into your .cpp files and only put these includes in your header files if they are required in the header file
Turn on show all files, now you will work with actual folders and you can be sure that if you adress a folder like "PKB" that this folder really exists since you can see it in the left solution explorer.
If you use using namespace std; for example make sure you also include the required header files. You might think "hey I already included e.g. iostream in another header file which I now include in this header file so I don't need it" That will really destroy you when you work with bigger projects.
Oh and regarding the stdafx.h include problem as soon as you switch to show all files I assume you will realise that stdafx is in a different file than the file where you use the include. Maybe something like #include "..\stdafx.h" is required (depending on your structure).
I think it's obivious but if you include a header file the include is allway relative to the file which is including the other header file.
stdafx.h is commonly used for creating a precompiled-header, which essentially is a compile-time optimisation such that the compiler will not continually compile these headers for every compilation unit.
If any of these headers changes, you will need to do a full system rebuild.
In reality it is preferable only to use it to include standard headers plus third-party headers (like boost libraries and similar) that you are not ever going to change.
You may decide that some of your own libraries are "set in stone" and can also be included.
Every project, i.e. every part of the project that is built into a separate unit (DLL or .exe) should have its own precompiled header and its own version of stdafx.h
Projects should only ever include their own .stdafx and not those of other projects, therefore this header file can also be used to define your dllexport macro.
When arranging your project headers you should be aware of:
1. Which headers are included externally
2. Which headers are only included internally, and are not even included indirectly externally.
The latter sort should include your stdafx.h file and should ideally not be in the same directory as those headers included from outside your project.

How to check programmatic by preprocessor directive whether a pre-compiled header is required in Visual C++?

Sometimes it would be useful to know whether the compiler requires a pre-compiled header or not, and how the header file is called. My goal is to add some preprocessor directives like this:
#ifdef REQUIRES_PRECOMPILED_HEADER
#include PRECOMPILEDHEADER_FILE
#endif
So my question is: Are there predefined variables like REQUIRES_PRECOMPILED_HEADER and PRECOMPILEDHEADER_FILE?
Well presumably your source files will not need any of the headers included in the precompiled header. So, if you are trying to include your source files in a project where other source files do use precompiled headers, just make sure precompiled headers are turned off for yours.
Just select the properties for your source files, and under "Precompiled Header" select "Not Using Precompiled Headers".
It's not your task to support others' use of precompiled headers. It's up to them to add your header to their precompiled header, or not. You just create trouble by trying to do it for them.
So, problem solved: don't do that.
It's unnecessary and it creates trouble.

The purpose of stdafx.h (And: Why doesn't this work?)

I am working on a project that has a vendor-provided API. I've made a class that uses that API in my project and I've included the vendors header file in my stdafx.h file. Things would not compile.
I then put the #include directly into my class' header file and now things compile (And yes, my class includes stdafx.h so that isn't the reason.
Do any of you have any guesses as to why it wouldn't compile the first time around? This isn't a project-stopper by far but I'd prefer if I could keep all vendor API files in stdafx.h where they belong.
EDIT: Problem solved, I'd created a cyclic dependency by forgetting to #ifndef a header file and then including them in the wrong order. I feel like an idiot.
stdafx.h is mainly used in the VS generated projects as the 'container' of headers to be precompiled.
When you added a new #include to stdafx.h it didn't get included because your project is probably configured to use precompiled headers, and when you add something to stdafx.h you need to regenerate the .pch file that contains the precompiled information.
One way to do that is to have a .cpp file in your project that does nothing but #include "stdafx.h". Maybe call it `precompile.cpp". Then go to the project settings for that one .cpp file and change the following setting (for all configurations):
"C/C++ | Precompiled Headers | Precompiled Header" setting
and select "Create /Yc".
That will set up the build so that when precompile.cpp needs to be built (because the stdafx.h header it includes has changed), it'll rebuild the .pch file that everything else uses.
EDIT: Wait - I don't think I read the question right. May still be helpful, though.
Another name for stdafx.h is a 'Precompiled header'
There aren't really any 'vendor specifics' in stdafx.h, what it does is it precompiles headers so that the compiler doesn't have to re-compile them every time you build the project.
It's only really helpful if you have a huge project (or a small one that includes tonnes of headers).
I use visual studio 2010 as well, generally it's not worth the fuss - I just disable it (which would solve your class inclusion issue also - make your own header, stick the vendor's in there).

Is there a way to use pre-compiled headers in VC++ without requiring stdafx.h?

I've got a bunch of legacy code that I need to write unit tests for. It uses pre-compiled headers everywhere so almost all .cpp files have a dependecy on stdafx.h which is making it difficult to break dependencies in order to write tests.
My first instinct is to remove all these stdafx.h files which, for the most part, contain #include directives and place those #includes directly in the source files as needed.
This would make it necessary to turn off pre-compiled headers since they are dependent on having a file like stdafx.h to determine where the pre-compiled headers stop.
Is there a way to keep pre-compiled headers without the stdafx.h dependencies? Is there a better way to approach this problem?
Yes, there is a better way.
The problem, IMHO, with the 'wizard style' of precompiled headers is that they encourage unrequired coupling and make reusing code harder than it should be. Also, code that's been written with the 'just stick everything in stdafx.h' style is prone to be a pain to maintain as changing anything in any header file is likely to cause the whole codebase to recompile every time. This can make simple refactoring take forever as each change and recompile cycle takes far longer than it should.
A better way, again IMHO, is to use #pragma hdrstop and /Yc and /Yu. This enables you to easily set up build configurations that DO use precompiled headers and also build configurations that do not use precompiled headers. The files that use precompiled headers don't have a direct dependency on the precompiled header itself in the source file which enables them to be build with or without the precompiled header. The project file determines what source file builds the precompiled header and the #pragma hdrstop line in each source file determines which includes are taken from the precompiled header (if used) and which are taken directly from the source file... This means that when doing maintenance you would use the configuration that doesn't use precompiled headers and only the code that you need to rebuild after a header file change will rebuild. When doing full builds you can use the precompiled header configurations to speed up the compilation process. Another good thing about having the non-precompiled header build option is that it makes sure that your cpp files only include what they need and include everything that they need (something that is hard if you use the 'wizard style' of precompiled header.
I've written a bit about how this works here: http://www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html (ignore the stuff about /FI) and I have some example projects that build with the #pragma hdrstop and /Yc /Yu method here: http://www.lenholgate.com/blog/2008/04/practical-testing-16---fixing-a-timeout-bug.html .
Of course, getting from the 'wizard style' precompiled header usage to a more controlled style is often non-trivial...
When you normally use precompiled headers, "stdafx.h" serves 2 purposes. It defines a set of stable, common include files. Also in each .cpp file, it serves as a marker as where the precompiled headers end.
Sounds like what you want to do is:
Leave precompiled header turned on.
Leave the "stdafx.h" include in each .cpp file.
Empty out the includes from "stdafx.h".
For each .cpp file, figure out which includes were needed from the old "stdafx.h". Add these before the #include "stdafx.h" in each .cpp file.
So now you have the minimal set of dependancies, and you still are using precompiled headers. The loss is that you are not precompiling your common set of headers only once. This would be a big hit for a full rebuild. For development mode, where you are only recompiling a few files at a time, it would be less of a hit.
No, there is probably NOT a better way.
However, for a given individual .cpp file, you might decide that you don't need the precompiled header. You could modify the settings for that one .cpp file and remove the stdafx.h line.
(Actually, though, I don't how the pre-compiled header scheme is interferring with the writing of your unit tests).
No. pre-compiled headers relies on a single header included by all sources compiled this way.
you can specify for a single source (or all) not to use pre-compiled headers at all, but that's not what you want.
In the past, Borland C++ compiler did pre-compilation without a specific header. however, if two sources files included the same headers but at different order, they were compiled separately, since, indeed, the order of header files in C++ can matter...
Thus it means that the borland pre-compiled headers did save time only if you very rigidly included sources in the same order, or had a single include file included (first) by all other files... - sounds familiar ?!?!
Yes. The "stdafx.h/stdafx.pch" name is just convention. You can give each .cpp its own precompiled header. This would probably be easiest to achieve by a small script to edit the XML in your .vcproj. Downside: you end up with a large stack of precompiled headers, and they're not shared between TU's.
Possible, but smart? I can't say for sure.
My advice is - don't remove precompiled headers unless you want to make your builds painfully slow. You basically have three options here:
Get rid of precompiled headers (not recommended)
Create a separate library for the legacy code; that way you can build it separately.
Use multiple precompiled headers within a single project. You can select individual C++ files in your Solution Explorer and tell them which precomiled header to use. You would also need to setup your OtherStdAfx.h/cpp to generate a precompiled header.
Pre-compiled headers are predicated on the idea that everything will include the same set of stuff. If you want to make use of pre-compiled headers then you have to live with the dependencies that this implies. It comes down to a trade-off of the dependencies vs the build speed. If you can build in a reasonable time with the pre-compiled headers turned off then by all means do it.
Another thing to consider is that you can have one pch per library. So you may be able to split up your code into smaller libraries and have each of them have a tighter set of dependencies.
I only use pre-compiled headers for the code that needs to include the afx___ stuff - usually just UI, which I don't unit-test. UI code handles UI and calls functions that do have unit-tests (though most don't currently due to the app being legacy).
For the bulk of the code I don't use pre-compiled headers.
G.
Precompiled headers can save a lot of time when rebuilding a project, but if a precompiled header changes, every source file depending on the header will be recompiled, whether the change affects it or not. Fortunately, precompiled headers are used to compile, not link; every source file doesn't have to use the same pre-compiled header.
pch1.h:
#include <bigHeader1.h>
#include ...
pch1.cpp:
#include "pch1.h"
source1.cpp:
#include "pch1.h"
[code]
pch2.h:
#include <bigHeader2.h>
#include ...
pch2.cpp:
#include "pch2.h"
source2.cpp
#include "pch2.h"
[code]
Select pch1.cpp, right click, Properties, Configuration Properties, C/C++, Precompiled Headers.
Precompiled Header : Create(/Yc)
Precompiled Header File: pch1.h
Precompiled Header Output File: $(intDir)pch1.pch
Select source1.cpp
Precompiled Header : Use(/Yu)
Precompiled Header File: pch1.h
Precompiled Header Output File: $(intDir)pch1.pch (I don't think this matters for /Yu)
Do the same thing for pch2.cpp and source2.cpp, except set the Header File and Header Output File to pch2.h and pch2.pch. That works for me.