【问题标题】:Msbuild CoreCompile depends on targetsMsbuild CoreCompile 依赖于目标
【发布时间】:2012-05-11 17:02:51
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: tfs msbuild


    【解决方案1】:

    我刚刚在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。

    【讨论】:

    • 我在日志中有以下错误:Task "CallTarget" skipped, due to false condition; ('$(TargetsTriggeredByCompilation)' != '') 被评估为 ('' != '')。我什至尝试评论我的扩展属性,但我在日志中得到了相同的消息。有什么想法吗?
    • 这是我添加到项目中的内容: $(TargetsTriggeredByCompilation); MyCustomTarget 我什至检查了这个块在公共目标中是否存在在核心编译 它就在那里
    • 我进行了一些调查:只有当我在 Microsoft.Csharp.Targets 中定义那些属性 TargetsTriggeredByCompilation 时它才有效,但这是不可接受的。我无法向前修改 Microsoft.Csharp.Targets。
    • 如果我也将这些属性添加到 Microsoft.Common.Targets 中,它就会起作用。但是,如果我需要将此属性添加到我的自定义 .proj 文件中,如何使其工作?
    • 当您说自定义 .proj 文件时,您是指项目本身的 .csproj/.vbproj 还是其他什么?如果您的意思是另一个文件通过 MSBuild 任务驱动这些文件,那么这种方法将不起作用。您需要修改您的问题并提供更多详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多