Web developer from Sydney Australia. Currently using asp.net, mvc where possible.

Sunday, October 17, 2010

Create a Build File for a Visual Studio Solution - MsBuild Series

Why create a build file for a Visual Studio 
Solution?
A build file automates the process of building, testing, analyzing, packaging, & deploying your project. Build files can be used to give you a single click solution to perform mundane tasks in a consistent way.
It saves you time by automating all the tedious steps necessary to prepare your project for testing or deploying. It reduces risk because you can confidently repeat the process, there's no change you will forgot to rename a file or change to release mode etc etc.

OK but How?
Creating a build file for the first time can be a little tricky so I have prepared a quick tutorial on creating a simple msbuild file for compiling your solution. Just follow the steps below and let me know if you have any issues.

1) Folder Structure

Once we start running builds of our project we need a place to store the results. We may also need extra tools for our build process and of course we need a place for our new build file.

Below is a the folder structure I will be using for this introduction. It allows us to keep all of the build files / folders out of our source tree.

Project Root:/
/Build – result of the build will be placed in here
/Source – all source code (& libraries) for the project
/Tools – collection of tools used for the build process
/build.bat – simple 'double click to build' ms dos batch file
/build.proj– our build file for msbuild, this is where we define the steps for our build process

2) Creating the Batch File

Create a new blank file called build.bat in the root directory of your project. This will be a simple ms dos batch file to kick off our build script. Simple copy the contents below into the batch file.
REM dont remove this line
"%windir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" /nologo build.proj  %*
Make sure you leave the first line intact, otherwise you may run into problems because of the encoding used to save the file. If you have issues with encoding then you may need to open the file using a specific encoding (850) see: http://msdn.microsoft.com/en-us/library/dxfdkfke(VS.80).aspx.

The batch file simply calls msbuild.exe and passes in our build.proj file. The %* argument passes any command line arguments supplied to the batch file into the msbuild.exe command. This allows us to specify a target at the command prompt like this: build /t:clean

4) Creating the Build File

Lets start with the simplest sample possible.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

     <PropertyGroup>
      <BuildOutputDir>build</BuildOutputDir>
     </PropertyGroup>

     <Target Name="Clean">
      <RemoveDir Directories="$(BuildOutputDir)" />
     </Target>
 
     <Target Name="Build" DependsOnTargets="Clean">
      <Message Text="Clean"/>
     </Target>
</Project>
 
The build file contains two targets: Clean & Build. Build is our default target so if you run build.bat without any target specified and the build target will be executed by default.

The default target is specified on the 2nd line with DefaultTargets="Build"

The Build target depends on the Clean target, so before the build target is executed the Clean target is executed. The Clean target simply deletes the output directory, giving us a clean working space to preform the build.

The output directory is defined in the ProperyGroup near the top of the file. This simply assigns the variable: BuildOutputDir to the string “build”, which is the name of our output or build directory.
5) Adding the Compile Target
To actually compile the project we need to add another target, which we are going to call Compile.

The updated proj file now looks like this:
<PropertyGroup>
  <BuildOutputDir>build</BuildOutputDir>
  <SolutionToCompile>Source\Jobping.StickBeak.sln</SolutionToCompile>
 </PropertyGroup>

 <Target Name="Clean">
  <RemoveDir Directories="$(BuildOutputDir)" />
 </Target>

 <Target Name="Compile">
  <MakeDir Directories="$(OutputDirectory)" />
  <MSBuild Projects="$(SolutionToCompile)"
     Properties="Configuration=Automated_Build;" />
 </Target>
 
 <Target Name="Build" DependsOnTargets="Clean;Compile">
  <Message Text="Clean, Compile"/>
 </Target>
 
Things to notice:
  • Extra variable for the solution to compile
  • Extra target called Compile
  • Compile target uses msbuild to compile the solution
  • Solution Configuration is set to Automated_Build
  • The Build target now depends on Compile too.
If you run this you should receive an error stating that the Automated_Build configuration does not exists. We need to create this configuration inside visual studio.

6) Creating the Configuration “Automated_Build” in VS

Open up our visual studio solution, then under the Build menu, select Configuration Manager. Create a new configuration called “Automated_Build” as show below, copy the settings from the release configuration.

Creating the Configuration inside Visual Studio


I am going to unselect SampleWeb because I do not want that project compiled as part of the automated build.

Configuration Setup - Removed Sample WEb

Now we will change the output directory for the “Jobping.StickyBeak” project under the “Automated_Build” configuration. As Show below:


With our project configuration complete we can now run our build.

Build Output

As you can see we now have our freshly compiled binaries in the build directory.

By simply adding more targets to your build file you can automate any tedious step that is needed to build and package your project.

This is just the beginning! next we will look at 
Resources:

Shout it kick it on DotNetKicks.com

5 comments:

Bành Quyền said...

great post! thank you so much!

Mark Kemper said...

@Bành Quyền no problem, glad you liked it.

Sayed Hashimi said...

Why are you suggesting to create a new build configuration? If it is just for the output path, just specify it via a property msbuild.exe YourProject /p:OutputPath="..\..\build\".

Mark Kemper said...

@Sayed Hashimi I create a new configuration because I am always tweaking more then just the output path for the automated build

For example, I choose NOT to build a the "Sample.Web" project for this new configuration.

NANDKISHOR WAGH said...

interesting piece of information, I had come to know about your web-page from my friend pramod, jaipur,i have read atleast eight posts of yours by now, and let me tell you, your blog gives the best and the most interesting information. This is just the kind of information that i had been looking for, i'm already your rss reader now and i would regularly watch out for the new posts, once again hats off to you! Thanks a million once again, Regards, Marathi Jokes in Marathi Language