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.
Related
My app is working correctly, but I'm trying to clear up something. When I include the precompile header in my source files, I get the following happen.
Basically the first line is underlined as if there is a problem with it, so I have to include it again underneath, with the correct path... but I need both or it wont compile.
Any ideas?
The Visual Studio uses precompiled header only if the name matches (the name is not case-sensitive). Let say, a precompiled header name StdAfx.h is set in your project, so only when a code contains #include "stdafx.h" then is precompiled header used.
The #include "..\stdafx.h" is not recognized as the precompiled header even though it is the real location.
You need to add an include path to the location of stdafx.h into your project settings and then the header #include "stdafx.h" will be work correctly.
Another common issue with a precompiled header is that the include directive is in a header. It should be always in the source file (.ccp).
I need a tool (command line, script or source code) that extracts all inlcude files that are included by a source file (recursive) with given preprocessor defines and include paths. I want to know the ones that could be found and the one that doesn't. The include files that could be found shall be recursivly parsed.
I know about the
gcc -M /-MM
cl /P
solution, but this does not work for me. The preprocessor stops as soon as it could not open a file. But at this time I don't have the correct path for that files and just want the preprocessor to skip that file and to tell me that it could not include that file
Also the cinclude2dot.pl from here is not useful, because it seems not to consider given preprocessor defines.
Very useful is the include file hierarchy finder from CodeProject. It considers the preprocessor flags and shows me all include files. Even the includes that couldn't be opened. But it is written in MFC and I would have to reimplement this for the gcc what is not such simple because a lot of WinAPI stuff is used even inside the parser.
Thus, maybe some one knows another solution.
an simple example:
main.cpp
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <SharedClass.h>
#include "MyClass.h"
#ifdef FOO
#include <OptClass.h>
#endif
int main() {}
Right now I start the include extraction like (simplified):
.getAllIncludes main.cpp -I includepath1;includepath2 -PD FOO
and obtain:
cannot open //-> I don't care right now, it's a default header
cannot open // -> here I can extract the info that I need boost
SharedClass.h
SharedDependenyClass.h //a header that is included by SharedClass...
MyClass.h
TestClass.h //a header that is included by the MyClass header...
TestClass2.h //a header that is included by the TestClass header...
OptClass.h
and for
.getAllIncludes main.cpp -I includepath1;includepath2
I'll obtain:
cannot open //-> I don't care right now, it's a default header
cannot open // -> here I can extract the info that I need boost
SharedClass.h
SharedDependenyClass.h //a header that is included by SharedClass...
MyClass.h
TestClass.h //a header that is included by the MyClass header...
TestClass2.h //a header that is included by the TestClass header...
I know that the deafault header may also define some values. But in my case I don't need that information, because the project source code doesn't depend on any of that defines. If thus, I feed my tool with this preprocessor define...
In the end the tool works quite well. It runs recursivly over ALL necessary files and in the end I have all needed files for the project. Of course there are some small restrictions I don't want to name then all (e.g. every header of an source file name has the same name, ... ).
Using gcc -M <source_file>, the code is not compiled, it is only processed by the precompiler. And, any solution you may find needs to process the source using the precompiler, to be correct. Imagine that the source, somewhere, has the following snipset:
#ifdef USE_BOOST_SUPERLIB
# include <boost/superlib.hpp>
#endif
then without preprocessing you cannot know if <boost/superlib.hpp> is included.
I'm working on a VC++ project in VS 2012 that takes about 8-10 minutes for a full compile. I know PCH can speedup compile times by upto 10x. I have currently disabled PCH in my project and I'm including header files where they are needed. How do I get started with PCH? I've looked everywhere for "how to" guides but all I got is the docs.
I'm assuming I'll have to :
Configure my project for PCH, creating a blank PCH header file
Collect headers from every .cpp file and place it into the PCH header file
Modify every file removing all header imports
Recompile and hope that nothing goes wrong ;)
How do I get started with this (specifically #1)? Have you modified a project to use PCH and what are the stumbling blocks or common problems/issues therein? Can PCH cause any problems or is it just the same compile-time/runtime behaviour as normal includes? Is there a tool to automate the process or do I have to go thru 500 .cpp files by hand and modify it to use PCH?
And last but not least, what is the compilation time speedup I can expect with PCH? Is it 2x-10x? Or would it just go like 30% faster? (which does not justify the time involved)
After configuring my project to use PCH, full-compile times were down to half, and incremental builds occurred almost instantly. PCH is a very effective way to speedup compile times, and I highly recommend it.
Althouh dsharlet mentions many important points, he skips some crucial steps that I had to eventually figure out. So here is the complete guide to configuring your project to use PCH:
Getting started with PCH in a VC++ project
Backup your src dir and any other directories that contain source code ... (you'll need this in case anything goes wrong)
Create 2 files in your project, Globals.cpp and Globals.h .. (choose any name but stick to it)
Right click Globals.cpp and open Properties, choose Configuration > All configurations
Go to C/C++ | Precompiled Header, and fill these in:
Precompiled Header : Create (/Yc)
Precompiled Header File : Globals.h
Open Globals.cpp and add this one line in, and nothing more: #include "Globals.h"
Right click your VC++ project and open Properties, choose Configuration > All configurations
Go to C/C++ | Precompiled Header, and fill these in:
Precompiled Header : Use (/Yu)
Precompiled Header File : Globals.h
Open all the .h and .cpp files in your project, and add this at the very top: #include "Globals.h". If you DONOT want to include every file manually, you can use the Force Include /FI[name].
Open Globals.h and add the following in: (its very important you have #pragma once at the top)
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <memory>
#include <string.h>
#include <limits.h>
#include <float.h>
#include <time.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <malloc.h>
#include <locale.h>
#include <math.h>
// Windows SDK
#define _WIN32_WINNT 0x0501 // _WIN32_WINNT_WINXP
#include <SDKDDKVer.h>
// Windows API
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
These includes are typical candidates for your PCH file
Remove the includes that you're not using
Go through your project and collect any more header files that do not change often
Using find and replace, search for each of the #include's in your PCH file, and remove them from all the .h and .cpp files in your project.
Do a full compile and ensure everything is working okay. Here are some solutions for common problems you'll encounter:
PCH file includes itself:
Your PCH file is including a header that includes the PCH header file again, creating a kind of circular dependency. Double click the error to take you to the offending file, and simply remove the line that says #include "Globals.h"
Undefined symbol X
Although all your project files can include the PCH header, the files included inside the PCH header cannot include the PCH header! (as stated above) so you'll need to add back any imports that were previously in the file. (diff the file with the backup version)
Cannot find symbol logf
Sometimes the global PCH file does not behave as expected, and breaks compiling with crazy errors that are impossible to solve. You can then turn off PCH for individual source code files.
Right click your .cpp file and open Properties, choose Configuration > All configurations
Go to C/C++ | Precompiled Header, and fill these in:
Precompiled Header : Not Using Precompiled Headers
Remove the line #include "Globals.h" in your .cpp file
Add back whatever imports the file originally had. (diff the file with the backup version)
Here's how I use PCH with decent results:
Go to the project properties, C/C++|PCH set Precompiled Header option to 'Use'. Set Precompiled Header File to something you want.
Go to the properties of a cpp file you want to be the PCH, and set the Precompiled Header option to 'Create' (it will have defaulted to 'Use' from the project property setting).
Include the pch header in all your cpp files in the project (basically, the ones that have 'Use' set for the Precompiled Header option). I suppose you could turn off 'Use' for some cpp files in the project instead of add the include for the PCH, but I've never tried that...
At this point, the project should still build and behave exactly as it used to, but there may not be any real improvement in compile time. Now, you'll need to move some of your #include "...h" to the PCH header file (and delete the includes of those files from elsewhere in the project). The includes that you should move to the PCH header should be headers that are included in many files, but change infrequently. Examples: STL headers, windows.h, core functionality headers from your project, etc.
Once PCH is set up, it should be transparent. It's basically just helping the compiler cache some intermediate compilation data. In other words, if you turned off PCH in your project, everything should still build exactly as it would have with PCH turned on (except slower!)
The speedup entirely depends on how much code is moved into the PCH (how much included code from headers is moved from arbitrary cpp files to the PCH header). I've seen multiple times improvement, but haven't benchmarked it precisely. I definitely felt like it was worth doing when I've gone through the trouble to use PCH on a big project.
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.
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)