目标生成顺序

如果一个目标的输入取决于另一个目标的输出,则必须对目标进行排序。 可以使用这些属性来指定运行目标的顺序:

  • InitialTargets。 此属性 Project 指定将首先运行的目标,即使目标是在命令行或属性中指定的 DefaultTargets

  • DefaultTargets。 此属性 Project 指定如果未在命令行上显式指定目标,将运行哪些目标。

  • DependsOnTargets。 此属性 Target 指定在运行此目标之前必须运行的目标。

  • BeforeTargetsAfterTargets。 这些 Target 属性指定此目标应在指定目标之前或之后运行。

通常情况下,不应依赖声明的顺序来决定哪些任务在其他任务之前运行。

即使生成中的后续目标依赖于它,目标也不会在生成期间运行两次。 运行目标后,它对构建的贡献已完成。

目标可以具有属性 Condition 。 如果指定条件的计算结果为false,则不会执行目标,并且对构建没有影响。 有关条件的详细信息,请参阅 “条件”。

初始目标

Project元素的InitialTargets属性指定运行时将首先执行的目标,即使这些目标是在命令行或DefaultTargets属性中指定的。 初始目标通常用于错误检查。

该属性的值 InitialTargets 可以是以分号分隔的有序目标列表。 以下示例指定 Warm 运行目标,然后 Eject 运行目标。

<Project InitialTargets="Warm;Eject" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

导入的项目可以有自己的 InitialTargets 属性。 所有初始目标聚合在一起并按顺序运行。

有关详细信息,请参阅 “如何:指定要首先生成的目标”。

默认目标

DefaultTargetsProject 元素的属性,用于指定在命令行中未明确指定目标时要构建的任务或任务。

属性的值 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 取决于目标 ChopCook。 MSBuild 运行Chop目标,然后运行Cook目标,再运行Serve目标。

注释

SDK 中的标准目标定义一些DependsOn属性,这些属性包含作为该目标的依赖项的目标列表(例如,$(BuildDependsOn)$(CleanDependsOn)等等)。 例如,

<Target Name="Build" DependsOnTargets="$(BuildDependsOn)">

若要自定义项目,可以使用扩展生成过程的其他自定义目标替代 DependsOn 属性,如 扩展 Visual Studio 生成过程中所述。

BeforeTargets 和 AfterTargets

可以通过使用BeforeTargetsAfterTargets属性来指定目标顺序。

请考虑以下脚本。

<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 确定目标生成顺序,如下所示:

  1. InitialTargets 目标被运行。

  2. 在命令行中,通过 -target 开关指定的目标会被运行。 如果在命令行上未指定任何目标,则执行 DefaultTargets 目标。 如果两者都不存在,则运行第一个遇到的目标。

  3. 对目标的Condition属性进行评估。 Condition如果该属性存在并计算结果为false,则该构建目标不会被执行,并且对构建没有进一步影响。

    其他在BeforeTargetsAfterTargets中列出条件目标的目标,仍会按照规定的顺序执行,而不考虑条件的结果。

  4. 在执行或跳过目标之前,将运行其 DependsOnTargets 目标,除非将 Condition 属性应用于目标并计算结果为 false

    注释

    如果目标未执行,并且输出项 up-to-date,则视为跳过(请参阅 增量生成)。 此检查在目标内执行任务之前完成,不会影响目标的执行顺序。

  5. 在目标被执行或跳过之前,任何在 BeforeTargets 属性中列出此目标的其他目标都会被运行。

  6. 在执行目标之前,将比较其 Inputs 属性和 Outputs 属性。 如果 MSBuild 确定与相应的输入文件或文件相关的任何输出文件已过期,则 MSBuild 将执行目标。 否则,MSBuild 将跳过目标。

  7. 执行或跳过目标后,任何在某个属性中列出它的其他目标都会运行。