47.5. MSBuild

MSBuild is the new compilation engine Microsoft released with Visual Studio 2005. It uses XML-based configuration files to identify the layout of a build project, including all of the settings discussed earlier in this chapter, as well as what files should be included in the actual compilation.

In fact, since Visual Studio 2005, Visual Studio uses MSBuild configuration files as its project definition files, in place of the old project file formats used by previous versions of Visual Studio. This enables the MSBuild engine to be used automatically when compiling your applications within the IDE because the same settings file is used for both your project definition in the IDE and the build process.

47.5.1. How Visual Studio Uses MSBuild

As already mentioned, the contents of Visual Studio 2008 project files are based on the MSBuild XML Schema and can be edited directly in Visual Studio so you can customize how the project is loaded and compiled.

However, to edit the project file, you need to effectively remove the project's active status from the Solution Explorer. Right-click the project you want to edit in the Solution Explorer and choose the Unload Project command from the bottom of the context menu that is displayed.

The project will be collapsed in the Solution Explorer and marked as unavailable. In addition, any open files that belong to the project will be closed while it is unloaded from the solution. Right-click the project entry again and an additional menu command will be available to edit the project file (see Figure 47-10).

Figure 47.10. Figure 47-10

The XML-based project file will be correspondingly opened in the XML editor of Visual Studio 2008, enabling you to collapse and expand nodes. The following listing is a sample MSBuild project file for an empty Visual Basic project:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft
.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>9.0.21022</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{DE305706-4F2E-44CE-A6CA-6DD4D03B0091}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <StartupObject>Build_Customization.My.MyApplication</StartupObject>
    <RootNamespace>Build_Customization</RootNamespace>
    <AssemblyName>Build Customization</AssemblyName>
    <FileAlignment>512</FileAlignment>
    <MyType>WindowsForms</MyType>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <OptionExplicit>On</OptionExplicit>
    <OptionCompare>Binary</OptionCompare>
    <OptionStrict>Off</OptionStrict>
    <OptionInfer>On</OptionInfer>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <DefineDebug>true</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <OutputPath>binDebug</OutputPath>
    <DocumentationFile>Build Customization.xml</DocumentationFile>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <DefineDebug>false</DefineDebug>
    <DefineTrace>true</DefineTrace>
    <Optimize>true</Optimize>
    <OutputPath>binRelease</OutputPath>
    <DocumentationFile>Build Customization.xml</DocumentationFile>
    <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Deployment" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Core">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
    <Reference Include="System.Xml.Linq">

<RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
    <Reference Include="System.Data.DataSetExtensions">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Import Include="Microsoft.VisualBasic" />
    <Import Include="System" />
    <Import Include="System.Collections" />
    <Import Include="System.Collections.Generic" />
    <Import Include="System.Data" />
    <Import Include="System.Drawing" />
    <Import Include="System.Diagnostics" />
    <Import Include="System.Windows.Forms" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)Microsoft.VisualBasic.targets" />
  <!-- To modify your build process, add your task inside one of the targets below
and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

The XML contains the information about the build. In fact, most of these nodes directly relate to settings you saw earlier in the Compile and Build pages, but also include any Framework namespaces that are required. The first PropertyGroup element contains project properties that apply to all build configurations. This is followed by two conditional elements that define properties for each of the two build configurations, Debug and Release. The remaining elements are for project references and project-wide namespace imports.

When the project includes additional files, such as forms and user controls, each one is defined in the project file with its own set of nodes. For example, the following listing shows the additional XML that is included in a standard WindowsApplication project, identifying the Form, its designer code file, and the additional application files required for a Windows-based application:

<ItemGroup>
  <Compile Include="Form1.vb">
    <SubType>Form</SubType>
  </Compile>
  <Compile Include="Form1.Designer.vb">
    <DependentUpon>Form1.vb</DependentUpon>
    <SubType>Form</SubType>
  </Compile>
  <Compile Include="My ProjectAssemblyInfo.vb" />
  <Compile Include="My ProjectApplication.Designer.vb">
    <AutoGen>True</AutoGen>
    <DependentUpon>Application.myapp</DependentUpon>
  </Compile>

<Compile Include="My ProjectResources.Designer.vb">
    <AutoGen>True</AutoGen>
    <DesignTime>True</DesignTime>
    <DependentUpon>Resources.resx</DependentUpon>
  </Compile>
  <Compile Include="My ProjectSettings.Designer.vb">
    <AutoGen>True</AutoGen>
    <DependentUpon>Settings.settings</DependentUpon>
    <DesignTimeSharedInput>True</DesignTimeSharedInput>
  </Compile>
</ItemGroup>
<ItemGroup>
  <EmbeddedResource Include="Form1.resx">
    <DependentUpon>Form1.vb</DependentUpon>
    <SubType>Designer</SubType>
  </EmbeddedResource>
  <EmbeddedResource Include="My ProjectResources.resx">
    <Generator>VbMyResourcesResXFileCodeGenerator</Generator>
    <LastGenOutput>Resources.Designer.vb</LastGenOutput>
    <CustomToolNamespace>My.Resources</CustomToolNamespace>
    <SubType>Designer</SubType>
  </EmbeddedResource>
</ItemGroup>
<ItemGroup>
  <None Include="My ProjectApplication.myapp">
    <Generator>MyApplicationCodeGenerator</Generator>
    <LastGenOutput>Application.Designer.vb</LastGenOutput>
  </None>
  <None Include="My ProjectSettings.settings">
    <Generator>SettingsSingleFileGenerator</Generator>
    <CustomToolNamespace>My</CustomToolNamespace>
    <LastGenOutput>Settings.Designer.vb</LastGenOutput>
  </None>
</ItemGroup>

You can also include additional tasks in the build process in the included Target nodes for BeforeBuild and AfterBuild events. However, these actions will not appear in the Visual Studio 2008 build events dialog discussed earlier. The alternative is to use a PropertyGroup node that includes PreBuildEvent and PostBuildEvent entries. For instance, if you wanted to execute the application after it was successfully built, you could include the following XML block immediately before the closing </Project> tag:

<PropertyGroup>
  <PostBuildEvent>$(TargetDir)$(TargetFileName)</PostBuildEvent>
</PropertyGroup>

Once you've finished editing the project file's XML, you need to re-enable it in the solution by right-clicking the project's entry in the Solution Explorer and selecting the Reload Project command. If you still have the project file open, Visual Studio will close it automatically.

47.5.2. MSBuild Schema

An extended discussion on the MSBuild engine is beyond the scope of this book. However, it's useful to understand the different components that make up the MSBuild project file so you can look at and update your own projects.

Four major elements form the basis of the project file: items, properties, targets, and tasks. Brought together, you can use these four node types to create a configuration file that describes a project in full, as shown in the previous sample Visual Basic project file.

47.5.2.1. Items

Items are those elements that define inputs to the build system and project. They are defined as children of an ItemGroup node, and the most common item is the Compile node used to identify to MSBuild that the specified file is to be included in the compilation. The following snippet from a project file shows an Item element defined for the Form1.Designer.vb file of a WindowsApplication project:

<ItemGroup>
  <Compile Include="Form1.Designer.vb">
    <DependentUpon>Form1.vb</DependentUpon>
    <SubType>Form</SubType>
  </Compile>
</ItemGroup>

47.5.2.2. Properties

PropertyGroup nodes are used to contain any properties defined to the project. Properties are typically key/value pairings. They can only contain a single value and are used to store the project settings you can access in the Build and Compile pages in the IDE.

PropertyGroup nodes can be optionally included by specifying a Condition attribute, as shown in the following sample listing:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   <DebugType>pdbonly</DebugType>
   <DefineDebug>false</DefineDebug>
   <DefineTrace>true</DefineTrace>
   <Optimize>true</Optimize>
   <OutputPath>binRelease</OutputPath>
</PropertyGroup>

This XML defines a PropertyGroup that will only be included in the build if the project is being built as a Release for the AnyCPU platform. Each of the five property nodes within the PropertyGroup uses the name of the property as the name of the node.

47.5.2.3. Targets

Target elements enable you to arrange tasks (discussed in the next section) into a sequence. Each Target element should have a Name attribute to identify it, and it can be called directly, thus enabling you to provide multiple entry points into the build process. The following snippet defines a Target with a name of BeforeBuild:

<Target Name="BeforeBuild">
</Target>

47.5.2.4. Tasks

Tasks define actions that MSBuild will execute under certain conditions. You can define your own tasks or take advantage of the many built-in tasks such as Copy. Shown in the following snippet, Copy can copy one or more files from one location to another:

<Target Name="CopyFiles">
    <Copy
        SourceFiles="@(MySourceFiles)"
        DestinationFolder="\PDSERVER01SourceBackup"
    />
</Target>

47.5.2.5. Assembly Versioning via MSBuild Task

One aspect of most automated build systems is planning application versioning. In this section you see how you can customize the build process for your project so that it can accept an external version number. This version number will be used to update the AssemblyInfo file, which will subsequently affect the assembly version. Let's start by looking at the AssemblyInfo.vb file, which typically contains assembly version information such as the following:

<Assembly: AssemblyVersion("1.0.0.0")>

What our build customization needs to do is replace the default version number with a number supplied as part of the build process. To do this we have elected to use a third-party MSBuild library entitled Microsoft.Sdc.Task, which is a project on CodePlex (http://www.codeplex.com). This includes a Replace task that can be used to match on a regular expression. Before we can use this task we need to include the source assembly in our MSBuild file (that is, the project file — Build Customization.vbproj):

<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft
.com/developer/msbuild/2003">
    <UsingTask TaskName="Microsoft.Sdc.Tasks.File.Replace"
   AssemblyFile="c:MyDownloadsMSBuild SDC TasksMicrosoft.Sdc.Tasks.dll" />
    <PropertyGroup>
    ...

Because we want to update the AssemblyInfo file before the build, we need to include the BeforeBuild target, as follows:

<Import Project="$(MSBuildToolsPath)Microsoft.VisualBasic.targets" />
<Target Name="BeforeBuild">
<!-- Change the core version files using current build label -->

<Replace Path="$(ProjectDir)My ProjectAssemblyInfo.vb"
   NewValue="Version(&quot;$(buildversion)&quot;)"
   RegularExpression="Version(&quot;[0-9]+.[0-9]+.[0-9]+.[0-9]+&quot;)"
   IgnoreCase="False" Force="True" />
    </Target>
</Project>

You will notice here that we are using a couple of properties, namely $(ProjectDir) and $(buildversion). Whereas the ProjectDir is a predefined property, buildversion is not, so we need to define this property so that our project will build even if this property is not supplied as an MSBuild argument:

<PropertyGroup>
    <buildversion>0.0.0.0</buildversion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

This is all we have to do in order to accept a version number as part of the build process through the property buildversion. When building this project in Visual Studio 2008, this property will not be specified, so it will use the default value of 0.0.0.0. In your automated build process you can specify the version number as an argument to the MSBuild call. For example:

MSBuild "Build Customization.vbproj" /t:Rebuild /p:Configuration=Debug;
/p:buildversion=1.2.3.4

If you get an error such as "The element <BuildingProject> beneath element <PropertyGroup> is unrecognized," it may be that your command is calling the wrong version of MSBuild. You may need to use the fully qualified MSBuild.exe command which is located at C:WindowsMicrosoft.NETFrameworkv3.5.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.157.6