2023-04-27 08:00:38 +00:00
|
|
|
{ pkgs
|
2023-08-23 11:14:13 +00:00
|
|
|
, bash
|
2023-04-27 08:00:38 +00:00
|
|
|
, lib
|
2023-04-27 08:14:11 +00:00
|
|
|
, makeWrapper
|
2023-03-22 21:21:00 +00:00
|
|
|
, python3
|
2023-04-27 08:00:38 +00:00
|
|
|
, stdenv
|
2023-08-23 11:14:13 +00:00
|
|
|
, zsh
|
2023-03-22 21:21:00 +00:00
|
|
|
}:
|
|
|
|
|
2023-04-27 08:00:38 +00:00
|
|
|
let
|
2023-05-02 01:19:16 +00:00
|
|
|
inherit (builtins) attrNames attrValues concatStringsSep foldl' map typeOf;
|
2023-04-27 08:00:38 +00:00
|
|
|
inherit (lib) concatMapAttrs;
|
2023-08-23 11:14:13 +00:00
|
|
|
bash' = bash;
|
2023-04-27 08:00:38 +00:00
|
|
|
pkgs' = pkgs;
|
2023-08-23 11:14:13 +00:00
|
|
|
python3' = python3;
|
|
|
|
zsh' = zsh;
|
2023-05-13 10:31:48 +00:00
|
|
|
# create an attrset of
|
|
|
|
# <name> = expected string in the nix-shell invocation
|
|
|
|
# <value> = package to provide
|
|
|
|
pkgsToAttrs = prefix: pkgSet: expr: ({
|
2023-06-07 06:53:45 +00:00
|
|
|
# branch based on the type of `expr`
|
2023-05-13 10:31:48 +00:00
|
|
|
"lambda" = expr: pkgsToAttrs prefix pkgSet (expr pkgSet);
|
|
|
|
"list" = expr: foldl' (acc: pname: acc // {
|
2023-06-07 06:53:45 +00:00
|
|
|
"${prefix + pname}" = lib.getAttrFromPath (lib.splitString "." pname) pkgSet;
|
2023-05-13 10:31:48 +00:00
|
|
|
}) {} expr;
|
|
|
|
"set" = expr: expr;
|
|
|
|
})."${typeOf expr}" expr;
|
2023-05-13 11:24:58 +00:00
|
|
|
in rec {
|
|
|
|
# transform a file which uses `#!/usr/bin/env nix-shell` shebang
|
|
|
|
# into a derivation that can be built statically.
|
|
|
|
#
|
|
|
|
# pkgs may take the following form:
|
|
|
|
# - [ "pkgNameA" "pkgNameB" ... ]
|
|
|
|
# - { pkgNameA = pkgValueA; pkgNameB = pkgValueB; ... }
|
|
|
|
# - ps: <evaluate to one of the above exprs>
|
2023-05-13 11:39:46 +00:00
|
|
|
mkShell = {
|
|
|
|
pname,
|
|
|
|
interpreter,
|
|
|
|
interpreterName ? lib.last (builtins.split "/" interpreter),
|
|
|
|
pkgsEnv,
|
|
|
|
pkgExprs,
|
|
|
|
srcPath ? pname,
|
|
|
|
...
|
|
|
|
}@attrs:
|
|
|
|
let
|
|
|
|
pkgsStr = concatStringsSep "" (map
|
|
|
|
(pname: " -p ${pname}")
|
|
|
|
pkgExprs
|
|
|
|
);
|
2023-06-22 23:33:49 +00:00
|
|
|
# allow any package to be a list of packages, to support things like
|
|
|
|
# -p python3Packages.foo.propagatedBuildInputs
|
|
|
|
pkgsEnv' = lib.flatten pkgsEnv;
|
2023-09-24 17:51:19 +00:00
|
|
|
doWrap = pkgsEnv' != [];
|
2023-05-13 11:39:46 +00:00
|
|
|
in
|
2023-05-13 11:24:58 +00:00
|
|
|
stdenv.mkDerivation ({
|
2023-05-13 10:31:48 +00:00
|
|
|
version = "0.1.0"; # default version
|
|
|
|
patchPhase = ''
|
|
|
|
substituteInPlace ${srcPath} \
|
2023-05-13 11:24:58 +00:00
|
|
|
--replace '#!/usr/bin/env nix-shell' '#!${interpreter}' \
|
2023-05-13 10:31:48 +00:00
|
|
|
--replace \
|
2023-05-13 11:24:58 +00:00
|
|
|
'#!nix-shell -i ${interpreterName}${pkgsStr}' \
|
2023-05-13 10:31:48 +00:00
|
|
|
'# nix deps evaluated statically'
|
|
|
|
'';
|
|
|
|
nativeBuildInputs = [ makeWrapper ];
|
|
|
|
installPhase = ''
|
2023-05-27 09:57:09 +00:00
|
|
|
runHook preInstall
|
2023-05-13 10:31:48 +00:00
|
|
|
mkdir -p $out/bin
|
|
|
|
mv ${srcPath} $out/bin/${srcPath}
|
|
|
|
|
|
|
|
# ensure that all nix-shell references were substituted
|
2023-05-13 11:39:46 +00:00
|
|
|
(! grep nix-shell $out/bin/${srcPath}) || exit 1
|
2023-05-13 10:31:48 +00:00
|
|
|
|
2023-09-24 17:51:19 +00:00
|
|
|
'' + lib.optionalString doWrap ''
|
2023-05-13 10:31:48 +00:00
|
|
|
# add runtime dependencies to PATH
|
|
|
|
wrapProgram $out/bin/${srcPath} \
|
2023-06-22 23:33:49 +00:00
|
|
|
--suffix PATH : ${lib.makeBinPath pkgsEnv' }
|
2023-09-24 17:51:19 +00:00
|
|
|
'' + ''
|
2023-05-27 09:57:09 +00:00
|
|
|
|
|
|
|
runHook postInstall
|
2023-05-13 10:31:48 +00:00
|
|
|
'';
|
2023-05-13 11:39:46 +00:00
|
|
|
} // (removeAttrs attrs [ "interpreter" "interpreterName" "pkgsEnv" "pkgExprs" "srcPath" ])
|
2023-05-13 10:31:48 +00:00
|
|
|
);
|
|
|
|
|
2023-05-13 11:24:58 +00:00
|
|
|
# `mkShell` specialization for `nix-shell -i bash` scripts.
|
2023-08-23 11:14:13 +00:00
|
|
|
mkBash = { pname, pkgs ? {}, srcPath ? pname, bash ? bash', ...}@attrs:
|
2023-05-13 11:24:58 +00:00
|
|
|
let
|
|
|
|
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
|
|
|
pkgsEnv = attrValues pkgsAsAttrs;
|
2023-05-13 11:39:46 +00:00
|
|
|
pkgExprs = attrNames pkgsAsAttrs;
|
2023-05-13 11:24:58 +00:00
|
|
|
in mkShell ({
|
2023-05-13 11:39:46 +00:00
|
|
|
inherit pkgsEnv pkgExprs;
|
2023-08-23 11:14:13 +00:00
|
|
|
interpreter = "${bash}/bin/bash";
|
|
|
|
} // (removeAttrs attrs [ "bash" "pkgs" ])
|
2023-05-13 11:24:58 +00:00
|
|
|
);
|
|
|
|
|
2023-06-07 07:20:27 +00:00
|
|
|
# `mkShell` specialization for `nix-shell -i zsh` scripts.
|
2023-08-23 11:14:13 +00:00
|
|
|
mkZsh = { pname, pkgs ? {}, srcPath ? pname, zsh ? zsh', ...}@attrs:
|
2023-06-07 07:20:27 +00:00
|
|
|
let
|
|
|
|
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
|
|
|
pkgsEnv = attrValues pkgsAsAttrs;
|
|
|
|
pkgExprs = attrNames pkgsAsAttrs;
|
|
|
|
in mkShell ({
|
|
|
|
inherit pkgsEnv pkgExprs;
|
2023-08-23 11:14:13 +00:00
|
|
|
interpreter = "${zsh}/bin/zsh";
|
|
|
|
} // (removeAttrs attrs [ "pkgs" "zsh" ])
|
2023-06-07 07:20:27 +00:00
|
|
|
);
|
|
|
|
|
2023-05-13 11:24:58 +00:00
|
|
|
# `mkShell` specialization for invocations of `nix-shell -p "python3.withPackages (...)"`
|
|
|
|
# pyPkgs argument is parsed the same as pkgs, except that names are assumed to be relative to `"ps"` if specified in list form.
|
2023-07-15 06:38:50 +00:00
|
|
|
# TODO: rename to `mkPython3` for consistency with e.g. `mkBash`
|
2023-08-23 11:14:13 +00:00
|
|
|
mkPython3Bin = { pname, pkgs ? {}, pyPkgs ? {}, srcPath ? pname, python3 ? python3', ... }@attrs:
|
2023-03-22 21:21:00 +00:00
|
|
|
let
|
2023-04-27 08:00:38 +00:00
|
|
|
pyEnv = python3.withPackages (ps: attrValues (
|
|
|
|
pkgsToAttrs "ps." ps pyPkgs
|
|
|
|
));
|
|
|
|
pyPkgsStr = concatStringsSep " " (attrNames (
|
|
|
|
pkgsToAttrs "ps." {} pyPkgs
|
|
|
|
));
|
|
|
|
|
|
|
|
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
|
|
|
|
pkgsEnv = attrValues pkgsAsAttrs;
|
2023-05-13 11:39:46 +00:00
|
|
|
pkgExprs = [
|
|
|
|
"\"python3.withPackages (ps: [ ${pyPkgsStr} ])\""
|
|
|
|
] ++ (attrNames pkgsAsAttrs);
|
2023-05-13 11:24:58 +00:00
|
|
|
in mkShell ({
|
2023-05-13 11:39:46 +00:00
|
|
|
inherit pkgsEnv pkgExprs;
|
2023-05-13 11:24:58 +00:00
|
|
|
interpreter = pyEnv.interpreter;
|
|
|
|
interpreterName = "python3";
|
2023-08-23 11:14:13 +00:00
|
|
|
} // (removeAttrs attrs [ "pkgs" "pyPkgs" "python3" ])
|
2023-03-22 21:21:00 +00:00
|
|
|
);
|
|
|
|
}
|