Mike's profileFreeToDevBlogLists Tools Help

Blog


    June 24

    MSBuild 4.0 BeforeTargets and AfterTargets

    Visual Studio 2010 Beta 1 gives the wider community their first look at what is on offer in MSBuild 4.0. In this post I’ll briefly cover the new BeforeTargets and AfterTargets features.

    These targets sit in the new MSBuild.Construction namespace and on initial inspection, they provide you with the ability to plug in targets to alter the execution path of a MSBuild file.

    Lets cover this with a basic example. Running the following sample,

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

      <Target Name="Default">
        <Message Text="Hello from Default"/>
      </Target>

    </Project>

    we get the expected:

    Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
      Hello from Default
    Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

    Now suppose you wanted to run a target before the Default target. In .NET 3.5 you would use DependsOnTargets as shown with the following:

     

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

      <Target Name="Default" DependsOnTargets="DefaultDependsOn">
        <Message Text="Hello from Default"/>
      </Target>

      <Target Name="DefaultDependsOn">
        <Message Text="Hello from DefaultDependsOn"/>
      </Target>

    </Project>

    which would result in:

    Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
      Hello from DefaultDependsOn
    Default:
      Hello from Default
    Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

    So what’s wrong with DependsOnTargets? Well, not a lot, however the above implementation does create an explicit bind between the targets and may reduce your ability to reuse the default target efficiently.

     

    Enter BeforeTargets

    In MSBuild 4.0 you can achieve the same result by using the following

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

      <Target Name="Default">
        <Message Text="Hello from Default"/>
      </Target>

      <Target Name="DefaultBeforeTarget" BeforeTargets="Default">
        <Message Text="Hello from DefaultBeforeTarget"/>
      </Target>

    </Project>

    which results in:

    Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
      Hello from DefaultBeforeTarget
    Default:
      Hello from Default
    Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

    So we get the same functionality, but our targets are arguably more reusable. I don’t think there is a need to go and re-write all your code, but remember that you have this feature in your tool belt in 4.0.

    Now it may be that I’ve used it a lot, but DependsOnTargets makes a lot of sense to me. It does ‘as it reads’, i.e. the Default target depends on Targets xyz… A minor concern I have with this new feature is that it doesn’t do ‘as it reads’. The first time i saw a sample with this I expected that all the BeforeTargets would run before the named target. Perhaps a better name would be RunBeforeTargets, which makes it clear that the named target will run before all the targets listed. The same logic could be applied to AfterTargets (or perhaps a better named RunAfterTargets)

     

    Enter AfterTargets

    In a very similar light, the new AfterTargets feature allows us to run a target after a given target. Running the following sample:

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

      <Target Name="Default">
        <Message Text="Hello from Default"/>
      </Target>

      <Target Name="DefaultBeforeTarget" BeforeTargets="Default">
        <Message Text="Hello from DefaultBeforeTarget"/>
      </Target>

      <Target Name="DefaultAfterTarget" AfterTargets="Default">
        <Message Text="Hello from DefaultAfterTarget"/>
      </Target>
    </Project>

    we get:

    Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
      Hello from DefaultBeforeTarget
    Default:
      Hello from Default
    DefaultAfterTarget:
      Hello from DefaultAfterTarget
    Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

     

    But DependsonTargets Rules!

    So you can see how these two new features provide the ability to easily tweak execution. You can also plug into existing target frameworks without affecting other users. Now what of the DependsOnTargets in 4.0? It still lives on of course and its important to understand the order of execution.

    Take the following example:

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

      <Target Name="Default" DependsOnTargets="DefaultDependsOn">
        <Message Text="Hello from Default"/>
      </Target>

      <Target Name="DefaultDependsOn">
        <Message Text="Hello from DefaultDependsOn"/>
      </Target>

      <Target Name="DefaultBeforeTarget" BeforeTargets="Default">
        <Message Text="Hello from DefaultBeforeTarget"/>
      </Target>

      <Target Name="DefaultAfterTarget" AfterTargets="Default">
        <Message Text="Hello from DefaultAfterTarget"/>
      </Target>
    </Project>

    Would you expect to see DefaultBeforeTarget or DefaultDependsOn execute first? Below is the result:

    Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" on node 1 (default targets).
      Hello from DefaultDependsOn
    DefaultBeforeTarget:
      Hello from DefaultBeforeTarget
    Default:
      Hello from Default
    DefaultAfterTarget:
      Hello from DefaultAfterTarget
    Done Building Project "C:\Users\administrator.DEV\Desktop\MSBuild Samples\BeforeAfter.proj" (default targets).

    So as you can see, order of execution is DependsOnTargets, BeforeTargets, [NamedTarget], AfterTargets.

    What do you think of this new feature? Can you think of better names or do they make sense to you?

    --- Mike

    Are you ready for .NET 4.0?

    Check out the .NET Framework Compatibility Blog for all the latest information regarding compatibility.

    You can also follow a walkthrough here

    June 11

    Inline coding in MSBuild 3.5

    Stephen Cleary has just checked in the first version of the DynamicExecute task. This will ship in version 3.5.4.0 of the MSBuild Extension Pack, but if you compile the code yourself, you can start using it now.

    We’d appreciate any feedback you have. Download

    Documentation for the task is provided here

    June 07

    MSBuild Extension Pack 3.5.3.0 --- Available now

    We’ve just shipped the latest release of the MSBuild Extension Pack! This release slipped in schedule a tiny bit but includes over 40 new tasks and represents a 20% increase in our code base.

    ScreenShot004

    Thanks to all those who have contributed to making this significant release. Download here

    PS, you can catch the latest updates on Twitter: http://twitter.com/msbep

    Mike