如果我的MSBuild脚本使用批处理在目标上“循环”,那么它的依赖关系也是如此?

时间:2009-02-16 12:50:51

标签: msbuild

有关某些背景信息,请参阅此MSDN帖子:Using metadata to call a target multiple times with different parameters

提出的解决方案是在Task的Output属性中使用元数据来强制批处理任务。

碰巧我们的构建步骤被划分为几个目标。我的要求是依赖关系在一种内循环中顺序运行。

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

<?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>

输出如下:

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

Build started 2/16/2009 20:41:14.  
Project "D:\Source\test\test.proj" on node 0 (BuildInstallers target(s)).  
  step 1 MyInstaller1.msi  
  step 1 MyInstaller2.msi  
Step2:  
  step 2 MyInstaller1.msi  
  step 2 MyInstaller2.msi  
Step3:  
  step 3 MyInstaller1.msi  
  step 3 MyInstaller2.msi  
BuildInstallers:  
  MyInstaller1.msi  
BuildInstallers:  
  MyInstaller2.msi  
Done Building Project "D:\Source\test\test.proj" (BuildInstallers target(s)).  


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

Time Elapsed 00:00:00.43 

任何想法如何让输出如此:

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

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

2 个答案:

答案 0 :(得分:2)

我确定在这里看到了问题

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

将在InstallerFileName输出上反复迭代。我认为您可以调用自定义目标,并且该目标会执行每个步骤。使用MSBuild Task从主脚本调用此目标,如下所示:

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

在BuildInstallers目标中,您将使用

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

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

答案 1 :(得分:0)

当您定义目标和依赖项时,您将定义依赖关系树。只要订单不违反任何依赖关系,MSBuild就可以按照它认为合适的任何顺序执行目标,包括并行(使用/m时)。

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

如果您希望输出的顺序是出于性能原因无法向MSBuild解释的,我猜您可以使用上面描述的<MSBuild> hack。