AppImage!
This commit is contained in:
parent
c1377d4f2a
commit
c33a27b2ea
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,3 +4,6 @@ debian/tmp
|
|||||||
build
|
build
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
*.autosave
|
*.autosave
|
||||||
|
AppImageBuilder.yml
|
||||||
|
appimage-builder-cache
|
||||||
|
AppDir
|
||||||
|
@ -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)
|
||||||
|
23
Dockerfile
23
Dockerfile
@ -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
7
debian/client-amd64
vendored
@ -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
7
debian/client-arm64
vendored
@ -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
7
debian/client-armhf
vendored
@ -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
7
debian/server-amd64
vendored
@ -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
7
debian/server-arm64
vendored
@ -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
7
debian/server-armhf
vendored
@ -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
|
|
@ -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
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
@ -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
|
||||||
// Use Correct LibC
|
|
||||||
#ifndef __ARM_ARCH
|
|
||||||
setenv("QEMU_LD_PREFIX", "/usr/arm-linux-gnueabihf", 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create Full Path
|
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
safe_asprintf(&full_path, "%s/" MCPI_NAME, binary_directory);
|
safe_asprintf(&full_path, "%s/" MCPI_BINARY, binary_directory);
|
||||||
|
char *resolved_path = realpath(full_path, NULL);
|
||||||
|
ALLOC_CHECK(resolved_path);
|
||||||
|
free(full_path);
|
||||||
|
|
||||||
|
// Set MCPI_EXECUTABLE_PATH
|
||||||
|
set_and_print_env("MCPI_EXECUTABLE_PATH", resolved_path);
|
||||||
|
|
||||||
|
// Set MCPI_DIRECTORY
|
||||||
|
chop_last_component(&resolved_path);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
|
@ -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
|
|
||||||
|
185
scripts/generate-appimage-builder-yaml.js
Executable file
185
scripts/generate-appimage-builder-yaml.js
Executable 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));
|
@ -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
14
scripts/package-all.sh
Executable 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
|
@ -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
|
|
||||||
|
@ -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}"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user