fixup caveats + add miniserver

This commit is contained in:
lizzie 2026-06-09 21:21:22 +00:00
parent 47822d1606
commit 46433279af
5 changed files with 109 additions and 4 deletions

View file

@ -252,7 +252,9 @@ When CMake invokes certain file syscalls - it may sometimes cause crashes or cor
WebAssembly or "WASM" for short is a *mainly 32-bit* virtual "architecture" which we only bootstrap on 64-bit only. This means not only the program runs 2x slower than it would due to using JS BigInt, it also means we need to go out of our way to enable proper 64-bit support via `-sMEMORY64=1`, however once again, some Emscripten quirks force us to specify `-s MEMORY64` and `-sMEMORY64=1` at the same time: see the [CI build script](../.ci/wasm/build.sh).
The WebAssembly target is very heavy on resources and requires at least 4 times the normal amount of resources that a native build would. Additionally, the only supported environment is `node.js` and `wasmtime`, with browser support being an afterthought (PRs welcome!).
The WebAssembly target is very heavy on resources and requires at least 4 times the normal amount of resources that a native build would. Additionally, the only supported environment is Firefox at the moment, node.js and `wasmtime are not supported (PRs welcome!)
If running under Firefox and you hit "out of memory" on dev console, close the entire tab, then open it back again, see [this issue](https://github.com/emscripten-core/emscripten/issues/8126).
To run the binary (after building) you should be fine with `node ./eden-cli.js`. For obvious reasons no Qt frontend is available on WASM, support for Vulkan is done charily via [llvmpipe2wasm](https://github.com/Devsh-Graphics-Programming/llvmpipe2wasm).

View file

@ -332,9 +332,9 @@ else()
if (NOT MAKE_FOUND)
find_program(MAKE gmake)
endif()
if (MAKE_FOUND)
if (MAKE_FOUND AND SYSTEM_THREADS GREATER 1)
# This version of make (GNU's make) supports subprocess threading jobs
set(FFmpeg_MAKE_ARGS -j${SYSTEM_THREADS})
set(FFmpeg_MAKE_ARGS -j ${SYSTEM_THREADS})
else()
# No GNU make implies that this system may be highly non-GNU
find_program(MAKE make required)

View file

@ -79,8 +79,10 @@ endif()
if (PLATFORM_EMSCRIPTEN)
# 10GB is required... yikes!
target_link_options(yuzu-cmd PRIVATE
-sINITIAL_MEMORY=10737418240
-sALLOW_MEMORY_GROWTH=1
-sMAXIMUM_MEMORY=10737418240
-sGLOBAL_BASE=16777216
-sEXPORTED_RUNTIME_METHODS="['FS']"
-sPTHREAD_POOL_SIZE_STRICT=0
-sPTHREAD_POOL_SIZE=navigator.hardwareConcurrency)
endif()

View file

@ -30,6 +30,7 @@ Tools for Eden and other subprojects. When adding new scripts please use `#!/bin
- `find-unused-strings.sh`: Find any unused strings in the Android app (XML -> Kotlin).
- `cpp-lint.sh`: Homemade dumb C++ linter.
- `fuzzsettings.cpp`: Fuzz settings files.
- `miniserver.js`: Make a quick server that serves a page with the WASM on it, takes a single argument which is the path to the build directory containing *both* `eden-cli.js` and `eden-cli.wasm`. Run via `node.js`, `wasmtime` isn't supported.
## Android
It's recommended to run these scritps after almost any Android change, as they are relatively fast and important both for APK bloat and CI.

100
tools/miniserver.js Normal file
View file

@ -0,0 +1,100 @@
#!/usr/local/env node
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
import { createServer } from 'http';
import { readFile } from 'fs';
import { join } from 'path';
// DO NOT RUN THIS IN ANY PRODUCTION ENVIRONMENT EVER
const server = createServer((req, res) => {
console.log(`reuqest? ${req.url}`);
if (req.url === '/') {
// https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Loading_and_running
// If your browser doesn't support fetch... HAHA GET FUCKED
res.writeHead(200, {
'Content-Type': 'text/html',
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
});
res.end(`<!DOCTYPE html>
<html>
<head>
<title>eden-cli</title>
<script>
var Module = {}; // MUST be global otherwise wasm does wawawawa
function finished_body() {
Module = { //do not prepend var
print: (e) => {
e = e.replace('[1;31m', '<span style="color:red;font-weight:bold;">');
e = e.replace('[0;37m', '<span style="color:white;font-weight:bold;">');
e = e.replace('[1;35m', '<span style="color:pink;font-weight:bold;">');
e = e.replace('[1;33m', '<span style="color:yellow;font-weight:bold;">');
e = e.replace('[0m', '</span>');
tty_stdout.innerHTML += e + '</br>';
},
printErr: (e) => {
tty_stdout.innerHTML += '<span style="color:red">' + e + '</span></br>';
},
// not a wasm func but idc
printInternal: (e) => {
tty_stdout.innerHTML += '<span style="color:pink">Internal WASM: ' + e + '</span></br>';
},
onRuntimeInitialized: () => { Module.printInternal("runtime ok"); },
setStatus: (e) => { Module.printInternal(e); },
monitorRunDependencies: (e) => { Module.printInternal("monitor deps: " + e); },
__wasm_call_ctors: () => { Module.printInternal("ctors beep"); },
};
var tty_stdout = document.createElement('div');
document.body.appendChild(tty_stdout);
Module.printInternal("loading from ${build_dir}/eden-cli.js");
Module.arguments = ['game.nro'];
var script = document.createElement('script');
script.src = '/eden-cli.js';
script.onload = () => {
Module.printInternal("Atomics: " + window.Atomics);
Module.printInternal("SharedArrayBuffer: " + window.SharedArrayBuffer);
Module.printInternal("trying to load script (if it hangs here check console)");
Module.FS.writeFile('/game.nro', [1,2,3]);
};
document.head.appendChild(script);
}
</script>
</head>
<body style="margin:0;padding:0;background-color:black;font-family:Monospace,Tahoma,Arial;" onload="finished_body();">
</body>
</html>`);
} else if (req.url === '/eden-cli.js') {
readFile(join(build_dir, 'eden-cli.js'), (err, content) => {
res.writeHead(200, {
'Content-Type': 'application/javascript',
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
});
res.end(content, 'utf-8');
});
} else if (req.url === '/eden-cli.wasm') {
readFile(join(build_dir, 'eden-cli.wasm'), (err, content) => {
res.writeHead(200, {
'Content-Type': 'application/wasm',
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
});
res.end(content, 'utf-8');
});
}
});
const build_dir = process.argv[2];
if (build_dir === undefined) {
console.log(`Usage: ${process.argv[0]} ${process.argv[1]} [build directory]`);
} else {
server.listen(2210, () => {
console.log(`${process.argv[0]} ${process.argv[1]} http://localhost:2210`);
console.log(`build dir = ${build_dir}`);
});
}