如何在MSBuild中批处理?

3

我不知道如何像传递方法一样将值传递到MSBuild任务中。请看下面的项目文件...

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Main">
<PropertyGroup>
    <Var1>Foo</Var1>
    <Var2>Bar</Var2>
</PropertyGroup>

<Target Name="Main">
    <Message Text="$(Var1)" Importance="high" />
    <Message Text="$(Var2)" Importance="high" />
</Target>   
</Project>

我希望将消息任务重构为目标,然后传递Var1和Var2以获得相同的输出。这只是一个非常简化的例子,但概念是相同的。


喜欢这样的链接吗? - KMoraz
@KMoraz 不,那篇帖子是指延迟名称解析。我想做的是将多个变量传递给目标,然后让目标像方法一样处理每个变量。 - oliwa
2个回答

4
我认为你想要做的是这样的:

我认为您想做的事情类似于这样:

<ItemGroup>
  <Messages Include="Message1">
    <Text>Hello from Message1</Text>
  </Messages>
  <Messages Include="Message2">
    <Text>Hello from Message2</Text>
  </Messages>
</ItemGroup>

<Target Name="TestMessage">
  <Message Text="%(Messages.Text)"/>
</Target>

这将产生以下输出:
TestMessage:
  Hello from Message1
  Hello from Message2

是的!这正是我想要的,但在这样做时,我发现了一个相关问题。如果在“Message”任务之后还有另一个任务,那么在继续执行下一个任务之前,将对“Messages ItemGroup”中的所有项目执行“Message”任务。如何让Task A、Task B和Task C按顺序运行每个ItemGroup中的项目? - oliwa
我不知道这是否可能。最简单的方法是创建目标A、目标B和目标C,并让每个目标执行消息任务,然后执行您想要运行的任务。否则,您可以编写自己的自定义MSBuild任务,该任务接受消息和目标/任务名称,然后像这样调用它:<CustomTask Param1="%(Messages.Text)" Param2="%(Messages.Operation)"/>。在我看来,第一种选项更容易。 - BryanJ
2
可以通过目标批处理来实现(而不是基于任务的批处理)。在Target元素中添加Outputs="%(Messages.Identity)",这样就可以达到目的,它将指示整个目标应进行批处理,每个项都会执行,无论其值如何。Sayed在这里有一个很好的描述,并提供了详细的示例:http://www.sedodream.com/PermaLink,guid,cab57d7f-9d6e-4358-8491-dc033fb3bacc.aspx - Matt Ryan

3

这是为了补充而不是替代@BryanJ的答案

有两种批处理类型。一种是任务批处理,当您使用%(ItemName.MetaData)语法时会发生。您只需将此值指定为任务参数,就好像%(ItemName.MetaData)只会扩展到一个特定值。然后,MSBuild会自动多次执行任务,避免任务明确支持迭代项目列表的需要。

另一种批处理类型是目标批处理。当您使用<Target/>InputsOutputs属性时,目标批处理就会发生。为了在任意项目集上进行批处理,以便目标针对每个项目仅执行一次,您可以指定Inputs="@(ItemName)" Outputs=%(Identity).bogus。重要的是要存在%(Identity)。批处理将查看InputsOutputs的所有可能扩展,并根据这些扩展来决定其批处理。因此,如果您想要为每个项目单独运行目标,则必须确保每个项目都有唯一的扩展。我使用Target批处理样式修改了@BryanJ的代码:

<?xml version="1.0"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="all">
  <ItemGroup>
    <Messages Include="Message1">
      <Text>Hello from Message1</Text>
      <Group>1</Group>
    </Messages>
    <Messages Include="Message2">
      <Text>Hello from Message2</Text>
      <Group>1</Group>
    </Messages>
    <Messages Include="Message3">
      <Text>Hello from Message3</Text>
      <Group>2</Group>
    </Messages>
  </ItemGroup>
  <Target Name="all" DependsOnTargets="TestMessage;TestMessageGrouping" />
  <!--
      Use the Inputs/Outputs attributes to specify Target
      batching. The metadata value I am batching over is
      Identity. Since Identity is unique per item, this means the
      Target will get run in full once for every value in
      Messages. We provide something bogus for Outputs. It is
      important that our bogus values do not coincide with real
      filenames. If MSBuild finds a file with the name of a value
      in Outputs and another file, with an older timestamp,
      matching the corresponding value in Inputs, it will skip
      running this Target. (This is useful in many situations, but
      not when we want to just print out messages!)
  -->
  <Target Name="TestMessage" Inputs="@(Messages)" Outputs="%(Identity).bogus">
    <Message Text="I will print the Text metadata property of %(Messages.Identity)" />
    <Message Text="%(Messages.Text)" />
  </Target>
  <!--
      If you want to combine Task and Target batching, you can specify
      a different metadata value than Identity to group the items
      by. I use the Group metadata I specified in the ItemGroup.
  -->
  <Target Name="TestMessageGrouping" Inputs="@(Messages)" Outputs="%(Group).bogus">
    <Message Text="I will print the Text metadata property of all messages from Group %(Messages.Group)" />
    <!--
        Now, within the Target batch, we use Task batching to print
        all of the messages in our %(Messages.Group) at once.
    -->
    <Message Text="%(Messages.Text)" />
  </Target>
</Project>

输出结果为:

TestMessage:
  I will print the Text metadata property of Message1
  Hello from Message1
TestMessage:
  I will print the Text metadata property of Message2
  Hello from Message2
TestMessage:
  I will print the Text metadata property of Message3
  Hello from Message3
TestMessageGrouping:
  I will print the Text metadata property of all messages from Group 1
  Hello from Message1
  Hello from Message2
TestMessageGrouping:
  I will print the Text metadata property of all messages from Group 2
  Hello from Message3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接