From 81a59d564bb8e2f593ca036124e31927343cf4a0 Mon Sep 17 00:00:00 2001 From: Greg Curtis Date: Mon, 2 Sep 2024 12:42:16 -0400 Subject: [PATCH] patchpkg: `lookPath` helper to find nix binaries When running inside a Nix derivation the PATH is completely empty, so functions like `exec.Command("bash")` don't work. To make dealing with this easier, add a helper function that looks for an environment variable named after the command and returns `$cmd/bin/cmd` (e.g., `bash` becomes `$bash/bin/bash`). This will automatically find build-time dependencies that are added as attributes to the derivation. --- internal/patchpkg/builder.go | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/internal/patchpkg/builder.go b/internal/patchpkg/builder.go index 32190124141..3377bb3adeb 100644 --- a/internal/patchpkg/builder.go +++ b/internal/patchpkg/builder.go @@ -67,8 +67,7 @@ func (d *DerivationBuilder) Build(ctx context.Context, pkgStorePath string) erro } } - bash := filepath.Join(os.Getenv("bash"), "bin/bash") - cmd := exec.CommandContext(ctx, bash, "-s") + cmd := exec.CommandContext(ctx, lookPath("bash"), "-s") cmd.Stdin = bytes.NewReader(glibcPatchScript) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -152,5 +151,24 @@ func allFiles(fsys fs.FS, root string) iter.Seq2[string, fs.DirEntry] { } } +// lookPath is like [exec.lookPath], but first checks if there's an environment +// variable with the name prog. If there is, it returns $prog/bin/prog instead +// of consulting PATH. +// +// For example, lookPath would be able to find bash and patchelf in the +// following derivation: +// +// derivation { +// inherit (nixpkgs.legacyPackages.x86_64-linux) bash patchelf; +// builder = devbox; +// } +func lookPath(prog string) string { + pkgPath := os.Getenv(prog) + if pkgPath == "" { + return prog + } + return filepath.Join(pkgPath, "bin", prog) +} + func isExecutable(mode fs.FileMode) bool { return mode&0o111 != 0 } func isSymlink(mode fs.FileMode) bool { return mode&fs.ModeSymlink != 0 }