What does #pragma hdrstop without parameter do when used in multiple files? - c++

What is the practical value ("what does it do") of putting #pragma hdrstop (no filename parameter) in a couple of source (cpp) files?
Note that the MSDN docs are (once again) as clear as mud to me.
Edit/Note: I'm asking this, because this answer and the article it links to seem to recommend that. But I do not understand what benefit it has to have a separate pch file for each compilation unit.

The answer to the original question is that the purpose of having #pragma hdrstop in a file with neither /Yc or /Yu set is that it's ignored and so you can set up a build configuration which builds without precompiled headers and other build configurations that build WITH precompiled headers and you don't need to change the code or the headers that are included at all to do so.
More detail...
The notes on MSDN say that "The hdrstop pragma gives you additional control over precompilation file names and over the location at which the compilation state is saved." which is true, but it's not especially obvious exactly how useful that can be...
In a nutshell.
Putting #pragma hdrstop in a source file that isn't compiled with /Yc or /Yu has no effect at all.
If you have /Yu set for the file then hdrstop tells the compiler to throw away everything before the line on which hdrstop appears and insert the precompiled header instead.
If /Yc is set for the file then hdrstop means save all of the compiled state for everything up to the line on which hdrstop appears as the precompiled header.
The trick is using /Yc and /Yu without the optional header file name; just check the 'use' or 'create' radio button and leave the 'through header' edit box blank (or edit the project file...).
So you have 1 file, possibly called PrecompiledHeader.cpp which includes the headers that you want to include in the precompiled header and which has #pragma hdrstop at the end of the list of include files. This ONE file is compiled with /Yc.
You then have all your other cpp files with #pragma hdrstop after the include files that are in your precompiled header. These files are all compiled with /Yu.
This results in PrecompiledHeader.cpp building your (in this example) single pch file and all of the other files using that single pch file.
The advantage in doing this is that NONE of your files need to include a 'global' precompiled header building header file - so no stdafx.h or whatever. This means that you can set up a build configuration which builds WITHOUT precompiled headers where all of the #pragma hdrstop lines are simply ignored.
This is "good" because it means that you can have a single 'no precomp' build configuration which lets you develop quickly (you can change a single header and NOT force the world to rebuild) and other "normal" configurations that DO use precompiled headers.

All the code before #pragma hdrstop will be part of a precompiled header. If no filename parameter is given, the name of the header will be the base name of the source file with a .PCH extension, as mentioned in the documentation:
The name of the precompiled header file is determined according to the
following rules, in order of precedence:
The argument to the /Fp compiler option
The filename argument to #pragma hdrstop
The base name of the source file with a .PCH extension
So, if you have that on a file named blah.cpp it will produce a file named blah.pch, IFF compiled with /Yc (which only one file should have set).

If not using #pragma hdrstop in your C/C++ project, you muse have a dedicated .cpp file as the source file for the .pch created.
If using #pragma hdrstop in a .cpp file with which you wish to create .pch file, the .cpp file can have other useful contents after the line of #pragma hdrstop. When you firstly compile this .cpp file with /Yc compilation option, you get the .pch file and the .obj file. When You alter the .cpp file and recompile it with /Yu compilation option, the compiler replaces the contents befor the line of #pragma hdrstop with the .pch file and recompile the part after the line of #pragma hdrstop, create a new .obj file, saving compilation time. It is very useful that your project has the only one source file.
For source files only using precompile head files, the #pragma hdrstop is a landmark for the compiler which part should be replaced by the .pch file, so you needn't indicate the header file name with /Yu compilation option.

Related

Using pragma once in .cpp file

Recently reading some pieces of code I encountered several .cpp files that contained
#pragma once in the beginning of file. I know that it is usually used in .h files as guards.
What are the cases when #pragma once should/can/must be used in .cpp files?
#pragma once shouldn't be used in source files, its one goal is to act as include guard. It won't do much harm .cpp files are normally going to be "scanned" once during compilation anyway. Note: Clang tidy will warn you if you do it.
Warning clang-diagnostic-pragma-once-outside-header #pragma once in main file

PCH compiler options for MSVC

I am a bit confused about when to use /Yc (create PCH) as opposed to /Yu (use PCH.) For a project that has never used precompiled headers in the past, naturally, the PCH file will not exist initially. Am I supposed to fire off a initial build with /Yc, have it create the PCH file and then change the setting to /Yu for all subsequent builds?
That can't possibly be it, right?
Try this: Create a header to contain all the headers to pre-compile eg: stdafx.h (this MUST be the 1st include in all .cpp files). File to generate the PCH: stdafx.cpp which only includes stdafx.h and compile this with /Yc. All other .cpp files include stdafx.h at the start and compile with /Yu. MSVC is clever enough to do the /Yc file 1st.

c++ precompiled header defined in a header VS2010. Compiler can't find

I've inherited some code that did something like this,
Header: HeaderFile.h
#ifndef HEADERFILE_H
#define HEADERFILE_H
#ifndef HEADERFILE_PCH_H
#include<LibStuff>
#include<LibStuff2>
#include<LibStuff3>
#include<LibStuff4>
#include<LibStuff5>
#endif
#include "FilesInProject"
Class A
{
//Code
};
#endif
Cpp: HeaderFile.cpp
#include "HeaderFile_pch.h" //(1)
#include "HeaderFile.h"
//More code
I understand what a precompiled header is for and what the code is doing here (sort of). When I copy these files into my project, this is so I can update deprecated code but not effect the original project, VS2010 chocks on line (1). VS2010 Saying it can't find that file.
I've gone between the two projects and I can't find any differences in settings.
What am I missing and why is it okay to imbed PCH's in headers like this instead of actually moving them to a file called HeaderFile_pch.h. Is this some kind of macro hack?
For starters, there is no such file as Headerfile_pch.h either in the samples you provided above nor likely on your local fs.
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" but can be anything you choose. All files will get this setting (thus the configuration at the project level) EXCEPT....
One file is responsible for generating the PCH file. That file is typically the stdafx.cpp file in your project, but again, it can be whatever single source you desire. Most just setup a dummy cpp file that has one thing in it: #include "myheader.h" (duh).. 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 that source file is recompiled first to regenerate the PCH data file before the others are kicked off.
The one attribute of this that is absolutely mandatory: that include header (myheader.h or whatever you're calling it) must be the first include in any source file you're compiling that is participating in using pch including (hopefully obviously) the file you specified as the "generator" (the one marked as "Create" in the prior paragraph).
Lastly, you can disable pch on a file-by-file basis if this is a problem due to unusual conditions in your build environment (i.e. 3rd party headers that do stupid things).
There are other ways of configuring PCH setting in Visual Studio, but this is by far the most common.

Visual C++ Precompiled Headers errors

Update:
What are the effects of including stdafx.h in my header files?
I started on a C++ project in Linux/Eclipse CDT and imported it into Visual C++/Windows.
In Visual C++, I started using precompiled headers to speed up compilation and defined stdafx.cpp and stdafx.h.
Here's my stdafx.h
#pragma once
#include <string>
#include <vector>
#include <map>
...
and my stdafx.cpp
#include "stdafx.h"
In every .h and .cpp file, I have the following:
#pragma once //if in a header file
#include "stdafx.h"
For both release and debug, I have "Create Precompiled Header (/Yc)". It compiled fine in debug mode, but in release mode it keeps reporting
error LNK2005: ___##_PchSym_#00#UfhvihUaszlaDUwlxfnvmghUnnlUhixUnnlPeDUnnlPeDUivovzhvUvmgrgbOlyq# already defined in A.obj
If I switch both to "Use precompiled header", I get in both Debug and Release
fatal error C1854: cannot overwrite information formed during creation of the precompiled header in object file:
Does anyone know what's going on?
You put "create precompiled header" only for stdafx.cpp. Then "use precompiled header" for all of the other ".cpp" files. Finally, have include "stdafx.h" at the start of each ".cpp" file (not usually in the header files.
The /Yc compiler option is used to create a pre-compiled header for a compilation action. The /Yu option instructs the compiler to use a pre-compiled header.
You will always use the /Yu option in project settings.
In the property pages for your stdafx.cpp file, the /Yc option will be set.
It is important to understand that there are separate compilation options for each .cpp file
.
See here for details of the /Y options.
You put the #pragma once before the #include "stdafx.h" which I think is causing the compiler to ignore the #pragma once directive.
Also, I don't think you should be putting the #include "stdafx.h" line into the header files at all.
The results of using "stdafx.h" are not influenced by the PreCompiled Header system. If you turn off Create PCH/Use PCH, the code compiles and creates the same output, except it does so slower. This is also why you can use it in portable code (unlike #pragma once)

Possible to use precompiled headers with MIDL generated files?

We do have a project wich uses the MIDL tool to create specific header/iid and proxy files. Those files are compiled and linked with the rest of the project using a post build step that calls nmake.
Is it possible to use precompiled headers with thos IDL generated files? How can I inject #include "stdafx-h" and remove other included headers?
Use the /FI option (Force Include): "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 specified on the command line, in the CL environment variable, or in a command file."
It won't remove the other headers, but this is not necessary for the Precompiled Header to be used... All the headers that you want to precompile should be included by stdafx.h. Then, provided the files have inclusion guards, it won't be a problem when they are included again in the sources.
Example
Generated a.cpp file:
#include <a.h>
#include <b.h>
//rest of the code
Suppose you want to pre-compile a.h and b.h. Then you create the file stdafx.h:
#include <a.h>
#include <b.h>
And then you use the /FI option to have this stdafx.h included as the first file into a.cpp. If the files a.h and b.h have include guards, leaving them in a.cpp is not an issue...
"stdafx.h" is merely a convention. If you know that yout generated source files always have a standard prefix of included headers, you can name the last of them in the /Yu switch (use precompiled headers). To create the PCH, create an single .cpp file with just those fixed headers and compile ith with /Yc.