具有条件目标的BeforeTargets行为

时间:2018-01-22 12:09:50

标签: .net msbuild

帮助我理解为什么目标A(和D)运行,而目标B不时调用MSBuild如下:

msbuild /target:C

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

<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>

根据target build order

  
      
  • 评估目标的Condition属性。如果Condition属性存在且评估为false,则目标不会被执行,并且对构建没有进一步影响。
  •   
  • 在执行目标之前,会运行其DependsOnTargets目标。
  •   
  • 在执行目标之前,将运行在BeforeTargets属性中列出目标的任何目标。
  •   
  • ...
  •   
  • 执行或跳过目标后,将运行在AfterTargets属性中列出目标的任何目标。
  •   

这就是为什么只能合理地断定,因为谓词在执行目标之前对于DependsOnTargetsBeforeTargets属性都是相同的,要么都是应该运行AB,或者不运行。

据我的理解,由于要求MSBuild运行目标A,因此无法运行BC,这是有条件的,Condition计算为{ {1}}。

P.S。 MSBuild 15.5.180.51428

1 个答案:

答案 0 :(得分:0)

这似乎是MSBuild 4.0 falseBeforeTargets属性与旧版AfterTargets属性之间存在特殊差异的情况。

简短回答

无论DependsOnTargets是什么,{p> BeforeTargetsAfterTargets都会运行,而当Condition评估为DependsOnTargets时会跳过Condition(和目标本身)

答案很长

false source code的调查表明

  1. 使用TargetBuilder::ProcessTargetStack()AfterTargets属性指定的目标unconditionally pushed到要通过BeforeTargetsafterTargets列表构建的目标堆栈上{ {1}}和beforeTargets方法。

  2. 通过GetTargetsWhichRunAfter()方法返回的GetTargetsWhichRunBefore()列表,DependsOnTargets属性指定的目标为pushed when non-null到目标堆栈。

  3. dependencies属性实际上仅在TargetEntry::GetDependencies()方法中进行评估,该方法返回empty list when condition is present and resolves to false,否则返回依赖项列表。

  4. target build order中的描述似乎与调度背后的逻辑相矛盾;正确的顺序似乎是:

      
        
    • 在执行目标之前,将运行在Condition属性中列出目标的任何目标。
    •   
    • 评估目标的TargetEntry::GetDependencies()属性。如果BeforeTargets属性存在且评估为Condition,则不会执行目标及其Condition目标。
    •   
    • ...
    •   
    • 执行或跳过目标后,将运行在false属性中列出目标的任何目标。
    •   

    (母语人士可能会更好地记录这一点。)

    P.S。如果我错了,请纠正我,但我来自C背景,check

    DependsOnTargets

    对我来说似乎是多余的,因为AfterTargets变量初始化为

    if (null != dependencies) 
    

    dependencies返回dependencies = currentTargetEntry.GetDependencies(...) 的{​​{1}} regardless的初始化实例:

    GetDependencies