184
flake.nix
184
flake.nix
@@ -11,112 +11,104 @@
|
|||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
flake-utils,
|
flake-utils,
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
flake-utils.lib.eachDefaultSystem (
|
flake-utils.lib.eachDefaultSystem (
|
||||||
system:
|
system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
|
||||||
|
# patched proot (relative interp + rpath)
|
||||||
|
prootPatched = (pkgs.proot.override { enablePython = false; }).overrideAttrs (prev: {
|
||||||
|
postFixup = (prev.postFixup or "") + ''
|
||||||
|
exe=$out/bin/proot
|
||||||
|
if interp="$(${pkgs.patchelf}/bin/patchelf --print-interpreter "$exe" 2>/dev/null)"; then
|
||||||
|
${pkgs.patchelf}/bin/patchelf --set-interpreter ."$interp" "$exe"
|
||||||
|
fi
|
||||||
|
if rpath="$(${pkgs.patchelf}/bin/patchelf --print-rpath "$exe" 2>/dev/null)"; then
|
||||||
|
${pkgs.patchelf}/bin/patchelf \
|
||||||
|
--set-rpath "$(printf %s "$rpath" | sed 's|/nix/store/|./nix/store/|g')" "$exe"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
bundlers = rec {
|
bundlers.proot-bundler =
|
||||||
proot-bundler =
|
drv:
|
||||||
drv:
|
let
|
||||||
pkgs.stdenvNoCC.mkDerivation {
|
ci = pkgs.closureInfo {
|
||||||
name = "myApp.run";
|
rootPaths = [
|
||||||
nativeBuildInputs = [
|
drv
|
||||||
pkgs.nix
|
prootPatched
|
||||||
pkgs.coreutils
|
|
||||||
pkgs.findutils
|
|
||||||
pkgs.gnutar
|
|
||||||
pkgs.gzip
|
|
||||||
pkgs.patchelf
|
|
||||||
];
|
];
|
||||||
# patch proot as you described
|
|
||||||
prootPatched = (pkgs.proot.override { enablePython = false; }).overrideAttrs (_: {
|
|
||||||
postFixup = ''
|
|
||||||
exe=$out/bin/proot
|
|
||||||
${pkgs.patchelf}/bin/patchelf \
|
|
||||||
--set-interpreter ."$(${pkgs.patchelf}/bin/patchelf --print-interpreter $exe)" \
|
|
||||||
--set-rpath "$(${pkgs.patchelf}/bin/patchelf --print-rpath $exe | sed 's|/nix/store/|./nix/store/|g')" \
|
|
||||||
$exe
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
|
|
||||||
buildCommand = ''
|
|
||||||
set -euo pipefail
|
|
||||||
# 1) Make payload dir that mirrors the bundle runtime layout
|
|
||||||
PAY="$PWD/payload"
|
|
||||||
mkdir -p "$PAY/nix/store"
|
|
||||||
|
|
||||||
# include app + patched proot in the payload closure
|
|
||||||
app=${drv}
|
|
||||||
proot=${
|
|
||||||
self.bundlers.${system}.selfExtracting.prootPatched or ""
|
|
||||||
} # not callable; we want the attr above
|
|
||||||
proot=${
|
|
||||||
pkgs.proot.overrideAttrs (_: {
|
|
||||||
postFixup = "${pkgs.patchelf}/bin/patchelf --set-interpreter .\"$(${pkgs.patchelf}/bin/patchelf --print-interpreter $out/bin/proot)\" --set-rpath \"$( ${pkgs.patchelf}/bin/patchelf --print-rpath $out/bin/proot | sed 's|/nix/store/|./nix/store/|g')\" $out/bin/proot";
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
# copy closure of app + proot into ./nix/store
|
|
||||||
paths=$( ${pkgs.nix}/bin/nix-store --query --requisites "$app" "$proot" )
|
|
||||||
for p in $paths; do
|
|
||||||
cp -a --no-preserve=ownership "$p" "$PAY/nix/store/"
|
|
||||||
done
|
|
||||||
|
|
||||||
# discover targets for the launcher
|
|
||||||
APP_BIN=$(find "$app/bin" -maxdepth 1 -type f -perm -111 | head -n1)
|
|
||||||
APP_REL="/nix/store/$(basename "$(dirname "$APP_BIN")")/$(basename "$APP_BIN")"
|
|
||||||
PROOT_REL="/nix/store/$(basename "$proot")/bin/proot"
|
|
||||||
|
|
||||||
# 2) Tar.gz the payload
|
|
||||||
( cd "$PAY" && tar -czf "$PWD/payload.tar.gz" . )
|
|
||||||
|
|
||||||
# 3) Assemble a self-extracting script at $out
|
|
||||||
cat > $out <<'SH'
|
|
||||||
#!/bin/sh
|
|
||||||
set -euf
|
|
||||||
# extract to temp dir
|
|
||||||
: "''${TMPDIR:=/tmp}"
|
|
||||||
EXTRACT_DIR="$(mktemp -d "''${TMPDIR%/}/nxbdl.XXXXXX")"
|
|
||||||
cleanup() { [ -n "''${KEEP_BUNDLE:-}" ] || rm -rf "$EXTRACT_DIR"; }
|
|
||||||
trap cleanup EXIT INT TERM
|
|
||||||
|
|
||||||
# locate embedded archive (line after marker)
|
|
||||||
ARCHIVE_LINE=$(awk '/^__ARCHIVE_BELOW__/ {print NR+1; exit 0}' "$0")
|
|
||||||
tail -n +$ARCHIVE_LINE "$0" | tar -xzf - -C "$EXTRACT_DIR"
|
|
||||||
|
|
||||||
cd "$EXTRACT_DIR"
|
|
||||||
# vars substituted by bundler at build time:
|
|
||||||
APP_REL='__APP_REL__'
|
|
||||||
PROOT_REL='__PROOT_REL__'
|
|
||||||
|
|
||||||
# run via proot
|
|
||||||
BUNDLE_PWD="''${BUNDLE_PWD:-$PWD}"
|
|
||||||
exec ".$PROOT_REL" \
|
|
||||||
-b ./nix:nix \
|
|
||||||
-R / \
|
|
||||||
-w "$BUNDLE_PWD" \
|
|
||||||
".$APP_REL" "$@"
|
|
||||||
|
|
||||||
__ARCHIVE_BELOW__
|
|
||||||
SH
|
|
||||||
|
|
||||||
# substitute the program + proot paths into the stub
|
|
||||||
sed -i \
|
|
||||||
-e "s|__APP_REL__|$APP_REL|g" \
|
|
||||||
-e "s|__PROOT_REL__|$PROOT_REL|g" \
|
|
||||||
$out
|
|
||||||
chmod +x $out
|
|
||||||
|
|
||||||
# 4) Append the payload bytes after the marker
|
|
||||||
cat payload.tar.gz >> $out
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
# resolve these now so we can hardcode into the runner
|
||||||
|
appBinGuess = "${drv}/bin";
|
||||||
|
prootBin = "${prootPatched}/bin/proot";
|
||||||
|
PROOT_REL = "/nix/store/${builtins.baseNameOf (builtins.dirOf prootBin)}/bin/proot";
|
||||||
|
in
|
||||||
|
pkgs.stdenvNoCC.mkDerivation {
|
||||||
|
name = "myApp.run";
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.findutils
|
||||||
|
pkgs.gnutar
|
||||||
|
pkgs.gzip
|
||||||
|
];
|
||||||
|
buildCommand = ''
|
||||||
|
set -euo pipefail
|
||||||
|
PAY="$PWD/payload"
|
||||||
|
mkdir -p "$PAY/nix/store"
|
||||||
|
|
||||||
default = proot-bundler;
|
# copy closure paths from closureInfo (no nix calls here)
|
||||||
};
|
while IFS= read -r p; do
|
||||||
|
cp -a --no-preserve=ownership "$p" "$PAY/nix/store/"
|
||||||
|
done < ${ci}/store-paths
|
||||||
|
|
||||||
|
# pick an app binary
|
||||||
|
APP_BIN=$(find ${appBinGuess} -maxdepth 1 -type f -perm -111 | head -n1)
|
||||||
|
if [ -z "''${APP_BIN:-}" ]; then
|
||||||
|
echo "no executable found in ${appBinGuess}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
APP_REL="/nix/store/$(basename "$(dirname "$APP_BIN")")/$(basename "$APP_BIN")"
|
||||||
|
|
||||||
|
( cd "$PAY" && tar -czf "$PWD/payload.tar.gz" . )
|
||||||
|
|
||||||
|
cat > $out <<'SH'
|
||||||
|
#!/bin/sh
|
||||||
|
set -euf
|
||||||
|
: "''${TMPDIR:=/tmp}"
|
||||||
|
EXTRACT_DIR="$(mktemp -d "''${TMPDIR%/}/nxbdl.XXXXXX")"
|
||||||
|
cleanup() { [ -n "''${KEEP_BUNDLE:-}" ] || rm -rf "$EXTRACT_DIR"; }
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
ARCHIVE_LINE=$(awk '/^__ARCHIVE_BELOW__/ {print NR+1; exit 0}' "$0")
|
||||||
|
tail -n +"$ARCHIVE_LINE" "$0" | tar -xzf - -C "$EXTRACT_DIR"
|
||||||
|
|
||||||
|
cd "$EXTRACT_DIR"
|
||||||
|
APP_REL='__APP_REL__'
|
||||||
|
PROOT_REL='__PROOT_REL__'
|
||||||
|
|
||||||
|
BUNDLE_PWD="''${BUNDLE_PWD:-$PWD}"
|
||||||
|
exec ".${PROOT_REL}" \
|
||||||
|
-b ./nix:nix \
|
||||||
|
-R / \
|
||||||
|
-w "$BUNDLE_PWD" \
|
||||||
|
".$APP_REL" "$@"
|
||||||
|
|
||||||
|
__ARCHIVE_BELOW__
|
||||||
|
SH
|
||||||
|
sed -i \
|
||||||
|
-e "s|__APP_REL__|$APP_REL|g" \
|
||||||
|
-e "s|__PROOT_REL__|${PROOT_REL}|g" \
|
||||||
|
$out
|
||||||
|
chmod +x $out
|
||||||
|
cat payload.tar.gz >> $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
default = self.bundlers.${system}.proot-bundler;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user