116 lines
4.5 KiB
JavaScript
116 lines
4.5 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const root = path.resolve(__dirname, "..");
|
|
|
|
function fail(message, error) {
|
|
console.error(`[verify] ${message}`);
|
|
if (error) {
|
|
console.error(`[verify] ${error instanceof Error ? error.message : String(error)}`);
|
|
}
|
|
if (process.platform === "win32") {
|
|
console.error("[verify] Retry with windows\\install.bat.");
|
|
console.error("[verify] Native fallback: run C:\\Program Files\\nodejs\\install_tools.bat as Administrator.");
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
function warn(message) {
|
|
console.warn(`[verify] WARNING: ${message}`);
|
|
}
|
|
|
|
function compareVersions(left, right) {
|
|
const leftParts = String(left || "").split(".").map((part) => Number(part) || 0);
|
|
const rightParts = String(right || "").split(".").map((part) => Number(part) || 0);
|
|
const length = Math.max(leftParts.length, rightParts.length);
|
|
for (let index = 0; index < length; index += 1) {
|
|
const difference = (leftParts[index] || 0) - (rightParts[index] || 0);
|
|
if (difference !== 0) return difference;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
try {
|
|
require("express");
|
|
} catch (error) {
|
|
fail("Express could not be loaded.", error);
|
|
}
|
|
|
|
try {
|
|
const Database = require("better-sqlite3");
|
|
const db = new Database(":memory:");
|
|
const row = db.prepare("SELECT 1 AS ok").get();
|
|
db.close();
|
|
if (row?.ok !== 1) {
|
|
fail("SQLite verification query returned an unexpected result.");
|
|
}
|
|
} catch (error) {
|
|
fail("better-sqlite3 could not be loaded or initialized.", error);
|
|
}
|
|
|
|
for (const directory of ["data", "logs"]) {
|
|
fs.mkdirSync(path.join(root, directory), { recursive: true });
|
|
}
|
|
|
|
if (process.platform === "win32") {
|
|
const ammcDir = path.join(root, "AMMC", "windows64");
|
|
const requiredFiles = ["ammc-amb.exe", "ammc.dll", "MyLapsSDK.dll"];
|
|
const missingFiles = requiredFiles.filter((file) => !fs.existsSync(path.join(ammcDir, file)));
|
|
if (missingFiles.length > 0) {
|
|
fail(`Bundled AMMC runtime is incomplete: ${missingFiles.join(", ")}`);
|
|
}
|
|
console.log(`[verify] AMMC Windows runtime: ${ammcDir}`);
|
|
}
|
|
|
|
function verifyUnixAmmcExecutables(directory, executableNames, runtimeLabel) {
|
|
const missingFiles = [];
|
|
const nonExecutableFiles = [];
|
|
|
|
for (const executableName of executableNames) {
|
|
const executablePath = path.join(directory, executableName);
|
|
if (!fs.existsSync(executablePath)) {
|
|
missingFiles.push(executableName);
|
|
continue;
|
|
}
|
|
try {
|
|
fs.accessSync(executablePath, fs.constants.X_OK);
|
|
} catch {
|
|
nonExecutableFiles.push(executableName);
|
|
}
|
|
}
|
|
|
|
if (missingFiles.length > 0) {
|
|
warn(`Bundled ${runtimeLabel} tools are missing: ${missingFiles.join(", ")}`);
|
|
}
|
|
if (nonExecutableFiles.length > 0) {
|
|
warn(`Bundled ${runtimeLabel} tools are not executable: ${nonExecutableFiles.join(", ")}. Run: chmod +x ${path.relative(root, directory)}/ammc-*`);
|
|
}
|
|
return missingFiles.length === 0 && nonExecutableFiles.length === 0;
|
|
}
|
|
|
|
if (process.platform === "linux" && process.arch === "x64") {
|
|
const ammcDir = path.join(root, "AMMC", "linux_x86-64");
|
|
const executableNames = ["ammc-amb", "ammc-prochip", "ammc-sim", "ammc-vostok", "ammc-x2"];
|
|
const requiredGlibc = "2.39";
|
|
const runtimeReady = verifyUnixAmmcExecutables(ammcDir, executableNames, "Linux AMMC");
|
|
const glibcVersion = process.report?.getReport?.().header?.glibcVersionRuntime || "";
|
|
if (!glibcVersion) {
|
|
warn(`Could not detect the host GLIBC version. The bundled Linux AMMC tools require GLIBC ${requiredGlibc} or newer.`);
|
|
} else if (compareVersions(glibcVersion, requiredGlibc) < 0) {
|
|
warn(`Host GLIBC ${glibcVersion} is too old for the bundled Linux AMMC tools (requires >= ${requiredGlibc}). RC RaceCore can still run, but use a compatible AMMC build or a newer Linux distribution. Do not replace the system GLIBC manually.`);
|
|
} else if (runtimeReady) {
|
|
console.log(`[verify] AMMC Linux runtime: ${ammcDir} (all tools executable; GLIBC ${glibcVersion}, requires >= ${requiredGlibc})`);
|
|
}
|
|
}
|
|
|
|
if (process.platform === "darwin" && process.arch === "arm64") {
|
|
const ammcDir = path.join(root, "AMMC", "apple_m");
|
|
const executableNames = ["ammc-amb", "ammc-prochip", "ammc-sim", "ammc-vostok"];
|
|
if (verifyUnixAmmcExecutables(ammcDir, executableNames, "Apple Silicon AMMC")) {
|
|
console.log(`[verify] AMMC Apple Silicon runtime: ${ammcDir} (all tools executable)`);
|
|
}
|
|
}
|
|
|
|
console.log(`[verify] Express and SQLite: OK (${process.platform}/${process.arch}, Node ${process.version})`);
|
|
console.log(`[verify] Installation is ready. Start with: ${process.platform === "win32" ? "npm.cmd start" : "npm start"}`);
|