dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.96k stars 4.65k forks source link

RID specific assets in component dependency resolution on self-contained apps #3659

Open vitek-karas opened 5 years ago

vitek-karas commented 5 years ago

The scenario is using AssemblyDependencyResolver to dynamically load a component when running in a self-contained app.

The component can be portable, that means it has all necessary assets for all platforms included in it. It's .deps.json will have runtimeTarget sections which will describe which assets are to be used by which RID. For example it might have a native mycode.dll for Windows and libmycode.so for Linux.

In order for the dependency resolution to work correctly it needs to have a RID fallback graph. That is a data structure which describes how the various RIDs fallback. So for example it states that win10-x64 falls back to win-x64. That means that if we're running on win10-x64 and there are no win10-x64 specific assets, as a next step look at win-x64 assets and use those if available.

For applications the RID fallback graph is read from the Microsoft.NETCore.App.deps.json which is part of the Microsoft.NETCore.App framework. The RID fallback graph is only needed for portable apps and those must be framework dependent.

Self-contained apps are always RID specific and thus they only contain assets for the target RID. The RID resolution is performed at build time by the SDK/NuGet. So the .deps.json of a self-contained app does not include the RID fallback graph.

When AssemblyDependencyResolver is used it takes the RID fallback graph from the app. For framework dependent apps that will come from the core framework and everything works. But for self-contained apps, there's no RID fallback graph in the app. The result is that portable components don't work well when hosted by self-contained apps.

There's currently no workaround as there's no way to make SDK include the RID fallback graph in self-contained apps and similarly the component can't carry the RID fallback graph with it.

vitek-karas commented 5 years ago

The proposed solution is to include the RID fallback graph in self-contained app's .deps.json so that it can act as the root framework.

See the SDK issue for this: https://github.com/dotnet/sdk/issues/3361

eerhardt commented 5 years ago

See also https://github.com/dotnet/core-setup/issues/1846 for a related proposal - The dotnet host should respect a RID graph from an app's .deps.json.

vitek-karas commented 5 years ago

@eerhardt I am aware of that one - it's related but not quite the same. In this case there's no RID graph at all, so it's really just a matter of taking the RID graph from the app instead of a framework - in fact the host change is trivial, the meat of the change is in the SDK to actually bake the RID graph into the app's .deps.json in this case.

In dotnet/runtime#2663 it becomes a little trickier as we would have to somehow merge two graphs - one potentially coming from the framework and another from the app. Maybe it's trivial (we use the app, and if that doesn't work, we use the framework, or something like that) - but it's a little bit more complex problem. There's also no good authoring story - other than .runtimeconfig.template.

But I definitely see value in both.