1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#!/usr/bin/env bash
# V -> WebAssembly, for the Flutter web build of the example.
#
# Nothing is installed system-wide. tool/bin/emcc is a DotSlash file pinning
# emscripten by content hash; DotSlash fetches it on first run (~285 MB) and
# caches it under ~/.cache/dotslash. Only `dotslash` itself has to be on PATH.
#
# Output lands in example/web/ and is loaded by a <script> tag in
# example/web/index.html. Re-run after editing src/vflutter.v.
set -euo pipefail
cd "$(dirname "$0")/.."
command -v v >/dev/null || { echo "V compiler not on PATH"; exit 1; }
command -v node >/dev/null || { echo "node not on PATH (emscripten needs it)"; exit 1; }
command -v dotslash >/dev/null || {
echo "dotslash not on PATH — https://dotslash-cli.com/docs/installation/" >&2
exit 1
}
out=example/web
mkdir -p build "$out"
# Fetches on first call, then just prints the cached path.
emcc_path="$(dotslash -- fetch tool/bin/emcc)"
root="$(dirname "$(dirname "$emcc_path")")"
# emcc wants a config file; the DotSlash cache is content-addressed and must
# stay read-only, so the config and the sysroot cache live under build/.
cat > build/emscripten.config <<EOF
LLVM_ROOT = '$root/bin'
BINARYEN_ROOT = '$root'
NODE_JS = '$(command -v node)'
CACHE = '$PWD/build/emcache'
EOF
export EM_CONFIG="$PWD/build/emscripten.config"
# V emits C for the emscripten target; emcc turns that into wasm. -gc none
# matches every other build, so the ownership rules are the same ones the
# native library exercises.
v -os wasm32_emscripten -gc none -o build/vflutter_em.c src/vflutter.v
# GLOBAL_BASE is not cosmetic. V's builtin vmemcpy refuses any copy whose
# source or destination is <= 0xFFFF:
#
# if (n == 0 || (u64)dest <= 0xFFFF || (u64)const_src <= 0xFFFF) return dest;
#
# That is a null-pointer heuristic written for 64-bit desktop, where the low
# 64 KB is never mapped. On wasm32 emscripten packs static data down at
# address ~1300 by default, so every copy out of a string literal silently
# does nothing and V strings come back as runs of zero bytes -- no crash, no
# diagnostic. (It only bites at -O1 and above; at -O0 the data happens to land
# above the threshold, which makes this look like an optimiser bug.) Starting
# static data at 1 MB puts it, and the stack and heap that follow it, clear of
# the guard. Verified by tool/test_wasm.mjs, which round-trips a string.
#
# ENVIRONMENT includes node so the module can be smoke-tested headlessly
# (tool/test_wasm.mjs) without a browser.
dotslash tool/bin/emcc build/vflutter_em.c -O3 -o "$out/vflutter.js" \
-sGLOBAL_BASE=1048576 \
-sMODULARIZE=1 \
-sEXPORT_NAME=createVFlutterModule \
-sENVIRONMENT=web,worker,node \
-sALLOW_MEMORY_GROWTH=1 \
-sEXPORTED_FUNCTIONS='["_vf_init","_vf_add","_vf_greet","_vf_free","_vf_mandelbrot","_malloc","_free"]' \
-sEXPORTED_RUNTIME_METHODS='["ccall","cwrap","UTF8ToString","stringToUTF8","lengthBytesUTF8","HEAPU8"]'
echo "built: $out/vflutter.js ($(stat -c%s "$out/vflutter.js") bytes)," \
"$out/vflutter.wasm ($(stat -c%s "$out/vflutter.wasm") bytes)"
|