diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index a683a91416..881eabfac9 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -1,11 +1,29 @@ ######################################################################## # This GNU makefile drives the build of the sqlite3 WASM # components. It is not part of the canonical build process. +# +# This build assumes a Linux platform and is not intended for +# client-level use. It is for the sqlite project's own development of +# the JS/WASM components. +# +# Primary targets: +# +# 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. +# +# dist = create end user deliverables. Add dist-opt=oX to build with a +# specific optimization level, where oX is one of the above-listed +# o? target names. +# +# clean = clean up ######################################################################## SHELL := $(shell which bash 2>/dev/null) MAKEFILE := $(lastword $(MAKEFILE_LIST)) -all: -release: all +default: all +release: default # Emscripten SDK home dir and related binaries... EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/src/emsdk $(HOME)/emsdk)) @@ -46,7 +64,9 @@ dir.api := api dir.jacc := jaccwabyt dir.common := common dir.fiddle := fiddle +dir.tool := $(dir.top)/tool CLEAN_FILES := *~ $(dir.jacc)/*~ $(dir.api)/*~ $(dir.common)/*~ +DISTCLEAN_FILES := ./-dummy emcc_enable_bigint ?= 1 sqlite3.c := $(dir.top)/sqlite3.c sqlite3.h := $(dir.top)/sqlite3.h @@ -113,8 +133,11 @@ emcc_opt_full := $(emcc_opt) -g3 $(sqlite3.c) $(sqlite3.h): $(MAKE) -C $(dir.top) sqlite3.c +.PHONY: clean distclean clean: -rm -f $(CLEAN_FILES) +distclean: clean + -rm -f $(DISTCLEAN_FILES) ifeq (release,$(filter release,$(MAKECMDGOALS))) ifeq (,$(wasm-strip)) @@ -128,7 +151,12 @@ endif version-info := $(dir.wasm)/version-info $(version-info): $(dir.wasm)/version-info.c $(sqlite3.h) $(MAKEFILE) $(CC) -O0 -I$(dir.top) -o $@ $< -CLEAN_FILES := $(version-info) +DISTCLEAN_FILES += $(version-info) + +stripccomments := $(dir.tool)/stripccomments +$(stripccomments): $(stripccomments).c $(MAKEFILE) + $(CC) -o $@ $< +DISTCLEAN_FILES += $(stripccomments) EXPORTED_FUNCTIONS.api.in := $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api @@ -480,11 +508,7 @@ push-fiddle: $(fiddle_files) # painful. .PHONY: o0 o1 o2 o3 os oz -o-xtra := -g3 -# ^^^ -g3 is important to keep higher -O levels from mangling (via -# minification), or outright removing, otherwise working code. - -o-xtra += -flto +o-xtra := -flto # ^^^^ -flto can have a considerably performance boost at -O0 but # doubles the build time and seems to have negligible effect on # higher optimization levels. @@ -515,7 +539,9 @@ PLATFORMS_WITH_NO_WASMFS := aarch64 # add any others here THIS_ARCH := $(shell /usr/bin/uname -m) ifneq (,$(filter $(THIS_ARCH),$(PLATFORMS_WITH_NO_WASMFS))) $(info This platform does not support the WASMFS build.) +HAVE_WASMFS := 0 else +HAVE_WASMFS := 1 include wasmfs.make endif diff --git a/ext/wasm/README-dist.txt b/ext/wasm/README-dist.txt index ecb906acdc..bbc82a1df8 100644 --- a/ext/wasm/README-dist.txt +++ b/ext/wasm/README-dist.txt @@ -15,10 +15,10 @@ This archive contains two related deliverables: but is less portable than the main build, so is provided as a separate binary. -Both directories contain small demonstration apps. Browsers will not -server WASM files from file:// URLs, so the demonstrations require a -web server and that server must include the following headers in its -response when serving the files: +Both directories contain small demonstration and test apps. Browsers +will not serve WASM files from file:// URLs, so the demo/test apps +require a web server and that server must include the following +headers in its response when serving the files: Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp diff --git a/ext/wasm/dist.make b/ext/wasm/dist.make index 84abe393a2..cb13b0bd92 100644 --- a/ext/wasm/dist.make +++ b/ext/wasm/dist.make @@ -9,51 +9,87 @@ ####################################################################### MAKEFILE.dist := $(lastword $(MAKEFILE_LIST)) +ifeq (0,$(HAVE_WASMFS)) +$(error The 'dist' target needs to be run on a WASMFS-capable platform.) +endif ######################################################################## # Chicken/egg situation: we need $(version-info) to get the version -# info for the archive name, but that binary may not yet be built, so -# we have to use a temporary name for the archive. +# info for the archive name, but that binary may not yet be built, and +# won't be built until we expand the dependencies. We have to use a +# temporary name for the archive. dist-name = sqlite-wasm-TEMP dist-archive = $(dist-name).zip - +.PHONY: $(dist-archive) +CLEAN_FILES += $(wildcard sqlite-wasm-*.zip) #ifeq (0,1) # $(info WARNING *******************************************************************) # $(info ** Be sure to create the desired build configuration before creating the) # $(info ** distribution archive. Use one of the following targets to do so:) +# $(info **) # $(info ** o2: builds with -O2, resulting in the fastest builds) # $(info ** oz: builds with -Oz, resulting in the smallest builds) # $(info /WARNING *******************************************************************) #endif +######################################################################## +# dist-opt must be the name of a target which triggers the +# build of the files to be packed into the dist archive. The +# intention is that it be one of (o0, o1, o2, o3, os, oz), each of +# which uses like-named -Ox optimization level flags. The o2 target +# provides the best overall runtime speeds. The oz target provides +# slightly slower speeds (roughly 10%) with significantly smaller WASM +# file sizes. Note that -O2 (the o2 target) results in faster binaries +# than both -O3 and -Os (the o3 and os targets) in all tests run to +# date. +dist-opt ?= oz + demo-123.html := $(dir.wasm)/demo-123.html demo-123-worker.html := $(dir.wasm)/demo-123-worker.html demo-123.js := $(dir.wasm)/demo-123.js -demo-files := $(demo-123.js) $(demo-123.html) $(demo-123-worker.html) +demo-files := $(demo-123.js) $(demo-123.html) $(demo-123-worker.html) \ + tester1.html tester1.js tester1-worker.html README-dist := $(dir.wasm)/README-dist.txt -$(dist-archive): $(sqlite3.wasm) $(sqlite3.js) $(sqlite3-wasmfs.wasm) $(sqlite3-wasmfs.js) -#$(dist-archive): $(sqlite3.h) $(sqlite3.c) $(sqlite3-wasm.c) -$(dist-archive): $(MAKEFILE.dist) $(version-info) $(demo-files) $(README-dist) -$(dist-archive): oz - rm -fr $(dist-name) - mkdir -p $(dist-name)/main $(dist-name)/wasmfs - cp -p $(README-dist) $(dist-name)/README.txt - cp -p $(sqlite3.wasm) $(sqlite3.js) $(dist-name)/main - cp -p $(demo-files) $(dist-name)/main - cp -p $(sqlite3-wasmfs.wasm) $(sqlite3-wasmfs.js) $(dist-name)/wasmfs - for i in $(demo-123.js) $(demo-123.html); do \ +dist-dir-main := $(dist-name)/main +dist-dir-wasmfs := $(dist-name)/wasmfs +######################################################################## +# $(dist-archive): create the end-user deliverable archive. +# +# Maintenance reminder: because $(dist-archive) depends on +# $(dist-opt), and $(dist-opt) will depend on clean, having any deps +# on $(dist-archive) which themselves may be cleaned up by the clean +# target will lead to grief in parallel builds (-j #). Thus +# $(dist-target)'s deps must be trimmed to non-generated files or +# files which are _not_ cleaned up by the clean target. +$(dist-archive): \ + $(stripccomments) $(version-info) \ + $(dist-opt) \ + $(MAKEFILE) $(MAKEFILE.dist) + @echo "Making end-user deliverables..." + @rm -fr $(dist-name) + @mkdir -p $(dist-dir-main) $(dist-dir-wasmfs) + @cp -p $(README-dist) $(dist-name)/README.txt + @cp -p $(sqlite3.wasm) $(dist-dir-main) + @$(stripccomments) -k -k < $(sqlite3.js) \ + > $(dist-dir-main)/$(notdir $(sqlite3.js)) + @cp -p $(demo-files) $(dist-dir-main) + @cp -p $(sqlite3-wasmfs.wasm) sqlite3-wasmfs.worker.js $(dist-dir-wasmfs) + @$(stripccomments) -k -k < $(sqlite3-wasmfs.js) \ + > $(dist-dir-wasmfs)/$(notdir $(sqlite3-wasmfs.js)) + @for i in $(demo-123.js) $(demo-123.html); do \ sed -e 's/\bsqlite3\.js\b/sqlite3-wasmfs.js/' $$i \ - > $(dist-name)/wasmfs/$${i##*/} || exit; \ + > $(dist-dir-wasmfs)/$${i##*/} || exit; \ done - vnum=$$($(version-info) --version-number); \ + @vnum=$$($(version-info) --version-number); \ vdir=sqlite-wasm-$$vnum; \ arc=$$vdir.zip; \ + echo "Making $$arc ..."; \ rm -f $$arc; \ mv $(dist-name) $$vdir; \ zip -qr $$arc $$vdir; \ rm -fr $$vdir; \ ls -la $$arc; \ - unzip -l $$arc + unzip -lv $$arc || echo "Missing unzip app? Not fatal." #$(shell $(version-info) --version-number) dist: $(dist-archive) diff --git a/manifest b/manifest index cb6da43b72..40f33190d9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\stest\sfile\swindowE.test,\sto\stest\sthe\swindow\sfunctions\smodules\sresponse\sto\san\sinconsistent\scollation\ssequence. -D 2022-10-18T15:02:08.725 +C More\swork\son\sthe\sJS\send-user\sdeliverables.\sAdd\stool/stripccomments.c\sto\ssupport\sthat. +D 2022-10-18T20:36:50.562 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -473,8 +473,8 @@ F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c F ext/wasm/EXPORTED_RUNTIME_METHODS.fiddle 0e88c8cfc3719e4b7e74980d9da664c709e68acf863e48386cda376edfd3bfb0 -F ext/wasm/GNUmakefile 2fd83d7183bce3f9236fdd2dbe20a4ea37b1d7b26e1a422054ec63008319f065 -F ext/wasm/README-dist.txt bc1fb4f90a28ad2ed0e555a637f393b9249d8d928ac509dad6293b7cae628ea4 +F ext/wasm/GNUmakefile 279fd4589ba602e24d8e66ca795ec5a2275a0e329405e4e984e8ea0579339bae +F ext/wasm/README-dist.txt 170be2d47b4b52504ef09088ca2f143aab657de0f9ac04d3a68e366f40929c3d F ext/wasm/README.md 1e5b28158b74ab3ffc9d54fcbc020f0bbeb82c2ff8bbd904214c86c70e8a3066 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api 89983a8d122c35a90c65ec667844b95a78bcd04f3198a99c1e0c8368c1a0b03a F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287 @@ -504,7 +504,7 @@ F ext/wasm/demo-123.html 7c239c9951d1b113f9f532969ac039294cf1dcfee2b3ae0a2c1ed2b F ext/wasm/demo-123.js e0cbeb3495e14103763d5c49794a24d67cf3d78e0ed5b82843be70c0c2ee4b3b F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424d6f5a0ea5e7f F ext/wasm/demo-kvvfs1.js 105596bd2ccd0b1deb5fde8e99b536e8242d4bb5932fac0c8403ff3a6bc547e8 -F ext/wasm/dist.make d7076e90f04396f1cc54cb41ee106451496179c10d54bbdebb65ae7b1ae12211 +F ext/wasm/dist.make 1d59fafdfcf6fc5ee0f3351b21199585dba21afcf0518241789fd5d37a1c011d F ext/wasm/fiddle.make b609dfde299b4523d7123b7e0cecaa1a0aff0dd984e62cea653aae91f5063c90 F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/fiddle/fiddle-worker.js 531859a471924a0ea48afa218e6877f0c164ca324d51e15843ed6ecc1c65c7ee @@ -2007,6 +2007,7 @@ F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaa F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848 F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 +F tool/stripccomments.c 20b8aabc4694d0d4af5566e42da1f1a03aff057689370326e9269a9ddcffdc37 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh 1612bd947750e21e7b47befad5f6b3825b06cce0705441f903bf35ced65ae9b9 F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003 @@ -2036,8 +2037,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 904b54625d985e742888e06ba792cab316b9ec9d6669d9cf509bac48030373ca -R 609c010622cb8a1edf242ffa07ea33a0 -U dan -Z 47ec91d5045ad14459bc2cd80292963b +P 740a2eb0928d54fdf735a8e573c6a61a34dbd295b46e5b6ef39e957fd2623293 +R f3423b9e5fdd1b3c8749326c161b8bbf +U stephan +Z 8ed4b03e8c6243f1d25f4dc2d31715c7 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d617a968ca..965ccd2dac 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -740a2eb0928d54fdf735a8e573c6a61a34dbd295b46e5b6ef39e957fd2623293 \ No newline at end of file +2156f0744acfe425457430a0f6a7e02de907de85edba81a6d4eef40293e561c8 \ No newline at end of file diff --git a/tool/stripccomments.c b/tool/stripccomments.c new file mode 100644 index 0000000000..53933c0138 --- /dev/null +++ b/tool/stripccomments.c @@ -0,0 +1,228 @@ +/** + Strips C- and C++-style comments from stdin, sending the results to + stdout. It assumes that its input is legal C-like code, and does + only little error handling. + + It treats string literals as anything starting and ending with + matching double OR single quotes OR backticks (for use with + scripting languages which use those). It assumes that a quote + character within a string which uses the same quote type is escaped + by a backslash. It should not be used on any code which might + contain C/C++ comments inside heredocs, and similar constructs, as + it will strip those out. + + Usage: $0 [--keep-first|-k] < input > output + + The --keep-first (-k) flag tells it to retain the first comment in the + input stream (which is often a license or attribution block). It + may be given repeatedly, each one incrementing the number of + retained comments by one. + + License: Public Domain + Author: Stephan Beal (stephan@wanderinghorse.net) +*/ +#include +#include +#include + +#if 1 +#define MARKER(pfexp) \ + do{ printf("MARKER: %s:%d:\t",__FILE__,__LINE__); \ + printf pfexp; \ + } while(0) +#else +#define MARKER(exp) if(0) printf +#endif + +struct { + FILE * input; + FILE * output; + int rc; + int keepFirst; +} App = { + 0/*input*/, + 0/*output*/, + 0/*rc*/, + 0/*keepFirst*/ +}; + +void do_it_all(void){ + enum states { + S_NONE = 0 /* not in comment */, + S_SLASH1 = 1 /* slash - possibly comment prefix */, + S_CPP = 2 /* in C++ comment */, + S_C = 3 /* in C comment */ + }; + int ch, prev = EOF; + FILE * out = App.output; + int const slash = '/'; + int const star = '*'; + int line = 1; + int col = 0; + enum states state = S_NONE /* current state */; + int elide = 0 /* true if currently eliding output */; + int state3Col = -99 + /* huge kludge for odd corner case: */ + /*/ <--- here. state3Col marks the source column in which a C-style + comment starts, so that it can tell if star-slash inside a + C-style comment is the end of the comment or is the weird corner + case marked at the start of _this_ comment block. */; + for( ; EOF != (ch = fgetc(App.input)); prev = ch, + ++col){ + switch(state){ + case S_NONE: + if('\''==ch || '"'==ch || '`'==ch){ + /* Read string literal... + needed to properly catch comments in strings. */ + int const quote = ch, + startLine = line, startCol = col; + int ch2, escaped = 0, endOfString = 0; + fputc(ch, out); + for( ++col; !endOfString && EOF != (ch2 = fgetc(App.input)); + ++col ){ + switch(ch2){ + case '\\': escaped = !escaped; + break; + case '`': + case '\'': + case '"': + if(!escaped && quote == ch2) endOfString = 1; + escaped = 0; + break; + default: + escaped = 0; + break; + } + if('\n'==ch2){ + ++line; + col = 0; + } + fputc(ch2, out); + } + if(EOF == ch2){ + fprintf(stderr, "Unexpected EOF while reading %s literal " + "on line %d column %d.\n", + ('\''==ch) ? "char" : "string", + startLine, startCol); + App.rc = 1; + return; + } + break; + } + else if(slash == ch){ + /* MARKER(("state 0 ==> 1 @ %d:%d\n", line, col)); */ + state = S_SLASH1; + break; + } + fputc(ch, out); + break; + case S_SLASH1: /* 1 slash */ + /* MARKER(("SLASH1 @ %d:%d App.keepFirst=%d\n", + line, col, App.keepFirst)); */ + switch(ch){ + case '*': + /* Enter C comment */ + if(App.keepFirst>0){ + elide = 0; + --App.keepFirst; + }else{ + elide = 1; + } + /*MARKER(("state 1 ==> 3 @ %d:%d\n", line, col));*/ + state = S_C; + state3Col = col-1; + if(!elide){ + fputc(prev, out); + fputc(ch, out); + } + break; + case '/': + /* Enter C++ comment */ + if(App.keepFirst>0){ + elide = 0; + --App.keepFirst; + }else{ + elide = 1; + } + /*MARKER(("state 1 ==> 2 @ %d:%d\n", line, col));*/ + state = S_CPP; + if(!elide){ + fputc(prev, out); + fputc(ch, out); + } + break; + default: + /* It wasn't a comment after all. */ + state = S_NONE; + if(!elide){ + fputc(prev, out); + fputc(ch, out); + } + } + break; + case S_CPP: /* C++ comment */ + if('\n' == ch){ + /* MARKER(("state 2 ==> 0 @ %d:%d\n", line, col)); */ + state = S_NONE; + elide = 0; + } + if(!elide){ + fputc(ch, out); + } + break; + case S_C: /* C comment */ + if(!elide){ + fputc(ch, out); + } + if(slash == ch){ + if(star == prev){ + /* MARKER(("state 3 ==> 0 @ %d:%d\n", line, col)); */ + /* Corner case which breaks this: */ + /*/ <-- slash there */ + /* That shows up twice in a piece of 3rd-party + code i use. */ + /* And thus state3Col was introduced :/ */ + if(col!=state3Col+2){ + state = S_NONE; + elide = 0; + state3Col = -99; + } + } + } + break; + default: + assert(!"impossible!"); + break; + } + if('\n' == ch){ + ++line; + col = 0; + state3Col = -99; + } + } +} + +static void usage(char const *zAppName){ + fprintf(stderr, "Strips C- and C++-style comments from stdin and sends " + "the results to stdout.\n"); + fprintf(stderr, "Usage: %s [--keep-first|-k] < input > output\n", zAppName); +} + +int main( int argc, char const * const * argv ){ + int i; + for(i = 1; i < argc; ++i){ + char const * zArg = argv[i]; + while( '-'==*zArg ) ++zArg; + if( 0==strcmp(zArg,"k") + || 0==strcmp(zArg,"keep-first") ){ + ++App.keepFirst; + }else{ + usage(argv[0]); + return 1; + } + } + App.input = stdin; + App.output = stdout; + do_it_all(); + return App.rc ? 1 : 0; +}