Include all dependencies using dotnet pack

17,153

Solution 1

As of 2020 there is no officially supported way to do this. However various people have come up with ways to achieve it, and the current best way is to install a NuGet package prepared by the amazing Teroneko. Then all you need to do is edit your .csproj to update all your project to be flagged with PrivateAssets="all", as per the package README.


If you are unable to install the aforementioned NuGet package, you can achieve the same effect by editing by editing your .csproj to include the following (once again, this was discovered by Teroneko - it's essentially what the NuGet package he created does):

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

As with the package, you then mark the depended-upon project reference(s) in your .csproj with PrivateAssets="all", and it Just Works(tm).

Solution 2

I was looking for this answer and was annoyed when I couldn't find an obvious one. The solution that worked best for me was to create a nuspec, add the list of DLLs I wanted in the nupkg to that spec and then build with dotnet pack. I created an easy sample and readme here - nuget sample app

Solution 3

Another solution to the problem is to create a custom .targets file to include in your projects. You can add some msbuild instructions to include the files that you need in the package. There is some documentation here on how to do it, here a short example

<PropertyGroup Condition="$(PackAsComponent) != ''">
  <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CustomBuildOutput</TargetsForTfmSpecificBuildOutput>
  <TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);CustomContentInPackage</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>

<Target Name="CustomBuildOutput">
  <ItemGroup>
    <BuildOutputInPackage Include="$(OutputPath)*.dll" Exclude="$(TargetPath)" />
    <BuildOutputInPackage Include="$(OutputPath)*.pdb" />
    <BuildOutputInPackage Include="$(OutputPath)*.exe" Exclude="$(TargetPath)" />
  </ItemGroup>
</Target>

<Target Name="CustomContentInPackage">
  <ItemGroup>
    <TfmSpecificPackageFile Include="abc.txt">
    <PackagePath>mycontent/$(TargetFramework)</PackagePath>
    </TfmSpecificPackageFile>
  </ItemGroup>
</Target>

Basically I activate this when I set the PackAsComponent property in my project. This preserve the "dotnet pack" functionality 100% without the need to specify any parameter.

Share:
17,153

Related videos on Youtube

Marcus
Author by

Marcus

CTO at software consultancy QueensLab, based in Gothenburg, Sweden.

Updated on September 14, 2022

Comments

  • Marcus
    Marcus over 1 year

    Is there any way to force dotnet pack to include all referenced assemblies (all dependencies in project.json)?

    I believe this is related:

  • Marcus
    Marcus over 7 years
    Yes, I am aware of this, but this nuget package is not intended for any audience, in my case I use it as a simple zip file which it in actuality is - I just don´t have the possiblility to zip the files in this environment, this is why I want to use the dotnet toolchain.
  • 108
    108 over 7 years
    Did you try the workaround described in the issues then?
  • Seabizkit
    Seabizkit almost 4 years
    im trying this simply does not work... get the following issues on pipelines " ##[error]Error: The process 'C:\Program Files\dotnet\dotnet.exe' failed with exit code 1 ##[error]An error occurred while trying to pack the files. "
  • OutstandingBill
    OutstandingBill almost 4 years
    +1 Works for me. I have a solution containing an F# project and a C# wrapper for it (plus some other bits and bobs). Before applying this solution (simple cut/paste) my .nupkg did not contain the F# DLL. After applying this solution, it did. Not sure why dependencies are not considered necessary by the pack command though.
  • OutstandingBill
    OutstandingBill almost 4 years
    This approach works for me too (as does Ian Kemp's - I tried them both). To me it feels like a more "proper" way to do it than Ian's answer - you don't have to explain to anybody what all the stuff in the .csproj file is for. Having the information about the dependencies in the .nuspec file feels like a more natural place for it.
  • Yas Ikeda
    Yas Ikeda almost 4 years
    This approach worked for me in the case where I need more control inside the package. just note that having <NuspecFile>./relative/path/to.nuspec</NuspecFile> in <PropertyGroup> in .csproj allows us to use dotnet pack command with the .nuspec file.
  • Teneko
    Teneko over 3 years
    Thanks, this is awesome, could be from me. :D (Here you find the source code of the lines above. I decided to deliver it as package too)
  • Ian Kemp
    Ian Kemp over 3 years
    @Teroneko I had no idea you have an account here - I have updated the answer to include your package and also converted the answer to Community Wiki so that I do not get credit for it (I should have done so when I first posted it). If you want, you can post your own answer with a link to your package in order to get deserved reputation from people it helps - if you do so, I will flag this answer to be deleted so that yours is the canonical one.
  • Teneko
    Teneko about 3 years
    Yep this is for advanced scenarios. Needs a lot of understanding for MSBuild but once you master it you can make a lot of it. Good job.
  • Marcus
    Marcus over 2 years
    Marking as correct, since there is still no way and probably never will be.