-#######################################################################
-# This GNU makefile creates the canonical sqlite3 WASM builds.
+#
+# This GNU makefile creates the canonical sqlite3 WASM builds. Plus some
+# others.
#
# This build assumes a Linux platform and is not intended for
# general-purpose client-level use, except for creating builds with
#
# default, all = build in dev mode
#
-# o0, o1, o2, o3, os, oz = full clean/rebuild with the -Ox level indicated
-# by the target name. Rebuild is necessary for all components to get
-# the desired optimization level.
+# o0, o1, o2, o3, os, oz = full clean/rebuild with the -Ox level
+# indicated by the target name. A clean rebuild is necessary for
+# all components to get the desired optimization level.
#
# 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.
+# with a specific optimization level, where oX is one of the
+# above-listed o? target names.
#
# snapshot = like dist, but uses a zip file name which clearly
-# marks it as a prerelease/snapshot build.
+# marks it as a prerelease/snapshot build.
#
# clean = clean up
#
# Required tools beyond those needed for the canonical builds:
#
# - Emscripten SDK: https://emscripten.org/docs/getting_started/downloads.html
+#
# - The bash shell
+#
# - GNU make, GNU sed, GNU awk, GNU grep (all in the $PATH and without
# a "g" prefix like they have on some non-GNU systems)
-# - wasm-strip for release builds: https://github.com/WebAssembly/wabt
+#
+# - wasm-strip for release builds: https://github.com/WebAssembly/wabt.
+# It will build without this but the .wasm files will be huge.
+#
# - InfoZip for 'dist' zip file
-########################################################################
+#
default: all
MAKEFILE = $(lastword $(MAKEFILE_LIST))
CLEAN_FILES =
CLEAN_FILES += $(3)
endef
+
+#
+# The various -D... values used by *.c-pp.js include:
+#
+# -Dtarget:es6-module: for all ESM module builds
+#
+# -Dtarget:node: for node.js builds
+#
+# -Dtarget:es6-module -Dtarget:es6-bundler-friendly: intended for
+# "bundler-friendly" ESM module build. These have some restrictions
+# on how URL() objects are constructed in some contexts: URLs which
+# refer to files which are part of this project must be referenced
+# as string literals so that bundlers' static-analysis tools can
+# find those files and include them in their bundles.
+#
+# -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.
+#
+# To repeat: all node.js builds are 100% untested and unsupported.
+#
+# Most c-pp.D.X are set via $(bin.mkwasmbuilds) and X is a build name.
+# Those make rules reference c-pp.D.64bit, so it should be defined in
+# advance.
+#
c-pp.D.64bit = -Dbits64
#
#
# 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 = \
echo '$(1) $(emo.bug) (disabled because it breaks emsdk 4.0.16+)'
# $(sqlite3.canonical.c) must point to the sqlite3.c in
# the sqlite3 canonical source tree, as that source file
# is required for certain utility and test code.
+#
sqlite3.canonical.c = $(dir.top)/sqlite3.c
sqlite3.c ?= $(firstword $(wildcard $(dir.top)/sqlite3-see.c) $(sqlite3.canonical.c))
sqlite3.h = $(dir $(sqlite3.c))/sqlite3.h
# 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.
+#
bin.version-info = ./version-info
$(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
$(CC) -o $@ -I$(dir $(sqlite3.h)) $(dir.tool)/version-info.c
t-version-info: $(bin.version-info)
DISTCLEAN_FILES += $(bin.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 $@ $<
t-stripccomments: $(bin.stripccomments)
DISTCLEAN_FILES += $(bin.stripccomments)
-
ifeq (1,$(MAKING_CLEAN))
SQLITE_C_IS_SEE = 0
else
# undefine barebones # relatively new gmake feature, not ubiquitous
#
-# It's important that sqlite3.h be built to completion before any
+# It's important that sqlite3.[ch] 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
# $(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 = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_TEMP_STORE=2 \
# removing them from this list will serve only to break the speedtest1
# builds.
+#
# Currently always needed but TODO is paring tester1.c-pp.js down
# to be able to run without this:
+#
SQLITE_OPT.common += -DSQLITE_WASM_ENABLE_C_TESTS
+#
# Extra flags for full-featured builds...
+#
SQLITE_OPT.full-featured = \
-DSQLITE_ENABLE_BYTECODE_VTAB \
-DSQLITE_ENABLE_DBPAGE_VTAB \
# -DSQLITE_OMIT_WINDOWFUNC
endif
+#
#SQLITE_OPT += -DSQLITE_DEBUG
# Enabling SQLITE_DEBUG will break sqlite3_wasm_vfs_create_file()
# (and thus sqlite3_js_vfs_create_file()). Those functions are
# 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:
#
# SQLITE_OMIT_DEPRECATED
# SQLITE_OMIT_UTF16
# SQLITE_OMIT_SHARED_CACHE
-########################################################################
-
+#
-########################################################################
+#
# Adding custom C code via sqlite3_wasm_extra_init.c:
#
# If the canonical build process finds the file
# make sqlite3_wasm_extra_init.c=my_custom_stuff.c
#
# See example_extra_init.c for an example implementation.
-########################################################################
+#
sqlite3_wasm_extra_init.c ?= $(wildcard sqlite3_wasm_extra_init.c)
cflags.wasm_extra_init =
ifneq (,$(sqlite3_wasm_extra_init.c))
#
WASM_CUSTOM_INSTANTIATE = 1
-########################################################################
+#
# $(bin.c-pp): a minimal text file preprocessor. Like C's but much
# less so.
#
#
# -D... flags which should be included in all invocations should be
# appended to $(b.c-pp.target.flags).
+#
bin.c-pp = ./c-pp-lite
$(bin.c-pp): c-pp-lite.c $(sqlite3.c) $(MAKEFILE)
$(CC) -O0 -o $@ c-pp-lite.c $(sqlite3.c) '-DCMPP_DEFAULT_DELIM="//#"' -I$(dir.top) \
b.c-pp.target.flags += -Denable-see
endif
+#
# cflags.common = C compiler flags for all builds
cflags.common = -I. -I$(dir $(sqlite3.c)) -std=c99 -fPIC
# emcc.WASM_BIGINT = 1 for BigInt (C int64) support, else 0. The API
# _are not tested_ on any regular basis.
emcc.WASM_BIGINT ?= 1
emcc.MEMORY64 ?= 0
-########################################################################
+#
# https://emscripten.org/docs/tools_reference/settings_reference.html#memory64
#
# 64-bit build requires wasm-strip 1.0.36 (maybe 1.0.35, but not
# 1.0.34) or will fail to strip with "tables may not be 64-bit".
-########################################################################
+#
+#
# 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.
# -O2 (which consistently creates the fastest-running deliverables).
# Build time suffers greatly compared to -O0, which is why -O0 is the
# default.
+#
ifeq (,$(filter $(OPTIMIZED_TARGETS),$(MAKECMDGOALS)))
emcc_opt ?= -O0
else
emcc_opt ?= -Oz
endif
+#
# 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
# ^^^ ALWAYS use -g3. See below for why.
#
# Much practice has demonstrated that -O2 consistently gives the best
# runtime speeds, but not by a large enough factor to rule out use of
# -Oz when smaller deliverable size is a priority.
-########################################################################
+#
-########################################################################
+#
# EXPORTED_FUNCTIONS.* = files for use with Emscripten's
# -sEXPORTED_FUNCTION flag.
+#
EXPORTED_FUNCTIONS.api.in = $(dir.api)/EXPORTED_FUNCTIONS.c-pp
EXPORTED_FUNCTIONS.api = $(dir.tmp)/EXPORTED_FUNCTIONS.api
EXPORTED_FUNCTIONS.c-pp.flags =
$(EXPORTED_FUNCTIONS.api),\
$(EXPORTED_FUNCTIONS.c-pp.flags)))
-########################################################################
+#
# emcc flags for .c/.o/.wasm/.js.
+#
emcc.flags =
ifeq (1,$(emcc.verbose))
emcc.flags += -v
$(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
-########################################################################
-#emcc.jsflags += -sMEMORY64=$(emcc.MEMORY64)
+#
emcc.jsflags += $(emcc.environment)
emcc.jsflags += -sSTACK_SIZE=512KB
# VFS, which requires twice that for its xRead() and xWrite() methods.
# 2023-03: those methods have since been adapted to use a malloc()'d
# buffer.
-########################################################################
+
+#
# $(sqlite3.js.init-func) is the name Emscripten assigns our exported
# module init/load function. This symbol name is hard-coded in
# $(extern-post-js.js) as well as in numerous docs.
#emcc.jsflags += --experimental-pic --unresolved-symbols=ingore-all --import-undefined
#emcc.jsflags += --unresolved-symbols=ignore-all
-########################################################################
+#
# -sSINGLE_FILE:
# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js
#
# cannot wasm-strip the binary before it gets encoded into the JS
# file. The result is that the generated JS file is, because of the
# -g3 debugging info, _huge_.
-########################################################################
-
-
-sqlite3.wasm = $(dir.dout)/sqlite3.wasm
-sqlite3-wasm.c = $(dir.api)/sqlite3-wasm.c
-sqlite3-wasm.c.in = $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.c)
+#
#
# b.call.patch-export-default is used by mkwasmbuilds.c and the
fi
endef
-#
-# The various -D... values used by *.c-pp.js include:
-#
-# -Dtarget:es6-module: for all ESM module builds
-#
-# -Dtarget:node: for node.js builds
-#
-# -Dtarget:es6-module -Dtarget:es6-bundler-friendly: intended for
-# "bundler-friendly" ESM module build. These have some restrictions
-# on how URL() objects are constructed in some contexts: URLs which
-# refer to files which are part of this project must be referenced
-# as string literals so that bundlers' static-analysis tools can
-# find those files and include them in their bundles.
-#
-# -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.
-#
-# To repeat: all node.js builds are 100% untested and unsupported.
-#
-########################################################################
-
#
# Inputs/outputs for the sqlite3-api.js family.
#
# end wasmfs (the rest is in mkwasmbuilds.c)
#
+#
+#
+#
+sqlite3-wasm.c = $(dir.api)/sqlite3-wasm.c
+# List of input files for compiling $(sqlite3-wasm.c). That file
+# #include's sqlite3.c directly, so it's implicitly includes here.
+sqlite3-wasm.c.in = $(sqlite3-wasm.c) $(sqlite3_wasm_extra_init.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
# we don't otherwise have a great place to attach them such that
# they're always copied when we need them.
#
+# The var $(out.$(B).js) comes from $(bin.mkwasmbuilds).
+#
$(foreach B,$(b.names),$(eval $(out.$(B).js): $(sqlite3.ext.js)))
#
# b-all: builds all available js/wasm builds.
#
# 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
+# $1 = build name to have a dep on
# $2 = suffix for tester1SUFFIX JS
# $3 = $(bin.c-pp) flags
$(call b.c-pp.target,test,tester1.c-pp.js,tester1$(2),$(3))
tester1: tester1$(2)
endef
-$(eval $(call gen-tester1.js,vanilla,.js, \
- $(c-pp.D.vanilla) \
- -Dsqlite3.js=$(dir.dout)/sqlite3.js))
-$(eval $(call gen-tester1.js,vanilla64,-64bit.js, \
- $(c-pp.D.vanilla64) \
- -Dsqlite3.js=$(dir.dout)/sqlite3-64bit.js))
-$(eval $(call gen-tester1.js,esm,.mjs, \
- $(c-pp.D.esm) \
- -Dsqlite3.js=$(dir.dout)/sqlite3.mjs))
-$(eval $(call gen-tester1.js,esm64,-64bit.mjs, \
- $(c-pp.D.esm64) \
- -Dsqlite3.js=$(dir.dout)/sqlite3-64bit.mjs))
+$(eval $(call gen-tester1.js,vanilla,.js,\
+ $(c-pp.D.vanilla) -Dsqlite3.js=$(dir.dout)/sqlite3.js))
+$(eval $(call gen-tester1.js,vanilla64,-64bit.js,\
+ $(c-pp.D.vanilla64) -Dsqlite3.js=$(dir.dout)/sqlite3-64bit.js))
+$(eval $(call gen-tester1.js,esm,.mjs,\
+ $(c-pp.D.esm) -Dsqlite3.js=$(dir.dout)/sqlite3.mjs))
+$(eval $(call gen-tester1.js,esm64,-64bit.mjs,\
+ $(c-pp.D.esm64) -Dsqlite3.js=$(dir.dout)/sqlite3-64bit.mjs))
+#
# tester1.html variants:
+#
define gen-tester1.html
# $1 = build name to have a dep on
# $2 = filename suffix: empty, -64bit, -esm, esm-64bit
-Dtester1.js=tester1-64bit.mjs \
-Dsqlite3.js=$(dir.dout)/sqlite3-64bit.mjs))
-# 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.
+#
+# tester1-worker.html variants: There is no ESM variant of this
+# file. Instead, that page accepts the ?esm URL flag to switch to ESM
+# mode.
+#
$(eval $(call b.c-pp.target,test,tester1-worker.c-pp.html,\
tester1-worker.html,-Dbitness=32))
$(eval $(call b.c-pp.target,test,tester1-worker.c-pp.html,\
tester1-worker-64bit.html: tester1-64bit.mjs
all: tester1
+#
# end tester1
-########################################################################
+#
#
# Convenience rules to rebuild with various -Ox levels. Much
#
# 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))
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
dist-name-prefix = sqlite-wasm$(dist-name-extra)
.PHONY: dist
dist:
- ./mkdist.sh $(dist-name-prefix)
+ $(bin.bash) ./mkdist.sh $(dist-name-prefix)
snapshot:
- ./mkdist.sh $(dist-name-prefix) --snapshot
+ $(bin.bash) ./mkdist.sh $(dist-name-prefix) --snapshot
endif
# ^^^ making dist/snapshot
CLEAN_FILES += $(wildcard sqlite-wasm-*.zip)