Skip to content

Add WASM target support to TemplateProject#23

Open
olilarkin wants to merge 2 commits intoclifrom
add-wasm-target
Open

Add WASM target support to TemplateProject#23
olilarkin wants to merge 2 commits intoclifrom
add-wasm-target

Conversation

@olilarkin
Copy link
Copy Markdown
Member

Mirrors the split DSP/UI wasm build that was added upstream in iPlug2 da6112de.
Adds the three makefiles (config + dsp + ui project) and the makedist-wasm.sh driver adapted for the iPlug2OOS layout, bumps the submodule so common-wasm.mk and the TemplateWasm HTML/JS templates are available, and teaches duplicate.py to recurse into build-web-wasm/.

Mirrors the split DSP/UI wasm build that was added upstream in iPlug2
da6112de. Adds the three makefiles (config + dsp + ui project) and the
makedist-wasm.sh driver adapted for the iPlug2OOS layout, bumps the
submodule so common-wasm.mk and the TemplateWasm HTML/JS templates are
available, and teaches duplicate.py to recurse into build-web-wasm/.
@claude
Copy link
Copy Markdown

claude Bot commented Apr 21, 2026

Code Review: Add WASM target support to TemplateProject

Good addition that mirrors the upstream split DSP/UI WASM build. The overall structure is solid and consistent with the existing build-web pattern. A few issues worth addressing before merge:


makedist-wasm.sh

Bug / Reliability

  • Missing set -euo pipefail at the top. The script manually checks emmake exit codes but silently ignores failures in cd, file_packager, sed, and mv calls. A stray cd failure will run subsequent commands in the wrong directory.

    # Add near the top, after the shebang
    set -euo pipefail
  • IPLUG2_ROOT is assigned twice, making the first line a dead intermediate:

    IPLUG2_ROOT=../../iPlug2          # used only to build the next line
    PROJECT_ROOT=$SCRIPT_DIR/..
    IPLUG2_ROOT=$SCRIPT_DIR/$IPLUG2_ROOT   # effective value

    Simplify to: IPLUG2_ROOT=$SCRIPT_DIR/../../iPlug2

  • Unquoted path variables throughout. Paths with spaces will break:

    cd $PROJECT_ROOT            # should be: cd "$PROJECT_ROOT"
    python3 $FILE_PACKAGER# should be: python3 "$FILE_PACKAGER" …
    rm -r build-web-wasm        # should be: rm -r "build-web-wasm"
    emrun --browser $EMRUN_BROWSER# should be: … "$EMRUN_BROWSER" …
  • rm -f *.bak at cleanup will also remove any pre-existing .bak files in build-web-wasm/, scripts/, and styles/ that the script didn't create. Safer to track and remove only what was created, or use a unique suffix like .iPlug2.bak.

Minor / Style

  • The --makefile flag (emmake make --makefile …) is accepted by GNU make but -f is the POSIX-standard short form — prefer -f for portability.

  • The hardcoded AudioWorklet shim writes a literal https://localhost/ into every project's DSP module:

    self.location = self.location || { href: 'https://localhost/' };

    Worth a comment explaining why this URL is a no-op placeholder and won't affect production deployments.

  • No debug-build path. Consider honouring a DEBUG=1 env var (or a script argument) to pass -g -s ASSERTIONS=1 instead of -O3 -s ASSERTIONS=0, matching how other iPlug2 build scripts handle debug vs release.


TemplateProject/projects/TemplateProject-wasm-{dsp,ui}.mk

The make rule has a dependency/recipe mismatch:

$(TARGET): $(OBJECTS)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC)   # uses SRC, not OBJECTS

If common-wasm.mk defines OBJECTS to something non-empty this will silently recompile on every run (stale dependency) or miss recompilation (incremental builds broken). If OBJECTS is intentionally empty/unused here, the prerequisite should be removed or a comment added.


TemplateProject/config/TemplateProject-wasm.mk

Looks correct. -O3 -s ASSERTIONS=0 is fine for a release template; see note above about debug support.


duplicate.py

The change is minimal and correct — build-web-wasm follows the same pattern as the existing build-web entry. The added trailing comma on "build-web" is a pre-existing style inconsistency but not a problem.


Submodule bump

Appropriate; the new common-wasm.mk and TemplateWasm HTML/JS templates need to be available.


Summary

Area Status
Overall structure ✅ Mirrors upstream correctly
duplicate.py ✅ Correct
Submodule bump ✅ Appropriate
Script error handling ⚠️ Missing set -euo pipefail, unquoted vars
Makefile recipe ⚠️ $(OBJECTS) dependency vs $(SRC) recipe — clarify intent
Debug builds ⚠️ No debug path
Minor nits ℹ️ --makefile-f, double IPLUG2_ROOT assignment, .bak cleanup

The core logic is sound — the main ask is hardening the shell script defensively before this ships as a template that new projects will copy verbatim.

- set -euo pipefail, quote paths, guard optional $1/$2
- drop duplicate IPLUG2_ROOT assignment
- switch .bak cleanup to a unique suffix so we only remove files we created
- require EMSDK via ${EMSDK:?}
- emmake: --makefile -> -f, replace post-hoc $? checks with ||{ exit }
- explain the https://localhost/ AudioWorklet shim
- mk: target depends on $(SRC) (was $(OBJECTS), which common-wasm.mk leaves empty)
@claude
Copy link
Copy Markdown

claude Bot commented Apr 24, 2026

placeholder

@claude
Copy link
Copy Markdown

claude Bot commented Apr 24, 2026

Code Review: Add WASM target support to TemplateProject

Overview

This PR mirrors the split DSP/UI WASM build architecture from upstream iPlug2 (da6112de) into the OOS layout. It adds three makefiles, a makedist-wasm.sh driver, bumps the iPlug2 submodule, and teaches duplicate.py to exclude the new build-web-wasm/ output directory. The approach is well-structured and the split DSP/UI model is the right design for AudioWorklet-based plugins.


Issues

High Priority

Shell glob expansion in file_packager.py calls (makedist-wasm.sh lines ~83, 90, 96, 103)

The --exclude arguments are unquoted, so the shell expands them before passing to Python. If any file matching *DS_Store or *@2x.png exists in the current working directory, the shell silently replaces the glob before Python sees it. They should be single-quoted:

python3 "$FILE_PACKAGER" fonts.data --preload ./resources/fonts/ --exclude '*DS_Store' --js-output=./fonts.js

All four --exclude arguments in the resource packaging block have this issue.

Fragile cd in @2x packaging block (lines ~104-110)

With set -euo pipefail active, if file_packager.py fails inside the cd build-web-wasm block, the script exits before cd .. runs, leaving the working directory wrong for everything that follows. A subshell isolates the directory change:

(cd build-web-wasm && python3 "$FILE_PACKAGER" imgs@2x.data ... && rm -r ./2x)

Medium Priority

HAS_UI detection can match commented-out defines (line ~23)

A config.h containing // #define PLUG_HAS_UI 1 (commented out) would incorrectly set HAS_UI=1. Anchoring to #define fixes this:

if grep -qE '^[[:space:]]*#define PLUG_HAS_UI[[:space:]]+1' "$PROJECT_ROOT/config.h" 2>/dev/null; then

The same fix applies to PLUG_HOST_RESIZE, PLUG_DOES_MIDI_IN, and PLUG_DOES_MIDI_OUT (lines ~196, 201, 207).

Unquoted path variables in sed commands (lines ~226-248)

The destination paths in sed calls like scripts/$PROJECT_NAME-bundle.js are unquoted. A project name with spaces would break this silently. Quote consistently throughout.

No .PHONY or clean targets in the makefiles

Both TemplateProject-wasm-dsp.mk and TemplateProject-wasm-ui.mk define a file-rule target but omit .PHONY and a clean target. Without explicit dependency tracking, make may not rebuild when sources change but the output file already exists. At minimum add a clean target that removes $(TARGET) and $(TARGET:.js=.wasm).

Low Priority / Suggestions

AudioWorklet var shim comment (lines ~120-130)

The comment explaining the AudioWorklet scope constraint is helpful. Consider expanding it to note that var self = globalThis is intentional and not a typo, since future maintainers will likely question this pattern.

emmake/emrun availability not verified

EMSDK is correctly validated with an early-exit and actionable message, but emmake and emrun are assumed to be on $PATH. An early command -v emmake check would give a clearer error message before compilation begins.

Redundant error handlers with set -e (lines ~113-117, ~163-167)

The || exit 1 pattern prevents -e from triggering (the || consumes the exit code) and then exits explicitly. This is harmless but mildly confusing. A trap ERR handler would be cleaner if custom error messages are needed.


What's Good

  • set -euo pipefail from the start.
  • SCRIPT_DIR / BASH_SOURCE[0] for reliable path resolution.
  • EMSDK validated with early-exit and actionable message.
  • Unique BAK_SUFFIX for sed -i backups with guaranteed cleanup via find -delete.
  • The split DSP/UI build correctly gates the UI module on PLUG_HAS_UI, with clear console output for the headless path.
  • The NAME_PLACEHOLDER_LC-before-NAME_PLACEHOLDER ordering comment is an important correctness note.
  • The duplicate.py change is correct and the missing trailing comma fix is appreciated.

Overall this is solid work that closely mirrors the upstream pattern and adapts it cleanly to the OOS layout. The shell glob expansion bug in the file_packager.py calls is the most important thing to fix before merging.

@olilarkin olilarkin changed the base branch from master to claude/cli-build-plot-hUKUG May 1, 2026 13:20
@olilarkin olilarkin changed the base branch from claude/cli-build-plot-hUKUG to cli May 1, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant