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 # @/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. # # WASM is architecture-independent — built once on x86-64, usable everywhere. on: push: pull_request: workflow_dispatch: inputs: emsdk_version: description: 'emsdk version to build with (default: latest; pin a version number to bisect)' type: string default: 'latest' dry_run: description: 'Dry run: pack only, do not publish even on tag pushes' type: boolean default: true # actions/upload-artifact@v5 still runs on Node.js 20. Force Node 24 to # silence the deprecation warning until upload-artifact ships a Node-24 # release. Drop this once upgraded. env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true permissions: contents: read packages: write jobs: build-wasm: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 with: fetch-depth: 2 - name: Set up Node.js uses: actions/setup-node@v5 with: node-version: '22' registry-url: 'https://npm.pkg.github.com' - name: Install emsdk env: # Defaults to latest so CI tracks emsdk HEAD and catches breakage early. # Override via workflow_dispatch to pin a specific version when needed # (e.g. to bisect a regression or verify a post-build.sh patch still applies). EMSDK_VERSION: ${{ github.event.inputs.emsdk_version || 'latest' }} run: | git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install "$EMSDK_VERSION" ./emsdk activate "$EMSDK_VERSION" # Dump native + emscripten preprocessor defines. Useful for diagnosing # WASM-build differences after an emsdk bump. - name: Emscripten Diagnostic run: | source ./emsdk/emsdk_env.sh echo "===== gcc -dM -E - ====="; echo | gcc -dM -E - | sort echo "===== g++ -dM -E - ====="; echo | g++ -dM -E - | sort echo "===== emcc -dM -E - ====="; echo | emcc -dM -E - | sort echo "===== em++ -dM -E - ====="; echo | em++ -dM -E - | sort - name: Build WASM 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 - name: Copy WASM artifacts into npm/ run: | cp magic/magic.js npm/ cp magic/magic.wasm npm/ - name: Run example tests run: cd npm && npm run test # Dump generated text outputs (.ext, .spice, .cif, …) into the CI log # so a regression in extraction / netlisting / cifoutput is visible # without having to download artifacts. The .gds output is binary — # skip it and just record its size. - name: Display example outputs run: | shopt -s nullglob for f in npm/examples/output/*; do name=$(basename "$f") case "$f" in *.gds) echo "===== $name (binary, $(wc -c < "$f") bytes — skipped) =====" ;; *) echo "===== $name ====="; cat "$f" ;; esac done - name: Set package version and scope 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 - name: Pack run: ./npm/pack.sh - name: Upload tarball as artifact uses: actions/upload-artifact@v5 with: 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' run: cd npm && npm publish env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}