8

I'm using dotnet pack command for creating a NuGet package for the following scenario:

The projects structure:

Project B
|----> Project A

Project A
|----> SomePackage

I want to create a single NuGet package the contains ProjectB.dll, ProjectA.dll, and SomePackage as NuGet package dependency.

In order to include ProjectA.dll as part of the NuGet package (and not package dependency), I used the following solution that suggests here.

In ProjectB.csproj:

  <ProjectReference Include="ProjectA.csproj" PrivateAssets="all"/>

  <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>

The issue:

When I run dotnet pack ProjectB.csproj I'm getting a single package the contains ProjectA.dll and Project B.dll, but without a dependency to SomePackage.

The question: How do I add the dependency to SomePackage to ProjectB NuGet package?

Possible solutions:

  1. Manually add a package reference from ProjectB to SomePackage.
  2. Create ProjectB.nuspec file and manually add the dependency to SomePakcage.

The disadvantage of the 2 approaches: I will need to add the dependency for every NuGet package that ProjectA use, which is very easy to forget and breakable.

Mr Qian
  • 21,064
  • 1
  • 31
  • 41
itaiy
  • 1,152
  • 1
  • 13
  • 22

1 Answers1

0

You have used PrivateAssets="all" for Project A which means that its transitive dependencies are private and cannot be access by the main Project B. We usually use it to disable the dependencies of referenced projects.

So if you use that, you cannot get the transitive dependencies from the referenced projects. And it will make Project A as a assembly dll and will make it lose the ability of nuget package and its transitive dependencies.

If you still want to achieve the goal, you should note these:

1) directly copy the transitive dependencies like PackageReference node from Project A's csproj into Project B's csproj.

 <PackageReference Include="SomePackage" Version="*.*.*" />

   ......

In this case, you do not have to use ProjectB.nuspec or nuget package manager UI.

2) Give up using PrivateAssets="all" for Project A and make Project A as a nuget package. Ensure the integrity of its nuget features.

Apart from this, there is no other way.

Mr Qian
  • 21,064
  • 1
  • 31
  • 41
  • Thank you for your answer. I want to use `PrivateAssets="all"` because I need to create only single NuGet package with all the project references and all the package dependencies. Option 1 is the same as I mentioned, the big disadvantage that in my case the example is more complex, I have more project reference with ~20 package references from the all the project references, which mean a lot of manual work + very easy to forget dependency and create faulted NuGet package (Can be detected only in runtime) – itaiy Dec 29 '20 at 07:45
  • + You are correct that option 2 is also a good solution, but I don't want to expose to my users all the project reference as NuGet packages, I need only a single NuGet package. – itaiy Dec 29 '20 at 07:49
  • Sure. To solve it, you have to directly copy the `PackageReference` node of referenced `Project A` into `Project B`. After all, `Project A`, the middle bridge, has lost its Nuget feature, so you must add its dependency nodes to `Project B`. In order to do that, you have to do this. – Mr Qian Dec 29 '20 at 08:34
  • That why I look for an easy solution to add all the dependencies automatically like the solution that copy all the project references dlls. If I had a list of all the NuGet dependencies of all the project references, this could help. – itaiy Dec 29 '20 at 08:36
  • Directly copy the `PackageReference ` node from Porject A into Project B, and then it will automatically install the nuget packages at one time on Project B, – Mr Qian Dec 29 '20 at 08:38
  • As I mentioned before, the only problem with it, that if someone adds another dependency to project A in the future, without adding it to Project B, we will get a faulted NuGet package that only on runtime we will get an exception for MethodNotFound or something like this. This solution is very breakable. – itaiy Dec 29 '20 at 08:49
  • Thanks for sharing the info. Hum. I am not sure if there is a function to realize that. Maybe not. In the follow-up, you can use `Manage Nuget packages for Solution`. Right-click on the solution-->`Manage nuget packages for Solution`. This will let the nuget package be installed both on the two projects. – Mr Qian Dec 29 '20 at 09:33