How to refer to custom derivation in shell.nix?

1.1k Views Asked by At

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.

1

There are 1 best solutions below

0
Charles Duffy On

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
'';