build: wrap nix build

These things currently require manual testing unfortunately since writing a nix stub would take a long time.
This commit is contained in:
Yonah 2025-07-14 22:10:48 +09:00
parent ba94989895
commit 011958f108
Signed by: yonah
SSH Key Fingerprint: SHA256:vnQvK8+XXH9Tbni2AV1a/8qdVK/zPcXw52GM0ruQvwA
3 changed files with 74 additions and 4 deletions

51
build.go Normal file
View File

@ -0,0 +1,51 @@
package nixbuild
import (
"context"
"iter"
"strings"
)
// Build builds all entries yielded by installables.
func Build(ctx context.Context, installables iter.Seq[string]) error {
c, cancel := context.WithCancel(ctx)
defer cancel()
cmd := Nix(c, CommandBuild,
FlagKeepGoing, FlagNoLink, FlagStdin)
if Stdout != nil {
cmd.Stdout = Stdout
cmd.Args = append(cmd.Args, FlagPrintBuildLogs)
} else {
cmd.Args = append(cmd.Args, FlagQuiet)
}
if Stderr != nil {
cmd.Stderr = Stderr
cmd.Args = append(cmd.Args, FlagVerbose)
}
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
if err = cmd.Start(); err != nil {
return err
}
for drv := range installables {
if strings.HasSuffix(drv, ".drv") {
// this is just what nix requires now :c
drv += "^*"
}
if _, err = stdin.Write([]byte(drv + "\n")); err != nil {
return err
}
}
if err = stdin.Close(); err != nil {
return err
}
return cmd.Wait()
}

View File

@ -8,6 +8,7 @@ import (
"log"
"os"
"os/signal"
"slices"
"strings"
"syscall"
@ -20,6 +21,9 @@ type commandHandlerError string
func (c commandHandlerError) Error() string { return string(c) }
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
var (
flagNixOS bool
flagVerbose bool
@ -38,7 +42,18 @@ func main() {
Flag(&flagVerbose, "v", command.BoolFlag(false), "Connect nix stderr").
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
c.Command("instantiated", "Evaluate an installable and output all derivations it instantiated", func(args []string) error {
c.Command("build", "Build a list of installables", func(args []string) error {
if len(args) < 1 {
return commandHandlerError("build requires at least 1 argument")
}
if err := nixbuild.Build(ctx, slices.Values(args)); err != nil {
return commandHandlerError(fmt.Sprintf("cannot build: %v", err))
}
return nil
})
c.Command("instantiated", "Evaluate an installable and output all derivations instantiated during evaluation", func(args []string) error {
if len(args) != 1 {
return commandHandlerError("instantiated requires exactly 1 argument")
}
@ -60,9 +75,6 @@ func main() {
}
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
if v, err := nixbuild.EvalInstantiated(ctx, installable); err != nil {
return commandHandlerError(fmt.Sprintf("cannot evaluate for instantiated derivations: %v", err))
} else if flagJSON {

View File

@ -48,6 +48,13 @@ const (
// FlagVersion show version information.
FlagVersion = "--version"
// FlagKeepGoing keep going in case of failed builds, to the greatest extent possible.
// That is, if building an input of some derivation fails, Nix will still build the other inputs,
// but not the derivation itself.
// Without this option, Nix stops if any build fails (except for builds of substitutes),
// possibly killing builds in progress (in case of parallel or distributed builds).
FlagKeepGoing = "--keep-going"
// OptionEvalCache whether to use the flake evaluation cache.
// Certain commands wont have to evaluate when invoked for the second time with a particular version of a flake.
// Intermediate results are not cached.