jpm42
jpm42

Reputation: 71

Any way to update MSBuild item metadata value?

I need to update item metadata values. It's easy to add to the value:

<ItemDefinitionGroup>
  <ClCompile>
    <PreprocessorDefinitions>FOO;BAR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  </ClCompile>
</ItemDefinitionGroup>

However, what I need to do is remove part of the value. Ideally something like this would work, but it doesn't:

<ItemDefinitionGroup>
  <ClCompile>
    <PreprocessorDefinitions>%(PreprocessorDefinitions.Replace('FOO;',''))</PreprocessorDefinitions>
  </ClCompile>
</ItemDefinitionGroup>

Is there any way to accomplish this in MSBuild 4?

Upvotes: 4

Views: 1281

Answers (2)

chwarr
chwarr

Reputation: 7192

In a subsequent ItemDefinitionGroup, you can create a copy of the current metadata then call Replace on that:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Dump" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <ItemDefinitionGroup>
    <SomeItem>
      <SomeMetaData>foo,bar,baz</SomeMetaData>
    </SomeItem>
  </ItemDefinitionGroup>

  <ItemGroup>
    <SomeItem Include="one;two" />
  </ItemGroup>

  <ItemDefinitionGroup>
    <SomeItem>
      <!-- Remove "bar" -->
      <SomeMetaData>$([System.String]::Copy('%(SomeMetaData)').Replace('bar',''))</SomeMetaData>
    </SomeItem>
  </ItemDefinitionGroup>

  <Target Name="Dump">
    <Message Text="SomeItem.SomeMetaData: @(SomeItem -> '%(Identity)=%(SomeMetaData)') " />
  </Target>
</Project>

Here's the output when run with MSBuild 14:

 > MSBuild .\foo.proj
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 2/17/2017 7:09:48 PM.
Project "D:\temp\mb\foo.proj" on node 1 (default targets).
Dump:
  SomeItem.SomeMetaData: one=foo,,baz;two=foo,,baz
Done Building Project "D:\temp\mb\foo.proj" (default targets).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.03

Upvotes: 1

bakedlama
bakedlama

Reputation: 21

I was trying to do the same thing, and while I couldn't figure out how to strip definitions out of the string, I did discover an additional property: UndefinePreprocessorDefinitions.

<ItemDefinitionGroup>
  <ClCompile>
    <UndefinePreprocessorDefinitions>FOO</UndefinePreprocessorDefinitions>
  </ClCompile>
</ItemDefinitionGroup>

This will cancel out a previous definition of FOO. It might look a bit silly to pass -DFOO -UFOO to the compiler instead of nothing at all, but it works just as well.

Upvotes: 2

Related Questions