|
#1
•
Stone Steps
Precompiled headers in VC++ (stdafx.h silliness)
Precompiled headers in VC++ are poorly implemented, using the content of the #include directive verbatim when looking for a precompiled header (PCH). Consider this directory structure:
...\project\
stdafx.h
main.cpp #include "stdafx.h" [1]
\sub-dir\
some-file.cpp #include "stdafx.h" with PCH [2]
#include "../stdafx.h" without PCH [3]
header.h #include "../stdafx.h" *must* be this! [4]
\sub-project\
stdafx.h
another.cpp #include "stdafx.h" [5]
#include "../sub-dir/header.h" [6][1] & [5] are simple - works fine under any circumstances.[2] & [3] If precompiled headers are on, then 2 must be used to get the file compiled. If PCH are off, [3] must be used instead. There's no conditional define to make this difference transparent to the application, so when switching to and from precompiled headers, all source files including stdafx.h must be flipped between [2] and [3]! The alternative is to specify explicitly ../stdafx.h in the PCH properties instead of the standard stdafx.h, which is hard to track and maintain, since there is no indication that this file has custom settings. [4] must refer to the actual stdafx.h file, using parent paths because it will be included from other projects and if plain "stdafx.h" is included, will refer to the on in the project containing [6]. By contrast, GCC can be instructed explicitly to precompile a header file, which produces a PCH file with the extension .h.gch. Every time the preprocessor finds a file with the extension .gch and the name matching the file mentioned in #include, it checks if the file is valid and uses it if it is. However, since precompiled headers do reduce build time, it makes sense to configure projects to use them. The rest of the post describes how to make it easier to maintain precompiled headers in VC++. If you are working with a multi-project Visual Studio solution configured to used precompiled headers, it is better to avoid using the same stdafx.h file throughout all of the projects. Instead, create a per-project precompiled header file, with a distinct name. For example, if you have two projects, one called common.vcproj and the other one called editor.vcproj, follow these steps: * create common.h and common.cpp and add them to the first project * open properties for common.cpp and in Configuration Properties > C/C++ > Precompiled Headers select Create Precompiled Header (/Yc) and type common.h in the Create/Use PCH Through File box. * create editor.h and editor.cpp and add them to the second project * open properties for editor.cpp and in Configuration Properties > C/C++ > Precompiled Headers select Create Precompiled Header (/Yc) and type editorh in the Create/Use PCH Through File box. * make sure each header file has directives to prevent multiple inclusion. For example, in common.h these directives would look like this: #ifndef __COMMON_H #define __COMMON_H // Any commonly-used includes should go here. For example: #include <stdio.h> #include "my-header.h" #endif // __COMMON_H * include the common.h as the first header file in every source file of the common project. * include the editor.h as the first header file in every source file of the editor project. * when including common.h and editor.h use the bare file name within double quotes, even for source files located below the directory containing the precompiled header. For example: #include "common.h"Note that if you decide to turn off precompiled headers, #include directives in source files located in sub-directories will generate file-not-found errors, as described at the beginning of this post. * include any commonly-used header files used throughout the common and editor projects into common.h and editor.h, respectively. * in general, it's a good idea to keep the content of the precompiled header file limited to commonly-used includes and pragmas, so that this header file wouldn't be included into any other header files of the current project and wouldn't result in cross-project references described at the beginning of this post. Now, when a build is started, the compiler will process common.cpp and editor.cpp before any other files in their respective projects and will produce two precompiled header files, each containing the compiler state that can be reused every time the include directive containing the precompiled header file is encountered (e.g. #include "common.h"). Format Codes
|