13 changed files with 402 additions and 2 deletions
-
8.ci/package-appimage.sh
-
4.github/workflows/build.yml
-
83AppImage-build-debian-inner.sh
-
73AppImage-build-debian.sh
-
42AppImage-build-local.sh
-
BINAppImageBuilder/appimagetool.AppImage
-
11AppImageBuilder/assets/AppRun
-
3AppImageBuilder/assets/eden-bqt.sh
-
3AppImageBuilder/assets/eden.sh
-
0AppImageBuilder/assets_aarch64/.gitkeep
-
BINAppImageBuilder/assets_x86_64/bwrap
-
1AppImageBuilder/assets_x86_64/bwrap-info.txt
-
176AppImageBuilder/build.sh
@ -0,0 +1,83 @@ |
|||
#! /bin/bash |
|||
set -e |
|||
|
|||
# Make sure script is called from inside our container |
|||
test -e /tmp/torzu-src-ro || (echo "Script MUST NOT be called directly!" ; exit 1) |
|||
|
|||
# Set up environment |
|||
export LANG=C.UTF-8 |
|||
export LC_ALL=C.UTF-8 |
|||
unset LC_ADDRESS LC_NAME LC_MONETARY LC_PAPER LC_TELEPHONE LC_MEASUREMENT LC_TIME |
|||
|
|||
# Raise max open files count |
|||
ulimit -n 50000 |
|||
|
|||
# Install dependencies |
|||
apt -y install cmake ninja-build build-essential autoconf pkg-config locales wget git file mold libtool lsb-release wget software-properties-common gnupg \ |
|||
qtbase5-dev qtmultimedia5-dev qtbase5-private-dev glslang-tools libssl-dev libavcodec-dev libavfilter-dev libavutil-dev libswscale-dev libpulse-dev libasound2-dev |
|||
if [ ! "$BUILD_USE_CPM" = 1 ]; then |
|||
apt -y install libfmt-dev libenet-dev liblz4-dev nlohmann-json3-dev zlib1g-dev libopus-dev libsimpleini-dev libstb-dev libzstd-dev libusb-1.0-0-dev libcubeb-dev libcpp-jwt-dev libvulkan-dev gamemode-dev libasound2-dev libglu1-mesa-dev libxext-dev mesa-common-dev libva-dev |
|||
|
|||
if [ ! -f /usr/local/lib/cmake/Boost-1.88.0/BoostConfigVersion.cmake ]; then |
|||
# Install Boost |
|||
wget https://archives.boost.io/release/1.88.0/source/boost_1_88_0.tar.bz2 |
|||
echo "Extracting Boost sources..." |
|||
tar xf boost_1_88_0.tar.bz2 |
|||
cd boost_1_88_0 |
|||
./bootstrap.sh |
|||
./b2 install --with-{headers,context,system,fiber,atomic,filesystem} link=static |
|||
cd .. |
|||
rm -rf boost_1_88_0 boost_1_88_0.tar.bz2 |
|||
fi |
|||
fi |
|||
|
|||
# Install Clang |
|||
if ([ "$BUILD_USE_CLANG" = 1 ] && ! clang-19 --version); then |
|||
cd /tmp |
|||
wget https://apt.llvm.org/llvm.sh |
|||
chmod +x llvm.sh |
|||
./llvm.sh 19 |
|||
rm llvm.sh |
|||
fi |
|||
|
|||
# Mount Torzu sources with temporary overlay |
|||
cd /tmp |
|||
mkdir torzu-src-upper torzu-src-work torzu-src |
|||
mount -t overlay overlay -olowerdir=torzu-src-ro,upperdir=torzu-src-upper,workdir=torzu-src-work torzu-src |
|||
|
|||
# Get extra configuration/compilation options |
|||
EXTRA_COMPILE_FLAGS="" |
|||
EXTRA_CMAKE_FLAGS="" |
|||
if [ "$BUILD_USE_CLANG" = 1 ]; then |
|||
EXTRA_CMAKE_FLAGS="-DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19" |
|||
FATLTO_FLAG="-flto=full" |
|||
else |
|||
FATLTO_FLAG="-flto" |
|||
fi |
|||
if [ "$BUILD_USE_THIN_LTO" = 1 ]; then |
|||
EXTRA_COMPILE_FLAGS="-flto=thin" |
|||
fi |
|||
if [ "$BUILD_USE_FAT_LTO" = 1 ]; then |
|||
EXTRA_COMPILE_FLAGS="$FATLTO_FLAG" |
|||
fi |
|||
if [ "$BUILD_USE_CPM" = 1 ]; then |
|||
EXTRA_CMAKE_FLAGS="$EXTRA_CMAKE_FLAGS -DYUZU_USE_CPM=ON" |
|||
fi |
|||
|
|||
# Build Torzu |
|||
cd /tmp |
|||
mkdir torzu-build |
|||
cd torzu-build |
|||
cmake /tmp/torzu-src -GNinja -DCMAKE_BUILD_TYPE=Release -DYUZU_TESTS=OFF -DENABLE_QT_TRANSLATION=OFF -DSPIRV_WERROR=OFF -DCMAKE_FIND_LIBRARY_SUFFIXES=".a;.so" -DSPIRV-Headers_SOURCE_DIR=/tmp/torzu-src/externals/SPIRV-Headers -DCMAKE_{C,CXX}_FLAGS="$EXTRA_COMPILE_FLAGS -fdata-sections -ffunction-sections" -DCMAKE_{EXE,SHARED}_LINKER_FLAGS="-Wl,--gc-sections" $EXTRA_CMAKE_FLAGS |
|||
ninja || ( |
|||
echo "Compilation has failed. Dropping you into a shell so you can inspect the situation. Run 'ninja' to retry and exit shell once compilation has finished successfully." |
|||
echo "Note that any changes made here will not be reflected to the host environment, but changes made from the host environment will be reflected here." |
|||
bash |
|||
) |
|||
|
|||
# Generate AppImage |
|||
cp -rv /tmp/torzu-src/AppImageBuilder /tmp/AppImageBuilder |
|||
cd /tmp/AppImageBuilder |
|||
./build.sh /tmp/torzu-build /tmp/torzu.AppImage || echo "This error is known. Using workaround..." |
|||
cp /lib/$(uname -m)-linux-gnu/libICE.so.6 build/ |
|||
mv build /tmp/hosttmp/torzu-debian-appimage-rootfs |
|||
@ -0,0 +1,73 @@ |
|||
#! /bin/bash |
|||
set -e |
|||
|
|||
# Parse options |
|||
for i in "$@" |
|||
do |
|||
case $i in |
|||
-l|--clang) |
|||
export BUILD_USE_CLANG=1 |
|||
echo "-> Using Clang for compilation." |
|||
;; |
|||
-o|--thin-lto) |
|||
export BUILD_USE_THIN_LTO=1 |
|||
echo "-> Thin link time optimization enabled." |
|||
;; |
|||
-O|--fat-lto) |
|||
export BUILD_USE_FAT_LTO=1 |
|||
echo "-> Fat link time optimization enabled." |
|||
;; |
|||
-p|--use-cpm) |
|||
export BUILD_USE_CPM=1 |
|||
echo "-> Using CPM to download most dependencies." |
|||
;; |
|||
-k|--keep-rootfs) |
|||
BUILD_KEEP_ROOTFS=1 |
|||
echo "-> Not deleting rootfs after successful build." |
|||
;; |
|||
*) |
|||
echo "Usage: $0 [--clang/-l] [--thin-lto/-o] [--fat-lto/-O] [--use-cpm/-p] [--keep-rootfs/-k]" |
|||
exit 1 |
|||
;; |
|||
esac |
|||
done |
|||
|
|||
# Make sure options are valid |
|||
if [ "$BUILD_USE_THIN_LTO" = 1 ] && [ "$BUILD_USE_CLANG" != 1 ]; then |
|||
echo "Thin LTO can't be used without Clang!" |
|||
exit 2 |
|||
fi |
|||
if [ "$BUILD_USE_THIN_LTO" = 1 ] && [ "$BUILD_USE_FAT_LTO" = 1 ]; then |
|||
echo "Only either thin or fat LTO can be used!" |
|||
exit 2 |
|||
fi |
|||
|
|||
# Get torzu source dir |
|||
TORZU_SOURCE_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" |
|||
echo "-> Source dir is $TORZU_SOURCE_DIR" |
|||
rm -rf "$TORZU_SOURCE_DIR/AppImageBuilder/build" |
|||
|
|||
# Generate debian rootfs |
|||
cd /tmp |
|||
echo "Cleaning up before build..." |
|||
rm -rf torzu-debian-appimage-rootfs |
|||
[ -d rootfs-torzu-appimage-build ] || |
|||
debootstrap stable rootfs-torzu-appimage-build http://deb.debian.org/debian/ |
|||
bwrap --bind rootfs-torzu-appimage-build / \ |
|||
--unshare-pid \ |
|||
--dev-bind /dev /dev --proc /proc --tmpfs /tmp --ro-bind /sys /sys --dev-bind /run /run \ |
|||
--tmpfs /var/tmp \ |
|||
--chmod 1777 /tmp \ |
|||
--ro-bind /etc/resolv.conf /etc/resolv.conf \ |
|||
--ro-bind "$TORZU_SOURCE_DIR" /tmp/torzu-src-ro \ |
|||
--chdir / \ |
|||
--tmpfs /home \ |
|||
--setenv HOME /home \ |
|||
--bind /tmp /tmp/hosttmp \ |
|||
/tmp/torzu-src-ro/AppImage-build-debian-inner.sh |
|||
appimagetool torzu-debian-appimage-rootfs torzu.AppImage |
|||
echo "AppImage generated at /tmp/torzu.AppImage! Cleaning up..." |
|||
rm -rf torzu-debian-appimage-rootfs |
|||
if [ ! "$BUILD_KEEP_ROOTFS" = 1 ]; then |
|||
rm -rf rootfs-torzu-appimage-build |
|||
fi |
|||
@ -0,0 +1,42 @@ |
|||
#!/bin/bash |
|||
|
|||
FILE=build/bin/eden |
|||
if test -f "$FILE"; then |
|||
# remove any previously made AppImage in the base eden git folder |
|||
rm ./eden.AppImage |
|||
|
|||
# enter AppImage utility folder |
|||
cd AppImageBuilder |
|||
|
|||
# run the build script to create the AppImage |
|||
# (usage) ./build.sh [source eden build folder] [destination .AppImage file] |
|||
./build.sh ../build ./eden.AppImage |
|||
|
|||
FILE=./eden.AppImage |
|||
if test -f "$FILE"; then |
|||
# move the AppImage to the main eden folder |
|||
mv eden.AppImage .. |
|||
# return to main eden folder |
|||
cd .. |
|||
# show contents of current folder |
|||
echo |
|||
ls |
|||
# show AppImages specifically |
|||
echo |
|||
ls *.AppImage |
|||
echo |
|||
echo "'eden.AppImage' is now located in the current folder." |
|||
echo |
|||
else |
|||
cd .. |
|||
echo "AppImage was not built." |
|||
fi |
|||
else |
|||
echo |
|||
echo "$FILE does not exist." |
|||
echo |
|||
echo "No eden executable found in the /eden/build/bin folder!" |
|||
echo |
|||
echo "You must first build a native linux version of eden before running this script!" |
|||
echo |
|||
fi |
|||
@ -0,0 +1,11 @@ |
|||
#! /bin/bash |
|||
|
|||
cd "$APPDIR" |
|||
|
|||
if [ -d /usr/lib/$(uname -m)-linux-gnu/qt5 ] || [ -d /usr/lib/qt ]; then |
|||
# System-wide Qt5 |
|||
exec ./yuzu.sh "$@" |
|||
else |
|||
# Bundled Qt5 |
|||
exec ./yuzu-bqt.sh "$@" |
|||
fi |
|||
@ -0,0 +1,3 @@ |
|||
#! /bin/sh |
|||
|
|||
LD_LIBRARY_PATH=./qt5:/usr/lib/$(uname -m)-linux-gnu:/usr/lib:. QT_PLUGIN_PATH=./qt5 exec ./yuzu "$@" |
|||
@ -0,0 +1,3 @@ |
|||
#! /bin/sh |
|||
|
|||
LD_LIBRARY_PATH=/usr/lib/$(uname -m)-linux-gnu:/usr/lib:. exec ./yuzu "$@" |
|||
@ -0,0 +1 @@ |
|||
This is a statically compiled bubblewrap 0.9.0 executable. |
|||
@ -0,0 +1,176 @@ |
|||
#! /bin/bash |
|||
set -e |
|||
|
|||
# Check arguments |
|||
if [[ $# != 2 ]]; then |
|||
>&2 echo "Bad usage!" |
|||
echo "Usage: $0 <build dir> <output file>" |
|||
exit 1 |
|||
fi |
|||
|
|||
# Get paths |
|||
ARCH="$(uname -m)" |
|||
SYSTEM_LIBS="/usr/lib" |
|||
SYSTEM_LIBS64="/usr/lib64" |
|||
EDEN_BIN="${1}/bin" |
|||
EDEN_BIN_GUI="${EDEN_BIN}/eden" |
|||
|
|||
# Make sure executable exists |
|||
if [[ $(file -b --mime-type "$EDEN_BIN_GUI") != application/x-pie-executable ]]; then |
|||
>&2 echo "Invalid eden executable!" |
|||
fi |
|||
|
|||
# Clean up build dir |
|||
rm -rf build |
|||
mkdir build |
|||
|
|||
# NOTE: some of these aren't used now, but can be reordered in priority when eden is converted to QT6 |
|||
# QT5 - /usr/lib/${ARCH}-linux-gnu/qt5 (debian), /usr/lib64/qt5 (fedora), /usr/lib/qt (steam deck) |
|||
# QT5 - /usr/lib/${ARCH}-linux-gnu/qt6 (debian), /usr/lib64/qt6 (fedora), /usr/lib/qt6 (steam deck) |
|||
QTFOUND="true" |
|||
QTDIR="$SYSTEM_LIBS"/${ARCH}-linux-gnu/qt5/plugins |
|||
if [ ! -d "$QTDIR" ]; then |
|||
# default qt5 folder not found, check for 64-bit qt5 folder |
|||
QTDIR="$SYSTEM_LIBS64"/qt5/plugins |
|||
if [ ! -d "$QTDIR" ]; then |
|||
# 64-bit qt5 folder not found, check for Steam Deck qt (qt5) folder |
|||
QTDIR="$SYSTEM_LIBS"/qt/plugins |
|||
if [ ! -d "$QTDIR" ]; then |
|||
# Steam Deck qt (qt5) folder not found, check for regular qt6 folder |
|||
QTDIR="$SYSTEM_LIBS"/${ARCH}-linux-gnu/qt6/plugins |
|||
if [ ! -d "$QTDIR" ]; then |
|||
# regular qt6 folder not found, check for 64-bit qt6 folder |
|||
QTDIR="$SYSTEM_LIBS64"/qt6/plugins |
|||
if [ ! -d "$QTDIR" ]; then |
|||
# 64-bit qt6 folder not found, check for Steam Deck qt6 folder |
|||
QTDIR="$SYSTEM_LIBS"/qt6/plugins |
|||
if [ ! -d "$QTDIR" ]; then |
|||
QTFOUND="false" |
|||
fi |
|||
fi |
|||
fi |
|||
fi |
|||
fi |
|||
fi |
|||
if [ $QTFOUND == "true" ]; then |
|||
echo "QT plugins from $QTDIR will be used." |
|||
|
|||
# Copy system dependencies used to build and required by the eden binary |
|||
# includes: |
|||
# - '/lib64/ld-linux-x86-64.so.2' or `/lib/ld-linux-aarch64.so.1` file per architecture |
|||
# - required files from `/usr/lib/x86_64-linux-gnu` or `/usr/lib/aarch64-linux-gnu` |
|||
# - different for SteamDeck, but still does it automatically |
|||
function copy_libs { |
|||
for lib in $(ldd "$1"); do |
|||
(cp -vn "$lib" ./build/ 2> /dev/null) || true |
|||
done |
|||
} |
|||
echo "Copying main dependencies..." |
|||
copy_libs "$EDEN_BIN_GUI" |
|||
|
|||
# Copy QT dependency folders, path determined above |
|||
echo "Copying Qt dependencies..." |
|||
mkdir ./build/qt5 |
|||
cp -rv "$QTDIR"/{imageformats,platforms,platformthemes,xcbglintegrations} ./build/qt5/ |
|||
|
|||
# Discover indirect dependencies (mostly from runtime-loaded Qt plugins) |
|||
echo "Copying extra dependencies..." |
|||
while true; do |
|||
LIBS="$(find ./build -name \*.so\*)" |
|||
LIB_COUNT=$(echo "$LIBS" | wc -l) |
|||
echo "$LIB_COUNT dependency libraries discovered so far..." |
|||
if [ $LIB_COUNT == "$PREV_LIB_COUNT" ]; then |
|||
break |
|||
fi |
|||
PREV_LIB_COUNT=$LIB_COUNT |
|||
|
|||
for plib in $LIBS; do |
|||
if [ -f "$plib" ]; then |
|||
copy_libs "$plib" |
|||
fi |
|||
done |
|||
done |
|||
|
|||
# Copy executable |
|||
cp -v "$EDEN_BIN_GUI" ./build/ |
|||
|
|||
cat > "build/org.eden_emu.eden.desktop" << EOL |
|||
[Desktop Entry] |
|||
Type=Application |
|||
Name=Eden |
|||
Icon=org.eden_emu.eden |
|||
Exec=eden |
|||
Categories=Game;Emulator; |
|||
EOL |
|||
|
|||
cp "../dist/eden.svg" build/org.eden_emu.eden.svg |
|||
|
|||
# Strip all libraries and executables |
|||
for file in $(find ./build -type f); do |
|||
(strip -v "$file" 2> /dev/null) || true |
|||
done |
|||
|
|||
PASSED_CHECKSUM="false" |
|||
FILE=appimagetool.AppImage |
|||
# total number of times to try downloading if a checksum doesn't match |
|||
DL_TRIES=3 |
|||
while [ $PASSED_CHECKSUM == "false" ] && [ "$DL_TRIES" -gt 0 ]; do |
|||
case $ARCH in |
|||
x86_64) |
|||
# Static copy from the 'ext-linux-bin' repo. |
|||
# Checksum will need to be changed when/if this file in the repo is updated. |
|||
if ! test -f "$FILE"; then |
|||
echo "Downloading appimagetool for architecture '$ARCH'" |
|||
wget -O appimagetool.AppImage https://github.com/litucks/ext-linux-bin/raw/refs/heads/main/appimage/appimagetool-x86_64.AppImage |
|||
fi |
|||
if [ $(shasum -a 256 appimagetool.AppImage | cut -d' ' -f1) = "110751478abece165a18460acbd7fd1398701f74a9405ad8ac053427d937bd5d" ] ; then |
|||
PASSED_CHECKSUM="true" |
|||
fi |
|||
# DISABLED TO USE THE ABOVE |
|||
# The current continuous release channel option, until a static copy is put in 'ext-linux-bin'. |
|||
# The checksum will pass until the continuous release is updated, then a new one needs to be |
|||
# generated to update this script. |
|||
#if ! test -f "$FILE"; then |
|||
# echo "Downloading appimagetool for architecture '$ARCH'" |
|||
# wget -O appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage |
|||
#fi |
|||
#if [ $(shasum -a 256 appimagetool.AppImage | cut -d' ' -f1) = "46fdd785094c7f6e545b61afcfb0f3d98d8eab243f644b4b17698c01d06083d1" ] ; then |
|||
# PASSED_CHECKSUM="true" |
|||
#fi |
|||
;; |
|||
aarch64) |
|||
# Currently set to the continuous release channel until a static copy is put in 'ext-linux-bin'. |
|||
# The checksum will pass until the continuous release is updated, then a new one needs to be |
|||
# generated to update this script. |
|||
if ! test -f "$FILE"; then |
|||
echo "Downloading appimagetool for architecture '$ARCH'" |
|||
wget -O appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-aarch64.AppImage |
|||
fi |
|||
if [ $(shasum -a 256 appimagetool.AppImage | cut -d' ' -f1) = "04f45ea45b5aa07bb2b071aed9dbf7a5185d3953b11b47358c1311f11ea94a96" ] ; then |
|||
PASSED_CHECKSUM="true" |
|||
fi |
|||
;; |
|||
*) |
|||
PASSED_CHECKSUM="invalid_arch" |
|||
;; |
|||
esac |
|||
# delete the appimagetool downloaded if the checksum doesn't match. |
|||
if [ ! $PASSED_CHECKSUM == "true" ]; then |
|||
rm -f appimagetool.AppImage |
|||
fi |
|||
((DL_TRIES-=1)) |
|||
done |
|||
if [ $PASSED_CHECKSUM == "true" ]; then |
|||
echo "Checksum passed. Proceeding to build image." |
|||
# Build AppImage |
|||
chmod a+x appimagetool.AppImage |
|||
./appimagetool.AppImage ./build "$2" |
|||
elif [ $PASSED_CHECKSUM == "invalid_arch" ]; then |
|||
echo "No download found for architecture '$ARCH'. Building halted." |
|||
else |
|||
echo "Checksum for appimagetool does not match. Building halted." |
|||
echo "If the file to be downloaded has been changed, a new checksum will need to be generated for this script." |
|||
fi |
|||
else |
|||
echo "QT not found, aborting AppImage build." |
|||
fi |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue