MSBuild 与目标输出混淆的行为 & Returns
MSBuild confusing behavior with Target Outputs & Returns
我正在尝试了解输出和 Returns 参数背后的逻辑。在使用 Outputs & Returns 属性的情况下,我发现了非常混乱的行为。
e.x。我创建了一个包含 2 个目标 "Build" 和 "InternalTarget" 的项目。第一个目标通过 Outputs 属性定义其输出,第二个目标通过 Returns 属性定义输出。因此,如果我通过 MSBuild 任务调用构建目标,我将无法获得任何输出 - 它始终为空!但是,如果我注释掉第二个目标(无论如何都未使用),输出会神奇地出现。
为什么会这样???
example.proj
<Project ToolsVersion="4.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build"
Outputs="Build executed">
<Message Text="Build executing ..." />
</Target>
<Target Name="_InternalTarget"
Returns="_InternalTarget executed">
<Message Text="_InternalTarget executing ..." />
</Target>
</Project>
build.proj
<Project ToolsVersion="4.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<_ProjectsToBuild Include="example.proj" />
</ItemGroup>
<PropertyGroup>
<_ProjectsToBuildProperties>
Configuration=Debug;
</_ProjectsToBuildProperties>
</PropertyGroup>
<Target Name="Build">
<MSBuild Targets="Build"
Projects="@(_ProjectsToBuild)"
Properties="$(_ProjectsToBuildProperties)">
<Output TaskParameter="TargetOutputs"
ItemName="_ProjectsToBuildOutput" />
</MSBuild>
<Message Text="Output: @(_ProjectsToBuildOutput)." />
</Target>
</Project>
输出
Build started 3/4/2015 12:41:21 PM.
Project "C:\Development\Sources\MSBuildReturnsExample\build.proj" on node 1 (default targets).
Project "C:\Development\Sources\MSBuildReturnsExample\build.proj" (1) is building "C:\Development\Sources\MSBuildReturn
sExample\example.proj" (2) on node 1 (Build target(s)).
Build:
Build executing ...
Done Building Project "C:\Development\Sources\MSBuildReturnsExample\example.proj" (Build target(s)).
Build:
Output: .
Done Building Project "C:\Development\Sources\MSBuildReturnsExample\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
来自Target
element documentation,备注部分:
Before MSBuild 4, Target returned any items that were specified in the Outputs attribute. To do this, MSBuild had to record these items in case tasks later in the build requested them. Because there was no way to indicate which targets had outputs that callers would require, MSBuild accumulated all items from all Outputs on all invoked Targets. This lead to scaling problems for builds that had a large number of output items.
If the user specifies a Returns on any Target element in a project, then only those Targets that have a Returns attribute record those items.
因此,基于以上内容,如果您希望看到“Output:Build executed”。您应该将 example.proj 修改为:
<Project ToolsVersion="4.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build"
Returns="Build executed">
<Message Text="Build executing ..." />
</Target>
<Target Name="_InternalTarget"
Returns="_InternalTarget executed">
<Message Text="_InternalTarget executing ..." />
</Target>
</Project>
我正在尝试了解输出和 Returns 参数背后的逻辑。在使用 Outputs & Returns 属性的情况下,我发现了非常混乱的行为。
e.x。我创建了一个包含 2 个目标 "Build" 和 "InternalTarget" 的项目。第一个目标通过 Outputs 属性定义其输出,第二个目标通过 Returns 属性定义输出。因此,如果我通过 MSBuild 任务调用构建目标,我将无法获得任何输出 - 它始终为空!但是,如果我注释掉第二个目标(无论如何都未使用),输出会神奇地出现。
为什么会这样???
example.proj
<Project ToolsVersion="4.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build"
Outputs="Build executed">
<Message Text="Build executing ..." />
</Target>
<Target Name="_InternalTarget"
Returns="_InternalTarget executed">
<Message Text="_InternalTarget executing ..." />
</Target>
</Project>
build.proj
<Project ToolsVersion="4.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<_ProjectsToBuild Include="example.proj" />
</ItemGroup>
<PropertyGroup>
<_ProjectsToBuildProperties>
Configuration=Debug;
</_ProjectsToBuildProperties>
</PropertyGroup>
<Target Name="Build">
<MSBuild Targets="Build"
Projects="@(_ProjectsToBuild)"
Properties="$(_ProjectsToBuildProperties)">
<Output TaskParameter="TargetOutputs"
ItemName="_ProjectsToBuildOutput" />
</MSBuild>
<Message Text="Output: @(_ProjectsToBuildOutput)." />
</Target>
</Project>
输出
Build started 3/4/2015 12:41:21 PM.
Project "C:\Development\Sources\MSBuildReturnsExample\build.proj" on node 1 (default targets).
Project "C:\Development\Sources\MSBuildReturnsExample\build.proj" (1) is building "C:\Development\Sources\MSBuildReturn
sExample\example.proj" (2) on node 1 (Build target(s)).
Build:
Build executing ...
Done Building Project "C:\Development\Sources\MSBuildReturnsExample\example.proj" (Build target(s)).
Build:
Output: .
Done Building Project "C:\Development\Sources\MSBuildReturnsExample\build.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
来自Target
element documentation,备注部分:
Before MSBuild 4, Target returned any items that were specified in the Outputs attribute. To do this, MSBuild had to record these items in case tasks later in the build requested them. Because there was no way to indicate which targets had outputs that callers would require, MSBuild accumulated all items from all Outputs on all invoked Targets. This lead to scaling problems for builds that had a large number of output items.
If the user specifies a Returns on any Target element in a project, then only those Targets that have a Returns attribute record those items.
因此,基于以上内容,如果您希望看到“Output:Build executed”。您应该将 example.proj 修改为:
<Project ToolsVersion="4.0"
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build"
Returns="Build executed">
<Message Text="Build executing ..." />
</Target>
<Target Name="_InternalTarget"
Returns="_InternalTarget executed">
<Message Text="_InternalTarget executing ..." />
</Target>
</Project>