From cd31532f5fbcc7427cb6d087a301d1aa1489066a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 30 Jun 2026 00:20:11 +0000 Subject: [PATCH] Replace Makefiles with just Convert the three Makefiles (ext, web_ext/sseq_gui, web_ext/steenrod_calculator) to justfiles and update every caller. - ext/justfile: benchmark pattern rules become parametrized recipes (bench/bench-concurrent/fix-bench NAME) plus loop recipes over examples/benchmarks/*. The benchmark first line is expanded unquoted into an inner `bash -c`, reproducing the Makefile's quote-removal of the literal "" tokens. Also fixes the long-standing fix-benchmarks bug (bare BENCHMARKS instead of $(BENCHMARKS)). - web_ext/sseq_gui/justfile: WASM_UNWIND becomes a justfile variable (override via `just WASM_UNWIND=1 wasm`) driving if/else flag vars; test-wasm-unwind re-invokes the lib build with the override. - CI (.github/workflows/ext.yaml): swap `make -C ` for `just --working-directory --justfile /justfile ` and add an extractions/setup-just step to every job that runs recipes. - Nix: add pkgs.just to the root flake's devTools (subflakes inherit it) and swap make->just in the ext/sseq_gui app run scripts. - READMEs: update documented commands. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01DSAx1G1eMeCYPwNH7WNMVo --- .github/workflows/ext.yaml | 72 +++++++++----- ext/Makefile | 81 ---------------- ext/README.md | 18 ++-- ext/flake.nix | 12 +-- ext/justfile | 140 +++++++++++++++++++++++++++ flake.nix | 1 + web_ext/sseq_gui/Makefile | 96 ------------------ web_ext/sseq_gui/README.md | 10 +- web_ext/sseq_gui/flake.nix | 20 ++-- web_ext/sseq_gui/justfile | 102 +++++++++++++++++++ web_ext/steenrod_calculator/Makefile | 25 ----- web_ext/steenrod_calculator/justfile | 29 ++++++ 12 files changed, 351 insertions(+), 255 deletions(-) delete mode 100644 ext/Makefile create mode 100644 ext/justfile delete mode 100644 web_ext/sseq_gui/Makefile create mode 100644 web_ext/sseq_gui/justfile delete mode 100644 web_ext/steenrod_calculator/Makefile create mode 100644 web_ext/steenrod_calculator/justfile diff --git a/.github/workflows/ext.yaml b/.github/workflows/ext.yaml index 3ea2204896..f2cec5cc5b 100644 --- a/.github/workflows/ext.yaml +++ b/.github/workflows/ext.yaml @@ -20,6 +20,9 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.9" + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" - name: Install rustup id: rustup @@ -40,16 +43,16 @@ jobs: run: pip install pytest - name: Run ext tests - run: make -C ext test + run: just --working-directory ext --justfile ext/justfile test - name: Run ext examples - run: make -C ext benchmarks + run: just --working-directory ext --justfile ext/justfile benchmarks - name: Run ext examples (nassau) - run: make -C ext benchmarks-nassau + run: just --working-directory ext --justfile ext/justfile benchmarks-nassau - name: Run ext examples (concurrent) - run: make -C ext benchmarks-concurrent + run: just --working-directory ext --justfile ext/justfile benchmarks-concurrent - name: Benchmark executable size run: | @@ -65,6 +68,9 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" - name: Install rustup id: rustup @@ -83,7 +89,7 @@ jobs: key: miri-${{ steps.rustup.outputs.rustc_hash }}-${{ hashFiles('**/Cargo.*') }} - name: Run miri - run: make -C ext miri + run: just --working-directory ext --justfile ext/justfile miri lint: if: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository }} @@ -95,6 +101,9 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" - name: Install rustup id: rustup @@ -116,13 +125,13 @@ jobs: key: lint-${{ steps.rustup.outputs.rustc_hash }}-${{ hashFiles('**/Cargo.*') }} - name: Run lint - run: make -C ext lint + run: just --working-directory ext --justfile ext/justfile lint - name: Lint sseq_gui - run: make -C web_ext/sseq_gui lint + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile lint - name: Lint sseq_gui tests - run: make -C web_ext/sseq_gui lint-selenium + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile lint-selenium # Build the wasm webserver with the default `panic=abort` configuration on # stable/beta. This is the compatibility build; the deployed artifact is @@ -143,6 +152,10 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" + - name: Install rustup uses: dtolnay/rust-toolchain@v1 id: rustup @@ -164,16 +177,16 @@ jobs: run: sudo apt-get install binaryen - name: Setup build environment - run: make -C web_ext/sseq_gui setup-wasm + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile setup-wasm - name: Lint sseq_gui wasm - run: make -C web_ext/sseq_gui lint-wasm + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile lint-wasm - name: Test worker panic handling - run: make -C web_ext/sseq_gui test-wasm-js + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile test-wasm-js - name: Build wasm - run: make -C web_ext/sseq_gui wasm + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile wasm - name: Benchmark wasm size run: ls -l web_ext/sseq_gui/dist/sseq_gui_wasm_bg.wasm @@ -198,6 +211,10 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" + - name: Install rustup uses: dtolnay/rust-toolchain@v1 id: rustup @@ -220,13 +237,13 @@ jobs: run: sudo apt-get install -y binaryen wabt - name: Setup build environment - run: make -C web_ext/sseq_gui setup-wasm + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile setup-wasm - name: Build wasm (panic=unwind) - run: make -C web_ext/sseq_gui wasm WASM_UNWIND=1 + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile WASM_UNWIND=1 wasm - name: Verify wasm unwinding - run: make -C web_ext/sseq_gui test-wasm-unwind + run: just --working-directory web_ext/sseq_gui --justfile web_ext/sseq_gui/justfile test-wasm-unwind - name: Benchmark wasm size run: ls -l web_ext/sseq_gui/dist/sseq_gui_wasm_bg.wasm @@ -259,6 +276,9 @@ jobs: continue-on-error: ${{ matrix.toolchain != 'stable' }} steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" - name: Download webserver uses: actions/download-artifact@v4 @@ -295,20 +315,20 @@ jobs: - name: Test wasm run: | - make serve-wasm & - (sleep 1 && xvfb-run -a -s "-screen 0 1280x720x24" make selenium) + just serve-wasm & + (sleep 1 && xvfb-run -a -s "-screen 0 1280x720x24" just selenium) - name: Test local run: | cargo build && (target/debug/sseq_gui & - (sleep 1 && xvfb-run -a -s "-screen 0 1280x720x24" make selenium)) + (sleep 1 && xvfb-run -a -s "-screen 0 1280x720x24" just selenium)) - name: Test local concurrent run: | cargo build --features concurrent && (target/debug/sseq_gui & - (sleep 1 && xvfb-run -a -s "-screen 0 1280x720x24" make selenium)) + (sleep 1 && xvfb-run -a -s "-screen 0 1280x720x24" just selenium)) - name: Upload Artifact if: ${{ failure() }} @@ -332,6 +352,9 @@ jobs: continue-on-error: ${{ matrix.toolchain != 'stable' }} steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" - name: Install rustup id: rustup @@ -354,13 +377,13 @@ jobs: run: sudo apt-get install binaryen - name: Setup build environment - run: make -C web_ext/steenrod_calculator setup-wasm + run: just --working-directory web_ext/steenrod_calculator --justfile web_ext/steenrod_calculator/justfile setup-wasm - name: Lint sseq_gui wasm - run: make -C web_ext/steenrod_calculator lint + run: just --working-directory web_ext/steenrod_calculator --justfile web_ext/steenrod_calculator/justfile lint - name: Build wasm - run: make -C web_ext/steenrod_calculator + run: just --working-directory web_ext/steenrod_calculator --justfile web_ext/steenrod_calculator/justfile all - name: Benchmark wasm size run: ls -l web_ext/steenrod_calculator/dist/steenrod_calculator_wasm_bg.wasm @@ -387,6 +410,9 @@ jobs: continue-on-error: ${{ matrix.toolchain != 'stable' }} steps: - uses: actions/checkout@v4 + - uses: extractions/setup-just@v2 + with: + just-version: "1.34" - name: Install rustup id: rustup @@ -405,7 +431,7 @@ jobs: key: docs-${{ steps.rustup.outputs.rustc_hash }}-${{ hashFiles('ext/Cargo.*') }} - name: Generate docs - run: make -C ext docs + run: just --working-directory ext --justfile ext/justfile docs - name: Upload docs uses: actions/upload-artifact@v4 diff --git a/ext/Makefile b/ext/Makefile deleted file mode 100644 index 963bc530a6..0000000000 --- a/ext/Makefile +++ /dev/null @@ -1,81 +0,0 @@ -.PHONY: all test test-concurrent lint dummy - -all: - cargo build - -test: - cargo test --examples - cargo test --features concurrent --lib --tests --workspace - cargo test --features concurrent --doc --workspace - pytest - -lint: - cargo fmt --all -- --check - cargo clippy --workspace --no-default-features --profile test - cargo clippy --workspace --all-targets --profile test - cargo check --workspace --no-default-features --profile test - cargo check --workspace --all-targets --all-features --profile test - -docs: - # Prevent the cached crates.js from confusing the current run - rm target/doc/crates.js || true - RUSTDOCFLAGS="--html-in-header gh-pages/katex-header.html $(RUSTDOCFLAGS)" cargo rustdoc --examples --all-features - RUSTDOCFLAGS="--html-in-header gh-pages/katex-header.html $(RUSTDOCFLAGS)" cargo doc --all --no-deps --document-private-items --all-features - # Prevent the examples from showing up in the sidebar - echo "window.ALL_CRATES = [$$(ls crates/ | sed "s/.*/'&',/; s/-/_/g")'ext'];" > target/doc/crates.js - - -BENCHMARKS = $(filter-out examples/benchmarks/%-nassau, $(wildcard examples/benchmarks/*)) - -benchmarks: $(BENCHMARKS) -benchmarks-nassau: $(wildcard examples/benchmarks/*-nassau) - -fix-benchmarks: $(patsubst examples/benchmarks/%, examples/benchmarks/%-fixed, BENCHMARKS) -fix-benchmarks-nassau: $(patsubst examples/benchmarks/%, examples/benchmarks/%-fixed, $(wildcard examples/benchmarks/*-nassau)) - -benchmarks-concurrent: $(patsubst examples/benchmarks/%, examples/benchmarks/%-concurrent, $(BENCHMARKS)) - -examples/benchmarks/%-fixed: FILE = examples/benchmarks/$* -examples/benchmarks/%-fixed: dummy - (head -n 1 $(FILE) && bash -c "echo '' | cargo run --example $$(head -n 1 $(FILE))") > $@ - if diff --color $(FILE) $@; then \ - rm $@; \ - else \ - mv $@ $(FILE); \ - fi -examples/benchmarks/%-nassau-fixed: dummy - (head -n 1 $(FILE)-nassau && bash -c "echo '' | cargo run --features nassau --example $$(head -n 1 $(FILE)-nassau)") > $@ - if diff --color $(FILE)-nassau $@; then \ - rm $@; \ - else \ - mv $@ $(FILE)-nassau; \ - fi - - -examples/benchmarks/%: dummy - (head -n 1 $@ && bash -c "echo '' | cargo run --example $$(head -n 1 $@)") | diff --color $@ - - -examples/benchmarks/%-nassau: dummy - (head -n 1 $@ && bash -c "echo '' | cargo run --features nassau --example $$(head -n 1 $@)") | diff --color $@ - - -examples/benchmarks/%-concurrent: FILE = examples/benchmarks/$* -examples/benchmarks/%-concurrent: dummy - @{ \ - head -n 1 $(FILE); \ - timeout 30 bash -c "echo '' | cargo run --features concurrent --example $$(head -n 1 $(FILE))"; \ - ec=$$?; \ - } > output.txt; \ - if [ $$ec -eq 124 ]; then \ - echo "Timeout occurred, but treating as success."; \ - elif [ $$ec -eq 0 ]; then \ - diff --color output.txt $(FILE); \ - rm output.txt; \ - else \ - echo "Command failed with code $$ec."; \ - rm output.txt; \ - exit 1; \ - fi - -miri: - cargo miri test -p once - MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" cargo miri test -p once --features concurrent diff --git a/ext/README.md b/ext/README.md index 3bc6c3872a..cbdd482901 100644 --- a/ext/README.md +++ b/ext/README.md @@ -81,7 +81,7 @@ Documentation for both the examples and the library itself is hosted at If documentation for a specific version of the library is sought, it can be generated by running ```shell -make docs +just docs ``` after which the documentation is placed at `target/doc/`. The link above opens @@ -94,7 +94,7 @@ the file `target/doc/ext/index.html`. Lint scripts can be run with ```shell -make lint +just lint ``` This runs `clippy` and `rustfmt`. @@ -108,7 +108,7 @@ There are multiple types of tests These can be run by ```shell -make test +just test ``` #### Example benchmarks @@ -121,14 +121,14 @@ the output should be. These can be run by ```shell -make benchmarks -make benchmarks-concurrent +just benchmarks +just benchmarks-concurrent ``` Running ```shell -make fix-benchmarks +just fix-benchmarks ``` updates the outputs in all benchmark files to match the current program output. @@ -137,7 +137,7 @@ This is useful for adding new benchmarks. These can be run for individual benchmarks by e.g. ```shell -make examples/benchmarks/resolve-S_2 -make examples/benchmarks/resolve-S_2-concurrent -make examples/benchmarks/resolve-S_2-fixed +just bench resolve-S_2 +just bench-concurrent resolve-S_2 +just fix-bench resolve-S_2 ``` diff --git a/ext/flake.nix b/ext/flake.nix index cfc98ca094..35e0d02fc8 100644 --- a/ext/flake.nix +++ b/ext/flake.nix @@ -44,12 +44,12 @@ export RUSTFLAGS="-D warnings" export RUSTDOCFLAGS="-D warnings" - make lint - make test - make benchmarks - make benchmarks-nassau - make benchmarks-concurrent - make miri + just lint + just test + just benchmarks + just benchmarks-nassau + just benchmarks-concurrent + just miri ''); }; }); diff --git a/ext/justfile b/ext/justfile new file mode 100644 index 0000000000..b28d60221f --- /dev/null +++ b/ext/justfile @@ -0,0 +1,140 @@ +# Command runner for the `ext` library. Replaces the old Makefile. +# Requires `just` >= 1.5 (shebang recipes, if/else expressions, CLI overrides). + +set shell := ["bash", "-c"] + +BENCH_DIR := "examples/benchmarks" + +# Build the library (default recipe). +all: + cargo build + +test: + cargo test --examples + cargo test --features concurrent --lib --tests --workspace + cargo test --features concurrent --doc --workspace + pytest + +lint: + cargo fmt --all -- --check + cargo clippy --workspace --no-default-features --profile test + cargo clippy --workspace --all-targets --profile test + cargo check --workspace --no-default-features --profile test + cargo check --workspace --all-targets --all-features --profile test + +docs: + # Prevent the cached crates.js from confusing the current run + rm target/doc/crates.js || true + RUSTDOCFLAGS="--html-in-header gh-pages/katex-header.html $RUSTDOCFLAGS" cargo rustdoc --examples --all-features + RUSTDOCFLAGS="--html-in-header gh-pages/katex-header.html $RUSTDOCFLAGS" cargo doc --all --no-deps --document-private-items --all-features + # Prevent the examples from showing up in the sidebar + echo "window.ALL_CRATES = [$(ls crates/ | sed "s/.*/'&',/; s/-/_/g")'ext'];" > target/doc/crates.js + +miri: + cargo miri test -p once + MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" cargo miri test -p once --features concurrent + +# ---- Benchmarks ---------------------------------------------------------- +# +# Each file in examples/benchmarks/ has the example argument on its first line +# and the expected output on the rest. Names ending in `-nassau` are run with +# `--features nassau`. + +# Run a single benchmark, e.g. `just bench resolve-S_2`. +bench NAME: + #!/usr/bin/env bash + set -euo pipefail + file="{{BENCH_DIR}}/{{NAME}}" + features="" + [[ "{{NAME}}" == *-nassau ]] && features="--features nassau" + # The first line is the example invocation. It is expanded UNQUOTED into the + # inner `bash -c` string, which then word-splits it into separate cargo args + # (e.g. `resolve -- S_2 "" 30 11 ""`) with the `""` tokens becoming empty + # arguments via the inner shell's quote removal — matching the old Makefile. + example="$(head -n 1 "$file")" + (echo "$example" && bash -c "echo '' | cargo run $features --example $example") | diff --color "$file" - + +# Run a single benchmark with --features concurrent (30s timeout = success). +bench-concurrent NAME: + #!/usr/bin/env bash + set -euo pipefail + file="{{BENCH_DIR}}/{{NAME}}" + example="$(head -n 1 "$file")" + { + echo "$example" + timeout 30 bash -c "echo '' | cargo run --features concurrent --example $example" + ec=$? + } > output.txt || ec=$? + if [ "${ec:-0}" -eq 124 ]; then + echo "Timeout occurred, but treating as success." + rm -f output.txt + elif [ "${ec:-0}" -eq 0 ]; then + diff --color output.txt "$file" + rm -f output.txt + else + echo "Command failed with code ${ec}." + rm -f output.txt + exit 1 + fi + +# Rewrite a single benchmark's expected output to the current program output. +fix-bench NAME: + #!/usr/bin/env bash + set -euo pipefail + file="{{BENCH_DIR}}/{{NAME}}" + features="" + [[ "{{NAME}}" == *-nassau ]] && features="--features nassau" + example="$(head -n 1 "$file")" + out="${file}-fixed" + (echo "$example" && bash -c "echo '' | cargo run $features --example $example") > "$out" + if diff --color "$file" "$out"; then + rm "$out" + else + mv "$out" "$file" + fi + +# All non-nassau benchmarks. +benchmarks: + #!/usr/bin/env bash + set -euo pipefail + for file in {{BENCH_DIR}}/*; do + name="$(basename "$file")" + [[ "$name" == *-nassau ]] && continue + just bench "$name" + done + +# All nassau benchmarks. +benchmarks-nassau: + #!/usr/bin/env bash + set -euo pipefail + for file in {{BENCH_DIR}}/*-nassau; do + just bench "$(basename "$file")" + done + +# All non-nassau benchmarks, concurrent. +benchmarks-concurrent: + #!/usr/bin/env bash + set -euo pipefail + for file in {{BENCH_DIR}}/*; do + name="$(basename "$file")" + [[ "$name" == *-nassau ]] && continue + just bench-concurrent "$name" + done + +# Rewrite all non-nassau benchmark outputs. +fix-benchmarks: + #!/usr/bin/env bash + set -euo pipefail + for file in {{BENCH_DIR}}/*; do + name="$(basename "$file")" + [[ "$name" == *-nassau ]] && continue + just fix-bench "$name" + done + +# Rewrite all nassau benchmark outputs. +fix-benchmarks-nassau: + #!/usr/bin/env bash + set -euo pipefail + for file in {{BENCH_DIR}}/*-nassau; do + just fix-bench "$(basename "$file")" + done diff --git a/flake.nix b/flake.nix index 705d06043b..2cc6fafcf6 100644 --- a/flake.nix +++ b/flake.nix @@ -33,6 +33,7 @@ pkgs = import nixpkgs {inherit system;}; in [ pkgs.git + pkgs.just pkgs.hyperfine pkgs.binutils pkgs.cargo-binutils diff --git a/web_ext/sseq_gui/Makefile b/web_ext/sseq_gui/Makefile deleted file mode 100644 index 6406b02d73..0000000000 --- a/web_ext/sseq_gui/Makefile +++ /dev/null @@ -1,96 +0,0 @@ -WASM_TARGET = wasm32-unknown-unknown -NAME = sseq_gui -WASM_LIB = target/$(WASM_TARGET)/release/$(NAME).wasm -WASM_OUT = dist/ -WASM_FILE = $(WASM_OUT)/$(NAME)_wasm_bg.wasm -EXT = ../../ext/ - -# Building with `panic=unwind` lets Rust panics unwind into JS exceptions -# instead of aborting the whole wasm module. The prebuilt std for -# wasm32-unknown-unknown is compiled with `panic=abort`, so `-C panic=unwind` -# alone is silently ignored: we must rebuild std with `-Z build-std` (nightly -# only) and enable the wasm exception-handling proposal. -# -# This is opt-in via `WASM_UNWIND=1` so the default build still works on -# stable/beta (panic=abort). CI builds stable/beta with panic=abort and the -# deployed build with `WASM_UNWIND=1` on nightly. -ifdef WASM_UNWIND -WASM_RUSTFLAGS = -C panic=unwind -C target-feature=+exception-handling -WASM_BUILD_STD = -Z build-std=std,panic_unwind -WASM_OPT_FLAGS = --enable-exception-handling -endif - -export PATH := $(HOME)/.cargo/bin:$(PATH) - -lint: - cargo clippy --all-features --all-targets - cargo clippy --no-default-features --all-targets - cargo fmt -- --check - -lint-wasm: - cargo clippy --lib --target $(WASM_TARGET) - -setup-wasm: - cargo install wasm-bindgen-cli --debug - rustup target add wasm32-unknown-unknown - # rust-src is required by `-Z build-std` (see the WASM_BUILD_STD note above). - rustup component add rust-src - -# Always defer to cargo to decide whether a rebuild is needed: it fingerprints -# RUSTFLAGS and the build-std setting, so it correctly rebuilds when toggling -# between panic=abort and panic=unwind (which `make`'s timestamp check cannot -# detect, as the sources are unchanged). -$(WASM_LIB): FORCE - RUSTFLAGS="$$RUSTFLAGS $(WASM_RUSTFLAGS)" \ - cargo build --lib --target $(WASM_TARGET) --release $(WASM_BUILD_STD) - -FORCE: - -$(WASM_FILE): $(WASM_LIB) - wasm-bindgen --no-typescript --target no-modules --out-dir $(WASM_OUT) --out-name $(NAME)_wasm $(WASM_LIB) - wasm-opt -O3 $(WASM_OPT_FLAGS) $(WASM_FILE) -o $(WASM_FILE) || true - -# Assert that the wasm is actually built with unwinding support: a wasm module -# using the exception-handling proposal contains a `Tag` section. If unwinding -# silently regressed to `panic=abort` (e.g. build-std got dropped), this fails. -# Forces a WASM_UNWIND=1 build of the lib so the check is meaningful regardless -# of how it was invoked. -test-wasm-unwind: - $(MAKE) WASM_UNWIND=1 $(WASM_LIB) - wasm-objdump -h $(WASM_LIB) | grep -qi '^ *Tag ' \ - || { echo "ERROR: $(WASM_LIB) has no Tag section; panic=unwind is not in effect"; exit 1; } - @echo "OK: wasm built with exception-handling (panic=unwind)" - -# Unit-test the panic-catching logic in the worker JS (wasm/*_worker.js). -# Runs in plain Node with mocked wasm globals, so no browser/wasm build needed. -test-wasm-js: - node --test wasm/*.test.mjs - -.PHONY: wasm serve-wasm clean-wasm clean dummy test selenium selenium-update test-wasm-unwind test-wasm-js FORCE - -wasm: $(WASM_FILE) $(wildcard interface/*) $(wildcard wasm/*) $(wildcard $(EXT)/steenrod_modules/*) - # Must be done in this order since both contain index.js and we want the wasm version - cp interface/* $(WASM_OUT) - cp wasm/* $(WASM_OUT) - cp vendor/* $(WASM_OUT) - cp -r $(EXT)/steenrod_modules $(WASM_OUT) - -serve-wasm: - python3 -m http.server --directory dist 8080 - -clean-wasm: - rm -r dist/* - -clean: clean-wasm - rm -r target - -lint-selenium: - flake8 --ignore E501 tests - black --diff --check tests - -selenium: - python3 -m pytest -s tests --driver chrome - python3 -m pytest -s tests --driver firefox - -selenium-update: - python3 -m pytest tests --driver firefox --update diff --git a/web_ext/sseq_gui/README.md b/web_ext/sseq_gui/README.md index 5fbcbaa9f6..58536342e7 100644 --- a/web_ext/sseq_gui/README.md +++ b/web_ext/sseq_gui/README.md @@ -32,7 +32,7 @@ distribution but is slower. A live version is available at To setup the build environment, run ```shell -make setup-wasm +just setup-wasm ``` By default the wasm is built with `panic=abort`, which works on stable. Passing @@ -41,18 +41,18 @@ By default the wasm is built with `panic=abort`, which works on stable. Passing than aborting the whole module: ```shell -make wasm WASM_UNWIND=1 +just WASM_UNWIND=1 wasm ``` This requires a **nightly** toolchain with the `rust-src` component (installed -by `make setup-wasm`). The deployed build uses `WASM_UNWIND=1`; CI also builds +by `just setup-wasm`). The deployed build uses `WASM_UNWIND=1`; CI also builds the default `panic=abort` configuration on stable/beta. Afterwards, build and serve with ```shell -make wasm -make serve-wasm +just wasm +just serve-wasm ``` This serves the website at `localhost:[port]`. The `[port]` argument is optional and defaults to `8000`. diff --git a/web_ext/sseq_gui/flake.nix b/web_ext/sseq_gui/flake.nix index d9c6b96039..ec9f48b4f2 100644 --- a/web_ext/sseq_gui/flake.nix +++ b/web_ext/sseq_gui/flake.nix @@ -33,7 +33,7 @@ pythonEnv pkgs.openssl - # wabt provides wasm-objdump, used by `make test-wasm-unwind` to + # wabt provides wasm-objdump, used by `just test-wasm-unwind` to # assert the wasm is actually built with unwinding support. pkgs.wabt ] @@ -45,24 +45,24 @@ export RUSTFLAGS="-D warnings" export RUSTDOCFLAGS="-D warnings" - make lint - make lint-selenium + just lint + just lint-selenium cargo install wasm-bindgen-cli --debug - make lint-wasm - make wasm - make test-wasm-unwind + just lint-wasm + just wasm + just test-wasm-unwind - make serve-wasm & - (sleep 1 && make selenium) + just serve-wasm & + (sleep 1 && just selenium) cargo build && (target/debug/sseq_gui & - (sleep 1 && make selenium)) + (sleep 1 && just selenium)) cargo build --features concurrent && (target/debug/sseq_gui & - (sleep 1 && make selenium)) + (sleep 1 && just selenium)) ''; in { devShells.default = pkgs.mkShell { diff --git a/web_ext/sseq_gui/justfile b/web_ext/sseq_gui/justfile new file mode 100644 index 0000000000..2e79c5f164 --- /dev/null +++ b/web_ext/sseq_gui/justfile @@ -0,0 +1,102 @@ +# Command runner for sseq_gui. Replaces the old Makefile. +# Requires `just` >= 1.5 (shebang recipes, if/else expressions, CLI overrides). + +set shell := ["bash", "-c"] + +WASM_TARGET := "wasm32-unknown-unknown" +NAME := "sseq_gui" +WASM_LIB := "target/" + WASM_TARGET + "/release/" + NAME + ".wasm" +WASM_OUT := "dist/" +WASM_FILE := WASM_OUT + "/" + NAME + "_wasm_bg.wasm" +EXT := "../../ext/" + +# Building with `panic=unwind` lets Rust panics unwind into JS exceptions +# instead of aborting the whole wasm module. The prebuilt std for +# wasm32-unknown-unknown is compiled with `panic=abort`, so `-C panic=unwind` +# alone is silently ignored: we must rebuild std with `-Z build-std` (nightly +# only) and enable the wasm exception-handling proposal. +# +# This is opt-in via `WASM_UNWIND=1` so the default build still works on +# stable/beta (panic=abort). Override on the command line, e.g. +# `just WASM_UNWIND=1 wasm`. CI builds stable/beta with panic=abort and the +# deployed build with `WASM_UNWIND=1` on nightly. +WASM_UNWIND := "" +WASM_RUSTFLAGS := if WASM_UNWIND != "" { "-C panic=unwind -C target-feature=+exception-handling" } else { "" } +WASM_BUILD_STD := if WASM_UNWIND != "" { "-Z build-std=std,panic_unwind" } else { "" } +WASM_OPT_FLAGS := if WASM_UNWIND != "" { "--enable-exception-handling" } else { "" } + +lint: + cargo clippy --all-features --all-targets + cargo clippy --no-default-features --all-targets + cargo fmt -- --check + +lint-wasm: + cargo clippy --lib --target {{WASM_TARGET}} + +setup-wasm: + cargo install wasm-bindgen-cli --debug + rustup target add wasm32-unknown-unknown + # rust-src is required by `-Z build-std` (see the WASM_UNWIND note above). + rustup component add rust-src + +# Always rebuild: cargo fingerprints RUSTFLAGS and the build-std setting, so it +# correctly rebuilds when toggling between panic=abort and panic=unwind (which a +# timestamp check cannot detect, as the sources are unchanged). +wasm-lib: + #!/usr/bin/env bash + set -euo pipefail + export PATH="$HOME/.cargo/bin:$PATH" + RUSTFLAGS="${RUSTFLAGS:-} {{WASM_RUSTFLAGS}}" \ + cargo build --lib --target {{WASM_TARGET}} --release {{WASM_BUILD_STD}} + +wasm-bindgen-step: wasm-lib + #!/usr/bin/env bash + set -euo pipefail + export PATH="$HOME/.cargo/bin:$PATH" + wasm-bindgen --no-typescript --target no-modules --out-dir {{WASM_OUT}} --out-name {{NAME}}_wasm {{WASM_LIB}} + wasm-opt -O3 {{WASM_OPT_FLAGS}} {{WASM_FILE}} -o {{WASM_FILE}} || true + +wasm: wasm-bindgen-step + # Must be done in this order since both contain index.js and we want the wasm version + cp interface/* {{WASM_OUT}} + cp wasm/* {{WASM_OUT}} + cp vendor/* {{WASM_OUT}} + cp -r {{EXT}}/steenrod_modules {{WASM_OUT}} + +# Assert that the wasm is actually built with unwinding support: a wasm module +# using the exception-handling proposal contains a `Tag` section. If unwinding +# silently regressed to `panic=abort`, this fails. Forces a WASM_UNWIND=1 build +# of the lib so the check is meaningful regardless of how it was invoked. +test-wasm-unwind: + #!/usr/bin/env bash + set -euo pipefail + export PATH="$HOME/.cargo/bin:$PATH" + just WASM_UNWIND=1 wasm-lib + wasm-objdump -h {{WASM_LIB}} | grep -qi '^ *Tag ' \ + || { echo "ERROR: {{WASM_LIB}} has no Tag section; panic=unwind is not in effect"; exit 1; } + echo "OK: wasm built with exception-handling (panic=unwind)" + +# Unit-test the panic-catching logic in the worker JS (wasm/*_worker.js). +# Runs in plain Node with mocked wasm globals, so no browser/wasm build needed. +test-wasm-js: + node --test wasm/*.test.mjs + +serve-wasm: + python3 -m http.server --directory dist 8080 + +clean-wasm: + rm -r dist/* + +clean: clean-wasm + rm -r target + +lint-selenium: + flake8 --ignore E501 tests + black --diff --check tests + +selenium: + python3 -m pytest -s tests --driver chrome + python3 -m pytest -s tests --driver firefox + +selenium-update: + python3 -m pytest tests --driver firefox --update diff --git a/web_ext/steenrod_calculator/Makefile b/web_ext/steenrod_calculator/Makefile deleted file mode 100644 index fae7193cc0..0000000000 --- a/web_ext/steenrod_calculator/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -WASM_TARGET = wasm32-unknown-unknown -NAME = steenrod_calculator -WASM_LIB = target/$(WASM_TARGET)/release/$(NAME).wasm -WASM_OUT = dist/ -WASM_FILE = $(WASM_OUT)/$(NAME)_wasm_bg.wasm - -EXT_SRC = ../../ext/Cargo.toml $(shell find ../../ext/src/) $(wildcard ../../ext/crates/*/Cargo.tml) $(shell find ../../ext/crates/*/src/) - -all: $(WASM_FILE) $(wildcard files/*) - cp files/* $(WASM_OUT) - -lint: - cargo fmt -- --check - cargo clippy --lib --target $(WASM_TARGET) - -setup-wasm: - cargo install wasm-bindgen-cli --debug - rustup target add wasm32-unknown-unknown - -$(WASM_LIB): Cargo.toml $(wildcard src/*) $(EXT_SRC) - cargo build --lib --target $(WASM_TARGET) --release - -$(WASM_FILE): $(WASM_LIB) - wasm-bindgen --no-typescript --target no-modules --out-dir $(WASM_OUT) --out-name $(NAME)_wasm $(WASM_LIB) - wasm-opt -O3 $(WASM_FILE) -o $(WASM_FILE) || true diff --git a/web_ext/steenrod_calculator/justfile b/web_ext/steenrod_calculator/justfile new file mode 100644 index 0000000000..3901e0390a --- /dev/null +++ b/web_ext/steenrod_calculator/justfile @@ -0,0 +1,29 @@ +# Command runner for the Steenrod calculator. Replaces the old Makefile. +# Requires `just` >= 1.5. + +set shell := ["bash", "-c"] + +WASM_TARGET := "wasm32-unknown-unknown" +NAME := "steenrod_calculator" +WASM_LIB := "target/" + WASM_TARGET + "/release/" + NAME + ".wasm" +WASM_OUT := "dist/" +WASM_FILE := WASM_OUT + "/" + NAME + "_wasm_bg.wasm" + +# Build the wasm and copy the static files (default recipe). +all: wasm-bindgen-step + cp files/* {{WASM_OUT}} + +lint: + cargo fmt -- --check + cargo clippy --lib --target {{WASM_TARGET}} + +setup-wasm: + cargo install wasm-bindgen-cli --debug + rustup target add wasm32-unknown-unknown + +wasm-lib: + cargo build --lib --target {{WASM_TARGET}} --release + +wasm-bindgen-step: wasm-lib + wasm-bindgen --no-typescript --target no-modules --out-dir {{WASM_OUT}} --out-name {{NAME}}_wasm {{WASM_LIB}} + wasm-opt -O3 {{WASM_FILE}} -o {{WASM_FILE}} || true