Search code examples
c#nuget

How do I target only the x64 version of a nuget package using centrally managed Nuget package versions?


We have a large solution (~400 C# projects) and are attempting to change the solution to use centralized package version management because things are quite messy. The final issue we need to address is a compilation error when referencing a specific multi-platform Nuget package (CefSharp.Wpf.NETCore and its ultimate dependency chromiumembeddedframework.runtime Directory.Packages.Props file this way:

<ItemGroup>
    ...
    <PackageVersion Include="CefSharp.Wpf.NETCore" Version="109.1.110" />
    <PackageVersion Include="chromiumembeddedframework.runtime" Version="109.1.11" />
    ...
</ItemGroup>

The project includes a package reference specified as:

<PackageReference Include="CefSharp.Wpf.NETCore" />
<PackageReference Include="chromiumembeddedframework.runtime" />

Note that we've tried referencing only CefSharp.Wpf.NETCore as well as the full chain of dependencies to Chromium Embedded Framework (CefSharp.Common.NetCore is in the middle). We have also tried referencing the specific CEF for the platform we are targeting (x64).

The project is targeting x64, so we have tried adding all of the target-specific dependencies and still have the error:

NU1008 Projects that use central package version management should not define the version on the PackageReference items but on the PackageVersion items: chromiumembeddedframework.runtime.win-arm64;chromiumembeddedframework.runtime.win-x86.

It appears that packages for other architectures are being added in at compile time and the build won't complete.

Minimal Example Using Visual Studio 2022 solution I can reproduce this problem with no code.

A simple project along with a directory.packages.props and a nuget.config (nuget.config is auto-generated) show it neatly. Project.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="CefSharp.Wpf.NETCore" />
  </ItemGroup>
</Project>

directory.packages.props

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
    <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="CefSharp.Wpf.NETCore" Version="109.1.110" />
    <PackageVersion Include="chromiumembeddedframework.runtime" Version="109.1.11" />
  </ItemGroup>
</Project>

Edit 1: the original issue only appeared to occur with the temporary project created for compiling XAML and since it had to do with package references my initial attempts to resolve it centered around the IncludePackageReferencesDuringMarkupCompilation property. This is not the case. The initial answers were for this problem but they made it clear I was asking the wrong question.


Solution

  • For the time being I have worked around this issue by explicitly adding all of the dependencies (for every target platform) to both the directory.packages.props file and the csproj file. Because I don't actually want the output to contain any dependencies other than x64 I have marked the other target platform dependencies as private so msbuild does not include them in the outputs.

    So, for my project that relies on CefSharp.Wpf.NETCore (which ultimately relies on the chromiumembeddedframework.runtime.win-x64) I have this grouping of PackageReference elements:

    <PackageReference Include="CefSharp.Wpf.NETCore" />
    <PackageReference Include="chromiumembeddedframework.runtime" />
    <PackageReference Include="chromiumembeddedframework.runtime.win-x64" />
    <PackageReference Include="chromiumembeddedframework.runtime.win-x86">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="chromiumembeddedframework.runtime.win-arm64">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    

    This solves the problem of the build failure and the problem in Visual Studio where the project package dependencies would constantly cycle from valid to invalid and back again. It also does not have the down side of including binaries I don't want in the build output. However, it seems like a bit of a hacky workaround.

    Edit: The problem appears to be related to discussion here and is because of the PackageReference elements in the buildTransitive/CefSharp.Common.NETCore.targets file (part of the CefSharp.Common.NETCore.nupkg). Might have to stick with the workaround.