Profpatsch/nix/runGoCommand
- drv/drv.go 5.1 KiB
- default.nix 1.7 KiB
- runGoCommand.7 3.6 KiB
runGoCommand(7)
NAME
runGoCommand - a Nix derivation whose builder is a Go program
SYNOPSIS
depot.nix.runGoCommand "name" ./builder.go {
input = somePackage;
flag = "x";
}
DESCRIPTION
runGoCommand
is the Go counterpart of
pkgs.runCommand:
instead of a bash script run under stdenv's setup, the build step is a
Go program.
The file is compiled for the build machine with
buildGo(7)
and becomes the derivation's
builder
itself.
There is no shell, no
setup
script, no hooks and no implicit
PATH.
It exists because builders that assemble file trees — copy this, write that, generate a config, refuse if a store path leaks — grow into shell scripts whose quoting, globbing and error handling are each a bug waiting to happen. In Go they are typed, testable, and fail loudly.
Arguments
name
The derivation's name.
builder
The Go file, package
main. It is the whole builder: one file, importing only the standard library anddrv.
derivationArgs
Passed to derivation() as they are. As with any derivation, each attribute becomes an environment variable of the builder: a package becomes its store path, a list its elements separated by spaces. The builder reads them with drv.Env() and drv.EnvList().
name, builder, args and system are reserved. system in particular is derivation()'s build platform, so an input called
systemwould silently select another platform; it is an evaluation error instead.
The drv package
Every builder can
import drv,
a small stdlib-only helper package
(drv/drv.go).
Its functions do not return errors: a builder has nothing to recover to, so
any failure prints a message and exits non-zero, which fails the build.
Out()
$out.
Env(name)
A required variable; missing is fatal.
EnvList(name)
A list attribute, split.
Run(prog, args...)
Run a program, output to the build log. prog must be a path; pass the package in derivationArgs and join
/bin/foo.
RunIn(dir, prog, args...)
Run() in a directory.
Output(prog, args...)
Run and return stdout.
Pipe(r, w, prog, args...)
Run with stdin and stdout attached.
Mkdir(paths...)
Write(path, content, mode)
WriteShebang(path, interpreter, lines...)
An executable script:
#!interpreter (arguments included, e.g. "/bin/execlineb -P"), then the lines, each newline-terminated.
Touch(path)
Symlink(target, link)
CopyFile(src, dst, mode)
Mode 0 keeps the source's mode, owner-writable.
CopyTree(src, dst)
Recursive, symlinks preserved, everything owner-writable.
Glob(pattern)
Check(err, context...)
Fatalf(format, args...)
EXAMPLES
// builder.go
package main
import "drv"
func main() {
out := drv.Out()
drv.Mkdir(out + "/bin")
drv.CopyFile(drv.Env("hello")+"/bin/hello", out+"/bin/hello", 0)
drv.Run(out+"/bin/hello", "-g", "built by a Go builder")
}
depot.nix.runGoCommand "example" ./builder.go {
hello = pkgs.hello;
}
SEE ALSO
buildGo(7), //nix/runExecline
CAVEATS
-
The builder runs with the bare build environment Nix provides: no
PATH, noHOMEbeyond /homeless-shelter. Programs that look themselves up onPATHneed it set via derivationArgs. -
Because there is no stdenv, nothing is patched, stripped or checked afterwards: the builder's output is the output.
-
Changing a builder recompiles it, which costs a second or two.