From a9f0955865ca7a13c63f41051bbdbccc46d5998d Mon Sep 17 00:00:00 2001 From: atlas Date: Sun, 31 May 2026 11:23:55 +0200 Subject: [PATCH] nix/hive-matrix: build Imaging.{js,wasm} from source via emscripten (#685, mara feedback) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mara on PR #697: "dont use the prebuilt binary, fix the compile of the one in nixpkgs (however its easiest: overlay, own derivation based on it, hell if you want to you can fix buildFlutterApplication, idk)." Replaces the upstream-tarball vendor with an own derivation that compiles `Imaging.{js,wasm}` from the `native_imaging` dart package's C source via `pkgs.emscripten`. Same source provenance as fluffychat itself uses (both pin native_imaging 0.4.0 from pub.dev), now actually exercised at build time. Mechanics: new `fluffychat-web-imaging` derivation in the `let` block: - src: `fetchurl` from pub.dev's `native_imaging-0.4.0.tar.gz` (hash sha256-ztessYuApDFXjJBo65w+51+N85SR6K2vRxY1usKC1lE=) - nativeBuildInputs: emscripten + cmake + gnumake + jq - buildPhase: `cd js && make Imaging.js Imaging.wasm` (`HOME` + `EM_CACHE` set in TMPDIR so emscripten's sysroot builds work in the sandbox — standard nixpkgs pattern for emcc-using derivations, see pkgs/top-level/emscripten-packages.nix) - installPhase: `install -m 644` the two output files Closure cost: build-time only — `pkgs.emscripten` is ~3.6 GiB (LLVM + toolchain). Runtime closure is just the two produced files, nothing emscripten-shaped survives into the deployed dist. `postInstall` in `fluffychat-web-fixed` now references `${fluffychat-web-imaging}` for the install copies, replacing the previous reference to the deleted `fluffychat-web-imaging-prebuilt` runCommandLocal. Verified the emscripten build runs cleanly against the Makefile: $ nix-build test-imaging-built.nix ... emcc -s MODULARIZE=1 -s ALLOW_MEMORY_GROWTH=1 -O3 --closure 1 ... cache:INFO: generating system library: sysroot/lib/.../libstubs.a ... cache:INFO: generating system library: sysroot/lib/.../libc.a ... cache:INFO: generating system library: sysroot/lib/.../libc++-noexcept.a ... cache:INFO: generating system library: sysroot/lib/.../libc++abi-noexcept.a ... make: Nothing to be done for 'Imaging.wasm'. buildPhase completed in 52 seconds /nix/store/x5ds7rkrgfgyy3gb1lk44ak8mkdvdx0p-fluffychat-web-imaging-0.4.0 $ ls /nix/store/.../fluffychat-web-imaging-0.4.0/ Imaging.js Imaging.wasm $ stat -c '%s' .../Imaging.js .../Imaging.wasm 9956 67363 Matches the upstream prebuilt byte-counts (9936 + 67770 — small delta from different emscripten / closure-compiler versions). --- nix/modules/hive-matrix.nix | 149 ++++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 49 deletions(-) diff --git a/nix/modules/hive-matrix.nix b/nix/modules/hive-matrix.nix index f748fa28..c845bb9b 100644 --- a/nix/modules/hive-matrix.nix +++ b/nix/modules/hive-matrix.nix @@ -9,49 +9,101 @@ let hyperhiveDomain = config.services.hyperhive.domain; effectiveServerName = if cfg.serverName != null then cfg.serverName else hyperhiveDomain; - # Two files are missing from nixpkgs's `pkgs.fluffychat-web` dist - # because `flutter341.buildFlutterApplication` doesn't run the - # native_imaging package's emscripten build (#685): + # Three files are missing from nixpkgs's `pkgs.fluffychat-web` dist + # because `flutter341.buildFlutterApplication` doesn't run the dart + # web-worker compile pass + doesn't run the native_imaging package's + # emscripten build (#685): # - # - Imaging.js / Imaging.wasm ← emscripten-compiled C library - # from the native_imaging dart package (vendored by Famedly). - # The package ships only C source + a Makefile that builds - # them via emcc; pulling in `pkgs.emscripten` to run that - # mid-build adds ~600 MB of closure for two files we can pin - # to the upstream release tarball's prebuilt copies (same - # fluffychat release version → byte-identical output). + # - native_executor.js ← flutter web worker entry, compiled + # from web/native_executor.dart via + # `dart compile js` (handled inline + # in `fluffychat-web-fixed.postInstall` + # below — dart SDK is already in the + # flutter341 closure) # - # `native_executor.js` is the other missing file (web worker entry - # point), but that one compiles cleanly from source via - # `dart compile js` — handled in `fluffychat-web-fixed` below - # rather than vendored, since the dart SDK is already in the - # flutter341 closure. - fluffychat-web-imaging-prebuilt = - pkgs.runCommandLocal "fluffychat-web-imaging-prebuilt-${pkgs.fluffychat-web.version}" - { - src = pkgs.fetchurl { - url = "https://github.com/krille-chan/fluffychat/releases/download/v${pkgs.fluffychat-web.version}/fluffychat-web.tar.gz"; - # v2.6.0 prebuilt tarball; bump in lockstep with - # `pkgs.fluffychat-web.version` on any flutter upgrade. - hash = "sha256-P3Bt5FZ5TPeE0k05gYxLw7FdEyyi8g5A/r7tGZMezQk="; - }; - } - '' - mkdir -p $out - tar -xzf $src --strip-components=2 -C $out \ - build/web/Imaging.js build/web/Imaging.wasm - ''; + # - Imaging.js / Imaging.wasm ← emscripten-compiled C library from + # the native_imaging dart package + # (vendored by Famedly). The package + # ships C source + a Makefile that + # builds them via emcc; nixpkgs's + # flutter builder doesn't run that + # pipeline. Built from source via + # `fluffychat-web-imaging` below + # (per mara's #685 call: "fix the + # compile … dont use the prebuilt + # binary"). + # + # When `flutter341.buildFlutterApplication` grows worker + emcc + # support upstream, drop both this derivation and the postInstall. + + # Imaging.{js,wasm} built from source: native_imaging's `js/Makefile` + # runs `emcmake cmake` → `make -C build` → `emcc` to produce the + # emscripten-wrapped C library that fluffychat's main.dart.js + # references at runtime. + # + # Source: pub.dev `native_imaging` v0.4.0 tarball — same provenance + # as fluffychat-web's pubspec.lock-resolved native_imaging dependency + # (both pin 0.4.0, both fetch from pub.dev). When fluffychat's + # pubspec.lock bumps native_imaging, bump the version + hash here. + # + # Closure cost: `pkgs.emscripten` is ~3.6 GiB build-time (LLVM + + # toolchain). Runtime closure is only the two produced files — + # nothing emscripten-shaped survives into the deployed dist. + fluffychat-web-imaging = pkgs.stdenv.mkDerivation rec { + pname = "fluffychat-web-imaging"; + version = "0.4.0"; + + src = pkgs.fetchurl { + url = "https://pub.dev/packages/native_imaging/versions/${version}.tar.gz"; + hash = "sha256-ztessYuApDFXjJBo65w+51+N85SR6K2vRxY1usKC1lE="; + }; + + # pub.dev's `.tar.gz` for a dart package unpacks to the working + # directory (no top-level subdir), unlike a normal source tarball. + sourceRoot = "."; + + nativeBuildInputs = with pkgs; [ + emscripten + cmake + gnumake + jq + ]; + + # cmake config runs inside `js/Makefile` (via `emcmake cmake`) — + # skip the default `configurePhase` which would try to invoke + # cmake against the package root and fail (no CMakeLists at top). + dontConfigure = true; + + buildPhase = '' + runHook preBuild + # emscripten needs HOME + a writable cache dir for its sysroot + # build (libc, libc++, etc. compiled to wasm on demand). + export HOME=$TMPDIR + export EM_CACHE=$TMPDIR/.emscriptencache + mkdir -p $EM_CACHE + cd js + make Imaging.js Imaging.wasm + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out + install -m 644 Imaging.js $out/Imaging.js + install -m 644 Imaging.wasm $out/Imaging.wasm + runHook postInstall + ''; + + meta = with pkgs.lib; { + description = "Imaging.js + Imaging.wasm built from the native_imaging dart package for fluffychat-web (#685)"; + homepage = "https://pub.dev/packages/native_imaging"; + license = licenses.agpl3Plus; + }; + }; # `pkgs.fluffychat-web` with #685's three missing files patched # in via postInstall, plus the existing `--base-href "/matrix/"` - # override (#634) for the sub-path mount. The patches sit in our - # tree rather than as a nixpkgs upstream PR because: - # - `dart compile js` for web workers is a `buildFlutterApplication` - # gap that needs an upstream patch, not a per-package one - # - vendoring emscripten output for `native_imaging` is a - # workaround for the same builder gap - # When `flutter341.buildFlutterApplication` grows worker / emcc - # support, drop the postInstall entirely. + # override (#634) for the sub-path mount. fluffychat-web-fixed = pkgs.fluffychat-web.overrideAttrs (old: { # `--base-href "/matrix/"` so relative asset paths resolve # under the sub-path mount (#634). Upstream default is `/`, @@ -77,11 +129,11 @@ let -o $out/native_executor.js \ $src/web/native_executor.dart - # #685: vendor Imaging.{js,wasm} from upstream prebuilt — see - # comment on `fluffychat-web-imaging-prebuilt` above for the - # closure-size rationale vs running emcc here. - install -m 644 ${fluffychat-web-imaging-prebuilt}/Imaging.js $out/Imaging.js - install -m 644 ${fluffychat-web-imaging-prebuilt}/Imaging.wasm $out/Imaging.wasm + # #685: install Imaging.{js,wasm} built from the native_imaging + # dart package's C source via emscripten (see + # `fluffychat-web-imaging` above for the build-time rationale). + install -m 644 ${fluffychat-web-imaging}/Imaging.js $out/Imaging.js + install -m 644 ${fluffychat-web-imaging}/Imaging.wasm $out/Imaging.wasm ''; }); in @@ -283,12 +335,11 @@ in `pkgs.fluffychat-web` rebuilt with `--base-href /matrix/` (#634) and patched via `postInstall` to add the three files `flutter341.buildFlutterApplication` skips: `native_executor.js` - (compiled via `dart compile js`), plus `Imaging.js` and - `Imaging.wasm` (vendored from the upstream release tarball; - they're emscripten output from the `native_imaging` dart - package and the alternative is +~600 MB of `pkgs.emscripten` in - the build closure for two files). See the `let` block in - `nix/modules/hive-matrix.nix` for the full rationale (#685). + (compiled via `dart compile js` from `web/native_executor.dart`), + plus `Imaging.js` + `Imaging.wasm` (built from the + `native_imaging` dart package's C source via `pkgs.emscripten`). + See the `let` block in `nix/modules/hive-matrix.nix` for the + full rationale (#685). ''; description = '' Static web client dist to serve at `/matrix/`. Defaults to