I have a precompiled header that needs to be included atop each .cpp in my project. I fear that I will waste a lot of time explaining and fixing that in coworkers code.
Is there an MSBuild step that I can do to #include "stdafx.h" at the top of all my .cpp files so it dosen't need to do done manually?
You have the compiler option /FI pathname
which virtually add #include "pathname" at the first line of the file.
Note: the equivalent for gcc is -include path.
Related
I have a solution which contains several projects. My projects (but not all of them) use precompiled headers. I decided to use protobuf and I've met a problem. After generetaing *.pb.h from *.proto by protoc.exe I'm trying to include the header and get the error - precompiled header wasn't included into *.pb.h.
How I can solve this problem? I have an idea (but I don't like it at all) - after protoc generates *.pb.h I can run some script, which'll include my precompiled header into the *.pb.h. But I don't like it because some projects may not use PCH, and PCH file name can be different.
I understand that I can just remove PCH from my projects, but I don't like that idea too.
Dont add the generated myproto.pb.cc to your project. Instead, create a myproto.cpp with
#include "pch.h"
#include "myproto.pb.cc"
I resolved my problem by creating a static library called proto-objects (without PCH) and including all my *pb.h(cpp) files there. After it I link that library to every project where I need my protobuf objects. Profit!
You can disable the pre-compiled header option on a file-by-file basis.
Given that the pch option is intended to speed up compilation, you can turn it off for the whole project, and no further changes should be necessary.
The choice of name of the header file, and the pch file are also selectable per file in the project
Update
The idea behind Microsoft's Pre-compilation PCH system is to
Speed up compilation
Make it easy to use
The header file system in C/C++ is problematic, as it is really a textual replacement.
That means that
#include "localdefs.h"
#include <windows.h>
#include "project.h"
#include "support.h"
Is in no way similar to
#include <windows.h>
#include "project.h"
#include "support.h"
That is because localdefs.h can redefine the behavior of all of the other includes.
Further to this the costs of walking through the complexities of the windows.h header files, is time consuming.
The PCH system tries to solve this by the observation that most projects have a fixed set of include files which are included by most/all of the CPP files.
Defining this set in stdafx.h allows the textual result of that parsing to be pasted in the cpp file and save a lot of work.
If most of the includes in the project are different, then there is no need to use it.
So if you are including the same qt header files in lots of places - add them to a pre-compiled header file. The more of the common includes added to this file, the better the compile speed improvements will be.
Any non-standard cpp file can be excluded by being specifically disabled - examples are "generated files". Where the template generator does not understand the MSVC system.
If all the files are different, then only limited performance benefit will be gained - as each compile would probably also include a pch recompile.
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.
I have a objective c/c++ project under iOS, moving it from OS/X and I get a 'file not found' error on
#include <string>
It's a clean project, and I've just added the files from the old project. Are the STL includes set up in XCode? A find produces a number of possibilities e.g.
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/usr/include/c++/4.2.1/debug/
but adding this to the search path just threw up more errors. Any suggestions?
(apart from don't use string - it's in house code I'm porting)
xcode 4.2.1, ios5.0 running on OS/X 10.7.3 and it's in a .cpp file, the code works fine on OS/X
Are you really sure <string> is included only from a .cpp file?
I just tested on a fresh project, by adding a .cpp file and including <string>, and it works, just as expected (same Xcode version, same SDK version).
But if I include <string> in a .m file, then of course I got a «file not found» compiler error.
So double-check this, as the error may come from here.
Do you include <string> from a .cpp file only, or from a .h file, intended to be used by a .cpp implementation?
Then maybe it's also included by a .m file, hence the error.
Also check your precompiled headers, if any, to see if you include some C++ stuff there...
Also remember, in that later case, that you can rely on the __cplusplus macro, when needed.
If you include a header in an ObjC file and it includes <string> then you hit errors like this. For all .m files XCode uses a C compiler (clang or llvm-gcc). For all .mm files it will use (clang++ or llvm-g++).
I suggest going through and renaming all your .m files to .mm. Including main.m to main.mm.
For me the reason was
MyHeader.h (which includes #include ) target was public. Changed it to project and it compiled.
For cocoa pod:
s.public_header_files = 'MyProject/Classes/**/*.h'
s.project_header_files = 'MyProject/Classes/MyHeader.h'
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)
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.