Following up on https://stackoverflow.com/questions/45964967/msbuild-itemgroup-exclude-doesnt-work-with-wildcards
Exclude patterns behave different at runtime than during static evaluation. For example:
<Project>
<ItemGroup>
<SourcItem Include="..\..\References\AnotherFolder\ReferencedAssembly.dll" />
<SourcItem Include="bin\GeneratedAssembly1.dll" />
<SourcItem Include="bin\GeneratedAssembly2.dll" />
<SourcItem Include="somefolder\somefile.txt" />
<SourcItem Include="somefolder\somefile.exe" />
<SourcItem Include="bin\anexe.exe" />
</ItemGroup>
<ItemGroup>
<StaticallyFilteredItem Include="@(SourcItem)" Exclude="..\..\References\**\*" />
</ItemGroup>
<Target Name="Build">
<ItemGroup>
<TargetFilteredItem Include="@(SourcItem)" Exclude="..\..\References\**\*" />
</ItemGroup>
<Message Importance="high" Text="StaticallyFilteredItem: %(StaticallyFilteredItem.Identity)" />
<Message Importance="high" Text="TargetFilteredItem: %(TargetFilteredItem.Identity)" />
</Target>
</Project>
produces:
$ dotnet msbuild
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
StaticallyFilteredItem: bin/GeneratedAssembly1.dll
StaticallyFilteredItem: bin/GeneratedAssembly2.dll
StaticallyFilteredItem: somefolder/somefile.txt
StaticallyFilteredItem: somefolder/somefile.exe
StaticallyFilteredItem: bin/anexe.exe
TargetFilteredItem: ../../References/AnotherFolder/ReferencedAssembly.dll
TargetFilteredItem: bin/GeneratedAssembly1.dll
TargetFilteredItem: bin/GeneratedAssembly2.dll
TargetFilteredItem: somefolder/somefile.txt
TargetFilteredItem: somefolder/somefile.exe
TargetFilteredItem: bin/anexe.exe
Is this by design and a desired behaviour or a bug?
I compared latest msbuild with msbuild that shipped with vs2015. Old msbuild only excluded the relative files if the files exist, but doesn't if the files do not exist. Latest msbuild has the old behaviour for target items, but static items exclude the file regardless whether it exists or not.
Simplified test project:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SourcItem Include="..\a\b.cs" />
</ItemGroup>
<ItemGroup>
<StaticallyFilteredItem Include="@(SourcItem)" Exclude="..\a\**" />
</ItemGroup>
<Target Name="Build">
<ItemGroup>
<TargetFilteredItem Include="@(SourcItem)" Exclude="..\a\**" />
</ItemGroup>
<Message Importance="high" Text="StaticallyFilteredItem: %(StaticallyFilteredItem.Identity)" />
<Message Importance="high" Text="TargetFilteredItem: %(TargetFilteredItem.Identity)" />
</Target>
</Project>
When the file exists:
E:.
โ
โโโโa
โ b.cs
โ
โโโโsub
build.proj
msbuild sub\build.proj /clp:v=m
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.
StaticallyFilteredItem:
TargetFilteredItem:
E:\projects\tests\projects\play>e:\projects\msbuild_2\bin\Bootstrap\MSBuild\15.0\Bin\MSBuild.exe sub\build.proj /clp:v=m
Microsoft (R) Build Engine version 15.5.165.8245 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
StaticallyFilteredItem:
TargetFilteredItem:
When the file does not exist:
E:.
โ
โโโโa
โ c.cs
โ
โโโโsub
build.proj
msbuild sub\build.proj /clp:v=m
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.
StaticallyFilteredItem: ..\a\b.cs
TargetFilteredItem: ..\a\b.cs
e:\projects\msbuild_2\bin\Bootstrap\MSBuild\15.0\Bin\MSBuild.exe sub\build.proj /clp:v=m
Microsoft (R) Build Engine version 15.5.165.8245 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
StaticallyFilteredItem:
TargetFilteredItem: ..\a\b.cs
Personally I think that relative excludes should work, regardless if the files exist or not. I am going to mark this as a bug, where static items are doing the right thing now, but target items still need to be fixed.
@cdmihai any chance to address this in 16.0 or do you want to close it as "we'll just need to live with the difference"?
Added this to the larger saga of unifying the two item evaluation clones: #1124 . The correct fix is to unify the cloned item evaluation code between static items and dynamic items.
I am going to mark it for dev16 for visibility, but there's a chance we won't get to it. :(
I've been affected this... So, how long until MSBuild 16.0 lands?
Also, Exclude is pretty poorly documented(!), so discovering it doesn't work as intended is not so surprising..
I have an example here in the docs issue I raised that also demonstates this issue with static vs. runtime:
#2780
Most helpful comment
Added this to the larger saga of unifying the two item evaluation clones: #1124 . The correct fix is to unify the cloned item evaluation code between static items and dynamic items.
I am going to mark it for dev16 for visibility, but there's a chance we won't get to it. :(