From 688c1901bd4159e0cfe2f1473af84630d761239d Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Thu, 4 Jun 2026 11:55:30 +0900 Subject: [PATCH] add ghcXX-minimal-ghc-web flavor: wasm + JS backend dev tooling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wasm and JavaScript backends need a small set of dev-time tools that aren't part of a stock Haskell shell: * nodejs_22 — required for utils/jsffi/post-link.mjs (uses import.meta.filename added in Node 20.11; Ubuntu's apt nodejs is 18.x and silently breaks the post-link step) and for JSFFI host execution at test time * wabt — wasm-objdump for inspecting custom sections (e.g. detecting ghc_wasm_jsffi imports) in wasm modules * wasmtime — pure-WASI runtime, when a wasm module has no JSFFI imports and can run standalone * emscripten — the JavaScript backend's C toolchain (emcc / em++ / emar / emnm / emranlib / emstrip) Currently downstream consumers (e.g. stable-haskell/ghc's wasm cross-compiler CI) bootstrap these per-platform via apt + NodeSource + nix-env + curl installers, plus PATH workarounds for devx scrubbing /usr/bin. Shipping them in the flavor collapses ~70 lines of platform-shell to one `shell:` line in user workflows. Deliberately NOT bundled: wasi-sdk. Its version needs to match the wasm32-wasi-ghc cross-compiler bundle that ghc-wasm-meta (https://gitlab.haskell.org/ghc/ghc-wasm-meta) owns, so keeping that pin in ghc-wasm-meta avoids version drift across two trees. Users still bootstrap wasi-sdk via ghc-wasm-meta for wasm32-wasi builds. Closure cost on aarch64-darwin (paired with the prior trim commit): ghc98-minimal-ghc (current master) : 6.12 GB ghc98-minimal-ghc (after trim PR) : 4.00 GB (-2.12 GB) ghc98-minimal-ghc-web (this commit) : 5.99 GB (+1.99 GB) Net: the web flavor with the full toolchain ends up SMALLER than the current untrimmed minimal-ghc, because the trim commit removed ghc-9.10.3 and emscripten's LLVM/apple-sdk now dedupes against the shell's base nixpkgs pin (no version fragmentation). Comfortably under the 10 GB GitHub Actions per-repo cache cap on both Darwin and Linux (Linux delta is similar magnitude — emscripten + closure-compiler are the heavy hitters on both). Verified inside the patched shell: $ ghc --version # 9.8.4 $ cabal --version # 3.17.0.0 $ happy --version # 2.1.7 $ alex --version # 3.5.4.0 $ git --version # 2.51.2 (gitMinimal) $ node --version # v22.21.1 $ wasm-objdump --version # 1.0.37 $ wasmtime --version # 38.0.3 $ emcc --version # 4.0.12-git All on the expected store paths. --- dynamic.nix | 24 +++++++++++++++++++++++- flake.nix | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/dynamic.nix b/dynamic.nix index a8b00f2..7865638 100644 --- a/dynamic.nix +++ b/dynamic.nix @@ -1,5 +1,5 @@ # define a development shell for dynamically linked applications (default) -{ self, pkgs, compiler, compiler-nix-name, toolsModule, withHLS ? true, withHlint ? true, withIOG ? true, withIOGFull ? false, withGHCTooling ? false }: +{ self, pkgs, compiler, compiler-nix-name, toolsModule, withHLS ? true, withHlint ? true, withIOG ? true, withIOGFull ? false, withGHCTooling ? false, withWebTooling ? false }: let iog = import ./iog-libs.nix { inherit pkgs; }; tool-version-map = (import ./tool-map.nix) self; tool = tool-name: pkgs.pkgsBuildBuild.haskell-nix.tool compiler-nix-name tool-name [(tool-version-map compiler-nix-name tool-name) toolsModule]; @@ -78,6 +78,7 @@ pkgs.mkShell { + lib.optionalString withIOG "-iog" + lib.optionalString withIOGFull "-full" + lib.optionalString withGHCTooling "-ghc" + + lib.optionalString withWebTooling "-web" ; in '' export PS1="\[\033[01;33m\][\w]$\[\033[00m\] " @@ -154,6 +155,27 @@ pkgs.mkShell { libffi.dev ] ) + ++ optionals withWebTooling ( + # Tooling for the wasm and JavaScript backends. wasi-sdk itself is + # deliberately not bundled — its version needs to match the + # wasm32-wasi-ghc cross-compiler bundle, which ghc-wasm-meta owns + # (https://gitlab.haskell.org/ghc/ghc-wasm-meta). Users still bootstrap + # wasi-sdk via ghc-wasm-meta's installer for wasm32-wasi cross-builds. + # What we DO bundle here: + # * nodejs_22 — required for post-link.mjs (uses import.meta.filename + # added in Node 20.11; Ubuntu's apt nodejs is 18.x) + # and for JSFFI host execution + # * wabt — wasm-objdump for inspecting wasm modules + # * wasmtime — pure-WASI runtime (when no JSFFI imports) + # * emscripten — the JavaScript backend's C toolchain (emcc / em++ + # / emar / emnm / emranlib / emstrip) + with pkgs; [ + nodejs_22 + wabt + wasmtime + emscripten + ] + ) ; passthru = { diff --git a/flake.nix b/flake.nix index d427fe8..dc30e30 100644 --- a/flake.nix +++ b/flake.nix @@ -225,6 +225,10 @@ pkgs.lib.nameValuePair "${short-name}-minimal-ghc" ( import ./dynamic.nix (args // { withHLS = false; withHlint = false; withIOG = false; withGHCTooling = true; }) )) (compilers pkgs) + // pkgs.lib.mapAttrs' (short-name: args: + pkgs.lib.nameValuePair "${short-name}-minimal-ghc-web" ( + import ./dynamic.nix (args // { withHLS = false; withHlint = false; withIOG = false; withGHCTooling = true; withWebTooling = true; }) + )) (compilers pkgs) // pkgs.lib.mapAttrs' (short-name: args: pkgs.lib.nameValuePair "${short-name}-static" ( import ./static.nix (args // { withIOG = false; })