diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile
index a9b4af209a..d08e46bc35 100644
--- a/ext/wasm/GNUmakefile
+++ b/ext/wasm/GNUmakefile
@@ -14,10 +14,6 @@
# by the target name. Rebuild is necessary for all components to get
# the desired optimization level.
#
-# quick, q = do just build the essentials for testing
-# (sqlite3.js/wasm, tester1) for faster development-mode
-# turnaround.
-#
# dist = create end user deliverables. Add dist.build=oX to build
# with a specific optimization level, where oX is one of the
# above-listed o? or qo? target names.
@@ -37,25 +33,61 @@
# - InfoZip for 'dist' zip file
########################################################################
default: all
-#default: quick
MAKEFILE = $(lastword $(MAKEFILE_LIST))
-MAKEFILE.fiddle = fiddle.make
CLEAN_FILES =
DISTCLEAN_FILES = config.make
MAKING_CLEAN = $(if $(filter %clean,$(MAKECMDGOALS)),1,0)
-.PHONY: clean distclean
-clean:
- -rm -f $(CLEAN_FILES)
-distclean: clean
- -rm -f $(DISTCLEAN_FILES)
+#
+# dir.X = various directory names.
+#
+# dir.top = the top dir of the canonical build tree, where
+# sqlite3.[ch] live.
+#
+dir.top = ../..
+dir.wasm = $(patsubst %/,%,$(dir $(MAKEFILE)))
+dir.api = api
+dir.jacc = jaccwabyt
+dir.common = common
+dir.fiddle = fiddle
+dir.fiddle.debug = fiddle-debug
+dir.tool = $(dir.top)/tool
+# 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.tmp = $(dir.wasm)/bld
+dir.wasmfs = $(dir.dout)
-########################################################################
+#
+# Emoji for log messages.
+#
+emo.bug = ๐
+emo.compile = โณ
+emo.roadblock = ๐ง
+emo.disk = ๐พ
+emo.done = โ
+emo.fire = ๐ฅ
+emo.folder = ๐
+emo.garbage = ๐
+emo.lock = ๐
+emo.magic = ๐ง
+emo.megaphone = ๐ฃ
+emo.mute = ๐
+emo.stop = ๐
+emo.strip = ๐
+emo.test = ๐งช
+emo.tool = ๐จ
+emo.wasm-opt = ๐งผ
+# ๐ท๐ช๐งฎ๐งซ๐งฝ๐ฟโฝ๐ง๐ฑ๐ช๐๐งผ
+
+#
# Special-case builds for which we require certain pre-conditions
# which, if not met, may cause warnings or fatal errors in the build.
# This also affects the default optimization level flags. The fiddle
# targets are in this list because they are used for generating
# sqlite.org/fiddle.
+#
OPTIMIZED_TARGETS = dist snapshot fiddle fiddle.debug
ifeq (1,$(MAKING_CLEAN))
@@ -67,7 +99,7 @@ ifeq (1,$(MAKING_CLEAN))
else
# Include config.make and perform some bootstrapping...
ifeq (,$(wildcard ./config.make))
- $(error Missing config.make (gets generated by the configure script if the EMSDK is found))
+ $(error Missing config.make. It gets generated by the configure script if the EMSDK is found)
endif
include ./config.make
ifeq (,$(bin.bash))
@@ -79,22 +111,24 @@ else
emcc.version = $(shell $(bin.emcc) --version | sed -n 1p | sed -e 's/^.* \([3-9][^ ]*\) .*$$/\1/;')
$(info using emcc version [$(emcc.version)])
ifeq (,$(bin.wasm-strip))
- ####################################################################
+ #
# We need wasm-strip for release builds (see below for why) but
# not strictly for non-release builds.
- $(info WARNING: *******************************************************************)
- $(info WARNING: Builds using -Oz will minify WASM-exported names, breaking)
- $(info WARNING: _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: *******************************************************************)
+ #
+ achtung = $(emo.fire)WARNING
+ $(info $(achtung): *******************************************************************)
+ $(info $(achtung): Builds using -Oz will minify WASM-exported names, breaking)
+ $(info $(achtung): _All The Things_. The workaround for that is to build)
+ $(info $(achtung): with -g3 (which explodes the file size) and then strip the debug)
+ $(info $(achtung): info after compilation, using wasm-strip, to shrink the wasm file.)
+ $(info $(achtung): wasm-strip was not found in the PATH so we cannot strip those.)
+ $(info $(achtung): If this build uses any optimization level higher than -O1 then)
+ $(info $(achtung): the ***resulting JS code WILL NOT BE USABLE***.)
+ $(info $(achtung): wasm-strip is part of the wabt package:)
+ $(info $(achtung): https://github.com/WebAssembly/wabt)
+ $(info $(achtung): on Ubuntu-like systems it can be installed with:)
+ $(info $(achtung): sudo apt install wabt)
+ $(info $(achtung): *******************************************************************)
ifneq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
$(error Cannot make release-quality binary because wasm-strip is not available.)
endif
@@ -108,73 +142,132 @@ else
endif
endif
# ^^^ end of are-we-MAKING_CLEAN
-maybe-wasm-strip = $(bin.wasm-strip)
-########################################################################
-# JS_BUILD_NAMES exists for documentation purposes only. It enumerates
-# the core build styles:
#
-# - sqlite3 = canonical library build
+# Common vars and $(call)/$(eval)able utilities.
#
-# - sqlite3-wasmfs = WASMFS-capable library build
+# The "b." prefix on some APIs is for "build". It was initially used
+# only for features specific to each distinct js/wasm build. That's no
+# longer the case, but the naming convention has stuck.
#
-JS_BUILD_NAMES = sqlite3 sqlite3-wasmfs
-########################################################################
-# JS_BUILD_MODES exists for documentation purposes only. It enumerates
-# the various "flavors" of build, each of which requires slight
-# customization of the output:
-#
-# - vanilla = plain-vanilla JS for use in browsers. This is the
-# canonical build mode.
-#
-# - esm = ES6 module, a.k.a. ESM, for use in browsers.
-#
-# - bundler-friendly = esm slightly tweaked for "bundler"
-# tools. Bundlers are invariably based on node.js, so these builds
-# are intended to be read at build-time by node.js but with a final
-# target of browsers. All bundler-friendly builds are UNTESTED.
-# They are provided primarily for use by the community-supported
-# subproject which hosts npm builds of sqlite3, and they are
-# actively supported only to the extent needed by that subproject.
-#
-# - node = for use by node.js for node.js, as opposed to by node.js on
-# behalf of browser-side code (use bundler-friendly for that). Note
-# that persistent storage (OPFS) is not available in these builds.
-# These builds are UNTESTED and UNSUPPORTED!
-#
-JS_BUILD_MODES = vanilla esm bunder-friendly node
+loud ?= 0
+ifeq (1,$(loud))
+ $(info $(emo.megaphone) Emitting loud build info. Pass loud=0 to disable it.)
+ b.cmd@ =
+ loud.if = 1
+else
+ $(info $(emo.mute) Eliding loud build info. Pass loud=1 to enable it.)
+ b.cmd@ = @
+ loud.if =
+endif
-########################################################################
-# dir.top = the top dir of the canonical build tree, where
-# sqlite3.[ch] live.
-dir.top = ../..
-# Maintenance reminder: some Emscripten flags require absolute paths
-# but we want relative paths for most stuff simply to reduce
-# noise. The $(abspath...) GNU make function can transform relative
-# paths to absolute.
-dir.wasm = $(patsubst %/,%,$(dir $(MAKEFILE)))
-dir.api = api
-dir.jacc = jaccwabyt
-dir.common = common
-dir.fiddle = fiddle
-dir.fiddle-debug = fiddle-debug
-dir.tool = $(dir.top)/tool
-# 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.tmp = $(dir.wasm)/bld
-dir.wasmfs = $(dir.dout)
+#
+# logtag.X value for log context labeling. logtag.OTHERX can be
+# assigned to customize it for a given X. This tag is used by
+# b.call.X, b.eval.X, etc. for logging. There motivation for this is
+# adding a build-specific prefix to messages so that the output of
+# parallel builds is easier to sort through. We use emoji for the
+# prefixes because it's far easier for my eyes to sort through than
+# using only each build's name as the prefix.
+#
+# Each distinct build sets up its own logtag.BUILDNAME.
+#
+logtag.@ = [$@]
+logtag.filter = [$(emo.disk) $@]
+logtag.test = [$(emo.test) $@]
+logtag.cp = [$(emo.disk) $@]
-MKDIR.bld = $(dir.tmp)
-$(MKDIR.bld):
- @mkdir -p $@ $(dir.dout)
+#
+# $(call b.echo,LOGTAG,msg)
+#
+b.echo = echo $(logtag.$(1)) $(2)
-CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \
- $(dir.fiddle-debug)/* $(dir.dout)/* $(dir.tmp)/*
+#
+# $(call b.mkdir@)
+#
+# $1 = optional LOGTAG
+#
+b.mkdir@ = if [ ! -d $(dir $@) ]; then \
+ echo '[$(emo.folder)+] $(if $(1),$(logtag.$(1)),[$(dir $@)])'; \
+ mkdir -p $(dir $@) || exit; fi
-########################################################################
+#
+# $(call b.cp,@,src,dest)
+#
+# $1 = build name, $2 = src file(s). $3 = dest dir
+b.cp = $(call b.mkdir@); \
+ echo '$(logtag.$(1)) $(emo.disk) $(2) ==> $3'; \
+ cp -p $(2) $(3) || exit
+
+#
+# $(eval $(call b.eval.c-pp,@,src,dest,-Dx=y...))
+#
+# $1 = build name
+# $2 = Input file(s): cat $(2) | $(bin.c-pp) ...
+# $3 = Output file: $(bin.c-pp) -o $(3)
+# $4 = optional $(bin.c-pp) -D... flags */
+define b.eval.c-pp
+$(3): $$(MAKEFILE_LIST) $$(bin.c-pp) $(2)
+ @$$(call b.mkdir@); \
+ $$(call b.echo,$(1),$$(emo.disk)$$(emo.lock) $$(bin.c-pp) $(4) $(if $(loud.if),$(2))); \
+ rm -f $(3); \
+ $$(bin.c-pp) -o $(3) $(4) $(2) || exit; \
+ chmod -w $(3)
+CLEAN_FILES += $(3)
+endef
+
+c-pp.D.64bit = -D64bit
+
+#
+# $(call b.strip-js-emcc-bindings)
+#
+# $1 = an optional log message prefix
+#
+# Our JS code installs bindings of each sqlite3_...() WASM export. The
+# generated Emscripten JS file does the same using its own framework,
+# but we don't use those results and can speed up lib init, and reduce
+# memory cost a bit, by stripping them out. Emscripten code-generation
+# changes can "break" this, causing this to be a no-op, but (probably)
+# the worst that can happen in that case is that it doesn't actually
+# strip anything, leading to slightly larger JS files.
+#
+# This is intended to be used in makefile targets which generate an
+# Emscripten module and where $@ is the module's .js/.mjs file.
+b.strip-js-emcc-bindings = \
+ sed -i -e '/^.*= \(_sqlite3\|_fiddle\)[^=]*=.*createExportWrapper/d' \
+ -e '/^var \(_sqlite3\|_fiddle\)[^=]*=.*makeInvalidEarlyAccess/d' $@ || exit; \
+ echo '$(1) $(emo.garbage) (Probably) /createExportWrapper()/d and /makeInvalidEarlyAccess()/d'
+
+
+#
+# bin.version-info = binary to output various sqlite3 version info for
+# embedding in the JS files and in building the distribution zip file.
+# It must NOT be in $(dir.tmp) because we need it to survive the
+# cleanup process for the dist build to work properly.
+#
+# Slight caveat: this uses the version info from the in-tree
+# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
+# end result is that the generated JS files may have static version
+# info from $(bin.version-info) which differ from their runtime-emitted
+# version info (e.g. from sqlite3_libversion()).
+bin.version-info = $(dir.top)/version-info
+$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
+ $(MAKE) -C $(dir.top) version-info
+
+#
+# bin.stripcomments is used for stripping C/C++-style comments from JS
+# files. The JS files contain large chunks of documentation which we
+# don't need for all builds. That app's -k flag is of particular
+# importance here, as it allows us to retain the opening comment
+# block(s), which contain the license header and version info.
+bin.stripccomments = $(dir.tool)/stripccomments
+$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
+ $(CC) -o $@ $<
+DISTCLEAN_FILES += $(bin.stripccomments)
+
+
+#
# Set up sqlite3.c and sqlite3.h...
#
# To build with SEE (https://sqlite.org/see), either put sqlite3-see.c
@@ -206,18 +299,11 @@ else
endif
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
-# parallel build of that file and its dependants.
-.NOTPARALLEL: $(sqlite3.h)
-$(sqlite3.h):
- $(MAKE) -C $(dir.top) sqlite3.c
-$(sqlite3.c): $(sqlite3.h)
-########################################################################
+#
# 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))
wasm-bare-bones = 1
$(info ==============================================================)
@@ -229,6 +315,24 @@ else
endif
# undefine barebones # relatively new gmake feature, not ubiquitous
+#
+# It's important that sqlite3.h be built to completion before any
+# other parts of the build run, thus we use .NOTPARALLEL to disable
+# parallel build of that file and its dependants. However, that makes
+# the whole build non-parallelizable because everything has a dep on
+# sqlite3.h/c. The alternative is to force the user to run (make
+# sqlite3.c) from the top of the tree before running this build.
+#
+#.NOTPARALLEL: $(sqlite3.h)
+#
+$(sqlite3.h):
+ @echo "$(sqlite3.h) is out of date. "; \
+ echo "To avoid problems with parallel builds, we're exiting now. Please do:"; \
+ echo " $(MAKE) -C $(dir.top) sqlite3.c"; \
+ echo "and try again."; exit 1
+# $(MAKE) -C $(dir.top) sqlite3.c
+$(sqlite3.c): $(sqlite3.h)
+
# Common options for building sqlite3-wasm.c and speedtest1.c.
# Explicit ENABLEs...
SQLITE_OPT.common = \
@@ -312,7 +416,6 @@ endif
# deprecated and alternatives are in place, but this crash behavior
# can be used to find errant uses of sqlite3_js_vfs_create_file()
# in client code.
-
########################################################################
# The following flags are hard-coded into sqlite3-wasm.c and cannot be
# modified via the build process:
@@ -354,33 +457,6 @@ ifneq (,$(sqlite3_wasm_extra_init.c))
cflags.wasm_extra_init = -DSQLITE_WASM_EXTRA_INIT
endif
-#########################################################################
-# bin.version-info = binary to output various sqlite3 version info for
-# embedding in the JS files and in building the distribution zip file.
-# It must NOT be in $(dir.tmp) because we need it to survive the
-# cleanup process for the dist build to work properly.
-#
-# Slight caveat: this uses the version info from the in-tree
-# sqlite3.c/h, which may diff from a user-provided $(sqlite3.c). The
-# end result is that the generated JS files may have static version
-# info from $(bin.version-info) which differ from their runtime-emitted
-# version info (e.g. from sqlite3_libversion()).
-bin.version-info = $(dir.top)/version-info
-.NOTPARALLEL: $(bin.version-info)
-$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
- $(MAKE) -C $(dir.top) version-info
-
-#########################################################################
-# bin.stripcomments is used for stripping C/C++-style comments from JS
-# files. The JS files contain large chunks of documentation which we
-# don't need for all builds. That app's -k flag is of particular
-# importance here, as it allows us to retain the opening comment
-# block(s), which contain the license header and version info.
-bin.stripccomments = $(dir.tool)/stripccomments
-$(bin.stripccomments): $(bin.stripccomments).c $(MAKEFILE)
- $(CC) -o $@ $<
-DISTCLEAN_FILES += $(bin.stripccomments)
-
#
# If $(WASM_CUSTOM_INSTANTIATE) is 1 then mkwasmbuilds will add
# -Dcustom-Module.instantiateWasm to some of the builds. This is
@@ -391,11 +467,10 @@ DISTCLEAN_FILES += $(bin.stripccomments)
WASM_CUSTOM_INSTANTIATE = 0
########################################################################
-# SQLITE.CALL.C-PP.FILTER: a $(call)able to transform $(1) to $(2) via:
+# $(bin.c-pp): a minimal text file preprocessor. Like C's but much
+# less so.
#
-# ./c-pp -f $(1) -o $(2) $(3)
-#
-# Historical notes:
+# Historical notes about preprocessing files in this project:
#
# - We first attempted to use gcc and/or clang to preprocess JS files
# in the same way we would normally do C files, but C-specific quirks
@@ -417,11 +492,11 @@ WASM_CUSTOM_INSTANTIATE = 0
# builds but is maintained as a standalone project:
# https://fossil.wanderinghorse.net/r/c-pp
#
-# Note that the SQLITE_... build flags used here have NO EFFECT on the
-# JS/WASM build. They are solely for use with $(bin.c-pp) itself.
+# The SQLITE_... build flags used here have NO EFFECT on the JS/WASM
+# build. They are solely for use with $(bin.c-pp) itself.
#
# -D... flags which should be included in all invocations should be
-# appended to $(SQLITE.CALL.C-PP.FILTER.global).
+# appended to $(b.eval.c-pp.flags).
bin.c-pp = ./c-pp
$(bin.c-pp): c-pp.c $(sqlite3.c) # $(MAKEFILE)
$(CC) -O0 -o $@ c-pp.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
@@ -429,22 +504,10 @@ $(bin.c-pp): c-pp.c $(sqlite3.c) # $(MAKEFILE)
-DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_WAL -DSQLITE_THREADSAFE=0 \
-DSQLITE_TEMP_STORE=3
DISTCLEAN_FILES += $(bin.c-pp)
-SQLITE.CALL.C-PP.FILTER.global ?=
+b.eval.c-pp.flags ?=
ifeq (1,$(SQLITE_C_IS_SEE))
- SQLITE.CALL.C-PP.FILTER.global += -Denable-see
+ b.eval.c-pp.flags += -Denable-see
endif
-define SQLITE.CALL.C-PP.FILTER
-# Create $2 from $1 using $(bin.c-pp)
-# $1 = Input file: c-pp -f $(1).js
-# $2 = Output file: c-pp -o $(2).js
-# $3 = optional c-pp -D... flags
-$(2): $(1) $$(MAKEFILE_LIST) $$(bin.c-pp)
- @mkdir -p $$(dir $$@)
- $$(bin.c-pp) -f $(1) -o $$@ $(3) $(SQLITE.CALL.C-PP.FILTER.global)
-CLEAN_FILES += $(2)
-endef
-# /end SQLITE.CALL.C-PP.FILTER
-########################################################################
# cflags.common = C compiler flags for all builds
cflags.common = -I. -I$(dir $(sqlite3.c))
@@ -460,17 +523,6 @@ emcc.MEMORY64 ?= 0
# 1.0.34) or will fail to strip with "tables may not be 64-bit".
########################################################################
-ifneq (0,$(emcc.MEMORY64))
- emcc.WASM_BIGINT = 1
- # -sMEMORY64=1+ assumes -sWASM_BIGINT=1, so we'll make it explicit
-
- # SQLITE.CALL.C-PP.FILTER.global += -D64bit
- # ^^ We no longer need build-time code filtering for 64-bit but if
- # we ever do again, just uncomment that line or, if it's just needed
- # in specific builds, update that build's -D flags in
- # mkwasmbuilds.c.
-endif
-
# emcc_opt = optimization-related flags. These are primarily used by
# the various oX targets. build times for -O levels higher than 0 are
# painful at dev-time.
@@ -488,22 +540,6 @@ else
emcc_opt ?= -Oz
endif
-# Our JS code installs bindings of each sqlite3_...() WASM export. The
-# generated Emscripten JS file does the same using its own framework,
-# but we don't use those results and can speed up lib init, and reduce
-# memory cost a bit, by stripping them out. Emscripten-side changes
-# can "break" this, causing this to be a no-op, but the worst that can
-# happen in that case is that it doesn't actually strip anything,
-# leading to slightly larger JS files.
-#
-# This snippet is intended to be used in makefile targets which
-# generate an Emscripten module and where $@ is the module's .js/.mjs
-# file.
-SQLITE.strip-createExportWrapper = \
- sed -i -e '/^.*= \(_sqlite3\|_fiddle\)[^=]*=.*createExportWrapper/d' \
- -e '/^var \(_sqlite3\|_fiddle\)[^=]*=.*makeInvalidEarlyAccess/d' $@ || exit; \
- echo '(Probably) stripped out createExportWrapper() and makeInvalidEarlyAccess() parts.'
-
# When passing emcc_opt from the CLI, += and re-assignment have no
# effect, so emcc_opt+=-g3 doesn't work. So...
emcc_opt_full = $(emcc_opt) -g3
@@ -546,101 +582,10 @@ ifeq (0,$(wasm-bare-bones))
EXPORTED_FUNCTIONS.api.in += $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
endif
EXPORTED_FUNCTIONS.api = $(dir.tmp)/EXPORTED_FUNCTIONS.api
-$(EXPORTED_FUNCTIONS.api): $(MKDIR.bld) $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
+$(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(sqlite3.c) $(MAKEFILE)
+ @$(call b.mkdir@)
cat $(EXPORTED_FUNCTIONS.api.in) > $@
-########################################################################
-# sqlite3-license-version.js = generated JS file with the license
-# header and version info.
-sqlite3-license-version.js = $(dir.tmp)/sqlite3-license-version.js
-# sqlite3-api-build-version.js = generated JS file which populates the
-# sqlite3.version object using $(bin.version-info).
-sqlite3-api-build-version.js = $(dir.tmp)/sqlite3-api-build-version.js
-# sqlite3-api.jses = the list of JS files which make up
-# $(sqlite3-api.js.in), in the order they need to be assembled.
-sqlite3-api.jses = $(sqlite3-license-version.js)
-# sqlite3-api-prologue.js: initial bootstrapping bits:
-sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
-# whwhasm.js and jaccwabyt.js: Low-level utils, mostly replacing
-# Emscripten glue:
-sqlite3-api.jses += $(dir.common)/whwasmutil.js
-sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
-# sqlite3-api-glue Glues the previous part together with sqlite:
-sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.c-pp.js
-# $(sqlite3-api-build-version.js) = library version info
-sqlite3-api.jses += $(sqlite3-api-build-version.js)
-# sqlite3-api-oo1 = the oo1 API:
-sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.c-pp.js
-# sqlite3-api-worker = the Worker1 API:
-sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.c-pp.js
-# sqlite3-vfs-helper = helper APIs for VFSes:
-sqlite3-api.jses += $(dir.api)/sqlite3-vfs-helper.c-pp.js
-ifeq (0,$(wasm-bare-bones))
- # sqlite3-vtab-helper = helper APIs for VTABLEs:
- sqlite3-api.jses += $(dir.api)/sqlite3-vtab-helper.c-pp.js
-endif
-# sqlite3-vfs-opfs = the first OPFS VFS:
-sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
-# sqlite3-vfs-opfs-sahpool = the second OPFS VFS:
-sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs-sahpool.c-pp.js
-# sqlite3-api-cleanup.js = "finalizes" the build and cleans up
-# any extraneous global symbols which are needed temporarily
-# by the previous files.
-sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
-
-########################################################################
-# SOAP.js is an external API file which is part of our distribution
-# but not part of the sqlite3-api.js amalgamation. It's a component of
-# the first OPFS VFS and necessarily an external file.
-SOAP.js = $(dir.api)/sqlite3-opfs-async-proxy.js
-SOAP.js.bld = $(dir.dout)/$(notdir $(SOAP.js))
-#
-# $(sqlite3-api.ext.jses) = API-related files which are standalone files,
-# not part of the amalgamation.
-#
-sqlite3-api.ext.jses = $(SOAP.js.bld)
-$(SOAP.js.bld): $(SOAP.js)
- cp $< $@
-
-########################################################################
-# $(sqlite3-api*.*js) contain the core library code but not the
-# Emscripten-related glue which deals with loading sqlite3.wasm. In
-# theory they can be used by arbitrary build environments and WASM
-# loaders, but in practice that breaks down because the WASM loader
-# has to be able to provide all of the necessary "imports" to
-# sqlite3.wasm, and that list of imports is unknown until sqlite3.wasm
-# is compiled, at which point Emscripten sets up the imports
-# appropriately. Abstractly speaking, it's impossible for other build
-# environments to know exactly which imports are needed and provide
-# them. Tools like wasm-objdump can be used to find the list of
-# imports but it's questionable whether a non-Emscripten tool could
-# realistically use that info to provide proper implementations.
-#
-# Sidebar: some of the imports are used soley by the Emscripten glue,
-# which the sqlite3 JS code does not rely on.
-#
-# 2025-09-04: the most significant WASM imports sqlite3.wasm relies on
-# are (A) sqlite3_malloc/sqlite3_free() (the memory-management APIs
-# used by the whole library) and (B) the libc proxies for POSIX I/O
-# emulation (arguably one of Emscripten's most convenient features
-# when building C code for WASM). If we eliminate the POSIX I/O
-# emulation then we could hypothetically eliminate all, or maybe all
-# but one, Emscripten import dependency. We would either need to add
-# our own POSIX emulation layer (not a trivial effort) or restrict the
-# library to use of only in-memory VFSes and the JS-side VFSes.
-#
-# sqlite3-api.js.in = the amalgamated sqlite3-api.js before it gets
-# preprocessed. It contains all of $(sqlite3-api.jses) but none of the
-# Emscripten-specific headers and footers.
-sqlite3-api.js.in = $(dir.tmp)/sqlite3-api.c-pp.js
-$(sqlite3-api.js.in): $(MKDIR.bld) $(sqlite3-api.jses) $(MAKEFILE)
- @echo "Making $@ ..."
- @for i in $(sqlite3-api.jses); do \
- echo "/* BEGIN FILE: $$i */"; \
- cat $$i; \
- echo "/* END FILE: $$i */"; \
- done > $@
-
########################################################################
# emcc flags for .c/.o/.wasm/.js.
emcc.flags =
@@ -649,18 +594,22 @@ emcc.flags += -v
# -v is _very_ loud but also informative about what it's doing
endif
-
-########################################################################
+#
# emcc flags for .c/.o.
+#
emcc.cflags =
emcc.cflags += -std=c99 -fPIC
# -------------^^^^^^^^ we need c99 for $(sqlite3-wasm.c), primarily
# for variadic macros and snprintf() to implement
# sqlite3__wasm_enum_json().
emcc.cflags += -I. -I$(dir.top)
-########################################################################
+
+#
# emcc flags specific to building .js/.wasm files...
+#
emcc.jsflags = -fPIC
+#emcc.jsflags += -Wno-gcc-install-dir-libstdcxx
+#emcc is not passing ^^^ this on to clang
emcc.jsflags += --no-entry
emcc.jsflags += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
emcc.jsflags += -sMODULARIZE
@@ -691,19 +640,7 @@ emcc.jsflags += -sSTRICT_JS=0
# -sSTRICT=1 Causes failures about unknown symbols which the build
# tools should be installing, e.g. __syscall_geteuid32
-# emcc -sENVIRONMENT values for the various build modes:
-emcc.environment.vanilla = web,worker
-emcc.environment.vanilla64 = $(emcc.environment.vanilla)
-emcc.environment.bundler-friendly = $(emcc.environment.vanilla)
-emcc.environment.esm = $(emcc.environment.vanilla)
-emcc.environment.esm64 = $(emcc.environment.vanilla)
-emcc.environment.node = node
-# Adding ",node" to the list for the other builds causes Emscripten to
-# generate code which confuses node: it cannot reliably determine
-# whether the build is for a browser or for node. We neither build nor
-# test node builds on a regular basis. They are fully unsupported.
-
-########################################################################
+#
# -sINITIAL_MEMORY: How much memory we need to start with is governed
# at least in part by whether -sALLOW_MEMORY_GROWTH is enabled. If so,
# we can start with less. If not, we need as much as we'll ever
@@ -719,6 +656,12 @@ emcc.environment.node = node
# but also says (in its changelog): "Note that it is currently not
# supported in all configurations (#21071)."
# https://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md
+#
+# 2025-09-25: it turns out that _this_ WASM's heap size is not
+# affected by Emscripten's in-memory virtual filesystem, so we don't
+# strictly need a lot of heap. Resizing the heap is slow, though, so
+# we want to start off with some room to grow.
+#
emcc.jsflags += -sALLOW_MEMORY_GROWTH
emcc.INITIAL_MEMORY.128 = 134217728
emcc.INITIAL_MEMORY.96 = 100663296
@@ -726,9 +669,10 @@ emcc.INITIAL_MEMORY.64 = 67108864
emcc.INITIAL_MEMORY.32 = 33554432
emcc.INITIAL_MEMORY.16 = 16777216
emcc.INITIAL_MEMORY.8 = 8388608
-emcc.INITIAL_MEMORY ?= 8
+emcc.INITIAL_MEMORY.4 = 4194304
+emcc.INITIAL_MEMORY ?= 8
ifeq (,$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)))
-$(error emcc.INITIAL_MEMORY must be one of: 8, 16, 32, 64, 96, 128 (megabytes))
+$(error emcc.INITIAL_MEMORY must be one of: 4, 8, 16, 32, 64, 96, 128 (megabytes))
endif
emcc.jsflags += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
# /INITIAL_MEMORY
@@ -793,69 +737,14 @@ emcc.jsflags += -sLLD_REPORT_UNDEFINED
# -g3 debugging info, _huge_.
########################################################################
-########################################################################
-# $(sqlite3-api-build-version.js) injects the build version info into
-# the bundle in JSON form.
-$(sqlite3-api-build-version.js): $(MKDIR.bld) $(bin.version-info) $(MAKEFILE)
- @echo "Making $@..."
- @{ \
- echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
- echo -n ' sqlite3.version = '; \
- $(bin.version-info) --json; \
- echo ';'; \
- echo '});'; \
- } > $@
-
-########################################################################
-# $(sqlite3-license-version.js) contains the license header and
-# in-comment build version info.
-#
-# Maintenance reminder: there are awk binaries out there which do not
-# support -e SCRIPT.
-$(sqlite3-license-version.js): $(MKDIR.bld) $(sqlite3.h) \
- $(dir.api)/sqlite3-license-version-header.js $(MAKEFILE)
- @echo "Making $@..."; { \
- cat $(dir.api)/sqlite3-license-version-header.js; \
- echo '/*'; \
- echo '** This code was built from sqlite3 version...'; \
- echo "**"; \
- awk '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' $(sqlite3.h); \
- awk '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
- echo "**"; \
- echo "** with the help of Emscripten SDK version $(emcc.version)."; \
- echo '*/'; \
- } > $@
-
-########################################################################
-# --post-js and --pre-js are emcc flags we use to append/prepend JS to
-# the generated emscripten module file. These rules set up the core
-# pre/post files for use by the various builds. --pre-js is used to
-# inject code which needs to run as part of the pre-WASM-load phase.
-# --post-js injects code which runs after the WASM module is loaded
-# and includes the entirety of the library plus some
-# Emscripten-specific post-bootstrapping code.
-pre-js.js.in = $(dir.api)/pre-js.c-pp.js
-post-js.js.in = $(dir.tmp)/post-js.c-pp.js
-post-jses.js = \
- $(dir.api)/post-js-header.js \
- $(sqlite3-api.js.in) \
- $(dir.api)/post-js-footer.js
-$(post-js.js.in): $(MKDIR.bld) $(post-jses.js) $(MAKEFILE)
- @echo "Making $@..."
- @for i in $(post-jses.js); do \
- echo "/* BEGIN FILE: $$i */"; \
- cat $$i; \
- echo "/* END FILE: $$i */"; \
- done > $@
-
# Undocumented Emscripten feature: if the target file extension is
# "mjs", it defaults to ES6 module builds:
# https://github.com/emscripten-core/emscripten/issues/14383
sqlite3.wasm = $(dir.dout)/sqlite3.wasm
sqlite3-wasm.c = $(dir.api)/sqlite3-wasm.c
-sqlite3-wasm.cfiles = $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
-sqlite3-wasmfs.cfiles = $(sqlite3-wasm.cfiles)
+sqlite3-wasm.c.in = $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
+sqlite3-wasmfs.c.in = $(sqlite3-wasm.c.in)
# sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter
# (predictably) results in a slightly faster binary. We're close
# enough to the target speed requirements that the 500ms makes a
@@ -863,12 +752,12 @@ sqlite3-wasmfs.cfiles = $(sqlite3-wasm.cfiles)
# of building a shared copy of sqlite3-wasm.o to link against.
########################################################################
-########################################################################
-# SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT is used by mkwasmbuilds.c and the
+#
+# b.call.patch-export-default is used by mkwasmbuilds.c and the
# wasmfs build. $1 is 1 if the build mode needs this workaround
# (modes: 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.
+# be 1. $(3) is an optional log prefix, defaulting to $(logtag.@)
#
# Reminder for ESM builds: even if we use -sEXPORT_ES6=0, emcc _still_
# adds:
@@ -885,12 +774,16 @@ sqlite3-wasmfs.cfiles = $(sqlite3-wasm.cfiles)
#
# Maintenance reminder: Mac sed works differently than GNU sed, so we
# use awk instead of sed for this.
-define SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT
+#
+define b.call.patch-export-default
if [ x1 = x$(1) ]; then \
- echo "Fragile workaround for emscripten/issues/18237. See SQLITE.CALL.xJS.ESM-EXPORT-DEFAULT."; \
+ echo "$(if $(3),$(3),$(logtag.@)) $(emo.bug) Fragile" \
+ "workaround for emscripten/issues/18237." \
+ "See b.call.patch-export-default."; \
{\
- awk '/^export default/ && !f{f=1; next} 1' $@ > $@.tmp && mv $@.tmp $@; \
- } || exit $$?; \
+ awk '/^export default/ && !f{f=1; next} 1' $@ \
+ > $@.tmp && mv $@.tmp $@; \
+ } || exit; \
if [ x1 = x$(2) ]; then \
if ! grep -q '^export default' $@; then \
echo "Cannot find export default." 1>&2; \
@@ -901,17 +794,6 @@ fi
endef
#
-# We define these to assist in deps handling to avoid concurrent
-# builds (more notes on that below).
-#
-sqlite3.js = $(dir.dout)/sqlite3.js
-sqlite3.mjs = $(dir.dout)/sqlite3.mjs
-sqlite3.wasm = $(dir.dout)/sqlite3.wasm
-sqlite3-64bit.js = $(dir.dout)/sqlite3-64bit.js
-sqlite3-64bit.mjs = $(dir.dout)/sqlite3-64bit.mjs
-sqlite3-64bit.wasm = $(dir.dout)/sqlite3-64bit.wasm
-EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
-
# The various -D... values used by *.c-pp.js include:
#
# -Dtarget=es6-module: for all ESM module builds
@@ -925,273 +807,19 @@ EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
# as string literals so that bundlers' static-analysis tools can
# find those files and include them in their bundles.
#
-# -Dtarget=es6-module -Dtarget=es6-bundler-friendly -Dtarget=node: is
-# intended for use by node.js for node.js, as opposed to by
-# node.js on behalf of a browser. Mixing -sENVIRONMENT=web and
-# -sENVIRONMENT=node leads to ambiguity and confusion on node's
-# part, as it's unable to reliably determine whether the target is
-# a browser or node.
+# -Dtarget=es6-module -Dtarget=node: is intended for use by node.js
+# for node.js, as opposed to by node.js on behalf of a
+# browser. Mixing -sENVIRONMENT=web and -sENVIRONMENT=node leads to
+# ambiguity and confusion on node's part, as it's unable to
+# reliably determine whether the target is a browser or node.
#
-# We repeat: all node.js builds are 100% untested and unsupported.
+# To repeat: all node.js builds are 100% untested and unsupported.
#
########################################################################
-########################################################################
-# We have to ensure that we do not build $(sqlite3*.*js) in parallel
-# for any builds which result in the creation of $(sqlite3.wasm). We
-# have no way to build just a .[m]js file without also building the
-# .wasm file because the generated .[m]js file has to include info
-# about the imports needed by the wasm file, so they have to be built
-# together. i.e. we're building $(sqlite3.wasm) multiple times, but
-# that's unavoidable (and harmless, but is a significant waste of
-# build time).
-$(sqlite3.wasm): $(sqlite3.js)
-$(sqlite3.mjs): $(sqlite3.js)
-$(sqlite3-64bit.wasm): $(sqlite3-64bit.js)
-$(sqlite3-64bit.mjs): $(sqlite3-64bit.js)
-$(dir.dout)/sqlite3-bundler-friendly.mjs: $(sqlite3.mjs)
-$(dir.dout)/sqlite3-node.mjs: $(sqlite3.mjs)
-#CLEAN_FILES += $(sqlite3.wasm)
-
-# This block MUST come between the above definitions of
-# sqlite3-...js/mjs and the $(eval) calls below this block which use
-# SQLITE.CALL.C-PP.FILTER.
-########################################################################
-# bin.mkwb is used for generating much of the makefile code for the
-# various wasm 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 previous 3 options.
#
-# Maintenance note: the various $(c-pp.D.XYZ) vars are defined via
-# $(bin.mkwb).
-bin.mkwb = ./mkwasmbuilds
-ifneq (1,$(MAKING_CLEAN))
-$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE)
- $(CC) -g -std=c99 -o $@ $< -DWASM_CUSTOM_INSTANTIATE=$(WASM_CUSTOM_INSTANTIATE)
-
-.wasmbuilds.make: $(bin.mkwb)
- @rm -f $@
- $(bin.mkwb) > $@
- @chmod -w $@
--include .wasmbuilds.make
-endif
-CLEAN_FILES += .wasmbuilds.make $(bin.mkwb)
-
-########################################################################
-# We need separate copies of certain supplementary JS files for the
-# bundler-friendly build. Concretely, any supplemental JS files which
-# themselves use importScripts() or Workers or URL() constructors
-# which refer to other in-tree (m)JS files require a bundler-friendly
-# copy. Bundler-friendly builds replace certain references to string
-# vars/expressions with string literals, as bundler tools are static
-# code analyzers and cannot cope with the former.
-#
-# Most of what follows is the generation of those copies.
-$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1.c-pp.js,\
- $(dir.dout)/sqlite3-worker1.js))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1.c-pp.js,\
- $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs,\
- $(c-pp.D.sqlite3-bundler-friendly)))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
- $(dir.dout)/sqlite3-worker1-promiser.js))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
- $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js,\
- $(c-pp.D.sqlite3-bundler-friendly)))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
- $(dir.dout)/sqlite3-worker1-promiser.mjs,\
- -Dtarget=es6-module -Dtarget=es6-bundler-friendly))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.js))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.js,demo-worker1-promiser.mjs,\
- -Dtarget=es6-module))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser.html))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,demo-worker1-promiser.c-pp.html,demo-worker1-promiser-esm.html,\
- -Dtarget=es6-module))
-
-$(dir.dout)/sqlite3-bundler-friendly.mjs: \
- $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs \
- $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js
-
-demo-worker1-promiser.html: $(dir.dout)/sqlite3-worker1-promiser.js demo-worker1-promiser.js
-demo-worker1-promiser-esm.html: $(sqlite3-worker1-promiser.mjs) demo-worker1-promiser.mjs
-all: demo-worker1-promiser.html demo-worker1-promiser-esm.html
-
-sqlite3-api.ext.jses += \
- $(dir.dout)/sqlite3-worker1-promiser.mjs \
- $(dir.dout)/sqlite3-worker1-promiser.js \
- $(dir.dout)/sqlite3-worker1-bundler-friendly.mjs \
- $(dir.dout)/sqlite3-worker1.js
-all quick: $(sqlite3-api.ext.jses)
-q: quick
-64bit: # populated by $(bin.mkwb)
-
-########################################################################
-# batch-runner.js is part of one of the test apps which reads in SQL
-# dumps generated by $(speedtest1) and executes them.
-dir.sql = sql
-speedtest1 = ../../speedtest1
-speedtest1.c = ../../test/speedtest1.c
-speedtest1.sql = $(dir.sql)/speedtest1.sql
-speedtest1.cliflags = --size 10 --big-transactions
-$(speedtest1):
- $(MAKE) -C ../.. speedtest1
-$(speedtest1.sql): $(speedtest1) $(MAKEFILE)
- $(speedtest1) $(speedtest1.cliflags) --script $@
-batch-runner.list: $(MAKEFILE) $(speedtest1.sql) $(dir.sql)/000-mandelbrot.sql
- bash split-speedtest1-script.sh $(dir.sql)/speedtest1.sql
- ls -1 $(dir.sql)/*.sql | grep -v speedtest1.sql | sort > $@
-clean-batch:
- rm -f batch-runner.list $(dir.sql)/speedtest1*.sql
-# ^^^ we don't do this along with 'clean' because we clean/rebuild on
-# a regular basis with different -Ox flags and rebuilding the batch
-# pieces each time is an unnecessary time sink.
-batch: batch-runner.list
-#all: batch
-# end batch-runner.js
-########################################################################
-# Wasmified speedtest1 is our primary benchmarking tool.
-#
-# emcc.speedtest1.common = emcc flags used by multiple builds of speedtest1
-# emcc.speedtest1 = emcc flags used by main build of speedtest1
-emcc.speedtest1.common = $(emcc_opt_full)
-emcc.speedtest1 = -I. -I$(dir $(sqlite3.canonical.c))
-emcc.speedtest1 += -sENVIRONMENT=web
-emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
-emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
-emcc.speedtest1.common += -sINVOKE_RUN=0
-emcc.speedtest1.common += --no-entry
-emcc.speedtest1.common += -sABORTING_MALLOC
-emcc.speedtest1.common += -sSTRICT_JS=0
-emcc.speedtest1.common += -sMODULARIZE
-emcc.speedtest1.common += -Wno-limited-postlink-optimizations
-emcc.speedtest1.common += -Wno-unused-main
-# ^^^^ -Wno-unused-main is for emcc 3.1.52+. speedtest1 has a wasm_main() which is
-# exported and called by the JS code.
-EXPORTED_FUNCTIONS.speedtest1 = $(abspath $(dir.tmp)/EXPORTED_FUNCTIONS.speedtest1)
-emcc.speedtest1.common += -sSTACK_SIZE=512KB
-emcc.speedtest1.common += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.speedtest1)
-emcc.speedtest1.common += $(emcc.exportedRuntimeMethods)
-emcc.speedtest1.common += -sALLOW_TABLE_GROWTH
-emcc.speedtest1.common += -sDYNAMIC_EXECUTION=0
-emcc.speedtest1.common += --minify 0
-emcc.speedtest1.common += -sEXPORT_NAME=$(sqlite3.js.init-func)
-emcc.speedtest1.common += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
-emcc.speedtest1.common += -sMEMORY64=$(emcc.MEMORY64)
-
-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
-# this error from Emscripten:
-#
-# > native function `free` called after runtime exit (use
-# NO_EXIT_RUNTIME to keep it alive after main() exits))
-#
-# If it's 0 and it crashes, we get:
-#
-# > stdio streams had content in them that was not flushed. you should
-# set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline
-# when you printf etc.
-#
-# and pending output is not flushed because it didn't end with a
-# newline (by design). The lesser of the two evils seems to be
-# -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app
-# which runs speedtest1 multiple times.
-
-$(EXPORTED_FUNCTIONS.speedtest1): $(MKDIR.bld) $(EXPORTED_FUNCTIONS.api.core)
- @echo "Making $@ ..."
- @{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.core); } > $@
-speedtest1.js = $(dir.dout)/speedtest1.js
-emcc.flags.speedtest1-vanilla = $(cflags.common) -DSQLITE_SPEEDTEST1_WASM
-speedtest1.cfiles = $(speedtest1.c) $(sqlite3-wasm.c)
-$(speedtest1.js): $(MAKEFILE) $(speedtest1.cfiles) \
- $(pre-post-speedtest1-vanilla.deps) \
- $(EXPORTED_FUNCTIONS.speedtest1)
- @echo "Building $@ ..."
- $(bin.emcc) \
- $(emcc.speedtest1) \
- $(emcc.speedtest1.common) \
- $(emcc.flags.speedtest1-vanilla) $(pre-post-speedtest1-vanilla.flags) \
- $(SQLITE_OPT) \
- -USQLITE_WASM_BARE_BONES \
- -USQLITE_C -DSQLITE_C=$(sqlite3.canonical.c) \
- $(speedtest1.exit-runtime0) \
- -o $@ $(speedtest1.cfiles) -lm
- @chmod -x $(basename $@).wasm
- @$(maybe-wasm-strip) $(basename $@).wasm
- @$(SQLITE.strip-createExportWrapper)
- @ls -la $@ $(speedtest1.wasm)
-
-speedtest1: $(speedtest1.js)
-all: speedtest1
-# end speedtest1.js
-########################################################################
-
-########################################################################
-# tester1 is the main unit and regression test application and needs
-# to be able to run in 4 separate modes to cover the primary
-# client-side use cases:
-#
-# 1) Load sqlite3 in the main UI thread of a conventional script.
-# 2) Load sqlite3 in a conventional Worker thread.
-# 3) Load sqlite3 as an ES6 module (ESM) in the main thread.
-# 4) Load sqlite3 as an ESM worker. (Not all browsers support this.)
-#
-# To that end, we require two separate builds of tester1.js:
-#
-# tester1.js: cases 1 and 2
-# tester1.mjs: cases 3 and 4
-#
-# To create those, we filter tester1.c-pp.js with $(bin.c-pp)...
-$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.js))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.js,tester1.mjs,$(c-pp.D.sqlite3-esm)))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1.html))
-$(eval $(call SQLITE.CALL.C-PP.FILTER,tester1.c-pp.html,tester1-esm.html,$(c-pp.D.sqlite3-esm)))
-tester1: tester1.js tester1.mjs tester1.html tester1-esm.html
-# We do not include $(dir.dout)/sqlite3-bundler-friendly.mjs in this
-# because bundlers are client-specific.
-all quick: tester1
-quick: $(sqlite3.js)
-
-########################################################################
-# Convenience rules to rebuild with various -Ox levels. Much
-# experimentation shows -O2 to be the clear winner in terms of speed.
-# Note that build times with anything higher than -O0 are somewhat
-# painful.
-
-.PHONY: o0 o1 o2 o3 os oz
-emcc-opt-extra =
-#ifeq (1,$(wasm-bare-bones))
-#emcc-opt-extra += -flto
-# ^^^^ -flto can have a considerably performance boost at -O0 but
-# doubles the build time and seems to have negligible, if any, effect
-# on higher optimization levels.
-#
-# -flto does not shrink the size of bare-bones builds by any measurable
-# amount.
-#endif
-o0: clean
- $(MAKE) -e "emcc_opt=-O0"
-o1: clean
- $(MAKE) -e "emcc_opt=-O1 $(emcc-opt-extra)"
-o2: clean
- $(MAKE) -j2 -e "emcc_opt=-O2 $(emcc-opt-extra)"
-o3: clean
- $(MAKE) -e "emcc_opt=-O3 $(emcc-opt-extra)"
-os: clean
- @echo "WARNING: -Os can result in a build with mysteriously missing pieces!"
- $(MAKE) -e "emcc_opt=-Os $(emcc-opt-extra)"
-oz: clean
- $(MAKE) -j2 -e "emcc_opt=-Oz $(emcc-opt-extra)"
-
-########################################################################
-# Sub-makes...
-
-# https://sqlite.org/fiddle application...
-include $(MAKEFILE.fiddle)
-
# Only add wasmfs if wasmfs.enable=1 or we're running (dist)clean
+#
ifneq (,$(filter wasmfs,$(MAKECMDGOALS)))
wasmfs.enable ?= 1
else
@@ -1218,18 +846,481 @@ $(info This platform does not support the WASMFS build.)
HAVE_WASMFS = 0
else
HAVE_WASMFS = 1
-include wasmfs.make
endif
endif
# /wasmfs
########################################################################
+#
+# Inputs/outputs for the sqlite3-api.js family.
+#
+# sqlite3-api.jses = the list of JS files which make up
+# sqlite3-api.js, in the order they need to be assembled.
+sqlite3-api.jses = $(sqlite3-license-version.js)
+sqlite3-api.jses += $(dir.api)/sqlite3-api-prologue.js
+sqlite3-api.jses += $(dir.common)/whwasmutil.js
+sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
+sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.c-pp.js
+sqlite3-api.jses += $(sqlite3-api-build-version.js)
+sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.c-pp.js
+sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.c-pp.js
+sqlite3-api.jses += $(dir.api)/sqlite3-vfs-helper.c-pp.js
+ifeq (0,$(wasm-bare-bones))
+ sqlite3-api.jses += $(dir.api)/sqlite3-vtab-helper.c-pp.js
+endif
+sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs.c-pp.js
+sqlite3-api.jses += $(dir.api)/sqlite3-vfs-opfs-sahpool.c-pp.js
+sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
+
+#
+# $(sqlite3-license-version.js) contains the license header and
+# in-comment build version info.
+#
+# Maintenance reminder: there are awk binaries out there which do not
+# support -e SCRIPT.
+#
+sqlite3-license-version.js = $(dir.tmp)/sqlite3-license-version.js
+$(sqlite3-license-version.js): $(bin.version-info) \
+ $(dir.api)/sqlite3-license-version-header.js
+ @echo '$(logtag.@) $(emo.disk)'; { \
+ $(call b.mkdir@); \
+ cat $(dir.api)/sqlite3-license-version-header.js || exit $$?; \
+ echo '/*'; \
+ echo '** This code was built from sqlite3 version...'; \
+ echo '**'; \
+ awk '/define SQLITE_VERSION/{$$1=""; print "**" $$0}' $(sqlite3.h); \
+ awk '/define SQLITE_SOURCE_ID/{$$1=""; print "**" $$0}' $(sqlite3.h); \
+ echo '**'; echo '** Emscripten SDK: $(emcc.version)'; \
+ echo '**'; \
+ echo '*/'; \
+ } > $@
+
+#
+# $(sqlite3-api-build-version.js) injects the build version info into
+# the bundle in JSON form.
+#
+sqlite3-api-build-version.js = $(dir.tmp)/sqlite3-api-build-version.js
+$(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE)
+ @echo '$(logtag.@) $(emo.disk)'; { \
+ $(call b.mkdir@); \
+ echo 'globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \
+ echo -n ' sqlite3.version = '; \
+ $(bin.version-info) --json; \
+ echo ';'; \
+ echo '});'; \
+ } > $@
+
+#
+# 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.in.js = $(dir.api)/extern-post-js.c-pp.js
+
+#
+# Emscripten flags for --[extern-][pre|post]-js=... for the
+# various builds.
+# pre-post-jses.*.deps = lists of dependencies for the
+# --[extern-][pre/post]-js files.
+#
+pre-post-jses.common.deps = $(extern-pre-js.js) $(sqlite3-license-version.js)
+
+# --post-js and --pre-js are emcc flags we use to append/prepend JS to
+# the generated emscripten module file. These rules set up the core
+# pre/post files for use by the various builds. --pre-js is used to
+# inject code which needs to run as part of the pre-WASM-load phase.
+# --post-js injects code which runs after the WASM module is loaded
+# and includes the entirety of the library plus some
+# Emscripten-specific post-bootstrapping code.
+pre-js.in.js = $(dir.api)/pre-js.c-pp.js
+post-js.in.js = $(dir.tmp)/post-js.c-pp.js
+post-jses.js = \
+ $(dir.api)/post-js-header.js \
+ $(sqlite3-api.jses) \
+ $(dir.api)/post-js-footer.js
+$(post-js.in.js): $(MKDIR.bld) $(post-jses.js) $(MAKEFILE)
+ @$(call b.echo,@,$(emo.disk)); \
+ for i in $(post-jses.js); do \
+ echo "/* BEGIN FILE: $$i */"; \
+ cat $$i || exit $$?; \
+ echo "/* END FILE: $$i */"; \
+ done > $@
+
+#
+# speedtest1 decls needed before the $(bin.mkws)-generated makefile
+# is included.
+#
+bin.speedtest1 = ../../speedtest1
+speedtest1.c = ../../test/speedtest1.c
+speedtest1.c.in = $(speedtest1.c) $(sqlite3-wasm.c)
+EXPORTED_FUNCTIONS.speedtest1 = $(abspath $(dir.tmp)/EXPORTED_FUNCTIONS.speedtest1)
+
+#
+# fiddle build flags
+#
+# Flags specifically for debug builds of fiddle. Performance suffers
+# greatly in debug builds.
########################################################################
-# Push files to public wasm-testing.sqlite.org server
+# shell.c and its build flags...
+#
+# We should ideally collect these from ../../configure and past
+# them in ./config.make. The problem with that is that SHELL_OPT is
+# generated at make-time, not configure-time.
+ifneq (1,$(MAKING_CLEAN))
+ make-np-0 = make -C $(dir.top) -n -p
+ make-np-1 = sed -e 's/(TOP)/(dir.top)/g'
+ # Extract SHELL_OPT and SHELL_DEP from the top-most makefile and import
+ # them as vars here...
+ $(eval $(shell $(make-np-0) | grep -e '^SHELL_OPT ' | $(make-np-1)))
+ $(eval $(shell $(make-np-0) | grep -e '^SHELL_DEP ' | $(make-np-1)))
+ # ^^^ can't do that in 1 invocation b/c newlines get stripped
+ ifeq (,$(SHELL_OPT))
+ $(error Could not parse SHELL_OPT from $(dir.top)/Makefile.)
+ endif
+ ifeq (,$(SHELL_DEP))
+ $(error Could not parse SHELL_DEP from $(dir.top)/Makefile.)
+ endif
+$(dir.top)/shell.c: $(SHELL_DEP) $(dir.tool)/mkshellc.tcl $(sqlite3.c)
+ $(MAKE) -C $(dir.top) shell.c
+endif
+# /shell.c
+########################################################################
+
+EXPORTED_FUNCTIONS.fiddle = $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle
+$(EXPORTED_FUNCTIONS.fiddle): $(fiddle.EXPORTED_FUNCTIONS.in) $(MAKEFILE_LIST)
+ @$(b.call.mkdir@)
+ @sort -u $(fiddle.EXPORTED_FUNCTIONS.in) > $@
+ @echo $(logtag.@) $(emo.disk)
+
+emcc.flags.fiddle = \
+ $(emcc.cflags) $(emcc_opt_full) \
+ --minify 0 \
+ -sALLOW_TABLE_GROWTH \
+ -sMEMORY64=$(emcc.MEMORY64) \
+ -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.8) \
+ -sABORTING_MALLOC \
+ -sSTRICT_JS=0 \
+ -sENVIRONMENT=web,worker \
+ -sMODULARIZE \
+ -sDYNAMIC_EXECUTION=0 \
+ -sWASM_BIGINT=$(emcc.WASM_BIGINT) \
+ -sEXPORT_NAME=$(sqlite3.js.init-func) \
+ -Wno-limited-postlink-optimizations \
+ $(emcc.exportedRuntimeMethods),FS \
+ -sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \
+ $(SQLITE_OPT.full-featured) \
+ $(SQLITE_OPT.common) \
+ $(SHELL_OPT) \
+ -UHAVE_READLINE -UHAVE_EDITLINE -UHAVE_LINENOISE \
+ -USQLITE_HAVE_ZLIB \
+ -USQLITE_WASM_BARE_BONES \
+ -DSQLITE_SHELL_FIDDLE
+
+clean: clean-fiddle
+clean-fiddle:
+ rm -f $(dir.fiddle)/fiddle-module.js \
+ $(dir.fiddle)/*.wasm \
+ $(dir.fiddle)/sqlite3-opfs-*.js \
+ $(dir.fiddle)/*.gz \
+ EXPORTED_FUNCTIONS.fiddle
+ rm -fr $(dir.fiddle-debug)
+
+emcc.flags.fiddle.debug = $(emcc.flags.fiddle) \
+ -DSQLITE_DEBUG \
+ -DSQLITE_ENABLE_SELECTTRACE \
+ -DSQLITE_ENABLE_WHERETRACE
+
+fiddle.EXPORTED_FUNCTIONS.in = \
+ EXPORTED_FUNCTIONS.fiddle.in \
+ $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-core \
+ $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-extras
+
+fiddle.c.in = $(dir.top)/shell.c $(sqlite3-wasm.c)
+
+#
+# bin.mkwb is used for generating much of the makefile code for the
+# various wasm 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 previous 3 options.
+#
+# Maintenance notes:
+#
+# - Ordering of this block within this file is fragile. The generated
+# makefile sets up many vars which are useful for the other targets.
+#
+# - Vars which are used by $(bin.mkwb) in dependency lists and such
+# need to be defined before this is included. Those used in recipies
+# do not.
+#
+bin.mkwb = ./mkwasmbuilds
+ifneq (1,$(MAKING_CLEAN))
+$(bin.mkwb): $(bin.mkwb).c $(MAKEFILE)
+ $(CC) -g -std=c99 -o $@ $< -DWASM_CUSTOM_INSTANTIATE=$(WASM_CUSTOM_INSTANTIATE)
+
+.wasmbuilds.make: $(bin.mkwb)
+ @rm -f $@
+ $(bin.mkwb) > $@
+ @chmod -w $@
+-include .wasmbuilds.make
+endif
+CLEAN_FILES += .wasmbuilds.make $(bin.mkwb)
+
+#
+# $(sqlite3.ext.js) = API-related files which are standalone
+# files, not part of the amalgamation. This list holds
+# the name of each such _output_ file.
+#
+sqlite3.ext.js =
+
+########################################################################
+# We need separate copies of certain supplementary JS files for the
+# bundler-friendly build. Concretely, any supplemental JS files which
+# themselves use importScripts() or Workers or URL() constructors
+# which refer to other in-tree (m)JS files require a bundler-friendly
+# copy. Bundler-friendly builds replace certain references to string
+# vars/expressions with string literals, as bundler tools are static
+# code analyzers and cannot cope with the former.
+
+#
+# sqlite3-worker1*.*
+# TODO: 64-bit
+#
+define gen-worker1
+# $1 = X.ext part of sqlite3-worker1X.ext
+# $2 = $(c-pp.D.NAME)
+$(call b.eval.c-pp,filter,$(dir.api)/sqlite3-worker1.c-pp.js,\
+ $(dir.dout)/sqlite3-worker1$(1),$(2))
+sqlite3.ext.js += $(dir.dout)/sqlite3-worker1$(1)
+all: $(dir.dout)/sqlite3-worker1$(1)
+endef
+
+$(eval $(call gen-worker1,.js,$(c-pp.D.vanilla)))
+$(eval $(call gen-worker1,.mjs,$(c-pp.D.esm)))
+$(eval $(call gen-worker1,-bundler-friendly.mjs,$(c-pp.D.bundler)))
+
+#
+# sqlite3-worker1-promiser*.*
+# TODO: 64-bit
+#
+define gen-promiser
+# $1 = X.ext part of sqlite3-worker1-promiserX.ext
+# $2 = $(c-pp.D.NAME)
+$(call b.eval.c-pp,filter,$(dir.api)/sqlite3-worker1-promiser.c-pp.js,\
+ $(dir.dout)/sqlite3-worker1-promiser$(1),$(2))
+sqlite3.ext.js += $(dir.dout)/sqlite3-worker1-promiser$(1)
+all: $(dir.dout)/sqlite3-worker1-promiser$(1)
+endef
+
+$(eval $(call gen-promiser,.js,$(c-pp.D.vanilla)))
+$(eval $(call gen-promiser,.mjs,$(c-pp.D.esm)))
+$(eval $(call gen-promiser,-bundler-friendly.mjs,$(c-pp.D.bundler)))
+
+#
+# demo1-worker-*.*:
+# $1 = .js or .mjs
+# $2 = .html or -esm.html
+# $3 = -D... flags for $(bin.c-pp)
+#
+define gen-dwp
+$(call b.eval.c-pp,test,demo-worker1-promiser.c-pp.js,demo-worker1-promiser$(1),$(3))
+$(call b.eval.c-pp,test,demo-worker1-promiser.c-pp.html,demo-worker1-promiser$(2),$(3))
+demos: demo-worker1-promiser$(1) demo-worker1-promiser$(2)
+endef
+$(eval $(call gen-dwp,.js,.html,$(c-pp.D.vanilla)))
+$(eval $(call gen-dwp,.mjs,-esm.html,$(c-pp.D.esm)))
+all: demos
+# End worker/promiser generation
+#######################################################################
+
+#
+# "SOAP" is a static file which is not part of the amalgamation but
+# gets copied into the build output folder and into each of the fiddle
+# builds.
+#
+sqlite3.ext.js += $(dir.dout)/sqlite3-opfs-async-proxy.js
+$(dir.dout)/sqlite3-opfs-async-proxy.js: $(dir.api)/sqlite3-opfs-async-proxy.js
+ @$(call b.cp,@,$<,$@)
+
+#
+# Add a dep of $(sqlite3.ext.js) on every individual build's JS file.
+# The primary purpose of this is to force them to be copied early in
+# the build process, which is sometimes a time-saver during
+# development, allowing the developer to reload a test page while
+# other parts of the build are still running. Another reason is that
+# we don't otherwise have a great place to attach them such that
+# they're always copied when we need them.
+#
+$(foreach B,$(b.names),$(eval $(out.$(B).js): $(sqlite3.ext.js)))
+
+#
+# speedtest1 is our primary benchmarking tool.
+#
+# emcc.speedtest1.common = emcc flags used by multiple builds of speedtest1
+# emcc.speedtest1 = emcc flags used by the main build of speedtest1
+#
+# These flags get applied via $(bin.mkwb).
+emcc.speedtest1.common = $(emcc_opt_full)
+emcc.speedtest1 = -I. -I$(dir $(sqlite3.canonical.c))
+emcc.speedtest1 += -sENVIRONMENT=web
+emcc.speedtest1 += -sALLOW_MEMORY_GROWTH
+emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))
+emcc.speedtest1.common += -sINVOKE_RUN=0
+emcc.speedtest1.common += --no-entry
+emcc.speedtest1.common += -sABORTING_MALLOC
+emcc.speedtest1.common += -sSTRICT_JS=0
+emcc.speedtest1.common += -sMODULARIZE
+emcc.speedtest1.common += -Wno-limited-postlink-optimizations
+emcc.speedtest1.common += -Wno-unused-main
+# ^^^^ -Wno-unused-main is for emcc 3.1.52+. speedtest1 has a wasm_main() which is
+# exported and called by the JS code.
+emcc.speedtest1.common += -sSTACK_SIZE=512KB
+emcc.speedtest1.common += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.speedtest1)
+emcc.speedtest1.common += $(emcc.exportedRuntimeMethods)
+emcc.speedtest1.common += -sALLOW_TABLE_GROWTH
+emcc.speedtest1.common += -sDYNAMIC_EXECUTION=0
+emcc.speedtest1.common += --minify 0
+emcc.speedtest1.common += -sEXPORT_NAME=$(sqlite3.js.init-func)
+emcc.speedtest1.common += -sWASM_BIGINT=$(emcc.WASM_BIGINT)
+emcc.speedtest1.common += -sMEMORY64=$(emcc.MEMORY64)
+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
+# this error from Emscripten:
+#
+# > native function `free` called after runtime exit (use
+# NO_EXIT_RUNTIME to keep it alive after main() exits))
+#
+# If it's 0 and it crashes, we get:
+#
+# > stdio streams had content in them that was not flushed. you should
+# set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline
+# when you printf etc.
+#
+# and pending output is not flushed because it didn't end with a
+# newline (by design). The lesser of the two evils seems to be
+# -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app
+# which runs speedtest1 multiple times.
+
+$(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api.core)
+ @echo "Making $@ ..."
+ @$(call b.mkdir@)
+ @{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api.core); } > $@
+speedtest1: $(out.speedtest1.js)
+# end speedtest1.js
+########################################################################
+
+#
+# tester1 is the main unit and regression test application and needs
+# to be able to run in 4 separate modes to cover the primary
+# client-side use cases:
+#
+# 1) Load sqlite3 in the main UI thread of a conventional script.
+# 2) Load sqlite3 in a conventional Worker thread.
+# 3) Load sqlite3 as an ES6 module (ESM) in the main thread.
+# 4) Load sqlite3 as an ESM worker. (Not all browsers support this.)
+#
+# To that end, we require two separate builds of tester1.js:
+#
+# tester1.js: cases 1 and 2
+# tester1.mjs: cases 3 and 4
+#
+# Then we need those again in 64-bit builds, which require a 64-bit
+# pair of js/wasm files.
+#
+# To create those, we filter tester1.c-pp.js/html with $(bin.c-pp)...
+
+# tester1.js variants:
+define gen-tester1.js
+# $1 = build name to have dep on
+# $2 = suffix for tester1SUFFIX JS
+# $3 = c-pp flags
+$(call b.eval.c-pp,test,tester1.c-pp.js,tester1$(2),$(3))
+tester1$(2): $(sqlite3.ext.js) $(out.$(1).wasm)
+tester1: tester1$(2)
+tester1-$(1): tester1$(2)
+endef
+
+$(eval $(call gen-tester1.js,vanilla,.js,$(c-pp.D.vanilla)))
+$(eval $(call gen-tester1.js,vanilla64,-64bit.js,$(c-pp.D.vanilla64)))
+$(eval $(call gen-tester1.js,esm,.mjs,$(c-pp.D.esm)))
+$(eval $(call gen-tester1.js,esm64,-64bit.mjs,$(c-pp.D.esm64)))
+
+# tester1.html variants:
+define gen-tester1.html
+# $1 = build name to have a dep on
+# $2 = file suffix: empty, -64bit, -esm, esm-64bit
+# $3 = c-pp -D flags.
+$(call b.eval.c-pp,test,tester1.c-pp.html,tester1$(2).html,$(3))
+tester1$(2).html: tester1-$(1)
+tester1: tester1$(2).html
+endef
+
+$(eval $(call gen-tester1.html,vanilla,,$(c-pp.D.vanilla)))
+$(eval $(call gen-tester1.html,vanilla64,-64bit,$(c-pp.D.vanilla64)))
+$(eval $(call gen-tester1.html,esm,-esm,$(c-pp.D.esm64)))
+$(eval $(call gen-tester1.html,esm64,-esm-64bit,$(c-pp.D.esm64)))
+
+# tester1-worker.html variants:
+# There is no ESM variant of this file. Instead, that page accepts a
+# ?esm URL flag to switch to ESM mode.
+$(eval $(call b.eval.c-pp,test,tester1-worker.c-pp.html,tester1-worker.html))
+$(eval $(call b.eval.c-pp,test,tester1-worker.c-pp.html,tester1-worker-64bit.html,$(c-pp.D.64bit)))
+tester: tester1-worker.html tester1-worker-64bit.html
+
+all: tester1
+# end tester1
+########################################################################
+
+#
+# Convenience rules to rebuild with various -Ox levels. Much
+# experimentation shows -O2 to be the clear winner in terms of speed.
+# -Oz results are significantly smaller and only slightly slower than
+# -O2 (very roughly 10% in highly unscientific tests), so -Oz is the
+# shipping configuration.
+#
+# Achtung: build times with anything higher than -O0 are somewhat
+# painful, which is why -O0 is the default.
+.PHONY: o0 o1 o2 o3 os oz
+emcc-opt-extra =
+#ifeq (1,$(wasm-bare-bones))
+#emcc-opt-extra += -flto
+# ^^^^ -flto can have a considerably performance boost at -O0 but
+# doubles the build time and seems to have negligible, if any, effect
+# on higher optimization levels.
+#
+# -flto does not shrink the size of bare-bones builds by any measurable
+# amount.
+#endif
+o0: clean
+ $(MAKE) -e "emcc_opt=-O0"
+o1: clean
+ $(MAKE) -e "emcc_opt=-O1 $(emcc-opt-extra)"
+o2: clean
+ $(MAKE) -e "emcc_opt=-O2 $(emcc-opt-extra)"
+o3: clean
+ $(MAKE) -e "emcc_opt=-O3 $(emcc-opt-extra)"
+os: clean
+ @echo "$(emo.fire)WARNING$(emo.fire): -Os can result in a build with mysteriously missing pieces!"
+ $(MAKE) -e "emcc_opt=-Os $(emcc-opt-extra)"
+oz: clean
+ $(MAKE) -e "emcc_opt=-Oz $(emcc-opt-extra)"
+
+#
+# Push files to the public wasm-testing.sqlite.org server.
+#
+# Ideally only -Oz builds should be pushed, so the practice has become:
+#
+# make clean
+# make -j4 for-testing
+# make push-testing
+#
wasm-testing.include = *.js *.mjs *.html \
./tests \
- $(dir.dout) $(dir.common) $(dir.fiddle) $(dir.fiddle-debug) $(dir.jacc)
-wasm-testing.exclude = sql/speedtest1.sql
+ $(dir.dout) $(dir.common) $(dir.fiddle) $(dir.fiddle.debug) $(dir.jacc)
+wasm-testing.exclude = sql/speedtest1.sql jswasm/*/*
wasm-testing.dir = /jail/sites/wasm-testing
wasm-testing.dest ?= wasm-testing:$(wasm-testing.dir)
# ---------------------^^^^^^^^^^^^ ssh alias
@@ -1242,6 +1333,18 @@ push-testing:
ssh wasm-testing 'cd $(wasm-testing.dir) && bash .gzip' || \
echo "SSH failed: it's likely that stale content will be served via old gzip files."
+# build everything needed by push-testing with -Oz
+.PHONY: for-testing
+for-testing: emcc_opt=-Oz
+for-testing: loud=1
+for-testing.deps = \
+ tester1 demos \
+ b-vanilla b-vanilla64 \
+ b-esm b-esm64 \
+ b-fiddle b-fiddle.debug \
+ speedtest1
+for-testing: $(for-testing.deps)
+
########################################################################
# If we find a copy of https://sqlite.org/wasm checked out, copy
# certain files over to it, applying some automated edits...
@@ -1256,12 +1359,12 @@ update-docs:
exit 127
else
wasm.docs.jswasm = $(wasm.docs.home)/jswasm
-update-docs: $(bin.stripccomments) $(sqlite3.js) $(sqlite3.wasm)
- @echo "Copying files to the /wasm docs. Be sure to use an -Oz build for this!"
- cp $(sqlite3.wasm) $(wasm.docs.jswasm)/.
- $(bin.stripccomments) -k -k < $(sqlite3.js) \
+update-docs: $(bin.stripccomments) $(out.sqlite3.js) $(out.sqlite3.wasm)
+ @echo "Copying files to the /wasm docs. Be sure to use an -Oz build for this!";
+ cp -p $(sqlite3.wasm) $(wasm.docs.jswasm)/.
+ $(bin.stripccomments) -k -k < $(out.vanilla.js) \
| sed -e '/^[ \t]*$$/d' > $(wasm.docs.jswasm)/sqlite3.js
- cp demo-123.js demo-123.html demo-123-worker.html $(wasm.docs.home)
+ cp -p demo-123.js demo-123.html demo-123-worker.html $(wasm.docs.home)/.
sed -n -e '/EXTRACT_BEGIN/,/EXTRACT_END/p' \
module-symbols.html > $(wasm.docs.home)/module-symbols.html
endif
@@ -1277,3 +1380,117 @@ endif
# Run local web server for the test/demo pages.
httpd:
althttpd -max-age 1 -enable-sab 1 -page index.html
+
+########################################################################
+# fiddle_remote is the remote destination for the fiddle app. It must
+# be a [user@]HOST:/path for rsync. The target "should probably"
+# contain a symlink of index.html -> fiddle.html.
+fiddle_remote ?=
+ifeq (,$(fiddle_remote))
+ifneq (,$(wildcard /home/stephan))
+ fiddle_remote = wh:www/wasm-testing/fiddle/.
+else ifneq (,$(wildcard /home/drh))
+ #fiddle_remote = if appropriate, add that user@host:/path here
+endif
+endif
+push-fiddle: fiddle
+ @if [ x = "x$(fiddle_remote)" ]; then \
+ echo "fiddle_remote must be a [user@]HOST:/path for rsync"; \
+ exit 1; \
+ fi
+ rsync -va fiddle/ $(fiddle_remote)
+# end fiddle remote push
+########################################################################
+
+.PHONY: clean distclean
+clean:
+ -rm -f $(CLEAN_FILES)
+ -rm -fr $(dir.dout) $(dir.tmp)
+
+distclean: clean
+ -rm -f $(DISTCLEAN_FILES)
+
+CLEAN_FILES += *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ $(dir.fiddle)/*~ \
+
+########################################################################
+# Explanation of, and some commentary on, various emcc build flags
+# follows. Full docs for these can be found at:
+#
+# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
+#
+# -sENVIRONMENT=web: elides bootstrap code related to non-web JS
+# environments like node.js. Removing this makes the output a tiny
+# tick larger but hypothetically makes it more portable to
+# non-browser JS environments.
+#
+# -sMODULARIZE: changes how the generated code is structured to avoid
+# declaring a global Module object and instead installing a function
+# which loads and initializes the module. The function is named...
+#
+# -sEXPORT_NAME=jsFunctionName (see -sMODULARIZE)
+#
+# -sEXPORTED_RUNTIME_METHODS=@/absolute/path/to/file: a file
+# containing a list of emscripten-supplied APIs, one per line, which
+# must be exported into the generated JS. Must be an absolute path!
+#
+# -sEXPORTED_FUNCTIONS=@/absolute/path/to/file: a file containing a
+# list of C functions, one per line, which must be exported via wasm
+# so they're visible to JS. C symbols names in that file must all
+# start with an underscore for reasons known only to the emcc
+# developers. e.g., _sqlite3_open_v2 and _sqlite3_finalize. Must be
+# an absolute path!
+#
+# -sSTRICT_JS ensures that the emitted JS code includes the 'use
+# strict' option. Note that -sSTRICT is more broadly-scoped and
+# results in build errors.
+#
+# -sALLOW_TABLE_GROWTH is required for (at a minimum) the UDF-binding
+# feature. Without it, JS functions cannot be made to proxy C-side
+# callbacks.
+#
+# -sABORTING_MALLOC causes the JS-bound _malloc() to abort rather than
+# return 0 on OOM. If set to 0 then all code which uses _malloc()
+# must, just like in C, check the result before using it, else
+# they're likely to corrupt the JS/WASM heap by writing to its
+# address of 0. It is, as of this writing, enabled in Emscripten by
+# default but we enable it explicitly in case that default changes.
+#
+# -sDYNAMIC_EXECUTION=0 disables eval() and the Function constructor.
+# If the build runs without these, it's preferable to use this flag
+# because certain execution environments disallow those constructs.
+# This flag is not strictly necessary, however.
+#
+# --no-entry: for compiling library code with no main(). If this is
+# not supplied and the code has a main(), it is called as part of the
+# module init process. Note that main() is #if'd out of shell.c
+# (renamed) when building in wasm mode.
+#
+# --pre-js/--post-js=FILE relative or absolute paths to JS files to
+# prepend/append to the emcc-generated bootstrapping JS. It's
+# easier/faster to develop with separate JS files (reduces rebuilding
+# requirements) but certain configurations, namely -sMODULARIZE, may
+# require using at least a --pre-js file. They can be used
+# individually and need not be paired.
+#
+# -O0..-O3 and -Oz: optimization levels affect not only C-style
+# optimization but whether or not the resulting generated JS code
+# gets minified. -O0 compiles _much_ more quickly than -O3 or -Oz,
+# and doesn't minimize any JS code, so is recommended for
+# development. -O3 or -Oz are recommended for deployment, but
+# primarily because -Oz will shrink the wasm file notably. JS-side
+# minification makes little difference in terms of overall
+# distributable size.
+#
+# --minify 0: supposedly disables minification of the generated JS
+# code, regardless of optimization level, but that's not quite true:
+# search the main makefile for wasm-strip for details. Minification
+# of the JS has minimal overall effect in the larger scheme of things
+# and results in JS files which can neither be edited nor viewed as
+# text files in Fossil (which flags them as binary because of their
+# extreme line lengths). Interestingly, whether or not the comments
+# in the generated JS file get stripped is unaffected by this setting
+# and depends entirely on the optimization level. Higher optimization
+# levels reduce the size of the JS considerably even without
+# minification.
+#
+########################################################################
diff --git a/ext/wasm/api/extern-post-js.c-pp.js b/ext/wasm/api/extern-post-js.c-pp.js
index e26e8bef66..ddba6917bd 100644
--- a/ext/wasm/api/extern-post-js.c-pp.js
+++ b/ext/wasm/api/extern-post-js.c-pp.js
@@ -69,6 +69,7 @@ const toExportForESM =
EmscriptenModule /* see post-js-header/footer.js */,
!!ff.__isUnderTest
);
+ sIMS.debugModule("sqlite3InitModule() sqlite3 =",s);
//const rv = s.asyncPostInit();
//delete s.asyncPostInit;
//#if wasmfs
diff --git a/ext/wasm/api/sqlite3-api-cleanup.js b/ext/wasm/api/sqlite3-api-cleanup.js
index a9e0047055..d0fc4e80f4 100644
--- a/ext/wasm/api/sqlite3-api-cleanup.js
+++ b/ext/wasm/api/sqlite3-api-cleanup.js
@@ -36,7 +36,6 @@ if( 'undefined' === typeof EmscriptenModule/*from post-js-header.js*/ ){
throw new Error("sqlite3-api-cleanup.js expects to be running in the "+
"context of its Emscripten module loader.");
}
-
try{
/* Config options for sqlite3ApiBootstrap(). */
const bootstrapConfig = Object.assign(
@@ -60,6 +59,8 @@ try{
bootstrapConfig.wasmPtrIR =
'number'===(typeof bootstrapConfig.exports.sqlite3_libversion())
? 'i32' :'i64';
+ const sIMS = sqlite3InitScriptInfo;
+ sIMS.debugModule("Bootstrapping lib config", sIMS);
/**
For purposes of the Emscripten build, call sqlite3ApiBootstrap().
diff --git a/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js b/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js
index 2edabe3e62..29e64e94cf 100644
--- a/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js
+++ b/ext/wasm/api/sqlite3-worker1-promiser.c-pp.js
@@ -252,10 +252,12 @@ globalThis.sqlite3Worker1Promiser = function callee(config = callee.defaultConfi
globalThis.sqlite3Worker1Promiser.defaultConfig = {
worker: function(){
-//#if target=es6-module
+//#if target=es6-bundler-friendly
return new Worker(new URL("sqlite3-worker1-bundler-friendly.mjs", import.meta.url),{
type: 'module'
});
+//#elif target=es6-module
+ return new Worker(new URL("sqlite3-worker1.js", import.meta.url));
//#else
let theJs = "sqlite3-worker1.js";
if(this.currentScript){
diff --git a/ext/wasm/api/sqlite3-worker1.c-pp.js b/ext/wasm/api/sqlite3-worker1.c-pp.js
index 74de9ec7ef..243128fe1d 100644
--- a/ext/wasm/api/sqlite3-worker1.c-pp.js
+++ b/ext/wasm/api/sqlite3-worker1.c-pp.js
@@ -34,6 +34,8 @@
*/
//#if target=es6-bundler-friendly
import {default as sqlite3InitModule} from './sqlite3-bundler-friendly.mjs';
+//#elif target=es6-module
+ return new Worker(new URL("sqlite3.js", import.meta.url));
//#else
"use strict";
{
diff --git a/ext/wasm/batch-runner-sahpool.html b/ext/wasm/batch-runner-sahpool.html
deleted file mode 100644
index ad7e7b5408..0000000000
--- a/ext/wasm/batch-runner-sahpool.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
-
- sqlite3-api batch SQL runner for the SAHPool VFS
-
-
- sqlite3-api batch SQL runner for the SAHPool VFS
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ext/wasm/batch-runner-sahpool.js b/ext/wasm/batch-runner-sahpool.js
deleted file mode 100644
index dfa5044a9e..0000000000
--- a/ext/wasm/batch-runner-sahpool.js
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- 2023-11-30
-
- 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.
-
- ***********************************************************************
-
- A basic batch SQL runner for the SAHPool VFS. This file must be run in
- a worker thread. This is not a full-featured app, just a way to get some
- measurements for batch execution of SQL for the OPFS SAH Pool VFS.
-*/
-'use strict';
-
-const wMsg = function(msgType,...args){
- postMessage({
- type: msgType,
- data: args
- });
-};
-const toss = function(...args){throw new Error(args.join(' '))};
-const warn = (...args)=>{ wMsg('warn',...args); };
-const error = (...args)=>{ wMsg('error',...args); };
-const log = (...args)=>{ wMsg('stdout',...args); }
-let sqlite3;
-const urlParams = new URL(globalThis.location.href).searchParams;
-const cacheSize = (()=>{
- if(urlParams.has('cachesize')) return +urlParams.get('cachesize');
- return 200;
-})();
-
-
-/** Throws if the given sqlite3 result code is not 0. */
-const checkSqliteRc = (dbh,rc)=>{
- if(rc) toss("Prepare failed:",sqlite3.capi.sqlite3_errmsg(dbh));
-};
-
-const sqlToDrop = [
- "SELECT type,name FROM sqlite_schema ",
- "WHERE name NOT LIKE 'sqlite\\_%' escape '\\' ",
- "AND name NOT LIKE '\\_%' escape '\\'"
-].join('');
-
-const clearDbSqlite = function(db){
- // This would be SO much easier with the oo1 API, but we specifically want to
- // inject metrics we can't get via that API, and we cannot reliably (OPFS)
- // open the same DB twice to clear it using that API, so...
- const rc = sqlite3.wasm.exports.sqlite3_wasm_db_reset(db.handle);
- log("reset db rc =",rc,db.id, db.filename);
-};
-
-const App = {
- db: undefined,
- cache:Object.create(null),
- log: log,
- warn: warn,
- error: error,
- metrics: {
- fileCount: 0,
- runTimeMs: 0,
- prepareTimeMs: 0,
- stepTimeMs: 0,
- stmtCount: 0,
- strcpyMs: 0,
- sqlBytes: 0
- },
- fileList: undefined,
- execSql: async function(name,sql){
- const db = this.db;
- const banner = "========================================";
- this.log(banner,
- "Running",name,'('+sql.length,'bytes)');
- const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
- let pStmt = 0, pSqlBegin;
- const metrics = db.metrics = Object.create(null);
- metrics.prepTotal = metrics.stepTotal = 0;
- metrics.stmtCount = 0;
- metrics.malloc = 0;
- metrics.strcpy = 0;
- if(this.gotErr){
- this.error("Cannot run SQL: error cleanup is pending.");
- return;
- }
- // Run this async so that the UI can be updated for the above header...
- const endRun = ()=>{
- metrics.evalSqlEnd = performance.now();
- metrics.evalTimeTotal = (metrics.evalSqlEnd - metrics.evalSqlStart);
- this.log("metrics:",JSON.stringify(metrics, undefined, ' '));
- this.log("prepare() count:",metrics.stmtCount);
- this.log("Time in prepare_v2():",metrics.prepTotal,"ms",
- "("+(metrics.prepTotal / metrics.stmtCount),"ms per prepare())");
- this.log("Time in step():",metrics.stepTotal,"ms",
- "("+(metrics.stepTotal / metrics.stmtCount),"ms per step())");
- this.log("Total runtime:",metrics.evalTimeTotal,"ms");
- this.log("Overhead (time - prep - step):",
- (metrics.evalTimeTotal - metrics.prepTotal - metrics.stepTotal)+"ms");
- this.log(banner,"End of",name);
- this.metrics.prepareTimeMs += metrics.prepTotal;
- this.metrics.stepTimeMs += metrics.stepTotal;
- this.metrics.stmtCount += metrics.stmtCount;
- this.metrics.strcpyMs += metrics.strcpy;
- this.metrics.sqlBytes += sql.length;
- };
-
- const runner = function(resolve, reject){
- ++this.metrics.fileCount;
- metrics.evalSqlStart = performance.now();
- const stack = wasm.scopedAllocPush();
- try {
- let t, rc;
- let sqlByteLen = sql.byteLength;
- const [ppStmt, pzTail] = wasm.scopedAllocPtr(2);
- t = performance.now();
- pSqlBegin = wasm.scopedAlloc( sqlByteLen + 1/*SQL + NUL*/) || toss("alloc(",sqlByteLen,") failed");
- metrics.malloc = performance.now() - t;
- metrics.byteLength = sqlByteLen;
- let pSql = pSqlBegin;
- const pSqlEnd = pSqlBegin + sqlByteLen;
- t = performance.now();
- wasm.heap8().set(sql, pSql);
- wasm.poke(pSql + sqlByteLen, 0);
- //log("SQL:",wasm.cstrToJs(pSql));
- metrics.strcpy = performance.now() - t;
- let breaker = 0;
- while(pSql && wasm.peek8(pSql)){
- wasm.pokePtr(ppStmt, 0);
- wasm.pokePtr(pzTail, 0);
- t = performance.now();
- rc = capi.sqlite3_prepare_v2(
- db.handle, pSql, sqlByteLen, ppStmt, pzTail
- );
- metrics.prepTotal += performance.now() - t;
- checkSqliteRc(db.handle, rc);
- pStmt = wasm.peekPtr(ppStmt);
- pSql = wasm.peekPtr(pzTail);
- sqlByteLen = pSqlEnd - pSql;
- if(!pStmt) continue/*empty statement*/;
- ++metrics.stmtCount;
- t = performance.now();
- rc = capi.sqlite3_step(pStmt);
- capi.sqlite3_finalize(pStmt);
- pStmt = 0;
- metrics.stepTotal += performance.now() - t;
- switch(rc){
- case capi.SQLITE_ROW:
- case capi.SQLITE_DONE: break;
- default: checkSqliteRc(db.handle, rc); toss("Not reached.");
- }
- }
- resolve(this);
- }catch(e){
- if(pStmt) capi.sqlite3_finalize(pStmt);
- this.gotErr = e;
- reject(e);
- }finally{
- capi.sqlite3_exec(db.handle,"rollback;",0,0,0);
- wasm.scopedAllocPop(stack);
- }
- }.bind(this);
- const p = new Promise(runner);
- return p.catch(
- (e)=>this.error("Error via execSql("+name+",...):",e.message)
- ).finally(()=>{
- endRun();
- });
- },
-
- /**
- Loads batch-runner.list and populates the selection list from
- it. Returns a promise which resolves to nothing in particular
- when it completes. Only intended to be run once at the start
- of the app.
- */
- loadSqlList: async function(){
- const infile = 'batch-runner.list';
- this.log("Loading list of SQL files:", infile);
- let txt;
- try{
- const r = await fetch(infile);
- if(404 === r.status){
- toss("Missing file '"+infile+"'.");
- }
- if(!r.ok) toss("Loading",infile,"failed:",r.statusText);
- txt = await r.text();
- }catch(e){
- this.error(e.message);
- throw e;
- }
- App.fileList = txt.split(/\n+/).filter(x=>!!x);
- this.log("Loaded",infile);
- },
-
- /** Fetch ./fn and return its contents as a Uint8Array. */
- fetchFile: async function(fn, cacheIt=false){
- if(cacheIt && this.cache[fn]) return this.cache[fn];
- this.log("Fetching",fn,"...");
- let sql;
- try {
- const r = await fetch(fn);
- if(!r.ok) toss("Fetch failed:",r.statusText);
- sql = new Uint8Array(await r.arrayBuffer());
- }catch(e){
- this.error(e.message);
- throw e;
- }
- this.log("Fetched",sql.length,"bytes from",fn);
- if(cacheIt) this.cache[fn] = sql;
- return sql;
- }/*fetchFile()*/,
-
- /**
- Converts this.metrics() to a form which is suitable for easy conversion to
- CSV. It returns an array of arrays. The first sub-array is the column names.
- The 2nd and subsequent are the values, one per test file (only the most recent
- metrics are kept for any given file).
- */
- metricsToArrays: function(){
- const rc = [];
- Object.keys(this.dbs).sort().forEach((k)=>{
- const d = this.dbs[k];
- const m = d.metrics;
- delete m.evalSqlStart;
- delete m.evalSqlEnd;
- const mk = Object.keys(m).sort();
- if(!rc.length){
- rc.push(['db', ...mk]);
- }
- const row = [k.split('/').pop()/*remove dir prefix from filename*/];
- rc.push(row);
- row.push(...mk.map((kk)=>m[kk]));
- });
- return rc;
- },
-
- metricsToBlob: function(colSeparator='\t'){
- const ar = [], ma = this.metricsToArrays();
- if(!ma.length){
- this.error("Metrics are empty. Run something.");
- return;
- }
- ma.forEach(function(row){
- ar.push(row.join(colSeparator),'\n');
- });
- return new Blob(ar);
- },
-
- /**
- Fetch file fn and eval it as an SQL blob. This is an async
- operation and returns a Promise which resolves to this
- object on success.
- */
- evalFile: async function(fn){
- const sql = await this.fetchFile(fn);
- return this.execSql(fn,sql);
- }/*evalFile()*/,
-
- /**
- Fetches the handle of the db associated with
- this.e.selImpl.value, opening it if needed.
- */
- initDb: function(){
- const capi = this.sqlite3.capi, wasm = this.sqlite3.wasm;
- const stack = wasm.scopedAllocPush();
- let pDb = 0;
- const d = Object.create(null);
- d.filename = "/batch.db";
- try{
- const oFlags = capi.SQLITE_OPEN_CREATE | capi.SQLITE_OPEN_READWRITE;
- const ppDb = wasm.scopedAllocPtr();
- const rc = capi.sqlite3_open_v2(d.filename, ppDb, oFlags, this.PoolUtil.vfsName);
- pDb = wasm.peekPtr(ppDb)
- if(rc) toss("sqlite3_open_v2() failed with code",rc);
- capi.sqlite3_exec(pDb, "PRAGMA cache_size="+cacheSize, 0, 0, 0);
- this.log("cache_size =",cacheSize);
- }catch(e){
- if(pDb) capi.sqlite3_close_v2(pDb);
- throw e;
- }finally{
- wasm.scopedAllocPop(stack);
- }
- d.handle = pDb;
- this.log("Opened db:",d.filename,'@',d.handle);
- return d;
- },
-
- closeDb: function(){
- if(this.db.handle){
- this.sqlite3.capi.sqlite3_close_v2(this.db.handle);
- this.db.handle = undefined;
- }
- },
-
- run: async function(sqlite3){
- delete this.run;
- this.sqlite3 = sqlite3;
- const capi = sqlite3.capi, wasm = sqlite3.wasm;
- this.log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
- this.log("WASM heap size =",wasm.heap8().length);
- let timeStart;
- sqlite3.installOpfsSAHPoolVfs({
- clearOnInit: true, initialCapacity: 4,
- name: 'batch-sahpool',
- verbosity: 2
- }).then(PoolUtil=>{
- App.PoolUtil = PoolUtil;
- App.db = App.initDb();
- })
- .then(async ()=>this.loadSqlList())
- .then(async ()=>{
- timeStart = performance.now();
- for(let i = 0; i < App.fileList.length; ++i){
- const fn = App.fileList[i];
- await App.evalFile(fn);
- if(App.gotErr) throw App.gotErr;
- }
- })
- .then(()=>{
- App.metrics.runTimeMs = performance.now() - timeStart;
- App.log("total metrics:",JSON.stringify(App.metrics, undefined, ' '));
- App.log("Reload the page to run this again.");
- App.closeDb();
- App.PoolUtil.removeVfs();
- })
- .catch(e=>this.error("ERROR:",e));
- }/*run()*/
-}/*App*/;
-
-let sqlite3Js = 'sqlite3.js';
-if(urlParams.has('sqlite3.dir')){
- sqlite3Js = urlParams.get('sqlite3.dir') + '/' + sqlite3Js;
-}
-importScripts(sqlite3Js);
-globalThis.sqlite3InitModule().then(async function(sqlite3_){
- log("Done initializing. Running batch runner...");
- sqlite3 = sqlite3_;
- App.run(sqlite3_);
-});
diff --git a/ext/wasm/batch-runner.html b/ext/wasm/batch-runner.html
deleted file mode 100644
index 5258f9597e..0000000000
--- a/ext/wasm/batch-runner.html
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
-
-
-
-
- sqlite3-api batch SQL runner
-
-
- sqlite3-api batch SQL runner
-
-
-
-
Initializing app...
-
- On a slow internet connection this may take a moment. If this
- message displays for "a long time", intialization may have
- failed and the JavaScript console may contain clues as to why.
-
-
-
Downloading...
-
-
-
-
- This page is for batch-running extracts from the output
- of speedtest1 --script, as well as other standalone SQL
- scripts.
-
-
ACHTUNG: this file requires a generated input list
- file. Run "make batch" from this directory to generate it.
-
-
WARNING: if the WASMFS/OPFS layer crashes, this page may
- become completely unresponsive and need to be closed and reloaded to recover.
-
-
WARNING: WebSQL's limited API requires that
- this app split up SQL batches into separate statements for execution. That will
- only work so long as semicolon characters are only used to terminate
- SQL statements, and not used within string literals or the like.
-