diff --git a/scripts/packaging/appimage/inject-libc-apprun.sh b/scripts/packaging/appimage/inject-libc-apprun.sh new file mode 100755 index 000000000..606ed1c8f --- /dev/null +++ b/scripts/packaging/appimage/inject-libc-apprun.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +REQUIRED_GLIBC_VERSION="__REQ_GLIBC_VERSION__" + +this_dir="$(readlink -f "$(dirname "$0")")" + +APPBIN="${this_dir}/usr/bin/__APPNAME__" +RUNTIME_DIR="${this_dir}/libc-runtime" +LOADER_BIN="${this_dir}/usr/bin/ld-linux" + +GLIBC_VERSION=$(ldd --version | head -1 | sed -e 's/.* \([0-9.]\)/\1/') + +echo "Detected glibc version ${GLIBC_VERSION}." + +if [[ -z "${GLIBC_VERSION}" || ! "${GLIBC_VERSION}" < "${REQUIRED_GLIBC_VERSION}" ]]; then + echo "Using system libc/libstdc++." + exec "${APPBIN}" "$@" +fi + + +echo "Using bundled libc/libstdc++ from ${RUNTIME_DIR}." +if [ -z "$LD_LIBRARY_PATH" ]; then + export LD_LIBRARY_PATH="${RUNTIME_DIR}" +else + export LD_LIBRARY_PATH="${RUNTIME_DIR}:${LD_LIBRARY_PATH}" +fi + +exec "${LOADER_BIN}" "${APPBIN}" "$@" + diff --git a/scripts/packaging/appimage/inject-libc.sh b/scripts/packaging/appimage/inject-libc.sh new file mode 100755 index 000000000..914a8dc45 --- /dev/null +++ b/scripts/packaging/appimage/inject-libc.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +set -e + +function retry_command { + # Package servers tend to be unreliable at times.. + # Retry a bunch of times. + local RETRIES=10 + + for i in $(seq 1 "$RETRIES"); do + "$@" && break + if [ "$i" == "$RETRIES" ]; then + echo "Command \"$@\" failed after ${RETRIES} retries." + exit 1 + fi + done +} + +this_dir="$(readlink -f "$(dirname "$0")")" + +if [ "$#" -ne 5 ]; then + echo "Syntax: $0 <.deb arch> " + echo "e.g. $0 DuckStation.AppDir amd64 x86_64-linux-gnu https://archive.ubuntu.com/ubuntu/ duckstation-qt" + exit 1 +fi + + +APPDIR=$1 +DEBARCH=$2 +TRIPLE=$3 +MIRROR=$4 +APPNAME=$5 + +LIBC_PACKAGE_URL="${MIRROR}/pool/main/g/glibc/libc6_2.35-0ubuntu3.8_${DEBARCH}.deb" +LIBGCCS_PACKAGE_URL="${MIRROR}/pool/main/g/gcc-12/libgcc-s1_12.3.0-1ubuntu1~22.04_${DEBARCH}.deb" +LIBSTDCXX_PACKAGE_URL="${MIRROR}/pool/main/g/gcc-12/libstdc++6_12.3.0-1ubuntu1~22.04_${DEBARCH}.deb" +GLIBC_VERSION=2.35 + +mkdir "temp" +cd "temp" +retry_command wget -O "libc.deb" "${LIBC_PACKAGE_URL}" +retry_command wget -O "libgccs.deb" "${LIBGCCS_PACKAGE_URL}" +retry_command wget -O "libstdc++.deb" "${LIBSTDCXX_PACKAGE_URL}" +dpkg -x "libc.deb" . +dpkg -x "libgccs.deb" . +dpkg -x "libstdc++.deb" . + +# Copy everything into AppDir +RUNTIME="${APPDIR}/libc-runtime" +mkdir -p "${RUNTIME}" + +# libc.so.6 and friends +cd "lib/${TRIPLE}" +cp -v * "${RUNTIME}" +cd ../../ + +# libstdc++ +cd "usr/lib/${TRIPLE}" +cp -v * "${RUNTIME}" || true +cd ../../.. + +# done with temps now +cd .. +rm -fr temp + +# Not risking mixing resolvers... +cd "${RUNTIME}" +rm -vf libnss_* + +# Move ld-linux.so.2 into the binary directory so we can preserve arg0's directory +mv -v "ld-linux-"*.so.2 "${APPDIR}/usr/bin/ld-linux" + +# Set up the replacement apprun script +cd "${APPDIR}" +rm -f AppRun.wrapped +cp "${this_dir}/inject-libc-apprun.sh" AppRun.wrapped +sed -i -e "s/__APPNAME__/${APPNAME}/" AppRun.wrapped +sed -i -e "s/__REQ_GLIBC_VERSION__/${GLIBC_VERSION}/" AppRun.wrapped + +echo Done. +