AppImage!

This commit is contained in:
TheBrokenRail 2022-03-09 18:47:31 -05:00
parent c1377d4f2a
commit c33a27b2ea
29 changed files with 404 additions and 158 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@ debian/tmp
build build
CMakeLists.txt.user CMakeLists.txt.user
*.autosave *.autosave
AppImageBuilder.yml
appimage-builder-cache
AppDir

View File

@ -7,6 +7,7 @@ option(MCPI_HEADLESS_MODE "Headless Mode" ${MCPI_SERVER_MODE})
set(MCPI_BUILD_MODE "both" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code; \"both\" = Build All Code As ARM") set(MCPI_BUILD_MODE "both" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code; \"both\" = Build All Code As ARM")
set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "both" "arm" "native") set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "both" "arm" "native")
option(MCPI_OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" FALSE) option(MCPI_OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" FALSE)
option(MCPI_IS_APPIMAGE_BUILD "AppImage Build" FALSE)
# Configure Build Mode # Configure Build Mode
if(MCPI_BUILD_MODE STREQUAL "arm") if(MCPI_BUILD_MODE STREQUAL "arm")
@ -95,6 +96,9 @@ endif()
if(MCPI_HEADLESS_MODE) if(MCPI_HEADLESS_MODE)
add_definitions(-DMCPI_HEADLESS_MODE) add_definitions(-DMCPI_HEADLESS_MODE)
endif() endif()
if(MCPI_IS_APPIMAGE_BUILD)
add_definitions(-DMCPI_IS_APPIMAGE_BUILD)
endif()
# Version # Version
file(STRINGS VERSION VERSION) file(STRINGS VERSION VERSION)

View File

@ -1,21 +1,32 @@
FROM debian:bullseye-slim FROM debian:bullseye-slim
# Copy DEB
ADD ./out/minecraft-pi-reborn-server_*_amd64.deb /root
# Install # Install
RUN \ RUN \
apt-get update && \ apt-get update && \
apt-get install -y tini && \ apt-get install -y tini sed && \
(dpkg -i /root/*.deb || :) && \
apt-get --fix-broken install -y && \ apt-get --fix-broken install -y && \
rm -f /root/*.deb && \ rm -f /root/*.deb && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# Copy AppImage
RUN mkdir /app
ADD ./out/minecraft-pi-reborn-server-*-amd64.AppImage /app
# Extract AppImage
WORKDIR /app
RUN \
sed -i '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' ./*.AppImage && \
./*.AppImage --appimage-extract && \
rm -f ./*.AppImage
# Setup AppImage
ENV OWD=/data
ENV APPDIR=/app/squashfs-root
# Setup Working Directory # Setup Working Directory
RUN mkdir /data RUN mkdir /data
WORKDIR /data WORKDIR /data
# Setup Entrypoint # Setup Entrypoint
ENTRYPOINT ["/usr/bin/tini", "--"] ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["minecraft-pi-reborn-server"] CMD ["/app/squashfs-root/AppRun"]

7
debian/client-amd64 vendored
View File

@ -1,7 +0,0 @@
Package: minecraft-pi-reborn-client
Version: ${VERSION}
Maintainer: TheBrokenRail <connor24nolan@live.com>
Description: Fun with Blocks
Homepage: https://www.minecraft.net/en-us/edition/pi
Architecture: amd64
Depends: libc6, libstdc++6, libc6-armhf-cross, libstdc++6-armhf-cross, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1, qemu-user

7
debian/client-arm64 vendored
View File

@ -1,7 +0,0 @@
Package: minecraft-pi-reborn-client
Version: ${VERSION}
Maintainer: TheBrokenRail <connor24nolan@live.com>
Description: Fun with Blocks
Homepage: https://www.minecraft.net/en-us/edition/pi
Architecture: arm64
Depends: libc6, libstdc++6, libc6:armhf, libstdc++6:armhf, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1

7
debian/client-armhf vendored
View File

@ -1,7 +0,0 @@
Package: minecraft-pi-reborn-client
Version: ${VERSION}
Maintainer: TheBrokenRail <connor24nolan@live.com>
Description: Fun with Blocks
Homepage: https://www.minecraft.net/en-us/edition/pi
Architecture: armhf
Depends: libc6, libstdc++6, zenity, libgles1, libegl1, libglfw3 | libglfw3-wayland, libfreeimage3, libopenal1

7
debian/server-amd64 vendored
View File

@ -1,7 +0,0 @@
Package: minecraft-pi-reborn-server
Version: ${VERSION}
Maintainer: TheBrokenRail <connor24nolan@live.com>
Description: Fun with Blocks
Homepage: https://www.minecraft.net/en-us/edition/pi
Architecture: amd64
Depends: libc6, libstdc++6, libc6-armhf-cross, libstdc++6-armhf-cross, qemu-user

7
debian/server-arm64 vendored
View File

@ -1,7 +0,0 @@
Package: minecraft-pi-reborn-server
Version: ${VERSION}
Maintainer: TheBrokenRail <connor24nolan@live.com>
Description: Fun with Blocks
Homepage: https://www.minecraft.net/en-us/edition/pi
Architecture: arm64
Depends: libc6, libstdc++6, libc6:armhf, libstdc++6:armhf

7
debian/server-armhf vendored
View File

@ -1,7 +0,0 @@
Package: minecraft-pi-reborn-server
Version: ${VERSION}
Maintainer: TheBrokenRail <connor24nolan@live.com>
Description: Fun with Blocks
Homepage: https://www.minecraft.net/en-us/edition/pi
Architecture: armhf
Depends: libc6, libstdc++6

View File

@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Name=Minecraft: Pi Edition: Reborn Name=Minecraft: Pi Edition: Reborn
Comment=Fun with Blocks Comment=Fun with Blocks
Icon=minecraft-pi-reborn-client Icon=com.thebrokenrail.MCPIReborn
StartupNotify=false StartupNotify=false
StartupWMClass=Minecraft: Pi Edition: Reborn StartupWMClass=Minecraft: Pi Edition: Reborn
Exec=minecraft-pi-reborn-client Exec=minecraft-pi-reborn-client

View File

@ -134,32 +134,60 @@ static void load(char **ld_preload, char *folder) {
} }
} }
#define MCPI_NAME "minecraft-pi" #define MCPI_BINARY "minecraft-pi"
#define QEMU_BINARY "qemu-arm"
// Bootstrap // Bootstrap
void bootstrap(int argc, char *argv[]) { void bootstrap(int argc, char *argv[]) {
INFO("%s", "Configuring Game..."); INFO("%s", "Configuring Game...");
// AppImage
#ifdef MCPI_IS_APPIMAGE_BUILD
if (chdir(getenv("OWD")) != 0) {
ERR("AppImage: Unable To Fix Current Directory: %s", strerror(errno));
}
#endif
// Get Binary Directory // Get Binary Directory
char *binary_directory = get_binary_directory(); char *binary_directory = get_binary_directory();
// Handle AppImage
#ifdef MCPI_IS_APPIMAGE_BUILD
char *usr_prefix = getenv("APPDIR");
#else
char *usr_prefix = "";
#endif
// Configure LD_LIBRARY_PATH // Configure LD_LIBRARY_PATH
{ {
// Preserve
PRESERVE_ENVIRONMENTAL_VARIABLE("LD_LIBRARY_PATH"); PRESERVE_ENVIRONMENTAL_VARIABLE("LD_LIBRARY_PATH");
char *new_ld_path = NULL;
// Add Library Directory // Add Library Directory
char *new_ld_path;
safe_asprintf(&new_ld_path, "%s/lib", binary_directory); safe_asprintf(&new_ld_path, "%s/lib", binary_directory);
// Add Existing LD_LIBRARY_PATH
// Add MCPI_LD_LIBRARY_PATH
{
char *value = get_env_safe("MCPI_LD_LIBRARY_PATH");
if (strlen(value) > 0) {
string_append(&new_ld_path, ":%s", value);
}
}
// Add LD_LIBRARY_PATH (ARM32 Only)
#ifdef __arm__
{ {
char *value = get_env_safe("LD_LIBRARY_PATH"); char *value = get_env_safe("LD_LIBRARY_PATH");
if (strlen(value) > 0) { if (strlen(value) > 0) {
string_append(&new_ld_path, ":%s", value); string_append(&new_ld_path, ":%s", value);
} }
} }
// Load ARM Libraries
#ifdef __ARM_ARCH
string_append(&new_ld_path, "%s", ":/usr/lib/arm-linux-gnueabihf:/usr/arm-linux-gnueabihf/lib");
#endif #endif
// Load ARM Libraries (Ensure Priority)
string_append(&new_ld_path, ":%s/usr/lib/arm-linux-gnueabihf:%s/usr/arm-linux-gnueabihf/lib", usr_prefix, usr_prefix);
// Add Full Library Search Path // Add Full Library Search Path
{ {
char *value = get_full_library_search_path(); char *value = get_full_library_search_path();
@ -168,8 +196,10 @@ void bootstrap(int argc, char *argv[]) {
} }
free(value); free(value);
} }
// Add Fallback Library Directory // Add Fallback Library Directory
string_append(&new_ld_path, ":%s/fallback-lib", binary_directory); string_append(&new_ld_path, ":%s/fallback-lib", binary_directory);
// Set And Free // Set And Free
set_and_print_env("LD_LIBRARY_PATH", new_ld_path); set_and_print_env("LD_LIBRARY_PATH", new_ld_path);
free(new_ld_path); free(new_ld_path);
@ -177,9 +207,9 @@ void bootstrap(int argc, char *argv[]) {
// Configure LD_PRELOAD // Configure LD_PRELOAD
{ {
// Preserve
PRESERVE_ENVIRONMENTAL_VARIABLE("LD_PRELOAD"); PRESERVE_ENVIRONMENTAL_VARIABLE("LD_PRELOAD");
char *new_ld_preload = NULL; char *new_ld_preload = NULL;
safe_asprintf(&new_ld_preload, "%s", get_env_safe("LD_PRELOAD"));
// Built-In Mods // Built-In Mods
{ {
@ -203,6 +233,24 @@ void bootstrap(int argc, char *argv[]) {
free(mods_folder); free(mods_folder);
} }
// Add MCPI_LD_PRELOAD
{
char *value = get_env_safe("MCPI_LD_PRELOAD");
if (strlen(value) > 0) {
string_append(&new_ld_preload, ":%s", value);
}
}
// Add LD_PRELOAD (ARM32 Only)
#ifdef __arm__
{
char *value = get_env_safe("MCPI_LD_PRELOAD");
if (strlen(value) > 0) {
string_append(&new_ld_preload, ":%s", value);
}
}
#endif
// Set LD_PRELOAD // Set LD_PRELOAD
set_and_print_env("LD_PRELOAD", new_ld_preload); set_and_print_env("LD_PRELOAD", new_ld_preload);
free(new_ld_preload); free(new_ld_preload);
@ -225,40 +273,63 @@ void bootstrap(int argc, char *argv[]) {
free(new_path); free(new_path);
} }
// Start Game // Resolve Binary Path & Set MCPI_DIRECTORY
INFO("%s", "Starting Game..."); {
// Resolve Full Binary Path
char *full_path = NULL;
safe_asprintf(&full_path, "%s/" MCPI_BINARY, binary_directory);
char *resolved_path = realpath(full_path, NULL);
ALLOC_CHECK(resolved_path);
free(full_path);
// Use Correct LibC // Set MCPI_EXECUTABLE_PATH
#ifndef __ARM_ARCH set_and_print_env("MCPI_EXECUTABLE_PATH", resolved_path);
setenv("QEMU_LD_PREFIX", "/usr/arm-linux-gnueabihf", 1);
#endif
// Create Full Path // Set MCPI_DIRECTORY
char *full_path = NULL; chop_last_component(&resolved_path);
safe_asprintf(&full_path, "%s/" MCPI_NAME, binary_directory); set_and_print_env("MCPI_DIRECTORY", resolved_path);
free(resolved_path);
}
// Free Binary Directory // Free Binary Directory
free(binary_directory); free(binary_directory);
#ifdef __ARM_ARCH // Start Game
// Mark argc As Used INFO("%s", "Starting Game...");
(void) argc;
// Run // Arguments
safe_execvpe(full_path, argv, environ); int argv_start = 2; // argv = &new_args[argv_start]
#else char *new_args[argv_start /* 2 Potential Prefix Arguments (QEMU And Linker) */ + argc + 1 /* NULL-Terminator */]; //
// Copy Existing Arguments
for (int i = 1; i < argc; i++) {
new_args[i + argv_start] = argv[i];
}
// NULL-Terminator
new_args[argv_start + argc] = NULL;
// Set Executable Argument
new_args[argv_start] = getenv("MCPI_EXECUTABLE_PATH");
// Non-ARM32 Systems Need Manually Specified Linker
#ifndef __arm__
argv_start--;
char *linker = NULL;
safe_asprintf(&linker, "%s/usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3", usr_prefix);
new_args[argv_start] = linker;
// Non-ARM Systems Need QEMU
#ifndef __ARM_ARCH
argv_start--;
new_args[argv_start] = QEMU_BINARY;
// Prevent QEMU From Being Modded // Prevent QEMU From Being Modded
PASS_ENVIRONMENTAL_VARIABLE_TO_QEMU("LD_LIBRARY_PATH"); PASS_ENVIRONMENTAL_VARIABLE_TO_QEMU("LD_LIBRARY_PATH");
PASS_ENVIRONMENTAL_VARIABLE_TO_QEMU("LD_PRELOAD"); PASS_ENVIRONMENTAL_VARIABLE_TO_QEMU("LD_PRELOAD");
// Use QEMU
#define EXE_INTERPRETER "qemu-arm"
// Create Arguments List
char *new_argv[argc + 2];
for (int i = 1; i <= argc; i++) {
new_argv[i + 1] = argv[i];
}
new_argv[0] = NULL; // Updated By safe_execvpe()
new_argv[1] = full_path; // Path To MCPI
// Run
safe_execvpe(EXE_INTERPRETER, new_argv, environ);
#endif #endif
#endif
// Run
char **new_argv = &new_args[argv_start];
safe_execvpe(new_argv[0], new_argv, environ);
} }

View File

@ -37,7 +37,10 @@ char *get_full_library_search_path() {
output.pop_back(); output.pop_back();
} }
// Close Process // Close Process
pclose(file); int ret = WEXITSTATUS(pclose(file));
if (ret != 0) {
ERR("ldconfig Failed: Exit Code: %i", ret);
}
// Return // Return
char *output_str = strdup(output.c_str()); char *output_str = strdup(output.c_str());
ALLOC_CHECK(output_str); ALLOC_CHECK(output_str);

View File

@ -4,7 +4,7 @@ add_library(reborn-headers INTERFACE)
target_include_directories(reborn-headers INTERFACE include) target_include_directories(reborn-headers INTERFACE include)
if(BUILD_ARM_COMPONENTS) if(BUILD_ARM_COMPONENTS)
add_library(reborn SHARED src/reborn.c) add_library(reborn SHARED src/patch.c)
target_link_libraries(reborn dl reborn-headers) target_link_libraries(reborn dl reborn-headers)
target_compile_definitions(reborn PUBLIC -DREBORN_HAS_COMPILED_CODE) target_compile_definitions(reborn PUBLIC -DREBORN_HAS_COMPILED_CODE)
# Install # Install

View File

@ -13,7 +13,7 @@
typedef void (*text_section_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data); typedef void (*text_section_callback_t)(ElfW(Addr) section, ElfW(Word) size, void *data);
static inline void iterate_text_sections(text_section_callback_t callback, void *data) { static inline void iterate_text_sections(text_section_callback_t callback, void *data) {
// Load Main Binary // Load Main Binary
FILE *file_obj = fopen("/proc/self/exe", "rb"); FILE *file_obj = fopen(getenv("MCPI_EXECUTABLE_PATH"), "rb");
// Verify Binary // Verify Binary
if (!file_obj) { if (!file_obj) {

View File

@ -19,6 +19,18 @@ __attribute__((noreturn)) static inline void safe_execvpe(const char *pathname,
ERR("%s", "Unknown execvpe() Error"); ERR("%s", "Unknown execvpe() Error");
} }
} }
// Chop Off Last Component
static inline void chop_last_component(char **str) {
size_t length = strlen(*str);
for (size_t i = 0; i < length; i++) {
size_t j = length - i - 1;
if ((*str)[j] == '/') {
(*str)[j] = '\0';
break;
}
}
}
// Get Binary Directory (Remember To Free) // Get Binary Directory (Remember To Free)
static inline char *get_binary_directory() { static inline char *get_binary_directory() {
// Get Path To Current Executable // Get Path To Current Executable
@ -26,17 +38,12 @@ static inline char *get_binary_directory() {
ALLOC_CHECK(exe); ALLOC_CHECK(exe);
// Chop Off Last Component // Chop Off Last Component
int length = strlen(exe); chop_last_component(&exe);
for (int i = length - 1; i >= 0; i--) {
if (exe[i] == '/') {
exe[i] = '\0';
break;
}
}
// Return // Return
return exe; return exe;
} }
// Safe execvpe() Relative To Binary // Safe execvpe() Relative To Binary
__attribute__((noreturn)) static inline void safe_execvpe_relative_to_binary(const char *pathname, char *argv[], char *const envp[]) { __attribute__((noreturn)) static inline void safe_execvpe_relative_to_binary(const char *pathname, char *argv[], char *const envp[]) {
// Get Binary Directory // Get Binary Directory
@ -49,3 +56,8 @@ __attribute__((noreturn)) static inline void safe_execvpe_relative_to_binary(con
// Run // Run
safe_execvpe(full_path, argv, envp); safe_execvpe(full_path, argv, envp);
} }
// Get MCPI Directory
static inline char *get_mcpi_directory() {
return getenv("MCPI_DIRECTORY");
}

View File

@ -29,7 +29,7 @@ static char *run_command(char *command, int *return_code) {
} }
// Return // Return
*return_code = pclose(out); *return_code = WEXITSTATUS(pclose(out));
return output; return output;
} }

View File

@ -29,9 +29,8 @@ void init_home() {
// Change Directory To Binary Directory Manually // Change Directory To Binary Directory Manually
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop" unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
patch((void *) 0xe0ac, nop_patch); patch((void *) 0xe0ac, nop_patch);
char *binary_directory = get_binary_directory(); char *binary_directory = get_mcpi_directory();
if (chdir(binary_directory) != 0) { if (chdir(binary_directory) != 0) {
ERR("Unable To Change Directory: %s", strerror(errno)); ERR("Unable To Change Directory: %s", strerror(errno));
} }
free(binary_directory);
} }

View File

@ -10,10 +10,12 @@
#include "../home/home.h" #include "../home/home.h"
// Check If String Starts With Prefix
static int starts_with(const char *s, const char *t) { static int starts_with(const char *s, const char *t) {
return strncmp(s, t, strlen(t)) == 0; return strncmp(s, t, strlen(t)) == 0;
} }
// Get Override Path For File (If It Exists)
char *override_get_path(const char *filename) { char *override_get_path(const char *filename) {
// Get MCPI Home Path // Get MCPI Home Path
char *home_path = home_get(); char *home_path = home_get();
@ -23,9 +25,8 @@ char *override_get_path(const char *filename) {
// Get Data Path // Get Data Path
char *data = NULL; char *data = NULL;
char *binary_directory = get_binary_directory(); char *binary_directory = get_mcpi_directory();
safe_asprintf(&data, "%s/data", binary_directory); safe_asprintf(&data, "%s/data", binary_directory);
free(binary_directory);
int data_length = strlen(data); int data_length = strlen(data);
// Get Full Path // Get Full Path

View File

@ -23,15 +23,11 @@ std::string _sound_get_source_file() {
// Resolve // Resolve
// Get Binary Directory // Get Binary Directory
char *binary_directory = get_binary_directory(); char *binary_directory = get_mcpi_directory();
// Get Full Path // Get Full Path
char *full_path = NULL; char *full_path = NULL;
safe_asprintf(&full_path, "%s/" SOURCE_FILE_BASE, binary_directory); safe_asprintf(&full_path, "%s/" SOURCE_FILE_BASE, binary_directory);
// Free Binary Directory
free(binary_directory);
// Handle Overrides // Handle Overrides
char *overridden_full_path = override_get_path(full_path); char *overridden_full_path = override_get_path(full_path);
if (overridden_full_path != NULL) { if (overridden_full_path != NULL) {

View File

@ -1,14 +0,0 @@
#!/bin/sh
set -e
# Clean Prefix
rm -rf out
# Build
./scripts/build.sh client amd64
./scripts/build.sh server amd64
./scripts/build.sh client arm64
./scripts/build.sh server arm64
./scripts/build.sh client armhf
./scripts/build.sh server armhf

View File

@ -13,14 +13,10 @@ export ARM_PACKAGES_SUPPORTED=1
echo '==== Installing Dependencies ====' echo '==== Installing Dependencies ===='
./scripts/install-dependencies.sh ./scripts/install-dependencies.sh
# Build # Build/Package
echo '==== Building ====' echo '==== Building & Packaging ===='
./scripts/build-all.sh ./scripts/package-all.sh
# Test # Test
echo '==== Testing ====' echo '==== Testing ===='
./scripts/test.sh ./scripts/test.sh
# Package
echo '==== Packaging ===='
./scripts/package.sh

View File

@ -0,0 +1,185 @@
#!/usr/bin/env node
// 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' : ''}`;
const name = `minecraft-pi-reborn-${mode}`;
// APT Data
const apt_distribution = 'bullseye';
const apt_key_url = 'https://ftp-master.debian.org/keys/archive-key-11.asc';
// Version
const fs = require('fs');
const version = fs.readFileSync('VERSION', 'utf8').trim();
// Packages/Dependencies
const packages = [
'libc6',
'libc-bin',
'libstdc++6'
];
if (mode === 'client') {
packages.push(
'zenity',
'libcanberra-gtk3-module',
'libglfw3',
'libfreeimage3',
'libopenal1'
);
}
if (arch !== 'armhf') {
packages.push(
'libc6-armhf-cross',
'libstdc++6-armhf-cross'
);
if (arch !== 'arm64') {
packages.push('qemu-user');
}
}
// Package Exclusions
const packageExclusions = [
// Exclude Unneeded Packages
'humanity-icon-theme',
'adwaita-icon-theme',
'libwebkit2gtk-*',
'libnotify4',
'*systemd*',
'dconf-service',
'dconf-gsettings-backend',
'libgnutls*',
'librest-*',
'libcups2',
'libcolord2',
'libmount1'
];
// APT
const apt = {
arch: arch,
sources: [
{
sourceline: `deb [arch=${arch}] http://deb.debian.org/debian/ ${apt_distribution} main`,
key_url: apt_key_url
},
{
sourceline: `deb [arch=${arch}] http://deb.debian.org/debian/ ${apt_distribution}-updates main`,
key_url: apt_key_url
}
],
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/locale',
'usr/share/help'
]
};
// Script After Bundling Dependencies
const afterBundle = [
// Remove Unused QEMU Binaries
'find ./AppDir/usr/bin -maxdepth 1 -name \'qemu-*\' -a ! -name \'qemu-arm\' -delete'
];
// Runtime
const runtime = {
env: mode === 'client' ? {
// Make GTK Work (Zenity Uses GTK)
GTK_EXE_PREFIX: '${APPDIR}/usr',
GTK_PATH: `\${APPDIR}/usr/lib/${triplet}/gtk-3.0`,
GTK_DATA_PREFIX: '${APPDIR}',
GTK_THEME: 'Default',
APPDIR_LIBRARY_PATH: `\${APPDIR}/usr/lib/${triplet}:\${APPDIR}/lib/${triplet}:\${APPDIR}/usr/lib:\${APPDIR}/usr/lib/${triplet}/gdk-pixbuf-2.0/2.10.0/loaders`
} : undefined,
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/arm-linux-gnueabihf/lib'
] : undefined
};
// AppDir
const appDir = {
path: `./AppDir`,
app_info: {
id: id,
name: `${name}`,
icon: mode === 'client' ? id : 'utilities-terminal',
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`
};
// Root
const root = {
version: 1,
AppDir: appDir,
script: script,
AppImage: appImage
};
// Write
fs.writeFileSync(`AppImageBuilder.yml`, JSON.stringify(root, null, 4));

View File

@ -18,9 +18,14 @@ fi
sudo apt-get update sudo apt-get update
sudo apt-get dist-upgrade -y sudo apt-get dist-upgrade -y
# Install Everything In One Go
PKG_QUEUE=''
queue_pkg() {
PKG_QUEUE="${PKG_QUEUE} $@"
}
# Install # Install
sudo apt-get install --no-install-recommends -y \ queue_pkg \
dpkg-dev \
git \ git \
cmake \ cmake \
ninja-build \ ninja-build \
@ -28,12 +33,13 @@ sudo apt-get install --no-install-recommends -y \
libfreeimage3 libfreeimage-dev \ libfreeimage3 libfreeimage-dev \
crossbuild-essential-armhf \ crossbuild-essential-armhf \
gcc g++ \ gcc g++ \
nodejs \
libopenal-dev \ libopenal-dev \
qemu-user qemu-user
# Install ARM Dependencies # Install ARM Dependencies
if [ ! -z "${ARM_PACKAGES_SUPPORTED}" ]; then if [ ! -z "${ARM_PACKAGES_SUPPORTED}" ]; then
sudo apt-get install --no-install-recommends -y \ queue_pkg \
libglfw3:armhf libglfw3-dev:armhf \ libglfw3:armhf libglfw3-dev:armhf \
libfreeimage3:armhf \ libfreeimage3:armhf \
libopenal-dev:armhf \ libopenal-dev:armhf \
@ -43,3 +49,28 @@ if [ ! -z "${ARM_PACKAGES_SUPPORTED}" ]; then
crossbuild-essential-arm64 crossbuild-essential-arm64
fi fi
# Install appimagetool Dependencies
queue_pkg \
python3-pip \
python3-setuptools \
patchelf \
desktop-file-utils \
libgdk-pixbuf2.0-dev \
fakeroot \
strace \
fuse \
sed
# Install Queue
sudo apt-get install --no-install-recommends -y ${PKG_QUEUE}
# Download appimagetool
sudo mkdir -p /opt
sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /opt/appimagetool
# Workaround AppImage Issues With Docker
cd /opt; sudo chmod +x ./appimagetool; sed -i '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' ./appimagetool; sudo ./appimagetool --appimage-extract
sudo mv /opt/squashfs-root /opt/appimagetool.AppDir
sudo ln -s /opt/appimagetool.AppDir/AppRun /usr/local/bin/appimagetool
# Install appimage-builder
sudo pip3 install git+https://github.com/AppImageCrafters/appimage-builder.git

14
scripts/package-all.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
set -e
# Clean Prefix
rm -rf out
# Build
./scripts/package.sh client amd64
./scripts/package.sh server amd64
./scripts/package.sh client arm64
./scripts/package.sh server arm64
./scripts/package.sh client armhf
./scripts/package.sh server armhf

View File

@ -2,36 +2,8 @@
set -e set -e
# Prepare # Generate
VERSION="$(cat VERSION)" ./scripts/generate-appimage-builder-yaml.js "$1" "$2"
# Common # Build/Package
package() { appimage-builder --recipe AppImageBuilder.yml
local dir="out/$1"
# Create DEBIAN Dir
rm -rf "${dir}/DEBIAN"
mkdir -p "${dir}/DEBIAN"
cp "debian/$1" "${dir}/DEBIAN/control"
# Format DEBIAN/control
sed -i "s/\${VERSION}/${VERSION}/g" "${dir}/DEBIAN/control"
# Fix Permissions On Jenkins
chmod -R g-s "${dir}"
# Package
dpkg-deb --root-owner-group --build "${dir}" out
}
# Find And Package
for dir in out/*; do
# Check If Directory Exists
if [ -d "${dir}" ]; then
# Check If Debian Package Exists
pkg="$(basename ${dir})"
if [ -f "debian/${pkg}" ]; then
package "${pkg}"
fi
fi
done

View File

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