Inspecting Nix Lambda Function Arguments
Ever wondered how callPackage
magically knows which dependencies to pass to a package function? The secret lies in Nix’s ability to inspect function arguments at runtime. Let’s explore this powerful feature that makes nixpkgs dependency injection work seamlessly.
Understanding Function Argument Inspection Link to heading
When you work with nixpkgs, you often encounter functions that expect specific named arguments. Here’s how to discover what those arguments are using nix repl
:
nix-repl> f = import "${pkgs.path}/pkgs/servers/varnish"
nix-repl> f
«lambda @ /nix/store/.../pkgs/servers/varnish/default.nix:1:1»
nix-repl> builtins.functionArgs f
{ fetchurl = false; groff = false; libedit = false; libxslt = false;
makeWrapper = false; ncurses = false; pcre = false; pkgconfig = false;
python = false; pythonPackages = false; readline = false; stdenv = false; }
The builtins.functionArgs
function returns an attribute set where:
- Keys represent the expected argument names
- Values indicate whether the argument has a default value (
true
means optional,false
means required)
How callPackage Uses This Information Link to heading
The callPackage
function leverages builtins.functionArgs
to automatically provide the right dependencies. It intersects the function’s expected arguments with the available packages:
nix-repl> builtins.intersectAttrs (builtins.functionArgs f) pkgs
{ fetchurl = «lambda @ .../fetchurl/default.nix:38:1»;
groff = «derivation /nix/store/...-groff-1.22.3.drv»;
libedit = «derivation /nix/store/...-libedit-20160903-3.1.drv»;
libxslt = «derivation /nix/store/...-libxslt-1.1.29.drv»;
makeWrapper = «derivation /nix/store/...-hook.drv»;
ncurses = «derivation /nix/store/...-ncurses-6.0-20171125.drv»;
pcre = «derivation /nix/store/...-pcre-8.41.drv»;
pkgconfig = «derivation /nix/store/...-pkg-config-0.29.2.drv»;
python = «derivation /nix/store/...-python-2.7.14.drv»;
pythonPackages = { ... };
readline = «derivation /nix/store/...-readline-6.3p08.drv»;
stdenv = «derivation /nix/store/...-stdenv.drv»; }
This intersection creates the exact argument set needed to call the function, pulling each dependency from the nixpkgs attribute set.
Practical Applications Link to heading
Exploring Package Dependencies When you want to understand what a package needs, check its function arguments:
builtins.functionArgs (import "<nixpkgs/pkgs/development/tools/misc/gdb>")
Debugging Override Issues If package overrides fail, verify you’re providing the correct argument names:
# Check what arguments the package actually expects
builtins.functionArgs pkgs.myPackage.override
Creating Custom callPackage Functions
Build your own dependency injection by combining functionArgs
with intersectAttrs
:
myCallPackage = f: args:
f (builtins.intersectAttrs (builtins.functionArgs f) (pkgs // args));
Key Takeaways Link to heading
The builtins.functionArgs
function provides the foundation for nixpkgs’ dependency management system. It enables:
- Automatic dependency resolution through callPackage
- Runtime function introspection for debugging
- Custom dependency injection patterns for advanced use cases
Next time you need to understand what arguments a Nix function expects, reach for builtins.functionArgs
. This simple builtin unlocks powerful metaprogramming capabilities that make nixpkgs both flexible and maintainable.