Skip to content

Instantly share code, notes, and snippets.

@jaames
Created March 7, 2026 19:50
Show Gist options
  • Select an option

  • Save jaames/b5189434870e1c6d5193a100e3ca248b to your computer and use it in GitHub Desktop.

Select an option

Save jaames/b5189434870e1c6d5193a100e3ca248b to your computer and use it in GitHub Desktop.
WOWCUBE custom build script (sorry it's Typescript)
import { dirname, relative, resolve } from 'path';
import { fileURLToPath } from 'url';
import { execSync, spawnSync } from 'child_process';
import { $, cd, within } from 'zx';
import { homedir } from 'os';
// import Watcher from 'watcher';
import {
escapePath,
listFilesWithExtensions,
makeDirIfNeeded,
toArrayString
} from './utils.mts';
const __dirname = dirname(fileURLToPath(import.meta.url));
const ARGS = process.argv.slice(2);
// Run app in emulator after building
const FLAG_RUN = ARGS.includes('--run');
const PROJECT_DIR = resolve(__dirname, '../Cubemaker');
const SOURCE_FILE_EXTS = ['.c', '.cc', '.cpp'];
const SOURCE_DIR = resolve(PROJECT_DIR, 'src');
const SOURCE_FILES = await listFilesWithExtensions(SOURCE_DIR, SOURCE_FILE_EXTS);
const SOURCE_PATHS = SOURCE_FILES.map(file => resolve(SOURCE_DIR, file));
const SOURCE_MANIFEST = resolve(PROJECT_DIR, `wowcubeapp-build.json`);
const WOWCUBE_SDK_BASE_PATH = resolve(homedir(), `Documents/WowCube/WOWCube Development Kit.app/Contents/sdk`);
const WOWCUBE_SDK_VERSION_MAJOR = 6;
const WOWCUBE_SDK_VERSION_MINOR = 3;
const WOWCUBE_SDK_VERSION = `${WOWCUBE_SDK_VERSION_MAJOR}.${WOWCUBE_SDK_VERSION_MINOR}`;
const WOWCUBE_SDK_TOOLS_PATH = resolve(homedir(), `WOWCube Development Kit/Tools/cpp/bin`);
const WOWCUBE_SDK_COMPILER_PATH = resolve(WOWCUBE_SDK_TOOLS_PATH, 'wasm32-wasip1-clang++');
const WOWCUBE_SDK_BUILD_PATH = resolve(WOWCUBE_SDK_BASE_PATH, 'tools/wowcube-build');
const WOWCUBE_SDK_EMULATOR_PATH = resolve(WOWCUBE_SDK_BASE_PATH, '../MacOS/WOWCube Emulator');
const WOWCUBE_SDK_PATH = resolve(WOWCUBE_SDK_BASE_PATH, `${WOWCUBE_SDK_VERSION}`);
const WOWCUBE_SDK_CPP_PATH = resolve(WOWCUBE_SDK_PATH, 'cpp');
const WOWCUBE_SDK_SRC_PATHS = [
resolve(WOWCUBE_SDK_CPP_PATH, 'AppManager.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'native.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Screen.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Scene.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'NetworkMessage.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Sound.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/Background.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/OffscreenRenderTarget.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/Sprite.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/Text.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/AnimatedSprite.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'SaveMessage.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Scramble.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/QRCode.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Splashscreen.cpp'),
resolve(WOWCUBE_SDK_CPP_PATH, 'Gfx/SpriteAtlas.cpp'),
].map(file => escapePath(file));
const BUILD_WASM = resolve(PROJECT_DIR, 'binary/Cubemaker.wasm');
const BUILD_CUBFILE = resolve(PROJECT_DIR, 'binary/Cubemaker.cub');
await makeDirIfNeeded(resolve(PROJECT_DIR, 'binary'));
// Compile with clang
const compileCpp = () => {
console.log('compiling wasm...');
spawnSync(`${escapePath(WOWCUBE_SDK_COMPILER_PATH)} ` + [
// List source files first
SOURCE_PATHS.join(' '),
WOWCUBE_SDK_SRC_PATHS.join(' '),
// Compiler flags
`-std=c++17`,
`-Oz`,
`-flto`,
`-fno-exceptions`,
`-mexec-model=reactor`,
`-z stack-size=10240`,
`-Wl",--initial-memory=65536,--export=run,--export=on_init,--strip-all,--lto-O3"`,
`-DABI_VERSION_MAJOR=${WOWCUBE_SDK_VERSION_MAJOR}`,
`-DABI_VERSION_MINOR=${WOWCUBE_SDK_VERSION_MINOR}`,
`-I${escapePath(WOWCUBE_SDK_CPP_PATH)}`,
// Output WASM
`-o ${BUILD_WASM}`,
].filter(Boolean).join(' '), {
stdio: 'inherit',
shell: true,
});
};
const build = () => {
console.log('building cubfile...');
spawnSync(`${escapePath(WOWCUBE_SDK_BUILD_PATH)} ` + [
SOURCE_MANIFEST,
BUILD_CUBFILE
].filter(Boolean).join(' '), {
stdio: 'inherit',
shell: true,
});
};
const runInEmulator = () => {
console.log('running in emulator...');
spawnSync(`${escapePath(WOWCUBE_SDK_EMULATOR_PATH)} ` + [
SOURCE_MANIFEST,
`--project-run "${BUILD_CUBFILE}"`,
`--run`
].filter(Boolean).join(' '), {
stdio: 'inherit',
shell: true,
});
};
// TODO
// https://github.com/wowcube/WOWCubeSDK_VSCodeExtension/blob/b64775c3cafab2503115afd278eb834c684faeb5/src/WOWCubeBuildTaskProvider.ts#L1562
compileCpp();
build();
if (FLAG_RUN)
runInEmulator();
// if (FLAG_WATCH) {
// console.log(FMT_GREEN, 'Watching for changes...');
// const watcher = new Watcher(SOURCE_DIR, { recursive: true });
// watcher.on('change', async (file) => {
// console.log(FMT_BLUE, `File ${ relative(SOURCE_DIR, file) } changed, recompiling...`);
// compile();
// });
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment