nvirth
nvirth

Reputation: 1751

MsBuild: Item: Remove with absolute path

This comes from a Shared project:

<Content Include="$(MSBuildThisFileDirectory)MyFile1" />

Let's say it's equivalent to

<Content Include="c:\MyProject\MyFile1" />

This comes from a normal project:

<Content Include="MyFile2" />

One is an absolute path, the other is a relative one.
Which makes issues when trying to Remove them, because eg the one with the relative path can't be Remove-d with its absolute path.
It seems Remove does string matching and not Path matching. Maybe I have to type into Remove the exact same string as it was Include-ed?

I can remove these files with:

<Content Remove="MyFile2" />
<Content Remove="c:\MyProject\MyFile1" />

I can't remove them with:

<Content Remove="c:\MyProject\MyFile2" />
<Content Remove="MyFile1" />

Is there a way to tell MsBuild these are paths and Remove them always by absolute path?

Upvotes: 0

Views: 569

Answers (1)

Jonathan Dodds
Jonathan Dodds

Reputation: 5008

Items have a set of metadata - see MSBuild well-known item metadata.

%(Identity) will be the string that was used for the item in the Include. But if the Item is a file that exists, then %(FullPath) will have a value.

e.g. Your example items are:

Identity FullPath
c:\MyProject\MyFile1 c:\MyProject\MyFile1
MyFile2 c:\MyProject\MyFile2

You need to use Identity for the Remove but you can create a new ItemGroup that is a subset of Content by testing the FullPath and then use that ItemGroup as the value of your Remove.

An example might be

<Target Name="Test">
    ...
    <ItemGroup>
        <FilesToRemove Include="@(Content)" Condition="'%(FullPath)' == 'c:\MyProject\MyFile1' or '%(FullPath)' == 'c:\MyProject\MyFile2'" />
    </ItemGroup>
    <ItemGroup>
        <Content Remove="@(FilesToRemove)" />
    </ItemGroup>
    ...
</Target>

The FilesToRemove ItemGroup is using task batching and must be within a Target.

Another example of the same approach but testing the file extension:

<Target Name="Test">
    ...
    <ItemGroup>
        <FilesToRemove Include="@(Content)" Condition="'%(Extension)' == '.js'" />
    </ItemGroup>
    <ItemGroup>
        <Content Remove="@(FilesToRemove)" MatchOnMetadata="Extension" />
    </ItemGroup>
    ...
</Target>

The Remove attribute accepts wildcards but

<Content Remove="**\*.js" />

won't work because it will not match items added without using a wildcard.

Upvotes: 2

Related Questions