118

I want to run a local/internal NuGet repository. I think I've figured out how to "reuse" existing NuGet packages by including them in a dummy project using NuGet and scanning the package file to grab my locally-cached .nupkg files, but...

How do you create a nuget package (.nupkg) from a project, automatically including all dll dependencies and not just those grabbed via NuGet?

Specifically:

  1. Create a solution
  2. Add a new Project
  3. Add references to various .dll files/other projects <-- this is the missing part
  4. Add NuGet packages via package manager / cmdline / whatever
  5. something automatically creates the .nupkg

From what I've found, you're supposed to do things like

  • manually edit your .csproj file to add <BuildPackage>true</BuildPackage> to include dependencies
  • manually create a .nuspec file and manually list your dependencies (similar ?)
  • manually run nuget pack on your .nuspec file

But everything is manual, which is stupid. Even the semi-automatic solutions are still awkward or half-manual:

I'll settle for something that automatically creates a .nuspec manifest from project references. Then theoretically that + the nuget build-event can be rolled up into a build-project/nuget package, which is what I really want to see.

Community
  • 1
  • 1
drzaus
  • 24,171
  • 16
  • 142
  • 201

6 Answers6

105

Your point #3 (Add references to various .dll files/other projects <-- this is the missing part) really contains two different issues: (1) add references to various dll files, and (2) add references to other projects in the same solution.

Number (2) here has gotten some added support as of NuGet 2.5. You can add an option to include references to other projects in the same solution when creating a NuGet package for a project:

nuget pack projectfile.csproj -IncludeReferencedProjects
  • If projectfile.csproj references any other projects in your solution that also is exposed as NuGet packages, these projects' NuGet packages will be added as dependencies.
  • If it references projects in your solution that doesn't expose themselves as NuGet packages, their dlls will be included in this NuGet package.

As for (1), if you find yourself often adding dlls to your projects that aren't available as NuGet packages, you could just create your own (internal) NuGet packages with these files. If you then add these dlls as a NuGet package instead of the files directly, this NuGet package will be a dependency in your project's NuGet package.

Jess
  • 23,901
  • 21
  • 124
  • 145
Julian
  • 20,008
  • 17
  • 77
  • 108
  • 3
    *sigh* #1 is still too manual for my tastes. Actually, "create your own (internal) NuGet package with these files" is what I'm trying to do -- the whole point of this question is that I want to automatically roll up non-NuGet .dlls into a NuGet package. Not go through and list each dll manually in a `.nuspec`, which I think is what you're suggesting? – drzaus May 02 '13 at 13:58
  • You don't have to specify each DLL separately. That would indeed be much work if you have _many_ of them. When listing files to include, you can use (recursive) wildcards (http://docs.nuget.org/docs/reference/nuspec-reference#Specifying_Files_to_Include_in_the_Package), so if you for instance place all these DLLs in a separate folder, it would be a one-liner to include them all. – Julian May 02 '13 at 20:46
  • Ah, now I get where you're going -- so if I make a wrapper project, include references via the usual "right-click project > Add Reference", then I can make a `nuspec` that includes everything in the `bin` directory (assuming my references are all "copy local"), it'll automatically pick up on whatever I've added. Seems a little hamfisted, but would probably work. – drzaus May 06 '13 at 17:30
  • 8
    It won't automatically pick up whatever is in your bin directory, you'd have to specify it explicitly, something like this: `` – Julian May 06 '13 at 19:30
  • correct, that's what I meant by "automatic" `nuspec`; thank you for clarifying – drzaus Jul 09 '13 at 14:29
  • 4
    Note worthy, if the projects being referenced happen to have a nuspec file then nuget will treat that as a package and NOT include in the lib folder but will add it to the package dependencies – workabyte Mar 28 '18 at 16:07
  • 24
    Is there an equivalent to `IncludeReferencedProjects` for `.csproj`? – rraallvv Sep 02 '20 at 13:56
27

I found a well-written article on this topic. I have the same issue with certain packages that have a hierarchy of dependencies and up until now I've been uploading each as a separate NuGet package (what. a. waste. of. time)

I've just tested the solution found here: https://dev.to/wabbbit/include-both-nuget-package-references-and-project-reference-dll-using-dotnet-pack-2d8p

And after examining the NuGet package using NuGet Package Explorer, the DLLs produced by referenced projects are indeed present. I'm going to test by actually submitting this package to NuGet and testing it.

Here's my source in case it is helpful to you: https://github.com/jchristn/NuGetPackTest

And the test NuGet package: https://www.nuget.org/packages/NuGetPackTest/1.0.0

The solution appears to work well. I don't know what it's going to look like when there are layers of references, I'm sure it could get really hairy and really fast.

enter image description here

.csproj from NuGetPackTest library which references project TestLibrary (portions removed for brevity)

<Project Sdk="Microsoft.NET.Sdk">
 
  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;netcoreapp3.0;netcoreapp3.1;net461</TargetFrameworks>
    ...
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>

    <!-- added this line -->
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
  </PropertyGroup>

  <ItemGroup>

    <!-- modified this ProjectReference to include the children ReferenceOutputAssembly and IncludeAssets -->
    <ProjectReference Include="..\TestLibrary\TestLibrary.csproj">
      <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
      <IncludeAssets>TestLibrary.dll</IncludeAssets>
    </ProjectReference>
  </ItemGroup>

  <!-- added this section -->
  <Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
    <ItemGroup>
      <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))"/>
    </ItemGroup>
  </Target>
  
</Project>
joelc
  • 2,687
  • 5
  • 40
  • 60
  • 6
    This solution does not add the reference project's nuget dependencies as dependencies. So you will have to add all the nuget dependencies that are added in sub-projects to the main project that will be a nuget package. Atleast that is what I encountered, including the created nuget package in another project results in 'assembly or file not found' issues. – CularBytes May 20 '21 at 12:28
9

For other Googlers, you can use this if you are using the NuGet.targets file to run NuGet Pack:

<Target Name="PrePackage" BeforeTargets="BuildPackage">
  <PropertyGroup>
    <BuildCommand>$(BuildCommand) -IncludeReferencedProjects</BuildCommand>
  </PropertyGroup>
</Target>
John Gietzen
  • 48,783
  • 32
  • 145
  • 190
4

I solved this for my case by adding the whole TargetDir to the nuget package.

Just add this to the .csproj:

<Target Name="IncludeAllFilesInTargetDir" AfterTargets="Build">
  <ItemGroup>
    <None Include="$(TargetDir)\**">
      <Pack>true</Pack>
      <PackagePath>tools</PackagePath>
    </None>
  </ItemGroup>
</Target>
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
PainElemental
  • 687
  • 6
  • 14
2

Check this out!

The solution which I found is an extension for Visual Studio: https://visualstudiogallery.msdn.microsoft.com/fbe9b9b8-34ae-47b5-a751-cb71a16f7e96/view/Reviews

You simply add new project called NuGet Package: NuGet Package

Then you are adding interesting you projects to references and BOOOM !! All dependencies and file directories are automatically added. If you want to modify NuSpec data you click right at project and go to Properties, then modify what you want. Generated NuSpec and nupkg will be in folder obj of your new project. I hope it helps ;).

SharpC
  • 6,974
  • 4
  • 45
  • 40
  • 1
    Is there also a solution for VS2017? – Dominic Jonas Nov 02 '17 at 13:44
  • 3
    This does not work in case of generating the packages on build server. – Michi-2142 Oct 08 '18 at 17:58
  • Too bad this is deprecated. Would have been useful. – joelc Oct 29 '20 at 00:42
  • I found a VS2017 version: https://marketplace.visualstudio.com/items?itemName=NuProjTeam.NuProj2017 and VS2019 version: https://marketplace.visualstudio.com/items?itemName=kamalraj.Nuproj201, although didn't have much luck on initial testing so just created the file manually in the end. – SharpC Mar 04 '22 at 08:09
1

The original NuGet pack would include local project dlls and if you used packages.config any nuget packages would be listed as dependencies. Everyone was happy.

Microsoft have since streamline everything, so now .Net (core) everything is done from the project file, which I do prefer. But now using nuget pack, your resulting package would have no dependencies listed.

Microsoft have said that the PackageReferences are not supported by the NuGet

NuGet CLI

So you need to use dotnet pack or msbuild -t:pack

dotnet CLI

However now using dotnet pack you have you dependencies back for your PackageReferences but you ProjectReferences are now also listed as dependencies.....

below is an example project file, with PackageReferences and ProjectReferences. for the Projects they have been marked as PrivateAssets="All" and then using custom build targets to copy the files needed from the projects into the package.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Title>Some.Project</Title>
  </PropertyGroup>

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Something" Version="1.0.0" />
  <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

<ItemGroup>
  <ProjectReference Include="..\Some.Other.Project.csproj" PrivateAssets="All" />
</ItemGroup>

<PropertyGroup>
  <TargetsForTfmSpecificBuildOutput> $(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>

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

  <ItemGroup>
    <BuildOutputInPackage Include="@(_ReferenceCopyLocalPaths)" TargetPath="%(_ReferenceCopyLocalPaths.DestinationSubDirectory)"/>
  </ItemGroup>
</Target>
</Project>

NuGet pack task doesn't include dependencies when using PackageReference #10301 nuget pack is ignoring dependencies when using PackageReference instead of packages.config #5979

Great guide and examples by Josef Ottosson Include Referenced Projects - Josef Ottosson

RickWeb
  • 1,765
  • 2
  • 25
  • 40