• 为了让derivation两个阶段成功运行,除了必要的三个元素,还需要out path存在

  • 为了构建out path,使用bash脚本来进行构建,通过向derivation函数传递参数args = [ ./builder.sh ]来让builder(bash)运行builder.sh构建脚本

  • 第一个可运行的derivation builder.sh

    1
    2
    
    declare -xp
    echo foo > $out
    

    nix repl -f '<nixpkgs>'

    1
    2
    
    nix-repl> d = derivation { name = "foo"; builder = "${bash}/bin/bash"; args = [ ./builder.sh ]; system = builtins.currentSystem; }
    nix-repl> :b d
    

    通过nix log /nix/store/gvwysj9dkjjan9hvxfnwq2f97chnz437-foo.drv来查看构建过程中的日志(包含打印出的环境变量) 使用nix derivation show /nix/store/gvwysj9dkjjan9hvxfnwq2f97chnz437-foo.drv查看out path

  • 第二个derivation 由前一个derivation的日志可知,PATH="/path-not-set",所以为了构建一个简单的c程序,我们需要将gcc的bin路径加入PATH中 对derivation函数来说,所有传给它的键值对(除了部分保留的元素,如args)都会以一定的规则转换成builder的环境变量 如derivation { other = ./other.file; some = "some"; },其中other(转换成复制到/nix/store/中的地址)和some会以环境变量的形式传给builder(多为bash)

    源码,作为src环境变量传入

    simple.c

    1
    2
    3
    
    void main() {
            puts("Simple!");
    }
    

    作为args参数传入,是builder(bash)的参数 (bash simple-builder.sh)

    simple-builder.sh

    1
    2
    3
    
    export PATH="$coreutils/bin/:$gcc/bin"
    mkdir $out
    gcc -o $out/simple $src
    

    调用derivation求值, 并构建

    1
    2
    3
    4
    
    nix-repl> d = derivation { name = "simple"; builder = "{bash}/bin/bash"; system = builtins.currentSystem; args = [ ./builder.sh ]; src = ./simple.c; inhert (pkgs) gcc coreutils; }
    nix-repl> :b d
    
    运行 /nix/store/5hykxkxc8rj9c0q5p19fmagk5ms2rczx-simple/simple
    
  • .nix文件而不是nix repl确保reproducible simple.nix

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    let 
      pkgs = import <nixpkgs> { };
    in
      derivation {
        name = "simple";
        builder = "${pkgs.bash}/bin/bash";
        system = builtins.currentSystem;
        args = [ ./simple-builder.sh ];
        inherit (pkgs) gcc coreutils;
        src = ./simple.c;
      }
    

    使用nix build --file ./simple.nix 或者 nix-build ./simple.nix来求值并构建该derivation (注:nix-build实际上做了两件事, nix-instantiatenix-sotre -r)