diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/wasm/GNUmakefile | 244 | ||||
-rw-r--r-- | ext/wasm/c-pp.c | 3 | ||||
-rwxr-xr-x | ext/wasm/make-make.sh | 98 | ||||
-rw-r--r-- | ext/wasm/mkwasmbuilds.c | 216 | ||||
-rw-r--r-- | ext/wasm/speedtest1-wasmfs.mjs | 12 | ||||
-rw-r--r-- | ext/wasm/wasmfs.make | 21 |
6 files changed, 314 insertions, 280 deletions
diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index 50fedfef7..e40db6a5f 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -56,8 +56,8 @@ ifeq (,$(SHELL)) $(error Cannot find the bash shell) endif MAKEFILE := $(lastword $(MAKEFILE_LIST)) -CLEAN_FILES := .gen.make -DISTCLEAN_FILES := ./--dummy-- +CLEAN_FILES := +DISTCLEAN_FILES := MAKING_CLEAN := $(if $(filter %clean,$(MAKECMDGOALS)),1,0) .PHONY: clean distclean clean: @@ -111,14 +111,13 @@ dir.common := common dir.fiddle := fiddle dir.fiddle-debug := fiddle-debug dir.tool := $(dir.top)/tool -# Maintenance reminder: the names of $(dir.dout) and $(dir.tmp) must -# stay in sync with make-make.sh -# +# dir.dout = output dir for deliverables +dir.dout := $(dir.wasm)/jswasm # dir.tmp = output dir for intermediary build files, as opposed to # end-user deliverables. -dir.dout := $(dir.wasm)/jswasm -# dir.dout = output dir for deliverables dir.tmp := $(dir.wasm)/bld +dir.wasmfs := $(dir.dout) + CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \ $(dir.fiddle-debug)/* $(dir.dout)/* $(dir.tmp)/* @@ -143,6 +142,13 @@ sqlite3.canonical.c := $(dir.top)/sqlite3.c sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c)) sqlite3.h := $(dir.top)/sqlite3.h +ifeq (,$(shell grep sqlite3_activate_see $(sqlite3.c))) + SQLITE_C_IS_SEE := 0 +else + SQLITE_C_IS_SEE := 1 + $(info This is an SEE build) +endif + ########################################################################@ # It's important that sqlite3.h be built to completion before any # other parts of the build run, thus we use .NOTPARALLEL to disable @@ -152,27 +158,51 @@ $(sqlite3.h): $(MAKE) -C $(dir.top) sqlite3.c $(sqlite3.c): $(sqlite3.h) -######################################################################## -# .gen.make is generated by a shell script and holds certain parts -# of the makefile, some of which are relatively expensive to calculate -# on each run (that is, they can take a human-visible amount of time). -# -# Sidebar: three attempts have been made to move much of the -# $(eval)-generated makefile code into make-make.sh but the result is -# even less legible/maintainable than make-side $(eval). -ifeq (0,$(MAKING_CLEAN)) -.gen.make: $(MAKEFILE) $(sqlite3.c) - rm -f $@ - $(SHELL) make-make.sh $(sqlite3.c) > $@ - chmod -w $@ --include .gen.make -endif - ifeq (,$(filter release snapshot,$(MAKECMDGOALS))) $(info Development build. Use 'release' or 'snapshot' target for a smaller release build.) endif ######################################################################## +# Find emcc (Emscripten compiler)... +emcc.bin := $(shell which emcc 2>/dev/null) +ifeq (,$(emcc.bin)) + ifneq (,$(EMSDK_HOME)) + emcc.bin := $(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) + endif + ifeq (,$(emcc.bin)) + $(error Cannot find emcc in path.) + endif +endif +emcc.version := $(shell $(emcc.bin) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;') +$(info using emcc version [$(emcc.version)]) +######################################################################### +# Find wasm-strip, which we need for release builds (see below for +# why) but not strictly for non-release builds. +wasm-strip.bin ?= $(shell which wasm-strip 2>/dev/null) +ifeq (,$(wasm-strip.bin)) + ifeq (,$(filter clean,$(MAKECMDGOALS))) + $(info WARNING: *******************************************************************) + $(info WARNING: builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,) + $(info WARNING: breaking _All The Things_. The workaround for that is to build) + $(info WARNING: with -g3 (which explodes the file size) and then strip the debug) + $(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.) + $(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.) + $(info WARNING: If this build uses any optimization level higher than -O1 then) + $(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.) + $(info WARNING: wasm-strip is part of the wabt package:) + $(info WARNING: https://github.com/WebAssembly/wabt) + $(info WARNING: on Ubuntu-like systems it can be installed with:) + $(info WARNING: sudo apt install wabt) + $(info WARNING: *******************************************************************) + endif + ifneq (,$(filter release snapshot,$(MAKECMDGOALS))) + $(error Cannot make release-quality binary because wasm-strip is not available.) + endif + wasm-strip.bin := echo "not wasm-stripping" +endif +maybe-wasm-strip := $(wasm-strip.bin) + +######################################################################## # barebones=1 disables all "extraneous" stuff from sqlite3-wasm.c, the # goal being to create a WASM file with only the core APIs. ifeq (1,$(barebones)) @@ -332,6 +362,18 @@ $(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE) $(CC) -o $@ $< DISTCLEAN_FILES += $(bin.stripccomments) +######################################################################## +# bin.mkwb is used for generating some of the makefile code for the +# various build builds. It used to be generated in this makefile via a +# difficult-to-read/maintain block of $(eval)'d code. Attempts were +# made to generate it from tcl and bash (shell) but having to escape +# the $ references in those languages made it just as illegible as the +# native makefile code. Somewhat surprisingly, moving that code generation +# to C makes it slightly less illegible than the previousq 3 options. +bin.mkwb := ./mkwasmbuilds +$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE) + $(CC) -o $@ $< +DISTCLEAN_FILES += $(bin.mkwb) ######################################################################## # C-PP.FILTER: a $(call)able to transform $(1) to $(2) via: @@ -749,55 +791,6 @@ $(post-js.js.in): $(post-jses.js) $(MAKEFILE) done > $@ -######################################################################## -# call-make-pre-post is a $(call)able which creates rules for -# pre-js.$(1)-$(2).js. $1 = the base name of the JS file on whose -# behalf this pre-js is for (one of: $(JS_BUILD_NAMES)). $2 is -# the build mode: one of $(JS_BUILD_MODES). This sets up -# --[extern-][pre/post]-js flags in $(pre-post-$(1)-$(2).flags) and -# dependencies in $(pre-post-$(1)-$(2).deps). The resulting files get -# filtered using $(C-PP.FILTER). Any flags necessary for such -# filtering need to be set in $(c-pp.D.$(1)-$(2)) before $(call)ing -# this. -# -# Maintenance note: a shell script was written to generate these rules -# with the hope that it would make them more legible and maintainable, -# but embedding makefile code in another language makes it even less -# legible than having the level of $(eval) indirection which we have -# here. -define call-make-pre-post -pre-post-$(1)-$(2).flags ?= -pre-js.js.$(1)-$(2).intermediary := $$(dir.tmp)/pre-js.$(1)-$(2).intermediary.js -pre-js.js.$(1)-$(2) := $$(dir.tmp)/pre-js.$(1)-$(2).js -#$$(error $$(pre-js.js.$(1)-$(2).intermediary) $$(pre-js.js.$(1)-$(2))) -$$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)-$(2).intermediary),$$(c-pp.D.$(1)-$(2)))) -post-js.js.$(1)-$(2) := $$(dir.tmp)/post-js.$(1)-$(2).js -$$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2)))) -extern-post-js.js.$(1)-$(2) := $$(dir.tmp)/extern-post-js.$(1)-$(2).js -$$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)-$(2)),$$(c-pp.D.$(1)-$(2)))) -pre-post-common.flags.$(1)-$(2) := \ - $$(pre-post-common.flags) \ - --post-js=$$(post-js.js.$(1)-$(2)) \ - --extern-post-js=$$(extern-post-js.js.$(1)-$(2)) -pre-post-jses.$(1)-$(2).deps := $$(pre-post-jses.deps.common) \ - $$(post-js.js.$(1)-$(2)) $$(extern-post-js.js.$(1)-$(2)) -$$(pre-js.js.$(1)-$(2)): $$(pre-js.js.$(1)-$(2).intermediary) $$(MAKEFILE) - cp $$(pre-js.js.$(1)-$(2).intermediary) $$@ - @if [ sqlite3-wasmfs = $(1) ]; then \ - echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \ - elif [ sqlite3 != $(1) ]; then \ - echo "Module[xNameOfInstantiateWasm].uri = '$(1).wasm';"; \ - fi >> $$@ -pre-post-$(1)-$(2).deps := \ - $$(pre-post-jses.$(1)-$(2).deps) \ - $$(dir.tmp)/pre-js.$(1)-$(2).js -pre-post-$(1)-$(2).flags += \ - $$(pre-post-common.flags.$(1)-$(2)) \ - --pre-js=$$(dir.tmp)/pre-js.$(1)-$(2).js -endef -# /post-js and pre-js -######################################################################## - # Undocumented Emscripten feature: if the target file extension is # "mjs", it defaults to ES6 module builds: # https://github.com/emscripten-core/emscripten/issues/14383 @@ -811,11 +804,14 @@ sqlite3-wasmfs.cfiles := $(sqlite3-wasm.cfiles) # difference, so we build all binaries against sqlite3-wasm.c instead # of building a shared copy of sqlite3-wasm.o to link against. ######################################################################## -# SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and -# SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid code -# duplication. $1 is 1 if the build mode needs this workaround (esm, -# bundler-friendly, node) and 0 if not (vanilla). $2 must be empty for -# all builds except sqlite3-wasmfs.mjs, in which case it must be 1. + +######################################################################## +# SQLITE3.xJS.ESM-EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE +# and SETUP_LIB_BUILD_MODE, factored into a separate piece to avoid +# code duplication. $1 is 1 if the build mode needs this workaround +# (esm, bundler-friendly, node) and 0 if not (vanilla). $2 must be +# 0 for all builds except sqlite3-wasmfs.mjs, in which case it +# must be 1. # # Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_ # adds: @@ -838,7 +834,7 @@ if [ x1 = x$(1) ]; then \ {\ awk '/^export default/ && !f{f=1; next} 1' $@ > $@.tmp && mv $@.tmp $@; \ } || exit $$?; \ - if [ x != x$(2) ]; then \ + if [ x1 = x$(2) ]; then \ if ! grep -q '^export default' $@; then \ echo "Cannot find export default." 1>&2; \ exit 1; \ @@ -847,78 +843,6 @@ if [ x1 = x$(1) ]; then \ fi endef -######################################################################## -# extern-post-js* and extern-pre-js* are files for use with -# Emscripten's --extern-pre-js and --extern-post-js flags. -extern-pre-js.js := $(dir.api)/extern-pre-js.js -extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js -# Emscripten flags for --[extern-][pre|post]-js=... for the -# various builds. -pre-post-common.flags := \ - --extern-pre-js=$(sqlite3-license-version.js) -# pre-post-jses.deps.* = a list of dependencies for the -# --[extern-][pre/post]-js files. -pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js) - -######################################################################## -# SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces -# for one of the build modes. -# -# $1 = one of: $(JS_BUILD_NAMES) -# $2 = build mode name: one of $(JS_BUILD_MODES) -# $3 = 1 for ESM build mode, else 0 -# $4 = resulting sqlite-api JS/MJS file -# $5 = resulting JS/MJS file -# $6 = -D... flags for $(bin.c-pp) -# $7 = optional extra flags for emcc -# -# Maintenance reminder: be careful not to introduce spaces around args -# ($1, $2), otherwise string concatenation will malfunction. -# -# Before calling this, emcc.environment.$(2) must be set to a value -# for emcc's -sENVIRONMENT flag. -# -# $(cflags.$(1)) and $(cflags.$(1).$(2)) may be defined to append -# CFLAGS to a given build mode. -# -# $(emcc.flags.$(1)) and $(emcc.flags.$(1).$(2)) may be defined to -# append emcc-specific flags to a given build mode. -define SETUP_LIB_BUILD_MODE -$(info Setting up build [$(1)-$(2)]: $(5)) -c-pp.D.$(1)-$(2) := $(6) -$$(eval $$(call call-make-pre-post,$(1),$(2))) -emcc.flags.$(1).$(2) ?= -emcc.flags.$(1).$(2) += $(7) -$$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(4), $(6))) -$(5): $(4) $$(MAKEFILE) $$(sqlite3-wasm.cfiles) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-$(1)-$(2).deps) - @echo "Building $$@ ..." - $$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \ - $$(emcc.jsflags) \ - -sENVIRONMENT=$$(emcc.environment.$(2)) \ - $$(pre-post-$(1)-$(2).flags) \ - $$(emcc.flags.$(1)) $$(emcc.flags.$(1).$(2)) \ - $$(cflags.common) $$(SQLITE_OPT) \ - $$(cflags.$(1)) $$(cflags.$(1).$(2)) \ - $$(cflags.wasm_extra_init) $$(sqlite3-wasm.cfiles) - @$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(3)) - @dotwasm=$$(basename $$@).wasm; \ - chmod -x $$$$dotwasm; \ - $(maybe-wasm-strip) $$$$dotwasm; \ - case $(2) in \ - bundler-friendly|node) \ - echo "Patching $$@ for $(1).wasm..."; \ - rm -f $$$$dotwasm; \ - dotwasm=; \ - sed -i -e 's/$(1)-$(2).wasm/$(1).wasm/g' $$@ || exit $$$$?; \ - ;; \ - esac; \ - ls -la $$$$dotwasm $$@ -all: $(5) -#quick: $(5) -#CLEAN_FILES += $(4) $(5) -endef -# ^^^ /SETUP_LIB_BUILD_MODE -######################################################################## sqlite3-api.js := $(dir.dout)/sqlite3-api.js sqlite3.js := $(dir.dout)/sqlite3.js sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs @@ -927,17 +851,14 @@ sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs sqlite3-api-node.mjs := $(dir.dout)/sqlite3-api-node.mjs sqlite3-node.mjs := $(dir.dout)/sqlite3-node.mjs -#$(info $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0, $(sqlite3-api.js), $(sqlite3.js))) -$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,vanilla,0,\ - $(sqlite3-api.js), $(sqlite3.js))) -$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,esm,1,\ - $(sqlite3-api.mjs), $(sqlite3.mjs), -Dtarget=es6-module)) -$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,bundler-friendly,1,\ - $(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\ - $(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly)) -$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3,node,1,\ - $(sqlite3-api-node.mjs),$(sqlite3-node.mjs),\ - $(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node)) +sqlite3-api-wasmfs.mjs := $(dir.tmp)/sqlite3-api-wasmfs.mjs +sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs +.wasmbuilds.make: $(bin.mkwb) + @rm -f $@ + $(bin.mkwb) > $@ + @chmod -w $@ +DISTCLEAN_FILES += .wasmbuilds.make +-include .wasmbuilds.make # The various -D... values used by *.c-pp.js include: # # -Dtarget=es6-module: for all ESM module builds @@ -1267,4 +1188,3 @@ endif # Run local web server for the test/demo pages. httpd: althttpd -max-age 1 -enable-sab 1 -page index.html - diff --git a/ext/wasm/c-pp.c b/ext/wasm/c-pp.c index c439a0d09..6815cb845 100644 --- a/ext/wasm/c-pp.c +++ b/ext/wasm/c-pp.c @@ -1,7 +1,8 @@ /* ** 2022-11-12: ** -** In place of a legal notice, here is a blessing: +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: ** ** * May you do good and not evil. ** * May you find forgiveness for yourself and forgive others. diff --git a/ext/wasm/make-make.sh b/ext/wasm/make-make.sh deleted file mode 100755 index 6f93d8883..000000000 --- a/ext/wasm/make-make.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/bash -######################################################################## -# Emits the makefile code for .cache.make. Any makefile bits which are -# potentially expensive to calculate on every build but rarely change -# should be emitted from here. -# -# Arguments: -# -# $1 = path to sqlite3.c. Default: ../../sqlite3.c -# -######################################################################## - -function die(){ - local rc=$1 - shift - echo "\$(error $0 failed: $@)" - # ^^^ Ensure that if this output is being redirected, the - # resulting makefile will fail loudly instead of just being - # truncated. - echo "Error: $@" 1>&2 - exit $rc -} - -SQLITE3_C="${1-../../sqlite3.c}" - -separator='########################################################################' - -cat <<EOF -# GENERATED makefile code. DO NOT EDIT. -# Generated by $0 on $(date) -_GEN_MAKE := \$(lastword \$(MAKEFILE_LIST)) -\$(_GEN_MAKE): ${SQLITE3_C} $0 -EOF - -if grep sqlite3_activate_see "$SQLITE3_C" &>/dev/null; then - echo 'SQLITE_C_IS_SEE := 1' - echo '$(info This is an SEE build)' -else - echo 'SQLITE_C_IS_SEE := 0' -fi - -######################################################################## -# Locate the emcc (Emscripten) binary... -echo $separator -EMCC_BIN=$(which emcc) -if [[ x = "x${EMCC_BIN}" ]]; then - if [[ x != "x${EMSDK_HOME}" ]]; then - EMCC_BIN="${EMSDK_HOME}/upstream/emscripten/emcc" - fi -fi -if [[ x = "x${EMCC_BIN}" ]]; then - die 1 "Cannot find emcc binary in PATH or EMSDK_HOME." -fi -[[ -x "${EMCC_BIN}" ]] || die 1 "emcc is not executable" -echo "emcc.bin := ${EMCC_BIN}" -echo "emcc.version :=" $("${EMCC_BIN}" --version | sed -n 1p \ - | sed -e 's/^.* \([3-9][^ ]*\) .*$/\1/;') -echo '$(info using emcc version [$(emcc.version)])' - -######################################################################### -# wasm-strip binary... -echo $separator -WASM_STRIP_BIN=$(which wasm-strip 2>/dev/null) -echo "wasm-strip ?= ${WASM_STRIP_BIN}" -if [[ x = "x${WASM_STRIP_BIN}" ]]; then -cat <<EOF -maybe-wasm-strip = echo "not wasm-stripping" -ifeq (,\$(filter clean,\$(MAKECMDGOALS)))' - \$(info WARNING: *******************************************************************) - \$(info WARNING: builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,) - \$(info WARNING: breaking _All The Things_. The workaround for that is to build) - \$(info WARNING: with -g3 (which explodes the file size) and then strip the debug) - \$(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.) - \$(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.) - \$(info WARNING: If this build uses any optimization level higher than -O1 then) - \$(info WARNING: the ***resulting JS code WILL NOT BE USABLE***.) - \$(info WARNING: wasm-strip is part of the wabt package:) - \$(info WARNING: https://github.com/WebAssembly/wabt) - \$(info WARNING: on Ubuntu-like systems it can be installed with:) - \$(info WARNING: sudo apt install wabt) - \$(info WARNING: *******************************************************************) -endif -ifneq (,\$(filter release snapshot,\$(MAKECMDGOALS))) - \$(error Cannot make release-quality binary because wasm-strip is not available.) -endif -EOF -else -echo 'maybe-wasm-strip = $(wasm-strip)' -fi -# /$(wasm-strip) -######################################################################## - -######################################################################## -# Make necessary dirs. Note that these need to align with their names -# in the main makefile. -for d in jswasm bld; do - [ -d $d ] || mkdir -p $d -done diff --git a/ext/wasm/mkwasmbuilds.c b/ext/wasm/mkwasmbuilds.c new file mode 100644 index 000000000..6f1488319 --- /dev/null +++ b/ext/wasm/mkwasmbuilds.c @@ -0,0 +1,216 @@ +/* +** 2024-09-23 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This app's single purpose is to emit parts of the Makefile code for +** building sqlite3's WASM build. The main motivation is to generate +** code which "can" be created via GNU Make's eval command but is +** highly illegible when built that way. Attempts to write this app in +** Bash and TCL have failed because both require escaping $ symbols, +** making the resulting script code as illegible as the eval spaghetti +** we want to get away from. Writing it in C is, somewhat +** surprisingly, _slightly_ less illegible than writing it in bash, +** tcl, or native Make code. +** +** The emitted makefile code is not standalone - it depends on +** variables and $(call)able functions from the main makefile. +** +*/ + +#undef NDEBUG +#define DEBUG 1 +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#define pf printf +#define ps puts +/* Very common printf() args combo. */ +#define zNM zName, zMode + +/* +** Valid names for the zName arguments. +*/ +#define JS_BUILD_NAMES sqlite3 sqlite3-wasmfs +/* +** Valid names for the zMode arguments. +*/ +#define JS_BUILD_MODES vanilla esm bundler-friendly node + +/* +** Emits common vars needed by the rest of the emitted code (but not +** needed by code outside of these generated pieces). +*/ +static void mk_prologue(void){ + ps("########################################################################"); + ps("# extern-post-js* and extern-pre-js* are files for use with"); + ps("# Emscripten's --extern-pre-js and --extern-post-js flags."); + ps("extern-pre-js.js := $(dir.api)/extern-pre-js.js"); + ps("extern-post-js.js.in := $(dir.api)/extern-post-js.c-pp.js"); + ps("# Emscripten flags for --[extern-][pre|post]-js=... for the"); + ps("# various builds."); + ps("pre-post-common.flags := --extern-pre-js=$(sqlite3-license-version.js)"); + ps("# pre-post-jses.deps.* = a list of dependencies for the"); + ps("# --[extern-][pre/post]-js files."); + ps("pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js)"); +} + +/* +** Emits makefile code for setting up values for the --pre-js=FILE, +** --post-js=FILE, and --extern-post-js=FILE emcc flags, as well as +** populating those files. +*/ +static void mk_pre_post(const char *zName, const char *zMode){ + pf("pre-post-%s-%s.flags ?=\n", zNM); + + /* --pre-js=... */ + pf("pre-js.js.%s-%s.intermediary := $(dir.tmp)/pre-js.%s-%s.intermediary.js\n", + zNM, zNM); + pf("pre-js.js.%s-%s := $(dir.tmp)/pre-js.%s-%s.js\n", + zNM, zNM); + pf("$(eval $(call C-PP.FILTER,$(pre-js.js.in),$(pre-js.js.%s-%s.intermediary)," + "$(c-pp.D.%s-%s)))\n", zNM, zNM); + + /* --post-js=... */ + pf("post-js.js.%s-%s := $(dir.tmp)/post-js.%s-%s.js\n", zNM, zNM); + pf("$(eval $(call C-PP.FILTER,$(post-js.js.in)," + "$(post-js.js.%s-%s),$(c-pp.D.%s-%s)))\n", zNM, zNM); + + /* --extern-post-js=... */ + pf("extern-post-js.js.%s-%s := $(dir.tmp)/extern-post-js.%s-%s.js\n", zNM, zNM); + pf("$(eval $(call C-PP.FILTER,$(extern-post-js.js.in),$(extern-post-js.js.%s-%s)," + "$(c-pp.D.%s-%s)))\n", zNM, zNM); + + /* Combine flags for use with emcc... */ + pf("pre-post-common.flags.%s-%s := " + "$(pre-post-common.flags) " + "--post-js=$(post-js.js.%s-%s) " + "--extern-post-js=$(extern-post-js.js.%s-%s)\n", zNM, zNM, zNM); + + pf("pre-post-%s-%s.flags += $(pre-post-common.flags.%s-%s) " + "--pre-js=$(pre-js.js.%s-%s)\n", zNM, zNM, zNM); + + pf("$(pre-js.js.%s-%s): $(pre-js.js.%s-%s.intermediary) $(MAKEFILE)\n", + zNM, zNM); + pf("\tcp $(pre-js.js.%s-%s.intermediary) $@\n", zNM); + /* Amend $(pre-js.js.zName-zMode) for all targets except the plain + "sqlite3" build... */ + if( 0==strcmp("sqlite3-wasmfs", zName) ){ + pf("\t@echo 'delete Module[xNameOfInstantiateWasm]; /" + "* for %s build *" "/' >> $@\n", zName); + }else if( 0!=strcmp("sqlite3", zName) ){ + pf("\t@echo 'Module[xNameOfInstantiateWasm].uri = \"$(1).wasm\";' >> $@\n"); + } + + /* Set up deps... */ + pf("pre-post-jses.%s-%s.deps := $(pre-post-jses.deps.common) " + "$(post-js.js.%s-%s) $(extern-post-js.js.%s-%s)\n", + zNM, zNM, zNM); + pf("pre-post-%s-%s.deps := $(pre-post-jses.%s-%s.deps) $(dir.tmp)/pre-js.%s-%s.js\n", + zNM, zNM, zNM); +} + +/* +** Emits makefile code for one build of the library, primarily defined +** by the combination of zName and zMode, each of which must be values +** from JS_BUILD_NAMES resp. JS_BUILD_MODES. +*/ +static void mk_lib_mode(const char *zName /* build name */, + const char *zMode /* build mode */, + int bIsEsm /* true only for ESM build */, + const char *zApiJsOut /* name of generated sqlite3-api.js/.mjs */, + const char *zJsOut /* name of generated sqlite3.js/.mjs */, + const char *zCmppD /* extra -D flags for c-pp */, + const char *zEmcc /* extra flags for emcc */){ + assert( zName ); + assert( zMode ); + assert( zApiJsOut ); + assert( zJsOut ); + if( !zCmppD ) zCmppD = ""; + if( !zEmcc ) zEmcc = ""; + + pf("#################### begin build [%s-%s]\n", zNM); + pf("$(info Setting up build [%s-%s]: %s)\n", zNM, zJsOut); + pf("c-pp.D.%s-%s := %s\n", zNM, zCmppD); + mk_pre_post(zNM); + pf("emcc.flags.%s.%s ?=\n", zNM); + if( zEmcc[0] ){ + pf("emcc.flags.%s.%s += %s\n", zNM, zEmcc); + } + pf("$(eval $(call C-PP.FILTER, $(sqlite3-api.js.in), %s, %s))\n", + zApiJsOut, zCmppD); + + /* target zJsOut */ + pf("%s: %s $(MAKEFILE) $(sqlite3-wasm.cfiles) $(EXPORTED_FUNCTIONS.api) " + "$(pre-post-%s-%s.deps)\n", + zJsOut, zApiJsOut, zNM); + pf("\t@echo \"Building $@ ...\"\n"); + pf("\t$(emcc.bin) -o $@ $(emcc_opt_full) $(emcc.flags) \\\n"); + pf("\t\t$(emcc.jsflags) -sENVIRONMENT=$(emcc.environment.%s) \\\n", zMode); + pf("\t\t$(pre-post-%s-%s.flags) \\\n", zNM); + pf("\t\t$(emcc.flags.%s) $(emcc.flags.%s.%s) \\\n", zName, zNM); + pf("\t\t$(cflags.common) $(SQLITE_OPT) \\\n" + "\t\t$(cflags.%s) $(cflags.%s.%s) \\\n" + "\t\t$(cflags.wasm_extra_init) $(sqlite3-wasm.cfiles)\n", zName, zNM); + if( bIsEsm ){ + /* TODO? Replace this CALL with the corresponding makefile code. + ** OTOH, we also use this $(call) in the speedtest1-wasmfs build, + ** which is not part of the rules emitted by this program. */ + pf("\t@$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1,%d)\n", + 0==strcmp("sqlite3-wasmfs", zName) ? 1 : 0); + } + pf("\t@dotwasm=$(basename $@).wasm; \\\n" + "\tchmod -x $$dotwasm; \\\n" + "\t$(maybe-wasm-strip) $$dotwasm; \\\n"); + /* + ** The above $(emcc.bin) call will write zJsOut and will create a + ** like-named .wasm file. That .wasm file name gets hard-coded into + ** zJsOut so we need to, for some cases, patch zJsOut to use the + ** name sqlite3.wasm instead. Note that the resulting .wasm file is + ** identical for all builds for which zEmcc is empty. + */ + if( 0==strcmp("bundler-friendly", zMode) + || 0==strcmp("node", zMode) ) { + pf("\techo 'Patching $@ for %s.wasm...' \\\n", zName); + pf("\trm -f $$dotwasm; dotwasm=; \\\n" + "\tsed -i -e 's/%s-%s.wasm/%s.wasm/g' $@ || exit $$?; \\\n", + zNM, zName); + } + pf("\tls -la $$dotwasm $@\n"); + if( 0!=strcmp("sqlite3-wasmfs", zName) ){ + /* The sqlite3-wasmfs build is optional and needs to be invoked + ** conditionally using info we don't have here. */ + pf("all: %s\n", zJsOut); + } + pf("#################### end build [%s-%s]\n\n", zNM); +} + +int main(void){ + int rc = 0; + ps("# What follows was GENERATED by mkwasbuilds.c. Edit at your own risk."); + mk_prologue(); + mk_lib_mode("sqlite3", "vanilla", 0, + "$(sqlite3-api.js)", "$(sqlite3.js)", 0, 0); + mk_lib_mode("sqlite3", "esm", 1, + "$(sqlite3-api.mjs)", "$(sqlite3.mjs)", + "-Dtarget=es6-module", 0); + mk_lib_mode("sqlite3", "bundler-friendly", 1, + "$(sqlite3-api-bundler-friendly.mjs)", "$(sqlite3-bundler-friendly.mjs)", + "$(c-pp.D.sqlite3-esm) -Dtarget=es6-bundler-friendly", 0); + mk_lib_mode("sqlite3" , "node", 1, + "$(sqlite3-api-node.mjs)", "$(sqlite3-node.mjs)", + "$(c-pp.D.sqlite3-bundler-friendly) -Dtarget=node", 0); + mk_lib_mode("sqlite3-wasmfs", "esm" ,1, + "$(sqlite3-api-wasmfs.mjs)", "$(sqlite3-wasmfs.mjs)", + "$(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs", + "-sEXPORT_ES6 -sUSE_ES6_IMPORT_META"); + return rc; +} diff --git a/ext/wasm/speedtest1-wasmfs.mjs b/ext/wasm/speedtest1-wasmfs.mjs index 2d5ae322a..aeb37dd7f 100644 --- a/ext/wasm/speedtest1-wasmfs.mjs +++ b/ext/wasm/speedtest1-wasmfs.mjs @@ -10,14 +10,14 @@ wMsg('log',"speedtest1-wasmfs starting..."); */ const wasmfsDir = function f(wasmUtil,dirName="/opfs"){ if(undefined !== f._) return f._; - if( !self.FileSystemHandle - || !self.FileSystemDirectoryHandle - || !self.FileSystemFileHandle){ + if( !globalThis.FileSystemHandle + || !globalThis.FileSystemDirectoryHandle + || !globalThis.FileSystemFileHandle){ return f._ = ""; } try{ if(0===wasmUtil.xCallWrapped( - 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName + 'sqlite3__wasm_init_wasmfs', 'i32', ['string'], dirName )){ return f._ = dirName; }else{ @@ -36,7 +36,7 @@ const logErr = (...args)=>wMsg('logErr',...args); const runTests = function(sqlite3){ console.log("Module inited.",sqlite3); const wasm = sqlite3.wasm; - const __unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["*","string"]); + const __unlink = wasm.xWrap("sqlite3__wasm_vfs_unlink", "int", ["*","string"]); const unlink = (fn)=>__unlink(0,fn); const pDir = wasmfsDir(wasm); if(pDir) log("Persistent storage:",pDir); @@ -46,7 +46,7 @@ const runTests = function(sqlite3){ } const scope = wasm.scopedAllocPush(); const dbFile = pDir+"/speedtest1.db"; - const urlParams = new URL(self.location.href).searchParams; + const urlParams = new URL(globalThis.location.href).searchParams; const argv = ["speedtest1"]; if(urlParams.has('flags')){ argv.push(...(urlParams.get('flags').split(','))); diff --git a/ext/wasm/wasmfs.make b/ext/wasm/wasmfs.make index 2bd7a0700..59ec55756 100644 --- a/ext/wasm/wasmfs.make +++ b/ext/wasm/wasmfs.make @@ -6,12 +6,10 @@ # GNUMakefile. ######################################################################## MAKEFILE.wasmfs := $(lastword $(MAKEFILE_LIST)) -$(warning The WASMFS build is currently incomplete.) +$(warning The WASMFS build is not well-supported. \ + WASMFS is a proverbial moving target, so what builds today might not tomorrow.) -#dir.wasmfs := $(dir.wasm) -dir.wasmfs := $(dir.dout) sqlite3-wasmfs.js := $(dir.wasmfs)/sqlite3-wasmfs.js -sqlite3-wasmfs.mjs := $(dir.wasmfs)/sqlite3-wasmfs.mjs sqlite3-wasmfs.wasm := $(dir.wasmfs)/sqlite3-wasmfs.wasm ######################################################################## @@ -25,9 +23,11 @@ cflags.sqlite3-wasmfs += -DSQLITE_ENABLE_WASMFS # emcc flags specific to building the final .js/.wasm file... emcc.flags.sqlite3-wasmfs := emcc.flags.sqlite3-wasmfs += \ - -sEXPORTED_RUNTIME_METHODS=wasmMemory,allocateUTF8OnStack,stringToUTF8OnStack + -sEXPORTED_RUNTIME_METHODS=wasmMemory # wasmMemory ==> for -sIMPORTED_MEMORY - # *OnStack ==> wasmfs internals (leaky abstraction) +# Some version of emcc between 3.1.60-ish and 3.1.62 deprecated the use of +# (allocateUTF8OnStack,stringToUTF8OnStack). Earlier emcc versions will +# fail to build without those in EXPORTED_RUNTIME_METHODS. emcc.flags.sqlite3-wasmfs += -sUSE_CLOSURE_COMPILER=0 emcc.flags.sqlite3-wasmfs += -Wno-limited-postlink-optimizations # ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag. @@ -46,12 +46,7 @@ emcc.flags.sqlite3-wasmfs += -sALLOW_MEMORY_GROWTH=0 # And, indeed, it runs slowly if memory is permitted to grow. #emcc.flags.sqlite3-wasmfs.vanilla := #emcc.flags.sqlite3-wasmfs.esm := -sEXPORT_ES6 -sUSE_ES6_IMPORT_META -sqlite3-api.mjs.wasmfs := $(dir.tmp)/sqlite3-api-wasmfs.mjs -$(eval $(call SETUP_LIB_BUILD_MODE,sqlite3-wasmfs,esm,1,\ - $(sqlite3-api.mjs.wasmfs), $(sqlite3-wasmfs.mjs),\ - $(c-pp.D.sqlite3-bundler-friendly) -Dwasmfs,\ - -sEXPORT_ES6 -sUSE_ES6_IMPORT_META\ -)) +all: $(sqlite3-wasmfs.mjs) $(sqlite3-wasmfs.js) $(sqlite3-wasmfs.mjs): $(MAKEFILE.wasmfs) ######################################################################## # Build quirk: we cannot build BOTH .js and .mjs with our current @@ -98,7 +93,7 @@ $(speedtest1-wasmfs.mjs): $(speedtest1.cfiles) $(sqlite3-wasmfs.js) \ $(emcc.flags.sqlite3-wasmfs) \ $(emcc.flags.speedtest1-wasmfs) \ -o $@ $(speedtest1.cfiles) -lm - @$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1) + @$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,1,1) $(maybe-wasm-strip) $(speedtest1-wasmfs.wasm) chmod -x $(speedtest1-wasmfs.wasm) ls -la $@ $(speedtest1-wasmfs.wasm) |