JS-Based Build Script
This commit is contained in:
parent
ddd9226e9e
commit
41fcc942fa
@ -34,12 +34,12 @@ jobs:
|
||||
run: ./scripts/install-dependencies.sh ${{ matrix.arch }}
|
||||
# Build
|
||||
- name: Build
|
||||
run: ./scripts/package.sh ${{ matrix.mode }} ${{ matrix.arch }}
|
||||
run: ./scripts/build.mjs appimage ${{ matrix.mode }} ${{ matrix.arch }}
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.mode }}-${{ matrix.arch }}
|
||||
path: ./out/*.AppImage*
|
||||
path: ./out/**/*.AppImage*
|
||||
# Test Project
|
||||
test:
|
||||
strategy:
|
||||
|
@ -9,8 +9,8 @@ endif()
|
||||
include(cmake/options/core-options.cmake)
|
||||
|
||||
# Build Mode
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
# Start Project
|
||||
|
@ -2,6 +2,9 @@
|
||||
mcpi_option(OPEN_SOURCE_ONLY "Only Install Open-Source Code (Will Result In Broken Install)" BOOL FALSE)
|
||||
mcpi_option(IS_APPIMAGE_BUILD "AppImage Build" BOOL FALSE)
|
||||
mcpi_option(IS_FLATPAK_BUILD "Flatpak Build" BOOL FALSE)
|
||||
if(MCPI_IS_APPIMAGE_BUILD AND MCPI_IS_FLATPAK_BUILD)
|
||||
message(FATAL_ERROR "Invalid Build Configuration")
|
||||
endif()
|
||||
|
||||
# Server/Headless Builds
|
||||
mcpi_option(SERVER_MODE "Server Mode" BOOL FALSE)
|
||||
@ -61,3 +64,13 @@ mcpi_option(APP_TITLE "App Title" STRING "${DEFAULT_APP_TITLE}")
|
||||
|
||||
# Skin Server
|
||||
mcpi_option(SKIN_SERVER "Skin Server" STRING "https://raw.githubusercontent.com/MCPI-Revival/Skins/data")
|
||||
|
||||
# QEMU
|
||||
if(BUILD_NATIVE_COMPONENTS)
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists("__ARM_ARCH" "" MCPI_IS_ARM32_OR_ARM64_TARGETING)
|
||||
set(MCPI_USE_QEMU TRUE)
|
||||
if(MCPI_IS_ARM32_OR_ARM64_TARGETING)
|
||||
set(MCPI_USE_QEMU FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -9,6 +9,7 @@ macro(setup_toolchain target)
|
||||
add_target_variant(unknown)
|
||||
add_target_variant(none)
|
||||
add_target_variant(pc)
|
||||
|
||||
# Find Compiler
|
||||
macro(find_compiler output name)
|
||||
set(possible_names "")
|
||||
@ -26,13 +27,11 @@ macro(setup_toolchain target)
|
||||
endmacro()
|
||||
find_compiler(CMAKE_C_COMPILER "gcc")
|
||||
find_compiler(CMAKE_CXX_COMPILER "g++")
|
||||
|
||||
# Extra
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
# Custom Search Paths
|
||||
if(NOT DEFINED ENV{MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS})
|
||||
# Find Root
|
||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
||||
# pkg-config
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
||||
endif()
|
||||
set(CMAKE_FIND_ROOT_PATH "/usr/${target}" "/usr/lib/${target}" "/usr")
|
||||
# pkg-config
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/${target}/pkgconfig:/usr/${target}/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig")
|
||||
endmacro()
|
||||
|
4
dependencies/CMakeLists.txt
vendored
4
dependencies/CMakeLists.txt
vendored
@ -13,11 +13,11 @@ if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
|
||||
add_subdirectory(zenity)
|
||||
endif()
|
||||
# LIEF
|
||||
if(BUILD_NATIVE_COMPONENTS OR (BUILD_ARM_COMPONENTS AND NOT MCPI_SERVER_MODE AND NOT MCPI_USE_MEDIA_LAYER_PROXY))
|
||||
if(BUILD_NATIVE_COMPONENTS OR (BUILD_MEDIA_LAYER_CORE AND NOT MCPI_HEADLESS_MODE))
|
||||
add_subdirectory(LIEF)
|
||||
endif()
|
||||
# QEMU
|
||||
if(BUILD_NATIVE_COMPONENTS AND NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64"))
|
||||
if(BUILD_NATIVE_COMPONENTS AND MCPI_USE_QEMU)
|
||||
add_subdirectory(qemu)
|
||||
endif()
|
||||
# GLFW
|
||||
|
@ -9,14 +9,5 @@
|
||||
|
||||
## Instructions
|
||||
```sh
|
||||
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
|
||||
./scripts/build.mjs <none|appimage|flatpak> <client|server> <armhf|arm64|amd64|host> [--clean] [--install] [-Dvar=value...]
|
||||
```
|
||||
|
||||
### Custom CMake Arguments
|
||||
```sh
|
||||
./scripts/setup.sh <client|server> <armhf|arm64|i686|amd64> <Custom CMake Arguments>
|
||||
./scripts/build.sh <client|server> <armhf|arm64|i686|amd64>
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
* `MCPI_TOOLCHAIN_USE_DEFAULT_SEARCH_PATHS`: Use Default CMake Search Paths Rather Than Guessing
|
||||
|
@ -10,10 +10,6 @@
|
||||
#define MCPI_BINARY "minecraft-pi"
|
||||
#define QEMU_BINARY "qemu-arm"
|
||||
|
||||
#ifndef __ARM_ARCH
|
||||
#define USE_QEMU
|
||||
#endif
|
||||
|
||||
#define REQUIRED_PAGE_SIZE 4096
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
@ -163,7 +159,7 @@ void pre_bootstrap(int argc, char *argv[]) {
|
||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
||||
|
||||
// Check Page Size (Not Needed When Using QEMU)
|
||||
#ifndef USE_QEMU
|
||||
#ifndef MCPI_USE_QEMU
|
||||
long page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size != REQUIRED_PAGE_SIZE) {
|
||||
ERR("Invalid page size! A page size of %ld bytes is required, but the system size is %ld bytes.", (long) REQUIRED_PAGE_SIZE, page_size);
|
||||
@ -338,7 +334,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
new_args[argv_start] = new_mcpi_exe_path;
|
||||
|
||||
// Non-ARM Systems Need QEMU
|
||||
#ifdef USE_QEMU
|
||||
#ifdef MCPI_USE_QEMU
|
||||
argv_start--;
|
||||
new_args[argv_start] = QEMU_BINARY;
|
||||
// Use 4k Page Size
|
||||
@ -349,7 +345,7 @@ void bootstrap(int argc, char *argv[]) {
|
||||
setup_exec_environment(1);
|
||||
|
||||
// Pass LD_* Variables Through QEMU
|
||||
#ifdef USE_QEMU
|
||||
#ifdef MCPI_USE_QEMU
|
||||
char *qemu_set_env = NULL;
|
||||
#define pass_variable_through_qemu(name) string_append(&qemu_set_env, "%s%s=%s", qemu_set_env == NULL ? "" : ",", name, getenv(name));
|
||||
for_each_special_environmental_variable(pass_variable_through_qemu);
|
||||
|
@ -12,3 +12,4 @@
|
||||
#cmakedefine MCPI_VARIANT_NAME "@MCPI_VARIANT_NAME@"
|
||||
#cmakedefine MCPI_SDK_DIR "@MCPI_SDK_DIR@"
|
||||
#cmakedefine MCPI_SKIN_SERVER "@MCPI_SKIN_SERVER@"
|
||||
#cmakedefine MCPI_USE_QEMU
|
||||
|
@ -28,7 +28,7 @@ CUSTOM_VTABLE(chat_screen, Screen) {
|
||||
self->super.m_textInputs->push_back(self->chat);
|
||||
self->chat->init(super->font);
|
||||
self->chat->setFocused(true);
|
||||
// Determien Max Length
|
||||
// Determine Max Length
|
||||
std::string prefix = _chat_get_prefix(Strings_default_username);
|
||||
int max_length = MAX_CHAT_MESSAGE_LENGTH - prefix.length();
|
||||
self->chat->setMaxLength(max_length);
|
||||
|
@ -1,8 +1,9 @@
|
||||
// Config Needs To Load First
|
||||
#include <libreborn/libreborn.h>
|
||||
#include "game-mode-internal.h"
|
||||
|
||||
// Game Mode UI Code Is Useless In Headless Mode
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
@ -11,7 +12,6 @@
|
||||
|
||||
#include <mods/text-input-box/TextInputScreen.h>
|
||||
#include <mods/touch/touch.h>
|
||||
#include "game-mode-internal.h"
|
||||
|
||||
// Strings
|
||||
#define GAME_MODE_STR(mode) ("Game Mode: " mode)
|
||||
|
196
scripts/build.mjs
Executable file
196
scripts/build.mjs
Executable file
@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env node
|
||||
import * as path from 'node:path';
|
||||
import * as url from 'node:url';
|
||||
import * as fs from 'node:fs';
|
||||
import * as child_process from 'node:child_process';
|
||||
|
||||
// Logging
|
||||
const EXIT_FAILURE = 1;
|
||||
function fail(message) {
|
||||
console.error(message);
|
||||
process.exit(EXIT_FAILURE);
|
||||
}
|
||||
function err(message) {
|
||||
fail('ERROR: ' + message);
|
||||
}
|
||||
function info(message) {
|
||||
console.log('INFO: ' + message);
|
||||
}
|
||||
|
||||
// Enums
|
||||
function Enum(values) {
|
||||
for (const value of values) {
|
||||
this[value] = {name: value.toLowerCase()};
|
||||
}
|
||||
}
|
||||
Enum.prototype.get = function (name) {
|
||||
for (const value in this) {
|
||||
if (value.toLowerCase() === name.toLowerCase()) {
|
||||
return this[value];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
function wrap(obj) {
|
||||
return new Proxy(obj, {
|
||||
get(target, property) {
|
||||
if (property in target) {
|
||||
return target[property];
|
||||
} else {
|
||||
err('Undefined Value: ' + property);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const PackageTypes = wrap(new Enum([
|
||||
'None',
|
||||
'AppImage',
|
||||
'Flatpak'
|
||||
]));
|
||||
const Variants = wrap(new Enum([
|
||||
'Client',
|
||||
'Server'
|
||||
]));
|
||||
const Architectures = wrap(new Enum([
|
||||
'AMD64',
|
||||
'ARM64',
|
||||
'ARMHF',
|
||||
'Host'
|
||||
]));
|
||||
|
||||
// Folders
|
||||
const __filename = url.fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const root = path.join(__dirname, '..');
|
||||
let build = path.join(root, 'build');
|
||||
let out = path.join(root, 'out');
|
||||
|
||||
// Positional Arguments
|
||||
let argIndex = 2; // Skip First Two Arguments
|
||||
const POSITIONAL_ARGUMENT_COUNT = 3;
|
||||
function readArg(from, type) {
|
||||
// Check Argument Count
|
||||
if (argIndex >= process.argv.length) {
|
||||
err('Expecting ' + type);
|
||||
}
|
||||
// Read Argument
|
||||
const arg = process.argv[argIndex++];
|
||||
const value = from.get(arg);
|
||||
if (value === null) {
|
||||
err(`Invalid ${type}: ${arg}`);
|
||||
}
|
||||
// Return
|
||||
return value;
|
||||
}
|
||||
// Type Of Packaging
|
||||
const packageType = readArg(PackageTypes, 'Package Type');
|
||||
// Build Variant
|
||||
const variant = readArg(Variants, 'Variant');
|
||||
// Build Architecture
|
||||
const architecture = readArg(Architectures, 'Architecture');
|
||||
// Flatpak Builds Work Best Without Custom Toolchains
|
||||
if (packageType === PackageTypes.Flatpak && architecture !== Architecture.Host) {
|
||||
err('Flatpak Builds Do Not Support Custom Toolchains');
|
||||
}
|
||||
|
||||
// CMake Build Options
|
||||
const options = {};
|
||||
|
||||
// Other Arguments
|
||||
let clean = false;
|
||||
let install = false;
|
||||
for (; argIndex < process.argv.length; argIndex++) {
|
||||
const arg = process.argv[argIndex];
|
||||
if (arg.startsWith('-D')) {
|
||||
// Pass Build Option To CMake
|
||||
let parsedArg = arg.substring(2);
|
||||
const split = parsedArg.indexOf('=');
|
||||
if (split === -1) {
|
||||
err('Unable To Parse Build Option: ' + arg);
|
||||
}
|
||||
const name = parsedArg.substring(0, split);
|
||||
const value = parsedArg.substring(split + 1);
|
||||
if (!/^[a-zA-Z_]+$/.test(name) || name.length === 0) {
|
||||
err('Invalid Build Option Name: ' + name);
|
||||
}
|
||||
options[name] = value;
|
||||
} else if (arg === '--clean') {
|
||||
// Remove Existing Build Directory
|
||||
clean = true;
|
||||
} else if (arg === '--install') {
|
||||
// Install To System Instead Of Output Directory
|
||||
if (packageType === PackageTypes.AppImage) {
|
||||
err('AppImages Cannot Be Installed');
|
||||
}
|
||||
install = true;
|
||||
} else {
|
||||
err('Invalid Argument: ' + arg);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Folders
|
||||
function updateDir(dir) {
|
||||
if (packageType !== PackageTypes.None) {
|
||||
dir = path.join(dir, packageType.name);
|
||||
}
|
||||
return path.join(dir, variant.name, architecture.name);
|
||||
}
|
||||
build = updateDir(build);
|
||||
out = updateDir(out);
|
||||
|
||||
// Configure Build Options
|
||||
function toCmakeBool(val) {
|
||||
return val ? 'ON' : 'OFF';
|
||||
}
|
||||
options['MCPI_SERVER_MODE'] = toCmakeBool(variant === Variants.Server);
|
||||
options['MCPI_IS_APPIMAGE_BUILD'] = toCmakeBool(packageType === PackageTypes.AppImage);
|
||||
options['MCPI_IS_FLATPAK_BUILD'] = toCmakeBool(packageType === PackageTypes.Flatpak);
|
||||
if (architecture !== Architectures.Host) {
|
||||
options['CMAKE_TOOLCHAIN_FILE'] = path.join(root, 'cmake', 'toolchain', architecture.name + '-toolchain.cmake');
|
||||
} else {
|
||||
delete options['CMAKE_TOOLCHAIN_FILE'];
|
||||
}
|
||||
if (packageType === PackageTypes.AppImage) {
|
||||
options['CPACK_PACKAGE_DIRECTORY'] = out;
|
||||
}
|
||||
|
||||
// Make Build Directory
|
||||
function createDir(dir, clean) {
|
||||
if (clean) {
|
||||
fs.rmSync(dir, {recursive: true, force: true});
|
||||
}
|
||||
fs.mkdirSync(dir, {recursive: true});
|
||||
}
|
||||
createDir(build, clean);
|
||||
if (!install) {
|
||||
createDir(out, true);
|
||||
}
|
||||
|
||||
// Run CMake
|
||||
function run(command) {
|
||||
try {
|
||||
info('Running: ' + command.join(' '));
|
||||
child_process.execFileSync(command[0], command.slice(1), {cwd: build, stdio: 'inherit'});
|
||||
} catch (e) {
|
||||
err(e);
|
||||
}
|
||||
}
|
||||
const cmake = ['cmake', '-GNinja'];
|
||||
for (const option in options) {
|
||||
cmake.push(`-D${option}=${options[option]}`);
|
||||
}
|
||||
cmake.push(root);
|
||||
run(cmake);
|
||||
|
||||
// Build
|
||||
run(['cmake', '--build', '.']);
|
||||
|
||||
// Package
|
||||
if (packageType !== PackageTypes.AppImage) {
|
||||
if (!install) {
|
||||
process.env.DESTDIR = out;
|
||||
}
|
||||
run(['cmake', '--install', '.']);
|
||||
} else {
|
||||
run(['cmake', '--build', '.', '--target', 'package']);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Variables
|
||||
MODE="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
ARCH="$(echo "$2" | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
# Run CMake If Needed
|
||||
if [ ! -f "build/${MODE}-${ARCH}/build.ninja" ]; then
|
||||
./scripts/setup.sh "${MODE}" "${ARCH}"
|
||||
fi
|
||||
# Use Build Dir
|
||||
cd "build/${MODE}-${ARCH}"
|
||||
|
||||
# Create Prefix
|
||||
if [ -z "${DESTDIR+x}" ]; then
|
||||
export DESTDIR="$(cd ../../; pwd)/out/${MODE}-${ARCH}"
|
||||
rm -rf "${DESTDIR}"
|
||||
mkdir -p "${DESTDIR}"
|
||||
fi
|
||||
|
||||
# Build
|
||||
cmake --build .
|
||||
cmake --install .
|
||||
|
||||
# Exit
|
||||
cd ../../
|
@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Prepare
|
||||
NAME='minecraft-pi-reborn'
|
||||
MODE="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
ARCH="$(echo "$2" | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
# Build
|
||||
./scripts/setup.sh "${MODE}" "${ARCH}" -DMCPI_IS_APPIMAGE_BUILD=ON
|
||||
./scripts/build.sh "${MODE}" "${ARCH}"
|
||||
|
||||
# Package
|
||||
cd "build/${MODE}-${ARCH}"
|
||||
rm -f *.AppImage*
|
||||
cmake --build . --target package
|
||||
|
||||
# Copy Output
|
||||
cp *.AppImage* ../../out
|
@ -1,38 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Variables
|
||||
MODE="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
ARCH="$(echo "$2" | tr '[:upper:]' '[:lower:]')"
|
||||
shift 2
|
||||
|
||||
# Verify Mode
|
||||
if [ "${MODE}" != "client" ] && [ "${MODE}" != "server" ]; then
|
||||
echo "Invalid Mode: ${MODE}" > /dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find Toolchain
|
||||
toolchain_file="$(pwd)/cmake/toolchain/${ARCH}-toolchain.cmake"
|
||||
if [ ! -f "${toolchain_file}" ]; then
|
||||
echo "Invalid Architecture: ${ARCH}" > /dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create Build Dir
|
||||
rm -rf "build/${MODE}-${ARCH}"
|
||||
mkdir -p "build/${MODE}-${ARCH}"
|
||||
cd "build/${MODE}-${ARCH}"
|
||||
|
||||
# Server Build
|
||||
server_mode='OFF'
|
||||
if [ "${MODE}" = "server" ]; then
|
||||
server_mode='ON'
|
||||
fi
|
||||
|
||||
# Build Components
|
||||
cmake -GNinja -DCMAKE_TOOLCHAIN_FILE="${toolchain_file}" -DMCPI_SERVER_MODE="${server_mode}" "$@" ../../
|
||||
|
||||
# Exit
|
||||
cd ../../
|
@ -4,14 +4,13 @@ set -e
|
||||
|
||||
# Variables
|
||||
MODE="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
|
||||
ARCH="$(dpkg-architecture -qDEB_BUILD_ARCH)"
|
||||
ARCH='host'
|
||||
|
||||
# Build
|
||||
./scripts/setup.sh "${MODE}" "${ARCH}" -DMCPI_HEADLESS_MODE=ON
|
||||
./scripts/build.sh "${MODE}" "${ARCH}"
|
||||
./scripts/build.mjs none "${MODE}" "${ARCH}" -DMCPI_HEADLESS_MODE=ON
|
||||
|
||||
# Add To PATH
|
||||
export PATH="$(pwd)/out/${MODE}-${ARCH}/usr/bin:${PATH}"
|
||||
export PATH="$(pwd)/out/${MODE}/${ARCH}/usr/bin:${PATH}"
|
||||
|
||||
# Make Test Directory
|
||||
rm -rf build/test
|
||||
|
Loading…
Reference in New Issue
Block a user