Msbuild CoreCompile依赖于目标

时间:2012-05-11 17:02:52

标签: tfs msbuild

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

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

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

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

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

1 个答案:

答案 0 :(得分:5)

我刚刚在http://sedodream.com/2012/05/14/MSBuildHowToExecuteATargetAfterCoreCompile.aspx发布了此博文,但我在下面粘贴了这些内容。

我今天在StackOverflow上发现了一个问题“How to I create a target which is executed when CoreCompile is, and that is skipped when CoreCompile is skipped?”下面是我的答案。

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

一般情况说明

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

在任何情况下,如果您想要跳过目标,您必须正确制作输入/输出。在你的情况下,你想跳过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都不会被调用。

enter image description here