JS-Ify Dependency Installation

This commit is contained in:
TheBrokenRail 2025-01-03 10:20:33 -05:00
parent b767b9d4ec
commit b055980103
8 changed files with 202 additions and 134 deletions

View File

@ -28,7 +28,7 @@ jobs:
submodules: true
# Dependencies
- name: Install Dependencies
run: ./scripts/install-dependencies.sh build ${{ matrix.arch }}
run: ./scripts/install-dependencies.mjs build ${{ matrix.arch }}
# Build
- name: Build
run: ./scripts/build.mjs appimage ${{ matrix.arch }}
@ -61,7 +61,7 @@ jobs:
submodules: false
# Dependencies
- name: Install Dependencies
run: ./scripts/install-dependencies.sh test ${{ matrix.arch }}
run: ./scripts/install-dependencies.mjs test ${{ matrix.arch }}
# Download Artifact
- name: Download Artifact
uses: actions/download-artifact@v3
@ -84,7 +84,7 @@ jobs:
submodules: false
# Dependencies
- name: Install Dependencies
run: ./scripts/install-dependencies.sh example_mods amd64
run: ./scripts/install-dependencies.mjs sdk amd64
# SDK
- name: Download SDK
uses: actions/download-artifact@v3

@ -1 +1 @@
Subproject commit 441bb4620bc7242a822b7cb4419c965d76119f6b
Subproject commit d4900dab6a9eea864fb14ed1ff7ea5b9f8678e04

View File

@ -1,17 +1,9 @@
#!/usr/bin/env node
import * as path from 'node:path';
import * as url from 'node:url';
import * as fs from 'node:fs';
import { info, err, run } from './lib/util.mjs';
import { info, err, run, createDir, getScriptsDir } from './lib/util.mjs';
import { parseOptions, Enum, Architectures } from './lib/options.mjs';
// Enums
const PackageTypes = new Enum([
'None',
'AppImage',
'Flatpak'
]);
// CMake Options
const cmakeArgPrefix = '-D';
const cmakeArgSeparator = '=';
@ -41,6 +33,11 @@ function parseCMakeOption(arg) {
}
// Options
const PackageTypes = new Enum([
'None',
'AppImage',
'Flatpak'
]);
const options = parseOptions([
['packageType', PackageTypes],
['architecture', Architectures]
@ -59,8 +56,7 @@ if (options.packageType === PackageTypes.AppImage && options.install) {
}
// Folders
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const __dirname = getScriptsDir();
const root = path.join(__dirname, '..');
let build = path.join(root, 'build');
let out = path.join(root, 'out');
@ -97,12 +93,6 @@ if (options.architecture !== Architectures.Host) {
}
// Make Build Directory
function createDir(dir, clean) {
if (clean) {
fs.rmSync(dir, {recursive: true, force: true});
}
fs.mkdirSync(dir, {recursive: true});
}
createDir(build, options.clean);
if (!options.install) {
createDir(out, !useOutRoot);

View File

@ -1,3 +1,2 @@
#!/bin/sh
exec sed -i '0,/AI\x02/{s|AI\x02|\x00\x00\x00|}' "$1"

150
scripts/install-dependencies.mjs Executable file
View File

@ -0,0 +1,150 @@
#!/usr/bin/env node
import * as path from 'node:path';
import * as fs from 'node:fs';
import { err, run, makeExecutable, getDebianVersion, getScriptsDir, info } from './lib/util.mjs';
import { parseOptions, Enum, Architectures } from './lib/options.mjs';
// Check System
if (process.getuid() !== 0) {
err("Must Run As Root!");
}
if (!fs.existsSync('/etc/debian_version')) {
err('Non-Debian OS Detected');
}
// Options
const Modes = new Enum([
'Build',
'Test',
'SDK'
]);
const options = parseOptions([
['mode', Modes],
['architecture', Architectures]
], [], null);
// Setup Backports If Needed
const debianVersion = getDebianVersion();
info('OS Version: ' + debianVersion);
let backportsSuffix = '';
if (debianVersion === 'bullseye') {
const repo = debianVersion + '-backports';
const source = `deb http://deb.debian.org/debian ${repo} main\n`;
fs.writeFileSync(`/etc/apt/sources.list.d/${repo}.list`, source);
backportsSuffix = '/' + repo;
}
// Update APT
let archSuffix = '';
if (options.architecture !== Architectures.Host) {
const arch = options.architecture.name;
run(['dpkg', '--add-architecture', arch]);
archSuffix = ':' + arch;
}
run(['apt-get', 'update']);
run(['apt-get', 'dist-upgrade', '-y']);
// Install Packages
const packages = [];
function addPackageForBuild(...arr) {
// The machine the package is built on.
packages.push(...arr);
}
function addPackageForHost(...arr) {
// The machine the package is built for.
for (const name of arr) {
packages.push(name + archSuffix);
}
}
// Build Dependencies
const handlers = new Map();
handlers.set(Modes.Build, function () {
// Build Dependencies
addPackageForBuild(
'git',
'cmake' + backportsSuffix,
'ninja-build'
);
// Compiler
if (options.architecture === Architectures.Host) {
addPackageForBuild('gcc', 'g++');
} else {
addPackageForBuild('crossbuild-essential-' + options.architecture.name);
}
// Main Dependencies
addPackageForHost('libopenal-dev');
// GLFW Dependencies
addPackageForBuild('libwayland-bin');
addPackageForHost(
'libwayland-dev',
'libxkbcommon-dev',
'libx11-dev',
'libxcursor-dev',
'libxi-dev',
'libxinerama-dev',
'libxrandr-dev',
'libxext-dev'
);
// QEMU Dependencies
addPackageForBuild(
'python3',
'python3-venv',
`python3-tomli` + backportsSuffix
);
addPackageForHost('libglib2.0-dev');
// AppImage Dependencies
addPackageForBuild(
'appstream',
'zsync'
);
// Download AppImageTool
function getAppImageArch() {
switch (process.arch) {
case 'x64': return 'x86_64';
case 'arm64': return 'aarch64';
case 'arm': return 'armhf';
default: err('Unsupported Build Architecture');
}
}
let appimagetool = '/opt/appimagetool';
run(['wget', '-O', appimagetool, `https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${getAppImageArch()}.AppImage`]);
makeExecutable(appimagetool);
run([getScriptsDir() + '/fix-appimage-for-docker.sh', appimagetool]);
const script = `#!/bin/sh\nexec ${appimagetool} --appimage-extract-and-run "$@"\n`;
appimagetool = '/usr/local/bin/' + path.basename(appimagetool);
fs.writeFileSync(appimagetool, script);
makeExecutable(appimagetool);
});
// Testing Dependencies
handlers.set(Modes.Test, function () {
addPackageForHost(
'libc6',
'libstdc++6',
'libopenal1',
'libglib2.0-0'
);
});
// SDK Usage Dependencies
handlers.set(Modes.SDK, function () {
addPackageForBuild(
'cmake' + backportsSuffix,
'ninja-build',
'g++-arm-linux-gnueabihf',
'gcc-arm-linux-gnueabihf'
);
});
// Run
handlers.get(options.mode)();
// Install Packages
run(['apt-get', 'install', '--no-install-recommends', '-y', ...packages]);

View File

@ -1,109 +0,0 @@
#!/bin/sh
set -e
# Don't Use Sudo When Running As Root
if [ "$(id -u)" -eq 0 ]; then
sudo() {
"$@"
}
fi
# Setup Backports
CODENAME="$(. /etc/os-release && echo "${VERSION_CODENAME}")"
BACKPORTS=''
if [ "${CODENAME}" = 'bullseye' ]; then
BACKPORTS="${CODENAME}-backports"
echo "deb http://deb.debian.org/debian ${BACKPORTS} main" | sudo tee "/etc/apt/sources.list.d/${BACKPORTS}.list" > /dev/null
BACKPORTS="/${BACKPORTS}"
fi
# Variables
MODE="$1"
ARCH="$(echo "$2" | tr '[:upper:]' '[:lower:]')"
# Add ARM Repository
sudo dpkg --add-architecture "${ARCH}"
# Update APT
sudo apt-get update
sudo apt-get dist-upgrade -y
# Run APT
install_pkg() {
sudo apt-get install --no-install-recommends -y "$@"
}
# Build Dependencies
run_build() {
install_pkg \
`# Build System` \
git \
"cmake${BACKPORTS}" \
ninja-build \
python3 \
python3-venv \
"python3-tomli${BACKPORTS}" \
`# Host Dependencies Needed For Compile` \
libwayland-bin \
`# Compiler` \
"crossbuild-essential-$1" \
`# Main Dependencies` \
"libopenal-dev:$1" \
`# GLFW Dependencies` \
"libwayland-dev:$1" \
"libxkbcommon-dev:$1" \
"libx11-dev:$1" \
"libxcursor-dev:$1" \
"libxi-dev:$1" \
"libxinerama-dev:$1" \
"libxrandr-dev:$1" \
"libxext-dev:$1" \
`# QEMU Dependencies` \
"libglib2.0-dev:$1" \
`# AppImage` \
appstream \
zsync
# Install appimagetool
sudo rm -rf /opt/squashfs-root /opt/appimagetool /usr/local/bin/appimagetool
case "$(dpkg --print-architecture)" in
'armhf') APPIMAGE_ARCH='armhf';;
'arm64') APPIMAGE_ARCH='aarch64';;
'amd64') APPIMAGE_ARCH='x86_64';;
esac
sudo mkdir -p /opt
sudo wget -O /opt/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${APPIMAGE_ARCH}.AppImage"
sudo chmod +x /opt/appimagetool
# Workaround AppImage Issues With Docker
sudo ./scripts/fix-appimage-for-docker.sh /opt/appimagetool
# Extract
cd /opt
sudo ./appimagetool --appimage-extract > /dev/null
sudo rm -f ./appimagetool
# Link
sudo mv ./squashfs-root ./appimagetool
printf '#!/bin/sh\nexec /opt/appimagetool/AppRun "$@"\n' | sudo tee /usr/local/bin/appimagetool > /dev/null
sudo chmod +x /usr/local/bin/appimagetool
}
# Test Dependencies
run_test() {
install_pkg \
"libc6:$1" \
"libstdc++6:$1" \
"libopenal1:$1" \
"libglib2.0-0:$1"
}
# Example Mods Dependencies
run_example_mods() {
install_pkg \
cmake \
ninja-build \
g++-arm-linux-gnueabihf \
gcc-arm-linux-gnueabihf
}
# Install Packages
"run_${MODE}" "${ARCH}"

View File

@ -36,7 +36,7 @@ function formatFlag(name) {
return '--' + name;
}
function formatOptionalArg(arg) {
return '[' + arg + '] ';;
return '[' + arg + '] ';
}
export function parseOptions(positionalArgs, flags, customHandler) {
// Usage Text
@ -52,7 +52,9 @@ export function parseOptions(positionalArgs, flags, customHandler) {
for (const flag of flags) {
usage += formatOptionalArg(formatFlag(flag));
}
usage += formatOptionalArg(customHandler(null));
if (customHandler) {
usage += formatOptionalArg(customHandler(null));
}
usage = usage.trim();
// Copy Arguments
@ -81,7 +83,7 @@ export function parseOptions(positionalArgs, flags, customHandler) {
// Unknown Arguments
for (const arg of args) {
if (!customHandler(arg)) {
if (!customHandler || !customHandler(arg)) {
fail(usage);
}
}

View File

@ -1,4 +1,7 @@
import * as child_process from 'node:child_process';
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as url from 'node:url';
// Logging
const EXIT_FAILURE = 1;
@ -22,3 +25,36 @@ export function run(command) {
err(e);
}
}
// Create Directory
export function createDir(dir, clean) {
if (clean) {
fs.rmSync(dir, {recursive: true, force: true});
}
fs.mkdirSync(dir, {recursive: true});
}
// Get System Information
export function getDebianVersion() {
const info = fs.readFileSync('/etc/os-release', 'utf8');
const lines = info.split('\n');
const prefix = 'VERSION_CODENAME=';
for (const line of lines) {
if (line.startsWith(prefix)) {
return line.substring(prefix.length);
}
}
return 'unknown';
}
// Make File Executable
export function makeExecutable(path) {
fs.chmodSync(path, 0o755);
}
// Get Scripts Directory
export function getScriptsDir() {
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
return path.join(__dirname, '..');
}