DependsOnTargets
和AfterTargets
有什么区别呢?我分辨不清这两个参数。
DependsOnTargets
和AfterTargets
有什么区别呢?我分辨不清这两个参数。
该属性定义了在执行目标前必须被先执行的目标。
<Target Name="DependsOn" DependsOnTargets="DependencyTarget1;DependencyTarget2">
<Message Text="Target : DependsOn"/>
</Target>
<Target Name="DependencyTarget2">
<Message Text="Target : DependencyTarget2"/>
</Target>
<Target Name="DependencyTarget1">
<Message Text="Target : DependencyTarget1"/>
</Target>
Output
> Target : DependencyTarget1
> Target : DependencyTarget2
> Target : DependsOn
表示目标应该在指定的目标之前或之后运行。
<Target Name="BeforeAndAfter">
<Message Text="Target : BeforeAndAfter"/>
</Target>
<!-- BeforeTarget1 will run BEFORE target "BeforeAndAfter" -->
<Target Name="BeforeTarget" BeforeTargets="BeforeAndAfter">
<Message Text="BeforeTarget run before : BeforeAndAfter"/>
</Target>
<!-- BeforeTarget1 will run AFTER target "BeforeAndAfter" -->
<Target Name="AfterTarget" AfterTargets="BeforeAndAfter">
<Message Text="AfterTarget run after : BeforeAndAfter"/>
</Target>
Output
> BeforeTarget run before : BeforeAndAfter
> Target : BeforeAndAfter
> AfterTarget run after : BeforeAndAfter
如果您有多个目标应该在同一个指定目标之前或之后运行,它们将按照声明顺序执行:
<Target Name="BeforeAndAfter">
<Message Text="Target : BeforeAndAfter"/>
</Target>
<!--
BOTH BeforeTarget1 and BeforeTarget2 should run before target "BeforeAndAfter"
-->
<Target Name="BeforeTarget1" BeforeTargets="BeforeAndAfter">
<Message Text="BeforeTarget1 run before : BeforeAndAfter"/>
</Target>
<Target Name="BeforeTarget2" BeforeTargets="BeforeAndAfter">
<Message Text="BeforeTarget2 run before : BeforeAndAfter"/>
</Target>
BeforeTargets
和AfterTargets
可以用于扩展现有的构建流程。
例如,通过使用这些属性,您可以在CoreCompile(定义在Microsoft.CSharp.targets中)之前轻松执行目标。如果没有这个属性,您将不得不重写属性CoreCompileDependsOn
。
如果没有AfterTargets
,您就没有办法在另一个目标之后轻松地执行一个目标,除非定义了扩展点(在目标末尾使用CallTarget
和一个可覆盖的属性)。
当在同一个目标上使用DependsOnTargets
、BeforeTargets
和AfterTargets
时,执行顺序为:
DependsOnTargets
BeforeTargets
AfterTargets
<Target Name="MainTarget" DependsOnTargets="DefaultDependsOn">
<Message Text="Target : MainTarget"/>
</Target>
<Target Name="DefaultDependsOn">
<Message Text="Target : DefaultDependsOn"/>
</Target>
<Target Name="DefaultBeforeTarget" BeforeTargets="MainTarget">
<Message Text="Target : DefaultBeforeTarget"/>
</Target>
<Target Name="DefaultAfterTarget" AfterTargets="MainTarget">
<Message Text="Target : DefaultAfterTarget"/>
</Target>
Output
> Target : DefaultDependsOn
> Target : DefaultBeforeTarget
> Target : MainTarget
> Target : DefaultAfterTarget
<Target Name="x" DependsOnTargets="y" />
的意思是:x
,必须先运行 y
。
<Target Name="a" AfterTargets="b" />
的意思是:b
,则在其后运行 a
。尽管之前提供的其他答案是正确的,但我认为它们没有提到我认为AfterTargets
相对于DependsOnTargets
的主要优点。
DependsOnTargets
从MSBuild的开始就存在了。 DependsOnTargets
的问题在于,它要求目标作者显式地允许可扩展性。这是通过定义一个属性作为DependsOnTargets
值来完成的,如下所示:
<PropertyGroup>
<SomeTargetDependsOnTargets>
Dependency1;Dependency2
</SomeTargetDependsOnTargets>
</PropertyGroup>
<Target Name="SomeTarget" DependsOnTargets="$(SomeTargetDependsOnTargets)">
...
</Target>
您可以通过修改SomeTargetDependsOnTargets
属性来添加依赖项,方法如下:
然后,您可以通过修改SomeTargetDependsOnTargets
属性来添加依赖项,方法如下:
<SomeTargetDependsOnTargets>
$(SomeTargetDependsOnTargets);Dependency3
</SomeTargetDependsOnTargets>
这个设计的问题在于,如果作者只是将Dependency1;Dependency2
内联而不是提取为属性,就没有办法进行外部修改以进行定制。
另一方面,AfterTargets
不需要原始目标作者显式地将DependsOnTargets
值提取到属性中以实现可扩展性。
msbuild /t:A
的方式。当使用 DependsOnTargets
属性指定依赖关系时,在这种方式下调用 msbuild 不会构建目标B。但是,当使用 AfterTargets
属性指定依赖关系时,在这种方式下调用 msbuild 将构建目标B。 - aprelev还有一个差异,正如另一个答案中提到的那样,
BeforeTargets
和AfterTargets
会在无论条件如何都运行,而DependsOnTargets
(以及目标本身)则在条件评估为false时被跳过。
In below code second target is executed even though first target is not executed:
<Target Name="FirstTarget" AfterTargets="PostBuildEvent" Condition="'False'">
<Message Text="This target is never executed" />
</Target>
<Target Name="SecondTarget" AfterTargets="FirstTarget">
<Message Text="SecondTarget is executed" />
</Target>
In below code second target is not executed:
<Target Name="FirstTarget" AfterTargets="PostBuildEvent" Condition="'False'">
<Message Text="This target is never executed" />
</Target>
<Target Name="SecondTarget" DependsOnTargets="FirstTarget">
<Message Text="SecondTarget is executed" />
</Target>
AfterTargets
和DependsOnTargets
之间还有一个区别。BeforeTargets
或AfterTargets
中,它的行为类似于“任意”,而不是“所有”。A1 -> A2 -> A3
。<Target Name="A1" BeforeTargets="Compile">
<Message Text="A1" />
</Target>
<Target Name="A3" AfterTargets="A1;A2">
<Message Text="A3" />
</Target>
<Target Name="A2" AfterTargets="A1">
<Message Text="A2" />
</Target>
A1
A3
A2
如前所述这里,以上只是意味着:
<Target Name="A1" BeforeTargets="Compile">
Compile
想要运行,需要先运行A1
。<Target Name="A3" AfterTargets="A1;A2">
A1
运行,那么在它之后运行A3
。A2
运行,那么在它之后运行A3
。<Target Name="A2" AfterTargets="A1">
A1
运行,那么运行 A2
。A1
将触发运行 A3
。注意,声明顺序很重要!A3
依赖于 A1
和 A2
,但上面的内容并不意味着这一点。<Target Name="A3" AfterTargets="A1;A2">
如果任何AfterTargets
已经执行,那么我也要执行。
如果A1
或者A2
执行了,那么就执行A3
为了安全地实现目标依赖链A1 -> A2 -> A3
,我会这样使用DependsOnTargets
:
<Target Name="B1" BeforeTargets="Compile">
<Message Text="B1" />
</Target>
<Target Name="B3" DependsOnTargets="B1;B2" BeforeTargets="Compile">
<Message Text="B3" />
</Target>
<Target Name="B2" DependsOnTargets="B1" BeforeTargets="Compile">
<Message Text="B2" />
</Target>
DependsOnTargets
中声明目标的所有依赖关系可以创建我们想要的图/链。DependsOnTargets
不会这样做(与AfterTargets
不同)。 (上面的代码在所有目标中使用BeforeTargets="Compile"
来实现此目的)DependsOnTarget
假设你有两个任务:
你可以通过执行任务2开始你的构建,然后在任务声明中定义其依赖关系。因此,如果你定义任务2依赖于任务1,则构建过程将开始并执行任务1,然后是2。
AfterTargets
更简单:它只意味着在其他目标之后执行的任务。所以,以上面的例子为例,在任务1之后-构建项目执行任务2。
我希望这能帮到你。
主要有两个区别:
第一:在 dependsOnTargets 属性中指定的目标会在 AfterTargets 中指定的目标之前执行。
第二:如果 AfterTargets 属性中指定的一个目标已经被执行,那么这个目标也会在之后被执行(我是指在指定 AfterTargets 属性的目标之后),而对于 DependsOnTargets 中的目标则不是这样。
DependsOnTargets
影响当前任务的行为,而不影响引用任务的行为。
AfterTargets
影响引用任务的行为,而不影响当前任务的行为。<Target Name="A" DependsOnTargets="B" />
<Target Name="B" />
<Target Name="C" AfterTargets="B" />
AfterTargets -> 目标 -> BeforeTargets
。 - Jez