How can I merge two ItemGroups in MSBuild

2019-08-31 12:25发布

问题:

I have two ItemGroups:

<ItemGroup>
    <Compile Include="A.cs" />
    <Compile Include="B.cs" />
    <Compile Include="C.cs" />
</ItemGroup>
<ItemGroup>
    <PEG Include="A.cs" />
    <PEG Include="Y.cs" />
    <PEG Include="Z.cs" />
</ItemGroup>

I need to do add each of the items in PEG to Compile IF AND ONLY IF that item is not AREADY in Compile.

Is there an easy way to do that?

My first attempt is something like:

<ItemGroup>
  <Compile Include="%(PEG.Identity)" Condition=" '$(Compile)' != '%(PEG.Identity)' " />
</ItemGroup>

But that doesn't work for obvious reasons. I don't really want to do a manual anti-join in MSBuild.

Perhaps using Exclude would work?

回答1:

Alright, I figured it out.

The first thing I was doing wrong, was using $(Compile) rather than @(Compile).

Next, I was on the right track with the Exclude property.

Here is what I have come up with:

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Compile">
  <ItemGroup>
    <Compile Include="A.cs" />
    <Compile Include="B.cs" />
    <Compile Include="C.cs" />
  </ItemGroup>
  <Target Name="Compile">
    <ItemGroup>
        <PEG Include="A" />
        <PEG Include="D" />
    </ItemGroup>
    <Message Text="Compile = @(Compile)" />
    <Message Text="PEG     = @(PEG)" />
    <ItemGroup>
        <Compile Include="%(PEG.Identity).cs" Exclude="@(Compile)" />
    </ItemGroup>
    <Message Text="Compile = @(Compile)" />
  </Target>
</Project>

After this is done, Compile contains A.cs;B.cs;C.cs;D.cs as desired.