NuGet / Home

Repo for NuGet Client issues
Other
1.5k stars 252 forks source link

dotnet pack does not respect target framework conditions #12169

Open ViktorHofer opened 2 years ago

ViktorHofer commented 2 years ago

Issue opened by @paatrofimov and migrated over from https://github.com/dotnet/runtime/issues/77164

Description

I have multitargeted csproj and I want to build and pack only the single target but dotnet pack always ignores passed configuration and packs all targets.

Reproduction Steps

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
        <Configurations>Net6;Netstandard20</Configurations>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)' == 'Net6'">
        <TargetFramework>net6.0</TargetFramework>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)' == 'Netstandard20'">
        <TargetFramework>netstandard2.0</TargetFramework>
    </PropertyGroup>

</Project>

The following command dotnet pack -c Netstandard20 results in error C:\Program Files\dotnet\sdk\6.0.201\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(221,5): error NU5026: The file 'E:\cm_1\drive\TestApp\bin\Netstandard20\net6.0\TestApp.dll' to be packed was not found on disk. [E:\cm_1\drive\TestApp\TestApp.csproj] because net6.0 configuration was not built and folder net6.0 is empty indeed.

I also tried to publish before packing (without build), but dotnet pack still does not seem to respect passed configuration.

  1. dotnet publish -c Netstandard20 - this command builds requested configuration and publishes it to bin\Netstandard20\netstandard2.0\publish.
  2. dotnet pack --no-build /p:OutputPath=bin\Netstandard20\netstandard2.0\publish\ - and this command produces nuget package which containts both folders lib\net6.0 and lib\netstandard2.0 with same published binaries which also looks incorrect since I wanted to publish and pack only netstandard2.0 configuration

Expected behavior

dotnet pack -c Netstandard20 to pack only the requested configuration and not try to do anything with the net6.0 target.

Actual behavior

dotnet pack -c Netstandard20 builds and packs all configurations listed in TargetFrameworks even though the following csproj conditions constrain the build only to the single target for passed configuration.

Regression?

No response

Known Workarounds

Can't figure out any, but would be glad if any would be suggested.

Configuration

No response

Other information

No response

ViktorHofer commented 2 years ago

This simplified code should work:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks Condition="'$(PackTargetFramework)' == ''">net6.0;netstandard2.0</TargetFrameworks>
    <TargetFramework Condition="'$(PackTargetFramework)' != ''">$(PackTargetFramework)</TargetFramework>
  </PropertyGroup>

</Project>

And then pass in the PackTargetFramework property when via the msbuild property syntax: dotnet pack /p:PackTargetFramework=netstandard2.0.

Note that I don't use Configuration for that as Configurations don't correlate to build nodes.

ghost commented 2 years ago

Issue is missing Type label, remember to add a Type label

nkolev92 commented 2 years ago

TargetFrameworks tends to be preferred over TargetFramework, which is what's happening here.

I'd recommend not mixing TargetFramework and TargetFrameworks declaration, and ideally use one.

Another workaround is:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
        <Configurations>Net6;Netstandard20</Configurations>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)' == 'Net6'">
        <TargetFrameworks>net6.0</TargetFrameworks>
    </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)' == 'Netstandard20'">
        <TargetFrameworks>netstandard2.0</TargetFrameworks>
    </PropertyGroup>

</Project>