Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 866
Ferruccio Avatar asked Nov 14 '08 13:11

Ferruccio


People also ask

Is Stdafx H necessary?

stdafx. h is not strictly necessary. Bad practice - you ought to always explicitly list the headers you need so you can check module dependencies. stdafx usually includes platform specific definitions common for all files.

Should you use precompiled headers?

Usage of precompiled headers may significantly reduce compilation time, especially when applied to large header files, header files that include many other header files, or header files that are included in many translation units.

How do I not use precompiled headers?

To turn off precompiled headersSelect the Configuration properties > C/C++ > Precompiled Headers property page. In the property list, select the drop-down for the Precompiled Header property, and then choose Not Using Precompiled Headers.

How do I precompile a header file?

Precompile code when you know that your source files use common sets of header files, or when you want to include source code in your precompilation. The precompiled-header options are /Yc (Create Precompiled Header File) and /Yu (Use Precompiled Header File). Use /Yc to create a precompiled header.


2 Answers

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...

like image 175
Len Holgate Avatar answered Oct 19 '22 08:10

Len Holgate


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.

like image 33
jyoung Avatar answered Oct 19 '22 07:10

jyoung