{"id":4915,"date":"2019-11-03T22:01:18","date_gmt":"2019-11-03T22:01:18","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=4915"},"modified":"2019-11-26T11:33:50","modified_gmt":"2019-11-26T11:33:50","slug":"creating-a-nuget-package-revisited","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/creating-a-nuget-package-revisited\/","title":{"rendered":"Creating a nuget package (revisited)"},"content":{"rendered":"<p>I&#8217;ve covered some of this post previous in my post <a href=\"http:\/\/putridparrot.com\/blog\/creating-local-packages-with-nuget\/\" target=\"_blank\" rel=\"noopener noreferrer\">Creating Local Packages with NuGet<\/a>, but I wanted to drill down a little more into this here.<\/p>\n<p>Part of the reason for a revisit is that I wanted to look at creating the relevant .nuspec for a couple of projects I&#8217;ve put on github and I wanted to cover the .nuspec files in a little more depth.  <\/p>\n<p><strong>Before we start<\/strong><\/p>\n<p>Before we start you&#8217;ll probably want to grab the latest nuget.exe from <a href=\"https:\/\/www.nuget.org\/downloads\" rel=\"noopener noreferrer\" target=\"_blank\">Available NuGet Distribution Versions<\/a>. The current recommended version is v4.9.4 and this should be placed in your project folder (or ofcourse wherever you prefer in the path). <\/p>\n<p><strong>Generating a nuspec file<\/strong><\/p>\n<p>We can now run <\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nnuget spec\r\n<\/pre>\n<p>in my case, this produced the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot;?&gt;\r\n&lt;package &gt;\r\n  &lt;metadata&gt;\r\n    &lt;id&gt;Package&lt;\/id&gt;\r\n    &lt;version&gt;1.0.0&lt;\/version&gt;\r\n    &lt;authors&gt;PutridParrot&lt;\/authors&gt;\r\n    &lt;owners&gt;PutridParrot&lt;\/owners&gt;\r\n    &lt;licenseUrl&gt;http:\/\/LICENSE_URL_HERE_OR_DELETE_THIS_LINE&lt;\/licenseUrl&gt;\r\n    &lt;projectUrl&gt;http:\/\/PROJECT_URL_HERE_OR_DELETE_THIS_LINE&lt;\/projectUrl&gt;\r\n    &lt;iconUrl&gt;http:\/\/ICON_URL_HERE_OR_DELETE_THIS_LINE&lt;\/iconUrl&gt;\r\n    &lt;requireLicenseAcceptance&gt;false&lt;\/requireLicenseAcceptance&gt;\r\n    &lt;description&gt;Package description&lt;\/description&gt;\r\n    &lt;releaseNotes&gt;Summary of changes made in this release of the package.&lt;\/releaseNotes&gt;\r\n    &lt;copyright&gt;Copyright 2019&lt;\/copyright&gt;\r\n    &lt;tags&gt;Tag1 Tag2&lt;\/tags&gt;\r\n    &lt;dependencies&gt;\r\n      &lt;dependency id=&quot;SampleDependency&quot; version=&quot;1.0&quot; \/&gt;\r\n    &lt;\/dependencies&gt;\r\n  &lt;\/metadata&gt;\r\n&lt;\/package&gt;\r\n<\/pre>\n<p>As you can see, it&#8217;s supplied the basics along with an example of a dependency. The dependencies are the package our project is dependent upon. The id can be found via the nuget website or from the nuget packages section within Visual Studio. The versions can also be found in the same way.<\/p>\n<p>If we wish to add files to our nuspec we add a files section after the metadata end tag. For example<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n  &lt;\/metadata&gt;\r\n\r\n   &lt;files&gt;\r\n      &lt;file src=&quot;&quot; target=&quot;&quot; \/&gt;\r\n   &lt;\/files&gt;\r\n\r\n&lt;\/package&gt;\r\n<\/pre>\n<p>The <em>src<\/em> is the relative location of the files to add (maybe we&#8217;re adding a README.txt for example). The <em>target<\/em> is where the file should be copied to. Using <em>content<\/em> as the start of the target will added file to the content folder.<\/p>\n<p><strong>Naming conventions<\/strong><\/p>\n<p>The next thing I want to touch on is naming conventions, which I think becomes important if you&#8217;re intending the deploy on the NuGet site (as opposed to local to your organization or the likes).<\/p>\n<p>The <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms229048(v=vs.110).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">Names of Assemblies and DLLs<\/a> discusses some possible conventions. Obviously the &lt;Company&gt;.&lt;Component&gt;.dll is a very sensible convention to adopt as we will need to ensure our assemblies are as uniquely named as possible to stay away from name clashes with others.<\/p>\n<p>Obviously using such naming conventions will tend to push towards namespace etc. naming conventions also, so have a read of <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms229026(v=vs.110).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">Names of Namespaces<\/a> also.<\/p>\n<p><strong>Generating our NuGet package from a project<\/strong><\/p>\n<p>Before we look at the nuspec file itself, let&#8217;s cover the simple way of generating our NuGet package, as this might be all you need if the component\/code you want to package is fairly self-contained.<\/p>\n<p>Before we create the package, let&#8217;s create a bare bones .nuspec file because otherwise, the nuget tool will generate one along these lines<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot;?&gt;\r\n&lt;package xmlns=&quot;http:\/\/schemas.microsoft.com\/packaging\/2011\/08\/nuspec.xsd&quot;&gt;\r\n  &lt;metadata&gt;\r\n    &lt;id&gt;PutridParrot.Collections&lt;\/id&gt;\r\n    &lt;version&gt;1.0.0.0&lt;\/version&gt;\r\n    &lt;title&gt;PutridParrot.Collections&lt;\/title&gt;\r\n    &lt;authors&gt;PutridParrot&lt;\/authors&gt;\r\n    &lt;owners&gt;PutridParrot&lt;\/owners&gt;\r\n    &lt;requireLicenseAcceptance&gt;false&lt;\/requireLicenseAcceptance&gt;\r\n    &lt;description&gt;Description&lt;\/description&gt;\r\n    &lt;copyright&gt;Copyright \u00a9 PutridParrot 2017&lt;\/copyright&gt;\r\n    &lt;dependencies \/&gt;\r\n  &lt;\/metadata&gt;\r\n&lt;\/package&gt;\r\n<\/pre>\n<p><em>Note: the project I ran this against was PutridParrot.Collections.csproj<\/em><\/p>\n<p>So lets take this and change it a little &#8211; create a .nuspec named after your project, i.e. mines PutridParrot.Collections.nuspec and paste the below, into it (change names etc. as you need).<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot;?&gt;\r\n&lt;package &gt;\r\n  &lt;metadata&gt;\r\n    &lt;id&gt;Your Project Name&lt;\/id&gt;\r\n    &lt;version&gt;1.0.0.0&lt;\/version&gt;\r\n    &lt;title&gt;Your project title&lt;\/title&gt;\r\n    &lt;authors&gt;Your Name&lt;\/authors&gt;\r\n    &lt;owners&gt;Your Name&lt;\/owners&gt;\r\n    &lt;requireLicenseAcceptance&gt;false&lt;\/requireLicenseAcceptance&gt;\r\n    &lt;description&gt;Your Description&lt;\/description&gt;\r\n    &lt;releaseNotes&gt;First Release&lt;\/releaseNotes&gt;\r\n    &lt;copyright&gt;Copyright 2017&lt;\/copyright&gt;\r\n    &lt;tags&gt;collections&lt;\/tags&gt;\r\n  &lt;\/metadata&gt;\r\n&lt;\/package&gt;\r\n<\/pre>\n<p><em>Note: The tags are used by the NuGet repos, so it&#8217;s best to come up with several (with a space between each) tags for your project.<\/em><\/p>\n<p>Now we&#8217;ve got a nuspec file this will be embedded into the package by nuget.<\/p>\n<p>From the command line, (easiest from the folder containing the project you want to package) run<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nnuget pack &lt;project-name&gt;.csproj\r\n<\/pre>\n<p><em>Note: as the package is zipped, just append .zip to it to open using File Explorer in Windows, so you can see how it&#8217;s laid out. Don&#8217;t forget to remove the .zip when relocating to local host of remote host.<\/em><\/p>\n<p><strong>Autogenerating parts of the nuspec from AssemblyInfo<\/strong><\/p>\n<p>We can actually tokenize some of our nuspec and have nuget use our project&#8217;s AssemblyInfo.cs file, see <a href=\"https:\/\/docs.microsoft.com\/en-us\/nuget\/schema\/nuspec#replacement-tokens\" target=\"_blank\" rel=\"noopener noreferrer\">Replacement tokens<\/a>.<\/p>\n<p>This means, for example version might be written like this<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;version&gt;$version$&lt;\/version&gt;\r\n<\/pre>\n<p>and will have this value automatically replaced and the nupkg will be named with that same version.<\/p>\n<p><strong>Multiple files or how to use nuget pack with the csproj<\/strong><\/p>\n<p>Running nuget pack against a project is useful but what if you want to handle multiple projects and\/or non-project files? Then we would be better off editing the nuspec file to pull in the files we want.<\/p>\n<p>Here&#8217;s an example of the previous nuspec which now includes more than one version of the project&#8217;s DLL.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;?xml version=&quot;1.0&quot;?&gt;\r\n&lt;package &gt;\r\n  &lt;metadata&gt;\r\n    &lt;id&gt;Your Project Name&lt;\/id&gt;\r\n    &lt;version&gt;1.0.0.0&lt;\/version&gt;\r\n    &lt;title&gt;Your project title&lt;\/title&gt;\r\n    &lt;authors&gt;Your Name&lt;\/authors&gt;\r\n    &lt;owners&gt;Your Name&lt;\/owners&gt;\r\n    &lt;requireLicenseAcceptance&gt;false&lt;\/requireLicenseAcceptance&gt;\r\n    &lt;description&gt;Your Description&lt;\/description&gt;\r\n    &lt;releaseNotes&gt;First Release&lt;\/releaseNotes&gt;\r\n    &lt;copyright&gt;Copyright 2017&lt;\/copyright&gt;\r\n    &lt;tags&gt;collections&lt;\/tags&gt;\r\n  &lt;\/metadata&gt;\r\n  &lt;files&gt;\r\n    &lt;file src=&quot;bin\\Release\\PutridParrot.Collections.dll&quot; target=&quot;lib\\net40&quot; \/&gt;\r\n    &lt;file src=&quot;bin\\Release\\PutridParrot.Collections.dll&quot; target=&quot;lib\\netstandard1.6&quot; \/&gt;\r\n  &lt;\/files&gt;  \r\n&lt;\/package&gt;\r\n<\/pre>\n<p>Now run<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nnuget pack PutridParrot.Collections.nuspec\r\n<\/pre>\n<p>Notice we&#8217;re running nuget pack against our nuspec file instead and this will bring in two DLL&#8217;s and make them available to lib\\net40 and lib\\netstandard1.6 thus targetting two different .NET frameworks.<\/p>\n<p>The following gives a list of valid <a href=\"https:\/\/docs.microsoft.com\/en-us\/nuget\/schema\/target-frameworks#supported-frameworks\" target=\"_blank\" rel=\"noopener noreferrer\">Supported frameworks<\/a> that we can assign.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve covered some of this post previous in my post Creating Local Packages with NuGet, but I wanted to drill down a little more into this here. Part of the reason for a revisit is that I wanted to look at creating the relevant .nuspec for a couple of projects I&#8217;ve put on github and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[66],"tags":[],"class_list":["post-4915","post","type-post","status-publish","format-standard","hentry","category-nuget"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=4915"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4915\/revisions"}],"predecessor-version":[{"id":7757,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4915\/revisions\/7757"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=4915"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=4915"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=4915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}