From an independent review of the branch:
* Makefile.in: `tcltk` is in both INSTALL_CAD_DIRS and PROGRAMS (Tcl build),
so install@tcltk / install-tcl@tcltk were defined twice -> "given more than
once" warnings on every command. Wrap both install lists in $(sort ...) to
dedup (as CLEAN_TARGETS already does). Also fix a stale comment (module@ now
waits for ${DATABASE_H}, not a `depend` phase).
* toolchains/emscripten/defs.mak: the scmos display-file embed globbed
`mos.*.dstyle`, which misses mos.7bit.mraster_dstyle (an underscore, not a
dot) -- so the mono-raster style was not embedded in WASM, and the comment
wrongly called that file non-existent. Glob `mos.*dstyle` to cover both.
* npm/build.sh: sed_strip_cr wrote the file back unconditionally, bumping the
mtimes of configure and every scripts/ file on each WASM build (contradicting
the "source never mutated" guarantee and able to force a coexisting native
rebuild). Only write back when a CR was actually stripped.
* graphics/Makefile.in: remove the dead DEPSRCS block left behind by retiring
the Depend machinery (it also referenced an undefined ${THREE_D_SRCS}).
* scripts/defs.mak.in: clarify that only the SOURCE_DATE_EPOCH branch is UTC.
Verified: 0 duplicate-target warnings, wildcard now lists mos.7bit.mraster_dstyle,
full Tcl build+install rc=0 (375 files), graphics lib builds, build.sh syntax OK.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
npm/build.sh built in-tree: it cd'd into the source root, ran
`./configure` there, appended the WASM defs.mak to the source-tree
defs.mak, and copied magic.js/.wasm out of the source magic/ dir.
Run each variant in a dedicated out-of-source build dir instead
(build-wasm-<variant>, overridable via WASM_BUILD_DIR):
* configure is invoked as "$REPO_ROOT/configure" from $build_dir, so
config.status and all generated files land under $build_dir; the
source tree is only read (VPATH).
* the WASM defs.mak is appended to $build_dir/defs.mak.
* artifacts are copied from $build_dir/magic/.
* a fresh `rm -rf $build_dir` per run replaces the old in-tree
`make distclean` (which also removes the need to touch the source
tree, and sidesteps the tracked-rules.mak distclean hazard entirely).
CRLF stripping now targets the source-tree configure inputs explicitly.
Note: build-wasm-<variant> dirs are not gitignored (left per task scope);
they are disposable and recreated each run.
(Static edit; not runtime-verified — emscripten is not available here.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously it was an archive of an archive (of the 'npm pack' output)
published under the same artifict filename (which becomes the default
download filenmame) which is a headache when you start to download more
than one (like when testing between versions).
Now the 'npm pack' output is attached as-is using its original filename,
but also the extracted contents are attached as standard GitHub
artifact ZIP, using a unique filename (based on the unique build version).
The example/suite runners discarded e.stack via console.error(e.message ?? e),
hiding the wasm-function offsets that emsymbolizer needs to map an abort back
to C source. A failing test only printed a terse message like "memory access
out of bounds" with no trace.
- Add reportError() to helpers.js/helpers-tcl.js; print the full stack
(falling back to the message).
- Wrap command execution in runScript() to name the command that aborted
before the error propagates.
- Use reportError() in all standalone runners and in all.js/all-tcl.js
(full stack to stderr, one-line PASS/FAIL summary kept; tests still run
independently).
- build.sh: run the --test step in a subshell so its cd does not leak into
the --pack step.
Replace the last three intubun/tcl mentions with tcltk/tcl in
npm/tcl.js, toolchains/emscripten/build-tcl-wasm.sh, and npm/tcl.ref.
Also remove the stale comment in tcl.ref that referenced a non-existent
update-tcl GitHub Actions workflow.
Rename *-magic.tcl scripts to *-tcl.tcl to match the -tcl.js test naming
convention. Delete the old bare-command pcell.tcl (used cellname create,
no magic:: prefix) and promote pcell-magic.tcl to pcell.tcl.
Fix misleading comment in magicWasm.c: Tclmagic_Init only bootstraps the
interpreter; magic:: commands are registered separately by
TclmagicRegisterCommands after magicMainInit. Align comment block
dashes in TclmagicRegisterCommands to match tclmagic.c style (62 dashes).
Replace intubun/tcl references in build scripts and CI with tcltk/tcl to
match the actual pinned repo in npm/tcl.ref. Also run both test suites
when build.sh is invoked with --test.
All non-TCL tests (extract, gds, drc, cif) now also run against the TCL
variant using magic::-prefixed Tcl scripts. A new PCell test generates
two parameterized rectangle cells and verifies their GDS output.
The CI workflow runs npm run test:tcl after the TCL build and saves the
generated output files as an artifact.
Bump VERSION to 8.3.645.
magic.wasm can now be built as two variants packaged in the same npm
release: notcl/ (legacy, magic's own parser) and tcl/ (intubun/tcl 9.x
statically linked, commands evaluated by Tcl_EvalEx). The TCL fork is
pinned via npm/tcl.ref and cloned/built by magic itself — the tcl/
checkout is treated as read-only and built out-of-source into
magic/build-tcl-wasm/.
Configure layer:
- New usingTk variable decoupled from usingTcl in scripts/configure.in
+ scripts/configure, so --with-tcl --without-tk is finally a valid
combination. Native Linux Tcl+Tk builds keep their previous behaviour
(both flags default to enabled).
- When usingTk is empty, configure passes -DMAGIC_NO_TK so the small
number of remaining Tk callsites in tcltk/tclmagic.{h,c} compile out,
and TKCOMMON_SRCS / USE_TK_STUBS are omitted from the link.
WASM build orchestration:
- toolchains/emscripten/build-tcl-wasm.sh builds libtcl9.x.a + libtclstub.a
+ tclConfig.sh out-of-source from a pristine intubun/tcl checkout.
- npm/build.sh grew a --variant=<tcl|notcl|both> flag and writes its
outputs into npm/tcl/ and npm/notcl/. It also clones intubun/tcl with
autocrlf=false at the SHA pinned by npm/tcl.ref.
- magic/Makefile (WASM block only): magicWasm.o is now compiled with
DFLAGS_NOSTUB so Tcl_CreateInterp resolves to libtcl9.x directly
before tclStubsPtr is set. magic.js link pulls in LIB_SPECS_NOSTUB
and -ltclstub. After rules.mak include, magic: is a phony alias for
magic.js so the generic ${MODULE} recipe doesn't fight it.
- toolchains/emscripten/defs.mak: add -sUSE_ZLIB=1 (libtcl9 references
zlib), replace -sSTACK_SIZE=N with -Wl,-z,stack-size=N (emcc >=5
rejects the setting form).
- magic/magicWasm.c bootstraps the embedded interp under MAGIC_WRAPPER
(Tcl_CreateInterp -> Tcl_Init -> Tclmagic_Init) and routes
run_command through Tcl_EvalEx.
- magic/magicTop.c: gate MagicVersion/Revision/CompileTime on
!MAGIC_WRAPPER so they don't collide with the copies in
tcltk/tclmagic.c when both objects land in the same wasm binary.
npm package:
- Subpath exports: ".", "./tcl", "./notcl". Default import keeps the
pre-existing non-TCL behaviour for backward compatibility.
- examples/smoke-tcl.mjs exercises the TCL variant.
CI:
- main-wasm.yml clones intubun/tcl at the pinned ref, builds both
variants via npm/build.sh --variant=both, runs the existing notcl
test suite and the new TCL smoke test, and publishes only on a
v<x.y.z>... git tag. Tag name (minus the leading v) becomes the
npm version.
Mirrors the AppImage versioning form (8.3.637~20260414~d157eea) as
closely as semver allows: 8.3.637-20260414.d157eea.
- package.json: placeholder 0.0.0-dev; CI always overwrites before pack
- npm-publish.yml: version step now runs unconditionally (not just on
tags), reading VERSION + git date + git hash — dry-run artifacts are
stamped too, making them unambiguously traceable to their source commit
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.