Thursday, May 17, 2012

Precompiled headers in vs-android

vs-android 0.93 does not have built-in support for precompiled headers, but it's possible to use precompiled headers with some small hacks.

According to the GCC documentation about precompiled headers, you're supposed to compile one like an ordinary source file. Presumably all you have to do is change the file extension from ".o" to ".h.gch" and GCC will pick it up as a precompiled header. The documentation implies you should put the gch in the same folder as the header, but I think that is a bad idea because Debug builds and Release builds must have separate gch files.

So instead what we will do is place the ".h.gch" file in the output folder with all the other ".o" files, and then add that folder with high priority so it is found before the real header file. Let's begin.
  1. Open your vs-android project file (*.vcxproj) in a text editor (instead of Visual Studio).
  2. Find the first <ClCompile Include="..."/> line. This line should be preceded by a <ItemGroup> opening tag.
  3. Assuming your precompiled header is called "Stdafx.h" and it is located in the "MyFolder" folder, insert the following code prior to <ItemGroup>
        <ClCompile Include="MyFolder\Stdafx.h">
          <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Debug|Android'">-x c++-header %(AdditionalOptions)</AdditionalOptions>
          <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Android'">-x c++-header %(AdditionalOptions)</AdditionalOptions>
          <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Android'">$(IntDir)%(FileName).h.gch</ObjectFileName>
          <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Android'">$(IntDir)%(FileName).h.gch</ObjectFileName>
    It is important that the precompiled header goes into its own ItemGroup prior to the other ItemGroups in the project file, in order to control the build order. ItemGroups are built in the order they appear, and it's important that our precompiled header build first. However, VS/MSBuild/vs-android does not respect the order of source files within a single ItemGroup.
  4. Open your solution in Visual Studio.
  5. Right click the project and click Properties.
  6. Beside Configuration, choose All Configurations.
  7. Go to Configuration Properties | C/C++ | General and then edit the list of Additional Include Directories.
  8. Add $(IntDir) as the first directory.
  9. Build your project. It should build faster now, but there will be no additional output except that Stdafx.h will build before the other source files. In order to verify that build time decreased, you can disable building StdAfx.h and then Clean and Rebuild the project and use a stopwatch to see if it takes more time. To disable StdAfx.h, right-click StdAfx.h, choose Properties, click General, then set Excluded From Build = Yes. Remember to re-enable it afterward.
In my slowest-building project, build time was cut in half, from 3:52 to 1:58 for 48 source files.
Note to self, do not edit this post. Blogger will corrupt the angle brackets.


Post a Comment

<< Home