How to create a package recipe

How to create a package recipe#

Important

For the list of all available configuration options for package recipes visit the package options reference.

Before writing a recipe, please spend some time to understand the software and gather the basic information from the package’s source code repository:

Metadata

  • Package name, description

  • Latest stable version

  • Homepage URL

  • License

  • Main executable name

Language and build system

Look for these files in the repository root:

File

Build system

configure.ac or configure

Autotools (C/C++)

CMakeLists.txt

CMake (C/C++)

go.mod

Go

Makefile

Make (C/C++)

pyproject.toml or setup.py

Python

Cargo.toml

Rust

Dependencies — look in:

  • CMakeLists.txt: find_package(), pkg_check_modules()

  • configure.ac: PKG_CHECK_MODULES, AC_CHECK_LIB

  • pyproject.toml / setup.py: [project.dependencies], install_requires

  • README.md, INSTALL.md: listed prerequisites

  • CI config (.github/workflows/, .gitlab-ci.yml): packages installed before build

Repository structure

  • Are build files in the repository root or a subdirectory?

  • Are there git submodules (.gitmodules file)?

  • Does the build download anything at build time? Nix builds run without network access - these must be patched out or disabled via build flags.

Recipe file#

Create the package recipe directory and recipe file:

mkdir recipes/pkgs/<package-name>
touch recipes/pkgs/<package-name>/recipe.nix

Add the recipe file to Git:

git add recipes/pkgs/<package-name>/recipe.nix

Important

Nix can only see recipe files tracked by Git. If the file is not added to Git, the package will not be recognized.

Metadata#

Start the package recipe with the following content:

 1{
 2  pkgs,
 3  ...
 4}:
 5
 6{
 7  pkgs.package-name = {        # lowercase with hyphens
 8    version = "1.0.0";           # latest released version
 9    description = "Short description of the package.";
10    homePage = "https://project-website.org";
11    mainProgram = "executable-name";
12    license = lib.licenses.gpl3Only;
13
14    # More configuration to be added here.
15    # ...
16  };
17}

Important

Ensure that the remainder of the package recipe is done within the pkgs.package-name block to avoid nasty infinite recursion errors.

Note

Use the following command to get the list of all available licenses:

nix repl nixpkgs <<<':p lib.licenses'

Source#

Add a source block pointing to the upstream release. Leave hash empty for now:

1source = {
2  git = "github:owner/repo/v1.0.0";
3  hash = "";  # fill in after first build
4};

For tarball releases use source.url.

If the repository uses git submodules, add source.submodules = true.

Builder#

Enable exactly one builder and configure it as needed.

Condition

Builder

CMake, Autotools, or Makefile

builders.standard

Go

builders.go

Python with CLI tools ([project.scripts] or entry_points)

builders.python

Python library (no executables)

builders.pythonModule

Rust

builders.rust

Also, add dependencies using packages.build, packages.run or packages.check options.

 1build.builders.standard = {
 2  enable = true;
 3
 4  # build-time dependencies
 5  packages.build = [
 6    pkgs.bison
 7    pkgs.boost
 8  ];
 9
10  # run-time dependencies
11  packages.run = [
12    pkgs.zlib
13  ];
14}

Run the first build:

nix build .#pkgs.<package-name> --print-build-logs

Nix will fail during the first build due to a missing source hash. Update source.hash with the value from the error output, then launch the build once again.

Troubleshooting#

To troubleshoot build failures, enable debug mode to enter an interactive build environment:

1build.debug = true;

Then launch the interactive build and follow the on-screen instructions. Press Ctrl-C to drop into a shell and start investigating.

mkdir dev && cd dev
nix develop .#pkgs.<package-name>

Tests#

Add a test script to verify that package works correctly:

1test.script = ''
2  program --help | grep "Usage: program"
3'';

Run test:

nix build .#pkgs.<package-name>.test --print-build-logs

Examples#

Browse the example package recipes, or create your own Forge project to try them out:

nix flake init --template github:ngi-nix/forge#provider