diff options
author | stephan <stephan@noemail.net> | 2022-09-29 22:08:22 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-09-29 22:08:22 +0000 |
commit | f71c954cbc07fa0fc8a59e2a8a5a2a32b8e5d95c (patch) | |
tree | 44ceac4d12ee7e382ed6d3c8124fa66996617720 /ext/wasm | |
parent | b0ccf50cbd0430eefaf50f5b6c2485ee8d68d6d4 (diff) | |
download | sqlite-f71c954cbc07fa0fc8a59e2a8a5a2a32b8e5d95c.tar.gz sqlite-f71c954cbc07fa0fc8a59e2a8a5a2a32b8e5d95c.zip |
Add JS infrastructure to ostensibly allow us to customize the wasm imports, which will hypothetically allow us to eliminate the dependency on EM_JS(), but the corresponding Emscripten glue-level feature currently breaks fatally with WASMFS builds so it's disabled.
FossilOrigin-Name: 88d9253b0db5494bf1c9b6d24f22524eeec856b89e64a66ffb30d945f0df21d3
Diffstat (limited to 'ext/wasm')
-rw-r--r-- | ext/wasm/GNUmakefile | 52 | ||||
-rw-r--r-- | ext/wasm/README.md | 1 | ||||
-rw-r--r-- | ext/wasm/api/extern-post-js.js | 2 | ||||
-rw-r--r-- | ext/wasm/api/extern-pre-js.js | 4 | ||||
-rw-r--r-- | ext/wasm/api/pre-js.js | 40 | ||||
-rw-r--r-- | ext/wasm/common/whwasmutil.js | 2 | ||||
-rw-r--r-- | ext/wasm/demo-123.js | 2 | ||||
-rw-r--r-- | ext/wasm/fiddle.make | 7 | ||||
-rw-r--r-- | ext/wasm/wasmfs.make | 21 |
9 files changed, 108 insertions, 23 deletions
diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index ab687d1e4..94cb17a72 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -153,6 +153,10 @@ $(sqlite3-api.js): $(sqlite3-api.jses) $(MAKEFILE) echo "/* END FILE: $$i */"; \ done > $@ +######################################################################## +# --post-js and --pre-js are emcc flags we use to append/prepend JS to +# the generated emscripten module file. +pre-js.js := $(dir.api)/pre-js.js post-js.js := post-js.js CLEAN_FILES += $(post-js.js) post-jses := \ @@ -167,8 +171,28 @@ $(post-js.js): $(post-jses) $(MAKEFILE) echo "/* END FILE: $$i */"; \ done > $@ extern-post-js.js := $(dir.api)/extern-post-js.js -sqlite3.js.flags.--post-js := --post-js=$(post-js.js) --extern-post-js=$(extern-post-js.js) -post-jses.deps := $(post-js.js) $(extern-post-js.js) +extern-pre-js.js := $(dir.api)/extern-pre-js.js +pre-post-common.flags := \ + --post-js=$(post-js.js) \ + --extern-post-js=$(extern-post-js.js) \ + --extern-pre-js=$(extern-pre-js.js) +pre-post-jses.deps := $(post-js.js) \ + $(extern-post-js.js) $(extern-pre-js.js) +######################################################################## +# call-make-pre-js creates rules for pre-js-$(1).js. $1 = the base +# name of the JS file on whose behalf this pre-js is for. +define call-make-pre-js +pre-post-$(1).flags ?= +pre-js-$(1).js: $$(pre-js.js) $$(MAKEFILE) + cp $$(pre-js.js) $$@ + echo "Module[xInstantiateWasm].uri = '$(1).wasm';" >> $$@ +CLEAN_FILES += pre-js-$(1).js +pre-post-$(1).deps := $$(pre-post-jses.deps) pre-js-$(1).js +pre-post-$(1).flags += --pre-js=pre-js-$(1).js +endef +#$(error $(call call-make-pre-js,sqlite3-wasmfs)) +# /post-js and pre-js +######################################################################## ######################################################################## # emcc flags for .c/.o/.wasm/.js. @@ -202,7 +226,7 @@ emcc.exportedRuntimeMethods := \ emcc.jsflags += $(emcc.exportedRuntimeMethods) emcc.jsflags += -sUSE_CLOSURE_COMPILER=0 emcc.jsflags += -sIMPORTED_MEMORY -emcc.environment := -sENVIRONMENT=web +emcc.environment := -sENVIRONMENT=web,worker emcc.jsflags += -sALLOW_MEMORY_GROWTH # emcc: warning: USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code # slowly, see https://github.com/WebAssembly/design/issues/1271 @@ -264,7 +288,6 @@ emcc.jsflags += -sWASM_BIGINT=$(emcc_enable_bigint) # code get confused and cannot load property (namely, the # sqlite3.worker.js generated in conjunction with -sWASMFS). sqlite3.js := sqlite3.js -emcc.jsflags += $(sqlite3.js.flags.--post-js) sqlite3.wasm := sqlite3.wasm sqlite3-wasm.o := $(dir.api)/sqlite3-wasm.o $(sqlite3-wasm.o): emcc.cflags += $(SQLITE_OPT) @@ -276,19 +299,25 @@ jaccwabyt_test.c := $(dir.jacc)/jaccwabyt_test.c # want to test the release builds with those apps, so we cannot simply # elide that file in release builds. That component is critical to the # VFS bindings so needs to be tested along with the core APIs. -define WASM_C_COMPILE +######################################################################## +# call-wasm-c-compile sets up build rules +# for $1.o. $1 must be the name of a C file (with extension). +define call-wasm-c-compile $(1).o := $$(subst .c,.o,$(1)) sqlite3.wasm.obj += $$($(1).o) $$($(1).o): $$(MAKEFILE) $(1) $$(emcc.bin) $$(emcc_opt_full) $$(emcc.flags) $$(emcc.cflags) -c $(1) -o $$@ CLEAN_FILES += $$($(1).o) endef -$(foreach c,$(sqlite3-wasm.c) $(jaccwabyt_test.c),$(eval $(call WASM_C_COMPILE,$(c)))) +$(foreach c,$(sqlite3-wasm.c) $(jaccwabyt_test.c),$(eval $(call call-wasm-c-compile,$(c)))) +$(eval $(call call-make-pre-js,sqlite3)) $(sqlite3.js): $(MAKEFILE) $(sqlite3.wasm.obj) \ EXPORTED_FUNCTIONS.api \ - $(post-jses.deps) + $(pre-post-sqlite3.deps) @echo "Building $@ ..." - $(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) $(emcc.jsflags) $(sqlite3.wasm.obj) + $(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \ + $(emcc.jsflags) $(pre-post-common.flags) $(pre-post-sqlite3.flags) \ + $(sqlite3.wasm.obj) chmod -x $(sqlite3.wasm) $(maybe-wasm-strip) $(sqlite3.wasm) @ls -la $@ $(sqlite3.wasm) @@ -342,8 +371,8 @@ speedtest1-common.eflags += -sALLOW_TABLE_GROWTH speedtest1-common.eflags += -sDYNAMIC_EXECUTION=0 speedtest1-common.eflags += --minify 0 speedtest1-common.eflags += -sEXPORT_NAME=$(sqlite3.js.init-func) -speedtest1-common.eflags += $(sqlite3.js.flags.--post-js) speedtest1-common.eflags += -sWASM_BIGINT=$(emcc_enable_bigint) +speedtest1-common.eflags += $(pre-post-common.flags) speedtest1.exit-runtime0 := -sEXIT_RUNTIME=0 speedtest1.exit-runtime1 := -sEXIT_RUNTIME=1 # Re -sEXIT_RUNTIME=1 vs 0: if it's 1 and speedtest1 crashes, we get @@ -377,11 +406,14 @@ $(speedtest1.js): emcc.cflags+= # the latter (predictably) results in a slightly faster binary, but we're # close enough to the target speed requirements that the 500ms makes a # difference. -$(speedtest1.js): $(MAKEFILE) $(speedtest1.cs) $(post-jses.deps) \ +$(eval $(call call-make-pre-js,speedtest1)) +$(speedtest1.js): $(MAKEFILE) $(speedtest1.cs) \ + $(pre-post-speedtest1.deps) \ EXPORTED_FUNCTIONS.speedtest1 @echo "Building $@ ..." $(emcc.bin) \ $(speedtest1.eflags) $(speedtest1-common.eflags) $(speedtest1.cflags) \ + $(pre-post-speedtest1.flags) \ $(SQLITE_OPT) \ $(speedtest1.exit-runtime0) \ -o $@ $(speedtest1.cs) -lm diff --git a/ext/wasm/README.md b/ext/wasm/README.md index f95001359..103295384 100644 --- a/ext/wasm/README.md +++ b/ext/wasm/README.md @@ -25,6 +25,7 @@ Those parts only need to be run once, but the SDK can be updated using: ``` $ git pull +$ ./emsdk install latest $ ./emsdk activate latest ``` diff --git a/ext/wasm/api/extern-post-js.js b/ext/wasm/api/extern-post-js.js index acb54c3c9..25d2d1b32 100644 --- a/ext/wasm/api/extern-post-js.js +++ b/ext/wasm/api/extern-post-js.js @@ -1,4 +1,4 @@ -/* emscripten-js-addenda.js must be appended to the resulting sqlite3.js +/* extern-post-js.js must be appended to the resulting sqlite3.js file. */ (function(){ /** diff --git a/ext/wasm/api/extern-pre-js.js b/ext/wasm/api/extern-pre-js.js new file mode 100644 index 000000000..26d066d2e --- /dev/null +++ b/ext/wasm/api/extern-pre-js.js @@ -0,0 +1,4 @@ +/* extern-pre-js.js must be prepended to the resulting sqlite3.js + file. This file is currently only used for holding snippets during + test and development. +*/ diff --git a/ext/wasm/api/pre-js.js b/ext/wasm/api/pre-js.js new file mode 100644 index 000000000..f373fecec --- /dev/null +++ b/ext/wasm/api/pre-js.js @@ -0,0 +1,40 @@ +Module['locateFile'] = function(path, prefix) { + return prefix + path; +}; + +/** + Bug warning: this xInstantiateWasm bit must remain disabled + until this bug is resolved or wasmfs won't work: + + https://github.com/emscripten-core/emscripten/issues/17951 +*/ +const xInstantiateWasm = 1 + ? 'emscripten-bug-17951' + : 'instantiateWasm'; +Module[xInstantiateWasm] = function callee(imports,onSuccess){ + imports.foo = function(){}; + console.warn("instantiateWasm() uri =",callee.uri, self.location.href); + const wfetch = ()=>fetch(callee.uri, {credentials: 'same-origin'}); + const loadWasm = WebAssembly.instantiateStreaming + ? function loadWasmStreaming(){ + return WebAssembly.instantiateStreaming(wfetch(), imports) + .then((arg)=>onSuccess(arg.instance, arg.module)); + } + : function loadWasmOldSchool(){ // Safari < v15 + return wfetch() + .then(response => response.arrayBuffer()) + .then(bytes => WebAssembly.instantiate(bytes, imports)) + .then((arg)=>onSuccess(arg.instance, arg.module)); + }; + loadWasm(); + return {}; +}; +/* + It is literally impossible to get the name of a Worker's own script, + so impossible to derive X.wasm from script name X.js. Thus we need, + at build-time, to redifine Module['instantiateWasm'].uri by + appending it to a build-specific copy of this file with the name of + the wasm file. This is apparently why Emscripten hard-codes the name of + the wasm file into their glue scripts. +*/ +Module[xInstantiateWasm].uri = 'sqlite3.wasm'; diff --git a/ext/wasm/common/whwasmutil.js b/ext/wasm/common/whwasmutil.js index 662978b20..8b6dbdd83 100644 --- a/ext/wasm/common/whwasmutil.js +++ b/ext/wasm/common/whwasmutil.js @@ -1538,7 +1538,7 @@ self.WhWasmUtilInstaller = function(target){ - `onload(loadResult,config)`: optional callback. The first argument is the result object from - WebAssembly.instanitate[Streaming](). The 2nd is the config + WebAssembly.instantiate[Streaming](). The 2nd is the config object passed to this function. Described in more detail below. - `imports`: optional imports object for diff --git a/ext/wasm/demo-123.js b/ext/wasm/demo-123.js index 00ea1f5bc..37dc7a7af 100644 --- a/ext/wasm/demo-123.js +++ b/ext/wasm/demo-123.js @@ -21,6 +21,7 @@ */ let logHtml; if(self.window === self /* UI thread */){ + console.log("Running demo from main UI thread."); logHtml = function(cssClass,...args){ const ln = document.createElement('div'); if(cssClass) ln.classList.add(cssClass); @@ -28,6 +29,7 @@ document.body.append(ln); }; }else{ /* Worker thread */ + console.log("Running demo from Worker thread."); logHtml = function(cssClass,...args){ postMessage({ type:'log', diff --git a/ext/wasm/fiddle.make b/ext/wasm/fiddle.make index c3892263a..6ccf8e029 100644 --- a/ext/wasm/fiddle.make +++ b/ext/wasm/fiddle.make @@ -57,10 +57,13 @@ SOAP.js := sqlite3-opfs-async-proxy.js $(dir.fiddle)/$(SOAP.js): $(SOAP.js) cp $< $@ +$(eval $(call call-make-pre-js,fiddle-module)) $(fiddle-module.js): $(MAKEFILE) $(MAKEFILE.fiddle) \ EXPORTED_FUNCTIONS.fiddle EXPORTED_RUNTIME_METHODS.fiddle \ - $(fiddle.cs) $(post-jses.deps) $(dir.fiddle)/$(SOAP.js) - $(emcc.bin) -o $@ $(fiddle.emcc-flags) $(fiddle.cs) + $(fiddle.cs) $(pre-post-fiddle.deps) $(dir.fiddle)/$(SOAP.js) + $(emcc.bin) -o $@ $(fiddle.emcc-flags) \ + $(pre-post-common.flags) $(pre-post-fiddle.flags) \ + $(fiddle.cs) $(maybe-wasm-strip) $(fiddle-module.wasm) gzip < $@ > $@.gz gzip < $(fiddle-module.wasm) > $(fiddle-module.wasm).gz diff --git a/ext/wasm/wasmfs.make b/ext/wasm/wasmfs.make index b93f2ab0c..fa8320e58 100644 --- a/ext/wasm/wasmfs.make +++ b/ext/wasm/wasmfs.make @@ -22,7 +22,7 @@ sqlite3-wasmfs.flags = ######################################################################## # emcc flags for .c/.o. sqlite3-wasmfs.cflags := -sqlite3-wasmfs.cflags += -std=c99 -fPIC -g +sqlite3-wasmfs.cflags += -std=c99 -fPIC sqlite3-wasmfs.cflags += -pthread sqlite3-wasmfs.cflags += -I. -I.. -I$(dir.top) sqlite3-wasmfs.cflags += $(SQLITE_OPT) -DSQLITE_WASM_WASMFS @@ -57,7 +57,6 @@ sqlite3-wasmfs.jsflags += -sIMPORTED_MEMORY #sqlite3-wasmfs.jsflags += -sTOTAL_STACK=4194304 sqlite3-wasmfs.jsflags += -sEXPORT_NAME=$(sqlite3.js.init-func) sqlite3-wasmfs.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr. -sqlite3-wasmfs.jsflags += $(sqlite3.js.flags.--post-js) #sqlite3-wasmfs.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API # Perhaps the wasmfs build doesn't? #sqlite3-wasmfs.jsflags += -sABORTING_MALLOC @@ -70,20 +69,22 @@ sqlite3-wasmfs.jsflags += -sLLD_REPORT_UNDEFINED sqlite3-wasmfs.jsflags += -sMEMORY64=0 sqlite3-wasmfs.jsflags += -sINITIAL_MEMORY=128450560 sqlite3-wasmfs.fsflags := -pthread -sWASMFS -sPTHREAD_POOL_SIZE=2 -sENVIRONMENT=web,worker +# -sPTHREAD_POOL_SIZE values of 2 or higher trigger that bug. sqlite3-wasmfs.jsflags += $(sqlite3-wasmfs.fsflags) -speedtest1-common.eflags += -sEXPORTED_FUNCTIONS=@$(dir.wasm)/EXPORTED_FUNCTIONS.speedtest1 #sqlite3-wasmfs.jsflags += -sALLOW_MEMORY_GROWTH #^^^ using ALLOW_MEMORY_GROWTH produces a warning from emcc: # USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly, # see https://github.com/WebAssembly/design/issues/1271 [-Wpthreads-mem-growth] sqlite3-wasmfs.jsflags += -sWASM_BIGINT=$(emcc_enable_bigint) - +$(eval $(call call-make-pre-js,sqlite3-wasmfs)) +sqlite3-wasmfs.jsflags += $(pre-post-common.flags) $(pre-post-sqlite3-wasmfs.flags) $(sqlite3-wasmfs.js): $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasm.c) $(sqlite3-wasmfs.extra.c) \ - EXPORTED_FUNCTIONS.api $(sqlite3-wasm.js) $(MAKEFILE) $(MAKEFILE.wasmfs) \ - $(post-jses.deps) + EXPORTED_FUNCTIONS.api $(MAKEFILE) $(MAKEFILE.wasmfs) \ + $(pre-post-sqlite3-wasmfs.deps) @echo "Building $@ ..." $(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \ - $(sqlite3-wasmfs.cflags) $(sqlite3-wasmfs.jsflags) $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasmfs.extra.c) + $(sqlite3-wasmfs.cflags) $(sqlite3-wasmfs.jsflags) \ + $(sqlite3-wasmfs.wasm.c) $(sqlite3-wasmfs.extra.c) chmod -x $(sqlite3-wasmfs.wasm) $(maybe-wasm-strip) $(sqlite3-wasmfs.wasm) @ls -la $@ $(sqlite3-wasmfs.wasm) @@ -99,13 +100,15 @@ speedtest1-wasmfs.js := speedtest1-wasmfs.js speedtest1-wasmfs.wasm := $(subst .js,.wasm,$(speedtest1-wasmfs.js)) speedtest1-wasmfs.eflags := $(sqlite3-wasmfs.fsflags) speedtest1-wasmfs.eflags += $(SQLITE_OPT) -DSQLITE_WASM_WASMFS -$(speedtest1-wasmfs.js): $(MAKEFILE) $(MAKEFILE.wasmfs) -#$(speedtest1-wasmfs.js): $(sqlite3-wasmfs.js) +$(eval $(call call-make-pre-js,speedtest1-wasmfs)) $(speedtest1-wasmfs.js): $(speedtest1.cs) $(sqlite3-wasmfs.js) \ + $(MAKEFILE) $(MAKEFILE.wasmfs) \ + $(pre-post-speedtest1-wasmfs.deps) \ EXPORTED_FUNCTIONS.speedtest1 @echo "Building $@ ..." $(emcc.bin) \ $(speedtest1-wasmfs.eflags) $(speedtest1-common.eflags) \ + $(pre-post-speedtest1-wasmfs.flags) \ $(speedtest1.cflags) \ $(sqlite3-wasmfs.cflags) \ -o $@ $(speedtest1.cs) -lm |