Dependencies
Previously we have built toy derivations with dummy output. In practice, Nix derivations are used for building programs, with build artifacts such as compiled binaries being the derivation output.
We can demonstrate this property by "building" a greet program. First we have to import a pinned version of nixpkgs as before. To simplify the process we abstract it out into a nixpkgs.nix at the root directory.
Now we build a greet program in greet.nix:
let
nixpkgs = import ../../nixpkgs.nix;
greet = nixpkgs.stdenv.mkDerivation {
name = "greet";
unpackPhase = "true";
buildPhase = ''
echo "building greet..."
sleep 3
'';
installPhase = ''
mkdir -p $out/bin
cat <<'EOF' > $out/bin/greet
#!/usr/bin/env bash
echo "Hello, $1!"
EOF
chmod +x $out/bin/greet
'';
};
in
greet
$ nix-build code/04-derivations/02-dependencies/greet.nix
these derivations will be built:
/nix/store/97lmyym0isl0ism7pfnv1b0ls4cahpi8-greet.drv
building '/nix/store/97lmyym0isl0ism7pfnv1b0ls4cahpi8-greet.drv'...
unpacking sources
patching sources
configuring
no configure script, doing nothing
building
building greet...
installing
post-installation fixup
shrinking RPATHs of ELF executables and libraries in /nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet
strip is /nix/store/bnjps68g8ax6abzvys2xpx12imrx8949-binutils-2.31.1/bin/strip
stripping (with command strip and flags -S) in /nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet/bin
patching script interpreter paths in /nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet
/nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet/bin/greet: interpreter directive changed from "/usr/bin/env bash" to "/nix/store/qdp56fi357fgxxnkjrwx1g67hrk775im-bash-4.4-p23/bin/bash"
checking for references to /build/ in /nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet...
/nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet
Now we can run greet:
$ result/bin/greet John
Hello, John!
Let's try to see what's inside the produced greet
script:
$ cat result/bin/greet
#!/nix/store/qdp56fi357fgxxnkjrwx1g67hrk775im-bash-4.4-p23/bin/bash
echo "Hello, $1!"
The shebang to the bash shell has been modified to pin to the Nix version of Bash.
Upper Greet
Our greet program can now be used as a dependency to other derivations.
Let's create an upper-greet
derivation that convert any greet result to
upper case.
let
nixpkgs = import ../../nixpkgs.nix;
inherit (nixpkgs) coreutils;
greet = import ./greet.nix;
in
nixpkgs.stdenv.mkDerivation {
name = "upper-greet";
unpackPhase = "true";
buildPhase = ''
echo "building upper-greet..."
sleep 3
'';
installPhase = ''
mkdir -p $out/bin
cat <<'EOF' > $out/bin/upper-greet
#!/usr/bin/env bash
${greet}/bin/greet "$@" | ${coreutils}/bin/tr [a-z] [A-Z]
EOF
chmod +x $out/bin/upper-greet
'';
}
Show Derivation
First we instantiate upper-greet.drv
without building it yet:
drv=$(nix-instantiate 04-derivations/02-dependencies/upper-greet.nix)
We can use nix show-derivation
to find out the dependency graph of the
derivation of upper-greet
:
$ nix show-derivation $drv
{
"/nix/store/n61g8616l7g7zv32q52yrzmzr850mjp0-upper-greet.drv": {
"outputs": {
"out": {
"path": "/nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet"
}
},
"inputSrcs": [
"/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"
],
"inputDrvs": {
"/nix/store/7gby8zic1p851ap63q1vdpwy7z1db85c-coreutils-8.32.drv": [
"out"
],
"/nix/store/97lmyym0isl0ism7pfnv1b0ls4cahpi8-greet.drv": [
"out"
],
"/nix/store/l54djrh1n7d8zdfn26w7v6zjh5wp7faa-bash-4.4-p23.drv": [
"out"
],
"/nix/store/x9why09hwx2pcnmw0fw7hhh1511hyskl-stdenv-linux.drv": [
"out"
]
},
...
"env": {
"buildInputs": "",
"buildPhase": "echo \"building upper-greet...\"\nsleep 3\n",
"builder": "/nix/store/qdp56fi357fgxxnkjrwx1g67hrk775im-bash-4.4-p23/bin/bash",
...
"installPhase": "mkdir -p $out/bin\n\ncat <<'EOF' > $out/bin/upper-greet\n#!/usr/bin/env bash\n/nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet/bin/greet \"$@\" | /nix/store/2shqhfsyzz4rnfyysbzgyp5kbfk29750-coreutils-8.32/bin/tr [a-z] [A-Z]\nEOF\n\nchmod +x $out/bin/upper-greet\n",
"name": "upper-greet",
...
We can see that greet.drv
is included as one of inputDrvs
. This means that when
upper-greet.drv
is being built, greet.drv
will have to be built first.
The output path of upper-greet.drv
is listed in outputs
. This shows that
the output hash of a derivation is fixed, regardless of the content of the
build result.
This is also why the output path of greet.drv
is used directly in env.installPhase
of upper-greet.drv
, even for the case when greet.drv
has not been built.
Build Derivation
$ nix-build 04-derivations/02-dependencies/upper-greet.nix
these derivations will be built:
/nix/store/n61g8616l7g7zv32q52yrzmzr850mjp0-upper-greet.drv
building '/nix/store/n61g8616l7g7zv32q52yrzmzr850mjp0-upper-greet.drv'...
unpacking sources
patching sources
configuring
no configure script, doing nothing
building
building upper-greet...
installing
post-installation fixup
shrinking RPATHs of ELF executables and libraries in /nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet
strip is /nix/store/bnjps68g8ax6abzvys2xpx12imrx8949-binutils-2.31.1/bin/strip
stripping (with command strip and flags -S) in /nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet/bin
patching script interpreter paths in /nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet
/nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet/bin/upper-greet: interpreter directive changed from "/usr/bin/env bash" to "/nix/store/qdp56fi357fgxxnkjrwx1g67hrk775im-bash-4.4-p23/bin/bash"
checking for references to /build/ in /nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet...
/nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet
As expected, the greet results are turned into upper case.
$ result/bin/upper-greet John
HELLO, JOHN!
The absolute paths to greet
and coreutils
are extended:
$ cat result/bin/upper-greet
#!/nix/store/qdp56fi357fgxxnkjrwx1g67hrk775im-bash-4.4-p23/bin/bash
/nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet/bin/greet "$@" | /nix/store/2shqhfsyzz4rnfyysbzgyp5kbfk29750-coreutils-8.32/bin/tr [a-z] [A-Z]
Runtime Dependency
If we query the references of the upper-greet
output (not the derivation),
we can see that greet
is still a runtime dependency of upper-greet
.
$ nix-store --query --references /nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet
/nix/store/2shqhfsyzz4rnfyysbzgyp5kbfk29750-coreutils-8.32
/nix/store/qdp56fi357fgxxnkjrwx1g67hrk775im-bash-4.4-p23
/nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet
We can use nix why-depends
to find out why Nix thinks greet
is a runtime
dependency to upper-greet
:
$ nix why-depends /nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet /nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet
/nix/store/dj2vp64gbja0bp65lngrw9q4lrm1a8r3-upper-greet
╚═══bin/upper-greet: …ash-4.4-p23/bin/bash./nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet/bin/greet "$@" | /nix/sto…
=> /nix/store/l6xy4qjr8x3ni16skfilw0fvnda13szq-greet