如何在目标之间传递带有元数据的ItemGroup?

时间:2014-12-05 21:58:40

标签: msbuild

根据我的理解,使用DependsOnTargets是在目标之间传递ItemGroup所必需的。我不确定是否有其他方法可以在没有DependsOnTargets的情况下传递目标。

我测试过ItemGroup无法从CallTargetMSBuild任务传递。解决方法是将ItemGroup转换为property(展平它)并使用Properties进行传递。

我定义了ItemGroup FileFile具有Value元数据。我想执行target并为每个递归循环删除一个File项。这是我的剧本:

<Target Name="MyGroup">
  <ItemGroup>
    <File Include="5">
      <Value>5a</Value>
    </File>
    <File Include="4">
      <Value>4a</Value>
    </File>
    <File Include="3">
      <Value>3a</Value>
    </File>
    <File Include="2">
      <Value>2a</Value>
    </File>
    <File Include="1">
      <Value>1a</Value>
    </File>
  </ItemGroup>
</Target>

<Target Name="Recursive" DependsOnTargets="MyGroup" Condition="$(Value) > 0">
  <ItemGroup>
    <File Remove="$(Value)" />
  </ItemGroup>

  <PropertyGroup>
    <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
  </PropertyGroup>

  <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />
  <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
</Target>

<Target Name="Build" DependsOnTargets="MyGroup">
  <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>

输出结果为:

File: 4a;3a;2a;1a Value=4
File: 5a;3a;2a;1a Value=3
File: 5a;4a;2a;1a Value=2
File: 5a;4a;3a;1a Value=1
File: 5a;4a;3a;2a Value=0

我希望输出为:

File: 4a;3a;2a;1a Value=4
File: 3a;2a;1a Value=3
File: 2a;1a Value=2
File: 1a Value=1
File: Value=0

有解决方案吗?

1 个答案:

答案 0 :(得分:1)

不是真的,你试图绕过msbuild只想构建一次目标的想法(除非输入\输出发生变化)。 并且您无法在MSBuild上下文之间传递项目组(当您调用MSBuild任务时 - 创建新上下文)。同样在您的脚本中 - ItemGroup的作用域为目标 - 您需要全局定义它,以便其他目标可用。 你能做的是:

  • 使用条件定义全局属性值以使用传递给脚本的值(如果存在)。
  • 将项目组从MyGroup目标更改为全局范围。
  • 根据Value属性值
  • 定义要发出的itemgroup的每个元素的条件

e.g。你的脚本将是这样的:

<?xml version="1.0" encoding="utf-8"?>
<Project  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Value Condition="$(Value) == ''">5</Value>
  </PropertyGroup>
  <ItemGroup>
    <File Include="5" Condition="$(Value) >5">
      <Value>5a</Value>
    </File>
    <File Include="4" Condition="$(Value) >4">
      <Value>4a</Value>
    </File>
    <File Include="3" Condition="$(Value) >3">
      <Value>3a</Value>
    </File>
    <File Include="2" Condition="$(Value) >2">
      <Value>2a</Value>
    </File>
    <File Include="1" Condition="$(Value) >1">
      <Value>1a</Value>
    </File>
  </ItemGroup>
  <Target Name="Recursive" Condition="$(Value) >0">
    <PropertyGroup>
      <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
    </PropertyGroup>
    <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
  </Target>
  <Target Name="Build">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
  </Target>
</Project>

正如Alexey Shcherbak指出的那样,我们无法从ItemGroup任务中通过MSBuild。我通过引入新属性Done来解决我的问题,以保留已处理的项目列表。

<Target Name="MyGroup">
    <ItemGroup>
        <File Include="5">
            <Value>5a</Value>
        </File>
        <File Include="4">
            <Value>4a</Value>
        </File>
        <File Include="3">
            <Value>3a</Value>
        </File>
        <File Include="2">
            <Value>2a</Value>
        </File>
        <File Include="1">
            <Value>1a</Value>
        </File>
    </ItemGroup>
</Target>

<Target Name="Recursive" DependsOnTargets="MyGroup" Condition="$(Value) > 0" >
    <ItemGroup>
        <File Remove="$(Value)" />
        <File Remove="$(Done)" />
    </ItemGroup>

    <Message Text="File: @(File->'%(Value)') Value=$(Value)" Importance="High" />

    <PropertyGroup>
        <Done>$(Done);$(Value)</Done>
        <Value>$([MSBuild]::Subtract($(Value), 1))</Value>
    </PropertyGroup>

    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value);Done=$(Done)" />
</Target>

<Target Name="Build" DependsOnTargets="MyGroup">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>