Background - My Build Scripting
I would like to use the dotnet CLI to create a nuget package that can target the following frameworks: net462
, net48
, net8.0
. My library has no dependencies (i.e. it doesn't require any other NuGet packages or projects).
I have written a powershell build script that builds my library such that three DLLs are created. The relevant part of the build script is included below:
dotnet build TestCI.sln -c "net462" -f "net462" -p:Platform=x64 -p:Version=$($MAJOR_MINOR_PATCH) --no-restore --disable-build-serversdotnet build TestCI.sln -c "net48" -f "net48" -p:Platform=x64 -p:Version=$($MAJOR_MINOR_PATCH) --no-restore --disable-build-serversdotnet build TestCI.sln -c "net8.0" -f "net8.0" -p:Platform=x64 -p:Version=$($MAJOR_MINOR_PATCH) --no-restore --disable-build-servers
This results in the following folder structure:
bin|-- net8.0-x64|-- |-- TestCI.dll|-- net48-x64|-- |-- TestCI.dll|-- net462-x64|-- |-- TestCI.dll
When decompiled with DotPeek, I can see that each DLL contains:
- The information from my .csproj that I would like/expect to see
- The proper target framework versions and runtime identifiers
So far, so good.
The Goal - A NuGet Package for Multiple Framework Targets
I would like to package these three DLLs into a single nuget package that can be deployed to net462
, net48
, and net8.0
runtimes, using only my SDK-style .csproj
file and the CLI.
The Problem - Versioning Upon Packaging
My long-term goal is to automate the building and packaging of this library (and others) using GitHub actions - hence the scripting. However, ehcin I run the following dotnet pack command:
dotnet pack TestCI\TestCI.csproj -p:PackageVersion=$($MAJOR_MINOR_PATCH) --no-restore --no-build
The resulting NuGet package contains DLLs that all specify net8.0
as the target framework. The f
TestCI.nupkg|-- lib|-- |-- net462|-- |-- |-- TestCI.dll|-- |-- net48|-- |-- |-- TestCI.dll|-- |-- net8.0|-- |-- |-- TestCI.dll
However when inspecting each DLL, they all contain the following line, regardless of the lib subdirecotry:
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
I.e. there doesn't appear to be a difference between the DLLs packged despite the fact that I know that each DLL was built to a different target framework, and have confirmed this on each DLL in the bin
directory.
So Far, I've Tried...
So far, I've tried several variations of the dotnet pack command, even including a rudimentary nuspec file:
dotnet pack TestCI\TestCI.csproj -p:PackageVersion=$($MAJOR_MINOR_PATCH) -p:NuspecFile=.nuspec --no-restore --no-build
(see this post on multi-targeted nuget packages)
This works, however I don't like this soltuion for the following reasons:
- The package version isn't properly applied to this package (results in 0.0.0), and I require the ability to control versioning information for CICD purposes.
- I would prefer to keep everything contained in my SDK-style
.csproj
file to keep my repository cleaner and simpler.
I've also ensured that my .csproj
file contains the following element:
<TargetFrameworks>net462;net48;net8.0</TargetFrameworks>
The Asks
- Am I misunderstanding how .NET works? Am I needlessly complicating my workflow?
- Has anyone encountered a similar situation?
- Do I need to use a
.nuspec
file? - Is it possible to achive what I've described with only a SDK
.csproj
file and the CLI?
Edits
[2024-07-26]
- I am using JetBrains DotPeek to inspect the NuGet package
- The csproj file I am using is included below:
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><RootNamespace>TestCI</RootNamespace><Company>XYZ</Company><Copyright>XYZ (c) 2024</Copyright><Version>0.0.1</Version></PropertyGroup><PropertyGroup><TargetFrameworks>net462;net48;net8.0-windows</TargetFrameworks> <Configurations>net48;net462;net8.0-windows</Configurations><Platforms>x64</Platforms><PlatformTarget>x64</PlatformTarget><OutputPath>bin\$(Configuration)-$(Platform)\</OutputPath></PropertyGroup><PropertyGroup><ProductName>$(RootNamesapce)</ProductName><OutputType>Library</OutputType><IsTestProject>False</IsTestProject></PropertyGroup><PropertyGroup><PackageID>$(RootNamespace)</PackageID><PackageVersion>$(Version)</PackageVersion><IsPackable>True</IsPackable><IncludeBuildOutput>True</IncludeBuildOutput><GeneratePackageOnBuild>False</GeneratePackageOnBuild><PackageOutputPath>..\nupkg</PackageOutputPath><PackageDescription>XYZ</PackageDescription><RepositoryUrl>XYZ</RepositoryUrl></PropertyGroup><PropertyGroup><DefineConstants>TRACE;DEBUG</DefineConstants><DebugType>embedded</DebugType><OutDir>bin\$(Configuration)-$(Platform)</OutDir></PropertyGroup><PropertyGroup><GenerateAssemblyInfo>True</GenerateAssemblyInfo><AssemblyName>$(RootNamespace)</AssemblyName><AssemblyVersion>$(Version).0</AssemblyVersion><FileVersion>$(Version).0</FileVersion></PropertyGroup><ItemGroup><Compile Remove=".github\**" /><EmbeddedResource Remove=".github\**" /><None Remove=".github\**" /></ItemGroup></Project>