1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{ depot, pkgs, lib, ... }:

# runGoCommand: a derivation whose builder is a Go program. See
# runGoCommand.7.
#
#   runGoCommand "name" ./builder.go { foo = somePkg; }
#
# The Go file (package main, may import "drv") is compiled for the build
# machine with buildGo and *is* the derivation's builder: no bash, no stdenv
# setup hooks. The attribute set is passed to `derivation` as is, so every
# attribute becomes an environment variable; $out is the output, and
# drv.Out()/drv.Env() read them.
let
  buildGo = depot.nix.buildGo;

  drvLib = buildGo.package {
    name = "drv";
    srcs = [ ./drv/drv.go ];
  };

  runGoCommand = name: builder: derivationArgs:
    # `derivation` itself owns these; `system` in particular is the build
    # platform, so an input named `system` would silently change it.
    assert lib.assertMsg (!derivationArgs ? name) "runGoCommand ${name}: `name` is the first argument";
    assert lib.assertMsg (!derivationArgs ? system) "runGoCommand ${name}: `system` is reserved by derivation (the build platform); rename the attribute";
    assert lib.assertMsg (!derivationArgs ? builder) "runGoCommand ${name}: `builder` is the second argument";
    assert lib.assertMsg (!derivationArgs ? args) "runGoCommand ${name}: `args` is reserved";
    let
      prog = buildGo.program {
        name = "${name}-builder";
        srcs = [ builder ];
        deps = [ drvLib ];
      };
    in
    derivation (derivationArgs // {
      inherit name;
      inherit (pkgs.stdenv.buildPlatform) system;
      builder = "${prog}/bin/${name}-builder";
      args = [ ];
    });
in
{
  __functor = _: runGoCommand;
  # The helper library builders import as "drv".
  drv = drvLib;
}