增量生成
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 比较目标 Inputs
和 Outputs
属性,以确定目标是否需要执行。 理想情况下,完成增量生成后存在的文件集应保持不变,无论是否执行关联的目标。 由于任务创建或更改的属性和项可能会影响生成,因此即使跳过影响它们的目标,MSBuild 也必须推断其值。 此进程称为“输出推理”。
有三种情况:
目标具有计算结果为
false
的Condition
属性。 这种情况不运行目标且不影响生成。目标具有过时的输出,将运行目标,让这些输出保持为最新。
目标没有过时的输出,将跳过目标。 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
元素,该元素的 TaskParameter
为 ValueSetByTask
。 例如:
<CreateProperty Value="true">
<Output TaskParameter="ValueSetByTask" PropertyName="CompileRan" />
</CreateProperty>
此代码创建属性 CompileRan
并为其提供值 true
,但前提是执行目标。 如果目标被跳过,则不会创建 CompileRan
。