diff --git a/pkgs/all-packages.nix b/pkgs/all-packages.nix index 0436503..92af27a 100644 --- a/pkgs/all-packages.nix +++ b/pkgs/all-packages.nix @@ -20,6 +20,8 @@ self: super: pkgs: with pkgs; { #meraculous = callPackage ./meraculous.nix { }; + inherit (callPackages ./opengl/default.nix { inherit super; }) mesa_noglu; + inherit (callPackages ./octopus/octopus.nix { }) octopus72; octopus7 = octopus72; octopus = octopus7; diff --git a/pkgs/opengl/auto-virtualgl.sh b/pkgs/opengl/auto-virtualgl.sh new file mode 100755 index 0000000..12d7acf --- /dev/null +++ b/pkgs/opengl/auto-virtualgl.sh @@ -0,0 +1,160 @@ +#!/bin/bash + + +# Stream producers +# +# These produce a stream of escaped new-line separated items +# + +# Stream the given arguments +# +VGL_sourceS() { + ( printf '%q\n' "$@" ) || (( $? == 141 )) +} + + +# Stream the results of the given command +# +VGL_systemS() { + declare -a command=("$@") + ( eval $(printf '%q ' "${command[@]}") ) || (( $? == 141 )) +} + +# Stream the results of find (correctly escapes all filenames) +# +VGL_findS() { + declare -a options=("$@") file + VGL_systemS find "${options[@]}" -print0 | + while read -d '' -r file; do + VGL_sourceS "$file" + done +} + +# Stream the closure of the list libraries from an elf file +# +VGL_elfLibsS() { + declare file=$1 line + VGL_systemS ldd "$file" | + while read line; do + line=${line#$'\t'} + case "$line" in + *' => not found') + line=${line% => not found} + ;; + *' => '*' ('*')') + line=${line#* => } + line=${line% (*)} + ;; + *' ('*')') + line=${line% (*)} + ;; + esac + VGL_sourceS "$line" + done +} + + + +# Stream transformers +# +# Take in a set of options and transform a stream of new-line separated items +# + +# Group all items onto a single line separated by given deliminator (or space) +# +VGL_joinS() { + declare deliminator=${1- } next + if read next; then + printf '%q' "$next" + while read next; do + printf '%s%q' "$deliminator" "$next" + done + printf '\n' + fi +} + +# Remove all items for which the given command returns false +# +VGL_filterS() { + declare command=("$@") + while read next; do + if eval $(printf '%q ' "${command[@]}" "$next"); then + VGL_sourceS "$next" + fi + done +} + + + +# Stream consumers +# +# These consume a stream of escaped new-line separated items +# +VGL_anyS() { + declare command=("$@") + while read next; do + if eval $(printf '%q ' "${command[@]}" "$next"); then + return 0 + fi + done + return 1 +} + + +# Tests for the filter transformer +# + +# Check for an elf file (binary or library) +# +VGL_isElfBin() { + declare file=$1 + case "$(file -b -N --mime-type "$file")" in + application/x-executable | application/x-pie-executable) + return 0 ;; + *) + return 1 ;; + esac +} + +# Check for libGL +# +VGL_isLibGL() { + declare file=$1 + case "$file" in + libGL.so* | */libGL.so*) + return 0 ;; + *) + return 1 ;; + esac +} + + + +# Setup hook +# + +# Find all executables that depend on libGL and add a libvglfaker.so dependency +# +VGL_autoAddVGL() { + echo "Inserting VirtualGL into OpenGL executables in $prefix..." >&2 + + for output in $outputs; do + VGL_findS "${!output}" -type f | VGL_filterS VGL_isElfBin | { + declare file + while read file; do + VGL_elfLibsS "$file" | + if VGL_anyS VGL_isLibGL; then + VGL_sourceS "$file" + fi + done + } | { + declare file + while read file; do + printf 'patchelf --add-needed @virtualglLib@/lib/libvglfaker.so %q\n' "$file" >&2 + patchelf --add-needed @virtualglLib@/lib/libvglfaker.so "$file" + done + } + done +} + +postFixupHooks+=(VGL_autoAddVGL) diff --git a/pkgs/opengl/default.nix b/pkgs/opengl/default.nix new file mode 100644 index 0000000..99cbde3 --- /dev/null +++ b/pkgs/opengl/default.nix @@ -0,0 +1,36 @@ +# This override makes OpenGL just automagically work with VirtualGL +# +# Add a setup hook to the mesa_noglu package that automatically adds +# a libvglfaker.so dependency to executables that depend on libGL.so. + +{ super, lib, buildEnv, makeSetupHook, file }: + +let + autoVirtualGLHook = + let + mesa_noglu = super.mesa_noglu; + mesa_glu = super.mesa_glu.override { inherit mesa_noglu; }; + mesa = buildEnv { + name = "mesa-${mesa_noglu.version}"; + paths = [ mesa_noglu.dev mesa_noglu.out mesa_glu mesa_glu.dev ]; + meta = { + platforms = lib.platforms.unix; + }; + }; + libGL = mesa_noglu; + libGLU = mesa_glu; + libGLU_combined = mesa; + virtualglLib = (super.virtualglLib.override { inherit libGLU_combined fltk; }); + fltk = super.fltk.override { inherit libGLU_combined freeglut; }; + freeglut = super.freeglut.override { inherit libGL libGLU; }; + in + makeSetupHook { + deps = [ file virtualglLib ]; + substitutions = { inherit virtualglLib; }; + } ./auto-virtualgl.sh; + +in { + mesa_noglu = super.mesa_noglu.overrideAttrs ( attrs: { + propagatedBuildInputs = attrs.propagatedBuildInputs or [] ++ [ autoVirtualGLHook ]; + } ); +}