xref: /sqlite-3.40.0/ext/wasm/GNUmakefile (revision eb97743c)
1########################################################################
2# This GNU makefile drives the build of the sqlite3 WASM
3# components. It is not part of the canonical build process.
4########################################################################
5SHELL := $(shell which bash 2>/dev/null)
6MAKEFILE := $(lastword $(MAKEFILE_LIST))
7all:
8release: all
9
10# Emscripten SDK home dir and related binaries...
11EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/src/emsdk $(HOME)/emsdk))
12emcc.bin ?= $(word 1,$(wildcard $(shell which emcc) $(EMSDK_HOME)/upstream/emscripten/emcc))
13ifeq (,$(emcc.bin))
14  $(error Cannot find emcc.)
15endif
16
17wasm-strip ?= $(shell which wasm-strip 2>/dev/null)
18ifeq (,$(filter clean,$(MAKECMDGOALS)))
19ifeq (,$(wasm-strip))
20  $(info WARNING: *******************************************************************)
21  $(info WARNING: builds using -O2/-O3/-Os/-Oz will minify WASM-exported names,)
22  $(info WARNING: breaking _All The Things_. The workaround for that is to build)
23  $(info WARNING: with -g3 (which explodes the file size) and then strip the debug)
24  $(info WARNING: info after compilation, using wasm-strip, to shrink the wasm file.)
25  $(info WARNING: wasm-strip was not found in the PATH so we cannot strip those.)
26  $(info WARNING: If this build uses any optimization level higher than -O1 then)
27  $(info WARNING: the ***resulting WASM binary WILL NOT BE USABLE***.)
28  $(info WARNING: wasm-strip is part of the wabt package:)
29  $(info WARNING:    https://github.com/WebAssembly/wabt)
30  $(info WARNING: on Ubuntu-like systems it can be installed with:)
31  $(info WARNING:    sudo apt install wabt)
32  $(info WARNING: *******************************************************************)
33endif
34endif # 'make clean' check
35
36ifeq (,$(wasm-strip))
37  maybe-wasm-strip = echo "not wasm-stripping"
38else
39  maybe-wasm-strip = $(wasm-strip)
40endif
41
42dir.top := ../..
43# Reminder: some Emscripten flags require absolute paths
44dir.wasm := $(patsubst %/,%,$(dir $(abspath $(MAKEFILE))))
45dir.api := api
46dir.jacc := jaccwabyt
47dir.common := common
48dir.fiddle := fiddle
49CLEAN_FILES := *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~
50emcc_enable_bigint ?= 1
51sqlite3.c := $(dir.top)/sqlite3.c
52SQLITE_OPT = \
53  -DSQLITE_ENABLE_FTS4 \
54  -DSQLITE_ENABLE_RTREE \
55  -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
56  -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \
57  -DSQLITE_ENABLE_STMTVTAB \
58  -DSQLITE_ENABLE_DBPAGE_VTAB \
59  -DSQLITE_ENABLE_DBSTAT_VTAB \
60  -DSQLITE_ENABLE_BYTECODE_VTAB \
61  -DSQLITE_ENABLE_OFFSET_SQL_FUNC \
62  -DSQLITE_OMIT_LOAD_EXTENSION \
63  -DSQLITE_OMIT_DEPRECATED \
64  -DSQLITE_OMIT_UTF16 \
65  -DSQLITE_OMIT_SHARED_CACHE \
66  -DSQLITE_THREADSAFE=0 \
67  -DSQLITE_TEMP_STORE=3 \
68  -DSQLITE_OS_KV_OPTIONAL=1 \
69  '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \
70  -DSQLITE_USE_URI=1
71#SQLITE_OPT += -DSQLITE_ENABLE_MEMSYS5
72# ^^^ MEMSYS5 is hypothetically useful for non-Emscripten builds but
73# requires adding more infrastructure and fixing one spot in the
74# sqlite3 internals which calls malloc() early on.
75
76# SQLITE_OMIT_LOAD_EXTENSION: if this is true, sqlite3_vfs::xDlOpen
77# and friends may be NULL.
78
79ifneq (,$(filter release,$(MAKECMDGOALS)))
80emcc_opt ?= -Oz -g3 -flto
81else
82emcc_opt ?= -O0 -g3
83# ^^^^ build times for -O levels higher than 0 are painful at
84# dev-time.
85endif
86# ^^^ -flto improves runtime speed at -O0 considerably but doubles
87# build time.
88#
89# ^^^^ -O3, -Oz, -Os minify symbol names and there appears to be no
90# way around that except to use -g3, but -g3 causes the binary file
91# size to absolutely explode (approx. 5x larger). This minification
92# utterly breaks the resulting module, making it unsable except as
93# self-contained/self-referential-only code, as ALL of the exported
94# symbols get minified names.
95#
96# However, we have an option for using -Oz or -Os:
97#
98# Build with (-Os -g3) or (-Oz -g3) then use wasm-strip, from the wabt
99# tools package (https://github.com/WebAssembly/wabt), to strip the
100# debugging symbols. That results in a small build with unmangled
101# symbol names. -Oz gives ever-so-slightly better compression than
102# -Os: not quite 1% in some completely unscientific tests. Runtime
103# speed for the unit tests is all over the place either way so it's
104# difficult to say whether -Os gives any speed benefit over -Oz.
105########################################################################
106
107
108$(sqlite3.c):
109	$(MAKE) -C $(dir.top) sqlite3.c
110
111clean:
112	-rm -f $(CLEAN_FILES)
113
114ifeq (release,$(filter release,$(MAKECMDGOALS)))
115  ifeq (,$(wasm-strip))
116    $(error Cannot make release-quality binary because wasm-strip is not available. \
117            See notes in the warning above)
118  endif
119else
120  $(info Development build. Use '$(MAKE) release' for a smaller release build.)
121endif
122
123EXPORTED_FUNCTIONS.api.in := $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api \
124    $(dir.jacc)/jaccwabyt_test.exports
125
126EXPORTED_FUNCTIONS.api: $(EXPORTED_FUNCTIONS.api.in) $(MAKEFILE)
127	cat $(EXPORTED_FUNCTIONS.api.in) > $@
128CLEAN_FILES += EXPORTED_FUNCTIONS.api
129
130sqlite3-api.jses := $(dir.api)/sqlite3-api-prologue.js
131sqlite3-api.jses += $(dir.common)/whwasmutil.js
132sqlite3-api.jses += $(dir.jacc)/jaccwabyt.js
133sqlite3-api.jses += $(dir.api)/sqlite3-api-glue.js
134sqlite3-api.jses += $(dir.api)/sqlite3-api-oo1.js
135sqlite3-api.jses += $(dir.api)/sqlite3-api-worker1.js
136sqlite3-api.jses += $(dir.api)/sqlite3-api-opfs.js
137sqlite3-api.jses += $(dir.api)/sqlite3-api-cleanup.js
138
139sqlite3-api.js := sqlite3-api.js
140CLEAN_FILES += $(sqlite3-api.js)
141$(sqlite3-api.js): $(sqlite3-api.jses) $(MAKEFILE)
142	@echo "Making $@..."
143	@for i in $(sqlite3-api.jses); do \
144		echo "/* BEGIN FILE: $$i */"; \
145		cat $$i; \
146		echo "/* END FILE: $$i */"; \
147	done > $@
148
149post-js.js := post-js.js
150CLEAN_FILES += $(post-js.js)
151post-jses := \
152  $(dir.api)/post-js-header.js \
153  $(sqlite3-api.js) \
154  $(dir.api)/post-js-footer.js
155$(post-js.js): $(post-jses) $(MAKEFILE)
156	@echo "Making $@..."
157	@for i in $(post-jses); do \
158		echo "/* BEGIN FILE: $$i */"; \
159		cat $$i; \
160		echo "/* END FILE: $$i */"; \
161	done > $@
162extern-post-js.js := $(dir.api)/extern-post-js.js
163sqlite3.js.flags.--post-js := --post-js=$(post-js.js) --extern-post-js=$(extern-post-js.js)
164post-jses.deps := $(post-js.js) $(extern-post-js.js)
165
166########################################################################
167# emcc flags for .c/.o/.wasm/.js.
168emcc.flags =
169#emcc.flags += -v # _very_ loud but also informative about what it's doing
170# -g is needed to keep -O2 and higher from creating broken JS via
171# minification.
172
173########################################################################
174# emcc flags for .c/.o.
175emcc.cflags :=
176emcc.cflags += -std=c99 -fPIC
177# -------------^^^^^^^^ we currently need c99 for WASM-specific sqlite3 APIs.
178emcc.cflags += -I. -I$(dir.top)
179
180########################################################################
181# emcc flags specific to building the final .js/.wasm file...
182emcc.jsflags := -fPIC
183emcc.jsflags += --minify 0
184emcc.jsflags += --no-entry
185emcc.jsflags += -sMODULARIZE
186emcc.jsflags += -sSTRICT_JS
187emcc.jsflags += -sDYNAMIC_EXECUTION=0
188emcc.jsflags += -sNO_POLYFILL
189emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(dir.wasm)/EXPORTED_FUNCTIONS.api
190emcc.exportedRuntimeMethods := \
191    -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory,allocateUTF8OnStack
192    # FS ==> stdio/POSIX I/O proxies
193    # wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY
194    # allocateUTF8OnStack => for kvvfs internals
195emcc.jsflags += $(emcc.exportedRuntimeMethods)
196emcc.jsflags += -sUSE_CLOSURE_COMPILER=0
197emcc.jsflags += -sIMPORTED_MEMORY
198emcc.environment := -sENVIRONMENT=web
199emcc.jsflags += -sALLOW_MEMORY_GROWTH
200# emcc: warning: USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code
201#       slowly, see https://github.com/WebAssembly/design/issues/1271
202#       [-Wpthreads-mem-growth]
203emcc.jsflags += -sINITIAL_MEMORY=13107200
204#emcc.jsflags += -sINITIAL_MEMORY=64225280
205# ^^^^ 64MB is not enough for WASMFS/OPFS test runs using batch-runner.js
206emcc.jsflags += $(emcc.environment)
207#emcc.jsflags += -sTOTAL_STACK=4194304
208
209sqlite3.js.init-func := sqlite3InitModule
210# ^^^^ $(sqlite3.js.init-func) symbol name is hard-coded in $(extern-post-js.js)
211
212emcc.jsflags += -sEXPORT_NAME=$(sqlite3.js.init-func)
213emcc.jsflags += -sGLOBAL_BASE=4096 # HYPOTHETICALLY keep func table indexes from overlapping w/ heap addr.
214#emcc.jsflags += -sSTRICT # fails due to missing __syscall_...()
215#emcc.jsflags += -sALLOW_UNIMPLEMENTED_SYSCALLS
216#emcc.jsflags += -sFILESYSTEM=0 # only for experimentation. sqlite3 needs the FS API
217#emcc.jsflags += -sABORTING_MALLOC
218emcc.jsflags += -sALLOW_TABLE_GROWTH
219emcc.jsflags += -Wno-limited-postlink-optimizations
220# ^^^^^ it likes to warn when we have "limited optimizations" via the -g3 flag.
221#emcc.jsflags += -sSTANDALONE_WASM # causes OOM errors, not sure why
222# https://lld.llvm.org/WebAssembly.html
223emcc.jsflags += -sERROR_ON_UNDEFINED_SYMBOLS=0
224emcc.jsflags += -sLLD_REPORT_UNDEFINED
225#emcc.jsflags += --allow-undefined
226emcc.jsflags += --import-undefined
227#emcc.jsflags += --unresolved-symbols=import-dynamic --experimental-pic
228#emcc.jsflags += --experimental-pic --unresolved-symbols=ingore-all --import-undefined
229#emcc.jsflags += --unresolved-symbols=ignore-all
230emcc.jsflags += -sWASM_BIGINT=$(emcc_enable_bigint)
231# ^^^^ MEMORY64=1 fails to load, erroring with:
232#  invalid memory limits flags 0x5
233#    (enable via --experimental-wasm-memory64)
234#
235# ^^^^ MEMORY64=2 builds and loads but dies when we do things like:
236#
237#  new Uint8Array(heapWrappers().HEAP8U.buffer, ptr, n)
238#
239# because ptr is now a BigInt, so is invalid for passing to arguments
240# which have strict must-be-a-Number requirements.
241########################################################################
242
243
244########################################################################
245# -sSINGLE_FILE:
246# https://github.com/emscripten-core/emscripten/blob/main/src/settings.js#L1704
247# -sSINGLE_FILE=1 would be really nice but we have to build with -g
248# for -O2 and higher to work (else minification breaks the code) and
249# cannot wasm-strip the binary before it gets encoded into the JS
250# file. The result is that the generated JS file is, because of the -g
251# debugging info, _huge_.
252########################################################################
253
254########################################################################
255# Maintenance reminder: the output .js and .wasm files of emcc must be
256# in _this_ dir, rather than a subdir, or else parts of the generated
257# code get confused and cannot load property (namely, the
258# sqlite3.worker.js generated in conjunction with -sWASMFS).
259sqlite3.js := sqlite3.js
260emcc.jsflags += $(sqlite3.js.flags.--post-js)
261sqlite3.wasm := sqlite3.wasm
262sqlite3-wasm.o := $(dir.api)/sqlite3-wasm.o
263$(sqlite3-wasm.o): emcc.cflags += $(SQLITE_OPT)
264$(sqlite3-wasm.o): $(dir.top)/sqlite3.c
265sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c
266jaccwabyt_test.c := $(dir.jacc)/jaccwabyt_test.c
267# ^^^ FIXME (how?): jaccwabyt_test.c is only needed for the test apps,
268# so we don't really want to include it in release builds. However, we
269# want to test the release builds with those apps, so we cannot simply
270# elide that file in release builds. That component is critical to the
271# VFS bindings so needs to be tested along with the core APIs.
272define WASM_C_COMPILE
273$(1).o := $$(subst .c,.o,$(1))
274sqlite3.wasm.obj += $$($(1).o)
275$$($(1).o): $$(MAKEFILE) $(1)
276	$$(emcc.bin) $$(emcc_opt) $$(emcc.flags) $$(emcc.cflags) -c $(1) -o $$@
277CLEAN_FILES += $$($(1).o)
278endef
279$(foreach c,$(sqlite3-wasm.c) $(jaccwabyt_test.c),$(eval $(call WASM_C_COMPILE,$(c))))
280$(sqlite3.js): $(MAKEFILE) $(sqlite3.wasm.obj) \
281    EXPORTED_FUNCTIONS.api \
282    $(post-jses.deps)
283	@echo "Building $@ ..."
284	$(emcc.bin) -o $@ $(emcc_opt) $(emcc.flags) $(emcc.jsflags) $(sqlite3.wasm.obj)
285	chmod -x $(sqlite3.wasm)
286	$(maybe-wasm-strip) $(sqlite3.wasm)
287	@ls -la $@ $(sqlite3.wasm)
288
289CLEAN_FILES += $(sqlite3.js) $(sqlite3.wasm)
290all: $(sqlite3.js)
291wasm: $(sqlite3.js)
292# End main Emscripten-based module build
293########################################################################
294
295########################################################################
296# batch-runner.js...
297dir.sql := sql
298speedtest1 := ../../speedtest1
299speedtest1.c := ../../test/speedtest1.c
300speedtest1.sql := $(dir.sql)/speedtest1.sql
301speedtest1.cliflags := --size 25 --big-transactions
302$(speedtest1):
303	$(MAKE) -C ../.. speedtest1
304$(speedtest1.sql): $(speedtest1) $(MAKEFILE)
305	$(speedtest1) $(speedtest1.cliflags) --script $@
306batch-runner.list: $(MAKEFILE) $(speedtest1.sql) $(dir.sql)/000-mandelbrot.sql
307	bash split-speedtest1-script.sh $(dir.sql)/speedtest1.sql
308	ls -1 $(dir.sql)/*.sql | grep -v speedtest1.sql | sort > $@
309clean-batch:
310	rm -f batch-runner.list $(dir.sql)/speedtest1*.sql
311# ^^^ we don't do this along with 'clean' because we clean/rebuild on
312# a regular basis with different -Ox flags and rebuilding the batch
313# pieces each time is an unnecessary time sink.
314batch: batch-runner.list
315all: batch
316# end batch-runner.js
317########################################################################
318# speedtest1.js...
319# speedtest1-common.eflags = emcc flags used by multiple builds of speedtest1
320# speedtest1.eflags = emcc flags used by main build of speedtest1
321speedtest1-common.eflags := -g $(emcc_opt)
322speedtest1.eflags :=
323speedtest1.eflags += -sENVIRONMENT=web
324speedtest1-common.eflags += -sINVOKE_RUN=0
325speedtest1-common.eflags += --no-entry
326#speedtest1-common.eflags += -flto
327speedtest1-common.eflags += -sABORTING_MALLOC
328speedtest1-common.eflags += -sINITIAL_MEMORY=128450560
329speedtest1-common.eflags += -sSTRICT_JS
330speedtest1-common.eflags += -sMODULARIZE
331speedtest1-common.eflags += -Wno-limited-postlink-optimizations
332speedtest1-common.eflags += -sEXPORTED_FUNCTIONS=@$(dir.wasm)/EXPORTED_FUNCTIONS.speedtest1
333speedtest1-common.eflags += $(emcc.exportedRuntimeMethods)
334speedtest1-common.eflags += -sALLOW_TABLE_GROWTH
335speedtest1-common.eflags += -sDYNAMIC_EXECUTION=0
336speedtest1-common.eflags += --minify 0
337speedtest1-common.eflags += -sEXPORT_NAME=$(sqlite3.js.init-func)
338speedtest1-common.eflags += $(sqlite3.js.flags.--post-js)
339speedtest1-common.eflags += -sWASM_BIGINT=$(emcc_enable_bigint)
340speedtest1.exit-runtime0 := -sEXIT_RUNTIME=0
341speedtest1.exit-runtime1 := -sEXIT_RUNTIME=1
342# Re -sEXIT_RUNTIME=1 vs 0: if it's 1 and speedtest1 crashes, we get
343# this error from emscripten:
344#
345# > native function `free` called after runtime exit (use
346# NO_EXIT_RUNTIME to keep it alive after main() exits))
347#
348# If it's 0 and it crashes, we get:
349#
350# > stdio streams had content in them that was not flushed. you should
351# set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline
352# when you printf etc.
353#
354# and pending output is not flushed because it didn't end with a
355# newline (by design). The lesser of the two evils seems to be
356# -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app
357# which runs speedtest1 multiple times.
358
359EXPORTED_FUNCTIONS.speedtest1: EXPORTED_FUNCTIONS.api
360	{ echo _wasm_main; cat EXPORTED_FUNCTIONS.api; } > $@
361CLEAN_FILES += EXPORTED_FUNCTIONS.speedtest1
362speedtest1.js := speedtest1.js
363speedtest1.wasm := $(subst .js,.wasm,$(speedtest1.js))
364speedtest1.cflags := \
365  -I. -I.. -I$(dir.top) \
366  -DSQLITE_SPEEDTEST1_WASM
367speedtest1.cs := $(speedtest1.c) $(sqlite3-wasm.c) $(jaccwabyt_test.c)
368$(speedtest1.js): emcc.cflags+=
369# speedtest1 notes re. sqlite3-wasm.o vs sqlite3-wasm.c: building against
370# the latter (predictably) results in a slightly faster binary, but we're
371# close enough to the target speed requirements that the 500ms makes a
372# difference.
373$(speedtest1.js): $(MAKEFILE) $(speedtest1.cs) $(post-jses.deps) \
374    EXPORTED_FUNCTIONS.speedtest1
375	@echo "Building $@ ..."
376	$(emcc.bin) \
377        $(speedtest1.eflags) $(speedtest1-common.eflags) $(speedtest1.cflags) \
378        $(SQLITE_OPT) \
379        $(speedtest1.exit-runtime0) \
380        -o $@ $(speedtest1.cs) -lm
381	$(maybe-wasm-strip) $(speedtest1.wasm)
382	ls -la $@ $(speedtest1.wasm)
383
384speedtest1: $(speedtest1.js)
385all: speedtest1
386CLEAN_FILES += $(speedtest1.js) $(speedtest1.wasm)
387# end speedtest1.js
388########################################################################
389
390########################################################################
391# fiddle_remote is the remote destination for the fiddle app. It
392# must be a [user@]HOST:/path for rsync.
393# Note that the target "should probably" contain a symlink of
394# index.html -> fiddle.html.
395fiddle_remote ?=
396ifeq (,$(fiddle_remote))
397ifneq (,$(wildcard /home/stephan))
398  fiddle_remote = wh:www/wh/sqlite3/.
399else ifneq (,$(wildcard /home/drh))
400  #fiddle_remote = if appropriate, add that user@host:/path here
401endif
402endif
403$(fiddle_files): default
404push-fiddle: $(fiddle_files)
405	@if [ x = "x$(fiddle_remote)" ]; then \
406		echo "fiddle_remote must be a [user@]HOST:/path for rsync"; \
407		exit 1; \
408	fi
409	rsync -va fiddle/ $(fiddle_remote)
410# end fiddle remote push
411########################################################################
412
413########################################################################
414# Convenience rules to rebuild with various -Ox levels. Much
415# experimentation shows -O2 to be the clear winner in terms of speed.
416# Note that build times with anything higher than -O0 are somewhat
417# painful.
418
419.PHONY: o0 o1 o2 o3 os oz
420o-xtra := -g3
421# ^^^ -g3 is important to keep higher -O levels from mangling (via
422# minification), or outright removing, otherwise working code.
423
424o-xtra += -flto
425# ^^^^ -flto can have a considerably performance boost at -O0 but
426# doubles the build time and seems to have negligible effect on
427# higher optimization levels.
428o0: clean
429	$(MAKE) -e "emcc_opt=-O0 $(o-xtra)" fiddle_opt=-O0
430o1: clean
431	$(MAKE) -e "emcc_opt=-O1 $(o-xtra)" fiddle_opt=-O1
432o2: clean
433	$(MAKE) -e "emcc_opt=-O2 $(o-xtra)" fiddle_opt=-O2
434o3: clean
435	$(MAKE) -e "emcc_opt=-O3 $(o-xtra)" fiddle_opt=-O3
436os: clean
437	@echo "WARNING: -Os can result in a build with mysteriously missing pieces!"
438	$(MAKE) -e "emcc_opt=-Os $(o-xtra)" fiddle_opt=-Os
439oz: clean
440	$(MAKE) -e "emcc_opt=-Oz $(o-xtra)" fiddle_opt=-Oz
441
442########################################################################
443# Sub-makes...
444
445include fiddle.make
446
447########################################################################
448# Some platforms do not support the WASMFS build. Raspberry Pi OS is one
449# of them. As such platforms are discovered, add their (uname -m) name
450# to PLATFORMS_WITH_NO_WASMFS to exclude the wasmfs build parts.
451PLATFORMS_WITH_NO_WASMFS := aarch64 # add any others here
452THIS_ARCH := $(shell /usr/bin/uname -m)
453ifneq (,$(filter $(THIS_ARCH),$(PLATFORMS_WITH_NO_WASMFS)))
454$(info This platform does not support the WASMFS build.)
455else
456include wasmfs.make
457endif
458
459########################################################################
460# Push files to public wasm-testing.sqlite.org server
461wasm-testing.include = *.wasm *.js *.html \
462    batch-runner.list sql common fiddle jaccwabyt
463wasm-testing.exclude = sql/speedtest1.sql
464wasm-testing.dir     = /jail/sites/wasm-testing
465wasm-testing.dest   ?= wasm-testing:$(wasm-testing.dir)
466# ---------------------^^^^^^^^^^^^ ssh alias
467push:
468	rsync -z -e ssh --ignore-times --chown=stephan:www-data --group -r \
469    $(patsubst %,--exclude=%,$(wasm-testing.exclude)) \
470    $(wasm-testing.include) $(wasm-testing.dest)
471	ssh wasm-testing 'cd $(wasm-testing.dir) && bash .gzip' || \
472    echo "SSH failed: it's likely that stale content will be served via old gzip files."
473
474