static-nix-shell: factor out some commonalities between bash & python impls

This commit is contained in:
Colin 2023-05-13 11:24:58 +00:00
parent 0270ccdebd
commit b6ae9f3646

View File

@ -19,22 +19,22 @@ let
}) {} expr; }) {} expr;
"set" = expr: expr; "set" = expr: expr;
})."${typeOf expr}" expr; })."${typeOf expr}" expr;
in { in rec {
mkBash = { pname, pkgs ? {}, srcPath ? pname, ...}@attrs: # transform a file which uses `#!/usr/bin/env nix-shell` shebang
let # into a derivation that can be built statically.
pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs; #
pkgsEnv = attrValues pkgsAsAttrs; # pkgs may take the following form:
pkgsStr = concatStringsSep "" (map # - [ "pkgNameA" "pkgNameB" ... ]
(pname: " -p ${pname}") # - { pkgNameA = pkgValueA; pkgNameB = pkgValueB; ... }
(attrNames pkgsAsAttrs) # - ps: <evaluate to one of the above exprs>
); mkShell = { pname, interpreter, interpreterName, pkgsEnv, pkgsStr, srcPath ? pname, ...}@attrs:
in stdenv.mkDerivation ({ stdenv.mkDerivation ({
version = "0.1.0"; # default version version = "0.1.0"; # default version
patchPhase = '' patchPhase = ''
substituteInPlace ${srcPath} \ substituteInPlace ${srcPath} \
--replace '#!/usr/bin/env nix-shell' '#!${pkgs'.bash}/bin/bash' \ --replace '#!/usr/bin/env nix-shell' '#!${interpreter}' \
--replace \ --replace \
'#!nix-shell -i bash -p ${pkgsStr}' \ '#!nix-shell -i ${interpreterName}${pkgsStr}' \
'# nix deps evaluated statically' '# nix deps evaluated statically'
''; '';
nativeBuildInputs = [ makeWrapper ]; nativeBuildInputs = [ makeWrapper ];
@ -49,18 +49,27 @@ in {
wrapProgram $out/bin/${srcPath} \ wrapProgram $out/bin/${srcPath} \
--suffix PATH : ${lib.makeBinPath pkgsEnv } --suffix PATH : ${lib.makeBinPath pkgsEnv }
''; '';
} // (removeAttrs attrs [ "pkgs" "pyPkgs" "srcPath" ]) } // (removeAttrs attrs [ "interpreter" "interpreterName" "pkgsEnv" "pkgsStr" "srcPath" ])
); );
# transform a file which uses `#!/usr/bin/env nix-shell` shebang with a `python3` interpreter # `mkShell` specialization for `nix-shell -i bash` scripts.
# into a derivation that can be built statically. mkBash = { pname, pkgs ? {}, srcPath ? pname, ...}@attrs:
# let
# pkgs and pyPkgs may take the following form: pkgsAsAttrs = pkgsToAttrs "" pkgs' pkgs;
# - [ "pkgNameA" "pkgNameB" ... ] pkgsEnv = attrValues pkgsAsAttrs;
# - { pkgNameA = pkgValueA; pkgNameB = pkgValueB; ... } pkgsStr = concatStringsSep "" (map
# - ps: <evaluate to one of the above exprs> (pname: " -p ${pname}")
# (attrNames pkgsAsAttrs)
# for pyPkgs, names are assumed to be relative to `"ps"` if specified in list form. );
in mkShell ({
inherit pkgsEnv pkgsStr;
interpreter = "${pkgs'.bash}/bin/bash";
interpreterName = "bash";
} // (removeAttrs attrs [ "pkgs" ])
);
# `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.
mkPython3Bin = { pname, pkgs ? {}, pyPkgs ? {}, srcPath ? pname, ... }@attrs: mkPython3Bin = { pname, pkgs ? {}, pyPkgs ? {}, srcPath ? pname, ... }@attrs:
let let
pyEnv = python3.withPackages (ps: attrValues ( pyEnv = python3.withPackages (ps: attrValues (
@ -76,27 +85,11 @@ in {
(pname: " -p ${pname}") (pname: " -p ${pname}")
(attrNames pkgsAsAttrs) (attrNames pkgsAsAttrs)
); );
in stdenv.mkDerivation ({ in mkShell ({
version = "0.1.0"; # default version inherit pkgsEnv;
patchPhase = '' pkgsStr = " -p \"python3.withPackages (ps: [ ${pyPkgsStr} ])\"${pkgsStr}";
substituteInPlace ${srcPath} \ interpreter = pyEnv.interpreter;
--replace '#!/usr/bin/env nix-shell' '#!${pyEnv.interpreter}' \ interpreterName = "python3";
--replace \ } // (removeAttrs attrs [ "pkgs" "pyPkgs" ])
'#!nix-shell -i python3 -p "python3.withPackages (ps: [ ${pyPkgsStr} ])"${pkgsStr}' \
'# nix deps evaluated statically'
'';
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
mv ${srcPath} $out/bin/${srcPath}
# ensure that all nix-shell references were substituted
! grep nix-shell $out/bin/${srcPath}
# add runtime dependencies to PATH
wrapProgram $out/bin/${srcPath} \
--suffix PATH : ${lib.makeBinPath pkgsEnv }
'';
} // (removeAttrs attrs [ "pkgs" "pyPkgs" "srcPath" ])
); );
} }