Friday 14 June 2013

Posted by Prasad KM | 11:00 Categories:

Msbuild Conditions 

Besides the CreateItem task in a previous example, our build scripts have been very static until now. This can be sufficient for a lot of projects, but sometimes you need slightly more flexible build scripts. A feature for fulfilling this in MSBuild is called Conditions. A condition in MSBuild is not that different from a condition in other software languages. It is a possibility, for instance, to make more flexible structures to avoid running targets and/or tasks when certain conditions are met. You can define conditions on all targets and almost all tasks. Let’s check out another example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8" ?>
  <PropertyGroup>
    <MyReleaseOutput>.\release</MyReleaseOutput>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
  </PropertyGroup>
  <Target Name="Build">
    <Message Text="Building msbuildintro $(Configuration)" />
    <MSBuild Projects="msbuildintro.csproj" Targets="Build" />
  </Target>
  <Target Name="Release" DependsOnTargets="Build" Condition="$(Configuration) == 'Release'">
    <MakeDir Directories="$(MyReleaseOutput)" />
    <CreateItem Include=".\bin\$(Configuration)\*.*" Exclude=".\bin\$(Configuration)\*vshost.exe">
      <Output TaskParameter="Include" ItemName="MyReleaseFiles" />
    </CreateItem>
    <Copy SourceFiles="@(MyReleaseFiles)" DestinationFolder="$(MyReleaseOutput)" />
  </Target>
</Project>
I added a lot of new stuff here. But of course you are already quite an MSBuild expert, so I think you will manage. First of all, I have added a new property named Configuration. This property contains a condition attribute, which determines the value of the property at runtime. If the Configuration property has not been set up front; the value of the attribute is set to Debug. Properties can be set upfront by using a special syntax on the command line:
Msbuild.exe build.proj /p:Configuration=Debug /t:release
More new stuff. I changed all references to the debug, with the value of the new Configuration property. This means that I am now able to run the script in both Debug and Release mode.
The last new addition is the condition attribute on the release target. This condition examines if the value of the Configuration property is Release and only allows execution of the Release target if this condition is true.

Frequently Used Tasks

CallTarget – Executes another target inside the current build file. Used where a target needs to call another target at a specific place inside the target itself. If the target were just dependant on the other target being executed, we would use the DependsOnTargets attribute instead.
Copy – We already saw this task in action. Copies one or more files from A to B.
CreateItem – Create dynamic items.
CreateProperty – Create dynamic properties.
Delete – Deletes on or more files.
Exec – Executes an external process. This is typically used to executed external tools, which did not implement MSBuild targets themself.
MakeDir – Creates one or more directories.
Message – Outputs a message to the console.
MSBuild – Executes one or more targets in an external MSBuild file.
RemoveDir – Removes one or more directories.
And there are a lot more.

Custom MSBuild Tasks

It is possible to write your own MSBuild tasks. This can be extremely useful if you want to integrate some of your own tools with MSBuild or if you need to do stuff which is not yet supported by MSBuild. The following example shows how to write a simple addition task:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
namespace MyTasks
{
  public class AddTask : Task
  {
    private int number1;
    [Required]
    public int Number1
    {
      get return number1; }
      set { number1 = value; }
    }
    private int number2;
    [Required]
    public int Number2
    {
      get return number2; }
      set { number2 = value; }
    }
    private int sum;
    [Output]
    public int Sum
    {
      get return sum; }
      set { sum = value; }
    }
    public override bool Execute()
    {
      try
      {
        sum = number1 + number2;
      }
      catch (ArithmeticException e)
      {
        Console.WriteLine(&quot;Error occured during addition: {0}&quot;, e.Message);
        return false;
      }
      return true;
    }
  }
}
I start by defining the AddTask class which extends the Task class from the MSBuild API. By extending this task, I don’t need to worry about implementing conditions etc.
I defined two properties which act as input variables to the addition task: Number1 and Number2. Both properties are marked with the Required attribute which tells the script to fail if they are not specified. An output property is added as well. The value of this property will be available within the build script. Let’s see how to use this new and fancy task:
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8" ?>
  <UsingTask TaskName="MyTasks.AddTask" AssemblyFile=".\AddTask.dll"/>
  <Target Name="Addition">
    <AddTask Number1="10" Number2="12">
      <Output TaskParameter="Sum" PropertyName="CalculatedSum" />
    </AddTask>
    <Message Text="10 + 12 = $(CalculatedSum)" />
  </Target>
</Project>
Because my AddTask in an external task not built into the MSBuild framework, I use the UsingTask element to reference it. The name of the task as well as the assembly name is specified.
The Addition target uses the AddTask with the two Number properties as attributes. The Output element copies the result of the task to a property called CalculatedSum. This property is accessible in the Message task for output on the console.
You just implemented your first custom MSBuild task. Pretty easy, right?


0 comments:

  • RSS
  • Delicious
  • Digg
  • Facebook
  • Twitter
  • Linkedin
  • Youtube