-
Notifications
You must be signed in to change notification settings - Fork 162
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
Add special case for Xamarin assets to nuget precedence rules #222
Conversation
Does this affect just this assembly or are there other cases where Xamarin frameworks included out-of-band assemblies in-box? I don't think it would be good to set a precedent of special-casing individual assemblies in the precedence rules. Perhaps we could generalize this by having the If we choose to go the route of updating the affected packages, we should consider adding a warning when affected projects directly or indirectly reference the old versions of the packages. |
It affects these assemblies/packages:
Sorry if this wasn't clear but my proposal was about making this a generalized rule like you described. |
Another thing that we noticed which would not be fixed by this proposal is that with the current precedence rules you also get transitive dependencies for the This manifests itself when referencing e.g.
i.e. unnecessary |
cc @joperezr since he was on the email. |
So NuGet selects the TFM for dependencies independently of selecting the TFM for assets? I don't know how hard it would be to change that, either in the general case or for this specific pattern. @nkolev92 ? Maybe it's okay to special case the package names, given it's a small and limited set and this is an exceptional scenario. |
Here's another case where we run into issues now due to nuget picking netcoreapp assets instead of netstandard: xunit/xunit#2314 I'm starting to wonder whether we should tweak the rules to prefer netstandard assets before netcoreapp <= 5 assets, since these earlier netcoreapp assets could've justifiably made the assumption that they're running on "desktop" .net core. |
This is a known behavior. There's a lot of packages that author their assets correctly, but don't use dependency groups for their dependencies. I'd really prefer us to update the packages, as that change would be error prone and pretty difficult to follow. |
So to summarize I think there are three issues right now:
|
FWIW I'm doing this in dotnet/runtime#53439 but that will only cover packages that we build live. cc @ericstj |
And only those that happen to have a |
Existing Xamarin will still be supported for quite some time (https://dotnet.microsoft.com/platform/support/policy/xamarin) so removing the placeholders would break the packages for them. |
Unless conflict resolution worked for them like it does for .NETCore and .NETFramework (where we have packages that overlap with shared framework and "best" wins). Not sure what the state of this is: do you know? |
Just so this PR contains all the suggested changes talked about, should we also introduce the ideal precedence order into the PR as it sounded like @Redth and @mattleibow saw some inconsistencies with this already? Is there a proposal on how to resolve the precedence issues here? If You can use a tool like https://nugettoolsdev.azurewebsites.net/5.10.0-preview.2.7185/framework-precedence to check out existing precedence rules. /cc @davidortinau |
@ericstj how exactly does this work? I can't think why it should be any different for ios/android, |
When there are two sources of the same binary it tries to decide which is better based on higher version. Reasons it could be different: if the build for these frameworks doesn't use these targets, if the files are not visible to the build (like the runtime packs in core that have to be represented in manifests passed to the resolver), or if for some reason the framework files should be better (eg more API, specialized implementation) but have a lower version than the package. You can try this out pretty easily by modifying the packages locally (deleting the placeholders in both the nupkg) and seeing how it works. |
Ah, it's a related problem but kinda the inverse? The problem here is that the fallbacks are causing the package to resolve to a TFM where the assets are in the framework, but in the current TFM they aren't in the framework and instead need to come from the package. So no assets are resolved at all and there is no conflict to be resolved. |
I'm discussing what can be done to fix those no assets cases: we can just remove placeholders from the packages and let things apply. Conflict resolution can make those additional assets a non-issue on the frameworks where they exists (Xamarin* frameworks). IOW: conflict resolution works better and replaces the uses of placeholder files. |
Oh, I wasn't aware the conflict resolution targets were available for non-SDK style projects. It looks they get conditionally imported for Unfortunately it doesn't look like Assuming we can make this work, it does seem like the best option. We should maybe consider guard rails for folks updating their NuGet references on older versions of Xamarin? |
@JonDouglas here's what I believe the precedence rules should really look like if we want to support the cases where packages expected net5.0/netcoreapp3.1-1.0 to run on desktop/coreclr and that netstandard2.1-1.0 would be selected in xamarin/mobile scenarios:
|
Do we have the full list of affected packages? Presumably most of those don't exist in dotnet/runtime's main branch anymore or don't generate a package anymore as configurations were removed. |
@ViktorHofer I posted the list of packages that run into the I'll update the proposal to include the precedence of netcoreapp vs. netstandard changes as those likely affect a lot more packages. |
Asking you mentioned that this list might not be complete:
|
I asked @Redth about precedence here based on the second point in this comment. |
@akoeplinger @ericstj as I see it we have three options:
|
@mhutch yup, that's true for solving the |
I really think the precedence discussion belongs in another issue. However, here's my read of the situation: AFAICT the only advantage of preferring
However, it will result in inferior assets being selected for "Type 2" packages, for which all the following are true:
And it will break valid "Type 3" packages for which all the following are true:
We don't know the relative numbers of these different types, nor do we know what proportion of type 1 packages would actually be fixed by the precedence change. It would also introduce a massive inconsistency into the precedence. |
I've to strongly agree with @mhutch here that it would be very weird if changing TFM from |
@mhutch Actually there is some conflict resolution logic already. It was recently broken too (dotnet/macios#10928). Look for *FrameworkList.xml.in files in https://github.com/xamarin/xamarin-macios/. This is already used for System.Buffers/System.Memory and similar assemblies to let the framework implementation win over the NuGet one. |
I actually tend to agree that the precedence rules are correct as currently designed, and not the ones I suggested in my last comment to collect more evidence of the correct decision either way. The unfortunate reality with the current rules is that many packages will need updating. Some of these are more impactful due to their prevalence in the ecosystem (xUnit for instance). Is there anything else we can do for the user experience here when this is encountered? Is there a way for consumers of packages in this scenario to work around it? I want to be sure this scenario is well understood and messaged appropriately /cc @terrajobst @richlander @davidortinau |
@Redth re. third party libraries, maybe NuGet should emit a warning when resolving there isn't really much else we can do. we could statically determine some broken cases but that would be too expensive to do on restore or build and wouldn't catch everything. perhaps we could have the linker validate the platform checks and warn if unavailable APIs are found to be reachable? it would be a bit late in the dev cycle (especially for android, where linking may not happen till publish) but better than nothing. it would also be a generalized feature that would be useful long after any of this ceases to be an issue. AFAIK there's no way to override the framework NuGet resolves for a package. it would definitely be a nice feature to have and would make problems like this actionable. i image it would mesh nicely with a generalized graph override capability. re. the framework assemblies that moved out of box, I think all we can do is detect the unfixed versions of these specific packages and emit a build error instructing the developer to update those packages. maybe we could have a nuget feature where the targets could instruct NuGet to force package references to a minimum version if found anywhere in the graph e.g. something like |
@filipnavara @ericstj ah, my bad, looks like we do in fact ship the conflict resolution targets on Mac and have enabled them unconditionally for all Xamarin frameworks since late 2018. We'd have to dig up some older versions of Xamarin and test it works correctly for all these packages, but maybe it's safe to just remove all those We'd still need the warning when using non-updated versions of those packages from |
I think for fixing the Warning when restoring
Yeah I think giving users an escape hatch to override might be a good compromise, basically something similar to |
Having the "override asset" feature would actually allow us to solve the <PackageReference Update="System.ComponentModel.Composition" Condition="Version == 5.0.0">
<AssetTargetOverride>netcoreapp3.1</AssetTargetOverride>
</PackageReference> |
Just to circle back and re-iterate on a potential consensus of the initial 3 issues & what's been discussed thus far:
Does this sound right? If so, I propose we find some owners for the various items above & work to close out this PR if there's nothing in addendum to precedence rules. |
It sounds good to me, however we'd need the asset override nuget feature to make it a good experience. @JonDouglas @nkolev92 how hard do you think that would be to implement? |
It's non trivial as NuGet does asset selection per asset group + the fact that we'd need to consider what this means upstream for consumers of the project in question, be it as a projref or packref. |
Conditionally applying metadata to I think my |
The NuGet Client team had been working on a Central Package Version Management feature, when we had fewer urgent tasks, but currently it doesn't make the cut when prioritized given our resources. Anyway, it contains a "transitive package pinning" feature, which we should use, once implemented, rather than providing another syntax. However, it took months to prototype, and once released, library authors immediately hated it given it's impact on pack & package dependencies, plus it broke features such as |
Ok so it seems the consensus is that we shouldn't do this 😃 We'll be doing this instead:
|
Correct me if I'm wrong but dotnet/runtime#54012 won't help with this in any way. None of the libraries mentioned above are part of the work tracked in that issue. |
Talked with Viktor offline, here's the status for the packages:
The following packages however are not building in dotnet/runtime main anymore and are basically deprecated:
From talking to @ViktorHofer we don't service these packages anymore so we need to work with package owners to remove their dependencies on these packages. |
ABANDONED, see #222 (comment)
While working on .NET 6 support for Xamarin we hit a build break in a test project when referencing the System.ComponentModel.Composition v4.7.0 nuget package.
We've tracked it down to the nuget restore storing this in obj/project.assets.json:
I.e. it wants to pick the assembly from the GAC/framework, which is what we want for the legacy Xamarin (since System.ComponentModel.Composition shipped in the framework there) but not for the new .NET6-based one since it is an out-of-band package there and doesn't ship in the framework.
We're proposing an addition to the nuget precedence rules to skip the Xamarin TFM asset in this case, so we fallback to the netcoreapp2.0 assembly.
The other alternative would be to add an explicit
net6.0
asset to the package, however this would only apply to new releases since we can't fix the existing nugets.Note: we discovered additional issues while working on this, see #222 (comment) so we're also proposing to change the precedence rules to prefer
netstandard
assets beforenet5.0
/cc @marek-safar @ericstj @rolfbjarne