Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Scenario 1
A project has multiple target framework aliases that resolve to the same effective framework, and pack can't determine which alias should contribute build output, dependencies, or framework references to the package.
Issue
A project like the following has two aliases (apple and banana) that both resolve to net10.0:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>apple;banana</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
<TargetFrameworkMoniker>.NETCoreApp,Version=v10.0</TargetFrameworkMoniker>
</PropertyGroup>
</Project>
When you run dotnet pack, NuGet raises NU5051 because it can't include duplicate build output or dependency groups for the same framework in a single package.
Solution
Set IncludeBuildOutput to false and SuppressDependenciesWhenPacking to true on all but one alias per effective framework. This tells NuGet which alias contributes the build output and dependencies.
<!-- Let 'apple' contribute the build output and dependencies -->
<PropertyGroup Condition="'$(TargetFramework)' == 'banana'">
<IncludeBuildOutput>false</IncludeBuildOutput>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
</PropertyGroup>
If the aliases have different FrameworkReference items, use PrivateAssets="all" on the framework references in the secondary aliases to suppress them from the package.
Scenario 2
A project has aliases for runtime-specific builds and wants to place each alias's build output into a custom package path (for example, runtimes/<rid>/lib/<tfm>/).
Issue
A project like the following has net10.0 as the primary alias and linux and ios as secondary aliases. All three resolve to the same effective framework:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net10.0;linux;ios</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'linux' OR '$(TargetFramework)' == 'ios' OR '$(TargetFramework)' == 'net10.0'">
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
<TargetFrameworkMoniker>.NETCoreApp,Version=v10.0</TargetFrameworkMoniker>
</PropertyGroup>
</Project>
Running dotnet pack raises NU5051 because three aliases produce build output and dependencies for the same framework.
Solution
Suppress the default build output and dependencies for the secondary aliases, and use TargetsForTfmSpecificContentInPackage to place the secondary aliases' assemblies into custom package paths:
<PropertyGroup>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);GetMyPackageFiles</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'linux' OR '$(TargetFramework)' == 'ios'">
<IncludeBuildOutput>false</IncludeBuildOutput>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
</PropertyGroup>
<Target Name="GetMyPackageFiles">
<ItemGroup Condition="'$(TargetFramework)' == 'linux' OR '$(TargetFramework)' == 'ios'">
<TfmSpecificPackageFile Include="$(OutputPath)$(AssemblyName).dll">
<PackagePath>runtimes/$(TargetFramework)/lib/net10.0</PackagePath>
</TfmSpecificPackageFile>
</ItemGroup>
</Target>
With this configuration, net10.0 contributes the default lib/net10.0/ build output and dependencies, while linux and ios place their assemblies under runtimes/linux/lib/net10.0/ and runtimes/ios/lib/net10.0/ respectively.
For more information about multi-targeting with duplicate frameworks, see Targeting multiple frameworks. For more information about pack extensibility, see pack target.