Build System

MSBuild Overview

The Microsoft Build Engine (MSBuild) is the build platform for Microsoft and Visual Studio. MSBuild has been shipped as a component of the .NET framework since it was first introduced in 2005 with .NET 2.0. Starting with Visual Studio 2013, the 2013 version of MSBuild will ship as a part of Visual Studio instead of the .NET Framework.

Learning MSBuild is like learning any new language. There are some basics that you need to understand to get started. For example, the language is declarative, as opposed to imperative languages such as C# and VB. Hence, the traditional flow of execution may seem strange at first.

One great exercise to start is to take a look at the contents of a new C# or VB project in Visual Studio. To do so, right-click on a project node in “Solution Explorer” and click “Unload Project” in the context menu that appears. The project will unload and become grayed out.

Next, right-click on the same project node and select “Edit {ProjectName}”. The project file will be loaded up in the Visual Studio XML editor.

Take a look at the XML: You will notice that there are PropertyGroups that contain child nodes (known in MSBuild as “properties”) which define the build settings for various configurations. These are the global switches you might provide to tools to determine whether you want optimized or debug code, or whether or not to generate symbols.

<?xml version=”1.0″ encoding=”utf-8″?>
<Project ToolsVersion=”4.0″ DefaultTargets=”Build” xmlns=”http://schemas.microsoft.com/developer/msbuild/2003″&gt;
<PropertyGroup>
<Configuration Condition=” ‘$(Configuration)’ == ” “>Debug</Configuration>
<Platform Condition=” ‘$(Platform)’ == ” “>x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8076DCA7-8C27-44D9-9A0F-7CD5C091C6E1}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Sample</RootNamespace>
<AssemblyName>Sample</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=” ‘$(Configuration)|$(Platform)’ == ‘Debug|x86’ “>
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>

Closer to the bottom of the file, you will see ItemGroups gathering sets of MSBuild “items”, used to represent concepts such as References (Imports in VB), Compile items (these are your source code files you have added to the project), resources, etc. Items are used to keep track of lists, while properties are key-value pairs.


<ItemGroup>
<Reference Include=”System” />
<Reference Include=”System.Core” />
<Reference Include=”System.Xml.Linq” />
<Reference Include=”System.Data.DataSetExtensions” />
<Reference Include=”Microsoft.CSharp” />
<Reference Include=”System.Data” />
<Reference Include=”System.Xml” />
</ItemGroup>
<ItemGroup>
<Compile Include=”Program.cs” />
<Compile Include=”Properties\AssemblyInfo.cs” />
</ItemGroup>
<Import Project=”$(MSBuildToolsPath)\Microsoft.CSharp.targets” />
</Project>

You are also bound to see an Import element or two. These allow you to pull in MSBuild code located in other files. By placing your MSBuild code outside the project in imports you keep the individual project files small. The things specific to that project are located in the project, and settings of broader interest are located in the reusable components (targets), which are generally located where lots of projects can easily point to them. Typically, imports have the “.props” or “.targets” extension. MSBuild does not really care what the extension is, and considers these to all be just regular MSBuild project files. By convention, the extensions imply that a “.props” file contains property definitions (and/or items and definitions), and a “.targets” file contains target definitions.

<Target Name=”PrintMyMessage”>
<PropertyGroup>
<MyMessage>MSBuild Rocks!</MyMessage>
</PropertyGroup>
<Message Text=”$(MyMessage)” />
</Target>

A target is something like a sub-routine or procedure in a traditional language. They are built with XML, but act more like imperative code. The example target above, named PrintMyMessage, sets the property MyMessage to “MSBuild Rocks!”, and then prints it to the output. The <Message /> element above is what calls the Message task to actually print the property. MSBuild ships with a wealth of targets for building the projects you use in Visual Studio.

Tasks are like MSBuild library functions. A large set of tasks are bundled with MSBuild, including tasks to make directories, copy/delete files, invoke the compilers, etc. In fact, almost all of the command line build tools in the .NET Framework that are needed to build most applications are wrapped by a corresponding MSBuild task. If none of the pre-existing tasks suit, you can look at an existing library like the comprehensive MSBuild Extensions Pack. Or, you can write your own tasks. Tasks can be built from any of the managed languages, or with v4.0, you can write inline tasks in VB or C#.

<Project ToolsVersion=”4.0″ DefaultTargets=”Build” xmlns=”http://schemas.microsoft.com/developer/msbuild/2003″&gt;

</Project>

To hook all of this together, you need a place to start. In MSBuild, there are several ways to get started. In the project file you have open, look at the top opening <Project> element. You will see a DefaultTargets attribute. This defines the targets that will executed if you run MSBuild on the file. In a standard project, this is set to “Build“. If you want to run something other than the default target(s), you can also tell MSBuild explicitly which target you want to execute in the project. For example, the Rebuild target runs the Clean target followed by the Build target to rebuild your project. To run the Rebuild target instead, in a standard Visual Studio command prompt you can type:

msbuild Sample.csproj /t:Rebuild

This will run MSBuild on the Sample.csproj project, and initiate the “Rebuild” target. To specify multiple targets, list them in a semicolon-delimited list, e.g.

msbuild Sample.csproj /t:Clean;Build

Once the process has been kicked off by specifying a starting target(s), MSBuild will then build the target(s) and any others that have been chained to it by the various means MSBuild has to specify dependencies. If a target depends on another target(s) (as specified by the DependsOnTargets attribute on the target element), then MSBuild will run the other target(s) prior to running the target specified. In MSBuild v4.0, you can also use the BeforeTargets and AfterTargets attributes to specify the targets this target needs to run before or after respectively.

Unlike the flexibility afforded to you by calling MSBuild on the command line, Visual Studio only explicitly supports the use of four targets: Build, Clean, Rebuild, and Publish.

When you are done exploring your project, right-click on the project name in the Solution Explorer and choose “Reload Project” from the context menu. This will load the project back up in Visual Studio.

Now, when you click build, or F5 to debug (which first requests a build under the covers), all this is set in motion. Visual Studio kicks off an execution of the desired MSBuild target, and the items in your project are built according to the definitions provided by the project and any other targets files or property sheets.

And this is where you come in: you can leverage this same system to do all sorts of cool things when you build. You can use MSBuild to deploy files to a server, automatically increment your build number, or even send yourself a text message upon completion of a nightly build. And it is so simple to do and to use.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s