具有多个输出的 MsBuild 目标

MsBuild Target with multiple Outputs

当你有多个输出时,有没有办法克服 Targets 的一对一映射?似乎这应该是可能的,但我不知道如何,因为我是 MsBuild 的新手,我可能遗漏了一些东西。

以下一段 msbuild 脚本来自微软的文档。当我有多个备份文件夹时应该更改什么?所以列表@(BackupFolders) 并且我想保留构建的增量行为?

<Target Name="Backup" Inputs="@(Compile)"   
    Outputs="@(Compile->'$(BackupFolder)%(Identity).bak')">  
    <Copy SourceFiles="@(Compile)" DestinationFiles=  
        "@(Compile->'$(BackupFolder)%(Identity).bak')" />  
</Target>  

首先,Target 节点上的 Inputs 和 Outputs 属性是针对 incremental builds 的。它们需要具有相同数量的条目,以便 msbuild 了解在构建时应过滤哪些项目。 MSBuild 检查输出是否已经存在并且是最新的,如果是,则从输入列表中筛选出匹配的输入项。如果你不关心增量构建,你可以完全跳过这个机制。如果输入和输出不匹配(或不存在),msbuild 将始终执行包含所有项目的目标,因为它无法决定哪些项目导致哪个输出。

其次,这些属性期望的是项目列表。这不一定是一个列表,它可以是任意列表。所以像这样扩展你的例子是完全公平的:

<Target Name="Backup" Inputs="@(Compile);@(Compile2)"   
  Outputs="@(Compile->'$(BackupFolder)%(Identity).bak');@(Compile2->'$(BackupFolder)%(Identity).bak')">  
  <Copy SourceFiles="@(Compile)" DestinationFiles=  
     "@(Compile->'$(BackupFolder)%(Identity).bak')" />  
  <Copy SourceFiles="@(Compile2)" DestinationFiles=  
     "@(Compile2->'$(BackupFolder)%(Identity).bak')" />  
</Target>

但是您想将相同的项目复制到不同的备份文件夹,对吗?所以应该这样做:

<Target Name="Backup">  
  <Copy SourceFiles="@(Compile)" DestinationFiles=  
      "@(Compile->'$(BackupFolder)%(Identity).bak')" />  
  <Copy SourceFiles="@(Compile)" DestinationFiles=  
      "@(Compile->'$(BackupFolder2)%(Identity).bak')" />  
</Target>

如果有两个备份文件夹,一个项目实际上可能在一个文件夹中已经是最新的,但在另一个文件夹中丢失了。您可以将一个定义为 "main" 备份文件夹,并告诉 MSBuild 使用它作为增量构建的参考。

编辑:对于两个位置的增量构建,最简单的解决方案可能是合并两个目标,两个目标都是增量构建:

<Target Name="Backup" DependsOnTargets="_Backup1;_Backup2">
</Target>

<Target Name="_Backup1" Inputs="@(Compile)"   
  Outputs="@(Compile->'$(BackupFolder)%(Identity).bak')">  
  <Copy SourceFiles="@(Compile)" DestinationFiles=  
     "@(Compile->'$(BackupFolder)%(Identity).bak')" />    
</Target>

<Target Name="_Backup2" Inputs="@(Compile)"   
  Outputs="@(Compile->'$(BackupFolder2)%(Identity).bak')">  
  <Copy SourceFiles="@(Compile)" DestinationFiles=  
     "@(Compile->'$(BackupFolder2)%(Identity).bak')" />  
</Target>