The official source of product insight from the Visual Studio Engineering Team
The VC++ build system is of course MSBuild based in VS 2010. This automatically gives you a great deal more flexibility to customize your build than you had with .vcproj project files in prior releases. We went out of our way to ensure that the .targets files that drive the build of a .vcxproj file in VS 2010 leverage as much MSBuild flexibility as possible.
Some build extensions are very simple: just execute a hard-coded command at a given place and time during the build. Others are more complex: any time you see a *.crt file run a custom tool on it, setting parameters based on properties on that item, etc. We wanted to keep the simple scenarios simple, and save the complexity that comes with flexibility for only those scenarios that needed it. This post will discuss a couple of the simple build extension options you have, and how they’ve changed since VS 2008.
In VS 2008, Visual C++ had a couple of the simple scenarios called Custom Build Step and Custom Build Tool. Actually these ideas ran together in not so obvious ways in 2008 which made them a bit confusing despite their intention to support the simple scenarios. So let’s just look at what they are in VS 2010.
First some overall truths about these build extensions:
Custom Build Steps are the quick (but not dirty) way to get an arbitrary command executed at a specific point during the build. The Custom Build Step is a project level build step (meaning it runs only once during a project build rather than once per file).
The way the Execute After and Execute Before properties work may not be totally obvious. It hooks into MSBuild’s new “before and after” targets feature, which allows an MSBuild target to declare any arbitrary target included in the project (or its imports) that this target should run before or after. Important ramifications of this include:
Custom Build Steps are included as part of the intelligence that drives incremental build using the “Additional Dependencies” and “Outputs” properties. If a file in your “Additional Dependencies” property is touched, then your Custom Build Step will be considered out of date and will build with your next build (as long as the .targets it runs before/after are also run).
The Outputs property is a semicolon-delimited list of files, and must list whatever files are generated as part of the execution of your custom build step. If you leave your Outputs property empty, your Custom Build Step will never execute, since MSBuild will determine that no outputs are out of date. If your step doesn’t generate files but you still want it to execute with every build, making up a fake filename will do the trick, since that file will never exist and MSBuild will always determine that the custom build step is out of date. However, before you do this, consider Build Events (below).
Custom Build Tools allow you to execute a custom command line for an individual source file as part of the build. Custom Build Tool is a file level build extension, and without a source item being marked CustomBuild, this tool won’t do anything. You can right-click a CustomBuild project item in Solution Explorer and click Compile to invoke your custom build tool.
Any source item (read: file in your project) can have a custom command line executed during the build by setting its Item Type property in the property pages for that item to “Custom Build Tool” (or CustomBuild in the project file directly). If using the UI, be sure to click Apply to see the Custom Build Tool property page appear.
In the Custom Build Tool property page, you may notice it looks very similar to the Custom Build Step property page. This is more by coincidence than design. But there is a legacy-compatibility link between Custom Build Step and Custom Build Tool in VS2010: custom build tools always run at the time the custom build step would run; except when it doesn’t. When no value is specified for Execute Before and Execute After for the Custom Build Step, the before and after targets for custom build step and custom build tool vary (go figure) in order to maintain compatibility with VS 2008. In all other ways these two build extensions are totally unrelated.
Custom Build Tool is targeted at the exceptional source item case (you have just one source item that needs this kind of command executed on it) rather than a group of files. If you’re trying to set up a command that runs on all .customextension files, you should consider using a Custom Build Rule (now called Build Customization) rather than a Custom Build Tool, as that is exactly what custom build rules are for.
If Custom Build Tool is file-level, why do you see Custom Build Tool in your project level property pages? Because just like any other tool (i.e. CL or Link), you can set project-level defaults for its properties. But these properties have no impact on the project itself… only on project source items that are of the CustomBuild type.
Nothing much changed here since VS2008. These three events (Pre-build, Pre-link, and Post-build) fire during the course of a normal build and allow you to execute arbitrary project-level commands.