diff --git a/scripts/deps/build-dependencies-linux-cross.sh b/scripts/deps/build-dependencies-linux-cross.sh index f265fb817..1cf7792c5 100755 --- a/scripts/deps/build-dependencies-linux-cross.sh +++ b/scripts/deps/build-dependencies-linux-cross.sh @@ -85,6 +85,20 @@ CMAKE_COMMON=( -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" ) +# Determine architecture. +if [ "$CROSSARCH" == "arm64" ]; then + CROSSSYSARCH="aarch64" + CROSSTRIPLET="aarch64-linux-gnu" + CMAKEPROCESSOR="aarch64" +elif [ "$CROSSARCH" == "armhf" ]; then + CROSSSYSARCH="armhf" + CROSSTRIPLET="arm-linux-gnueabihf" + CMAKEPROCESSOR="armv7-a" +else + echo "Unknown cross arch $CROSSARCH" + exit 1 +fi + # TODO: Pull all of this from the main file. FREETYPE=2.13.3 @@ -228,24 +242,24 @@ if [ "$ONLY_DOWNLOAD" == true ]; then fi # Stop pkg-config picking up host files. -export PKG_CONFIG_PATH=${SYSROOTDIR}/usr/lib/${CROSSARCH}-linux-gnu/pkgconfig:${SYSROOTDIR}/usr/lib/pkgconfig:${SYSROOTDIR}/usr/share/pkgconfig +export PKG_CONFIG_PATH=${SYSROOTDIR}/usr/lib/${CROSSTRIPLET}/pkgconfig:${SYSROOTDIR}/usr/lib/pkgconfig:${SYSROOTDIR}/usr/share/pkgconfig export PKG_CONFIG_SYSROOT_DIR=${SYSROOTDIR} # Generate cmake toolchain file. cat > "$TOOLCHAINFILE" << EOF set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR ${CROSSARCH}) +set(CMAKE_SYSTEM_PROCESSOR ${CMAKEPROCESSOR}) -set(CMAKE_C_COMPILER "/usr/bin/${CROSSARCH}-linux-gnu-gcc") -set(CMAKE_C_COMPILER_TARGET "${CROSSARCH}-linux-gnu") -set(CMAKE_C_COMPILER_AR "/usr/bin/${CROSSARCH}-linux-gnu-ar") -set(CMAKE_C_COMPILER_RANLIB "/usr/bin/${CROSSARCH}-linux-gnu-ranlib") +set(CMAKE_C_COMPILER "/usr/bin/${CROSSTRIPLET}-gcc") +set(CMAKE_C_COMPILER_TARGET "${CROSSTRIPLET}") +set(CMAKE_C_COMPILER_AR "/usr/bin/${CROSSTRIPLET}-ar") +set(CMAKE_C_COMPILER_RANLIB "/usr/bin/${CROSSTRIPLET}-ranlib") -set(CMAKE_CXX_COMPILER "/usr/bin/${CROSSARCH}-linux-gnu-g++") -set(CMAKE_CXX_COMPILER_TARGET "${CROSSARCH}-linux-gnu") -set(CMAKE_CXX_COMPILER_AR "/usr/bin/${CROSSARCH}-linux-gnu-ar") -set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/${CROSSARCH}-linux-gnu-ranlib") +set(CMAKE_CXX_COMPILER "/usr/bin/${CROSSTRIPLET}-g++") +set(CMAKE_CXX_COMPILER_TARGET "${CROSSTRIPLET}") +set(CMAKE_CXX_COMPILER_AR "/usr/bin/${CROSSTRIPLET}-ar") +set(CMAKE_CXX_COMPILER_RANLIB "/usr/bin/${CROSSTRIPLET}-ranlib") set(CMAKE_FIND_ROOT_PATH "${INSTALLDIR};${SYSROOTDIR}") set(CMAKE_SYSROOT "${SYSROOTDIR}") @@ -274,9 +288,9 @@ fi # NOTE: Must be a shared library because otherwise aarch64 libgcc symbols are missing when building with clang. echo "Building libbacktrace..." rm -fr "libbacktrace-$LIBBACKTRACE" -tar xf "$LIBBACKTRACE.tar.gz" +tar xf "libbacktrace-$LIBBACKTRACE.tar.gz" cd "libbacktrace-$LIBBACKTRACE" -./configure --prefix="$INSTALLDIR" --build=x86_64-linux-gnu --host="${CROSSARCH}-linux-gnu" --with-pic --enable-shared --disable-static +./configure --prefix="$INSTALLDIR" --build=x86_64-linux-gnu --host="${CROSSTRIPLET}" --with-pic --enable-shared --disable-static make make install cd .. @@ -376,8 +390,6 @@ echo "Building SDL..." rm -fr "SDL3-$SDL3" tar xf "SDL3-$SDL3.tar.gz" cd "SDL3-$SDL3" -# needed because -Isystem with chroot/usr/include breaks -patch -p1 < "$SCRIPTDIR/sdl2-disable-isystem.patch" patch -p1 < "$SCRIPTDIR/sdl3-joystick-crash.patch" cmake -B build "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DSDL_SHARED=ON -DSDL_STATIC=OFF -DSDL_TESTS=OFF -G Ninja cmake --build build --parallel diff --git a/scripts/deps/sdl2-disable-isystem.patch b/scripts/deps/sdl2-disable-isystem.patch deleted file mode 100644 index 01301c004..000000000 --- a/scripts/deps/sdl2-disable-isystem.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/CMakeLists.txt 2024-12-29 21:34:43.219279282 +1000 -+++ b/CMakeLists.txt 2024-12-29 21:34:59.495612349 +1000 -@@ -3047,10 +3047,6 @@ - listtostr(EXTRA_CFLAGS _EXTRA_CFLAGS) - set(EXTRA_CFLAGS ${_EXTRA_CFLAGS}) - --if(USE_GCC OR USE_CLANG) -- string(REGEX REPLACE "(^| )-I" "\\1 -isystem" EXTRA_CFLAGS "${EXTRA_CFLAGS}") --endif() -- - # Compat helpers for the configuration files - - if(EXISTS "${PROJECT_SOURCE_DIR}/VERSION.txt") diff --git a/scripts/packaging/appimage/inject-libc.sh b/scripts/packaging/appimage/inject-libc.sh index de6dc988d..82baecef9 100755 --- a/scripts/packaging/appimage/inject-libc.sh +++ b/scripts/packaging/appimage/inject-libc.sh @@ -18,9 +18,9 @@ function retry_command { this_dir="$(readlink -f "$(dirname "$0")")" -if [ "$#" -ne 5 ]; then +if [ "$#" -ne 4 ]; then echo "Syntax: $0 <.deb arch> " - echo "e.g. $0 DuckStation.AppDir amd64 x86_64-linux-gnu https://archive.ubuntu.com/ubuntu/ duckstation-qt" + echo "e.g. $0 DuckStation.AppDir amd64 x86_64-linux-gnu duckstation-qt" exit 1 fi @@ -28,22 +28,26 @@ fi APPDIR=$1 DEBARCH=$2 TRIPLE=$3 -MIRROR=$4 -APPNAME=$5 +APPNAME=$4 -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 +if [ ! -f "libc.deb" ]; then + retry_command wget -O "libc.deb" "https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/libc6_2.35-0ubuntu3.9_${DEBARCH}.deb" +fi +if [ ! -f "libgccs.deb" ]; then + retry_command wget -O "libgccs.deb" "https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/libgcc-s1_12.3.0-1ubuntu1.22.04_${DEBARCH}.deb" +fi +if [ ! -f "libstdc++.deb" ]; then + retry_command wget -O "libstdc++.deb" "https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/libstdc++6_12.3.0-1ubuntu1.22.04_${DEBARCH}.deb" +fi + +rm -fr "temp" 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" . +dpkg -x "../libc.deb" . +dpkg -x "../libgccs.deb" . +dpkg -x "../libstdc++.deb" . # Copy everything into AppDir RUNTIME="${APPDIR}/libc-runtime" diff --git a/scripts/packaging/appimage/make-cross-appimage.sh b/scripts/packaging/appimage/make-cross-appimage.sh index 67262b551..df382961b 100755 --- a/scripts/packaging/appimage/make-cross-appimage.sh +++ b/scripts/packaging/appimage/make-cross-appimage.sh @@ -26,111 +26,74 @@ if [ "$1" == "-inject-libc" ]; then fi if [ "$#" -ne 5 ]; then - echo "Syntax: $0 [-inject-libc] " + echo "Syntax: $0 [-inject-libc] " exit 1 fi -ARCH=$1 -BUILDDIR=$2 -DEPSDIR=$3 -CHROOTDIR=$4 -NAME=$5 +BINARY=$1 +ARCH=$2 +BUILDDIR=$3 +DEPSDIR=$4 +CHROOTDIR=$5 -BINARY=duckstation-qt -APPDIRNAME=DuckStation.AppDir STRIP=llvm-strip -TRIPLE="${ARCH}-linux-gnu" + +if [ "$ARCH" == "arm64" ]; then + DEBARCH="arm64" + RUNTIMEARCH="aarch64" + TRIPLE="aarch64-linux-gnu" +elif [ "$ARCH" == "armhf" ]; then + DEBARCH="armhf" + RUNTIMEARCH="armhf" + TRIPLE="arm-linux-gnueabihf" +else + echo "Unknown arch ${ARCH}." + exit 1 +fi + +if [ "$BINARY" == "duckstation-qt" ]; then + echo "Building Qt AppImage." + ADD_QT_LIBS=true + APPIMAGENAME="DuckStation-${ARCH}" +elif [ "$BINARY" == "duckstation-mini" ]; then + echo "Building Mini AppImage." + ADD_QT_LIBS=false + APPIMAGENAME="DuckStation-Mini-${ARCH}" +else + echo "Unknown binary $BINARY" + exit 1 +fi + +APPDIRNAME="${APPIMAGENAME}.AppDir" declare -a SYSLIBS=( - "libatk-1.0.so.0" - "libatk-bridge-2.0.so.0" - "libatspi.so.0" - "libblkid.so.1" "libbrotlicommon.so.1" "libbrotlidec.so.1" "libbsd.so.0" - "libcairo-gobject.so.2" - "libcairo.so.2" - "libcap.so.2" "libcrypto.so.3" "libcurl.so.4" - "libdatrie.so.1" - "libdbus-1.so.3" - "libdeflate.so.0" - "libepoxy.so.0" "libffi.so.8" - "libgcrypt.so.20" - "libgdk-3.so.0" - "libgdk_pixbuf-2.0.so.0" - "libgio-2.0.so.0" - "libglib-2.0.so.0" - "libgmodule-2.0.so.0" "libgnutls.so.30" - "libgobject-2.0.so.0" - "libgraphite2.so.3" "libgssapi_krb5.so.2" - "libgtk-3.so.0" "libhogweed.so.6" "libidn2.so.0" - "libjbig.so.0" "libk5crypto.so.3" "libkeyutils.so.1" "libkrb5.so.3" "libkrb5support.so.0" "liblber-2.5.so.0" "libldap-2.5.so.0" - "liblz4.so.1" - "liblzma.so.5" - "libmd.so.0" - "libmount.so.1" "libnettle.so.8" "libnghttp2.so.14" "libp11-kit.so.0" - "libpango-1.0.so.0" - "libpangocairo-1.0.so.0" - "libpangoft2-1.0.so.0" - "libpcre2-16.so.0" - "libpcre2-8.so.0" - "libpcre.so.3" - "libpixman-1.so.0" "libpsl.so.5" "librtmp.so.1" "libsasl2.so.2" - "libselinux.so.1" "libssh.so.4" "libssl.so.3" - "libsystemd.so.0" "libtasn1.so.6" - "libtiff.so.5" "libudev.so.1" "libunistring.so.2" - "libXau.so.6" - "libxcb-cursor.so.0" - "libxcb-glx.so.0" - "libxcb-icccm.so.4" - "libxcb-image.so.0" - "libxcb-keysyms.so.1" - "libxcb-randr.so.0" - "libxcb-render.so.0" - "libxcb-render-util.so.0" - "libxcb-shape.so.0" - "libxcb-shm.so.0" - "libxcb-sync.so.1" - "libxcb-util.so.1" - "libxcb-xfixes.so.0" - "libxcb-xkb.so.1" - "libXcomposite.so.1" - "libXcursor.so.1" - "libXdamage.so.1" - "libXdmcp.so.6" - "libXext.so.6" - "libXfixes.so.3" - "libXinerama.so.1" - "libXi.so.6" - "libxkbcommon.so.0" - "libxkbcommon-x11.so.0" - "libXrandr.so.2" - "libXrender.so.1" ) declare -a DEPLIBS=( @@ -139,11 +102,12 @@ declare -a DEPLIBS=( "libharfbuzz.so" "libjpeg.so.62" "libpng16.so.16" - "libSDL2-2.0.so.0" + "libSDL3.so.0" "libsharpyuv.so.0" "libwebpdemux.so.2" "libwebpmux.so.3" "libwebp.so.7" + "libz.so.1" "libzip.so.5" "libzstd.so.1" @@ -163,36 +127,103 @@ declare -a DEPLIBS=( #"libva.so.2" ) -declare -a QTLIBS=( - "libQt6Core.so.6" - "libQt6DBus.so.6" - "libQt6Gui.so.6" - "libQt6OpenGL.so.6" - "libQt6Svg.so.6" - "libQt6WaylandClient.so.6" - "libQt6WaylandEglClientHwIntegration.so.6" - "libQt6Widgets.so.6" - "libQt6XcbQpa.so.6" -) +if [ "${ADD_QT_LIBS}" == true ]; then + SYSLIBS+=( + "libatk-1.0.so.0" + "libatk-bridge-2.0.so.0" + "libatspi.so.0" + "libblkid.so.1" + "libcairo-gobject.so.2" + "libcairo.so.2" + "libcap.so.2" + "libdatrie.so.1" + "libdeflate.so.0" + "libdbus-1.so.3" + "libepoxy.so.0" + "libgcrypt.so.20" + "libgdk-3.so.0" + "libgdk_pixbuf-2.0.so.0" + "libgio-2.0.so.0" + "libglib-2.0.so.0" + "libgmodule-2.0.so.0" + "libgobject-2.0.so.0" + "libgraphite2.so.3" + "libgtk-3.so.0" + "libjbig.so.0" + "liblz4.so.1" + "liblzma.so.5" + "libmd.so.0" + "libmount.so.1" + "libpango-1.0.so.0" + "libpangocairo-1.0.so.0" + "libpangoft2-1.0.so.0" + "libpcre2-16.so.0" + "libpcre2-8.so.0" + "libpcre.so.3" + "libpixman-1.so.0" + "libselinux.so.1" + "libsystemd.so.0" + "libtiff.so.5" + "libXau.so.6" + "libxcb-cursor.so.0" + "libxcb-glx.so.0" + "libxcb-icccm.so.4" + "libxcb-image.so.0" + "libxcb-keysyms.so.1" + "libxcb-randr.so.0" + "libxcb-render.so.0" + "libxcb-render-util.so.0" + "libxcb-shape.so.0" + "libxcb-shm.so.0" + "libxcb-sync.so.1" + "libxcb-util.so.1" + "libxcb-xfixes.so.0" + "libxcb-xkb.so.1" + "libXcomposite.so.1" + "libXcursor.so.1" + "libXdamage.so.1" + "libXdmcp.so.6" + "libXext.so.6" + "libXfixes.so.3" + "libXinerama.so.1" + "libXi.so.6" + "libxkbcommon.so.0" + "libxkbcommon-x11.so.0" + "libXrandr.so.2" + "libXrender.so.1" + ) -declare -a QTPLUGINS=( - "plugins/iconengines" - "plugins/imageformats" - "plugins/platforminputcontexts" - "plugins/platforms" - "plugins/platformthemes" - "plugins/wayland-decoration-client" - "plugins/wayland-graphics-integration-client" - "plugins/wayland-shell-integration" - "plugins/xcbglintegrations" -) + declare -a QTLIBS=( + "libQt6Core.so.6" + "libQt6DBus.so.6" + "libQt6Gui.so.6" + "libQt6OpenGL.so.6" + "libQt6Svg.so.6" + "libQt6WaylandClient.so.6" + "libQt6WaylandEglClientHwIntegration.so.6" + "libQt6Widgets.so.6" + "libQt6XcbQpa.so.6" + ) + + declare -a QTPLUGINS=( + "plugins/iconengines" + "plugins/imageformats" + "plugins/platforminputcontexts" + "plugins/platforms" + "plugins/platformthemes" + "plugins/wayland-decoration-client" + "plugins/wayland-graphics-integration-client" + "plugins/wayland-shell-integration" + "plugins/xcbglintegrations" + ) +fi set -e IFS=" " APPIMAGETOOL=./appimagetool-x86_64 -APPIMAGERUNTIME=./runtime-${ARCH} +APPIMAGERUNTIME=./runtime-${RUNTIMEARCH} PATCHELF=patchelf if [ ! -f "$APPIMAGETOOL" ]; then @@ -201,7 +232,7 @@ if [ ! -f "$APPIMAGETOOL" ]; then fi if [ ! -f "$APPIMAGERUNTIME" ]; then - retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${ARCH} + retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${RUNTIMEARCH} fi OUTDIR=$(realpath "./$APPDIRNAME") @@ -212,10 +243,6 @@ mkdir -p "$OUTDIR/usr/bin" "$OUTDIR/usr/lib" echo "Copying binary and resources..." cp -a "$BUILDDIR/bin/$BINARY" "$BUILDDIR/bin/resources" "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin" -# Currently we leave the main binary unstripped, uncomment if this is not desired. -# NOTE: Strip must come before patchelf, otherwise shit breaks. -$STRIP "$OUTDIR/usr/bin/$BINARY" - # Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system. echo "Patching RPATH in ${BINARY}..." patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY" @@ -238,7 +265,7 @@ for lib in "${SYSLIBS[@]}"; do exit 1 fi - $STRIP $OUTDIR/usr/lib/$blib + "$STRIP" $OUTDIR/usr/lib/$blib done echo "Copying local libraries..." @@ -252,28 +279,37 @@ for lib in "${DEPLIBS[@]}"; do exit 1 fi - $STRIP "$OUTDIR/usr/lib/$blib" + "$STRIP" "$OUTDIR/usr/lib/$blib" done -echo "Copying Qt libraries..." -for lib in "${QTLIBS[@]}"; do - cp -avL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib" - $STRIP "$OUTDIR/usr/lib/$lib" -done +if [ "${ADD_QT_LIBS}" == true ]; then + echo "Copying Qt libraries..." + for lib in "${QTLIBS[@]}"; do + cp -avL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib" + "$STRIP" "$OUTDIR/usr/lib/$lib" + done -echo "Copying Qt plugins..." -mkdir -p $OUTDIR/usr/lib/plugins -for plugin in "${QTPLUGINS[@]}"; do - mkdir -p "$OUTDIR/usr/lib/$plugin" - cp -avL "$DEPSDIR/$plugin/"*.so "$OUTDIR/usr/lib/$plugin/" -done + echo "Copying Qt plugins..." + mkdir -p $OUTDIR/usr/lib/plugins + for plugin in "${QTPLUGINS[@]}"; do + mkdir -p "$OUTDIR/usr/lib/$plugin" + cp -avL "$DEPSDIR/$plugin/"*.so "$OUTDIR/usr/lib/$plugin/" + done -for so in $(find $OUTDIR/usr/lib/plugins -iname '*.so'); do - # This is ../../ because it's usually plugins/group/name.so - echo "Patching RPATH in ${so}..." - patchelf --set-rpath '$ORIGIN/../..' "$so" - $STRIP "$so" -done + for so in $(find $OUTDIR/usr/lib/plugins -iname '*.so'); do + # This is ../../ because it's usually plugins/group/name.so + echo "Patching RPATH in ${so}..." + patchelf --set-rpath '$ORIGIN/../..' "$so" + "$STRIP" "$so" + done + + echo "Creating qt.conf..." +cat > "$OUTDIR/usr/bin/qt.conf" << EOF +[Paths] +Plugins = ../lib/plugins +EOF + +fi for so in $(find $OUTDIR/usr/lib -maxdepth 1); do if [ -f "$so" ]; then @@ -282,12 +318,6 @@ for so in $(find $OUTDIR/usr/lib -maxdepth 1); do fi done -echo "Creating qt.conf..." -cat > "$OUTDIR/usr/bin/qt.conf" << EOF -[Paths] -Plugins = ../lib/plugins -EOF - # Copy desktop/icon echo "Copying desktop/icon..." mkdir -p "$OUTDIR/usr/share/applications" @@ -310,16 +340,12 @@ ln -s "usr/bin/$BINARY" "$OUTDIR/AppRun.wrapped" # Optionally inject libc if [ "$INJECT_LIBC" == true ]; then echo "Injecting libc/libc++..." - if [ "$ARCH" == "aarch64" ]; then - DEBARCH="arm64" - else - echo "Unknown arch for libc injection." - exit 1 - fi - - "$SCRIPTDIR/inject-libc.sh" "$OUTDIR" "$DEBARCH" "$TRIPLE" "https://ports.ubuntu.com" "$BINARY" + "$SCRIPTDIR/inject-libc.sh" "$OUTDIR" "$DEBARCH" "$TRIPLE" "$BINARY" fi echo "Generating AppImage..." -rm -f "$NAME.AppImage" -"$APPIMAGETOOL" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$NAME.AppImage" +rm -f "$APPIMAGENAME.AppImage" + +# Can't run the appimage in a docker container because no fuse, so extract it first. +"$APPIMAGETOOL" --appimage-extract +"$PWD/squashfs-root/AppRun" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$APPIMAGENAME.AppImage"