131 lines
4.3 KiB
Nix
131 lines
4.3 KiB
Nix
{
|
|
description = "My flake";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
|
|
flake-utils.url = "github:numtide/flake-utils";
|
|
};
|
|
|
|
outputs =
|
|
{
|
|
self,
|
|
nixpkgs,
|
|
flake-utils,
|
|
...
|
|
}:
|
|
flake-utils.lib.eachDefaultSystem (
|
|
system:
|
|
let
|
|
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
|
|
{
|
|
bundlers = rec {
|
|
proot-bundler =
|
|
drv:
|
|
let
|
|
ci = pkgs.closureInfo {
|
|
rootPaths = [
|
|
drv
|
|
prootPatched
|
|
];
|
|
};
|
|
mainProgram = drv.meta.mainProgram or (throw "${drv.name} has no meta.mainProgram set");
|
|
prootStoreBase = builtins.baseNameOf prootPatched;
|
|
PROOT_REL = "/nix/store/${prootStoreBase}/bin/proot";
|
|
in
|
|
pkgs.stdenvNoCC.mkDerivation {
|
|
name = "${mainProgram}-bdl";
|
|
nativeBuildInputs = [
|
|
pkgs.coreutils
|
|
pkgs.findutils
|
|
pkgs.gnutar
|
|
pkgs.gzip
|
|
];
|
|
dontFixup = true;
|
|
buildCommand = ''
|
|
set -euo pipefail
|
|
|
|
PAY="$PWD/payload"
|
|
mkdir -p "$PAY/nix/store"
|
|
|
|
# 1) copy closure (no nix calls; uses closureInfo)
|
|
while IFS= read -r p; do
|
|
cp -a --no-preserve=ownership "$p" "$PAY/nix/store/"
|
|
done < ${ci}/store-paths
|
|
|
|
# 2) pick app binary and make relative path used by the runner
|
|
APP_BIN="${drv}/bin/${mainProgram}"
|
|
if [ ! -x "$APP_BIN" ]; then
|
|
echo "mainProgram ${mainProgram} not found in ${drv}/bin" >&2
|
|
exit 1
|
|
fi
|
|
#APP_REL="/nix/store/$(basename "$(dirname "$APP_BIN")")/$(basename "$APP_BIN")"
|
|
APP_REL="$APP_BIN"
|
|
|
|
# 3) tar the payload OUTSIDE $PAY to avoid self-inclusion
|
|
_TMP="$(mktemp -d)"
|
|
( cd "$PAY" && tar \
|
|
--owner=0 --group=0 \
|
|
--mode=u+rw,uga+r \
|
|
--hard-dereference \
|
|
--format=gnu \
|
|
--sort=name \
|
|
-czf "$_TMP/payload.tar.gz" . )
|
|
|
|
# 4) write the self-extracting stub
|
|
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"
|
|
|
|
BUNDLE_PWD="''${BUNDLE_PWD:-$PWD}"
|
|
|
|
cd "$EXTRACT_DIR"
|
|
APP_REL='__APP_REL__'
|
|
PROOT_REL='__PROOT_REL__'
|
|
|
|
exec "$EXTRACT_DIR''${PROOT_REL}" \
|
|
-b "$EXTRACT_DIR/nix:nix" \
|
|
-R / \
|
|
-w "$BUNDLE_PWD" \
|
|
"$EXTRACT_DIR''${APP_REL}" "$@"
|
|
|
|
__ARCHIVE_BELOW__
|
|
SH
|
|
|
|
# 5) inject paths, chmod, and append payload
|
|
sed -i \
|
|
-e "s|__APP_REL__|$APP_REL|g" \
|
|
-e "s|__PROOT_REL__|${PROOT_REL}|g" \
|
|
"$out"
|
|
chmod +x "$out"
|
|
cat "$_TMP/payload.tar.gz" >> "$out"
|
|
'';
|
|
};
|
|
|
|
default = proot-bundler;
|
|
};
|
|
}
|
|
);
|
|
}
|