ruffle/web/packages/core/tools/build_wasm.js

147 lines
4.4 KiB
JavaScript

const { execFileSync } = require("child_process");
const { copyFileSync, mkdirSync, rmSync } = require("fs");
const process = require("process");
function runWasmOpt({ path, flags }) {
let args = ["-o", path, "-O", "-g", path];
if (flags) {
args = args.concat(flags);
}
execFileSync("wasm-opt", args, {
stdio: "inherit",
});
}
function runWasmBindgen({ path, outName, flags, dir }) {
let args = [
path,
"--target",
"web",
"--out-dir",
dir,
"--out-name",
outName,
];
if (flags) {
args = args.concat(flags);
}
execFileSync("wasm-bindgen", args, {
stdio: "inherit",
});
}
function cargoBuild({ profile, features, rustFlags }) {
let args = ["build", "--locked", "--target", "wasm32-unknown-unknown"];
if (profile) {
args.push("--profile", profile);
}
if (process.env["CARGO_FEATURES"]) {
features = (features || []).concat(
process.env["CARGO_FEATURES"].split(","),
);
}
if (features) {
args.push("--features", features.join(","));
}
let totalRustFlags = process.env["RUSTFLAGS"] || "";
if (rustFlags) {
if (totalRustFlags) {
totalRustFlags += ` ${rustFlags.join(" ")}`;
} else {
totalRustFlags = rustFlags.join(" ");
}
}
if (process.env["CARGO_FLAGS"]) {
args = args.concat(process.env["CARGO_FLAGS"].split(" "));
}
execFileSync("cargo", args, {
env: Object.assign(Object.assign({}, process.env), {
RUSTFLAGS: totalRustFlags,
}),
stdio: "inherit",
});
}
function buildWasm(profile, filename, optimise, extensions, wasmSource) {
const rustFlags = ["-Aunknown_lints"];
const wasmBindgenFlags = [];
const wasmOptFlags = [];
const flavor = extensions ? "extensions" : "vanilla";
if (extensions) {
rustFlags.push(
"-C",
"target-feature=+bulk-memory,+simd128,+nontrapping-fptoint,+sign-ext,+reference-types",
);
wasmBindgenFlags.push("--reference-types");
wasmOptFlags.push("--enable-reference-types");
}
let originalWasmPath;
if (wasmSource === "cargo" || wasmSource === "cargo_and_store") {
console.log(`Building ${flavor} with cargo...`);
cargoBuild({
profile,
rustFlags,
});
originalWasmPath = `../../../target/wasm32-unknown-unknown/${profile}/ruffle_web.wasm`;
if (wasmSource === "cargo_and_store") {
copyFileSync(originalWasmPath, `../../dist/${filename}.wasm`);
}
} else if (wasmSource === "existing") {
originalWasmPath = `../../dist/${filename}.wasm`;
} else {
throw new Error(
"Invalid wasm source: must be one of 'cargo', 'cargo_and_store' or 'existing'",
);
}
console.log(`Running wasm-bindgen on ${flavor}...`);
runWasmBindgen({
path: originalWasmPath,
outName: filename,
dir: "dist",
flags: wasmBindgenFlags,
});
if (optimise) {
console.log(`Running wasm-opt on ${flavor}...`);
runWasmOpt({
path: `dist/${filename}_bg.wasm`,
flags: wasmOptFlags,
});
}
}
function copyStandIn(from, to) {
const suffixes = [`_bg.wasm`, `_bg.wasm.d.ts`, `.js`, `.d.ts`];
console.log(`Copying ${from} as a stand-in for ${to}...`);
for (const suffix of suffixes) {
copyFileSync(`dist/${from}${suffix}`, `dist/${to}${suffix}`);
}
}
function detectWasmOpt() {
try {
execFileSync("wasm-opt", ["--version"]);
return true;
} catch (_a) {
return false;
}
}
const buildExtensions = !!process.env["ENABLE_WASM_EXTENSIONS"];
const wasmSource = process.env["WASM_SOURCE"] || "cargo";
const hasWasmOpt = detectWasmOpt();
if (!hasWasmOpt) {
console.log(
"NOTE: Since wasm-opt could not be found (or it failed), the resulting module might not perform that well, but it should still work.",
);
}
if (wasmSource === "cargo_and_store") {
rmSync("../../dist", { recursive: true, force: true });
mkdirSync("../../dist");
}
buildWasm("web-vanilla-wasm", "ruffle_web", hasWasmOpt, false, wasmSource);
if (buildExtensions) {
buildWasm(
"web-wasm-extensions",
"ruffle_web-wasm_extensions",
hasWasmOpt,
true,
wasmSource,
);
} else {
copyStandIn("ruffle_web", "ruffle_web-wasm_extensions");
}