-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Ensure that Trimming and AOT scenarios trigger downloading of necessary runtime packs #51765
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
base: main
Are you sure you want to change the base?
Ensure that Trimming and AOT scenarios trigger downloading of necessary runtime packs #51765
Conversation
…also bring in the runtime packs when targeting a single RID. This fixes a gap where 'dotnet restore' for a RID followed by 'dotnet publish --no-restore' for that RID in trimming/AOT scenarios wouldn't work.
| <ItemGroup> | ||
| <ProjectCapability Remove="TestContainer" /> | ||
| </ItemGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is a bugfix from the DevKit folks (thanks @peterwald!) that unblocks the DevKit test explorer experience.
Because this project references xunit (thanks Arcade!) the xunit package adds this capability. Because the project has this capability, DevKit tries to load it as a test. Because this project is a library and doesn't have all of the test dependencies, it fails to load and crashes the test-discovery process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request fixes a gap in runtime pack resolution where projects using PublishTrimmed or PublishAot without SelfContained=true would fail during publish with --no-restore because required runtime packs weren't downloaded during restore.
Key Changes:
- Introduced
DeploymentModelRequiresRuntimeComponentsproperty that consolidates logic for determining when runtime packs are needed, now includingRequiresILLinkPack(set when trimming is enabled) alongsideSelfContained,ReadyToRunEnabled, andPublishAot - Refactored
KnownRuntimePackstruct to use C# 12 primary constructor and readonly properties for better maintainability - Added comprehensive unit tests covering various publish scenarios including trimming and AOT without self-contained deployment
- Created documentation specification detailing expected behavior of
ProcessFrameworkReferencestask across different deployment scenarios
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs | Core fix to runtime pack resolution logic; refactored struct to use modern C# features; introduced constants and helper properties for better code clarity |
| src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/ProcessFrameworkReferencesTests.cs | Added comprehensive test coverage for PublishTrimmed, PublishAot, and ReadyToRun scenarios with and without SelfContained; added support for ReadyToRunEnabled in test configuration |
| documentation/specs/ProcessFrameworkReferences-outputs.md | New specification document describing expected outputs for different deployment scenarios and documenting the fix for issue #51667 |
| test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj | Removed TestContainer project capability to prevent VS from treating the framework project as a test container |
| tasks.slnf | New solution filter for convenient development focused on build tasks projects |
src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
| /// <summary> | ||
| /// We have several deployment models that require the use of runtime assets of various kinds. | ||
| /// This member helps identify when any of those models are in use, because we've had bugs in the past | ||
| /// where we didn't properly account for all of them. | ||
| /// </summary> | ||
| private bool DeploymentModelRequiresRuntimeComponents => | ||
| SelfContained || ReadyToRunEnabled || PublishAot || RequiresILLinkPack; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This member is the actual fix. Every other change is tests, infra, debugging utility, clarity, etc.
|
Nit: per #51766 (comment) |
| <SelfContained>true</SelfContained> | ||
| <RuntimeIdentifier>linux-x64</RuntimeIdentifier> | ||
| <ReadyToRunEnabled>true</ReadyToRunEnabled> | ||
| <ReadyToRunUseCrossgen2>true</ReadyToRunUseCrossgen2> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a minimum runtime pack version that the current .NET SDK is compatible with? Does the current .NET SDK still support publishing for .NET 5 in all flavors?
UseCrossgen2 property was a thing in .NET 5 where crossgen2 was in preview and setting this property to true was used to opt-in into the preview. It has no purpose (it is always true) in .NET 6+.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SDK does still support publishing net5 apps - though you get a warning that that runtime is out of support. The property is mostly mentioned here for completeness given that it does play into the runtime pack selection in the processframeworkreferences task today - I didn't want a reader to read this and then see an entirely new concept in the implementation and wonder if we missed something critical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SDK does still support publishing net5 apps
Do you have a deprecation schedule for when .NET SDK is going to drop support for runtimes that are out of support for a long time?
I do not think it is a good use of resources to carry this baggage around, and the support is likely broken in number of ways anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why currently have no timeline for this. The general approach has been to allow everything, but only explicitly test 2 LTSs back. So for example net 6 is the lower bound on a lot of our tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why currently have no timeline for this. The general approach has been to allow everything, but only explicitly test 2 LTSs back. So for example net 6 is the lower bound on a lot of our tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general approach has been to allow everything
What's your confidence that the extra code required to allow everything actually works?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surprisingly high - there are a pretty high number of SDK-repo scenario tests that cover .NET 5 at least. I do get what you're saying though - there is a cost to carrying this around. There's a tension that we face on the tooling level because we want to enable folks to use the most recent tooling regardless of the TFM they're actually targeting. We feel that this is the best strategy to ensure that folks are getting the improved tooling experiences, perf improvements in the tooling, etc. The downside to this is that the tooling then needs to keep all of this downlevel logic around, and the tests contribute to overall SDK PR times, etc etc.
My gut feel is that this cost isn't incredibly high right now, but I'd be in favor of pushing tests that target these out of support or more-niche scenarios to a kind of 'outerloop' test run that doesn't block or impact normal PR flow.
…n't explicitly set to true until ILLink targets are updated
| <!-- The ILLink Targets expect projects to set SelfContained specifically, but the real condition they're trying to detect is | ||
| 'does this publish scenario require runtime components'. SelfContained is just the 'legacy' signal for that. | ||
| See https://github.com/dotnet/sdk/pull/51765#issuecomment-3537080089 for more context. | ||
| To work around this current constraint, we can detect the scenarios where runtime components are required | ||
| and set SelfContained accordingly before ILLink runs. It's ok to set SelfContained this 'late' because | ||
| the ProcessFrameworkReferences Task (which is where runtime packs are resolved) has already run by this | ||
| point and it has been updated to use this 'expanded' definition of when runtime components are required | ||
| already (e.g. the ProcessFrameworkReferences.DeploymentModelRequiresRuntimeComponents member). | ||
| The _RequiresILLinkPack property is set based on this expanded definition, so we can reuse it as our signal here. | ||
| It's possible that this property is what the ILLink targets should be using directly instead of SelfContained, but | ||
| we may want to have more 'abstract', non-private signal. | ||
| --> | ||
| <Target Name="_AlignSelfContainedBeforeILLink" BeforeTargets="PrepareForPublish" Condition=""> | ||
| <PropertyGroup> | ||
| <SelfContained Condition="'$(SelfContained)' != 'true' and '$(_RequiresILLinkPack)' == 'true'">true</SelfContained> | ||
| </PropertyGroup> | ||
| </Target> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a target to the SDK that 'patches' the SelfContained status so that we can demonstrate end-to-ends - we should have a conversation on what the ILLink Targets should be conditioning on instead of SelfContained directly.

Fixes dotnet/runtime#51667
There was a gap when restoring a project for a RID and then publishing it for that same RID with
--no-restorewhere if that project only set PublishTrimmed or PublishAOT, the runtime packs for that RID would not be restored. This would lead to the publish command failing saying that required runtime packs weren't available. There were a couple workarounds:Along the way I added some tests to cover the new scenarios, and extracted out a documentation spec to capture how we think ProcessFrameworkReferences should behave, modulo any bugs. In the future we should be able to reference this when answering questions about what the expected behavior is.
I also made a
tasks.slnfto make it easier to iterate on the SDK's MSBuild Tasks and their tests in isolation. This massively helps the VSCode user experiences, especially on the testing inner loop.