Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
What does Nixpkgs' callPackage do?
callPackage is a complex function (reasons include the Nix language being lazy, usage of fixed-point evaluation, overrides, etc.), and this complexity steals the spotlight from what this function actually does and why is it so useful.
There are a plethora of online resources about this topic (see below), but I couldn't find a simple, concise summary.
-
[
nix.dev] Package parameters and overrides with callPackage — nix.dev documentation -
[
Nix Pills] 13. Callpackage Design Pattern -
[
Nix-Book] Imports and callPackage - Nix-Book -
Nixpkgs commit and email introducing
callPackage -
[
stackoverflow] Where iscallPackagedefined in the Nixpkgs repo (or how to find Nix lambda definitions in general)? -
[
NixOS Discourse] Where iscallPackagedefined exactly? (part 2) - Help - NixOS Discourse -
[
Nixpkgs repo] Issue #36354 - Document what callPackage does and its preconditions -
[
Summer of Nix]callPackage, a tool for the lazy -
[
NixOS & Flakes Book]pkgs.callPackage
1 answer
For the record, this write-up is not better than any of the resources listed in the question; writing it simply helped me better understand callPackage.
Level 0. Poor, but short
callPackage f attr_set will
- call function
fwith inputs automatically supplied fromattr_setand Nixpkgs - make the resulting attribute set overridable.
callPackage is used overwhelmingly with functions that produce a derivation. Building a project can require a lot of dependencies that won't have to be specified manually this way, and callPackage also makes it possible to configure "Nix derivation expressions" after callPackage has been called using overrides. (This email goes has the full rationale.)
"Nix derivation expression" is just a personal term, not an official one, that I use to refer to an attribute set that represents a store derivation in terms of the Nix language before instantiation.
Level 1. Wordier and still inexact
callPackage accepts 2 inputs:
-
a function that takes as input an attribute set
e.g.,{ stdenv, miez, lofa ? 27 }: { inherit stdenv miez lofa; } -
an attribute set that must be a subset of the input function's input attribute set
e.g., in the case of the example in item 1., this would be ok:{ miez = 7; lofa = 9; }
callPackage will
-
call the input function with an attribute set whose attributes are supplied from
- the attribute set in
callPackage's 2nd argument - a subset of the Nixpkgs package (attribute) set1
- the attribute set in
-
make the resulting attribute set overridable.
Level 2. More precise but also more abstruse
callPackage :: ( attr_set_function | path_to_file_with_attr_set_function )
-> constrained_attr_set
-> ( overridable_attr_set | arbitrary_nix_value )
attr_set_function :: input_attr_set -> attr_set
The Nix language is dynamically typed, so this is just a personal notation.
where
-
input_attr_setis a regular attribute set with caveats depending on whether its attributes are Nixpkgs or not:-
IN Nixpkgs
If the attribute names match attributes in the limited subset of Nixpkgs package set1, then these won't have to be specified inconstrained_attr_setascallPackagewill auto-populate them. -
NOT in Nixpkgs
These either must have a default value or have to be specified inconstrained_attr_set.
-
-
constrained_attr_setis an attribute set that can only be a subset ofattr_set_function's input attribute set. -
overridable_att_set- See this section of thenix.devtutorial.
Level 3. Source
splicedPackagesWithXorg = splicedPackages // builtins.removeAttrs splicedPackages.xorg [
"callPackage"
"newScope"
"overrideScope"
"packages"
];
# ...
callPackage = pkgs.newScope { };
callPackages = ...;
newScope = extra: lib.callPackageWith (splicedPackagesWithXorg // extra);
callPackages (note the extra s!) is also defined here, but omitted it, lest I muddy the waters even more.
callPackageWith is quite long, so only posting the link, but the resources in the question explain the nitty-gritty - and the core of it is this line:
callPackage = f: args:
f ((builtins.intersectAttrs (builtins.functionArgs f) pkgs) // args);
... and this is an email from 2009 that introduces it.
Examples
NOTE
The termpkgsbelow will refer to the Nixpkgs package set. Such as the result of any of the following calls innix repl:
pkgs = import<nixpkgs>{}pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/06278c77b5d162e62df170fec307e83f1812d94b.tar.gz") {}- ... and so on
-
✅
pkgs.callPackage ({ lib, stdenv }: { ... }) {}libandstdenvare valid attributes in Nixpkgs, so these will be auto-populated from there. Roughly equivalent to:
pkgs.callPackage ({ lib, stdenv }: ... }) { lib = pkgs.lib; stdenv = pkgs.stdenv; } -
✅
pkgs.callPackage ({ lib, stdenv, lofa ? 27 }: { ... }) {}Same things apply as in the previous item, except that Nixpkgs has no
lofaattribute, but there is a default value provided for it, so it will work. -
✅
( pkgs.callPackage ({ lib, stdenv, lofa }: { inherit lofa lib; }) { lofa = 27; lib = "whatever"; } )Same as in previous item, but attributes
lofaandlibare explicitly provided. -
✅
let id = x: x; in pkgs.callPackage id {}callPackage's input function (1st parameter) is called with an attribute set, so this still works. -
❌
pkgs.callPackage (i: i + 2) {}callPackagewill choke becauseiwill be an attribute set and the+operator will try to coerce it into a string. -
❌
pkgs.callPackage ({ lib, stdenv, lofa }: { inherit lofa; }) {}will raise
error: Function called without required argument "lofa". -
✅
$ echo "{lib, stdenv, lofa ? 27}: {inherit lofa;}" > f.nix $ nix repl nix-repl> pkgs = import <nixpkgs> {} nix-repl> pkgs.callPackage ./f.nix {}Providing a valid file system path containing a Nix expression (that conforms to what
callPackageis accepting) works too as the file will be automatically imported first.
The result of attr_set_function is usually a Nix derivation expression (which is an attribute set denoting a derivation - or something like it; look this up).

0 comment threads