There are scenarios where the situation calls for performing set operations on item collections. You may want to join them together, subtract one from another, or perform an inner join. I originally came up with the idea to demonstrate these from this forum question. These examples work in both MSBuild 2.0 and MSBuild 3.5. A 3.5 only version is included with the attachment to this article.
Set Up
Create an empty msbuild file. Add a default target that you will use to perform the set operations and display messages to show your results.
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SetA Include="alpha;beta;gamma;delta"/>
<SetB Include="alpha;gamma;epsilon"/>
</ItemGroup>
<Target Name="Build">
</Target>
</Project>
Union All
Perhaps the easiest set operation is the Union All. This operation combines one collection with another, including duplicates. We only have to use the CreateItem including both sets. Add the following code inside your target to see this in action.
<CreateItem Include="@(SetA);@(SetB)" >
<Output TaskParameter="Include" ItemName="UnionAllSet"/>
</CreateItem>
<Message Text="Union All: @(UnionAllSet)"/>
Minus
The Minus operation works similar to the Union All operation. However, instead of including both sets, you include one set and exclude the other.
<CreateItem Include="@(SetA)" Exclude="@(SetB)" >
<Output TaskParameter="Include" ItemName="MinusSet"/>
</CreateItem>
<Message Text="Minus: @(MinusSet)"/>
Intersect
Intersect only takes items that are in both collections. It starts to get tricky with this operation and in fact was the catalyst for this article. I attempted to perform this one using conditions, but nothing seemed to work. I finally realized I would have to perform multiple operations to get the desired intersection: take the first set and exclude the minus set.
<CreateItem Include="@(SetA)" Exclude="@(MinusSet)" >
<Output TaskParameter="Include" ItemName="IntersectSet"/>
</CreateItem>
<Message Text="Intersect: @(IntersectSet)"/>
Union
The Union operation pulls elements from both item collections. This is very similar to Union All except that it does not include duplicates. To accomplish this, take the UnionAllSet and exclude IntersectSet. Since this removes the original and duplicate items, add IntersectSet back to the results.
<CreateItem Include="@(UnionAllSet)" Exclude="@(IntersectSet)" >
<Output TaskParameter="Include" ItemName="UnionSet"/>
</CreateItem>
<CreateItem Include="@(IntersectSet)" >
<Output TaskParameter="Include" ItemName="UnionSet"/>
</CreateItem>
<Message Text="Union: @(UnionSet)"/>
Conclusion
These are basic examples of doing set operations in MSBuild. Combined with batching and transforms, there isn't much standing in the way of defining your item collections how you wish.
Be sure to download the samples below. It includes an MSBuild 3.5 version using the new, cleaner ItemGroup syntax.
MSBuildSetOperations.zip (1.12 kb)