Files
ccpkgs/pkgs/opengl/auto-virtualgl.sh

161 lines
3.0 KiB
Bash
Executable File

#!/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)