NuGet/Home

Feature Request: Allow architecture-specific binaries without requiring client projects to use RuntimeIdentifier(s)

davidmatson opened this issue · 11 comments

When to use Platforms vs PlatformTarget vs RuntimeIdentifier(s) is a bit messy at the moment. (For more context: dotnet/sdk#1553)

In the meantime, while we're waiting on guidance/cleanup there, we usually use only Platforms or PlatformTarget to mark a binary as x64.

We have NuGet packages used by these projects that have x64-only binaries in them. The only current way I can find to provide these native binaries in a NuGet package and have them show up in bin (well, apart from a custom target file) is to use the "runtimes" folder:
https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks

And have a subfolder named something like win-x64.

However, it looks like NuGet does not include these binaries in your client projects unless they also set RuntimeIdentifier(s). Perhaps this is related to the "win-" part of the architecture-specific folder. Can we provide a way to do architecture-specific folders that are not also platform-specific? Perhaps something like:

runtimes\{architecture}\native

or for example:

runtimes\x64\native\foo.dll

in addition to the existing:

runtimes\{platform}-{architecture}\native

or for example:

runtimes\win-x64\native\foo.dll

Changes on the project system/SDK side are another potential solution here, though that seems a ways off at the moment.

How is NuGet supposed to know whether to include these assets if it doesn't know the target runtime?

If the csproj says TargetPlatform=x64 and the nupkg says "include this file in bin when building for x64", then it would know to include it. I believe NuGet knows (or could know) the TargetPlatform - is that correct?

@davidmatson
It can figure it out yes, but that wouldn't solve the Platforms vs PlatformTarget vs RuntimeIdentifier problem.
It would just move it to NuGet in addition to SDK.

In my opinion, NuGet should not do anything until dotnet/sdk#1553 is resolved, and then act potentially if there's a change/unification on the SDK side.

//cc @rrelyea @dsplaisted

I think the way to handle this would be to have architecture-specific but platform-agnostic Runtime Identifiers. Essentially, x86, x64, arm, and arm64 would be added to the RID Graph.

I'm not sure if this is feasible. @weshaggard @ericstj

Understood. The one thing that makes we wonder if we should do something in the meantime, is that currently it's the only reason I'd set RuntimeIdentifier(s) in multiple client csprojs - NuGet is taking a dependency on RuntimeIdentifier being set in cases where the rest of the project system is satisfied by Platforms/PlatformTarget. i.e. - is NuGet making this problem worse than the rest of the SDK makes it.

@dsplaisted - I think that's one option. Another one might be to infer a platform of "win" when the csproj targets .NET Framework (rather than .NET Standard or .NET Core).

(I believe .NET Framework is always Windows - is that right?)

@davidmatson Mono also uses the .NETFramework TargetFrameworkIdentifier

Interesting. What does Mono correspond to from a runtime identifier standpoint? (It doesn't look like there's a Mono platform - does it use one of the Linux ones?)

Also, when a Windows box compiles with PlatformTarget=x64 and TargetFramework=net471, does that always means it's targeting Windows specifically anyway (regardless of whether a runtime identifier is set)? In other words, for .NET Framework, does the machine doing the build determine what platform is to be supported (perhaps only for non-Any CPU PlatformTargets)?

However, it looks like NuGet does not include these binaries in your client projects unless they also set RuntimeIdentifier(s).

I know the SDK does things a bit differently but FWIW non-SDK projects do get something close to this behavior: https://github.com/NuGet/NuGet.BuildTasks/blob/dev/src/Microsoft.NuGet.Build.Tasks/Microsoft.NuGet.targets#L90-L96

I'm not opposed to adding OS-agnostic RIDs (eg: for Architecture specific IL) but I wouldn't recommend that for native binaries. Regardless, that's a bit of a side-track from the main issue which is communicating some platform to NuGet by default.

Also, when a Windows box compiles with PlatformTarget=x64 and TargetFramework=net471, does that always means it's targeting Windows specifically anyway (regardless of whether a runtime identifier is set)?

I would like to know this also. There doesnt seem to be any direction on how to handle combinations of bitness and target frameworks in the same package.

I agree this should be built-in to NuGet. In the interim, my MSBuild.Sdk.Extras allows you to build/package NuGet packages that contain ref and runtimes:

https://github.com/onovotny/MSBuildSdkExtras#rids

You can set RuntimeIdentifiers per TFM turn on the per-RID builds with a property, and it'll do the right thing.