NuGet package restore

Note: This documentation is for FAKE.exe before version 5 (or the non-netcore version). The documentation needs te be updated, please help!

If you are using a source control system like git you probably don't want to store all binary dependencies in it. With FAKE you can use NuGet to download all dependent packages during the build.

Setting the stage for NuGet

In order to download the packages during the build we need to add NuGet.exe to our repository. You can download the "NuGet.exe Command Line Tool" from the release page.

Restore packages from the build script

Modify your build script and add RestorePackages() near the beginning of the script. This will use the default parameters to retrieve all NuGet packages specified in "./**/packages.config" files.

If you need to use different parameters please use the RestorePackage task directly.

Download latest version of FAKE via NuGet

If you don't want to store FAKE.exe and its components in your repository, you can use a batch file which downloads it before the build:

1: 
2: 
3: 
4: 
5: 
@echo off
cls
"tools\nuget\nuget.exe" "install" "FAKE" "-OutputDirectory" "tools" "-ExcludeVersion"
"tools\FAKE\tools\Fake.exe" build.fsx
pause

Creating NuGet packages

Note: This documentation is for FAKE.exe before version 5 (or the non-netcore version). The documentation needs te be updated, please help!

Creating a .nuspec template

The basic idea to create nuget packages is to create a .nuspec template and let FAKE fill out the missing parts. The following code shows such .nuspec file from the OctoKit project.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
<?xml version="1.0" encoding="utf-8"?>
<package xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">    
  <id>@[email protected]</id>
  <version>@[email protected]</version>
  <authors>@[email protected]</authors>
  <owners>@[email protected]</owners>
  <summary>@[email protected]</summary>
  <licenseUrl>https://github.com/octokit/octokit.net/blob/master/LICENSE.txt</licenseUrl>
  <projectUrl>https://github.com/octokit/octokit.net</projectUrl>
  <iconUrl>https://github.com/octokit/octokit.net/icon.png</iconUrl>
  <requireLicenseAcceptance>false</requireLicenseAcceptance>
  <description>@[email protected]</description>
  <releaseNotes>@[email protected]</releaseNotes>
  <copyright>Copyright GitHub 2013</copyright>    
  <tags>GitHub API Octokit</tags>
  @[email protected]
  @[email protected]
  </metadata>
  @[email protected]
</package>

The .nuspec template contains some placeholders like @[email protected] which can be replaced later by the build script. It also contains some specific information like the copyright which is not handled by FAKE.

The following table gives the correspondence between the placeholders and the fields of the record type used by the NuGet task.

Placeholder

replaced by (NuGetParams record field)

@[email protected]

Version

@[email protected]

Authors

@[email protected]

Project

@[email protected]

Summary

@[email protected]

Description

@[email protected]

Tags

@[email protected]

ReleaseNotes

@[email protected]

Copyright

@[email protected]

a combination of Dependencies and DependenciesByFramework

@[email protected]

a combination of References and ReferencesByFramework

@[email protected]

a list of source, target, and exclude strings for files to be included in the nuget package

Setting up the build script

In the build script you need to create a target which executes the NuGet task:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
Target "CreatePackage" (fun _ ->
    // Copy all the package files into a package folder
	CopyFiles packagingDir allPackageFiles

	NuGet (fun p -> 
		{p with
			Authors = authors
			Project = projectName
			Description = projectDescription                               
			OutputPath = packagingRoot
			Summary = projectSummary
			WorkingDir = packagingDir
			Version = buildVersion
			AccessKey = myAccesskey
			Publish = true }) 
			"myProject.nuspec"
)

There are a couple of interesting things happening here. In this sample FAKE created:

  • a copy of the .nuspec file
  • filled in all the specified parameters
  • created the NuGet package
  • pushed it to nuget.org using the given myAccessKey.

Handling package dependencies

If your project dependends on other projects it is possible to specify these dependencies in the .nuspec definition (see also Nuget docs). Here is a small sample which sets up dependencies for different framework versions:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
    NuGet (fun p -> 
            {p with
                    Authors = authors
                    // ...
                    Dependencies =  // fallback - for all unspecified frameworks
				["Octokit", "0.1"
				"Rx-Main", GetPackageVersion "./packages/" "Rx-Main"]
                    DependenciesByFramework =
                                    [{ FrameworkVersion  = "net40"
                                    Dependencies = 
                                            ["Octokit", "0.1"
                                             "Rx-Main", GetPackageVersion "./packages/" "Rx-Main"
                                             "SignalR", GetPackageVersion "./packages/" "SignalR"]}
                                    { FrameworkVersion  = "net45"
                                    Dependencies = 
                                            ["Octokit", "0.1"
                                             "SignalR", GetPackageVersion "./packages/" "SignalR"]}]
                    // ...
                    Publish = true }) 
                    "myProject.nuspec"

Explicit assembly references

If you want to have auxiliary assemblies next to the ones that get referenced by the target project, you can place all the needed files in the lib directory and explicitly specify which of them should be referenced (see Nuget docs) via the References and ReferencesByFramework fields. Here is a code snippet showing how to use these:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
NuGet (fun p -> 
    {p with
        Authors = authors
        // ...
        References = ["a.dll"]
        ReferencesByFramework =
            [{ FrameworkVersion  = "net40"; References = ["b.dll"]}
             { FrameworkVersion  = "net45"; References = ["c.dll"]}]
        // ...
        Publish = false })
        "template.nuspec"

Explicit file specifications

If you want to specify exactly what files are packaged and where they are placed in the resulting NuGet package you can specify the Files property directly. This is exactly like having the Files element of a nuspec filled out ahead of time. Here is a code snippet showing how to use this:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
// Here we are specifically only taking the js and css folders from our project and placing them in matching target folder in the resulting nuspec.
// Note that the include paths are relative to the location of the .nuspec file
// See [Nuget docs](http://docs.nuget.org/docs/reference/nuspec-reference#Specifying_Files_to_Include_in_the_Package) for more detailed examples of how to specify file includes, as this follows the same syntax.
NuGet (fun p ->
	{p with
		// ...
		Files = [
			(@"tools\**\*.*", None, None)
			(@"bin\Debug\*.dll", Some "lib", Some "badfile.css;otherbadfile.css")
		]
		// ...
	})
	"template.nuspec"
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>