增量生成

MSBuild 增量生成是经过优化的生成。优化后,如果目标具有的输出文件相对于其相应的输入文件保持为最新,则系统不会执行该目标。

目标元素可以同时具有一个 Inputs 属性,该属性指示目标期望作为输入的项,以及一个 Outputs 属性,该属性指示它作为输出生成的项。 MSBuild 尝试在这些属性的值之间查找一对一映射。 如果存在此类映射,MSBuild 会将每个输入项的时间戳与其相应输出项的时间戳进行比较。 没有一对一映射的输出文件与所有输入文件进行比较。 如果某项的输出文件的时间戳与该项的一个或多个输入文件相同,或与之相比较新,则将该项视为最新。

说明

当 MSBuild 评估输入文件时,只考虑当前执行中列表的内容。 上次生成列表中的更改不会自动使目标过期。

如果所有输出项都 up-to-date,MSBuild 将跳过目标。 目标的这种增量生成可以显著提高生成速度。 如果只有部分文件保持为最新,MSBuild 会执行目标,但跳过最新的项,从而使所有项均保持为最新。 此进程称为“部分增量生成”

一对一映射只能通过使 Outputs 属性成为 Inputs 属性的转换来生成。 有关详细信息,请参阅 MSBuild 转换

请考虑以下目标:

<Target Name="Backup" Inputs="@(Compile)"
    Outputs="@(Compile->'$(BackupFolder)%(Identity).bak')">
    <Copy SourceFiles="@(Compile)" DestinationFiles=
        "@(Compile->'$(BackupFolder)%(Identity).bak')" />
</Target>

Compile 项类型表示的文件集将复制到备份目录。 备份文件具有 .bak 文件扩展名。 如果运行 Backup 目标后,不会删除或修改由 Compile 项类型或相应的备份文件表示的文件,则在后续生成中跳过 Backup 目标。

输出推理

MSBuild 比较目标 InputsOutputs 属性,以确定目标是否需要执行。 理想情况下,完成增量生成后存在的文件集应保持不变,无论是否执行关联的目标。 由于任务创建或更改的属性和项可能会影响生成,因此即使跳过影响它们的目标,MSBuild 也必须推断其值。 此进程称为“输出推理”

有三种情况:

  • 目标具有计算结果为 falseCondition 属性。 这种情况不运行目标且不影响生成。

  • 目标具有过时的输出,将运行目标,让这些输出保持为最新。

  • 目标没有过时的输出,将跳过目标。 MSBuild 会评估目标,并像运行目标一样对项和属性进行更改。

为了支持增量编译,任务必须确保任何 Output 元素 TaskParameter 属性值等于任务输入参数。 例如:

<CreateProperty Value="123">
    <Output PropertyName="Easy" TaskParameter="Value" />
</CreateProperty>

此代码创建了属性 Easy,该属性无论目标是否执行或跳过,其值均为 123

从 MSBuild 3.5 开始,输出推理会自动对目标中的项和属性组执行。 目标中无需 CreateItem 任务,应避免该任务。 此外,CreateProperty 任务仅应在目标中使用,以确定目标是否已被执行。

在 MSBuild 3.5 之前,可以使用 CreateItem 任务。

确认是否运行了某个目标

由于输出推理,必须检查目标的属性和项,以确定是否执行了目标。 为此,向目标添加 CreateProperty 任务,并为其提供 Output 元素,该元素的 TaskParameterValueSetByTask。 例如:

<CreateProperty Value="true">
    <Output TaskParameter="ValueSetByTask" PropertyName="CompileRan" />
</CreateProperty>

此代码创建属性 CompileRan 并为其提供值 true,但前提是执行目标。 如果目标被跳过,则不会创建 CompileRan