如果我的MSBuild脚本使用批处理来;“循环”;在一个目标上,它的依赖项是否也进行批处理?

如果我的MSBuild脚本使用批处理来;“循环”;在一个目标上,它的依赖项是否也进行批处理?,msbuild,Msbuild,有关一些背景信息,请参阅此MSDN帖子: 提出的解决方案是在任务的输出属性中使用元数据强制对任务进行批处理 我们的构建步骤恰好是跨几个目标进行划分的。我的要求是依赖项在某种内部循环中顺序运行 我用以下脚本尝试了这个概念: <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="BuildSolutions" xmlns="http://schemas.microsoft.com/devel

有关一些背景信息,请参阅此MSDN帖子:

提出的解决方案是在任务的输出属性中使用元数据强制对任务进行批处理

我们的构建步骤恰好是跨几个目标进行划分的。我的要求是依赖项在某种内部循环中顺序运行

我用以下脚本尝试了这个概念:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildSolutions"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         ToolsVersion="3.5">
    <ItemGroup>
        <BuildFile Include="myscript.txt">
          <InstallerFileName>MyInstaller1.msi</InstallerFileName>
          <CustomTwiddleBit>true</CustomTwiddleBit>
          <OtherCustomTwiddleBit>false</OtherCustomTwiddleBit>
        </BuildFile>
        <BuildFile Include="myscript.txt">
          <InstallerFileName>MyInstaller2.msi</InstallerFileName>
          <CustomTwiddleBit>false</CustomTwiddleBit>
          <OtherCustomTwiddleBit>true</OtherCustomTwiddleBit>
        </BuildFile>
    </ItemGroup>

    <Target  
        Name="BuildInstallers" 
        Outputs="OutputDir\%(BuildFile.InstallerFileName)" 
        DependsOnTargets="Step3" 
    >
        <Exec Command="echo %(BuildFile.InstallerFileName)" />
    </Target>

    <Target Name="Step1">  
        <Exec Command="echo step 1 %(BuildFile.InstallerFileName)" /> 
    </Target> 

    <Target Name="Step2" 
            DependsOnTargets="Step1">  
        <Exec Command="echo step 2 %(BuildFile.InstallerFileName)" /> 
    </Target> 

    <Target Name="Step3" 
            DependsOnTargets="Step2">  
        <Exec Command="echo step 3 %(BuildFile.InstallerFileName)" /> 
    </Target>      
</Project>
有什么想法可以让我的输出是这样的:

step 1 MyInstaller1.msi
step 2 MyInstaller1.msi
step 3 MyInstaller1.msi

step 1 MyInstaller2.msi
step 2 MyInstaller2.msi
step 3 MyInstaller2.msi

我当然认为这里的问题是

<Exec Command="echo step 1 %(BuildFile.InstallerFileName)" />

将在InstallerFileName输出上反复迭代。我认为您可以调用一个自定义目标,该目标将完成您的每个步骤。使用MSBuild任务从主脚本调用此目标,如下所示:

<MSBuild Projects="CustomTargets.proj" 
  Targets="BuildInstallers"
  Properties="BuildFile=%(BuildFile.InstallerFileName)" />

在您的构建安装程序中,您将使用

<Target ="BuildInstallers" DependsOnTargets="Step3" >
</Target>

<Target Name="Step1">  
    <Exec Command="echo step 1 $(BuildFile)" /> 
</Target> 


etc

定义目标和依赖项时,您定义的是依赖项树。MSBuild可以按照其认为合适的任何顺序执行目标,包括并行执行(在使用
/m
时),只要该顺序不违反任何依赖项

在您的情况下,MSBuild选择首先运行
步骤1 MyInstaller1.msi
+
步骤1 MyInstaller2.msi
,如果您添加
/m
,它们可能会并行运行。如果它们不能并行运行,这可能是您的设计中的一个限制-可能共享相同的中间文件-您应该解决这个问题


如果出于无法向MSBuild解释的性能原因,您希望输出按这种顺序排列,那么我想您可以使用上面描述的
hack。

我希望避免定制构建步骤,但这似乎是目前最实用的解决方案。我故意在每个任务上放置%(BuildFile.InstallerFileName)元数据,以强制它进行迭代。由于MSBuild设计,删除每个目标只调用一次的。
<Target ="BuildInstallers" DependsOnTargets="Step3" >
</Target>

<Target Name="Step1">  
    <Exec Command="echo step 1 $(BuildFile)" /> 
</Target>