When using mkDerivation in Nix, is it possible to specify the shell used by `buildPhase`?

429 Views Asked by At

Suppose the following line in your flake.nix:

        foo = pkgs.stdenv.mkDerivation {
          name = "foo";
          buildPhase = ''
            #some shell script
          '';
          installPhase = ''
            #some shell script
          '';
        };

Is it possible to specify a shell (ideally defined with mkShell, or passed in as a path) to use for the buildPhase, installPhase, etc, instead of plain old bash?

I tried reproducing the shell environment specified elsewhere in each of the text blocks, and it feels un-Nix-y

3

There are 3 best solutions below

0
On

Not semantically the same, but you can run scripts written in other languages in your derivation. For example:

{
  buildPhase = ''
    ./my-build-script.py
  '';
}
0
On

Actually, there's an easy way to get what I want, it turns out. I'm a little embarrassed to have asked. Solution for anyone else who might find this question. This approach allows you to reuse a shell configuration (packages, environment variables) across derivations, shells, and scripts (very handy in flake.nix.)

It's not quite what I was looking for, but it meets the needs that had me looking.

Do something along the lines of:


# ...
let
  shellHook = ''
    export SOME_VAR=1
  '';
  nativeBuildInputs = [ pkgs.foo ];

  # for `nix develop`
  my-shell = pkgs.mkShell = {
    inherit nativeBuildInputs shellHook;
    # ...
  };

  my-package = pkgs.stdenv.mkDerivation {
    inherit nativeBuildInputs shellHook;
    # ...
  };

  my-script = pkgs.writeScript ''
    #!/usr/bin/env nix-shell
    #!nix-shell -i bash -p ${builtins.concatStringsSep ' ' nativeBuildInputs}
    ${shellHook}
    # ...

  '';
  }
in {
  apps.default = {
    type = "app";
    program = "${my-script}";
  };
  packages.default = my-package;
  devShells.default = my-shell;
}
# ...
0
On

This is not possible, as the phases run one after the other in a single shell session. They often use and set local variables.

Any predefined phases or setup hooks provided by build inputs are designed for Bash as well.

To use another shell, you'd need to use derivation with a custom builder, which would mean giving up all the infrastructure mkDerivation provides, notably including input propagation and cross-compilation.