0

I'm very new to Nix. I'd like to refer to project scripts in my shell.nix file, so that when I cd into my project directory I can refer to them by name, and I can keep them up-to-date whenever the sources change.

To learn how to do this, I created a very simple derivation for a shell script. Eventually I'd like to use other languages, but I'm starting simple. It looks like this:

project
  nix
    myScript
      default.nix
      builder.sh
    shell.nix
# default.nix
{ pkgs ? import <nixpkgs> {} }:

pkgs.stdenv.mkDerivation rec {
  name = "myScript";

  echo = pkgs.coreutils + "/bin/echo";
  builder = "${pkgs.coreutils}/bin/bash";
  args = [ ./builder.sh ];
}
# builder.sh
$echo "$echo Hello world" > $out

When I run nix-build myScript.nix it creates a symlinked result file that looks like this:

/nix/store/3mfkgajns47hfv0diihzi2scwl4hm2fl-coreutils-9.1/bin/echo Hello world

I tried referencing this in my shell.nix file like this:

{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/bf972dc380f36a3bf83db052380e55f0eaa7dcb6.tar.gz") {} }:

let
  myScript = import ./myScript {};
in
pkgs.mkShell {
  buildInputs = [
    myScript
  ];

  shellHook = ''
    echo Loading shell.nix
  '';
}

But whenever I enter the projects directory and run the command `myScript, I get an error:

zsh: command not found: myScript

I already have direnv configured correctly, which I can confirm by adding other shell tools and checking their versions. So it's something wrong with my nix files.

I'm almost certainly doing something wrong here. I know I can simplify this with pkgs.writeShellScriptBin, but the shell script is more a minimal example of what I want to get working. Eventually I'd use more complex derivations.

What I think is wrong

I think the myScript derivation or builder is doing something wrong. It does create the expected output file (i.e. I can chmod +x and run it, and it works) but I suspect I need to tell nix how to run it? I'm not sure. And also I might be importing the derivation incorrectly.

haz
  • 2,034
  • 4
  • 28
  • 52
  • Your current derivation isn't creating a `$out/bin/myScript` file, which is what you need. Are you okay with rewriting it to use some of the trivial builders nixpkgs ships with? (See https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix) – Charles Duffy Aug 22 '22 at 15:18
  • In your `mkShell` change `buildInputs` to `nativeBuildInputs`. That way you'll get shell completion from package that support it. `nativeBuildInputs` is for packages that run in your builder (or shell). It's more important when you cross compile or use `strictDeps = true`. – Robert Hensing Aug 22 '22 at 17:11

1 Answers1

0

This is a problem with your default.nix, not your shell.nix.

For mkShell to work with buildInputs as you intend, you need $out to be a directory with an $out/bin/myScript, not a file on its own. nixpkgs has a helper that will do this for you, in https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix --

# default.nix; no builder.sh needed
{ pkgs ? import <nixpkgs> {} }:

pkgs.writeShellScript "myScript" ''
  echo "Hello world" # use the bash-builtin echo, not the external coreutils one
'';
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441