Add nix-run and myEnvRun

This adds nix-run, which is a thin wrapper around nix-build.
nix-run calls nix-build, and then executes the resulting build.
If no executable artifact is built, nix-runs outputs an error
message.

myEnvRun calls myEnvFun and builds a script that directly runs
the load-env-* script.

Together, nix-run and myEnvRun allows you to set up an environment
that can be loaded in this way:

  envs.nix:
    {
      gcc = myEnvRun {
        name = "gcc";
        buildInputs = [ gcc ];
      };
    }

  $ nix-run -A gcc envs.nix

You end up directly in your environment without having to do
nix-env -i. You will always have a fresh environment and you
don't have to pollute you profile with a lot of env packages.
This commit is contained in:
Rickard Nilsson 2013-09-13 16:48:54 +02:00
parent 214e92081f
commit 8685278f11
3 changed files with 84 additions and 0 deletions

View File

@ -0,0 +1,6 @@
{ writeScript, bash, myEnvFun }: args:
let env = myEnvFun args; in writeScript "envrun-${args.name}" ''
#!${bash}/bin/bash
${env}/bin/load-env-${args.name}
''

View File

@ -0,0 +1,72 @@
{ stdenv, bash, writeScript }:
let
nix-run = writeScript "nix-run" ''
#!${bash}/bin/bash
# Runs nix-build and executes the result
# All arguments before "--" are given to nix-build,
# and all arguments after "--" are given to the
# executed command. stdin is redirected to the executed
# command.
out=$(mktemp)
rm "$out"
# parse args into args1 and args2, separated by --
# args1 goes to nix-build, args2 goes to the built command
args1=("$@")
args2=()
for i in "''${!args1[@]}"; do
if [ "''${args1[$i]}" == "--" ]; then
args2=("''${args1[@]:$((i+1))}")
args1=("''${args1[@]:0:$((i))}")
break
fi
done
if nix-build -o "$out" "''${args1[@]}" >/dev/null; then
target=$(readlink -m "$out")
unlink "$out"
if test -f "$target" && test -x "$target"; then
exec "$target" "''${args2[@]}" <&0
else
echo "nix-run: No executable target produced by nix-build"
exit 1
fi
else
echo "nix-run: nix-build failed"
exit 1
fi
'';
in stdenv.mkDerivation {
name = "nix-run";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
ln -s ${nix-run} $out/bin/nix-run
'';
meta = {
description = ''
Wrapper around nix-build that automatically executes the binary
produced by the provided Nix expression.
'';
longDescription = ''
nix-run invokes nix-build with any options given to it. It then
expects one executable file to be produced by nix-build. If this
is the case, that file is executed with any options that is given
to nix-run after a <literal>--</literal> option separator. If no
executable file is produced by nix-build, nix-run will exit with
an error. An example invocation of nix-run is <literal>nix-run -A
myattr mynix.nix -- -o opt</literal>. nix-run will then build the
attribute <literal>myattr</literal> from the Nix expression given
in the file <literal>mynix.nix</literal>. If a single executable
file is produced, that file is executed with the option
<literal>-o opt</literal>.
'';
maintainers = [ stdenv.lib.maintainers.rickynils ];
platforms = stdenv.lib.platforms.linux;
};
}

View File

@ -10352,6 +10352,12 @@ let
inherit (stdenv) mkDerivation;
};
myEnvRun = import ../build-support/my-env-run {
inherit writeScript bash myEnvFun;
};
nix-run = callPackage ../misc/nix-run { };
# patoline requires a rather large ocaml compilation environment.
# this is why it is build as an environment and not just a normal package.
# remark : the emacs mode is also installed, but you have to adjust your load-path.