]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fiddle: fix makefile dependency issue and duplicate inclusion of post-js.js. Reimplem...
authorstephan <stephan@noemail.net>
Sat, 1 Oct 2022 16:01:41 +0000 (16:01 +0000)
committerstephan <stephan@noemail.net>
Sat, 1 Oct 2022 16:01:41 +0000 (16:01 +0000)
FossilOrigin-Name: 29db7de79232c21d19b91bb0fc253114e02e21dd9bf90619453dbe72a4c8bf7f

ext/wasm/api/sqlite3-api-glue.js
ext/wasm/api/sqlite3-api-prologue.js
ext/wasm/api/sqlite3-wasm.c
ext/wasm/fiddle.make
ext/wasm/fiddle/fiddle-worker.js
manifest
manifest.uuid
src/os_kv.c

index 347c03bc44df338c3248a47a24bff0959bd217c2..ab9424acabf5ac2ee7ed9d1a4f1ee76df0c25c90 100644 (file)
@@ -291,7 +291,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
        For the given integer, returns the SQLITE_xxx result code as a
        string, or undefined if no such mapping is found.
     */
-    capi.sqlite3_wasm_rc_str = (rc)=>__rcMap[rc];
+    capi.sqlite3_web_rc_str = (rc)=>__rcMap[rc];
     /* Bind all registered C-side structs... */
     for(const s of wasm.ctype.structs){
       capi[s.name] = sqlite3.StructBinder(s);
index a6e055ff404e423fece17d12adeaf9dbf8c4be65..121b3d4ffa4a46d9ef8abf15a3e36d27775e0e0c 100644 (file)
@@ -870,6 +870,51 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
     return rc;
   };
 
+  /**
+     Serializes the given `sqlite3*` pointer to a Uint8Array, as per
+     sqlite3_serialize(). On success it returns a Uint8Array. On
+     error it throws with a description of the problem.
+  */
+  capi.sqlite3_web_db_export = function(pDb){
+    if(!pDb) toss('Invalid sqlite3* argument.');
+    const wasm = capi.wasm;
+    if(!wasm.bigIntEnabled) toss('BigInt64 support is not enabled.');
+    const scope = wasm.scopedAllocPush();
+    let pOut;
+    try{
+      const pSize = wasm.scopedAlloc(8/*i64*/ + wasm.ptrSizeof);
+      const ppOut = pSize + 8;
+      /**
+         Maintenance reminder, since this cost a full hour of grief
+         and confusion: if the order of pSize/ppOut are reversed in
+         that memory block, fetching the value of pSize after the
+         export reads a garbage size because it's not on an 8-byte
+         memory boundary!
+      */
+      wasm.setPtrValue(ppOut, 0);
+      wasm.setMemValue(pSize, 0, 'i64');
+      let rc = wasm.exports.sqlite3_wasm_db_serialize(
+        pDb, ppOut, pSize, 0
+      );
+      if(rc){
+        toss("Database serialization failed with code",
+             sqlite3.capi.sqlite3_web_rc_str(rc));
+      }
+      const pOut = wasm.getPtrValue(ppOut);
+      const nOut = wasm.getMemValue(pSize, 'i64');
+      rc = nOut
+        ? wasm.heap8u().slice(pOut, pOut + Number(nOut))
+        : new Uint8Array();
+      return rc;
+    }catch(e){
+      console.error('internal error?',e);
+      throw w;
+    }finally{
+      if(pOut) wasm.exports.sqlite3_free(pOut);
+      wasm.scopedAllocPop(scope);
+    }
+  };
+  
   if( capi.util.isMainWindow() ){
     /* Features specific to the main window thread... */
 
@@ -945,7 +990,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
           }
         }
       });
-      return sz * 2 /* because JS uses UC16 encoding */;
+      return sz * 2 /* because JS uses 2-byte char encoding */;
     };
 
   }/* main-window-only bits */
index da8f5c32e7cf28178fed45d89fb9d64e6e029cc4..a66b51a8fcb80c5d4d0c394a7966b8686ab63521 100644 (file)
@@ -406,6 +406,7 @@ const char * sqlite3_wasm_enum_json(void){
   } _DefGroup;
 
   DefGroup(serialize){
+    DefInt(SQLITE_SERIALIZE_NOCOPY);
     DefInt(SQLITE_DESERIALIZE_FREEONCLOSE);
     DefInt(SQLITE_DESERIALIZE_READONLY);
     DefInt(SQLITE_DESERIALIZE_RESIZEABLE);
@@ -567,6 +568,83 @@ int sqlite3_wasm_vfs_unlink(const char * zName){
   return rc;
 }
 
+/*
+** Uses the current database's VFS xRead to stream the db file's
+** contents out to the given callback. The callback gets a single
+** chunk of size n (its 2nd argument) on each call and must return 0
+** on success, non-0 on error. This function returns 0 on success,
+** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
+** code from the callback. Note that this is not thread-friendly: it
+** expects that it will be the only thread reading the db file and
+** takes no measures to ensure that is the case.
+**
+** This implementation appears to work fine, but
+** sqlite3_wasm_db_serialize() is arguably the better way to achieve
+** this.
+*/
+WASM_KEEP
+int sqlite3_wasm_db_export_chunked( sqlite3* pDb,
+                                    int (*xCallback)(unsigned const char *zOut, int n) ){
+  sqlite3_int64 nSize = 0;
+  sqlite3_int64 nPos = 0;
+  sqlite3_file * pFile = 0;
+  unsigned char buf[1024 * 8];
+  int nBuf = (int)sizeof(buf);
+  int rc = pDb
+    ? sqlite3_file_control(pDb, "main",
+                           SQLITE_FCNTL_FILE_POINTER, &pFile)
+    : SQLITE_NOTFOUND;
+  if( rc ) return rc;
+  rc = pFile->pMethods->xFileSize(pFile, &nSize);
+  if( rc ) return rc;
+  if(nSize % nBuf){
+    /* DB size is not an even multiple of the buffer size. Reduce
+    ** buffer size so that we do not unduly inflate the db size
+    ** with zero-padding when exporting. */
+    if(0 == nSize % 4096) nBuf = 4096;
+    else if(0 == nSize % 2048) nBuf = 2048;
+    else if(0 == nSize % 1024) nBuf = 1024;
+    else nBuf = 512;
+  }
+  for( ; 0==rc && nPos<nSize; nPos += nBuf ){
+    rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
+    if(SQLITE_IOERR_SHORT_READ == rc){
+      rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
+    }
+    if( 0==rc ) rc = xCallback(buf, nBuf);
+  }
+  return rc;
+}
+
+/*
+** A proxy for sqlite3_serialize() which serializes the "main" schema
+** of pDb, placing the serialized output in pOut and nOut. nOut may be
+** NULL. If pDb or pOut are NULL then SQLITE_MISUSE is returned. If
+** allocation of the serialized copy fails, SQLITE_NOMEM is returned.
+** On success, 0 is returned and `*pOut` will contain a pointer to the
+** memory unless mFlags includes SQLITE_SERIALIZE_NOCOPY and the
+** database has no contiguous memory representation, in which case
+** `*pOut` will be NULL but 0 will be returned.
+**
+** If `*pOut` is not NULL, the caller is responsible for passing it to
+** sqlite3_free() to free it.
+*/
+WASM_KEEP
+int sqlite3_wasm_db_serialize( sqlite3* pDb, unsigned char **pOut, sqlite3_int64 * nOut,
+                               unsigned int mFlags ){
+  unsigned char * z;
+  if( !pDb || !pOut ) return SQLITE_MISUSE;
+  if(nOut) *nOut = 0;
+  z = sqlite3_serialize(pDb, "main", nOut, mFlags);
+  if( z || (SQLITE_SERIALIZE_NOCOPY & mFlags) ){
+    *pOut = z;
+    return 0;
+  }else{
+    return SQLITE_NOMEM;
+  }
+}
+
+
 #if defined(__EMSCRIPTEN__)
 #include <emscripten/console.h>
 #if defined(SQLITE_WASM_WASMFS)
index 6ccf8e0294840bcd69b866296b639a945782a44e..585add4270b21419d75c3b87195594569f9d774e 100644 (file)
@@ -37,7 +37,6 @@ fiddle.emcc-flags = \
   $(sqlite3.js.flags.--post-js) \
   -sEXPORTED_RUNTIME_METHODS=@$(dir.wasm)/EXPORTED_RUNTIME_METHODS.fiddle \
   -sEXPORTED_FUNCTIONS=@$(dir.wasm)/EXPORTED_FUNCTIONS.fiddle \
-  --post-js=$(post-js.js) \
   $(SQLITE_OPT) $(SHELL_OPT) \
   -DSQLITE_SHELL_FIDDLE
 # -D_POSIX_C_SOURCE is needed for strdup() with emcc
@@ -60,9 +59,9 @@ $(dir.fiddle)/$(SOAP.js): $(SOAP.js)
 $(eval $(call call-make-pre-js,fiddle-module))
 $(fiddle-module.js): $(MAKEFILE) $(MAKEFILE.fiddle) \
     EXPORTED_FUNCTIONS.fiddle EXPORTED_RUNTIME_METHODS.fiddle \
-    $(fiddle.cs) $(pre-post-fiddle.deps) $(dir.fiddle)/$(SOAP.js)
+    $(fiddle.cs) $(pre-post-fiddle-module.deps) $(dir.fiddle)/$(SOAP.js)
        $(emcc.bin) -o $@ $(fiddle.emcc-flags) \
-    $(pre-post-common.flags) $(pre-post-fiddle.flags) \
+    $(pre-post-common.flags) $(pre-post-fiddle-module.flags) \
     $(fiddle.cs)
        $(maybe-wasm-strip) $(fiddle-module.wasm)
        gzip < $@ > $@.gz
index 6a0cf53b72c478f95777fb68d4043667324912f1..ef2e3fcb5b00fccae6aface7e2d59b7cbc5e588d 100644 (file)
       f._();
     }
   };
-
-  /**
-     Exports the shell's current db file in such a way that it can
-     export DBs hosted in the Emscripten-supplied FS or in native OPFS
-     (and, hypothetically, kvvfs). Throws on error. On success returns
-     a Blob containing the whole db contents.
-
-     Bug/to investigate: xFileSize() is returning garbage for the
-     default VFS but works in OPFS. Thus for exporting that impl we'll
-     use the fiddleModule.FS API for the time being. The equivalent
-     native impl, fiddle_export_db(), works okay with both VFSes, so
-     the bug is apparently in (or via) this code.
-  */
-  const brokenExportDbFileToBlob = function(){
-    const capi = sqlite3.capi, wasm = capi.wasm;
-    const pDb = Sqlite3Shell.dbHandle();
-    if(!pDb) toss("No db is opened.");
-    const scope = wasm.scopedAllocPush();
-    try{
-      const ppFile = wasm.scopedAlloc(12/*sizeof(i32 + i64)*/);
-      const pFileSize = ppFile + 4;
-      wasm.setMemValue(ppFile, 0, '*');
-      let rc = capi.sqlite3_file_control(
-        pDb, "main", capi.SQLITE_FCNTL_FILE_POINTER, ppFile
-      );
-      if(rc) toss("Cannot get sqlite3_file handle.");
-      const jFile = new capi.sqlite3_file(wasm.getPtrValue(ppFile));
-      const jIom = new capi.sqlite3_io_methods(jFile.$pMethods);
-      const xFileSize = wasm.functionEntry(jIom.$xFileSize);
-      const xRead = wasm.functionEntry(jIom.$xRead);
-      wasm.setMemValue(pFileSize, 0, 'i64');
-      //stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
-      rc = xFileSize( jFile.pointer, pFileSize );
-      if(rc) toss("Cannot get db file size.");
-      //stderr("nFileSize =",wasm.getMemValue(pFileSize,'i64'),"pFileSize =",pFileSize);
-      const nFileSize = Number( wasm.getMemValue(pFileSize,'i64') );
-      if(nFileSize <= 0n || nFileSize>=Number.MAX_SAFE_INTEGER){
-        toss("Unexpected DB size:",nFileSize);
-      }
-      //stderr("nFileSize =",nFileSize,"pFileSize =",pFileSize);
-      const nIobuf = 1024 * 4;
-      const iobuf = wasm.scopedAlloc(nIobuf);
-      let nPos = 0;
-      const blobList = [];
-      const heap = wasm.heap8u();
-      for( ; nPos < nFileSize; nPos += nIobuf ){
-        rc = xRead(jFile.pointer, iobuf, nIobuf, BigInt(nPos));
-        if(rc){
-          if(capi.SQLITE_IOERR_SHORT_READ === rc){
-            //stderr('rc =',rc,'nPos =',nPos,'nIobuf =',nIobuf,'nFileSize =',nFileSize);
-            rc = ((nPos + nIobuf) < nFileSize) ? rc : 0/*assume EOF*/;
-          }
-          if(rc) toss("xRead() SQLITE_xxx error #"+rc,capi.sqlite3_wasm_rc_str(rc));
-        }
-        blobList.push(heap.slice(iobuf, iobuf+nIobuf));
-      }
-      return new Blob(blobList);
-    }catch(e){
-      console.error('exportDbFileToBlob()',e);
-      stderr("exportDbFileToBlob():",e.message);
-    }finally{
-      wasm.scopedAllocPop(scope);
-    }
-  }/*brokenExportDbFileToBlob()*/;
-
-  const exportDbFileToBlob = function f(){
-    if(!f._){
-      f._ = sqlite3.capi.wasm.xWrap('fiddle_export_db', 'int', '*');
-    }
-    const capi = sqlite3.capi;
-    const wasm = capi.wasm;
-    const blobList = [];
-    const heap = wasm.heap8u();
-    const callback = wasm.installFunction('ipi', function(buf, n){
-      blobList.push(heap.slice(buf, buf+n));
-      return 0;
-    });
-    try {
-      const rc = wasm.exports.fiddle_export_db( callback );
-      if(rc) toss("DB export failed with code", capi.sqlite3_wasm_rc_str(rc));
-      return new Blob(blobList);
-    }catch(e){
-      console.error("exportDbFileToBlob():",e.message);
-      throw(e);
-    }finally{
-      wasm.uninstallFunction(callback);
-    }
-  }/*exportDbFileToBlob()*/;
   
   self.onmessage = function f(ev){
     ev = ev.data;
           stdout("Exporting",fn+".");
           const fn2 = fn ? fn.split(/[/\\]/).pop() : null;
           try{
-            if(!fn2) throw new Error("DB appears to be closed.");
-            exportDbFileToBlob().arrayBuffer().then((buffer)=>{
-              wMsg('db-export',{filename: fn2, buffer}, [buffer]);
-            });
+            if(!fn2) toss("DB appears to be closed.");
+            const buffer = sqlite3.capi.sqlite3_web_db_export(
+              Sqlite3Shell.dbHandle()
+            );
+            wMsg('db-export',{filename: fn2, buffer: buffer.buffer}, [buffer.buffer]);
           }catch(e){
+            console.error("Export failed:",e);
             /* Post a failure message so that UI elements disabled
                during the export can be re-enabled. */
             wMsg('db-export',{
index 2ff0e775e9ccf8dffa471da9a0ab77f90bee19ef..b5ccfef55a447855f4b9919c80c002ff4939ddb0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\strunk\sinto\sfiddle-opfs\sbranch.
-D 2022-10-01T13:45:14.035
+C Fiddle:\sfix\smakefile\sdependency\sissue\sand\sduplicate\sinclusion\sof\spost-js.js.\sReimplement\sdb\sexport\susing\ssqlite3_serialize().
+D 2022-10-01T16:01:41.242
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -485,13 +485,13 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814
 F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b
 F ext/wasm/api/pre-js.js 2db711eb637991b383fc6b5c0f3df65ec48a7201e5730e304beba8de2d3f9b0b
 F ext/wasm/api/sqlite3-api-cleanup.js 5d22d1d3818ecacb23bfa223d5970cd0617d8cdbb48c8bc4bbd463f05b021a99
-F ext/wasm/api/sqlite3-api-glue.js ead29e6008ba148e7c67ad2bd928819dc72313ad2dcd34510cc61e089ee01c4e
+F ext/wasm/api/sqlite3-api-glue.js b15a51b88aaa472d36bf82d5123dbfdafe8ddf6ca75fba934510e4a20bbe4adb
 F ext/wasm/api/sqlite3-api-oo1.js 9caed0757a5e039ed92467e827fd3ca347fa08f19fe086fcbdd14a4ebe9c2f01
 F ext/wasm/api/sqlite3-api-opfs.js 1b097808b7b081b0f0700cf97d49ef19760e401706168edff9cd45cf9169f541
-F ext/wasm/api/sqlite3-api-prologue.js 04e0c929deeb28c9a2509d8004dfe3214992b988d277c4f50afa84953689c23c
+F ext/wasm/api/sqlite3-api-prologue.js d7904da82691f68b9ffb081c072cf4725716154284a63447f2d1dce40ab4b85f
 F ext/wasm/api/sqlite3-api-worker1.js 7f4f46cb6b512a48572d7567233896e6a9c46570c44bdc3d13419730c7c221c8
 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
-F ext/wasm/api/sqlite3-wasm.c 336389b23c9b83763177499e49a0967949c392b2f7d84fbbb52ad6678e159f18
+F ext/wasm/api/sqlite3-wasm.c 61c6bf8404a07f3d5f2861fbc1d3596474cecfc38801fb3a38c560fe847f79a5
 F ext/wasm/batch-runner.html c363032aba7a525920f61f8be112a29459f73f07e46f0ba3b7730081a617826e
 F ext/wasm/batch-runner.js ce92650a6681586c89bef26ceae96674a55ca5a9727815202ca62e1a00ff5015
 F ext/wasm/common/SqliteTestUtil.js 647bf014bd30bdd870a7e9001e251d12fc1c9ec9ce176a1004b838a4b33c5c05
@@ -503,9 +503,9 @@ F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b
 F ext/wasm/demo-123.js 536579fd587974c2511c5bf82034b253d4fdeceabb726927ad7599ef6b7578e8
 F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424d6f5a0ea5e7f
 F ext/wasm/demo-kvvfs1.js 105596bd2ccd0b1deb5fde8e99b536e8242d4bb5932fac0c8403ff3a6bc547e8
-F ext/wasm/fiddle.make d343d44c58bca06ac0ec0296207f6441560bff89f1e587bbaf843b73c2ca5d76
+F ext/wasm/fiddle.make 3f4efd62bc2a9c883bfcea52ae2755114a62d444d6d042df287f4aef301d6c6c
 F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
-F ext/wasm/fiddle/fiddle-worker.js 2a7107b06e5be3b9b063c340ec952f687e37ba6e0aa736b58c280dfb5e16625a
+F ext/wasm/fiddle/fiddle-worker.js ebf6e95fe031738cd9f79d1ccdf6d80640a2884a43f7006a5e3459995f93069b
 F ext/wasm/fiddle/fiddle.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
 F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
 F ext/wasm/index.html 63b370619e4f849ac76f1baed435c05edc29dbb6795bc7c1c935561ff667dd27
@@ -599,7 +599,7 @@ F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
 F src/os.c 0eb831ba3575af5277e47f4edd14fdfc90025c67eb25ce5cda634518d308d4e9
 F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
-F src/os_kv.c cf02a39ab3271d237890c7de03a49e5ecc19c930b8f4ad6afd43651dc05c9400
+F src/os_kv.c 88872a68ba37e4ed4306eb6fa78d559dcc675761ce1f6458ba710e1c10a2d667
 F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6
 F src/os_unix.c 287aa5f5691a2b356780c63e83abaa33549add84227b8313395f04088486d79c
 F src/os_win.c 8d129ae3e59e0fa900e20d0ad789e96f2e08177f0b00b53cdda65c40331e0902
@@ -2029,8 +2029,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 000ef7059bfb54dc4f829b81a8d8c927c0382980218d8a3d60cd2c4d89151c90 b7da0bcdf70e53ab1ec00a0694e17c7429e23bc6eb3f39b622d06a930aa2f6a3
-R 5df8cd3132a0539ad9a559117068898c
+P 64ebcbe41615a6d7776597564105ea7638e4a9095a764ea558c2620640429cf8
+R 624d71ac921985ea3965d7f2eda6af5a
 U stephan
-Z 7ab2cbdb07e5b8371b60f5611bb9584c
+Z 9261b853936f36a4eb842018d682a85c
 # Remove this line to create a well-formed Fossil manifest.
index cee93bde1c4bb5d0531f8f983e8549002858fbad..be02a9242520ac37d03d2ea25b8fc0d37ad5b195 100644 (file)
@@ -1 +1 @@
-64ebcbe41615a6d7776597564105ea7638e4a9095a764ea558c2620640429cf8
\ No newline at end of file
+29db7de79232c21d19b91bb0fc253114e02e21dd9bf90619453dbe72a4c8bf7f
\ No newline at end of file
index fb8eae627094e3f4ae0f826b8ad1f935c121f212..8de687ff115a7365416c59ece053759cccf48324 100644 (file)
@@ -195,12 +195,12 @@ static void kvstorageMakeKey(
 ** be exported from the wasm file (but may still be used internally
 ** within the wasm file).
 **
-** The functions in this file (sqlite3-wasm.c) which require exporting
-** are marked with this flag. They may also be added to any explicit
-** build-time export list but need not be. All of these APIs are
-** intended for use only within the project's own JS/WASM code, and
-** not by client code, so an argument can be made for reducing their
-** visibility by not including them in any build-time export lists.
+** The functions in this filewhich require exporting are marked with
+** this flag. They may also be added to any explicit build-time export
+** list but need not be. All of these APIs are intended for use only
+** within the project's own JS/WASM code, and not by client code, so
+** an argument can be made for reducing their visibility by not
+** including them in any build-time export lists.
 **
 ** 2022-09-11: it's not yet _proven_ that this approach works in
 ** non-Emscripten builds. If not, such builds will need to export