In my build process, I'm always using a pattern, whereby somes tasks are designed to compute the list of items in an item group, and some other tasks create the physical corresponding items.
This allows me to minimize my build times by performing incremental build.
In one of our project, I need to manipulate the items in an ItemGroup
. My first attempt, was to first, clear the contents of the ItemGroup
and then, include only the ones I'm interested about back into the ItemGroup
.
However, I stumbled upon a behavior of MSBuild that does not make sense to me. The issue, is trying to clear items from an ItemGroup
only when a particular Target
executes. That is, only if, after analysing its Inputs
and Outputs
attributes, MSBuild determines that the Target
must be executed.
Here is a minimal code snippet that reproduce my problem:
<Target Name="ComputeCustomItemGroup">
<CreateItem Include="C:\Temp\fichier1.ext;C:\Temp\fichier2.ext;">
<Output TaskParameter="Include" ItemName="CustomItemGroup" />
</CreateItem>
</Target>
<Target Name="CreateCustomItemGroup" DependsOnTargets="ComputeCustomItemGroup"
Inputs="C:\Temp\input"
Outputs="C:\Temp\output">
<Message Text="Creating custom item group..." />
<!-- Would like the ability to clear item group *ONLY* when the target is executed -->
<!-- But this clears the item group every time it appears in the dependency chain of a currently executing target ! -->
<ItemGroup>
<CustomItemGroup Remove="@(CustomItemGroup)" />
</ItemGroup>
</Target>
<Target Name="CustomTarget" DependsOnTargets="CreateCustomItemGroup">
<Message Text="Executing Custom Target..." />
<!-- Here, @(CustomItemGroup) is always empty... -->
<Message Text="CustomItemGroup: @(CustomItemGroup)" />
</Target>
<Target Name="Build" DependsOnTargets="CustomTarget" />
</Project>
In the code sample above, the @(CustomItemGroup)
is initially set to a collection containing a couple of file paths. That's fine.
Now, if you create two files, at the following locations C:\Temp\input and C:\Temp\output (one after the other, obviously), then the result of the sample code above is that @(CustomItemGroup)
comes back empty, even though the Target Name="CreateCustomItemGroup"
is not executed.
I've tried using the legacy CreateItem
way to manipulate ItemGroup
s but I could not find a safisfying answer.
Can anyone suggest a workaround?
You are facing "Output Inference" as described here http://msdn.microsoft.com/en-us/library/vstudio/ee264087%28v=vs.100%29.aspx
The target has no out-of-date outputs and is skipped. MSBuild evaluates the target and makes changes to items and properties as if the target had been run.
Consider re-designing your logic to use condition statements for assignments.