mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-06-07 13:53:42 +00:00
Compare commits
6 Commits
master
...
devShellTo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bc9864e04 | ||
|
|
ce7fbda708 | ||
|
|
fd0b01320a | ||
|
|
94812628f5 | ||
|
|
1289d19440 | ||
|
|
5b15d2dd85 |
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
|
runtimeShell,
|
||||||
|
bashInteractive,
|
||||||
|
stdenv,
|
||||||
writeTextFile,
|
writeTextFile,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
@@ -72,4 +75,101 @@ rec {
|
|||||||
# https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1253
|
# https://github.com/NixOS/nix/blob/2.8.0/src/libexpr/primops.cc#L1253
|
||||||
lib.genAttrs outputList (output: builtins.unsafeDiscardStringContext outputMap.${output}.outPath);
|
lib.genAttrs outputList (output: builtins.unsafeDiscardStringContext outputMap.${output}.outPath);
|
||||||
|
|
||||||
|
toBashEnv =
|
||||||
|
{ env }:
|
||||||
|
lib.concatStringsSep "\n" (
|
||||||
|
lib.mapAttrsToList (
|
||||||
|
name: value:
|
||||||
|
if lib.isValidPosixName name then ''export ${name}=${lib.escapeShellArg value}'' else ""
|
||||||
|
) env
|
||||||
|
);
|
||||||
|
|
||||||
|
buildShellEnv =
|
||||||
|
{
|
||||||
|
drvAttrs,
|
||||||
|
promptPrefix ? "build shell",
|
||||||
|
promptName ? null,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
name = drvAttrs.pname or drvAttrs.name or "shell";
|
||||||
|
env = unstructuredDerivationInputEnv { inherit drvAttrs; };
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation (finalAttrs: {
|
||||||
|
name = "${name}-env";
|
||||||
|
passAsFile = [
|
||||||
|
"bashEnv"
|
||||||
|
"bashrc"
|
||||||
|
"runShell"
|
||||||
|
];
|
||||||
|
bashEnv = toBashEnv { inherit env; };
|
||||||
|
bashrc = ''
|
||||||
|
export NIXPKGS_SHELL_TMP="$(mktemp -d --tmpdir nixpkgs-shell-${name}.XXXXXX)"
|
||||||
|
export TMPDIR="$NIXPKGS_SHELL_TMP"
|
||||||
|
export TEMPDIR="$NIXPKGS_SHELL_TMP"
|
||||||
|
export TMP="$NIXPKGS_SHELL_TMP"
|
||||||
|
export TEMP="$NIXPKGS_SHELL_TMP"
|
||||||
|
|
||||||
|
echo "Using TMPDIR=$TMPDIR"
|
||||||
|
|
||||||
|
source @envbash@
|
||||||
|
|
||||||
|
mkdir -p $TMP/outputs
|
||||||
|
for _output in $outputs; do
|
||||||
|
export "''${_output}=$TMP/outputs/''${_output}"
|
||||||
|
done
|
||||||
|
|
||||||
|
source @stdenv@/setup
|
||||||
|
|
||||||
|
# Set a distinct prompt to make it clear that we are in a build shell
|
||||||
|
case "$PS1" in
|
||||||
|
*"(build shell $name)"*)
|
||||||
|
echo "It looks like your running a build shell inside a build shell."
|
||||||
|
echo "It might work, but this is probably not what you want."
|
||||||
|
echo "You may want to exit your shell before loading a new one."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Prefix a line to the prompt to indicate that we are in a build shell
|
||||||
|
PS1=$"\n(\[\033[1;33m\]"${lib.escapeShellArg promptPrefix}$": \[\033[1;34m\]"${
|
||||||
|
if promptName != null then lib.escapeShellArg promptName else ''"$name"''
|
||||||
|
}"\[\033[1;33m\]\[\033[0m\]) $PS1"
|
||||||
|
|
||||||
|
runHook shellHook
|
||||||
|
'';
|
||||||
|
buildCommand = ''
|
||||||
|
mkdir -p $out/lib $out/bin
|
||||||
|
bashrc="$out/lib/bashrc"
|
||||||
|
envbash="$out/lib/env.bash"
|
||||||
|
|
||||||
|
mv "$bashEnvPath" "$envbash"
|
||||||
|
substitute "$bashrcPath" "$bashrc" \
|
||||||
|
--replace-fail "@envbash@" "$envbash" \
|
||||||
|
--replace-fail "@stdenv@" "$stdenv" \
|
||||||
|
;
|
||||||
|
|
||||||
|
substitute ${./run-shell.sh} "$out/bin/run-shell" \
|
||||||
|
--replace-fail "@bashrc@" "$bashrc" \
|
||||||
|
--replace-fail "@runtimeShell@" "${runtimeShell}" \
|
||||||
|
--replace-fail "@bashInteractive@" "${bashInteractive}" \
|
||||||
|
;
|
||||||
|
|
||||||
|
# NOTE: most other files are script for the source command, and not
|
||||||
|
# standalone executables, so they should not be made executable.
|
||||||
|
chmod a+x $out/bin/run-shell
|
||||||
|
'';
|
||||||
|
preferLocalBuild = true;
|
||||||
|
passthru = {
|
||||||
|
# Work this as a shell environment, so that commands like `nix-shell`
|
||||||
|
# will be able to check it and use it correctly. This also lets Nix know
|
||||||
|
# to stop when the user requests pkg.devShell explicitly, or a different
|
||||||
|
# attribute containing a shell environment.
|
||||||
|
isShellEnv = true;
|
||||||
|
devShell = throw "You're trying to access the devShell attribute of a shell environment. We appreciate that this is very \"meta\" and interesting, but it's usually just not what you want. Most likely you've selected one `.devShell` to deep in an expression or on the command line. Try removing the last one.";
|
||||||
|
};
|
||||||
|
meta = {
|
||||||
|
description = "An environment similar to the build environment of ${name}";
|
||||||
|
# TODO longDescription
|
||||||
|
mainProgram = "run-shell";
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
87
pkgs/build-support/dev-shell-tools/run-shell.sh
Normal file
87
pkgs/build-support/dev-shell-tools/run-shell.sh
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#!@runtimeShell@
|
||||||
|
|
||||||
|
# baked variables, not exported
|
||||||
|
bashrc='@bashrc@'
|
||||||
|
bash='@bashInteractive@/bin/bash'
|
||||||
|
|
||||||
|
# detected variables and option defaults
|
||||||
|
shell="$(basename $SHELL)"
|
||||||
|
mode=interactive
|
||||||
|
|
||||||
|
# remaining args
|
||||||
|
args=()
|
||||||
|
|
||||||
|
# parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-c)
|
||||||
|
mode=commands
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
mode=exec
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
args+=("$1")
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
case "$mode" in
|
||||||
|
interactive)
|
||||||
|
;;
|
||||||
|
commands)
|
||||||
|
if ${#args[@]} -eq 0; then
|
||||||
|
echo "nixpkgs: You've requested a command shell, but didn't provide a command."
|
||||||
|
echo " Please provide a command to run."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
exec)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
invokeWithArgs() {
|
||||||
|
bash -c 'source "'"$bashrc"'"; _script="$(shift)"; _args=("$@"); eval "$_script"' -- "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# For bash, we'll run the interactive variant of the version Nixpkgs uses.
|
||||||
|
# For other shells, version correctness can't be a goal, so it's best
|
||||||
|
# to launch the user's shell from $SHELL. This also avoids bringing in
|
||||||
|
# dependencies of which N-1 aren't needed. Keeps it quick.
|
||||||
|
launchBash() {
|
||||||
|
case "$mode" in
|
||||||
|
interactive)
|
||||||
|
exec "$bash" --rcfile "$bashrc" "${args[@]}"
|
||||||
|
;;
|
||||||
|
commands)
|
||||||
|
exec "$bash" -c 'source "'"$bashrc"'"; _script="$1"; shift; eval "$_script"' -- "${args[@]}"
|
||||||
|
;;
|
||||||
|
exec)
|
||||||
|
exec "$bash" -c 'source "'"$bashrc"'"; "$@"' -- "${args[@]}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
launchShell() {
|
||||||
|
case "$shell" in
|
||||||
|
bash|"")
|
||||||
|
launchBash
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
(
|
||||||
|
echo "nixpkgs: I see that you weren't running bash. That's cool, but"
|
||||||
|
echo " stdenv derivations are built with bash, so that's what"
|
||||||
|
echo " I'll run for you by default. We'd love to have support"
|
||||||
|
echo " for many shells, so PRs are welcome!"
|
||||||
|
) >&2
|
||||||
|
launchBash
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
launchShell
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
bash,
|
||||||
|
coreutils,
|
||||||
devShellTools,
|
devShellTools,
|
||||||
emptyFile,
|
emptyFile,
|
||||||
|
gnugrep,
|
||||||
lib,
|
lib,
|
||||||
|
runCommand,
|
||||||
stdenv,
|
stdenv,
|
||||||
hello,
|
hello,
|
||||||
writeText,
|
writeText,
|
||||||
@@ -187,4 +191,70 @@ lib.recurseIntoAttrs {
|
|||||||
"args"
|
"args"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# derivation: Call it directly so that we get a minimal environment to run in
|
||||||
|
buildHelloInShell =
|
||||||
|
derivation {
|
||||||
|
inherit (stdenv.buildPlatform) system;
|
||||||
|
name = "buildHelloInShell";
|
||||||
|
builder = "${bash}/bin/bash";
|
||||||
|
PATH = lib.makeBinPath [
|
||||||
|
coreutils
|
||||||
|
gnugrep
|
||||||
|
];
|
||||||
|
args = [
|
||||||
|
"-euo"
|
||||||
|
"pipefail"
|
||||||
|
"-c"
|
||||||
|
''
|
||||||
|
${lib.getExe hello.devShell} -c 'genericBuild && ln -s $out "'"$PWD"'/result"'
|
||||||
|
ls -al
|
||||||
|
./result/bin/hello | grep -i 'hello, world'
|
||||||
|
(set -x; [[ ! -e $out ]])
|
||||||
|
touch $out
|
||||||
|
''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
# Required package attributes for Nixpkgs (CI)
|
||||||
|
meta = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
various =
|
||||||
|
let
|
||||||
|
hello2 = hello.overrideAttrs (o: {
|
||||||
|
shellHook = ''
|
||||||
|
echo 'shellHook says hi :)'
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
inherit (hello2) devShell;
|
||||||
|
in
|
||||||
|
derivation {
|
||||||
|
inherit (stdenv.buildPlatform) system;
|
||||||
|
name = "various";
|
||||||
|
builder = "${bash}/bin/bash";
|
||||||
|
PATH = lib.makeBinPath [
|
||||||
|
coreutils
|
||||||
|
gnugrep
|
||||||
|
];
|
||||||
|
args = [
|
||||||
|
"-euo"
|
||||||
|
"pipefail"
|
||||||
|
"-c"
|
||||||
|
''
|
||||||
|
${lib.getExe devShell} -c 'echo "hello, world"' \
|
||||||
|
| grep -F 'hello, world'
|
||||||
|
${lib.getExe devShell} -c 'echo "hello, world"' \
|
||||||
|
| grep -F 'hello, world'
|
||||||
|
|
||||||
|
ls -al
|
||||||
|
(set -x; [[ ! -e $out ]])
|
||||||
|
touch $out
|
||||||
|
''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
# Required package attributes for Nixpkgs (CI)
|
||||||
|
meta = { };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
lib,
|
lib,
|
||||||
stdenv,
|
stdenv,
|
||||||
buildEnv,
|
buildEnv,
|
||||||
|
devShellTools,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
# A special kind of derivation that is only meant to be consumed by the
|
# A special kind of derivation that is only meant to be consumed by the
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
nativeBuildInputs ? [ ],
|
nativeBuildInputs ? [ ],
|
||||||
propagatedBuildInputs ? [ ],
|
propagatedBuildInputs ? [ ],
|
||||||
propagatedNativeBuildInputs ? [ ],
|
propagatedNativeBuildInputs ? [ ],
|
||||||
|
passthru ? { },
|
||||||
...
|
...
|
||||||
}@attrs:
|
}@attrs:
|
||||||
let
|
let
|
||||||
@@ -42,6 +44,7 @@ let
|
|||||||
in
|
in
|
||||||
|
|
||||||
stdenv.mkDerivation (
|
stdenv.mkDerivation (
|
||||||
|
finalAttrs:
|
||||||
{
|
{
|
||||||
inherit name;
|
inherit name;
|
||||||
|
|
||||||
@@ -68,6 +71,33 @@ stdenv.mkDerivation (
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
preferLocalBuild = true;
|
preferLocalBuild = true;
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
devShell =
|
||||||
|
let
|
||||||
|
inherit (finalAttrs.finalPackage) drvAttrs;
|
||||||
|
in
|
||||||
|
devShellTools.buildShellEnv {
|
||||||
|
inherit drvAttrs;
|
||||||
|
|
||||||
|
# The default prefix is "build shell", but this shell is not derived
|
||||||
|
# directly from a derivation, so we set a more generic title.
|
||||||
|
promptPrefix = "nix";
|
||||||
|
|
||||||
|
# Change the default name
|
||||||
|
promptName =
|
||||||
|
if
|
||||||
|
# name was passed originally
|
||||||
|
attrs ? name
|
||||||
|
# or with overrideAttrs
|
||||||
|
|| drvAttrs.name != "nix-shell"
|
||||||
|
then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
"mkShell";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// passthru;
|
||||||
}
|
}
|
||||||
// rest
|
// rest
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
ghcWithHoogle,
|
ghcWithHoogle,
|
||||||
ghcWithPackages,
|
ghcWithPackages,
|
||||||
nodejs,
|
nodejs,
|
||||||
|
devShellTools,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -1045,6 +1046,8 @@ lib.fix (
|
|||||||
// env';
|
// env';
|
||||||
} "echo $nativeBuildInputs $buildInputs > $out";
|
} "echo $nativeBuildInputs $buildInputs > $out";
|
||||||
|
|
||||||
|
# Specialise the devShell attribute, so we get our improved shell.
|
||||||
|
devShell = env.devShell;
|
||||||
env = envFunc { };
|
env = envFunc { };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -97,11 +97,13 @@ let
|
|||||||
let
|
let
|
||||||
args = stageFun prevStage;
|
args = stageFun prevStage;
|
||||||
args' = args // {
|
args' = args // {
|
||||||
stdenv = args.stdenv // {
|
stdenv = args.stdenv.override (prevArgs: {
|
||||||
# For debugging
|
# Extra package attributes for debugging
|
||||||
__bootPackages = prevStage;
|
extraAttrs = prevArgs.extraAttrs or { } // {
|
||||||
__hatPackages = nextStage;
|
__bootPackages = prevStage;
|
||||||
};
|
__hatPackages = nextStage;
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
thisStage =
|
thisStage =
|
||||||
if args.__raw or false then
|
if args.__raw or false then
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ let
|
|||||||
|
|
||||||
shell,
|
shell,
|
||||||
allowedRequisites ? null,
|
allowedRequisites ? null,
|
||||||
|
# Extra package attributes, like passthru. Not passed to `derivation`.
|
||||||
extraAttrs ? { },
|
extraAttrs ? { },
|
||||||
overrides ? (self: super: { }),
|
overrides ? (self: super: { }),
|
||||||
config,
|
config,
|
||||||
@@ -63,6 +64,9 @@ let
|
|||||||
# This is convenient to have as a parameter so the stdenv "adapters" work better
|
# This is convenient to have as a parameter so the stdenv "adapters" work better
|
||||||
mkDerivationFromStdenv ?
|
mkDerivationFromStdenv ?
|
||||||
stdenv: (import ./make-derivation.nix { inherit lib config; } stdenv).mkDerivation,
|
stdenv: (import ./make-derivation.nix { inherit lib config; } stdenv).mkDerivation,
|
||||||
|
|
||||||
|
# callPackage for "passthru" utilities only
|
||||||
|
callPackage ? null,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -90,6 +94,11 @@ let
|
|||||||
|
|
||||||
stdenv = (stdenv-overridable argsStdenv);
|
stdenv = (stdenv-overridable argsStdenv);
|
||||||
|
|
||||||
|
devShellTools =
|
||||||
|
if callPackage == null then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
callPackage ../../build-support/dev-shell-tools { inherit stdenv; };
|
||||||
in
|
in
|
||||||
# The stdenv that we are producing.
|
# The stdenv that we are producing.
|
||||||
derivation (
|
derivation (
|
||||||
@@ -213,6 +222,8 @@ let
|
|||||||
# commands and extglob affects the Bash parser, we enable extglob always.
|
# commands and extglob affects the Bash parser, we enable extglob always.
|
||||||
shellDryRun = "${stdenv.shell} -n -O extglob";
|
shellDryRun = "${stdenv.shell} -n -O extglob";
|
||||||
|
|
||||||
|
buildShellEnv = if devShellTools ? buildShellEnv then devShellTools.buildShellEnv else _: null;
|
||||||
|
|
||||||
tests = {
|
tests = {
|
||||||
succeedOnFailure = import ../tests/succeedOnFailure.nix { inherit stdenv; };
|
succeedOnFailure = import ../tests/succeedOnFailure.nix { inherit stdenv; };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -874,6 +874,8 @@ let
|
|||||||
|
|
||||||
inherit passthru overrideAttrs;
|
inherit passthru overrideAttrs;
|
||||||
inherit meta;
|
inherit meta;
|
||||||
|
devShell = stdenv.buildShellEnv { drvAttrs = derivationArg; };
|
||||||
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
# Pass through extra attributes that are not inputs, but
|
# Pass through extra attributes that are not inputs, but
|
||||||
|
|||||||
@@ -167,6 +167,7 @@ let
|
|||||||
name,
|
name,
|
||||||
overrides ? (self: super: { }),
|
overrides ? (self: super: { }),
|
||||||
extraNativeBuildInputs ? [ ],
|
extraNativeBuildInputs ? [ ],
|
||||||
|
callPackage ? null,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -223,6 +224,7 @@ let
|
|||||||
);
|
);
|
||||||
|
|
||||||
overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
|
overrides = self: super: (overrides self super) // { fetchurl = thisStdenv.fetchurlBoot; };
|
||||||
|
inherit callPackage;
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -170,7 +170,12 @@ let
|
|||||||
pkgs = self.pkgsHostTarget;
|
pkgs = self.pkgsHostTarget;
|
||||||
targetPackages = self.pkgsTargetTarget;
|
targetPackages = self.pkgsTargetTarget;
|
||||||
|
|
||||||
inherit stdenv stdenvNoCC;
|
stdenv = stdenv.override (o: {
|
||||||
|
callPackage = self.callPackage;
|
||||||
|
});
|
||||||
|
stdenvNoCC = stdenvNoCC.override (o: {
|
||||||
|
callPackage = self.callPackage;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
splice = self: super: import ./splice.nix lib self (adjacentPackages != null);
|
splice = self: super: import ./splice.nix lib self (adjacentPackages != null);
|
||||||
|
|||||||
Reference in New Issue
Block a user