msbuild
msbuild copied to clipboard
Unexpected duplicate items
Issue Description
In the Dependency target below, OutFiles is what I expect. But its content is duplicated when accessed in the Primary target.
The issue goes away if I remove the Input and Output attributes.
Issue.targets:
<Project DefaultTargets="Primary">
<ItemGroup>
<InFiles Include="A.in;B.in" />
</ItemGroup>
<Target Name="Primary"
DependsOnTargets="Dependency">
<Message Text="In Primary target. OutFiles: @(OutFiles)" Importance="high" />
</Target>
<Target Name="Dependency"
Inputs="@(InFiles)"
Outputs="@(InFiles->'%(filename).out')">
<ItemGroup>
<OutFiles Include="*.out" />
</ItemGroup>
<Message Text="In Dependency target. OutFiles: @(OutFiles)" Importance="high" />
</Target>
</Project>
Output:
PS> dotnet build Issue.targets --nologo
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out;A.out;B.out
Steps to Reproduce
Here's a working example, since it may depend on file time stamps:
MSBuildIssue.zip
Unzip and run dotnet build Issue.targets.
Expected Behavior
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out
Actual Behavior
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out;A.out;B.out
Versions & Configurations
msbuild.exe
- Microsoft (R) Build Engine version 17.3.0-preview-22277-01+f1dae6ab6 for .NET Framework
17.3.0.27701
dotnet.exe
- 6.0.400-preview.22301.10
Team triage: this is a super weird bug with a great repro, thank you!
It looks like you can work around by specifying
Outputs="@(InFiles->'%(Directory)%(FileName).out')"
but we're not totally sure why yet.
We initially thought that something was erroneously causing MSBuild to interpret the item transform expression in your Outputs as a batch operation, so the entire target was running for each InFiles item. But that's not the case; the list is only ever doubled, even when there are more InFiles items, and we don't see the log message from inside Dependency more than once.
Try
<OutFiles Include="@(InFiles->'%(FileName).out')" />
We can rule out globbing if this also produces similar output!
~~Also, I only have v17.2.5 and this doesn't happen on that version so something must have changed in-between!~~
Also, I only have
v17.2.5and this doesn't happen on that version so something must have changed in-between!
I repro on 17.2:
❯ msbuild .\Issue.targets -v:m
Microsoft (R) Build Engine version 17.2.1+52cd2da31 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out;A.out;B.out
And older:
❯ msbuild Issue.targets -v:m
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out;A.out;B.out
Edit: and even older:
> C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe Issue.targets -v:m
Microsoft (R) Build Engine version 4.8.4161.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out;A.out;B.out
With <OutFiles Include="@(InFiles->'%(FileName).out')" />, it produces
❯ msbuild Issue.targets -v:m
Microsoft (R) Build Engine version 4.8.9032.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
In Dependency target. OutFiles: B.out
In Primary target. OutFiles: A.out;B.out
Is this expected output?
By directly specifying the file, it also duplicates the items:
❯ msbuild Issue.targets -v:m
Microsoft (R) Build Engine version 4.8.9032.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
In Dependency target. OutFiles: A.out;B.out
In Primary target. OutFiles: A.out;B.out;A.out;B.out
When I included the extra item, as expected with your repro, it also duplicates further.
❯ msbuild Issue.targets -v:m
Microsoft (R) Build Engine version 4.8.9032.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
In Dependency target. OutFiles: A.out;B.out;A.out
In Primary target. OutFiles: A.out;B.out;A.out;A.out;B.out;A.out
So, I think no globbing is involved!