magic/npm/examples/helpers.js

73 lines
2.6 KiB
JavaScript
Raw Normal View History

Add npm package and CI workflows The user-facing layer of the WASM port: a publishable npm package plus the GitHub Actions that build and ship it. * npm/package.json — publishes as `magic-vlsi-wasm`, ESM-only, HPND licensed, version tracks Magic's own VERSION file (8.3.637). Whitelists the published files and exposes index.js + index.d.ts. * npm/index.js, npm/index.d.ts — thin JS/TS wrapper around the four WASM exports. createMagic(opts) returns { init, runCommand, sourceFile, update, FS } so consumers can write into the Emscripten virtual filesystem and dispatch Magic commands from Node.js, browsers or Web Workers. * npm/build.sh — end-to-end build: locates emsdk (via PATH or EMSDK_DIR), runs distclean+configure+make in the right order (techs before mains so embed-files are present), copies magic.js / magic.wasm into npm/. Optional --release, --test, --pack flags. Preserves configure's exec bits across invocations. * npm/pack.sh — produces a reproducible npm tarball by touching every file to the build time and exporting SOURCE_DATE_EPOCH so pacote does not rewrite mtimes to its 1985 fallback. * npm/examples/ — runnable smoke tests for the four common workflows (extract, gds, drc, cif), driven by examples/all.js. Each example is self-contained and uses the bundled siliwiz technology. helpers.js encapsulates the boilerplate. * npm/LICENSE, npm/README.md — license text and consumer-facing docs (install, quick-start, API, examples, build-from-source, license, third-party content notice). * .github/workflows/main.yml — adds a `simple_build_wasm` job that installs a pinned emsdk (3.1.56), builds the WASM module, runs the example test suite and uploads the npm tarball as an artifact. Pinned for reproducibility against the post-build.sh patches; switchable to "latest" by commenting two lines. * .github/workflows/main-aarch64.yml — drops the now-redundant WASM ARM job. WASM is architecture-independent. * .github/workflows/npm-publish.yml — new workflow. Publishes to npm on `v*` tag pushes (manual `workflow_dispatch` supported as a dry-run). Uses the same pinned emsdk and pack.sh. Also sets FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 in both workflows to silence the Node.js 20 deprecation warnings until actions/upload-artifact@v6 ships a Node-24 release.
2026-05-04 13:32:51 +02:00
// Shared utilities for Magic WASM examples.
import createMagicModule from '../magic.js';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, resolve, basename } from 'node:path';
export const EXAMPLES_DIR = dirname(fileURLToPath(import.meta.url));
export const wasmBinary = readFileSync(resolve(EXAMPLES_DIR, '../magic.wasm'));
2026-05-06 19:16:55 +02:00
export const DEFAULT_TECH = 'scmos';
export const DEFAULT_MAG = resolve(EXAMPLES_DIR, 'min.mag');
Add npm package and CI workflows The user-facing layer of the WASM port: a publishable npm package plus the GitHub Actions that build and ship it. * npm/package.json — publishes as `magic-vlsi-wasm`, ESM-only, HPND licensed, version tracks Magic's own VERSION file (8.3.637). Whitelists the published files and exposes index.js + index.d.ts. * npm/index.js, npm/index.d.ts — thin JS/TS wrapper around the four WASM exports. createMagic(opts) returns { init, runCommand, sourceFile, update, FS } so consumers can write into the Emscripten virtual filesystem and dispatch Magic commands from Node.js, browsers or Web Workers. * npm/build.sh — end-to-end build: locates emsdk (via PATH or EMSDK_DIR), runs distclean+configure+make in the right order (techs before mains so embed-files are present), copies magic.js / magic.wasm into npm/. Optional --release, --test, --pack flags. Preserves configure's exec bits across invocations. * npm/pack.sh — produces a reproducible npm tarball by touching every file to the build time and exporting SOURCE_DATE_EPOCH so pacote does not rewrite mtimes to its 1985 fallback. * npm/examples/ — runnable smoke tests for the four common workflows (extract, gds, drc, cif), driven by examples/all.js. Each example is self-contained and uses the bundled siliwiz technology. helpers.js encapsulates the boilerplate. * npm/LICENSE, npm/README.md — license text and consumer-facing docs (install, quick-start, API, examples, build-from-source, license, third-party content notice). * .github/workflows/main.yml — adds a `simple_build_wasm` job that installs a pinned emsdk (3.1.56), builds the WASM module, runs the example test suite and uploads the npm tarball as an artifact. Pinned for reproducibility against the post-build.sh patches; switchable to "latest" by commenting two lines. * .github/workflows/main-aarch64.yml — drops the now-redundant WASM ARM job. WASM is architecture-independent. * .github/workflows/npm-publish.yml — new workflow. Publishes to npm on `v*` tag pushes (manual `workflow_dispatch` supported as a dry-run). Uses the same pinned emsdk and pack.sh. Also sets FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 in both workflows to silence the Node.js 20 deprecation warnings until actions/upload-artifact@v6 ships a Node-24 release.
2026-05-04 13:32:51 +02:00
export const DEFAULT_OUT = resolve(EXAMPLES_DIR, 'output');
export { basename };
export function vfsWrite(FS, vfsPath, source) {
const dir = vfsPath.substring(0, vfsPath.lastIndexOf('/'));
if (dir) FS.mkdirTree(dir);
FS.writeFile(vfsPath, typeof source === 'string' ? readFileSync(source) : source);
}
export function vfsRead(FS, vfsPath) {
try { return Buffer.from(FS.readFile(vfsPath)); } catch { return null; }
}
export class MagicWasm {
constructor(mod) {
this._init = mod.cwrap('magic_wasm_init', 'number', []);
this._run = mod.cwrap('magic_wasm_run_command', 'number', ['string']);
this.FS = mod.FS;
}
init() {
const rc = this._init();
if (rc !== 0) throw new Error(`magic_wasm_init failed with code ${rc}`);
}
runScript(text) {
for (const line of text.split('\n')) {
const l = line.trim();
if (l && !l.startsWith('#')) this._run(l);
}
}
}
// Creates a fresh Magic WASM instance and calls init().
// onPrint / onPrintErr default to console.log/error with a [magic] prefix.
// All output lines are also collected into the returned `lines` array.
export async function createMagic({ onPrint, onPrintErr } = {}) {
const lines = [];
const mod = await createMagicModule({
wasmBinary,
print: onPrint ?? (msg => { lines.push(msg); console.log('[magic]', msg); }),
printErr: onPrintErr ?? (msg => { lines.push(msg); console.error('[magic]', msg); }),
});
const magic = new MagicWasm(mod);
magic.init();
return { magic, lines };
}
2026-05-06 19:16:55 +02:00
// Loads a layout into the VFS. `tech` is the name of a technology that is
// either built into the WASM binary (e.g. 'scmos', 'minimum', 'nmos') or has
// already been written to /magic/sys/current/<tech>.tech by the caller.
export function loadCell(FS, tech, magFile) {
const cell = basename(magFile, '.mag');
vfsWrite(FS, `/work/${cell}.mag`, magFile);
Add npm package and CI workflows The user-facing layer of the WASM port: a publishable npm package plus the GitHub Actions that build and ship it. * npm/package.json — publishes as `magic-vlsi-wasm`, ESM-only, HPND licensed, version tracks Magic's own VERSION file (8.3.637). Whitelists the published files and exposes index.js + index.d.ts. * npm/index.js, npm/index.d.ts — thin JS/TS wrapper around the four WASM exports. createMagic(opts) returns { init, runCommand, sourceFile, update, FS } so consumers can write into the Emscripten virtual filesystem and dispatch Magic commands from Node.js, browsers or Web Workers. * npm/build.sh — end-to-end build: locates emsdk (via PATH or EMSDK_DIR), runs distclean+configure+make in the right order (techs before mains so embed-files are present), copies magic.js / magic.wasm into npm/. Optional --release, --test, --pack flags. Preserves configure's exec bits across invocations. * npm/pack.sh — produces a reproducible npm tarball by touching every file to the build time and exporting SOURCE_DATE_EPOCH so pacote does not rewrite mtimes to its 1985 fallback. * npm/examples/ — runnable smoke tests for the four common workflows (extract, gds, drc, cif), driven by examples/all.js. Each example is self-contained and uses the bundled siliwiz technology. helpers.js encapsulates the boilerplate. * npm/LICENSE, npm/README.md — license text and consumer-facing docs (install, quick-start, API, examples, build-from-source, license, third-party content notice). * .github/workflows/main.yml — adds a `simple_build_wasm` job that installs a pinned emsdk (3.1.56), builds the WASM module, runs the example test suite and uploads the npm tarball as an artifact. Pinned for reproducibility against the post-build.sh patches; switchable to "latest" by commenting two lines. * .github/workflows/main-aarch64.yml — drops the now-redundant WASM ARM job. WASM is architecture-independent. * .github/workflows/npm-publish.yml — new workflow. Publishes to npm on `v*` tag pushes (manual `workflow_dispatch` supported as a dry-run). Uses the same pinned emsdk and pack.sh. Also sets FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 in both workflows to silence the Node.js 20 deprecation warnings until actions/upload-artifact@v6 ships a Node-24 release.
2026-05-04 13:32:51 +02:00
return { tech, cell };
}
// Reads a TCL script from EXAMPLES_DIR, substitutes __TECH__ and __CELL__.
export function loadScript(name, tech, cell) {
return readFileSync(resolve(EXAMPLES_DIR, name), 'utf8')
.replaceAll('__TECH__', tech)
.replaceAll('__CELL__', cell);
}