有条件目标的BeforeTargets行为 [英] BeforeTargets behaviour with conditional targets

查看:34
本文介绍了有条件目标的BeforeTargets行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

帮我理解为什么在这样调用MSBuild时为什么运行目标A(和D)而没有运行目标B :

Help me understand, why target A (and D) is run while target B is not when MSBuild is invoked like this:

msbuild /target:C

在这个简单的项目上(省略XML标头):

on this simple project (XML header omitted):

<Target Name="A" BeforeTargets="C">
  <Message Text="Inside target A" />
</Target>

<Target Name="B">
  <Message Text="Inside target B" />
</Target>

<Target Name="C" DependsOnTargets="B" Condition="'False'">
  <Message Text="Inside target C" />
</Target>

<Target Name="D" AfterTargets="C">
  <Message Text="Inside target D" />
</Target>

根据目标构建顺序:

  • 评估目标的 Condition 属性.如果存在 Condition 属性,并且评估结果为 false ,则不会执行目标,并且不会对构建产生进一步影响.
  • 在执行目标之前,将运行其 DependsOnTargets 目标.
  • 在执行目标之前,将运行在 BeforeTargets 属性中列出该目标的所有目标.
  • ...
  • 执行或跳过目标后,将运行在 AfterTargets 属性中列出该目标的所有目标.
  • The Condition attribute of the target is evaluated. If the Condition attribute is present and evaluates to false, the target isn't executed and has no further effect on the build.
  • Before a target is executed, its DependsOnTargets targets are run.
  • Before a target is executed, any target that lists it in a BeforeTargets attribute is run.
  • ...
  • After a target is executed or skipped, any target that lists it in an AfterTargets attribute is run.

这就是为什么只能逻辑得出结论,因为谓词在执行目标之前对于 DependsOnTargets BeforeTargets 属性都是相同的,应该同时运行 A B ,或者都不运行.

which is why it is only logical to conclude that since predicate Before a target is executed is the same for both DependsOnTargets and BeforeTargets attributes, either both A and B should be run, or neither.

据我所知, A B 均不应运行,因为要求MSBuild运行目标 C ,这是有条件的和 Condition 评估为 false .

As far as my understanding goes, neither A nor B should be run since MSBuild is asked to run target C, which is conditional and Condition evaluates to false.

PS MSBuild 15.5.180.51428

P.S. MSBuild 15.5.180.51428

推荐答案

这似乎是MSBuild 4.0 BeforeTargets AfterTargets 属性与旧版 DependsOnTargets 属性.

This seems to be a case of peculiar difference between MSBuild 4.0 BeforeTargets, AfterTargets attributes versus older DependsOnTargets attribute.

BeforeTargets AfterTargets 的运行与 Condition 无关,而 DependsOnTargets (以及目标本身)在以下情况下被跳过条件的计算结果为 false .

BeforeTargets and AfterTargets are run regardless of the Condition whereas DependsOnTargets (and target itself) are skipped when Condition evaluates to false.

TargetBuilder :: ProcessTargetStack()的调查

Investigation of TargetBuilder::ProcessTargetStack() source code showed that

    使用 AfterTargets BeforeTargets 属性指定的
  1. 目标是

  1. Targets specified with AfterTargets and BeforeTargets attributes are unconditionally pushed onto stack of targets to be built via afterTargets and beforeTargets lists returned by GetTargetsWhichRunAfter() and GetTargetsWhichRunBefore() methods.

目标是

Targets specified with DependsOnTargets attribute are pushed when non-null onto stack of targets via dependencies list returned by TargetEntry::GetDependencies() method.

Condition 属性,该方法返回

Condition attribute is actually evaluated only inside TargetEntry::GetDependencies() method which returns empty list when condition is present and resolves to false, and list of dependencies otherwise.

目标构建顺序中的描述似乎与计划背后的逻辑相矛盾;正确的顺序似乎是:

Description in target build order seems to contradict the logic behind scheduling; the correct order seems to be:

  • 在执行目标之前,将运行在 BeforeTargets 属性中列出该目标的所有目标.
  • 评估目标的 Condition 属性.如果存在 Condition 属性并评估为 false ,则不会执行目标及其 DependsOnTargets 目标.
  • ...
  • 执行或跳过目标后,将运行在 AfterTargets 属性中列出该目标的所有目标.
  • Before a target is executed, any target that lists it in a BeforeTargets attribute is run.
  • The Condition attribute of the target is evaluated. If the Condition attribute is present and evaluates to false, the target and its DependsOnTargets targets are not executed.
  • ...
  • After a target is executed or skipped, any target that lists it in an AfterTargets attribute is run.

(母语人士可能会更好地证明这一点.)

(Native speakers can probably document this better.)

PS 如果我错了,请纠正我,但我来自C背景,并且

P.S. Correct me if I'm wrong, but I come from C background and this check

if (null != dependencies) 

对我来说似乎多余,因为 dependencies 变量被初始化为

seems redundant to me because dependencies variable is initialised as

dependencies = currentTargetEntry.GetDependencies(...)

GetDependencies 返回 List< ..> 的初始化实例

and GetDependencies returns initialised instance of List<..> regardless of condition:

List<...> GetDependencies(...)
{
    bool condition = ConditionEvaluator.EvaluateCondition(...);
    if (!condition)
    {
        ...
        return new List<...>();
    }
    ...
    List<...> dependencyTargets = new List<...>();
    ...
    return dependencyTargets;
}

这篇关于有条件目标的BeforeTargets行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆