Tfs Msbuild CoreCompile依赖于目标

Tfs Msbuild CoreCompile依赖于目标,tfs,msbuild,Tfs,Msbuild,这就是我们所拥有的:ccnet+tfs+msbuild 问题是我们的构建过程太慢,因为有很多项目 我做了一些调查,这就是我想做的 在编译每个项目后,它都会从输出文件夹复制到共享文件夹,并且在任何情况下都会执行此操作,即使该项目没有编译。因此,我检查了msbuild的详细日志,我发现:跳过目标“CoreCompile”,因为所有输出文件相对于输入文件都是最新的 此验证操作在Microsoft.TeamFoundation.Build.targets中声明。问题是我如何截获这些信息,创建自己的目标,

这就是我们所拥有的:ccnet+tfs+msbuild

问题是我们的构建过程太慢,因为有很多项目

我做了一些调查,这就是我想做的

在编译每个项目后,它都会从输出文件夹复制到共享文件夹,并且在任何情况下都会执行此操作,即使该项目没有编译。因此,我检查了msbuild的详细日志,我发现:跳过目标“CoreCompile”,因为所有输出文件相对于输入文件都是最新的

此验证操作在Microsoft.TeamFoundation.Build.targets中声明。问题是我如何截获这些信息,创建自己的目标,添加一些条件,并执行某种触发,如果出现“跳过目标”或“编译”消息,则不要运行我的复制目标并跳过它,如果项目已经编译,那么这个复制目标应该运行。

我刚刚在博客上写了这个,但我在下面为您粘贴了内容

我今天在StackOverflow上,注意到一个与此类似的问题“”下面是我的答案

对于一般情况来说,这是一个需要解决的棘手问题,但在您的情况下,这是非常容易的,因为CoreCompile具有对该场景的特殊内置支持。在我详细介绍如何使用CoreCompile实现这一点之前,让我解释一下它的工作原理

一般情况的解释 由于增量生成,已跳过MSBuild中的目标。增量构建完全由目标本身的输入和输出属性驱动。输入是目标将“使用”的文件列表,输出是目标“生成”的文件列表。我使用引号是因为它是一个松散的概念,而不是一个具体的概念。为了简化它,您可以将输入/输出作为文件列表处理。当目标即将执行时,MSBuild将获取输入并将其时间戳与输出进行比较。如果所有输出都较新,则输入将跳过目标。(仅供参考,如果你想知道只有一些输出过时时会发生什么,请阅读我的博客)

在任何情况下,如果你想跳过一个目标,你必须正确地设计你的输入/输出。在您的例子中,每当跳过CoreCompile时,您都希望跳过您的目标,因此在表面上,您似乎可以简单地复制CoreCompile的输入/输出,但这不起作用。它不起作用,因为当执行CoreCompile时,文件可能已经过时,但目标本身会使它们更新。然后,当您的目标被执行时,因为它们都是最新的,所以它将被跳过。您必须复制输入/输出,并将一个附加文件附加到目标创建的输入/输出。这将确保您的目标不会在第一次通过时被跳过

CoreCompile的具体解决方案 如果查看项目文件,您将在底部看到导入了文件Microsoft.Common.targets,然后该文件将导入特定于语言的.targets文件。例如,它将导入Microsoft.CSharp.targets或Microsoft.VisualBasic.targets(如果您使用的是C#或VB)。在这些.targets文件中,您将发现定义了CoreCompile。在CoreCompile的定义中,您将在末尾找到以下内容

<CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''"/>
在本例中,我定义属性TargetsTriggeredByCompilation,并将MyCustomTarget附加到该属性。包含$(targetStriguredBycomilation)是非常重要的在那里,如果不这样做,则不会追加,而是覆盖。所以如果其他人使用这种技术,你会消灭他们的目标

下面的图片显示了我构建一次、执行CoreCompile和MyCustomTarget的位置。然后跳过第二个构建CoreComile,但从未调用MyCustomTarget


我在日志中遇到以下错误:由于条件错误,跳过了任务“CallTarget”;(“$(TargetsTriggeredByCompilation)”的计算结果为(“”!“”)。我甚至尝试注释我的扩展属性,但我在日志中得到了相同的消息。有什么想法吗?这是我在我的项目中添加的:$(TargetsTriggeredByCompilation);MyCustomTarget我甚至在core compile中的公共目标中检查了该块的存在性,我做了一些调查:只有在Microsoft.Csharp.targets中定义了那些属性targetStriguredBycomilation,它才有效,但这是不可接受的。我不能主动修改Microsoft.Csharp.Targets。如果我也将这些属性添加到Microsoft.Common.Targets中,它就会工作。但是,如果我需要将此属性添加到自定义.proj文件中,如何使其工作?当您说自定义.proj文件时,是指项目本身的.csproj/.vbproj还是其他文件?如果您指的是通过MSBuild任务驱动这些文件的另一个文件,那么这种方法将不起作用。你需要更详细地修改你的问题。
<PropertyGroup>
  <TargetsTriggeredByCompilation>
    $(TargetsTriggeredByCompilation);
    MyCustomTarget
  </TargetsTriggeredByCompilation>
</PropertyGroup>

<Target Name="MyCustomTarget">
  <Message Text="MyCustomTarget called" Importance ="high"/>
</Target>