Nick
Nick

Reputation: 13

How to reevaluate MSBuild property

I can create MSBuild property, which contain unexpanded property reference. Here is example of it:

Text file property.txt contains single line

$(SomeProperty)

It can be processed with msbuild script like this:

<ItemGroup>
  <PropertyFile Include="property.txt"/>
</ItemGroup>

<!-- Standart task for file reading -->
<ReadLinesFromFile File="@(PropertyFile)" >
  <Output
      TaskParameter="Lines"
      ItemName="ItemsFromFile"/>
</ReadLinesFromFile>

<!-- Property LastLine now has value $(SomeProperty) -->
<PropertyGroup>
  <LastLine>%(ItemsFromFile.Identity)</LastLine>     
</PropertyGroup>

<Message Text="$(LastLine)"/>

Now I want to expand property reference, which contains in CurrentLine. Is it possible?

Upvotes: 1

Views: 1836

Answers (2)

Brian Kretzler
Brian Kretzler

Reputation: 9938

If you know in advance all of the properties that are candidates for being the single property listed in the file there is a way to do this with item filtering. Caveats:

1) Specify only the PropertyName in the file, not $(PropertyName), unless you want to parse the string using a property function.

2) There can only be a single line in the file with the approach below, for multiple lines you'll need an extra level of batching.

<ItemGroup>
  <PropertyFile Include="property.txt" />
</ItemGroup>

<PropertyGroup>
  <SomeProperty>1</SomeProperty>
  <SomeOtherProperty>2</SomeOtherProperty>
</PropertyGroup>
<ItemGroup>
  <ChooseProperty Include="SomeProperty">
    <Value>$(SomeProperty)</Value>
  </ChooseProperty>
  <ChooseProperty Include="SomeOtherProperty">
    <Value>$(SomeOtherProperty)</Value>
  </ChooseProperty>
</ItemGroup>

The constructs above establish two candidate properties, $(SomeProperty) and $(SomeOtherProperty). For this example the contents of property.txt was a single line...

SomeProperty

...which correlates to $(SomeProperty) which has a value of 1

<Target Name="ReadItems">
  <ReadLinesFromFile File="@(PropertyFile)">
    <Output
      TaskParameter="Lines"
      ItemName="ItemsFromFile"
      />
  </ReadLinesFromFile>
</Target>

<Target Name="FilterItems"
  Outputs="%(ChooseProperty.Identity)">
  <PropertyGroup>
    <_ThisProperty>%(ChooseProperty.Identity)</_ThisProperty>
    <_ThisValue>%(ChooseProperty.Value)</_ThisValue>
    <_ItemFromFile>%(ItemsFromFile.Identity)</_ItemFromFile>
  </PropertyGroup>
  <ItemGroup Condition="'$(_ItemFromFile)' == '$(_ThisProperty)'">
    <_FilteredItems Include="$(_ThisProperty)">
      <Value>$(_ThisValue)</Value>
    </_FilteredItems>
  </ItemGroup>
</Target>

Above are the two dependent targets for the main target below. They use a dependent target to read the file so that it is published into an item group to be used with target batching on the @(ChooseProperty) item group. The key thing to note is the condition on the creation of the @(_FilteredItems) item group, which will contain a single member, due to this...

Condition="'$(_ItemFromFile)' == '$(_ThisProperty)'

...notice that the batched item meta data is transferred to these temporary properties in order to make the condition work (and this is why the file can only contain a single line, so that there is only a single item).

<Target Name="ChoosePropertyFromItem"
  DependsOnTargets="ReadItems;FilterItems">
  <!-- Standard task for file reading -->
  <PropertyGroup>
    <LastLine>%(_FilteredItems.Value)</LastLine>
  </PropertyGroup>
  <Message Text="LastLine='$(LastLine)'" />
</Target>

...finally the $(LastLine) Property is pulled from the single item in @(_FilteredItems). The resulting output is below:

ChoosePropertyFromItem:
  LastLine='1'

Changing the property.txt to contain 'SomeOtherProperty' results in this:

ChoosePropertyFromItem:
  LastLine='2'

Upvotes: 1

Sergio Rykov
Sergio Rykov

Reputation: 4286

You can't create new properties in such a way. You can't create property names dynamically. You can modify build process. Example

 msbuild.exe yourproject.sln /p:UseSomeProp=true

Upvotes: 0

Related Questions