Building NuGet packages with Dotnet Core

Xavier Penya
2 min readOct 8, 2018

--

Straight to the point: the easiest way to pack a project is like this =>

dotnet pack "path/to/your/PROJECT/folder" --include-symbols --force --output "path/to/your/NUGETS/folder" --runtime "net461" -p:PackageVersion="1.0.0"

But there are other issues to consider, that will be discussed in the rest of the article.

Uhm… but “dotnet pack” doesn’t let me add “Author”!

Yes and no: those other fields now have to be placed in the .csprjo file, like this:

<PropertyGroup>    <TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>    <Authors>Xavier Penya</Authors>
<Company>MyCompany</Company>
</PropertyGroup>

The package doesn’t work if I have multiple projects

dotnet pack just packs a single project. It doesn’t pack all of its project dependencies, it just says “hey, this package I am creating has all those other dependencies”. This is why when you load your new package into a different project, NuGet expects to find all its dependent nuget packages (3rd party packages as well as your own other projects that were referenced in your main project). If it doesn’t find all of them, it doesn’t even finish installing your package.

To solve this error, you have at least 2 options:

Option 1: create N nuget packages

That is: one nuget package per dependency, like so:

:: From the command line:
SET PACKAGE_VERSION=%1
SET OUTPUT_DIRECTORY="path/to/your/NUGETS/directory"
SET RUNTIME="net461"
dotnet pack "path/to/proj/depenency/1" --include-symbols --force --output %OUTPUT_DIRECTORY% --runtime %RUNTIME% -p:PackageVersion=%PACKAGE_VERSION%
dotnet pack "path/to/proj/depenency/2" --include-symbols --force --output %OUTPUT_DIRECTORY% --runtime %RUNTIME% -p:PackageVersion=%PACKAGE_VERSION%
dotnet pack "path/to/proj/depenency/3" --include-symbols --force --output %OUTPUT_DIRECTORY% --runtime %RUNTIME% -p:PackageVersion=%PACKAGE_VERSION%

Option 2 [recommended]: modify the .csproj

The solution came from this comment (remember to set PrivateAssets="All" for every project reference!):

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net47</TargetFrameworks>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\ClassLibrary2\ClassLibrary2.csproj" PrivateAssets="all" />
<ProjectReference Include="..\ClassLibrary3\ClassLibrary3.csproj" Condition="'$(TargetFramework)' == 'net47'" PrivateAssets="all" />
</ItemGroup>

<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
</ItemGroup>
</Target>
</Project>

Why CakeBuild’s NuGetPack() doesn’t work

Uuh… I don’t know. But it doesn’t.

The build was OK, but when the nuget package was installed in a different code it produced this runtime error: Could not load file or assembly System.Runtime, Version=4.2.0.0 . So after asking on StackOverflow a user suggested that I tried dotnet pack . And that solved the issue.

So how do I combine “dotnet pack” with CakeBuild?

You can replace this:

NuGetPack(nuGetPackSettings);

By this:

StartProcess("pack.bat", "1.0.0");

…where pack.bat code is as follows:

:: From the command line:
SET PACKAGE_VERSION=%1
SET SRC_PATH="path/to/your/PROJECT/folder"
SET OUTPUT_DIRECTORY="path/to/your/NUGETS/folder"
SET RUNTIME="net461"
dotnet pack %SRC_PATH% --include-symbols --force --output %OUTPUT_DIRECTORY% --runtime %RUNTIME% -p:PackageVersion=%PACKAGE_VERSION%

--

--

Xavier Penya

Developer & data analyst | Loves playing around with side projects