Skip to content

[Breaking change] DefineConstants for target frameworks not available at evaluation time#52279

Open
Copilot wants to merge 4 commits intomainfrom
copilot/fix-defineconstants-evaluation-time
Open

[Breaking change] DefineConstants for target frameworks not available at evaluation time#52279
Copilot wants to merge 4 commits intomainfrom
copilot/fix-defineconstants-evaluation-time

Conversation

Copy link
Contributor

Copilot AI commented Mar 11, 2026

Adds a new breaking change article documenting that TFM-related DefineConstants values (such as NET9_0_OR_GREATER, NETSTANDARD2_0, and similar) are no longer computed at MSBuild evaluation time in .NET 10. Project file Condition attributes that inspect these values now silently evaluate against empty strings.

Changes

  • New article docs/core/compatibility/sdk/10.0/defineconstants-not-available-at-evaluation.md covering previous/new behavior, reason for change, and migration guidance
  • Entry added to docs/core/compatibility/toc.yml under .NET 10 > SDK and MSBuild
  • Row added to the SDK and MSBuild table in docs/core/compatibility/10.md

Migration pattern

<!-- Before (.NET 9 and earlier) — no longer works in .NET 10 -->
<ItemGroup Condition="$(DefineConstants.Contains('NET9_0_OR_GREATER'))">
  <PackageReference Include="SomePackage" Version="1.0.0" />
</ItemGroup>

<!-- After (.NET 10+) — use MSBuild TargetFramework functions -->
<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))">
  <PackageReference Include="SomePackage" Version="1.0.0" />
</ItemGroup>

User-defined DefineConstants values are unaffected; only the SDK-injected TFM constants moved to target-execution time.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Breaking change]: DefineConstants items for target frameworks are no longer available at evaluation-time</issue_title>
<issue_description>### Description

In .NET 10, we moved the generation of several DefineConstants MSBuild Property values related to the TargetFramework and Runtime (NET/NETFRAMEWORK/NETSTANDARD and OR_GREATER variants) used for the given build from evaluation-time to target-execution time. This was done for several reasons, including protecting critical areas of the build pipeline from inadvertent user corruption (via the use of /p:DefineConstants and friends), as well as making the overall build changes more understandable.

As a result, users who tried to key off of these DefineConstants values in Conditions at evaluation time will find those Conditions no longer triggering.

Version

.NET 10

Previous behavior

Usage of the the (NET/NETFRAMEWORK/NETSTANDARD)[VERSION][_OR_GREATER] DefineConstants (like NET, NET_452_OR_GREATER, NET9_0_OR_GREATER, and so on) worked at evaluation time, like the following in a project file:

<ItemGroup Condition="$(DefineConstants.Contains('NET_9_0_OR_GREATER'))">
  <PackageReference Include=".." Version=".." />
</ItemGroup>

New behavior

Usage of the the (NET/NETFRAMEWORK/NETSTANDARD)[VERSION][_OR_GREATER] DefineConstants (like NET, NET_452_OR_GREATER, NET9_0_OR_GREATER, and so on) will not work directly in a project file. Instead, users should use the documented TargetFramework comparison functions to perform such logic:

<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('net9.0', '$(TargetFramework)'))">
  <PackageReference Include=".." Version=".." />
</ItemGroup>

Type of breaking change

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

Direct access/manipulation of DefineConstants led to users overwriting the values, and we also needed the ability to call a Target to make those values get computed in other, more complex MSbuild orchestration that other tools required.

Recommended action

DO NOT

  • directly inspect DefineConstants properties for TFM-related values during evaluation

DO

  • use documented MSBuild property functions to check for TargetFramework compatibility
  • continue to use DefineConstants in Conditions if they are constants that you control

Feature area

SDK

Affected APIs

No response


Associated WorkItem - 558444</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.


Internal previews

📄 File 🔗 Preview link
docs/core/compatibility/10.md Breaking changes in .NET 10
docs/core/compatibility/sdk/10.0/defineconstants-not-available-at-evaluation.md DefineConstants for target frameworks not available at evaluation time
docs/core/compatibility/toc.yml docs/core/compatibility/toc

@gewarren
Copy link
Contributor

@copilot please try again

…t available at evaluation time

Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot please try again

Done in commit 43f1f5b. The breaking change article has been created at docs/core/compatibility/sdk/10.0/defineconstants-not-available-at-evaluation.md, with entries added to the TOC and the .NET 10 compatibility table.

Copilot AI changed the title [WIP] [Breaking change] Fix DefineConstants items for evaluation-time usage [Breaking change] DefineConstants for target frameworks not available at evaluation time Mar 12, 2026
Copilot AI requested a review from gewarren March 12, 2026 21:25
@gewarren gewarren marked this pull request as ready for review March 13, 2026 00:25
@gewarren gewarren requested a review from a team as a code owner March 13, 2026 00:25
Copilot AI review requested due to automatic review settings March 13, 2026 00:25
@gewarren gewarren enabled auto-merge (squash) March 13, 2026 00:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new .NET 10 SDK breaking change article documenting that the SDK-injected TFM-related values in DefineConstants are no longer available during MSBuild evaluation, and updates the compatibility index pages to include it.

Changes:

  • Adds a new breaking change article describing the evaluation-time behavior change and migration guidance.
  • Updates the .NET 10 compatibility index table to include the new breaking change.
  • Adds the new article to the compatibility TOC under .NET 10 > SDK and MSBuild.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
docs/core/compatibility/toc.yml Adds the new breaking change article to the TOC.
docs/core/compatibility/sdk/10.0/defineconstants-not-available-at-evaluation.md New breaking change article explaining the change and recommended migration pattern.
docs/core/compatibility/10.md Adds a new row in the .NET 10 breaking changes table referencing the article.

You can also share your feedback on Copilot code review. Take the survey.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Breaking change]: DefineConstants items for target frameworks are no longer available at evaluation-time

3 participants