10 Minute Tutorial - Silverlight: Building a Silverlight application with MSBuild (C#)

“If you build it they will come”

Don’t know about that, but if you use MSBuild, it’ll sure make everyone’s life a hell of alot easier. :)

Until now, I used batch files to build the C# managed code used in my Silverlight tutorials. Now granted, a build and batch file share many traits: both execute instructions in a (mostly) seequential order on a set of inputs. However, build systems really shine in their ability to provide more domain specific constructs for working with files, directories, source assets and external utilities. This relieves the developer from the typical file shuffling burden that plagues an even midly complex build. As of .NET 2.0, Microsoft provides developers with a build engine, called MSBuild, as part of the runtime distribution. In this tutorial, I will walk through hand-coding a MSBuild build file for the sample code of my last Silverlight tutorial application.

Prerequisites

QuickStart

If you want to see the end result of this tutorial and you have installed all the prerequisites, then please download the ZIP file below, unzip it and run this command:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\msbuild.exe Scriptable.csproj

Lesson

Step #1: Create a project file

First, unzip Scriptable.zip file that you downloaded in the prerequisites into its own directory. Then in that directory, create a file named Scriptable.csproj. In this file, declare a Project that contains a Compile Target, like so:

<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<Target Name="Compile">
	</Target>
</Project>

As you can see, MSBuild uses XML for its build definition files. The Project element, the most top-level element in a MSBuild file, encompasses EVERYTHING: targets, property definitions, input file items, etc. Inside this project, resides a Target named Compile. A Target represents a callable grouping of instructions that MSBuild will execute in sequential order, similar to a function in C# or any other language. Also, note that by setting the Project DefaultTargets attribute, the project will execute the Compile Target by default if the target remains unspecified when building this project using the msbuild command line program.

And with that, we have a valid (yet empty) build file. Now, let’s make it do something useful.

Step #2: Add the input files

Clearly, the Compile Target we defined in Step #1 needs something to compile. So, let’s add the Scriptable.xaml.cs to the project:

<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<ItemGroup>
 		<ScriptableXAMLCS Include=”Scriptable.xaml.cs” />
	</ItemGroup>
	<Target Name=”Compile”>
	</Target>
</Project>

So, the highlighted ItemGroup tag contains a tag that I completely made up called ScriptableXAMLCS. Since the ScriptableXAMLCS tag resides within an ItemGroup tag, the MSBuild system sees it as an “MSBuild Item“. MSBuild Items represent collections of input files for the project and carry user-defined names. In this case, I have a collection named ScriptableXAMLCS that contains one file, “Scriptable.xaml.cs”.

Step #3: Reference the Silverlight assembiles

To successfully compile, the project will also need to reference the Silverlight libraries. Those references will need their own collection:

<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<ItemGroup>
 		<ScriptableXAMLCS Include="Scriptable.xaml.cs" />
	</ItemGroup>
	<ItemGroup>
 		<SilverlightLibs Include=”agclr.dll” />
	 	<SilverlightLibs Include=”mscorlib.dll” />
	 	<SilverlightLibs Include=”system.dll” />
	 	<SilverlightLibs Include=”System.Core.dll” />
	 	<SilverlightLibs Include=”System.Silverlight.dll” />
	 	<SilverlightLibs Include=”System.Xml.Core.dll ” />
	 </ItemGroup>
	 <Target Name=”Compile”>
	 </Target>
</Project>

Nothing new here. Note that each Item in the highlighted ItemGroup has the same tag name. This means, that all these files will belong to the collection SilverlightLibs and we can reference them using one name.

Which we’re going to do right now…

Step #4: Compile

The coup de gras. With all our inputs defined, MSBuild needs to pass those inputs into csc, the C# compiler. But first, as a refresher, let’s look at the previous compilation command contained in the compile.bat file:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe /t:library /nostdlib+ /noconfig /out:ScriptableCanvas.dll /lib:"C:\Program Files\Microsoft Silverlight" /r:agclr.dll;mscorlib.dll;system.dll;System.Core.dll;System.Silverlight.dll;System.Xml.Core.dll Scriptable.xaml.cs

Let’s build this step by step. First, we need to execute CSC. We can do this using an MSBuild Task named, unsurprisingly, CSC:

<CSC />

CSC needs to build a library (the /t:library in our command-line above), and we tell it that by setting the TargetType attribute:

<CSC TargetType="library" />

CSC does not need to use the standard libraries (/nostdlib+), so we set the NoStandardLib attribute to “true”:

<CSC TargetType="library" NoStandardLib="true" />

This project doesn’t require any of the assemblies shipped with the .NET Framework as defined in the csc.rsp file, and setting the NoConfig attribute makes sure these files don’t get referenced:

<CSC TargetType="library" NoStandardLib="true" NoConfig="true" />

Now, we need to tell CSC what to name the output file:

<CSC TargetType="library" NoStandardLib="true" NoConfig="true" OutputAssembly="ScriptableCanvas.dll" />

For a default installation of Silverlight, the assemblies this project needs to reference will reside in the “C:\Program Files\Microsoft Silverlight” directory. We can pass CSC this information using the AdditionalLibPaths attribute:

<CSC TargetType="library" NoStandardLib="true" NoConfig="true" OutputAssembly="ScriptableCanvas.dll" AdditionalLibPaths="C:\Program Files\Microsoft Silverlight" />

Now, things get interesting. From Step #3, we know that the SilverlightLibs collection contains all of the Silverlight libraries files needed by this application. MSBuild uses the @(name) syntax to reference collections and the CSC expects the libraries as part of its References attribute. So, the CSC task now looks like this:

<CSC TargetType="library" NoStandardLib="true" NoConfig="true" OutputAssembly="ScriptableCanvas.dll" AdditionalLibPaths="C:\Program Files\Microsoft Silverlight" References="@(SilverlightLibs)" />

Finally, the including the “Scriptable.xaml.cs” source file defined in the ScriptableXAMLCS collection will happen in a similar manner:

<CSC TargetType="library" NoStandardLib="true" NoConfig="true" OutputAssembly="ScriptableCanvas.dll" AdditionalLibPaths="C:\Program Files\Microsoft Silverlight" References="@(SilverlightLibs)" Sources="@(ScriptableXAMLCS)" />

Phew. Now, we just need to put our newly-minted CSC task into the Compile Target:

<Project DefaultTargets="Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<ItemGroup>
	 	<ScriptableXAMLCS Include="Scriptable.xaml.cs" />
	</ItemGroup>
	<ItemGroup>
	 	<SilverlightLibs Include="agclr.dll" />
		<SilverlightLibs Include="mscorlib.dll" />
	 	<SilverlightLibs Include="system.dll" />
	 	<SilverlightLibs Include="System.Core.dll" />
	 	<SilverlightLibs Include="System.Silverlight.dll" />
	 	<SilverlightLibs Include="System.Xml.Core.dll " />
	</ItemGroup>
	 <Target Name=”Compile”>
	 	<CSC TargetType=”library” NoStandardLib=”true” NoConfig=”true” OutputAssembly=”ScriptableCanvas.dll” AdditionalLibPaths=”C:\Program Files\Microsoft Silverlight” References=”@(SilverlightLibs)” 	Sources=”@(ScriptableXAMLCS)” />
	</Target>
</Project>
Step #5: Run it!

First, delete the ScriptableCanvas.dll currently in the directory. Then to run the build file, execute this command, assuming you have the .NET SDK installed in the default directory on your workstation:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\msbuild.exe Scriptable.csproj

This should create the ScriptableCanvas.dll.

Conclusion

This tutorial walked through creating a basic MSBuild file for a Silverlight application. Granted, you may not see the point in simply recreating a working batch file, but having an MSBuild file opens up a whole new realm of productivity and flexibility. Developers can spend less time coding up small utilities, worrying about command line switches to shell scripts and mucking around in the files system and spend more time using and writing tasks to manipulate their build assests quickly. Also, Visual Studio can open any valid MSBuild file, so a developer can go back and forth between hand-tweaking their build and then reusing that as a Visual Studio project. Although NAnt served me well for years, it brings me solace to see Microsoft recognizing the need for a standalone build engine and then meeting that need with the high quality solution developers expect from the .NET eco-system.

For further reading, check out the links below:

An Introduction to MSBuild on The Code Project

MSBuild Wiki Page

7 Steps to MSBuild

Share and Enjoy:
These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • StumbleUpon
  • Reddit
  • del.icio.us
Leave a Donation

If you found this article helpful, please leave a donation for Dave, so he can help you again. As always, thank you for your support!

Related Posts:
10 Minute Tutorial - JavaFX: Hello World
Birds of a Feather: Silverlight, Flex and JavaFX
10 Minute Tutorial - Silverlight: Application Framework
Channel 9 video review: Mike Sampson - Building a Silverlight player for Channel 9

Comments are closed.