Treat AppImages As Self-Mounting Tarballs

This commit is contained in:
TheBrokenRail 2022-07-04 16:44:00 -04:00
parent ea4c5c77a1
commit b539491713
14 changed files with 95 additions and 261 deletions

View File

@ -96,7 +96,11 @@ endif()
# Specify Default Installation Prefix
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "" FORCE)
set(DEFAULT_PREFIX "/usr")
if(MCPI_IS_APPIMAGE_BUILD)
set(DEFAULT_PREFIX "/")
endif()
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
endif()
# Optimizations

View File

@ -1,19 +1,10 @@
# Symlink Function
function(install_symlink target link)
install(CODE "\
# Prepare\n \
set(file \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${link}\")\n \
\
# Create Directory\n \
get_filename_component(dir \"\${file}\" DIRECTORY)\n \
file(MAKE_DIRECTORY \${dir})\n \
\
# Create Symlink\n \
if(NOT EXISTS \"\${file}\")\n \
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink ${target} \"\${file}\")\n \
message(\"-- Installing: \${file}\")\n \
else()\n \
message(\"-- Up-to-date: \${file}\")\n \
endif() \
")
get_filename_component(parent "${link}" DIRECTORY)
if(parent STREQUAL "")
set(parent ".")
endif()
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/symlink/${parent}")
file(CREATE_LINK "${target}" "${CMAKE_BINARY_DIR}/symlink/${link}" SYMBOLIC)
install(FILES "${CMAKE_BINARY_DIR}/symlink/${link}" DESTINATION "${parent}")
endfunction()

View File

@ -10,13 +10,13 @@ else()
# Copy To Binary Directory
set(APT_DIR "${CMAKE_CURRENT_BINARY_DIR}/apt")
file(REMOVE_RECURSE "${APT_DIR}")
file(MAKE_DIRECTORY "${APT_DIR}")
# Make Directories
file(MAKE_DIRECTORY "${APT_DIR}/apt.conf.d")
file(MAKE_DIRECTORY "${APT_DIR}/preferences.d")
file(MAKE_DIRECTORY "${APT_DIR}/keys")
file(MAKE_DIRECTORY "${APT_DIR}/dpkg")
file(MAKE_DIRECTORY "${APT_DIR}/archives")
file(TOUCH "${APT_DIR}/dpkg/status")
# Create APT Sources
@ -65,7 +65,6 @@ else()
# Create Sysroot Directory
set(SYSROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}/sysroot")
file(REMOVE_RECURSE "${SYSROOT_DIR}")
file(MAKE_DIRECTORY "${SYSROOT_DIR}")
# Download
@ -78,6 +77,7 @@ else()
add_custom_command(
OUTPUT "${APT_DIR}/.download-stamp"
DEPENDS "${APT_DIR}/.update-stamp"
COMMAND find "${APT_DIR}/archives" -maxdepth 1 -type f -name "*.deb" -delete
COMMAND ${APT_ENV} apt-get install -y --no-install-recommends --download-only ${APT_PACKAGES}
COMMAND "${CMAKE_COMMAND}" -E touch "${APT_DIR}/.download-stamp"
VERBATIM
@ -85,7 +85,8 @@ else()
add_custom_command(
OUTPUT "${APT_DIR}/.extract-stamp"
DEPENDS "${APT_DIR}/.download-stamp"
COMMAND ${APT_ENV} find "${APT_DIR}/archives" -maxdepth 1 -type f -name "*.deb" -exec dpkg -x {} "${SYSROOT_DIR}" ";"
COMMAND find "${SYSROOT_DIR}" -mindepth 1 -delete
COMMAND find "${APT_DIR}/archives" -maxdepth 1 -type f -name "*.deb" -exec dpkg -x {} "${SYSROOT_DIR}" ";"
COMMAND "${CMAKE_COMMAND}" -E touch "${APT_DIR}/.extract-stamp"
VERBATIM
)

View File

@ -15,3 +15,9 @@ install(
DESTINATION "share/icons/hicolor/scalable/apps"
RENAME "${MCPI_APP_ID}.png"
)
# AppImage
if(MCPI_IS_APPIMAGE_BUILD)
install_symlink("share/icons/hicolor/scalable/apps/${MCPI_APP_ID}.png" "${MCPI_APP_ID}.png")
install_symlink("${MCPI_APP_ID}.png" ".DirIcon")
endif()

View File

@ -110,3 +110,10 @@ install(
DESTINATION "share/metainfo"
RENAME "${MCPI_APP_ID}.appdata.xml"
)
# AppImage
if(MCPI_IS_APPIMAGE_BUILD)
install_symlink("bin/${MCPI_VARIANT_NAME}" "AppRun")
install_symlink("share/applications/${MCPI_APP_ID}.desktop" "${MCPI_APP_ID}.desktop")
install_symlink("." "usr")
endif()

View File

@ -37,3 +37,4 @@ TRUE Improved Title Background
TRUE Force Touch GUI Button Behavior
TRUE Improved Button Hover Behavior
TRUE Implement Create World Dialog
TRUE Remove Forced GUI Lag

View File

@ -12,6 +12,9 @@ __attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char
// Run
int ret = execvpe(argv[0], (char *const *) argv, (char *const *) envp);
if (ret == -1) {
if (errno == ENOENT && strcmp(argv[0], "qemu-qrm")) {
ERR("Unable to find QEMU! To install on Ubuntu/Debian, run \"sudo apt install qemu-user\". To install on Arch Linux, run \"sudo pacman -Sy qemu-user\".");
}
ERR("Unable To Execute Program: %s: %s", argv[0], strerror(errno));
} else {
IMPOSSIBLE();

View File

@ -129,26 +129,6 @@ void init_compat() {
sigaction(SIGTERM, &act_sigterm, NULL);
}
// Cleanup Temporary Files
__attribute__((destructor)) static void cleanup_temporary() {
// Cleanup Executable
{
char *exe = realpath("/proc/self/exe", NULL);
// Check If Successful
if (exe != NULL) {
// Check If Executable Is Temporary
if (starts_with(exe, "/tmp")) {
// Cleanup Temporary File
if (unlink(exe) != 0) {
ERR("Unable To Cleanup Temporary File: %s", strerror(errno));
}
}
// Free
free(exe);
}
}
}
// Store Exit Requests
static int exit_requested = 0;
int compat_check_exit_requested() {

View File

@ -205,6 +205,8 @@ static void GameRenderer_render_injection(unsigned char *game_renderer, float pa
}
// Init
static void nop() {
}
void init_misc() {
// Remove Invalid Item Background (A Red Background That Appears For Items That Are Not Included In The gui_blocks Atlas)
if (feature_has("Remove Invalid Item Background", server_disabled)) {
@ -255,6 +257,11 @@ void init_misc() {
media_disable_vsync();
}
// Remove Forced GUI Lag
if (feature_has("Remove Forced GUI Lag", server_enabled)) {
overwrite_calls((void *) sleepMs, (void *) nop);
}
// Init C++ And Logging
_init_misc_cpp();
_init_misc_logging();

View File

@ -24,7 +24,7 @@ run() {
git \
cmake \
ninja-build \
nodejs
dpkg-dev
# Host Dependencies Needed For Compile
queue_pkg \
@ -65,26 +65,30 @@ run() {
architecture_specific_pkg "${arch}"
done
# Install appimagetool & appimage-builder Dependencies
queue_pkg \
python3-pip \
python3-setuptools \
python3-wheel \
patchelf \
desktop-file-utils \
libgdk-pixbuf2.0-dev \
fakeroot \
gtk-update-icon-cache \
shared-mime-info \
squashfs-tools \
zsync \
sed
# Install Queue
sudo apt-get install --no-install-recommends -y ${PKG_QUEUE}
# Install appimage-builder
sudo pip3 install 'git+https://github.com/AppImageCrafters/appimage-builder.git'
# Install appimagetool
sudo rm -rf /opt/squashfs-root /opt/appimagetool.AppDir
sudo rm -f /opt/appimagetool /usr/local/bin/appimagetool
case "$(dpkg-architecture -qDEB_BUILD_ARCH)" in
'armhf') APPIMAGE_ARCH='armhf';;
'arm64') APPIMAGE_ARCH='aarch64';;
'i386') APPIMAGE_ARCH='i686';;
'amd64') APPIMAGE_ARCH='x86_64';;
esac
sudo mkdir -p /opt
sudo wget -O /opt/appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${APPIMAGE_ARCH}.AppImage"
sudo chmod +x /opt/appimagetool
# Workaround AppImage Issues With Docker
cd /opt
sudo sed -i '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' ./appimagetool
# Extract
sudo ./appimagetool --appimage-extract
sudo rm -f ./appimagetool
# Link
sudo mv ./squashfs-root ./appimagetool.AppDir
sudo ln -s /opt/appimagetool.AppDir/AppRun /usr/local/bin/appimagetool
}
# Run

View File

@ -2,12 +2,33 @@
set -e
# Generate
./scripts/tools/generate-appimage-builder-yaml.js "$1" "$2"
# Prepare
NAME='minecraft-pi-reborn'
# Build/Package
appimage-builder --recipe AppImageBuilder.yml
# Build
./scripts/setup.sh "$1" "$2" -DMCPI_IS_APPIMAGE_BUILD=ON
./scripts/build.sh "$1" "$2"
# Download Runtime
case "$2" in
'armhf') RUNTIME_ARCH='armhf';;
'arm64') RUNTIME_ARCH='aarch64';;
'i386') RUNTIME_ARCH='i686';;
'amd64') RUNTIME_ARCH='x86_64';;
esac
mkdir -p build/appimage
if [ ! -f "build/appimage/runtime-$2" ]; then
wget -O "build/appimage/runtime-$2" "https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-${RUNTIME_ARCH}"
fi
# Package
ARCH="${RUNTIME_ARCH}" appimagetool \
--updateinformation "zsync|https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/${NAME}-latest-$2.AppImage.zsync" \
--runtime-file "build/appimage/runtime-$2" \
--comp xz \
"./out/$1-$2" \
"./out/${NAME}-$1-$(cat VERSION)-$2.AppImage"
# Move ZSync
rm -f "./out/minecraft-pi-reborn-$1-latest-$2.AppImage.zsync"
mv "./minecraft-pi-reborn-$1-$(cat VERSION)-$2.AppImage.zsync" "./out/minecraft-pi-reborn-$1-latest-$2.AppImage.zsync"
rm -f "./out/${NAME}-$1-latest-$2.AppImage.zsync"
mv "./${NAME}-$1-$(cat VERSION)-$2.AppImage.zsync" "./out/${NAME}-$1-latest-$2.AppImage.zsync"

View File

@ -3,8 +3,9 @@
set -e
# Build Test
./scripts/setup.sh server "$(dpkg-architecture -qDEB_BUILD_ARCH)"
./scripts/build.sh server "$(dpkg-architecture -qDEB_BUILD_ARCH)"
ARCH="$(dpkg-architecture -qDEB_BUILD_ARCH)"
./scripts/setup.sh server "${ARCH}"
./scripts/build.sh server "${ARCH}"
# Add minecraft-pi-reborn-server To PATH
export PATH="$(pwd)/out/server-$(dpkg-architecture -qDEB_BUILD_ARCH)/usr/bin:${PATH}"

View File

@ -1,195 +0,0 @@
#!/usr/bin/env node
// Child Process
const child_process = require('child_process');
// Arguments
if (process.argv.length < 4) {
throw new Error('Invalid Arguments');
}
const mode = process.argv[2];
const arch = process.argv[3];
// Data
const id = `com.thebrokenrail.MCPIReborn${mode === 'server' ? 'Server' : 'Client'}`;
const name = `minecraft-pi-reborn-${mode}`;
const updateURL = `https://jenkins.thebrokenrail.com/job/minecraft-pi-reborn/job/master/lastSuccessfulBuild/artifact/out/${name}-latest-${arch}.AppImage.zsync`;
// APT Sources
const apt_sources = child_process.execFileSync('./scripts/tools/get-apt-sources.sh', [], {encoding: 'utf-8'}).trim().split('\n');
const apt_sources_formatted = [];
for (const apt_source of apt_sources) {
apt_sources_formatted.push({sourceline: apt_source});
}
// Version
const fs = require('fs');
const version = fs.readFileSync('VERSION', 'utf8').trim();
// Packages/Dependencies
const packages = [
'libc6',
'libstdc++6',
'patchelf'
];
if (mode === 'client') {
// GLFW's Dependencies Aren't Included As They Should Be Provided By The Host System
packages.push(
'libgtk-3-0',
'libglib2.0-0',
'libgdk-pixbuf2.0-0',
'librsvg2-common',
'shared-mime-info',
'libopenal1'
);
}
if (arch !== 'armhf' && arch !== 'arm64') {
packages.push('qemu-user');
}
// Package Exclusions
const packageExclusions = [
// Exclude Unneeded Packages
'humanity-icon-theme',
'adwaita-icon-theme',
'libxml2',
'*systemd*',
'dconf-service',
'dconf-gsettings-backend',
'librest-*',
'libcups2',
'libcolord2',
'libmount1',
'libwayland-*'
];
// APT
const apt = {
arch: arch,
sources: apt_sources_formatted,
allow_unauthenticated: true,
include: packages,
exclude: packageExclusions
};
// Get Architecture Triplet
const triplet = {
'amd64': 'x86_64-linux-gnu',
'i386': 'i386-linux-gnu',
'arm64': 'aarch64-linux-gnu',
'armhf': 'arm-linux-gnueabihf'
}[arch];
if (!triplet) {
throw new Error();
}
// Files
const files = {
exclude: [
// Exclude Unused Files
`usr/lib/${triplet}/gconv`,
'usr/share/man',
'usr/share/doc/*/README.*',
'usr/share/doc/*/changelog.*',
'usr/share/doc/*/NEWS.*',
'usr/share/doc/*/TODO.*',
'usr/include',
'usr/share/lintian',
'usr/share/gcc',
'usr/share/gdb',
'usr/share/locale',
'usr/share/help',
'usr/bin/update-mime-database'
]
};
// Script After Bundling Dependencies
const afterBundle = [
// Remove Unused QEMU Binaries
'find ./AppDir/usr/bin -maxdepth 1 -name \'qemu-*\' -a ! -name \'qemu-arm\' -delete'
];
// Environment
const env = {
APPDIR_MODULE_DIR: '/tmp/.minecraft-pi-patched'
};
if (mode === 'client') {
// Make GTK Work (Zenity Uses GTK)
env.GTK_EXE_PREFIX = '${APPDIR}/usr';
env.GTK_PATH = `\${APPDIR}/usr/lib/${triplet}/gtk-3.0`;
env.GTK_DATA_PREFIX = '${APPDIR}';
env.GTK_THEME = 'Default';
env.XDG_DATA_DIRS = '${APPDIR}/share:${APPDIR}/usr/share:/share:/usr/share';
env.APPDIR_LIBRARY_PATH = `\${APPDIR}/usr/lib/${triplet}:\${APPDIR}/usr/${triplet}/lib:\${APPDIR}/lib/${triplet}:\${APPDIR}/usr/lib:\${APPDIR}/usr/lib/${triplet}/gdk-pixbuf-2.0/2.10.0/loaders`;
}
// Runtime
const runtime = {
env: env,
preserve: arch !== 'armhf' ? [
// On non-ARM32 systems, an ARM32 linker is embedded, this
// prevents AppImage-Builder from modifying ARM32 binaries
// to use a (usually non-existent) system linker.
`usr/lib/${name}/minecraft-pi`,
`usr/lib/${name}/**/*.so`,
`usr/lib/${name}/sysroot`
] : [
// MCPI's license prohibits distributing a modified
// minecraft-pi binary.
`usr/lib/${name}/minecraft-pi`
]
};
// AppDir
const appDir = {
path: `./AppDir`,
app_info: {
id: id,
name: `${name}`,
icon: id,
version: version,
exec: `usr/bin/${name}`,
exec_args: '$@'
},
apt: apt,
files: files,
after_bundle: afterBundle,
runtime: runtime
};
// Build Script
const script = [
`rm -rf ./build/${mode}-${arch}`,
`./scripts/setup.sh ${mode} ${arch} -DMCPI_IS_APPIMAGE_BUILD=ON`,
`rm -rf ./out/${mode}-${arch}`,
`./scripts/build.sh ${mode} ${arch}`,
'rm -rf ./AppDir',
`cp -ar ./out/${mode}-${arch} ./AppDir`
];
// AppImage
const appImageArch = {
'amd64': 'x86_64',
'i386': 'i686',
'arm64': 'aarch64',
'armhf': 'armhf'
}[arch];
if (!appImageArch) {
throw new Error();
}
const appImage = {
arch: appImageArch,
file_name: `./out/${name}-${version}-${arch}.AppImage`,
'update-information': `zsync|${updateURL}`
};
// Root
const root = {
version: 1,
AppDir: appDir,
script: script,
AppImage: appImage
};
// Write
fs.writeFileSync(`AppImageBuilder.yml`, JSON.stringify(root, null, 4));

View File

@ -15,6 +15,9 @@ typedef unsigned char bool;
typedef void (*renderCursor_t)(float x, float y, unsigned char *minecraft);
static renderCursor_t renderCursor = (renderCursor_t) 0x480c4;
typedef void (*sleepMs_t)(int32_t x);
static sleepMs_t sleepMs = (sleepMs_t) 0x13cf4;
static char **default_path = (char **) 0xe264; // /.minecraft/
static char **default_username = (char **) 0x18fd4; // StevePi
static char **minecraft_pi_version = (char **) 0x39d94; // v0.1.1 alpha