Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nuget Pack multiple projects into single Nuget package with all external dependencies

I am looking to create a single nuget package out of multiple .csproj.

Ex: I have two .csproj, one of them having dependency on other external packages such as NewtonSoft.

dotnet new classlib -o ClassLibrary1
dotnet new classlib -o ClassLibrary2
cd ClassLibrary1
dotnet add package Newtonsoft.Json

I am looking to publish a single nuget package which contains both ClassLibrary1.dll and ClassLibrary2.dll and resulting .nuspec have dependency Newtonsoft.Json listed.

I tried doing something like this: Created a dummy .csproj and added references to ClassLibrary1 & 2 and created a nuget package with -IncludeReferencedProjects: Ex:-

dotnet new classlib -o dummyNuget
dotnet add reference ClassLibrary1.csproj
dotnet add reference ClassLibrary2.csproj
nuget pack dummyNuget.csproj -IncludeReferencedProjects

it produces below .nuspec file , missing the NewtonSoft Dependency.

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>dummynuget</id>
    <version>1.0.0</version>
    <authors></authors>
    <description>Description</description>
    <dependencies />
  </metadata>
</package>

Any ideas? how to create a single nuget package with -IncludeReferencedProjects and all the dependencies listed.

Sample Github Repo to quickly reproduce the issue : https://github.com/vivekscripts/TestNugetPack/tree/main

I know common approach would be to first combine the source files into a single project and thus use dotnet pack to publish a single package but lets say that option is not available easily due to cross team dependencies.

like image 504
VJSharp Avatar asked Oct 21 '25 10:10

VJSharp


1 Answers

You can achieve this with "dotnet pack" with a bit of hackery.

For this scenario, in PowerShell, I ran the following to create the (3) projects, add project references, and to also add a Nuget reference to NewtonSoft.Json.

# Create projects
dotnet new classlib -o ClassLibrary1
dotnet new classlib -o ClassLibrary2
dotnet new classlib -o dummyNuget

# Add references
dotnet add dummyNuget reference ClassLibrary1
dotnet add dummyNuget reference ClassLibrary2
dotnet add dummyNuget package Newtonsoft.Json
dotnet add dummyNuget package Nuget.Build.Tasks.Pack

# Create nuget package
dotnet build dummyNuget

After creating these projects, you have to modify the *.csproj ProjectReference entries to include "PrivateAssets."

  <!-- To ensure project refernece DLLs are included, must set PrivateAssets="All" -->
  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" PrivateAssets="All" />
    <ProjectReference Include="..\ClassLibrary2\ClassLibrary2.csproj" PrivateAssets="All" />
  </ItemGroup>

And next comes the hackery bit. This section can be added to the project to ensure the DLLs from the ProjectReferences get included int he lib/net6.0 folder of the nuget package.

<!-- Fix for dotnet pack not including private (project) references -->
  <PropertyGroup>
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
  </PropertyGroup>

  <Target Name="CopyProjectReferencesToPackage" DependsOnTargets="BuildOnlySettings;ResolveReferences">
    <ItemGroup>
      <!-- Filter out unnecessary files -->
      <_ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"/>
    </ItemGroup>

    <!-- Print batches for debug purposes -->
    <Message Text="Batch for .nupkg: ReferenceCopyLocalPaths = @(_ReferenceCopyLocalPaths), ReferenceCopyLocalPaths.DestinationSubDirectory = %(_ReferenceCopyLocalPaths.DestinationSubDirectory) Filename = %(_ReferenceCopyLocalPaths.Filename) Extension = %(_ReferenceCopyLocalPaths.Extension)" Importance="High" Condition="'@(_ReferenceCopyLocalPaths)' != ''" />

    <ItemGroup>
      <!-- Add file to package with consideration of sub folder. If empty, the root folder is chosen. -->
      <BuildOutputInPackage Include="@(_ReferenceCopyLocalPaths)" TargetPath="%(_ReferenceCopyLocalPaths.DestinationSubDirectory)"/>
    </ItemGroup>
  </Target>
  <!-- End of dotnet pack fix -->

With those changes in place, we can run dotnet pack to get the nuget package with proper dependencies referenced and with local dependencies in the lib folder:

dotnet pack dummyNuget\dummyNuget.csproj

I used these two links as guides, btw:

https://josef.codes/dotnet-pack-include-referenced-projects/

https://dev.to/yerac/include-both-nuget-package-references-and-project-reference-dll-using-dotnet-pack-2d8p

like image 120
long2know Avatar answered Oct 25 '25 09:10

long2know



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!