Search code examples
.netcross-platform

Target dotnet project for net8.0 and net8.0-windows


I have an executable that needs to be compatible with Linux and Windows. One specific functionality uses a 3rd party library that needs Winforms, so it needs a Windows target framework. I can just disable that functionality on a Linux build.

I've separated that functionality into a separate library project, with net8.0-windows as target framework.

In my executable I have a conditional project reference that only references the Windows-library if the OS is Windows:

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <Optimize>true</Optimize>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <ErrorReport>prompt</ErrorReport>

    <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
    <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
</PropertyGroup>

<ItemGroup Condition="'$(IsWindows)'=='true'">
    <ProjectReference Include="..\WindowsLibrary.csproj" />
</ItemGroup>

The problem I have is with the target framework. I would think I need to specify both supported target frameworks:

    <TargetFrameworks>net8.0;net8.0-windows</TargetFrameworks>

In my CI/CD pipeline I would then pass the target framework with the -f option on dotnet publish.

But I don't get this to work. It seems to always build with net8.0, then complaining that the Windows library is not compatible.

I've added this to the project file of the executable, to print the target framework used:

<Target Name="Print used target framework" BeforeTargets="CollectPackageReferences">
    <Message Importance="High" Text="TargetFramework: $(TargetFramework)" />
</Target>

This is the command I use and the output:

dotnet publish .myapp.csproj --configuration Release -f "net8.0-windows" --runtime win-x64 --output ./MyApp --no-self-contained

MSBuild version 17.8.3+195e7f5a3 for .NET
  Determining projects to restore...
  TargetFramework:
  TargetFramework: net8.0
  TargetFramework: net8.0-windows
C:\myapp.csproj : error NU1201: Project WindowsLibrary is not compatible with net8.0 (.NETCoreApp,Version=v8.0). Project WindowsLibrary supports: net8.0-windows7.0 (.NETCoreApp,Version=v8.0)
C:\myapp.csproj : error NU1201: Project WindowsLibrary is not compatible with net8.0 (.NETCoreApp,Version=v8.0) / win-x64. Project WindowsLibrary supports: net8.0-windows7.0 (.NETCoreApp,Version=v8.0)

So why does it keep trying to build for net8.0?


Solution

  • The key thing is making sure you have a Condition on either the individual element that adds this package, or the <ItemGroup> that contains it. This could be as simple as Condition="'$(TargetFramework)'=='net8.0-windows'"; you can do more complex and nuanced Condition constructions, but it quickly gets hard to be sure whether something is included or not.