Simple Package¶
Overview¶
Most upstream software that ships a Unix-style build (./configure && make && make install, or equivalent) is packaged in Nixpkgs with stdenv.mkDerivation. You declare pname / version, fetch a fixed source, put tools and libraries in the right dependency slots, and let stdenv run the default build phases.
This page is the minimal walkthrough: one callPackage-style function, one tarball or Git tag, automatic phases, enough meta to land in the tree, and where that file lives under pkgs/by-name/.
Details¶
Function shape¶
Prefer the callPackage pattern: a function { lib, stdenv, fetchurl, … }: whose arguments are filled from Nixpkgs’ package set. That keeps dependencies explicit and makes overrides predictable. See callPackage.
Inside, call stdenv.mkDerivation with at least pname, version, and src. Since RFC 0035, Nixpkgs derives name as "${pname}-${version}" (see the manual’s Using stdenv).
Source and hash¶
Use fetchurl / fetchzip for release archives, or fetchFromGitHub (and similar fetchers) for tagged sources. Every fixed-output fetch needs a hash (SRI sha256-…) or legacy sha256. After the first failed build, copy the hash Nix reports rather than guessing—the nix.dev packaging tutorial walks through that loop with GNU Hello.
buildInputs vs nativeBuildInputs¶
| Attribute | Holds | Examples |
|---|---|---|
nativeBuildInputs |
Tools that run on the build machine during the build | pkg-config, cmake, makeWrapper, autoreconfHook |
buildInputs |
Libraries and headers linked into the product | zlib, openssl, libpng |
Stdenv setup hooks wire these into PATH, PKG_CONFIG_PATH, compiler flags, and related variables. On cross builds the split is strict. Native builds are more forgiving when strictDeps is off, but misplacing tools vs libraries still bites once you cross-compile or tighten dependency tracking. See dependency sections for propagated inputs and other slots.
Phases¶
For typical autotools or plain-Make projects you usually do not define phases yourself. Stdenv’s default builder runs unpack → patch → configure → build → install (and fixup) via genericBuild. Add preInstall, postPatch, or similar hooks for small fixes; replace a whole phase only when the upstream build system is non-standard.
meta¶
Set at least:
description— short, factual summarylicense— fromlib.licenses(or a custom license set when needed)platforms— oftenlib.platforms.unixor a tighter list after you verify the buildmaintainers— handles from maintainers-and-teams
meta is not a builder input; changing it alone does not rebuild the package.
Landing in Nixpkgs (pkgs/by-name)¶
New top-level packages that use pkgs.callPackage should live under pkgs/by-name/ whenever possible. Layout is:
<ab> is the lowercase two-letter prefix of the attribute name; <name> is the attribute (for example pkgs/by-name/ex/example/package.nix → pkgs.example). The directory is auto-discovered—no all-packages.nix entry for the default case. Language-scoped packages (python3Packages.*, and so on) and other exceptions stay in the category hierarchy; see the by-name README and CONTRIBUTING.md. Review expectations: review process.
Examples¶
Illustrative only—placeholder hashes and URLs will not build until you substitute a real source and the hash Nix reports.
Minimal package from a tarball with one library dependency:
{ lib, stdenv, fetchurl, zlib }:
stdenv.mkDerivation {
pname = "example";
version = "1.0.0";
src = fetchurl {
url = "https://example.com/example-1.0.0.tar.gz";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
buildInputs = [ zlib ];
meta = with lib; {
description = "Example library and CLI";
homepage = "https://example.com/";
license = licenses.mit;
platforms = platforms.unix;
maintainers = with maintainers; [ ];
};
}
Same shape with a GitHub tag and a native build tool (pkg-config in nativeBuildInputs, library in buildInputs):
{ lib, stdenv, fetchFromGitHub, pkg-config, zlib }:
stdenv.mkDerivation {
pname = "example";
version = "2.0.0";
src = fetchFromGitHub {
owner = "org";
repo = "example";
rev = "v2.0.0";
hash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
};
nativeBuildInputs = [ pkg-config ];
buildInputs = [ zlib ];
meta = with lib; {
description = "Example with pkg-config";
license = licenses.gpl3Only;
platforms = platforms.linux;
maintainers = with maintainers; [ ];
};
}
For a worked end-to-end build (GNU Hello + fixing the hash), follow the nix.dev tutorial in References. Shared vault fixtures (not evaluated here): simple-package.nix (callPackage wrapper shape) and fod-fetchurl.nix (placeholder FOD hash).
References¶
- The Standard Environment (
stdenv) — Nixpkgs manual chapter - Using stdenv —
pname/version, phases, minimal attrs - Build-time vs. host-time dependencies —
nativeBuildInputsvsbuildInputsand related slots - Packaging existing software — nix.dev tutorial (worked Hello example; use for a real hash loop)
- pkgs/by-name README — name-based package layout
- Nixpkgs CONTRIBUTING.md — where and how to add packages
- RFC 0035 (pname/version)
See also¶
- mkDerivation — attribute reference and overrides
- stdenv — environment, phases, and hooks
- Derivation — primitive below
mkDerivation - Build phases — default phase order
- Multiple outputs — splitting bin/lib/dev outputs
- Patches and overrides — fixing upstream without forking
- Example corpus —
simple-package.nix,fod-fetchurl.nix