mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-09-04 00:31:02 +02:00
Add TCL-embedded WASM build variant alongside the existing non-TCL build
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.
This commit is contained in:
committed by
R. Timothy Edwards
parent
8d61bae1f1
commit
e45db485d8
@@ -1,13 +1,16 @@
|
||||
name: CI-wasm
|
||||
|
||||
# Builds the Magic WebAssembly target on every push and pull request.
|
||||
# When the VERSION file changes on the default branch, the package is
|
||||
# additionally published to GitHub Packages (npm.pkg.github.com) as
|
||||
# @<owner>/magic-vlsi-wasm — no manual tag or token required.
|
||||
# Tim Edwards updates VERSION to trigger a new release; the scope resolves
|
||||
# automatically to the repo owner, so forks publish under their own namespace.
|
||||
# Builds the Magic WebAssembly target (both the non-TCL and TCL variants)
|
||||
# on every push and pull request as a CI check. **Publishing** only happens
|
||||
# when a release tag of the form v<x.y.z>... is pushed — that gate is the
|
||||
# manual release trigger:
|
||||
#
|
||||
# WASM is architecture-independent — built once on x86-64, usable everywhere.
|
||||
# # bump magic/VERSION and/or npm/tcl.ref, commit, push to default branch
|
||||
# git tag v8.3.638
|
||||
# git push origin v8.3.638
|
||||
#
|
||||
# The tag name (minus the leading "v") becomes the published npm version.
|
||||
# Forks publish under their own namespace via the @<owner>/ scope.
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -70,32 +73,32 @@ jobs:
|
||||
echo "===== emcc -dM -E - ====="; echo | emcc -dM -E - | sort
|
||||
echo "===== em++ -dM -E - ====="; echo | em++ -dM -E - | sort
|
||||
|
||||
- name: Build WASM
|
||||
# Clone intubun/tcl into a sibling directory at the pinned ref from
|
||||
# npm/tcl.ref. npm/build.sh would do this on its own, but doing it as
|
||||
# an explicit step makes the resolved SHA visible at the top of the
|
||||
# job log and keeps the build step's output focused on the C build.
|
||||
# The TCL source tree is treated as read-only — the actual WASM build
|
||||
# runs inside magic (toolchains/emscripten/build-tcl-wasm.sh).
|
||||
- name: Pin and clone intubun/tcl
|
||||
run: |
|
||||
. npm/tcl.ref
|
||||
: "${TCL_REPO_URL:=https://github.com/intubun/tcl.git}"
|
||||
: "${TCL_REF:=main}"
|
||||
echo "Pinned TCL: $TCL_REF ($TCL_REPO_URL)"
|
||||
# autocrlf=false: ubuntu-latest is already LF, but make it explicit.
|
||||
git -c core.autocrlf=false clone "$TCL_REPO_URL" ../tcl
|
||||
( cd ../tcl && git checkout --detach "$TCL_REF" )
|
||||
|
||||
- name: Build WASM — both variants (tcl + notcl)
|
||||
run: |
|
||||
source ./emsdk/emsdk_env.sh
|
||||
# --without/--disable flags: no WASM library available for these features
|
||||
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1" emconfigure ./configure \
|
||||
--without-cairo --without-opengl --without-x --without-tk --without-tcl \
|
||||
--disable-readline --disable-compression \
|
||||
--host=asmjs-unknown-emscripten \
|
||||
--target=asmjs-unknown-emscripten
|
||||
# Append WASM linker flags and activate the WASM link target
|
||||
cat toolchains/emscripten/defs.mak >> defs.mak
|
||||
# Echo the merged defs.mak so CI logs show the exact build config
|
||||
echo "===== defs.mak ====="; cat defs.mak; echo "===== defs.mak ====="
|
||||
# Build in order: techs must exist before mains (--embed-file embeds them)
|
||||
emmake make depend
|
||||
emmake make -j$(nproc) modules libs
|
||||
emmake make techs
|
||||
emmake make mains
|
||||
bash npm/build.sh --variant=both
|
||||
|
||||
- name: Copy WASM artifacts into npm/
|
||||
run: |
|
||||
cp magic/magic.js npm/
|
||||
cp magic/magic.wasm npm/
|
||||
- name: Run example tests (non-TCL variant)
|
||||
run: cd npm && npm test
|
||||
|
||||
- name: Run example tests
|
||||
run: cd npm && npm run test
|
||||
- name: Run smoke test (TCL variant)
|
||||
run: cd npm && npm run test:tcl
|
||||
|
||||
# Dump generated text outputs (.ext, .spice, .cif, …) into the CI log
|
||||
# so a regression in extraction / netlisting / cifoutput is visible
|
||||
@@ -112,21 +115,40 @@ jobs:
|
||||
esac
|
||||
done
|
||||
|
||||
- name: Set package version and scope
|
||||
# The release gate. We publish a new npm version only when a tag of the
|
||||
# shape v<x.y.z>... is pushed. The tag name (minus the leading "v") is
|
||||
# taken as the npm version verbatim — so `v8.3.638` → npm 8.3.638.
|
||||
- name: Determine release version (tag-driven only)
|
||||
id: release
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "push" ] && \
|
||||
echo "${{ github.ref }}" | grep -Eq '^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+'; then
|
||||
tag="${GITHUB_REF#refs/tags/}"
|
||||
echo "publish=true" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${tag#v}" >> "$GITHUB_OUTPUT"
|
||||
echo "Tag release: $tag → npm version ${tag#v}"
|
||||
else
|
||||
# For non-tag CI runs, use a dev-suffixed version so the packed
|
||||
# tarball is still consumable for local inspection / artifact upload.
|
||||
base=$(cat VERSION)
|
||||
date=$(git show -s --format=%cs | tr -d '-')
|
||||
hash=$(git show -s --format=%h)
|
||||
echo "publish=false" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${base}-${date}.${hash}" >> "$GITHUB_OUTPUT"
|
||||
echo "Non-tag build: will not publish."
|
||||
fi
|
||||
|
||||
- name: Set package version and scope
|
||||
env:
|
||||
VERSION: ${{ steps.release.outputs.version }}
|
||||
run: |
|
||||
base=$(cat VERSION) # e.g. 8.3.637
|
||||
date=$(git show -s --format=%cs | tr -d '-') # e.g. 20260414
|
||||
hash=$(git show -s --format=%h) # e.g. d157eea
|
||||
VERSION="${base}-${date}.${hash}"
|
||||
# Scope the package to the repo owner so it lands in the right
|
||||
# GitHub Packages namespace regardless of who hosts the repo.
|
||||
# e.g. @rtimothyedwards/magic-vlsi-wasm on Tim's repo,
|
||||
# @intubun/magic-vlsi-wasm on a fork.
|
||||
SCOPED_NAME="@${{ github.repository_owner }}/magic-vlsi-wasm"
|
||||
cd npm
|
||||
npm pkg set name="$SCOPED_NAME"
|
||||
npm pkg set publishConfig.registry="https://npm.pkg.github.com"
|
||||
npm version "$VERSION" --no-git-tag-version
|
||||
npm version "$VERSION" --no-git-tag-version --allow-same-version
|
||||
|
||||
- name: Pack
|
||||
run: ./npm/pack.sh
|
||||
@@ -137,24 +159,8 @@ jobs:
|
||||
name: magic-vlsi-wasm-npm
|
||||
path: npm/*.tgz
|
||||
|
||||
- name: Check if VERSION changed
|
||||
id: version_changed
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
if echo "${{ github.ref }}" | grep -q '^refs/tags/'; then
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref }}" = "refs/heads/${{ github.event.repository.default_branch }}" ]; then
|
||||
if git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -q '^VERSION$'; then
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Publish to GitHub Packages
|
||||
if: steps.version_changed.outputs.changed == 'true' && github.event.inputs.dry_run != 'true'
|
||||
if: steps.release.outputs.publish == 'true' && github.event.inputs.dry_run != 'true'
|
||||
run: cd npm && npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
Reference in New Issue
Block a user