What does it accept?
The runCommand
source simply states that
/* Run the shell command `buildCommand' to produce a store path named
* `name'. The attributes in `env' are added to the environment
* prior to running the command.
and the runCommand
section in the Nixpkgs manual goes further with
env
is an attribute set specifying environment variables that will be set for this derivation.
The latter seems misleading though as I was immediately thinking of shell environment variables (especially because the phrase “environment variable” is used exclusively in this context in the Nixpkgs manual) but, looking at the examples, this is not the case:
-
from the NixOS manual:
Nix expressions can also be given on the command line. For instance, the following starts a shell containing the packages
sqlite
andlibX11
:$ nix-shell -E 'with import <nixpkgs> { }; runCommand "dummy" { buildInputs = [ sqlite xorg.libX11 ]; } ""'
-
from various parts in the the Nixpkgs manual:
runCommand "test.pdf" { nativeBuildInputs = [ latex_with_foiltex ]; } ''
runCommand "${pname}-tests" { meta.timeout = 3; } ''
and so on.
Would it be fair to say that env
in runCommand name env buildCommand
is basically
an arbitrary Nix expression to satisfy certain prerequisites (dependencies, shell environment variables, etc.)
?
The snippet below from this post seems to corroborate this:
runCommand "foo"
{ buildInputs = [ python imagemagick ]; }
''
I am an indented string
I will be executed as a bash script, with the following
dependencies available:
- python
- imagemagick
...
''
How does it work?
Based on my understanding looking at the source, it shouldn’t even work.
update: Totally misinterpreted the very last line (// builtins.removeAttrs derivationArgs [ "passAsFile" ]);
which is merging derivationArgs
(nee env
) into mkDerivation
's input attribute set…
runCommand = name: env: runCommandWith {
stdenv = stdenvNoCC;
runLocal = false;
inherit name;
derivationArgs = env;
};
runCommandWith =
let
# prevent infinite recursion for the default stdenv value
defaultStdenv = stdenv;
in
{ stdenv ? defaultStdenv
# which stdenv to use, defaults to a stdenv with a C compiler, pkgs.stdenv
, runLocal ? false
# whether to build this derivation locally instead of substituting
, derivationArgs ? {}
# extra arguments to pass to stdenv.mkDerivation
, name
# name of the resulting derivation
}: buildCommand:
stdenv.mkDerivation ({
name = lib.strings.sanitizeDerivationName name;
inherit buildCommand;
passAsFile = [ "buildCommand" ]
++ (derivationArgs.passAsFile or []);
}
// (lib.optionalAttrs runLocal {
preferLocalBuild = true;
allowSubstitutes = false;
})
// builtins.removeAttrs derivationArgs [ "passAsFile" ]);