about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2017-09-27 21:58:04 +0200
committeraszlig <aszlig@redmoonstudios.org>2017-10-03 23:41:23 +0200
commitede9acb3d19d981c66082323e0a02c7f42530dc8 (patch)
treed5bbf928e6b5bf3df8c99dd39a2140c72b513d4e /pkgs/games/build-support
parent2554e3ce9096c7036cbea55d78828794085734af (diff)
pkgs/build-game: Introduce buildSandbox
So far creating the sandbox has been a setup hook, however it's a bit
ugly how we gathered the needed paths for the chroot file system by
recursively searching for store paths.

While I'd like to have the sandbox being built within the main
derivation, it really isn't very practical when the build takes longer
than 10 minutes.

With this implementation however the sandbox builds really fast and we
can also modify the sandbox without needing to rebuild a particular
game.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/build-game.nix17
-rw-r--r--pkgs/games/build-support/build-sandbox/default.nix60
-rw-r--r--pkgs/games/build-support/build-sandbox/sandbox.c (renamed from pkgs/games/build-support/sandbox.c)0
-rw-r--r--pkgs/games/build-support/default.nix1
-rw-r--r--pkgs/games/build-support/setup-hooks/make-sandbox.sh103
5 files changed, 63 insertions, 118 deletions
diff --git a/pkgs/games/build-support/build-game.nix b/pkgs/games/build-support/build-game.nix
index e402787c..f23ddd9a 100644
--- a/pkgs/games/build-support/build-game.nix
+++ b/pkgs/games/build-support/build-game.nix
@@ -1,4 +1,4 @@
-{ stdenv, lib, file, unzip, gcc, makeSetupHook
+{ stdenv, lib, file, unzip
 
 , withPulseAudio ? true, libpulseaudio ? null
 , alsaLib
@@ -16,15 +16,7 @@ assert withPulseAudio -> libpulseaudio != null;
 , ...
 }@attrs:
 
-let
-  sandboxHook = makeSetupHook {
-    substitutions = {
-      inherit gcc;
-      sandbox_main = ./sandbox.c;
-    };
-  } ./setup-hooks/make-sandbox.sh;
-
-in stdenv.mkDerivation ({
+stdenv.mkDerivation ({
   buildInputs = [ stdenv.cc.cc ] ++ buildInputs;
 
   nativeBuildInputs = [
@@ -48,11 +40,6 @@ in stdenv.mkDerivation ({
     fi
   '';
 
-  # Use ":!*!:" as delimiter as we can consider this highly unlikely to
-  # be part of a real path component and we're out of Nix territory, so
-  # the path components could contain almost anything.
-  extraSandboxPaths = lib.concatStringsSep ":!*!:" extraSandboxPaths;
-
   runtimeDependencies = let
     deps = lib.singleton alsaLib
         ++ lib.optional withPulseAudio libpulseaudio
diff --git a/pkgs/games/build-support/build-sandbox/default.nix b/pkgs/games/build-support/build-sandbox/default.nix
new file mode 100644
index 00000000..3b41e1bd
--- /dev/null
+++ b/pkgs/games/build-support/build-sandbox/default.nix
@@ -0,0 +1,60 @@
+{ stdenv, lib }:
+
+drv: { extraSandboxPaths ? [], ... }@attrs:
+
+stdenv.mkDerivation ({
+  name = "${drv.name}-sandboxed";
+
+  src = drv;
+
+  phases = [ "buildPhase" "installPhase" ];
+
+  exportReferencesGraph = [ "sandbox-closure" drv ];
+
+  buildPhase = ''
+    runtimeDeps="$(sed -ne '
+      p; n; n
+
+      :cdown
+      /^0*$/b
+      :l; s/0\(X*\)$/X\1/; tl
+
+      s/^\(X*\)$/9\1/; tdone
+      ${lib.concatMapStrings (num: ''
+        s/${toString num}\(X*\)$/${toString (num - 1)}\1/; tdone
+      '') (lib.range 1 9)}
+
+      :done
+      y/X/9/
+      x; n; p; x
+      bcdown
+    ' sandbox-closure | sort -u)"
+
+    echo 'static bool setup_app_paths(void) {' > params.c
+
+    for dep in $runtimeDeps; do
+      echo 'if (!bind_mount("'"$dep"'", true)) return false;' >> params.c
+    done
+
+    ${lib.concatMapStrings (extra: let
+      escaped = lib.escapeShellArg (lib.escape ["\\" "\""] extra);
+      result = "echo 'if (!extra_mount(\"'${escaped}'\")) return false;'";
+    in "${result} >> params.c") extraSandboxPaths}
+
+    echo 'return true; }' >> params.c
+    cat params.c
+  '';
+
+  installPhase = ''
+    mkdir -p "$out/bin"
+    for bin in "$src"/bin/*; do
+      progname="$(basename "$bin")"
+      gcc -g -std=gnu11 -Wall \
+        -DWRAPPED_PATH=\""$bin"\" \
+        -DWRAPPED_PROGNAME=\""$progname"\" \
+        -DPARAMS_FILE=\""$(pwd)/params.c"\" \
+        -o "$out/bin/$progname" ${./sandbox.c}
+    done
+  '';
+
+} // removeAttrs attrs [ "extraSandboxPaths" ])
diff --git a/pkgs/games/build-support/sandbox.c b/pkgs/games/build-support/build-sandbox/sandbox.c
index 69553628..69553628 100644
--- a/pkgs/games/build-support/sandbox.c
+++ b/pkgs/games/build-support/build-sandbox/sandbox.c
diff --git a/pkgs/games/build-support/default.nix b/pkgs/games/build-support/default.nix
index 8e227afc..3017fe8e 100644
--- a/pkgs/games/build-support/default.nix
+++ b/pkgs/games/build-support/default.nix
@@ -4,5 +4,6 @@
   buildGame = callPackage ./build-game.nix {
     withPulseAudio = config.pulseaudio or true;
   };
+  buildSandbox = callPackage ./build-sandbox {};
   buildUnity = callPackage ./build-unity.nix {};
 }
diff --git a/pkgs/games/build-support/setup-hooks/make-sandbox.sh b/pkgs/games/build-support/setup-hooks/make-sandbox.sh
deleted file mode 100644
index 7779234f..00000000
--- a/pkgs/games/build-support/setup-hooks/make-sandbox.sh
+++ /dev/null
@@ -1,103 +0,0 @@
-sandbox_params_include="$(mktemp --suffix=.c)"
-trap "rm -f '$sandbox_params_include'" EXIT
-sandbox_references=""
-
-hasReference() {
-    local ref
-    for ref in $sandbox_references; do
-        if [ "$1" = "$ref" ]; then return 0; fi
-    done
-
-    return 1
-}
-
-addReference() {
-    local toAdd="$1"
-
-    sandbox_references="$sandbox_references $toAdd"
-
-    echo 'if (!bind_mount("'"$toAdd"'", true)) return false;' \
-        >> "$sandbox_params_include"
-}
-
-gatherReferencesRecursive() {
-    local path="$1"
-
-    if hasReference "$path"; then return; fi
-    addReference "$path"
-
-    local valid_hash='[0-9a-df-np-sv-z]\{32\}'
-    local valid_name='[A-Za-z0-9+_?=-][A-Za-z0-9+._?=-]*'
-    local valid_path="$NIX_STORE/$valid_hash-$valid_name"
-
-    local hashpaths="$(
-        find "$path" -type f -exec grep -hao "$valid_path" {} +
-        find "$path" -type l -exec readlink {} +
-    )"
-
-    local hashpath
-    for hashpath in $hashpaths; do
-        local realsp
-        for realsp in "$NIX_STORE"/*; do
-            if echo "$hashpath" | grep -q -m 1 "^${realsp//./\\.}"; then
-                gatherReferencesRecursive "$realsp"
-                break
-            fi
-        done
-    done
-}
-
-gatherReferences() {
-    [ -z "$sandbox_references" ] || return 0
-
-    echo 'static bool setup_app_paths(void) {' > "$sandbox_params_include"
-
-    for output in $outputs; do
-        [ -e "${!output}" ] || continue
-        gatherReferencesRecursive "${!output}"
-    done
-
-    if [ -n "$extraSandboxPaths" ]; then
-        local oldIfs="$IFS"
-        IFS=':!*!:'
-        local extra
-        for extra in $extraSandboxPaths; do
-            local extraC="$(echo "$extra" | sed -e 's/"\\/\\&/g')"
-            echo 'if (!extra_mount("'"$extraC"'")) return false;' \
-                >> "$sandbox_params_include"
-        done
-        IFS="$oldIfs"
-    fi
-
-    echo 'return true; }' >> "$sandbox_params_include"
-    cat "$sandbox_params_include"
-}
-
-wrapSandbox() {
-    local progname="$1"
-    local wrapped="$2"
-    local output="$3"
-
-    @gcc@/bin/gcc -g -std=gnu11 -Wall \
-        -DWRAPPED_PATH=\""$wrapped"\" \
-        -DWRAPPED_PROGNAME=\""$progname"\" \
-        -DPARAMS_FILE=\""$sandbox_params_include"\" \
-        -o "$output" @sandbox_main@
-}
-
-makeSandbox() {
-    gatherReferences
-
-    for output in $outputs; do
-        [ -e "${!output}" ] || continue
-        local bin
-        for bin in "${!output}"/bin/*; do
-            local binbase="$(basename "$bin")"
-            local newdest="$(dirname "$bin")/.$binbase-wrapped"
-            mv "$bin" "$newdest"
-            wrapSandbox "$binbase" "$newdest" "$bin"
-        done
-    done
-}
-
-postFixupHooks+=(makeSandbox)