Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / TFS

Automated Creation of NuGet Packages

5.00/5 (6 votes)
6 Aug 2014LGPL35 min read 59.4K  
Fast, stable and powerful creation of NuGet packages

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:

  1. Create packages automatically during TFS builds
  2. Create packages automatically during local builds
  3. Fast creation of packages, so local builds won't take long
  4. Sync package version number with assembly version numbers
  5. Enable automatic assign of pre-release version number to packages
  6. Enable packaging of multiple assemblies from solution
  7. Enable automatic listing of external (NuGet package) dependencies
  8. Support dependencies on internal NuGet packages, built in same solution (during same build)
  9. Enable including source code within packages for easier step into source
  10. Automatically refresh list of source code files during each build
  11. Do not crash

However, none of the existing options met these objectives.

Using the Code

  1. 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:
    1. AssemblyCompany, under which put your company name or the author's name
    2. AssemblyTrademark, under which put the project's URL (make sure the license is under that URL too).
    3. 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.
    4. 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.
    C#
    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
  2. 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.)
  3. Remove the AssemblyCompany, AssemblyTrademark, AssemblyFileVersion and AssemblyInformationalVersion attributes from the AssemblyInfo.cs files to prevent duplicate attributes (which will fail build).
  4. 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).
  5. Repeat steps 2+3 for the new project (add link to VersionInfo.cs, remove duplicates from AssemblyInfo.cs).
  6. Add references from the new NuGet project to any assemblies within the same solution which you want included in the package.
  7. Add NuGet packages to the new NuGet project for any external NuGet packages that this package should depend on.
  8. Internal NuGet dependencies: If your package depends on other NuGet packages that are created within the same solution:
    1. Add a text file named internalPackages.config to the new NuGet project (you can copy the packages.config and rename it).
    2. 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.
    XML
    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="PubComp.NoSql.Core" version="2.0.0" targetFramework="net45" />
    </packages>
  9. List any tags you want your package to have in the attribute AssemblyTitle within AssemblyInfo.cs.
  10. Add a description for you package in the attribute AssemblyDescription within AssemblyInfo.cs.
  11. Set the package's name in the attribute AssemblyProduct within AssemblyInfo.cs.
    C#
    [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("")]
  12. Add NuGet.exe and NuGetPack.exe to your solution's folder + add the solution itself (so they will be available to TFS builds).
    1. NuGet.exe is the standard NuGet.exe file you already have
    2. NuGetPack.exe is available as both source and binary at https://pubcomp.codeplex.com/
  13. 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:
    XML
    <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>
  14. If you use the "add framework references" option, then remove any framework references that are not really required from the package project.
  15. 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.
  16. 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.
  17. 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.
  18. 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.
  19. Add the following post-build event to your NuGet project:
    C#
    "$(SolutionDir)NuGetPack.exe" "$(ProjectPath)" "$(TargetPath)" $(ConfigurationName)
  20. Repeat steps 4-19 for each additional NuGet package you want to create.
  21. Build your solution.
  22. 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.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)