-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sharing the same WebAssembly file across multiple targets #3790
Comments
I honestly don't know as I only use the Web target, but I don't remember any Wasm changes related to the target being made by A very simple way to find out is just give it a try, if the Wasm file produced by |
I looked at implementing this but since most people use wasm-bindgen through wasm-pack, it looked like it would be a huge rippling change. So I opted to hack around it by creating a build script that builds all 3 targets, moves them into subdirectories of my |
This is an attempt to share a wasm file across multiple compilation targets. 1. Project StructureUnder the src directory, use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn err() -> Result<(), u8> {
Err(1)
} This is the most basic example I've found where the WASM imports include an additional function, which we need to address next. 2. BuildExecuting # web
wasm-pack build --target=web --out-dir=web
wasm2wat web/wasm_bindgen_proposal_bg.wasm -o web/wasm_bindgen_proposal_bg.wat
# nodejs
wasm-pack build --target=nodejs --out-dir=nodejs
wasm2wat nodejs/wasm_bindgen_proposal_bg.wasm -o nodejs/wasm_bindgen_proposal_bg.wat
# bundler
wasm-pack build --target=bundler --out-dir=bundler
wasm2wat bundler/wasm_bindgen_proposal_bg.wasm -o bundler/wasm_bindgen_proposal_bg.wat This will generate three directories, namely 3. AnalysisIt can be observed that the content of the wasm files in the three generated directories is almost the same, but there is a slight difference.
(import "wbg" "__wbindgen_number_new" (func (;0;) (type 6)))
(import "__wbindgen_placeholder__" "__wbindgen_number_new" (func (;0;) (type 6)))
(import "./wasm_bindgen_proposal_bg.js" "__wbindgen_number_new" (func (;0;) (type 6))) This only difference makes it difficult to share the wasm file. I tried to unify the entry in JohnnyMorganz/StyLua#848 with some hack methods, but a unified entry from wasm-bindgen during generation would be more convenient. 4. AttemptI duplicated the web directory to create a We then convert the modified WAT file back to WASM using wat2wasm proposal/web_modified.wat -o proposal/wasm_bindgen_proposal.wasm Next, we need to modify the glue files to make them work correctly in web, nodejs, and bundler environments. First, we need to modify the aforementioned entry file - function __wbg_get_imports() {
- const imports = {};
- imports.wbg = {};
- imports.wbg.__wbindgen_number_new = function(arg0) {
- const ret = arg0;
- return addHeapObject(ret);
- };
-
- return imports;
- }
+ export function __wbindgen_number_new(arg0) {
+ const ret = arg0;
+ return addHeapObject(ret);
+ };
+
+ function __wbg_get_imports() {
+ const imports = {};
+ imports["./wasm_bindgen_proposal.js"] = {
+ __wbindgen_number_new,
+ };
+
+ return imports;
+ } We no longer use the wbg entry, but use the Observing the import * as wasm from "./wasm_bindgen_proposal_bg.wasm";
import { __wbg_set_wasm } from "./wasm_bindgen_proposal.js";
__wbg_set_wasm(wasm);
export * from "./wasm_bindgen_proposal.js"; So, we need to add and export the So far, the glue files for esm and bundle have been modified. Let's look at the glue file for the nodejs environment next. - imports['__wbindgen_placeholder__'] = module.exports;
+ imports['./wasm_bindgen_proposal.js'] = module.exports; In this way, we have completed the modification of the glue file for the nodejs environment. 5. TestingIn fact, what we generate are We now write test files, which are import { initSync, err } from "./proposal/wasm_bindgen_proposal.js"
import fs from "node:fs";
const wasm = fs.readFileSync("./proposal/wasm_bindgen_proposal_bg.wasm");
initSync(wasm);
try {
err();
} catch (error) {
console.log(error);
} const m = require("./proposal/wasm_bindgen_proposal.cjs");
try {
m.err();
} catch (error) {
console.log(error);
} Because nodejs does not support the fetch In the end, we see that the output results are all 1, which means our shared wasm file is successful. Next, we test webpack compatibility, and the webpack configuration file is webpack.config.js We execute 6. SummarySharing WASM files is feasible by standardizing the import entry and adjusting glue code for different environments. This approach allows the same WASM file to be used across web, Node.js, and bundler compilation targets. |
This is a proof of concept, demonstrating the potential for sharing Wasm file. |
There are no plans to implement a feature like this. |
Summary
Compiling wasm for multiple targets is a common scenario.
Is it possible to share the same wasm and only have different JavaScript glue code?
Additional Details
related issue:
The text was updated successfully, but these errors were encountered: