New content are available at http://tis-method.org/. All articles from this site will be moved to the new location.

суббота, 28 мая 2011 г.

MSBuild's items indirect addressing

If you like MSBuild like i'm, you are using this tool everywere. Product deployment, continuous integration, development environment configuration, etc.

Every complex script contains a lot of items transformation steps.
Below, I would like describe one techique, that could be useful for MSBuild's script development.

Let's assume, that you need extract subset from items group with some condition.
Stardard solution could be something like this:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 <ItemGroup>
  <source Include="http://boost.org/download/boost-1.46.1.zip">
   <tag>boost</tag>
  </source>
  <source Include="http://sourceforge.net/projects/loki-lib/files/Loki/Loki%200.1.7/loki-0.1.7.zip/download">
   <tag>loki</tag>
  </source>
 </ItemGroup>
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 <Target Name="Extract">
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  <ItemGroup>
   <item Condition="%(source.tag)==$(tag)" Include="@(source)"/>
  </ItemGroup>
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  <Message Text="Download: %(item.Identity)" />
 </Target>
</Project>
Every 'source' item has additional 'tag' property and this value is used during item transformation.
You can specify item subset with value of 'tag' property.

As you can see, MSBuild's output shows only item with value equal 'boost' in the 'tag' property.
> msbuild extract.targets /p:tag=boost

Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.225]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 28.05.2011 16:10:16.
Project "D:\deployment\msi.targets" on node 1 (default targets).
Extract:
Download: http://boost.org/download/boost-1.46.1.zip
Done Building Project "D:\deployment\msi.targets" (default targets).

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:00.05

The solution with indirect addressing is:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 <ItemGroup>
  <boost Include="http://boost.org/download/boost-1.46.1.zip"/>
  <loki Include="http://sourceforge.net/projects/loki-lib/files/Loki/Loki%200.1.7/loki-0.1.7.zip/download"/>
 </ItemGroup>
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 <Target Name="Extract">
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  <ItemGroup>
   <item Include="@($(tag))"/>
  </ItemGroup>
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  <Message Text="Download: %(item.Identity)" />
 </Target>
</Project>

The MSBuild's output is equal the previous.
The key element of the solution is usage "@($(tag))" expression inside 'Include' item's attribute.

Комментариев нет:

Отправить комментарий