-
Notifications
You must be signed in to change notification settings - Fork 266
Design for allowing restore of multiple equivalent frameworks (Target Frameworks as Aliases) #12124
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: dev
Are you sure you want to change the base?
Conversation
Nirmal4G
left a comment
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.
Some ideas and suggestions. Feel free to ignore it. 😅🙃
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
|
Thanks for taking a look @Nirmal4G For context, this is design I'm still working on, I'd say it's at about 50%. Hoping to add more details about the scenarios and just in general provide more concrete proposals soon. |
|
@nkolev92 These are some of my observations and preliminary suggestions, ideas and takeaways from this draft. I'm not taking this as a concrete proposal. I'm just viewing this from a 10-foot view (or design perspective) of the proposal to see how it could impact normal as well as advanced users. In that mindset, read through my comments again. You would then see what I was talking about. |
Sure, Will look though once you mark this ready for review. Sorry for the uninvited comments. I'll stop now. |
Oh no worries. I appreciate the feedback as this is a large doc so getting feedback early on is always great. My comment was more about that fact that I'll be adding even more info to the doc, setting expectations about when something like this would even be close to happening :) |
proposed/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
55c6bba to
1c19625
Compare
accepted/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
accepted/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
accepted/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
|
This PR has been automatically marked as stale because it has no activity for 30 days. It will be closed if no further activity occurs within another 15 days of this comment, unless it has a "Status:Do not auto close" label. If it is closed, you may reopen it anytime when you're ready again, as long as you don't delete the branch. |
|
oops, vacation and other priorities has kept this feature on the backburner, but it's still planned. |
accepted/2022/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
| Should we consider more significant schema changes in the assets file? | ||
|
|
||
| Under `$/libraries`, each package lists every file in the package. | ||
| However, the performance penalty of needing to parse that list every time the assets file is read may be worse than any benefit it provides from avoiding enumerating the filesystem when it is needed. |
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.
For a functions extensibility scenario, I am considering having extension packages include a well-known marker file in their nupkg. I was going to leverage the fact that the assets file already has all nupkg file contents listed in it to speed up that process.
With this change, is the suggestion I would need to manually scan the file system of every nuget package? Or do you have an idea of a more general way I can add metadata to a nuget package and read it during a build?
Today we have an assembly attribute and we use Mono.Cecil to scan runtime assemblies from nuget looking for that attribute. This is understandably not performant. Which is why I am considering the marker file approach. I wouldn't block on this change just for our use case, but some metadata system for nupkgs that can be read at build time would be helpful (but obviously that would be an entirely different proposal).
1c19625 to
ddc7fae
Compare
ddc7fae to
413d370
Compare
… Frameworks as Aliases)
650ca9a to
b6c47f6
Compare
|
@ericstj @ViktorHofer @dsplaisted @baronfel @zivkan @jeffkl This is ready for review. It's a complicated, but I'd love to get through it async as much as possible because of the length itself :D |
|
|
||
| Currently `GetReferenceNearestTargetFrameworkTask` is implemented by running NuGet's "nearest match" algorithm. | ||
| This feature would extend it to first try nearest match, and if there is more than one matching `TargetFramework`, then look for a `TargetFramework` that has an exact name match in both projects. | ||
| If there are more than one "nearest" framework, but no exact name match, then for the first version of this feature, NuGet will report an error. |
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.
How hard would it be to have some sort of extensibility point so that you can add your own logic to choose the "nearest" framework if the NuGet logic results in more than one match?
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.
To add to that question, in the "No match found" case, would it make sense to return that information without raising an error / warning so that we could allow for customization in the msbuild target instead of in the task (which would give us much more flexibility)?
We still want to raise an error if there's no customization (I'm trying to avoid the word "fallback" here as it has a different meaning for NuGet). That would probably need to be moved outside of the task, into the 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.
How hard would it be to have some sort of extensibility point so that you can add your own logic to choose the "nearest" framework if the NuGet logic results in more than one match?
It's not impossible. I'd love to see any usage of this multiple framework project reference scenario before we want that direction though.
To add to that question, in the "No match found" case, would it make sense to return that information without raising an error / warning so that we could allow for customization in the msbuild target instead of in the task (which would give us much more flexibility)?
Can you help me understand how this could help?
If there's no nearest match/restore/build should be failing.
I see this as equivalent to a nearest framework not matching at all.
We still want to raise an error if there's no customization (I'm trying to avoid the word "fallback" here as it has a different meaning for NuGet). That would probably need to be moved outside of the task, into the target.
The target that calls the task does not run during restore.
In the core restore algorithm, NuGet picks the nearest project ref and that's based on the data provided to NuGet and collected at the beginning of restore.
Effectively, NuGet does the same thing internally when choosing to flow the package references coming through projects.
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 see, fair point. I was basically wondering if we can add an extension point / a callback to provide additional information that would allow us to extend the selection algorithm for the multiple or non found cases.
Runtime today overwrites the entire selection algorithm target (msbuild) and task (nuget) due to not an extension point being available. This isn't great and needs an update every time the P2P protocol is touched and the msbuild target gets updated.
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 know you're not focusing on that right now, but what are some practical examples where the runtime needs to overwrite the selection.
I was hoping alias matching would address a bunch of those needs.
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.
RID based selection. I.e. net10.0-linux should be able to reference net10.0-unix (as unix is a parent of linux in the graph). The current algorithm as you describe in the doc wouldn't be able to handle that but it would support direct matches, i.e. net10.0-unix referencing net10.0-unix.
We can probably workaround that limitation if necessary or even change the RIDs that we target in TFMs but yeah...
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 see. That's the next step then yeah.
Rids are a cross product, but maybe it'll be possible to add first class support for nearest that accounts for the RID as well.
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 probably wouldn't try to include RID matching in NuGet or the SDK for the first version of this, ideally just an extensibility point so that people could add it.
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 think in V1, we can just add alias matching support, but I'll create a follow-up for the extensibility point.
Right now, the current technical implementation does not allow a computational extensibility.
accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
|
|
||
| PackageReference is also supported by non-SDK style projects, which use [dotnet/NuGet.BuildTools](https://github.com/NuGet.BuildTools) which, despite the name, is owned by the non-SDK project system team, not NuGet. | ||
| The changes to the assets file that affect legacy projects will be done in a non-breaking way and as such, changes should not be required there. | ||
| NuGet will utilize the SDKAnalysisLevel property when it writes out an assets file with breaking changes, ensuring that the .NET SDK will be able to read the assets file for the build. |
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.
Customers are expected to change SDKAnalysisLevel if they have build errors when upgrading to a newer SDK. I can't remember the name of the property, but there's an SDK version that feels more appropriate for what this is aiming to achieve.
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.
Yeah, there's an SDK version property for sure, we raise telemetry on that, but I see SDKAnalysisLevel to mean, behave like the previous SDK version, and to me that'd imply the older restore behavior in general.
I don't feel too strongly though, and can easily be convinced otherwise.
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.
In my mind, SdkAnalysisLevel is about warnings and errors (diagnostics), not features, and looking at the original spec, I feel my opinion is reinforced: https://github.com/dotnet/designs/blob/main/proposed/sdk-analysis-level.md
The spec doesn't say it, but I always thought SdkAnalysisLevel was inspired by Roslyn's AnalysisLevel, and Roslyn also has LangVersion which I consider to be the feature toggle. The SDK/NuGet doesn't have a "global feature toggle" like Roslyn does with LangVersion. Using SdkAnalysisLevel is a choice that can be made, but then customers lose the ability to enable new features while disabling new diagnostics. I guess we need to decide whether that's an important distinction to allow customers to have.
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 think Chet has a good compass when it comes to SDKAnalysisLevel.
Curious what you think @baronfel
tldr;
NuGet will introduce a V4 of the assets file.
It requires a new .NET SDK reader, ie a specific .NET SDK version.
Should that "switch" be based off of the SDKAnalysisLevel or NETCoreSdkVersion property.
More context on the pros and cons in the above comments.
accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
|
|
||
| As previously shown in [the assets file pivots changes](#target-framework-pivots), NuGet uses `tfm/rid` as the property name in the `$/targets` object. | ||
| Therefore, a `TargetFramework` that includes a `/` will cause parsing challenges. | ||
| NuGet's libraries could attempt to do the split on the last `/` character. |
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.
Considering the assets file has an entry for the ridless target, in addition to the per-rid targets, I think it would be challening to tell the difference between the two.
If the parser keeps raw strings in memory and then parses the alias/rid only once all targets are parsed from json, then you can find what the max number of / are, and assume the ridless has n-1.
But I think it's easier if we fail restore if the alias has a /. It's easier to block first and later allow, than the other way around.
Since we're already incrementing the version number, I think it'd be ideal if we could make another breaking change to the format, so instead of
"targets": {
"alias" : { },
"alias/rid": { }
}we could instead have
"targets": {
"alias": {
"": { },
"rid": { }
}
}But I suspect this might be a lot harder to implement.
However, as is pointed out just below, the target alias is used as the directory name for the obj and bin directories, and / is a directory separator, so I think that's another reason we could just block / from the alias
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.
Yeah, I'd be fine with blocking that yeah.
Honestly, I can't image this to be a super critical scenario that would need to be addressed.
The more changes we make, the higher the risk of the change anyways.
accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md
Outdated
Show resolved
Hide resolved
Fixes # ### Context Design: NuGet/Home#12124 To allow duplicate frameworks in aliasing, the project reference protocol nearest framework selection needs to be updated to support matching by alias as well. Relevant part: https://github.com/NuGet/Home/blob/dev-nkolev92-tfmaliases/accepted/2025/Multiple-Equivalent-Framework-Support-TFM-As-Aliases.md#project-to-project-references NuGet/NuGet.Client#7011 NuGet.Client side adding the parameter. NuGet/NuGet.Client#6972 will add the full implementation at a later point. ### Changes Made - Pass CurrentProjectTargetFrameworkProperty if GetReferenceNearestTargetFrameworkTaskSupportsTargetFrameworKPropertyParameter is set. - If GetReferenceNearestTargetFrameworkTaskSupportsTargetFrameworKPropertyParameter is not set, but GetReferenceNearestTargetFrameworkTaskSupportsTargetPlatformParameter is set, call the old variation. - Otherwise calls the last variation. ### Testing - Manual testing. - I'd be happy to add tests if someone can point me in the right direction. ### Notes The idea here is to get ahead of things. Currently aliasing work can't be end to end tested because it requires an msbuild change. It makes it really hard to validate the NuGet changes are enough and good, but this is the only change needed on the msbuild side. --------- Co-authored-by: Copilot <[email protected]>
Design for #5154
Rendered
cc @dsplaisted