Skip to content

Commit

Permalink
wasm32-wasi support (#1179)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhess authored Nov 29, 2023
2 parents 5d5d158 + 0007287 commit af21875
Show file tree
Hide file tree
Showing 15 changed files with 358 additions and 116 deletions.
9 changes: 9 additions & 0 deletions .buildkite/primer-wasm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
agents:
public: "true"
os: "linux"

steps:
- label: ":haskell: :linux: Primer Wasm targets"
command: |
nix develop .#wasm --print-build-logs --command make wasm32-update
nix develop .#wasm --print-build-logs --command make wasm32-test-opt
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ $(targets):
$(MAKE) -C primer-service $@
$(MAKE) -C primer-benchmark $@

wasm32-update:
wasm32-wasi-cabal update

wasm32 = wasm32-build wasm32-build-opt wasm32-configure wasm32-check wasm32-test wasm32-test-opt wasm32-clean

$(wasm32):
$(MAKE) -C primer $@
$(MAKE) -C primer-api $@

weeder:
cabal build all --enable-benchmarks --enable-tests
weeder
Expand All @@ -21,4 +30,4 @@ openapi.json: build
cabal run -v0 primer-service:exe:primer-openapi > $@
openapi-generator-cli validate --recommend -i $@

.PHONY: $(targets) weeder
.PHONY: $(targets) $(wasm32-targets) weeder
37 changes: 36 additions & 1 deletion cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ packages:

optimization: 0

allow-newer: hedgehog-classes:hedgehog
allow-newer: hedgehog-classes:hedgehog,hedgehog-classes:pretty-show,hedgehog:pretty-show

package *
ghc-options: -fwrite-ide-info
Expand All @@ -24,6 +24,10 @@ package primer-api
package primer-service
test-options: "--size-cutoff=32768"

if arch(wasm32)
package tasty
flags: -unix

-- We need a newer version of Selda than what's been released to
-- Hackage, plus some GHC 9.6 fixes from a community fork.
source-repository-package
Expand All @@ -39,3 +43,34 @@ source-repository-package
tag: 54c12169ce8cd46a7b3c698f65cea55e41a13fe6
subdir: selda-sqlite
--sha256: 0q8m8asmb83mpa3j3adlrhc446xif7gv6lql20gv05k33lmbjfhg

-- Wasm workarounds.

-- Upstream requires `happy` at build time, which doesn't work on Wasm
-- targets.
source-repository-package
type: git
location: https://github.com/hackworthltd/pretty-show
tag: 91d119cb0e3c5f7d866589b25158739580c8fc88
--sha256: sha256-mu8Eq0Sg6nCF8C2sXB6ebZcLhz8TVZAbNMiorA7RVc8=

-- Upstream depends on Posix types unavailable in Wasm.
source-repository-package
type: git
location: https://github.com/hackworthltd/semirings
tag: 369f696d9d00fe004b16b0de08888fee7a3d08c3
--sha256: sha256-kkHCp4Y9IqMXGaDyW5UpsmRjy0ZWZkVSo1nOhpgZUQ0=

-- Upstream uses custom setup, which breaks on Wasm.
source-repository-package
type: git
location: https://github.com/cdepillabout/pretty-simple
tag: 6fb9b281800ad045925c7344ceb9fd293d86c3b9
--sha256: sha256-1gsYj/iznEUCeQ1f5Xk7w54h9FLJSNrIR9V3p4eaRYk=

-- Upstream doesn't want to support Wasm while it's "experimental."
source-repository-package
type: git
location: https://github.com/amesgen/splitmix
tag: 83b906c4bcdc2720546f1779a16eb65e8e12ecba
--sha256: sha256-sR+Ne56SBzVbPfC7AJeQZn20YDfFwBDpRI873cTm1nU=
1 change: 1 addition & 0 deletions docs/development-guide-toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ the various packages' Haddocks.
* [Primitives](primitives.md)
* [Database ops](database.md)
* [Benchmarking](benchmarking.md)
* [WebAssembly support](wasm.md)
43 changes: 43 additions & 0 deletions docs/wasm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# WebAssembly (Wasm) support

**Note**: WebAssembly support is currently very preliminary.

For horizontal scalability reasons, we would like to run the `primer`
and `primer-api` packages in the student's browser, rather than on a
backend server. Therefore, we'd like to compile these packages to a
`wasm32-wasi` target and call the (native) Primer API from TypeScript.

Currently, we can compile these two packages to `wasm32-wasi`, but
with the following caveats:

1. Neither `haskell.nix` nor `nixpkgs.haskellPackages` support the
`wasm32-wasi` cross-target at the moment, so we can only build Wasm
targets directly via `wasm32-wasi-cabal` and `wasm32-wasi-ghc`. For
interactive development, we provide a special `nix develop` shell
which provides the necessary tools:

```sh
nix develop .#wasm
```

Note that the required tools are currently only available for
`x86_64-linux` Nix systems, so the special `wasm` Nix shell only
exists for that platform.

2. Once you're in the special Wasm shell, it's advisable to use the
special `wasm32` `Makefile` targets. To build the libraries, run:

```sh
make wasm32-configure
make wasm32-build
```

To build the tests and run them using the `wasmtime` runtime, run:

```sh
make wasm32-test
```

The `wasm32-test`, in particular, needs to run several steps that
you'd otherwise need to run by hand in order to work around
`wasmtime` issues.
95 changes: 82 additions & 13 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
nixpkgs.follows = "haskell-nix/nixpkgs-unstable";
hacknix.inputs.nixpkgs.follows = "nixpkgs";
pre-commit-hooks-nix.inputs.nixpkgs.follows = "nixpkgs";

ghc-wasm.url = "git+https://gitlab.haskell.org/ghc/ghc-wasm-meta";
};

outputs = inputs@ { flake-parts, ... }:
Expand Down Expand Up @@ -305,7 +307,25 @@
})
// primerFlake.apps;

devShells.default = primerFlake.devShell;
devShells = {
default = primerFlake.devShell;
} // (pkgs.lib.optionalAttrs (system == "x86_64-linux")) {
# Unfortunately, this is only available on x86_64-linux.
wasm = pkgs.mkShell {
packages = with inputs.ghc-wasm.packages.${system};
[
wasm32-wasi-ghc-9_6
wasm32-wasi-cabal-9_6
wasmtime

pkgs.gnumake

# We need to run native `tasty-discover` at compile
# time, because we can't do it via `wasmtime`.
(pkgs.haskell-nix.tool ghcVersion "tasty-discover" { })
];
};
};

# This is a non-standard flake output, but we don't want to
# include benchmark runs in `packages`, because we don't
Expand Down
1 change: 1 addition & 0 deletions primer-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/TestsWasm32.hs
28 changes: 26 additions & 2 deletions primer-api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,47 @@
# Most commands assume you're running this from the top-level `nix
# develop` shell.

wasm32-primer-api-test := $(shell wasm32-wasi-cabal list-bin -v0 test:primer-api-test)
wasm32-primer-api-test-opt := $(shell wasm32-wasi-cabal list-bin -O2 -v0 test:primer-api-test)

build:
cabal build

wasm32-build:
wasm32-wasi-cabal build

wasm32-build-opt:
wasm32-wasi-cabal build -O2

configure:
cabal configure

wasm32-configure:
wasm32-wasi-cabal configure

check: test

test:
cabal test
wasm32-check: wasm32-test

wasm32-test:
tasty-discover test/Test.hs _ test/TestsWasm32.hs --tree-display
wasm32-wasi-cabal build test:primer-api-test
wasmtime --dir test::test "$(wasm32-primer-api-test)"

wasm32-test-opt: wasm32-build-opt
tasty-discover test/Test.hs _ test/TestsWasm32.hs --tree-display
wasm32-wasi-cabal build -O2 test:primer-api-test
wasmtime --dir test::test "$(wasm32-primer-api-test-opt)"

docs:
cabal haddock

clean:
cabal clean

wasm32-clean:
wasm32-wasi-cabal clean

bench:

realclean:
Expand Down
Loading

1 comment on commit af21875

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Primer benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: af21875 Previous: 5d5d158 Ratio
evalTestM/discard logs/mapEven 1: outlier variance 0.09309383264333644 outlier variance 0.02498356344510187 outlier variance 3.73

This comment was automatically generated by workflow using github-action-benchmark.

CC: @dhess

Please sign in to comment.