Utility Pattern

June 6, 2008

Precompiled Headers with Qt under Visual Studio 2005

Filed under: C++, Qt — utilitypattern @ 9:33 am

 

Pre-Compiled headers can greatly reduce compile times, but setting this up correctly so it doesn’t conflict the Qt’s visual studio integration and MOC is not straightforward. This article will walk you through the process. There are drawbacks to precompiled headers. Please take a look at the references at the end for more details on precompiled headers and their pluses and minuses. Now, on to speeding up your build!

First, enable build timings in Visual Studio so you can see if your making things better or worse. Set Tools | Options | Projects and Solutions | VC++ Project Settings | Build Timing to Yes. Ideally, you should run the build a few times to get some before metrics. I ended up just jumping right in. The improvement was so great it was easy to see.

Now, you will need to add two files, a header (.h) and source (.cpp) file, to every Visual Studio project (.vcproj). The .cpp file will be used by the compiler to trigger the creation of the precompiled header (.pch) file. The .h file specifies which headers should be included as precompiled headers. You can name the files anything, but I like to a) have them match and b) have them be easy to recognize. So, I suggest using MyProject_pch.h and MyProject_pch.cpp. As a side note, if you create a default MFC project visual studio will name the files stdafx.h and stdafx.cpp.

Create the source files for the precompiled headers

Create the MyProject_pch.h file and add this file into the project with your other headers. In the file, #include any headers which are large, seldom change, and are used frequently in the project. Almost any Qt header your using is a good candidate. Also, any headers from the standard library should be included here. Here’s an example.

/* Use include guards,
just as you would with any regular header. */
#if !defined(MYPROJECT_PCH_H)
#define MYPROJECT_PCH_H

/* In addition, its a good idea to surround the headers
with an additional define so we can switch the inclusion
of the pre-compiled headers them on and off.
For platforms which don't support pre-compiled headers,
don't define USE_PRECOMPILED_HEADERS. */
#ifdef USE_PRECOMPILED_HEADERS

/* I like to include this pragma too,
so the build log indicates if pre-compiled headers
were in use. */
#pragma message( "Using pre-compiled headers\n" )

// Include files that are used in many places and change infrequently.

// Std library stuff
#include <vector>
#include <stdio.h>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <memory>

// Qt stuff
#include <qvector>
#include <qvariant>
#include <qlist>
#include <qstring>
#include <qstringlist>
#include <qmutex>
#include <qmutexlocker>
#include <qregexp>
#include <qmap>
#include <qabstractitemmodel>
#include <qmodelindex>
#include <qstandarditem>
#include <qstandarditemmodel>
#include <qthread>

// Boost stuff
#include <boost smart_ptr.hpp>

#endif // USE_PRECOMPILED_HEADERS 

#endif //MYPROJECT_PCH_H.

The MyProject_pch.cpp file is dead simple. Add it to the project with your other source files.

// Build the precompiled headers.
#include "MyProject_pch.h"

 

Configure Visual Studio

Right click on the project in the Solution Explorer. Choose Properties. Change the Configuration to All Configurations. You want to select All Configurations so the changes you make will affect both debug and release builds. Then select Configuration Properties | C/C++ | Precompiled Headers

  • Set Create/Use Precompiled Header to Use Precompiled Header (/Yu)
  • Set Create/Use PCH Through File to MyProject_pch.h
  • Leave Precompiled Header File at $(IntDir)\$(TargetName).pch

This will set every source file in the project to use pre-compiled versions of the headers, as specified in ‘MyProject_pch.h’

Now, find MyProject_pch.cpp in the Solution Explorer. Right click on it and select Properties. Again, change the Configuration to All Configurations. Then select Configuration Properites | C/C++ | Precompiled Headers

  • Set Create/Use Precompiled Header to Create Precompiled Header (/Yc)
  • Set Create/Use PCH Through File to MyProject_pch.h
  • Leave Precompiled Header File at $(IntDir)\$(TargetName).pch

This triggers visual studio to generate the pre-compiled header (.pch) file. If you skip this step, Visual Studio will complain about creating or recreating the precompiled header.

The MyProject_pch.h file must be the first non-comment line in every .cpp file in the project. In fact, Visual Studio will silently ignore every line of code before this file. If it isn’t in .cpp file at all, you will get an error.

fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add ‘#include “CipherOm_pch.h”‘ to your source?

You could write a script to add ‘#include ‘MyProject_pch.h’ as the first line of every source file. However, if you try and go this route, Qt’s MOC and it’s generated source are going to make the build process pretty complicated. You would need to make sure the script runs after the MOC but before the file is compiled. Fortunately there is a much easier way. Use Visual Studio’s Force Includes directive.

Right click on the project in the Solution Explorer. Choose Properties. Change the Configuration to All Configurations. Then select Configuration Properties | C/C++ | Advanced

  • Set Force Includes to MyProject_pch.h

Now, every .cpp file in the project will have the precompiled header file included as if it were the first line of the file. This includes MOC generated code.

It probably a good idea to make sure and include all the headers needed by the .cpp file in the .cpp file explicitly. Then test this periodically by building without USE_PRECOMPILED_HEADERS defined. Explicitly including dependencies will clearly indicate what headers the .cpp file needs and help keep the code base in good shape in case you need to compile on a platform that doesn’t support precompiled headers. This is Qt after all.

References

The information here was synthesized from the following blog posts. I recommend reading the first at a minimum.

Precompiled Headers

The Care and Feeding of Pre-Compiled Headers

Non-intrusive build speedup in Visual C++ .NET

Advertisements

4 Comments »

  1. Thanks for that guide, it very help me.

    Comment by Zombie! — June 11, 2009 @ 8:47 am

    • You’re welcome.

      Comment by utilitypattern — June 11, 2009 @ 11:26 am

  2. Very nice! Saved a lot of time for me.

    Comment by pld — September 1, 2009 @ 3:11 pm

  3. Thanks a lot, man – this will save me a lot of time, too!

    Comment by Greg — May 5, 2011 @ 8:45 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: