目标生成顺序
如果目标的输入取决于另一目标的输出,那么必须将目标排序。 可使用这些属性指定目标运行的顺序:
InitialTargets
。Project
属性指定将首先运行的目标,即使在命令行或DefaultTargets
属性中指定了目标。DefaultTargets
。 如果未在命令行上显示指定目标,则此Project
属性可指定要运行的目标。DependsOnTargets
。 此Target
属性指定必须运行的目标后才能运行此目标。BeforeTargets
和AfterTargets
。 这些Target
属性指定应在指定的目标运行前或后运行此目标。
通常,不应依赖于声明顺序来指定哪些任务在其他任务之前运行。
生成过程中一个目标绝不会运行两次,即使在生成中有后续目标依赖于该目标。 目标运行后,其在生成中的任务就已完成。
目标可以有 Condition
属性。 如果指定的条件评估结果为 false
,那么该目标不会执行且对生成没有影响。 有关条件的详细信息,请参阅条件。
初始目标
ProjectDefaultTargets
元素的 InitialTargets
属性指定将首先运行的目标,即使在命令行或 属性中指定了目标。 初始目标常用于错误检查。
InitialTargets
属性的值可以是以分号分隔的、有序的目标列表。 以下示例指定运行的 Warm
目标,然后指定运行的 Eject
目标。
<Project InitialTargets="Warm;Eject" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
导入的项目可能有自己的 InitialTargets
属性。 所有初始目标都聚集在一起并按顺序运行。
有关详细信息,请参阅如何:指定首先生成的目标。
默认目标
如果未在命令行上显式指定某个目标,Project 元素的 DefaultTargets
属性可指定将生成哪个或哪些目标。
DefaultTargets
属性的值可以是以分号分隔的、有序的默认目标列表。 以下示例指定运行的 Clean
目标,然后指定运行的 Build
目标。
<Project DefaultTargets="Clean;Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
若要重写默认目标,可以在命令行中使用 -target 开关。 以下示例指定运行的 Build
目标,然后指定运行的 Report
目标。 以此方式指定目标时,将忽略所有默认目标。
msbuild -target:Build;Report
如果指定了初始目标和默认目标,且未指定命令行的目标,那么 MSBuild 会先运行初始目标,然后运行默认目标。
导入的项目可能有自己的 DefaultTargets
属性。 第一个出现的 DefaultTargets
属性将确定要运行的默认目标。
有关详细信息,请参阅如何:指定首先生成的目标。
第一个目标
如果没有初始目标、默认目标或命令行目标,那么 MSBuild 会先运行项目文件中或任意导入的项目文件中出现的第一个目标。
目标依赖项
目标可描述相互依赖关系。 DependsOnTargets
属性表示目标依赖于其他目标。 例如,
<Target Name="Serve" DependsOnTargets="Chop;Cook" />
告知 MSBuild Serve
目标依赖于 Chop
目标和 Cook
目标。 MSBuild 将运行 Chop
目标,然后运行 Cook
目标,之后再运行 Serve
目标。
注意
SDK 中的标准目标定义一些 DependsOn
属性,这些属性包含作为该目标的依赖项的目标列表(例如,$(BuildDependsOn)
、$(CleanDependsOn)
等)。 例如,
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)">
若要自定义项目,可以使用扩展生成过程的其他自定义目标替代 DependsOn
属性,如扩展 Visual Studio 生成过程中所述。
在目标之前和在目标之后
可通过使用 BeforeTargets
和 AfterTargets
属性指定目标顺序。
请考虑使用以下脚本。
<Project DefaultTargets="Compile;Link" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Compile">
<Message Text="Compiling" />
</Target>
<Target Name="Link">
<Message Text="Linking" />
</Target>
</Project>
若要创建在 Compile
目标后,Link
目标前运行的直接目标 Optimize
,请将以下目标添加到 Project
元素中的任意位置。
<Target Name="Optimize" AfterTargets="Compile">
<Message Text="Optimizing" />
</Target>
或者,将顺序指定为
<Target Name="Optimize" BeforeTargets="Link">
<Message Text="Optimizing" />
</Target>
在同一目标上同时指定 BeforeTargets
和 AfterTargets
并没有作用。 如下一部分所述,只有遇到的第一个目标才会导致新目标运行。
确定目标生成顺序
MSBuild 按以下方式确定目标生成顺序:
运行
InitialTargets
目标。运行的是在命令行中使用 -target 开关指定的目标。 如果未在命令行上指定目标,则运行
DefaultTargets
目标。 如果都不存在,则运行出现的第一个目标。评估目标的
Condition
属性。 如果出现Condition
属性且评估结果为false
,那么不会运行该目标,且目标不会对生成造成进一步影响。列出
BeforeTargets
或AfterTargets
中的条件目标的其他目标仍按指定顺序执行。在执行或跳过目标之前,将运行其
DependsOnTargets
目标,除非将Condition
属性应用于目标并且计算结果为false
。注意
如果目标未执行,则会将其视为已跳过,因为其输出项是最新的(请参阅增量生成)。 此检查在执行目标内的任务之前完成,并且不会影响目标的执行顺序。
执行或跳过目标之前,运行
BeforeTargets
属性中列出的目标的其他目标。执行目标前,会比较其
Inputs
属性和Outputs
属性。 如果 MSBuild 确定任何输出文件相对于相应的输入文件过期,那么 MSBuild 将执行该目标。 否则,MSBuild 会跳过该目标。执行或跳过目标后,运行
AfterTargets
属性中列出目标的任何其他目标。