Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: all references to metadata(in an Item element inside a Target) always refer to the value prior to evaluating the Item element #10721

Open
Arthri opened this issue Sep 30, 2024 · 4 comments
Assignees
Labels

Comments

@Arthri
Copy link

Arthri commented Sep 30, 2024

Issue Description

When using item metadata within an Item element contained inside a Target, the value of the metadata always evaluates to its value immediately before entering the Item element. That is, any updates to metadata inside an Item element are not reflected in later references to that metadata inside the same Item element

Steps to Reproduce

A minimal sample project is available at https://github.com/Arthri/msbuild_demo_batching

  1. Include some items into a group
  2. Create a target which operates over the items and changes some metadata
  3. In the same Item element, update metadata conditionally using the metadata that was changed

Miminal sample

<ItemGroup>
  <T Include="a;b;c;d" />
</ItemGroup>

<Target Name="_T" BeforeTargets="Build">
  <ItemGroup>
    <T>
      <M>default data</M>
      <M Condition="'%(T.M)' == 'default data'">new default</M>
    </T>
  </ItemGroup>

  <!-- Outputs 'default data' four times -->
  <Warning Text="%(T.Identity): %(T.M)" />
</Target>

Expected Behavior

The condition should've used the new value of the metadata, and outputted four warnings containing "new default"

Actual Behavior

The condition used the old value of the metadata: the metadata before entering the Item element in the ItemGroup, and outputted four warnings containing "default data"

Analysis

I believe that MSBuild is replacing the metadata before entering the Item element, and when the condition runs, it never sees the updated metadata values.

Assuming the aforementioned is true, it can be concluded that spreading the metadata updates over several Item elements should work. And from my testing, I've observed that this is a working solution

<ItemGroup>
  <T>
    <M>default data</M>
  </T>
  <T>
    <M Condition="'%(T.M)' == 'default data'">new default</M>
  </T>
</ItemGroup>

Versions & Configurations

.NET SDK version 8.0.400
MSBuild version 17.11.3.35201 / 17.11.3+0c8610977
Microsoft Visual Studio version 17.11.3

@Arthri Arthri added the bug label Sep 30, 2024
@KalleOlaviNiemitalo
Copy link

It seems likely that some projects are relying on the current behaviour already. Are there easy ways to analyse public source code to measure how common that is?

@Arthri
Copy link
Author

Arthri commented Sep 30, 2024

Pardon? Is that a question meant for me?

@KalleOlaviNiemitalo
Copy link

To anyone who knows about tools or services that can be used for such analysis.

@AR-May AR-May self-assigned this Oct 1, 2024
@AR-May
Copy link
Member

AR-May commented Oct 1, 2024

@rainersigwald It seems like documentation concerning expansion in conditions does not mention this situation in detail: "The value of an %-expression in a target is evaluated at run-time and depends on any state changes during target execution.".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants