有条件目标的BeforeTargets行为 [英] BeforeTargets behaviour with conditional targets
问题描述
帮我理解为什么在这样调用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 theCondition
attribute is present and evaluates tofalse
, 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
Targets specified with
AfterTargets
andBeforeTargets
attributes are unconditionally pushed onto stack of targets to be built viaafterTargets
andbeforeTargets
lists returned byGetTargetsWhichRunAfter()
andGetTargetsWhichRunBefore()
methods.
Targets specified with DependsOnTargets
attribute are pushed when non-null onto stack of targets via dependencies
list returned by TargetEntry::GetDependencies()
method.
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 theCondition
attribute is present and evaluates tofalse
, the target and itsDependsOnTargets
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.)
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屋!