Skip to content

Latest commit

 

History

History
356 lines (275 loc) · 10.7 KB

50-derivations.org

File metadata and controls

356 lines (275 loc) · 10.7 KB

Derivations

Core part of Nix


A derivation is an attribute set that describes a build environment. Derivations on-disk are stored in .drv files.

nix-repl> derivation { name = "my_derivation"; builder = "my_builder"; system = "my_system"; }
«derivation /nix/store/3k6kqw1s85kaz5vgm43v6mqxjpn812sy-my_derivation.drv»

 ❤ (theia) ~> nix show-derivation /nix/store/d4ncq4ww3zmmm6j6q0j17631qbid59m3-my_name.drv
{
    "/nix/store/d4ncq4ww3zmmm6j6q0j17631qbid59m3-my_name.drv": {
        "outputs": {
            "out": {
                "path": "/nix/store/70ppafkb5a37k6im23cwgrnpl243v1mq-my_name"
            }
        },
        "inputSrcs": [],
        "inputDrvs": {},
        "system": "my_system",
        "builder": "my_builder",
        "args": [],
        "env": {
            "builder": "my_builder",
            "name": "my_name",
            "out": "/nix/store/70ppafkb5a37k6im23cwgrnpl243v1mq-my_name",
            "system": "my_system"
        }
    }
}

You can build .drv files


… or not …

❤ (theia) ~> nix-build /nix/store/d4ncq4ww3zmmm6j6q0j17631qbid59m3-my_name.drv
this derivation will be built: /nix/store/d4ncq4ww3zmmm6j6q0j17631qbid59m3-my_name.drv
error: a 'my_system' with features {} is required to build
    '/nix/store/d4ncq4ww3zmmm6j6q0j17631qbid59m3-my_name.drv',
    but I am a 'x86_64-linux' with features {benchmark, big-parallel, kvm, nixos-test}

{ name = ... }


  • Specifies the name and version of the package being built
  • Format: ${pname}-${version}
  • Somewhat deprecated/ out of style
    • Use pname and version explicitly instead!

{ builder = ... }


  • Builders are the root process which produces a package output.
  • Usually this is ${pkgs.bash}/bin/bash
  • It is very unusual to change the builder

{ system = ... }


  • The current build system
  • This value can be changed for cross-compilation
  • By default filled in with builtins.currentSystem
  • More on this during the cross-compilation day

Derivations are attribute sets


In fact, you can create a useless derivation very easily!

nix-repl> { type = "derivation"; }
«derivation ???»

Utility functions


  • Very basic derivation builder function: derivation
  • Much more useful derivation builder function: mkDerivation

A deeper look


nix-repl> hello
«derivation /nix/store/b3rw75kc63qd9ssb4khbf47lcj1g6ay7-hello-2.12.1.drv»

A deeper look


The raw .drv file on-disk.

Derive(
  [("out","/nix/store/3ng68pn55h3na7dayydpqrh4bm1ag2sl-hello-2.12.1","","")],
    [("/nix/store/1df310z72algpp1nxg45rhq2dfvkbrp5-bash-5.1-p16.drv",["out"]),
      ("/nix/store/dyivpmlaq2km6c11i0s6bi6mbsx0ylqf-hello-2.12.1.tar.gz.drv",["out"]),
      ("/nix/store/mjzy4drz2z4sbj3h5m7h3ndyvaqzdl80-stdenv-linux.drv",["out"])],
    ["/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],

    "x86_64-linux",

    "/nix/store/lj2bdg618093ny9505d0nzzjdq0fwp8a-bash-5.1-p16/bin/bash",

    ["-e","/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"],

    [("buildInputs",""),("builder","/nix/store/lj2bdg618093ny9505d0nzzjdq0fwp8a-bash-5.1-p16/bin/bash"),
      ("cmakeFlags",""),("configureFlags",""),("depsBuildBuild",""),
      ("depsBuildBuildPropagated",""),("depsBuildTarget",""),("depsBuildTargetPropagated",""),
      ("depsHostHost",""),("depsHostHostPropagated",""),("depsTargetTarget",""),("depsTargetTargetPropagated",""),
      ("doCheck","1"),("doInstallCheck",""),("mesonFlags",""),("name","hello-2.12.1"),("nativeBuildInputs",""),
      ("out","/nix/store/3ng68pn55h3na7dayydpqrh4bm1ag2sl-hello-2.12.1"),("outputs","out"),("patches",""),
      ("pname","hello"),("propagatedBuildInputs",""),("propagatedNativeBuildInputs",""),
      ("src","/nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz"),
      ("stdenv","/nix/store/43215b010yhnvpmr169abg324zq1l0sr-stdenv-linux"),
      ("strictDeps",""),("system","x86_64-linux"),("version","2.12.1")]
)

A deeper look


The evaluated .drv file.

{
  "/nix/store/qcvlk255x98i46cg9vphkdw5pghrizsh-hello-2.12.1.drv": {
    "outputs": {
      "out": {
        "path": "/nix/store/g2m8kfw7kpgpph05v2fxcx4d5an09hl3-hello-2.12.1"
      }
    },
    "inputSrcs": [
      "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"
    ],
    "inputDrvs": {
      "/nix/store/2knhp55njxnhh7j1l0w7ns0hi6bxmn1k-stdenv-linux.drv": [
        "out"
      ],
      "/nix/store/3sjd4vvbdssljiy45a9igjy9kkxd2skq-bash-5.1-p16.drv": [
        "out"
      ],
      "/nix/store/42j03b6x0cdj84b77mhkh9zwqgq61w6d-hello-2.12.1.tar.gz.drv": [
        "out"
      ]
    },
    "system": "x86_64-linux",
    "builder": "/nix/store/dsd5gz46hdbdk2rfdimqddhq6m8m8fqs-bash-5.1-p16/bin/bash",
    "args": [
      "-e",
      "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh"
    ],
    "env": {
      "buildInputs": "",
      "builder": "/nix/store/dsd5gz46hdbdk2rfdimqddhq6m8m8fqs-bash-5.1-p16/bin/bash",
      "cmakeFlags": "",
      "configureFlags": "",
      "depsBuildBuild": "",
      "depsBuildBuildPropagated": "",
      "depsBuildTarget": "",
      "depsBuildTargetPropagated": "",
      "depsHostHost": "",
      "depsHostHostPropagated": "",
      "depsTargetTarget": "",
      "depsTargetTargetPropagated": "",
      "doCheck": "1",
      "doInstallCheck": "",
      "mesonFlags": "",
      "name": "hello-2.12.1",
      "nativeBuildInputs": "",
      "out": "/nix/store/g2m8kfw7kpgpph05v2fxcx4d5an09hl3-hello-2.12.1",
      "outputs": "out",
      "patches": "",
      "pname": "hello",
      "propagatedBuildInputs": "",
      "propagatedNativeBuildInputs": "",
      "src": "/nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz",
      "stdenv": "/nix/store/kmfaajdpyyyg319vfqni5jm9wkxjmf73-stdenv-linux",
      "strictDeps": "",
      "system": "x86_64-linux",
      "version": "2.12.1"
    }
  }
}

Packages are built in two three parts


  • Part 0: evaluate package definition, compute hashes, and create .drv file
  • Part 1: evaluate derivation output
  • Part 2: build package according to derivation

 ❤ (theia) ~> nix-build /nix/store/qcvlk255x98i46cg9vphkdw5pghrizsh-hello-2.12.1.drv
this path will be fetched (0.05 MiB download, 0.22 MiB unpacked):
  /nix/store/g2m8kfw7kpgpph05v2fxcx4d5an09hl3-hello-2.12.1
copying path '/nix/store/g2m8kfw7kpgpph05v2fxcx4d5an09hl3-hello-2.12.1' from 'https://cache.nixos.org'...
/nix/store/g2m8kfw7kpgpph05v2fxcx4d5an09hl3-hello-2.12.1

stdenv.mkDerivation


Don’t build derivations by hand!

Instead use the mkDerivation function instead.

Have a look at (some of) the arguments this function takes.

{
  # ... 
, nativeBuildInputs           ? [] # -1 ->  0  N.B. Legacy name
, buildInputs                 ? [] #  0 ->  1  N.B. Legacy name

, checkInputs                 ? []
, installCheckInputs          ? []

, configureFlags ? []
, cmakeFlags ? []
, mesonFlags ? []

, doCheck ? config.doCheckByDefault or false
, doInstallCheck ? config.doCheckByDefault or false
, strictDeps ? if config.strictDepsByDefault then true else stdenv.hostPlatform != stdenv.buildPlatform

, enableParallelBuilding ? config.enableParallelBuildingByDefault
, meta ? {}
, passthru ? {}
, outputs ? [ "out" ]
, sandboxProfile ? ""
, propagatedSandboxProfile ? ""

, hardeningEnable ? []
, hardeningDisable ? []

, patches ? []
, ... } @ attrs: ...

A basic package


with import <nixpkgs> {};
stdenv.mkDerivation {
  name = "my-packge";
  dontUnpack = true;
  installPhase = ''
    mkdir $out
    echo "Hello :)" >> $out/message.txt
  '';
}

We use name instead of pname to avoid having to also set an explicit version here.

 ❤ (theia) ~> nix-build ./message.nix
this derivation will be built:
  /nix/store/j5b12i6gabrp868yimgxq2f6sd2prlqi-my-packge.drv
building '/nix/store/j5b12i6gabrp868yimgxq2f6sd2prlqi-my-packge.drv'...
patching sources
configuring
no configure script, doing nothing
building
no Makefile, doing nothing
installing
post-installation fixup
shrinking RPATHs of ELF executables and libraries in /nix/store/4q104yifnnn49gkwcsk4l2y1msc443zh-my-packge
strip is /nix/store/dq0xwmsk1g0i2ayg6pb7y87na2knzylh-gcc-wrapper-11.3.0/bin/strip
patching script interpreter paths in /nix/store/4q104yifnnn49gkwcsk4l2y1msc443zh-my-packge
checking for references to /build/ in /nix/store/4q104yifnnn49gkwcsk4l2y1msc443zh-my-packge...
/nix/store/4q104yifnnn49gkwcsk4l2y1msc443zh-my-packge

❤ (theia) ~> cat /nix/store/357fxrxpqcbrczdq0yfiijq6yn5igq7r-my-packge/message.txt
Hello :)

Environment variables


Any additional key passed to mkDerivation is set as an environment variable in the build environment

Some of these variables are used by Nix builds internally (for example dontUnpack). Everything else is up to you.

Some less common configuration


  1. Find nixpkgs on your system (type <nixpkgs> in the repl)
  2. nixpkgs/pkgs/stdenv/generic/setup.sh

Some less common configuration


  • dontUnpack (default true)
  • dontPatch (default true)
  • dontConfigure (default true)
  • dontBuild (default true)
  • doCheck (default false)
  • dontInstall (default true)
  • dontFixup (default true)
  • doInstallCheck (default false)
  • doDist (default false)

Importantly: some of these defaults are different based on what builder is invoking them (more on that later)

Some more useful things: https://nixos.org/manual/nix/stable/language/advanced-attributes.html