Exploring the New MSBuild Features for Visual C++ 2010

The move in Visual C++ 2010 to MSBuild is a great step forward for Visual C++ developers. At first glance, the use of a different file format for Visual C++ projects may cause reactions ranging from indifference to concern over disruptions and breakages to any existing customizations to the build process. However, by allowing Visual C++ builds to take advantage of the wide variety of extensibility points in the MSBuild engine, the limited extensibility of the VCPROJ format looks primitive by comparison.

MSBuild: The Basics

In some ways, the use of MSBuild as the file format for Visual C++ is a back-to-the-future moment for long-time C++ developers. In the early days of Visual C++, the MAK file format was preferred way to describe the build process that would compile and link a collection of source code files into a binary image. Although MAK files and the nmake tool are still supported, the file format of Visual C++ changed over the years to an XML format that was not compatible with nmake. To support Visual C++ compilations on build boxes and other machines without the Visual C++ IDE installed, VCBuild.exe was introduced; it can build based on the Visual C++ XML VCPROJ file format. A degree of MSBuild support is available in Visual C++ 2008 and below with the VBBuild MSBuild task, but this treats the Visual C++ compilation as a black box, and does not allow easy integration with the rest of MSBuild’s features.

Visual C++ 2010 uses MSBuild as the native project file format for C++. This offers a number of advantages for C++ developers—MSBuild is extremely flexible in the ways a build process can be customized, and custom task development for MSBuild is simple (tasks are the ‘doing’ things in MSBuild, and they will be covered in more details later in this article). Microsoft ships dozens of MSBuild Tasks out-of-the-box, with functionality ranging from copying files to registering assemblies to signing a file with a certificate. There is also a rich range of community and commercial tasks available for more advanced tasks, and the Exec task can be used to call out to existing command-line based build tools.

The Visual C++ 2010 October 2008 CTP ships with MSBuild support disabled, but it can be activated by running the NewVcProjectSystem.cmd batch file located at C:Program FilesMicrosoft Visual Studio 10.0Common7IDE on the Virtual PC image. It also is possible to upgrade an existing project to use the MSBuild file format using the C:Program FilesMicrosoft Visual Studio 10.0Common7Toolsvcupgrade.exe application. The RTM version of Visual C++ 2010 will not have this issue.

MSBuild Features

The full schema definition for the MSBuild file format is available on the MSDN site. Even though the schema looks pretty complex, MSBuild conceptually can be simplified to four main concepts:

Items

An item in MSBuild is an input into the build system. Items are specified in MSBuild by including them as child elements of an ItemGroup element. The name of the elements beneath an ItemGroup determines the name of the ItemGroup. The following XML sample shows three of the ItemGroup elements from a Win32Console application:

<ItemGroup>
   <None Include="ReadMe.txt" />
</ItemGroup>

<ItemGroup>
   <ClInclude Include="stdafx.h" />
   <ClInclude Include="targetver.h" />
</ItemGroup>

<ItemGroup>
   <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader
         Condition="'$(Configuration)|$(Platform)'==
         'Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader
         Condition="'$(Configuration)|$(Platform)'==
         'Release|Win32'">Create</PrecompiledHeader>
   </ClCompile>
   <ClCompile Include="Win32ConsoleApp.cpp" />
</ItemGroup>

The three ItemGroups are None, ClInclude, and ClCompile. These item groups can be referred to in the MSBuild file by using the @(group_name) syntax. For the MSbuild extract shown, the three item group names are @(None), @(ClInclude), and @(ClCompile). The @(ClCompile) item also includes a child element that contains metadata about the item. Item metadata is referenced by prefixing it with the percent (%) symbol, so @(ClCompile) has metadata of %PrecompiledHeader.

Properties

Although Items allow complex collections of build input to be specified, MSBuild Properties are much simpler, and are used to specify a simple key-value pair of information for the build. The properties in a MSBuild file map to the properties that are set on the Configuration properties for a Visual C++ project. As shown below, properties are grouped in a PropertyGroup element in much the same way as ItemGroup elements.

Some properties will be relevant regardless of build configuration; others will be relevant only for a certain project configuration. In the following MSBuild extract, two property groups are shown—the first property group is relevant for all project configurations, and the second is conditionally active for a Debug | Win32 configuration. Properties can be referred to in other sections of the MSBuild file by using the $(PropertyName) syntax, as shown for the $(Configuration) and $(Platform) properties in the Condition statement.

<PropertyGroup>
   <ConfigurationType>Application</ConfigurationType>
   <TargetName>Win32ConsoleApp</TargetName>
   <ShowAllFiles>false</ShowAllFiles>
   <ProjectGUID>
      {A3D3BF50-460A-4396-9204-7E4041E9AD7B}
   </ProjectGUID>
   <TargetFrameworkVersion>4.0</TargetFrameworkVersion>
   <Keyword>Win32Proj</Keyword>
   <RootNamespace>Win32ConsoleApp</RootNamespace>
</PropertyGroup>

<PropertyGroup
   Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
   <CharacterSet>Unicode</CharacterSet>
   <LinkIncremental>true</LinkIncremental>
</PropertyGroup>

Properties also can be specified on the MSBuild command line by using the /property command line switch. It has the effect of overriding the value of the property set within the MSBuild file.

Tasks

Tasks in MSBuild take Items and Properties, and complete an activity. Examples of tasks include compiling source code files, signing binary images produced by the build, or sending an email if the build fails. Even though it is possible to use an XML CDATA section to write tasks inline in a MSBuild XML file, tasks generally will be written in a managed language, and will be in the form of a managed class that implements the ITask interface. A Task can expose any number of user-defined properties that are specified in the MSBuild file and passed through to the Task by the MSBuild engine when the Task object is created. When a Task needs to be kicked off by the MSBuild engine, the ITask.Execute method is called.

A task can be imported into a MSBuild file by using the UsingTask element. To access the C++ compilers CppClean task in a MSBuild file, the following declaration needs to be included:

<UsingTask TaskName="CPPClean"
           AssemblyName="Microsoft.Build.CPPTasks.Common,
           Version=4.0.0.0,
           Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

<ItemGroup>
   <CoreCPPClean Include="$(IntDir)" />
   <CoreCPPClean Include="$(OutDir)">
      <FilePatternsToDelete>$(TargetName).exe;
         $(TargetName).dll;
         $(TargetName).lib;
         $(TargetName).pdb;
         $(TargetName).ilk
      </FilePatternsToDelete>
   </CoreCPPClean>
</ItemGroup>

<CPPClean
   FoldersToClean = "@(CoreCPPClean)"
   FilePatternsToDeleteOnClean =
      "%(CoreCPPClean.FilePatternsToDelete)"
/>

Two properties are supplied to the CPPClean task—the FolderToClean property that is set to the CoreCPPClean item, and the FilePatternsToDeleteOnClean property that is set to the %(CoreCPPClean.FilePatternsToDelete) item metadata.

Targets

Targets are the externally visible part of a MSBuild file, and represent a grouping of tasks in a particular order to produce an action that is meaningful to the end user. The CPPClean task can be wrapped in a Target as follows:

<Target Name="CleanTheBuild">
   <Message Text="Cleaning The Build" />
   <CPPClean
      FoldersToClean = "@(CoreCPPClean)"
      FilePatternsToDeleteOnClean =
         "%(CoreCPPClean.FilePatternsToDelete)"
   />
</Target>

If this target is included in a file called Win32ConsoleApp.vcxproj (vcxproj is the file extension for Visual C++ projects that use MSBuild), the CleanTheBuild target can be activated by the following command line statement:

MSBuild.exe Win32ConsoleApp.vcxproj /target:CleanTheBuild

A MSBuild file also can specify a default target, which will be the compile action for a vcxproj file. The default target is called by the MSBuild engine when no /target command line switch is supplied.

Conclusion

The move of Visual C++ onto the MSBuild platform brings C++ inline with Microsoft’s other compiler offerings that all use this format. Visual C++ 2010 is deeply integrated into MSBuild, with all elements of the build process fully visible and accessible in the new VCXPROJ project file format.

MSBuild is a documented, powerful, and extensible build engine that far exceeds the capabilities of the previous Visual C++ build engine. MSBuild takes Items and associated Properties as inputs into a Task, and Tasks are grouped together into Targets to form a high-level build activity. MSBuild will be welcomed by C++ developers who miss the power and expressiveness of MAK files, and for developers who have yet to explore the world of build customization and extension, the introduction of MSBuild as the project file format for Visual C++ 2010 represents the best time to get started.

About the Author

Nick Wienholt is an independent Windows and .NET consultant based in Sydney. He is the author of Maximizing .NET Performance and co-author of A Programmers Introduction to C# 2.0 from Apress, and specialises in system-level software architecture and development, with a particular focus of performance, security, interoperability, and debugging.

Nick is a keen and active participant in the .NET community. He is the co-founder of the Sydney Deep .NET User group and writes technical articles for Australian Developer Journal, ZDNet, Pinnacle Publishing, CodeGuru, MSDN Magazine (Australia and New Zealand Edition), and the Microsoft Developer Network. An archive of Nick’s SDNUG presentations, articles, and .NET blog is available at www.dotnetperformance.com. In recognition of his work in the .NET area, he was awarded the Microsoft Most Valued Professional Award from 2002 through 2007.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read