diff --git a/.github/scripts/Linux/prepare.sh b/.github/scripts/Linux/prepare.sh index 496fec2cf..f12093223 100755 --- a/.github/scripts/Linux/prepare.sh +++ b/.github/scripts/Linux/prepare.sh @@ -20,6 +20,7 @@ sudo add-apt-repository ppa:savoury1/vlc3 # new x265 sudo sed -n 'p; /^deb /s/^deb /deb-src /p' -i /etc/apt/sources.list # for build-dep ffmpeg sudo apt update sudo apt -y upgrade +sudo apt install appstream # appstreamcli for mkappimage AppStream validation sudo apt install libcppunit-dev sudo apt --no-install-recommends install nvidia-cuda-toolkit sudo apt install libglew-dev freeglut3-dev libgl1-mesa-dev diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 4830572cc..a2996907d 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -115,7 +115,7 @@ jobs: - name: check libc/libstdc++ ABI run: .github/scripts/Linux/check_abi.sh 2.27 3.4.22 1.3.9 bin/* lib/ultragrid/* - name: Create AppImage - run: APPIMAGE=`data/scripts/Linux-AppImage/create-appimage.sh https://github.com/$GITHUB_REPOSITORY/releases/download/continuous/UltraGrid-$CHANNEL-x86_64.AppImage.zsync` && mv $APPIMAGE UltraGrid-$VERSION-x86_64.AppImage + run: data/scripts/Linux-AppImage/create-appimage.sh https://github.com/$GITHUB_REPOSITORY/releases/download/continuous/UltraGrid-$CHANNEL-x86_64.AppImage.zsync - name: Check AppImage run: | docker build -f .github/scripts/Linux/utils/Dockerfile.ubuntu -t aitest-ubuntu . diff --git a/data/scripts/Linux-AppImage/AppRun b/data/scripts/Linux-AppImage/AppRun index 1239e6eef..90d64f99c 100755 --- a/data/scripts/Linux-AppImage/AppRun +++ b/data/scripts/Linux-AppImage/AppRun @@ -1,100 +1,200 @@ #!/bin/sh -eu +# defaults +use_bundled_libva_default=0 + # if not run from AppImage (eg. extracted), use default values APPIMAGE=${APPIMAGE-none} ARGV0=${ARGV0-$0} -DIR=`dirname $0` -export LD_LIBRARY_PATH=$DIR/usr/lib${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"} +DIR=$(dirname "$0") +AI_LIB_PATH=$DIR/usr/lib +export LD_LIBRARY_PATH="$AI_LIB_PATH"${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"} +LD_PRELOAD=${LD_PRELOAD-} # there is an issue with running_from_path() which evaluates this executable # as being system-installed #export PATH=$DIR/usr/bin:$PATH -export QT_QPA_FONTDIR=$DIR/usr/lib/fonts -export QT_PLUGIN_PATH=$DIR/usr/lib/qt5/plugins -export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_PLUGIN_PATH/platforms -if [ -d "$DIR/usr/lib/va" ] && [ -z "${LIBVA_DRIVERS_PATH:-}" ]; then - export LIBVA_DRIVERS_PATH=$DIR/usr/lib/va -fi +export QT_QPA_FONTDIR="$DIR/usr/share/fonts" +export UG_FONT_DIR="$DIR/usr/share/fonts" +QT_PLUGIN_PATH=$(set -- "$DIR"/usr/lib/qt?/plugins; echo "$1") +export QT_PLUGIN_PATH +export QT_QPA_PLATFORM_PLUGIN_PATH="$QT_PLUGIN_PATH/platforms" +bold=$(tput bold || true) +red=$(tput setaf 1 || true) +reset=$(tput sgr0 || true) + +get_tools() { + find "$DIR/usr/bin" -mindepth 1 -exec basename {} \; | tr '\n' ' ' +} usage() { printf "usage:\n" - printf "\t$ARGV0 [--gui [args]]\n" + printf "\t${bold}${red}%s${reset} ${bold}[--gui [args]]${reset}\n" "$ARGV0" printf "\t\tinvokes GUI\n" printf "\n" - printf "\t$ARGV0 --appimage-help\n" + printf "\t${bold}${red}%s${reset} ${bold}--appimage-help${reset}\n" "$ARGV0" printf "\t\tprints AppImage related options\n" printf "\n" - printf "\t$ARGV0 -h|--help|--fullhelp\n" - printf "\t\tprints this help (extended version with --fullhelp)\n" + printf "\t${bold}${red}%s${reset} ${bold}-h | --help | --fullhelp${reset}\n" "$ARGV0" + printf "\t\tprints this help (extended version with ${bold}--fullhelp${reset})\n" printf "\n" - printf "\t$ARGV0 -m|--man [uv|hd-rum-transcode]\n" + printf "\t${bold}${red}%s${reset} ${bold}-m|--man [uv|hd-rum-transcode]${reset}\n" "$ARGV0" printf "\t\tprints manual page\n" printf "\n" - printf "\t$ARGV0 -u|--update [args]\n" + printf "\t${bold}${red}%s${reset} ${bold}-u|--update [args]${reset}\n" "$ARGV0" printf "\t\tupdates AppImage (args will be passed to appimageupdatetool)\n" printf "\n" - printf "\t$ARGV0 --tool uv --help\n" + printf "\t${bold}${red}%s${reset} ${bold}-o|--tool uv --help${reset}\n" "$ARGV0" printf "\t\tprints command-line UltraGrid help\n" printf "\n" - printf "\t$ARGV0 --tool [args]\n" + printf "\t${bold}${red}%s${reset} ${bold}-o|--tool [args]${reset}\n" "$ARGV0" printf "\t\tinvokes specified tool\n" - printf "\t\ttool may be: $(ls $DIR/usr/bin | tr '\n' ' ')\n" + printf "\t\ttool may be one of: ${bold}%s${reset}\n" "$(get_tools)" printf "\n" - printf "\t$ARGV0 args\n" + printf "\t${bold}${red}%s${reset} ${bold}args${reset}\n" "$ARGV0" printf "\t\tinvokes command-line UltraGrid\n" printf "\n" } usage_aux() { printf "environment variables:\n" - printf "\tULTRAGRID_AUTOUPDATE: 1 - try to autoupdate; 0 - disable update advice\n" - printf "\tULTRAGRID_USE_FIREJAIL: run the UltraGrid executable with firejail. If\n" - printf "\t the variable contains printf a profile path\n" - printf "\t (ends with '.profile'), it will be used.\n" + printf "\tULTRAGRID_AUTOUPDATE: 1 - try to autoupdate; 0 - disable update advice\n" + printf "\tULTRAGRID_BUNDLED_LIBVA: 1 - use bundled libva; 0 - use system libva (if available), default %d\n" $use_bundled_libva_default + printf "\tULTRAGRID_USE_FIREJAIL: run the UltraGrid executable with firejail. If\n" + printf "\t the variable contains printf a profile path\n" + printf "\t (ends with '.profile'), it will be used.\n" printf "\n" } update_notify_days=90 ## Print update hint if UG binary is older than $update_notify_days days, if $ULTRAGRID_AUTOUPDATE=1 triggers update. handle_updates() { - if [ $APPIMAGE = none ]; then + if [ "$APPIMAGE" = none ]; then return fi - if [ -n ${ULTRAGRID_AUTOUPDATE-""} ]; then - if [ $ULTRAGRID_AUTOUPDATE -eq 1 ]; then - $DIR/appimageupdatetool $APPIMAGE + if [ -n "${ULTRAGRID_AUTOUPDATE-}" ]; then + if [ "$ULTRAGRID_AUTOUPDATE" -eq 1 ]; then + "$DIR/appimageupdatetool" "$APPIMAGE" fi return fi - if expr $APPIMAGE : '.*continuous' > /dev/null; then + if expr "$APPIMAGE" : '.*continuous' > /dev/null; then update_notify_days=30 fi - APPIMAGE_MTIME=$(stat --format=%Y $APPIMAGE) + APPIMAGE_MTIME=$(stat -c %Y "$APPIMAGE") CURR_TIMESTAMP=$(date +%s) - if [ $CURR_TIMESTAMP -lt $(($APPIMAGE_MTIME + $update_notify_days * 24 * 60 * 60)) ]; then + if [ "$CURR_TIMESTAMP" -lt $((APPIMAGE_MTIME + update_notify_days * 24 * 60 * 60)) ]; then return fi - printf "UltraGrid binary older than $update_notify_days days, consider checking updates:\n" + printf "UltraGrid binary older than %d days, consider checking updates:\n" $update_notify_days printf "\n" - printf "$ARGV0 -u\n" + printf "%s -u\n" "$ARGV0" printf "\t- updates AppImage\n" - printf "$ARGV0 -u -j; [ \$? -eq 1 ] && echo Update available || echo No update available\n" + printf "%s -u -j; [ \$? -eq 1 ] && echo Update available || echo No update available\n" "$ARGV0" printf "\t- check for update without actually updating\n" - printf "$ARGV0 -u -h\n" + printf "%s -u -h\n" "$ARGV0" printf "\t- prints update options\n" printf "\n" printf "Hint: you can set environment variable ULTRAGRID_AUTOUPDATE to 1 for automatic update or 0 to suppress the above message.\n" printf "\n" } +get_dynamic_loader() { + LOADER_LIST='/lib64/ld-linux-*so* /lib/ld-linux-*so* /lib*/ld-linux-*so*' + for LOADER in $LOADER_LIST; do + for n in $LOADER; do + if [ -x "$n" ]; then + echo "$n" + return + fi + done + done +} + +## Tries to find system libva. If found it is preloaded (+libva-drm+libva-x11) +## @retval 0 if preloaded; 1 otherwise +set_libva_ld_preload() { + if [ ! -f "$AI_LIB_PATH/ultragrid/ultragrid_vcompress_libavcodec.so" ]; then + return 1 + fi + LOADER=$(get_dynamic_loader) + if [ ! -x "$LOADER" ]; then + return 1 + fi + AI_LIBAVCODEC_LIB=$(LD_TRACE_LOADED_OBJECTS=1 "$LOADER" "$AI_LIB_PATH/ultragrid/ultragrid_vcompress_libavcodec.so" | grep libavcodec.so | grep -v 'not found' | awk '{print $3}') + if [ -z "$AI_LIBAVCODEC_LIB" ]; then + return 1 + fi + S_LD_LIBRARY_PATH=$LD_LIBRARY_PATH + LD_LIBRARY_PATH= + LIBVA_LIB=$(LD_TRACE_LOADED_OBJECTS=1 "$LOADER" "$AI_LIBAVCODEC_LIB" | grep libva.so | grep -v 'not found' | awk '{print $3}') + LD_LIBRARY_PATH=$S_LD_LIBRARY_PATH + if [ -z "$LIBVA_LIB" ]; then + return 1 + fi + libva_libs=$LIBVA_LIB + # add also libva-drm, libva-x11 if present + for n in libva-drm libva-x11; do + NAME=$(echo "$LIBVA_LIB" | sed s/libva/$n/) + if [ -f "$NAME" ]; then + libva_libs=$libva_libs:$NAME + fi + done + export LD_PRELOAD="$libva_libs${LD_PRELOAD:+:$LD_PRELOAD}" + return 0 +} + +## Tries to set LD_PRELOAD to system libva (see set_libva_ld_preload()). If failed, sets path to bundled libva drivers. +setup_vaapi() { + ULTRAGRID_BUNDLED_LIBVA=${ULTRAGRID_BUNDLED_LIBVA:-$use_bundled_libva_default} + if [ "$ULTRAGRID_BUNDLED_LIBVA" -ne 1 ]; then + if ! set_libva_ld_preload; then + echo "${bold}${red}Could not set system libva, using bundled libraries instead!${reset}" >&2 + ULTRAGRID_BUNDLED_LIBVA=1 + fi + fi + if [ "$ULTRAGRID_BUNDLED_LIBVA" -eq 1 ]; then + if [ -d "$DIR/usr/lib/va" ] && [ -z "${LIBVA_DRIVERS_PATH:-}" ]; then + export LIBVA_DRIVERS_PATH="$AI_LIB_PATH/va" + fi + fi +} + +## Parse params to get whitelists that may be needed to add +## @todo spaces inside paths doesn't work +get_firejail_whitelist() { + separator='' + playback_path=$(echo "$@" | sed -n 's/.*--playback \([^ :]*\).*/\1/p') + if [ -n "$playback_path" ]; then + printf -- "$separator--whitelist=%s" "$playback_path" + separator=' ' + fi + # print every argument of "filename=" or "file=" pattern + for n in "$@"; do + file_path=$(echo "$n" | sed -n -e 's/.*filename=\([^:]*\).*/\1/p' -e 's/.*file=\([^:]*\).*/\1/p') + if [ -n "$file_path" ]; then + printf -- "$separator--whitelist=%s" "$file_path" + separator=' ' + fi + done + if [ -z "$separator" ]; then + printf -- "--private" + fi +} + +setup_vaapi +# shellcheck source=/dev/null +. "$DIR/scripts/jack_preload.sh" + RUN= -if [ -n "${ULTRAGRID_USE_FIREJAIL-}" ]; then +if [ -n "${ULTRAGRID_USE_FIREJAIL-}" ] && [ "$ULTRAGRID_USE_FIREJAIL" != 0 ] && [ "$ULTRAGRID_USE_FIREJAIL" != no ]; then command -v firejail >/dev/null || { echo "Firejail not present in system!"; exit 1; } - if expr $ULTRAGRID_USE_FIREJAIL : '.*\.profile' >/dev/null; then + if expr "$ULTRAGRID_USE_FIREJAIL" : '.*\.profile' >/dev/null; then FIREJAIL_OPTS="--profile=$ULTRAGRID_USE_FIREJAIL" else - FIREJAIL_OPTS="--caps.drop=all --ipc-namespace --nonewprivs --noroot --protocol=unix,inet,inet6,netlink --seccomp --shell=none --disable-mnt --private-bin=none --private-opt=none --private --read-only=/tmp --writable-var" - FIREJAIL_OPTS="$FIREJAIL_OPTS --private-etc=alsa,group,hostname,ld.so.conf,ld.so.cache,ld.so.conf.d,nsswitch.conf,passwd,resolv.conf" + FJ_TMPDIR=${TMPDIR-/tmp/ultragrid-$(id -u)} + FIREJAIL_OPTS="--caps.drop=all --ipc-namespace --nonewprivs --noroot --protocol=unix,inet,inet6,netlink --seccomp --shell=none --disable-mnt --private-bin=none --private-opt=none --read-only=/tmp --mkdir=$FJ_TMPDIR --read-write=$FJ_TMPDIR --writable-var" + FIREJAIL_OPTS="$FIREJAIL_OPTS $(get_firejail_whitelist "$@") --private-etc=alsa,group,hostname,ld.so.conf,ld.so.cache,ld.so.conf.d,nsswitch.conf,passwd,resolv.conf --ignore=novideo" fi if firejail --version | grep -iq "d-\{0,1\}bus.*enabled"; then FIREJAIL_OPTS="$FIREJAIL_OPTS --dbus-user=none --dbus-system=none" @@ -102,41 +202,47 @@ if [ -n "${ULTRAGRID_USE_FIREJAIL-}" ]; then if firejail --help | grep -q -- --keep-var-tmp; then FIREJAIL_OPTS="$FIREJAIL_OPTS --keep-var-tmp" fi - RUN="firejail --env=LD_LIBRARY_PATH=${LD_LIBRARY_PATH} $FIREJAIL_OPTS " + RUN="firejail --env=LD_PRELOAD=${LD_PRELOAD} --env=LD_LIBRARY_PATH=${LD_LIBRARY_PATH}${FJ_TMPDIR+ --env=TMPDIR=${FJ_TMPDIR}} --env=UG_FONT_DIR=${UG_FONT_DIR} $FIREJAIL_OPTS " fi -if [ $# -eq 0 -o x"${1-}" = x"--gui" ]; then +if [ $# -eq 0 ] || [ "${1-}" = "--gui" ]; then handle_updates - [ $# -eq 0 ] && usage || shift - if [ -x $DIR/usr/bin/uv-qt ]; then - $DIR/usr/bin/uv-qt --with-uv $DIR/usr/bin/uv "$@" + if [ $# -eq 0 ]; then usage; else shift; fi + if [ -x "$DIR/usr/bin/uv-qt" ]; then + "$DIR/usr/bin/uv-qt" --with-uv "$DIR/usr/bin/uv" "$@" else echo "GUI was not compiled in!" >&2 exit 1 fi -elif [ x"$1" = x"--tool" ]; then +elif [ "$1" = "-o" ] || [ "$1" = "--tool" ]; then handle_updates TOOL=$2 shift 2 - ${RUN}$DIR/usr/bin/$TOOL "$@" -elif [ x"$1" = x"-h" -o x"$1" = x"--help" ]; then + if [ "$TOOL" = help ]; then + printf "available tools: ${bold}%s${reset}\n" "$(get_tools)" + exit 0 + fi + # shellcheck disable=SC2086 + ${RUN}"$DIR/usr/bin/$TOOL" "$@" +elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then usage exit 0 -elif [ x"$1" = x"--fullhelp" ]; then +elif [ "$1" = "--fullhelp" ]; then usage usage_aux exit 0 -elif [ x"$1" = x"-m" -o x"$1" = x"--man" ]; then +elif [ "$1" = "-m" ] || [ "$1" = "--man" ]; then PAGE=${2:-uv} - cat $DIR/usr/share/man/man1/$PAGE.1 | man -l - -elif [ x"$1" = x"-u" -o x"$1" = x"--update" ]; then + man -l "$DIR/usr/share/man/man1/$PAGE.1" +elif [ "$1" = "-u" ] || [ "$1" = "--update" ]; then shift unset LD_LIBRARY_PATH - touch $APPIMAGE # update AppImage mtime to avoid update notices if there are no updates avalable but were checked for - $DIR/appimageupdatetool ${1+"$@" }$APPIMAGE + touch "$APPIMAGE" # update AppImage mtime to avoid update notices if there are no updates avalable but were checked for + "$DIR/appimageupdatetool" ${1+"$@" }"$APPIMAGE" else handle_updates - ${RUN}$DIR/usr/bin/uv "$@" + # shellcheck disable=SC2086 + ${RUN}"$DIR/usr/bin/uv" "$@" fi exit $? diff --git a/data/scripts/Linux-AppImage/create-appimage.sh b/data/scripts/Linux-AppImage/create-appimage.sh index 5278cb675..850745284 100755 --- a/data/scripts/Linux-AppImage/create-appimage.sh +++ b/data/scripts/Linux-AppImage/create-appimage.sh @@ -8,22 +8,20 @@ APPDIR=UltraGrid.AppDir APPPREFIX=$APPDIR/usr -ARCH=`uname -m` -DATE=`date +%Y%m%d` -GLIBC_VERSION=`ldd --version | sed -n '1s/.*\ \([0-9][0-9]*\.[0-9][0-9]*\)$/\1/p'` -APPNAME=UltraGrid-${DATE}.glibc${GLIBC_VERSION}-${ARCH}.AppImage -eval $(cat Makefile | grep 'srcdir *=' | tr -d \ ) +eval "$(grep 'srcdir *=' < Makefile | tr -d \ )" # redirect the whole output to stderr, output of this script is a created AppName only ( exec 1>&2 +umask 022 + mkdir tmpinstall $APPDIR make DESTDIR=tmpinstall install mv tmpinstall/usr/local $APPPREFIX # add packet reflector -make -f $srcdir/hd-rum-multi/Makefile SRCDIR=$srcdir/hd-rum-multi +make -f "${srcdir?srcdir not found}/hd-rum-multi/Makefile" "SRCDIR=$srcdir/hd-rum-multi" cp hd-rum $APPPREFIX/bin # add platform and other Qt plugins if using dynamic libs @@ -31,51 +29,67 @@ cp hd-rum $APPPREFIX/bin # @todo use https://github.com/probonopd/linuxdeployqt PLUGIN_LIBS= if [ -f $APPPREFIX/bin/uv-qt ]; then - QT_DIR=$(dirname $(ldd $APPPREFIX/bin/uv-qt | grep Qt5Gui | grep -v found | awk '{ print $3 }')) + QT_DIR=$(dirname "$(ldd $APPPREFIX/bin/uv-qt | grep Qt.Gui | grep -v 'not found' | awk '{ print $3 }')") else QT_DIR= fi if [ -n "$QT_DIR" ]; then - SRC_PLUGIN_DIR=$QT_DIR/qt5/plugins - DST_PLUGIN_DIR=$APPPREFIX/lib/qt5/plugins - mkdir -p $DST_PLUGIN_DIR - cp -r $SRC_PLUGIN_DIR/* $DST_PLUGIN_DIR - PLUGIN_LIBS=$(find $DST_PLUGIN_DIR -type f) - - # add DejaVu font - mkdir $APPPREFIX/lib/fonts - cp $(fc-list "DejaVu Sans" | sed 's/:.*//') $APPPREFIX/lib/fonts + QT_PLUGIN_PREFIX=$(find "$QT_DIR" -maxdepth 1 -type d -name 'qt?') + SRC_PLUGIN_DIR=$QT_PLUGIN_PREFIX/plugins + DST_PLUGIN_DIR=$APPPREFIX/lib/$(basename "$QT_PLUGIN_PREFIX")/plugins + mkdir -p "$DST_PLUGIN_DIR" + cp -r "$SRC_PLUGIN_DIR"/* "$DST_PLUGIN_DIR" + PLUGIN_LIBS=$(find "$DST_PLUGIN_DIR" -type f) fi +add_fonts() { # for GUI+testcard2 + # add DejaVu font + mkdir $APPPREFIX/share/fonts + for family in "DejaVu Sans" "DejaVu Sans Mono"; do + for style in "Book" "Bold"; do + FONT_PATH=$(fc-match "$family:style=$style" file | sed 's/.*=//') + cp "$FONT_PATH" $APPPREFIX/share/fonts + done + done +} +add_fonts + # copy dependencies mkdir -p $APPPREFIX/lib -for n in $APPPREFIX/bin/* $APPPREFIX/lib/ultragrid/* $PLUGIN_LIBS; do - for lib in `ldd $n | awk '{ print $3 }'`; do - [ ! -f $lib ] || cp $lib $APPPREFIX/lib +for n in "$APPPREFIX"/bin/* "$APPPREFIX"/lib/ultragrid/* $PLUGIN_LIBS; do + for lib in $(ldd "$n" | awk '{ print $3 }'); do + [ ! -f "$lib" ] && continue + DST_NAME=$APPPREFIX/lib/$(basename "$lib") + [ -f "$DST_NAME" ] && continue + cp "$lib" $APPPREFIX/lib done done # Remove libraries that should not be bundled, see https://gitlab.com/probono/platformissues wget https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -cat $(dirname $0)/excludelist.local >> excludelist +DIRNAME=$(dirname "$0") +cat "$DIRNAME/excludelist.local" >> excludelist EXCLUDE_LIST= while read -r x; do - if [ "$x" = "" -o $(expr "x$x" : x\#) -eq 2 ]; then + if [ -z "$x" ] || expr "x$x" : x\# > /dev/null; then continue fi NAME=$(echo "$x" | awk '{ print $1 }') EXCLUDE_LIST="$EXCLUDE_LIST $NAME" done < excludelist for n in $EXCLUDE_LIST; do - if [ -f $APPPREFIX/lib/$n ]; then - rm $APPPREFIX/lib/$n + if [ "$n" = libjack.so.0 ]; then # JACK is currently handled in AppRun + continue + fi + if [ -f "$APPPREFIX/lib/$n" ]; then + rm "$APPPREFIX/lib/$n" fi done ( cd $APPPREFIX/lib; rm -f libcmpto* ) # remove non-free components # ship VA-API drivers if have libva -if [ -f $(echo $APPPREFIX/lib/libva.so.* | cut -d\ -f 1) ]; then +if [ -f "$(echo $APPPREFIX/lib/libva.so.* | cut -d\ -f 1)" ]; then for n in ${LIBVA_DRIVERS_PATH:-} /usr/lib/x86_64-linux-gnu/dri /usr/lib/dri; do if [ -d "$n" ]; then cp -r "$n" $APPPREFIX/lib/va @@ -84,35 +98,35 @@ if [ -f $(echo $APPPREFIX/lib/libva.so.* | cut -d\ -f 1) ]; then done fi -cp $srcdir/data/scripts/Linux-AppImage/AppRun $srcdir/data/ultragrid.png $APPDIR -cp $srcdir/data/uv-qt.desktop $APPDIR/ultragrid.desktop +cp -r "$srcdir/data/scripts/Linux-AppImage/AppRun" "$srcdir/data/scripts/Linux-AppImage/scripts" "$srcdir/data/ultragrid.png" $APPDIR +cp "$srcdir/data/uv-qt.desktop" $APPDIR/cz.cesnet.ultragrid.desktop APPIMAGEUPDATETOOL=$(command -v appimageupdatetool-x86_64.AppImage || true) if [ -n "$APPIMAGEUPDATETOOL" ]; then - cp $APPIMAGEUPDATETOOL $APPDIR/appimageupdatetool + cp "$APPIMAGEUPDATETOOL" $APPDIR/appimageupdatetool else wget --no-verbose https://github.com/AppImage/AppImageUpdate/releases/download/continuous/appimageupdatetool-x86_64.AppImage -O $APPDIR/appimageupdatetool # use AppImageUpdate for GUI updater fi chmod ugo+x $APPDIR/appimageupdatetool -if [ -n "${appimage_key-}" ]; then - echo "$appimage_key" >> key - gpg --import key - SIGN=--sign +GIT_ROOT=$(git rev-parse --show-toplevel || true) +if [ -n "${appimage_key-}" ] && [ -n "${GIT_ROOT-}" ]; then + echo "$appimage_key" >> "$GIT_ROOT/pubkey.asc" fi -APPIMAGETOOL=$(command -v appimagetool-x86_64.AppImage || true) -if [ -z "$APPIMAGETOOL" ]; then - wget --no-verbose https://github.com/AppImage/AppImageKit/releases/download/12/appimagetool-x86_64.AppImage -O appimagetool && chmod 755 appimagetool - APPIMAGETOOL=./appimagetool +MKAPPIMAGE=$(command -v mkappimage-x86_64.AppImage || true) +if [ -z "$MKAPPIMAGE" ]; then + MKAI_PATH=$(curl -s https://api.github.com/repos/probonopd/go-appimage/releases/tags/continuous | grep "browser_download_url.*mkappimage-.*-x86_64.AppImage" | head -n 1 | cut -d '"' -f 4) + wget -q -c "$MKAI_PATH" -O mkappimage + chmod +x mkappimage + MKAPPIMAGE=./mkappimage fi UPDATE_INFORMATION= if [ $# -ge 1 ]; then UPDATE_INFORMATION="-u zsync|$1" fi -$APPIMAGETOOL ${SIGN+$SIGN }--comp gzip $UPDATE_INFORMATION $APPDIR $APPNAME +# shellcheck disable=SC2086 # word spliting of $UPDATE_INFORMATION is requested behavior +$MKAPPIMAGE $UPDATE_INFORMATION $APPDIR rm -rf $APPDIR tmpinstall ) -echo $APPNAME - diff --git a/data/scripts/Linux-AppImage/scripts/jack_preload.sh b/data/scripts/Linux-AppImage/scripts/jack_preload.sh new file mode 100644 index 000000000..f446ffd95 --- /dev/null +++ b/data/scripts/Linux-AppImage/scripts/jack_preload.sh @@ -0,0 +1,35 @@ +# shellcheck shell=sh +get_loader() { + loaders='/lib64/ld-linux-*so* /lib/ld-linux-*so* /lib*/ld-linux-*so*' + for n in $loaders; do + for m in $n; do + if [ -x "$m" ]; then + echo "$m" + return + fi + done + done +} + +set_ld_preload() { + # ultragrid_aplay_jack.so is not used because it loads JACK with dlopen, + # while portaudio is linked directly to JACK library + portaudio_lib=$AI_LIB_PATH/ultragrid/ultragrid_aplay_portaudio.so + if [ ! -f "$portaudio_lib" ]; then + return + fi + loader=$(get_loader) + if [ ! -x "$loader" ]; then + return + fi + S_LD_LIBRARY_PATH=$LD_LIBRARY_PATH + LD_LIBRARY_PATH= + jack_lib=$(LD_TRACE_LOADED_OBJECTS=1 $loader "$portaudio_lib" | grep libjack | grep -v 'not found' | awk '{print $3}') + LD_LIBRARY_PATH=$S_LD_LIBRARY_PATH + if [ -n "$jack_lib" ]; then + export LD_PRELOAD="$jack_lib"${LD_PRELOAD:+":$LD_PRELOAD"} + fi +} + +set_ld_preload +