如何阻止我的项目被错误地视为"最新"?

时间:2014-07-23 14:56:53

标签: msbuild msbuild-task

我修改了一个.csproj项目,将任务附加到BuildDependsOn。这将执行文件复制。如果文件复制失败,则构建失败。 (见下面的XML)。

但是,如果我在构建尝试失败后再次“构建”(在Visual Studio中),Visual Studio会报告项目已成功构建。它认为该项目为up to date

========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========

如何确保此CopyFiles目标在每个构建上运行,以防止在构建中的关键阶段失败时VS报告成功构建的问题?

<ItemGroup>
  <MySourceFiles Include="$(TargetDir)*.dll;$(TargetDir)*.pdb"/>
</ItemGroup>


<Target Name="CopyFiles">
  <Copy SourceFiles="@(MySourceFiles)" DestinationFolder="$(DestFolder)\subfolder" />
  <Copy SourceFiles="$(ProjectDir)AnotherFile.txt" DestinationFolder="$(DestFolder)" />
   <OnError ExecuteTargets="CopyFiles_Failed" />
</Target>
<Target Name="CopyFiles_Failed">
  <Error text="File copies failed">
  </Error>
</Target>

<PropertyGroup>
  <BuildDependsOn>
    $(BuildDependsOn);
    CopyFiles
  </BuildDependsOn>
</PropertyGroup>

2 个答案:

答案 0 :(得分:1)

正如@maxkenir所提到的那样,Inputs and Output parameter in a target define the set of files the build should check to decide whether it is up to date

  

输入

     

形成此目标输入的文件。多个文件由分号分隔。将文件的时间戳与输出中文件的时间戳进行比较,以确定目标是否是最新的。有关更多信息,请参阅增量构建,如何:增量构建和MSBuild转换。

     

输出

     

形成输出到此目标的文件。多个文件由分号分隔。将文件的时间戳与输入中文件的时间戳进行比较,以确定目标是否是最新的。有关更多信息,请参阅增量构建,如何:增量构建和MSBuild转换。

article on Incremental Builds进一步解释了使用它们的过程。

对于简单的复制文件操作,基本上它看起来像是:

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

有关这些MsBuild transforms can be found again on MSDN的更多信息,在您的情况下可能非常接近:

<Target Name="CopyOutputs"
    Inputs="@(BuiltAssemblies)"
    Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')">

    <Copy
        SourceFiles="@(BuiltAssemblies)"
        DestinationFolder="$(OutputPath)"/>

</Target>

但输入和输出也会accept an Item Group,您也可以进行多次转换。

答案 1 :(得分:1)

对于记录,这是我的特定解决方案XML(使用@jessehouwing的答案):

首先:创建一个包含我要复制的所有文件的MySourceFiles项目组,即使我需要将文件复制到不同的文件夹中。 其次:使用保存其目标文件夹的元数据值标记要复制的每个文件项:DestFolder

然后我可以使用变换生成输出路径列表:

@(MySourceFiles->'%(DestFolder)%(Filename)%(Extension)')

要指定目标的输入和输出,我可以使用MySourceFiles和变换。

<PropertyGroup>
  <DEST>c:\where\to\copy\files\</DEST>
</PropertyGroup>

<ItemGroup>
  <!-- dlls/pdbs go in DEST\bin -->
  <MySourceFiles Include="$(TargetDir)*.pdb;$(TargetDir)*.dll">
    <DestFolder>$(DEST)bin\</DestFolder>
  </MySourceFiles>
  <!-- anotherfile.txt goes in DEST -->
  <MySourceFiles Include="$(ProjectDir)anotherfile.txt">
    <DestFolder>$(DEST)</DestFolder>
  </MySourceFiles>
</ItemGroup>

<Target 
  Name="CopyFiles" 
  Inputs="@(MySourceFiles)" 
  Outputs="@(MySourceFiles->%(DestFolder)%(Filename)%(Extension))">
    <Copy SourceFiles="@(MySourceFiles)" DestinationFiles="@(MySourceFiles->'%(DestFolder)%(Filename)%(Extension)')" />
  </Target>

<!-- inject target into build process -->
<PropertyGroup>
  <BuildDependsOn>
    $(BuildDependsOn);
    CopyFilesToSDK
  </BuildDependsOn>
</PropertyGroup>