Introduction
This tip will present a simple, fast, automated and full-featured open-source solution for creation of NuGet packages.
Background
There are many methods for creation of NuGet packages such as:
- Manually creating a NuSpec XML file, then creating a NuPkg file using NuGet.exe
- Using NuGet Package Explorer
- Installing an add-on to Visual Studio
- Using a custom TFS template
My objectives in creating NuGet packages were:
- Create packages automatically during TFS builds
- Create packages automatically during local builds
- Fast creation of packages, so local builds won't take long
- Sync package version number with assembly version numbers
- Enable automatic assign of pre-release version number to packages
- Enable packaging of multiple assemblies from solution
- Enable automatic listing of external (NuGet package) dependencies
- Support dependencies on internal NuGet packages, built in same solution (during same build)
- Enable including source code within packages for easier step into source
- Automatically refresh list of source code files during each build
- Do not crash
However, none of the existing options met these objectives.
Using the Code
- Create a source for the version numbers:
Add a shared file named VersionInfo.cs (or any other name) to your solution with the following attributes in it:
AssemblyCompany
, under which put your company name or the author's name AssemblyTrademark
, under which put the project's URL (make sure the license is under that URL too). AssemblyFileVersion
, under which put the version number for the assemblies and the NuGet packages e.g. 1.2.3.0. Leave the forth number as 0
, as it will be ignored. AssemblyInformationalVersion
, under which put the above version number + -sometext if the package is a pre-release package e.g. 1.2.3-alpha of 1.2.3-pre-release e.g.
using System.Reflection;
[assembly: AssemblyCompany("Your company name")]
[assembly: AssemblyTrademark("https://your.project.url/")]
[assembly: AssemblyFileVersion("1.2.3.0")]
#if DEBUG
[assembly: AssemblyInformationalVersion("1.2.3-alpha")]
#else
[assembly: AssemblyInformationalVersion("1.2.3")]
#endif
- Synchronize version number between projects:
Alt+Drag the VersionInfo.cs file to all the assemblies in your solution which you want to include in packages. (Alt+Drag creates a link to the file, instead of copying it the new location.) - Remove the
AssemblyCompany
, AssemblyTrademark
, AssemblyFileVersion
and AssemblyInformationalVersion
attributes from the AssemblyInfo.cs files to prevent duplicate attributes (which will fail build). - Add a new project for your NuGet package to the solution using the standard add "Class Library" dialog (yes the standard class library template!). Called
YourNuGetPackageName.NuGet
(the .NuGet
is optional). - Repeat steps 2+3 for the new project (add link to VersionInfo.cs, remove duplicates from AssemblyInfo.cs).
- Add references from the new NuGet project to any assemblies within the same solution which you want included in the package.
- Add NuGet packages to the new NuGet project for any external NuGet packages that this package should depend on.
- Internal NuGet dependencies: If your package depends on other NuGet packages that are created within the same solution:
- Add a text file named internalPackages.config to the new NuGet project (you can copy the packages.config and rename it).
- Edit the internalPackages.config file so its structure will be the same as the packages.config file, however, list the NuGet packages created with the solution, e.g.
="1.0"="utf-8"
<packages>
<package id="PubComp.NoSql.Core" version="2.0.0" targetFramework="net45" />
</packages>
- List any tags you want your package to have in the attribute
AssemblyTitle
within AssemblyInfo.cs. - Add a description for you package in the attribute
AssemblyDescription
within AssemblyInfo.cs. - Set the package's name in the attribute
AssemblyProduct
within AssemblyInfo.cs.
[assembly: AssemblyTitle("NoSQL, Repository,
Abstraction, Design Patterns, MongoDb")]
[assembly: AssemblyDescription
("A MongoDb-based implementation of the NoSQL abstraction layer")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("PubComp.NoSql.MongoDb")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyCulture("")]
- Add NuGet.exe and NuGetPack.exe to your solution's folder + add the solution itself (so they will be available to TFS builds).
- NuGet.exe is the standard NuGet.exe file you already have
- NuGetPack.exe is available as both source and binary at https://pubcomp.codeplex.com/
- Optional: Alternatively you can set the tags, description, summary, authors, owners, copyright, icon URL, project URL and package generation options by adding a file named NuGetPack.config to your Package Project:
<NuGetPack>
<AddFrameworkReferences>true</AddFrameworkReferences>
<DoIncludeSources>true</DoIncludeSources>
<IconUrl>http://www.nuget.org/favicon.ico</IconUrl>
<ProjectUrl>https://pubcomp.codeplex.com/</ProjectUrl>
<LicenseUrl>https://pubcomp.codeplex.com/license</LicenseUrl>
<Authors>Demo Author</Authors>
<Owners>Demo Owner</Owners>
<Copyright>Demo Copyright</Copyright>
<Description>Demo Description</Description>
<Summary>Demo Summary</Summary>
<Keywords>Demo, Key, Word</Keywords>
</NuGetPack>
- If you use the "add framework references" option, then remove any framework references that are not really required from the package project.
- Optional: You can include
content
under a folder named content in the package project.
The content files can be added as links instead of copies of the originals if you drag them with the ALT key pressed down or if you use the drop down option of "Add As Link" on the "Add" button when using the "Add Existing Item" menu option. - Optional: You can include (non-NuGet)
binaries
under a folder named lib in the package project. To include .NET Framework version specific binaries, place them under sub folders e.g. lib\net20, lib\net40 and etc.
As in the content files, these files may be added as links or copies of the original files. - Optional: You can include items that are to remain under the packages folder, yet not added to any projects by adding them under a folder named sln in the package project.
As in the content files, these files may be added as links or copies of the original files. - The .NET Framework version your package depends on is set by the Framework version of the package project. To change it, change the "Target Framework" of the package project via the project's Properties.
- Add the following post-build event to your NuGet project:
"$(SolutionDir)NuGetPack.exe" "$(ProjectPath)" "$(TargetPath)" $(ConfigurationName)
- Repeat steps 4-19 for each additional NuGet package you want to create.
- Build your solution.
- The NuPkg (and NuSpec) files will be under the output folder (e.g. bin\Debug, bin\Release).
Update
NuGetPack.exe is now available as a NuGet and a Project Template for NuGet packages is now available as a VSIX.
Points of Interest
Next time, I'll show you how to automatically pull NuGet package dependencies from custom sources and push output NuGet packages to any source during TFS builds.