msbuilditemgroup

How to clear (and possibly include other) items from an ItemGroup?


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 ItemGroups but I could not find a safisfying answer.

Can anyone suggest a workaround?


Solution

  • 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.