C::B supports precompiled headers that are created like gcc does: compile the header into a
.gch and gcc will find it if it's in the same directory as the header. Visual C++'s precompiled headers require distinct flags for creating and using the precompiled header.
Because C::B doesn't support per-file configuration, giving different options to files is impossible, unless you use the "custom build" option in the properties.
So, here's how you can use precompiled headers with Visual C++ 2005/2008. I'm assuming the names
pch.cpp and
pch.h.
- Add pch.cpp and pch.h to the project.
- Go in the project's build options, "Compiler settings" tab, "Other options" section, and add:
/Yupch.h /Fp$objects_output_dir\pch.obj
Careful: if pch.cpp is not in the same directory as the project file, you'll need to specify it manually. I usually have the project file in / and my sources in /src. Therefore, I use:
/Fp$objects_output_dir\src\pch.obj
This is because C::B creates a directory structure in $objects_out_dir that's similar to the one for source files.
- Right-click on pch.cpp, select "Properties".
- In the "Build" tab, uncheck "Link file" and move the priority slider to 0. This makes sure the pch is compiled first.
- In the "Advanced" tab, check "Use custom command to build this file" and enter:
$compiler /nologo $options $includes /c $file /Ycpch.h
It is possible to avoid entering the path by hand in /Fp by simply using
$objects_output_dir. While this works fine, it breaks C::B's build system, which expects to see the object file in the right directory. Your program will still compile and link fine, but it will always try to rebuild the pch, because it's not in the right place. It will also never clean it.
This also relies on cl.exe being able to choose between /Yu (set in the build options, included through $options in the custom command) and /Yc (set in the custom command) when both are specified, which is the case while compiling
pch.cpp. This seems to work fine on both 2005 and 2008.
[
edit 31-mar-2011: Ugh, there's more problems than I thought with this. The above tricks the build system into thinking that
pch.obj is a regular object file. This way, it is generated and cleaned correctly. However, it is
not an object file, it is a precompiled header. That's why you need to uncheck "Link file".
I realized that a
pch.obj was still being generated in the root directory. This is because /Fo is not specified in the custom command. That
pch.obj is the real object file generated by
pch.cpp.
I now understand that Visual C++ generates two files when compiling
pch.cpp: a precompiled header (
pch.pch) and an object file (
pch.obj). The former is used in each subsequent file using /Yu and the latter is linked at the end. This allows adding definitions in
pch.cpp.
The scheme above does not link with
pch.cpp because its object file is the precompiled header.
There are two possibilities here:
- Getting rid of the pch.obj in the root directory: This would be fine if you didn't need to link with pch.cpp at all. I can't find any way to do this. cl.exe has no way of saying: use this file to generate a precompiled header, but no object file. The /Yc flag is meant to generate the precompiled header in addition to the regular object file.
You can however add a post-build step "cmd /c del pch.obj" which will delete the stray pch.obj from disk. This is something of a hack, but it works.
- Generate both the precompiled header and object file correctly and link with the object file: This is the behavior of Visual C++. To do this, the precompiled header needs to use a different extension, such as .pch, so it doesn't clash with the object file:
- Change /Fp in the project build options to generate "pch.pch" instead of "pch.obj".
- Recheck "Link file" in pch.cpp's properties and add "/Fo$object" back to the custom command.
This way, you'll end up with both pch.pch and pch.obj in the output directory and pch.obj will be linked correctly. This is the typical Visual C++ behavior. However, you now have a file pch.pch of which C::B knows nothing about, because it was generated behind its back with /Yc. Therefore, cleaning the project will not delete that file.
I can't find any way of emulating Visual C++'s behavior exactly: if you generate both files, one of them won't be cleaned. If you don't specify /Fo, you can't link with
pch.cpp and you end up with an unused object file in the root directory.
I could probably make this work if C::B had a place to specify additional files to clean, but there's not.]
[
edit 14-sep-2011: typos]