5

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

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

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

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

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

4

1 回答 1

6

我刚刚在http://sedodream.com/2012/05/14/MSBuildHowToExecuteATargetAfterCoreCompile.aspx上写了这篇博客,但我在下面为您粘贴了内容。

我今天在 StackOverflow 上,注意到一个问题“<a href="https://stackoverflow.com/q/10555649/105999">如何创建一个在 CoreCompile 时执行的目标,并且被跳过什么时候跳过 CoreCompile?” 下面是我的回答。

对于一般情况,这是一个很难解决的问题,但在您的情况下,这很容易,因为 CoreCompile 对这种情况有特殊的内置支持。在详细介绍如何使用 CoreCompile 完成此任务之前,让我先解释一下它的一般工作原理。

一般情况说明

在 MSBuild 中,由于增量构建,目标被跳过。增量构建完全由目标本身的输入和输出属性驱动。输入是目标将“使用”的文件列表,输出是目标“生成”的文件列表。我使用引号是因为它是一个松散的概念,而不是一个具体的概念。为了简化它,您可以将输入/输出视为文件列表。当目标即将执行时,MSBuild 将获取输入并将它们的时间戳与输出进行比较。如果所有输出都比输入新,则将跳过目标。(仅供参考,如果您想知道只有一些输出过期时会发生什么,请阅读我的博客http://sedodream.com/2010/09/23/MSBuildYouveHeardOfIncrementalBuildingButHaveYouHeardOfPartialBuilding。

在任何情况下,如果您希望跳过某个目标,您必须正确地制作您的输入/输出。在您的情况下,您希望在跳过 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属性中定义的所有目标。因此,如果您希望在执行CoreCompile 时调用您的目标,您可以扩展该属性。这是如何做到这一点的。

<PropertyGroup>
  <TargetsTriggeredByCompilation>
    $(TargetsTriggeredByCompilation);
    MyCustomTarget
  </TargetsTriggeredByCompilation>
</PropertyGroup>

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

在这种情况下,我定义属性TargetsTriggeredByCompilation并将 MyCustomTarget 附加到它。包含$(TargetsTriggeredByCompilation);非常重要。在那里,如果你不这样做,那么你将不会追加而是覆盖。因此,如果其他人使用此技术,您将消灭他们的目标。

下图显示了我构建一次并执行 CoreCompile 和 MyCustomTarget 的位置。然后第二个构建 CoreCompile 被跳过,任何 MyCustomTarget 永远不会被调用。

在此处输入图像描述

于 2012-05-14T03:03:42.470 回答