Summary
dwasm fails at step 2 (wasm-bindgen) for any crate whose name contains hyphens (e.g. dsprint-survey, enterprise-portal). The build succeeds but the WASM file is never found because dwasm looks for the wrong filename.
Root Cause
Line 70 in src/main.rs:
let wasm_name = cli.crate_name.replace('-', "_");
This converts dsprint-survey → dsprint_survey, then on line 92 constructs the WASM path as:
let wasm_file = project
.join("target/wasm32-unknown-unknown/release")
.join(format!("{}.wasm", wasm_name));
// Looks for: target/.../release/dsprint_survey.wasm
But cargo build outputs the WASM file using the original crate name with hyphens intact:
target/wasm32-unknown-unknown/release/dsprint-survey.wasm
The hyphen-to-underscore conversion is correct for Rust use statements and for wasm-bindgen output filenames (the _bg.wasm and .js files DO use underscores), but it's wrong for the initial cargo build output .wasm file, which keeps the original Cargo.toml package name.
Reproduction
# Succeeds (no hyphens):
dwasm --crate-name dinkedin --project /opt/dinkedin --standalone
# ✓ Finds: target/.../release/dinkedin.wasm
# Fails (has hyphens):
dwasm --crate-name dsprint-survey --project /opt/dsprint-survey --standalone
# ✗ Looks for: target/.../release/dsprint_survey.wasm
# ✗ Actual file: target/.../release/dsprint-survey.wasm
dwasm --crate-name enterprise-portal --project /opt/enterprise-portal --standalone
# ✗ Same issue
Error output:
[1/5] cargo build --release --target wasm32-unknown-unknown
Finished `release` profile [optimized] target(s) in 23.32s
[2/5] wasm-bindgen
WASM file not found: /opt/dsprint-survey/target/wasm32-unknown-unknown/release/dsprint_survey.wasm
Proof the file exists with hyphens:
$ ls /opt/dsprint-survey/target/wasm32-unknown-unknown/release/*.wasm
/opt/dsprint-survey/target/wasm32-unknown-unknown/release/dsprint-survey.wasm
Affected Crates
Any DIRMACS project with a hyphenated crate name:
dsprint-survey — currently built with trunk as workaround
enterprise-portal — currently built with trunk as workaround
Projects without hyphens work fine:
dinkedin, dirmacs-admin (uses underscore internally), ehb-admin, ehb-buddy, eruka-web
Wait — dirmacs-admin and ehb-admin also have hyphens but they work. Let me clarify: cargo uses the crate name from Cargo.toml [package] name for the output binary. The issue is specifically about how cargo names the .wasm output vs how wasm-bindgen names its output. Cargo keeps hyphens in the .wasm filename; wasm-bindgen converts them to underscores in _bg.wasm and .js.
Update after checking: Actually dirmacs-admin and ehb-admin DO have hyphens and DO work with dwasm. So the behavior might depend on the Rust/cargo version or some other factor. The key point is: the .wasm file in target/ uses the original name with hyphens, and dwasm should look for that first.
Proposed Fix
The fix is to try BOTH the hyphenated and underscored filenames when looking for the cargo output. Change line 90-96:
// Step 2: wasm-bindgen
step("2/5", "wasm-bindgen");
let wasm_file = {
let underscore_name = project
.join("target/wasm32-unknown-unknown/release")
.join(format!("{}.wasm", wasm_name)); // underscored
let hyphen_name = project
.join("target/wasm32-unknown-unknown/release")
.join(format!("{}.wasm", cli.crate_name)); // original with hyphens
if underscore_name.exists() {
underscore_name
} else if hyphen_name.exists() {
hyphen_name
} else {
eprintln!("WASM file not found. Checked:");
eprintln!(" {}", underscore_name.display());
eprintln!(" {}", hyphen_name.display());
std::process::exit(1);
}
};
This is backwards-compatible — existing working builds still find the underscore version first, and hyphenated crate names now fall through to the hyphen version.
Alternative (more robust): Query cargo for the actual output path
Instead of guessing the filename, use cargo metadata or parse the cargo build output (--message-format=json) to get the exact artifact path:
let output = Command::new("cargo")
.args(["build", "--release", "--target", "wasm32-unknown-unknown",
"--message-format=json", "-p", &cli.crate_name])
.current_dir(&project)
.output()
.expect("cargo build");
// Parse JSON lines to find the artifact path
let wasm_file = String::from_utf8_lossy(&output.stdout)
.lines()
.filter_map(|line| serde_json::from_str::<serde_json::Value>(line).ok())
.find(|msg| msg["reason"] == "compiler-artifact"
&& msg["target"]["name"].as_str() == Some(&cli.crate_name))
.and_then(|msg| msg["filenames"].as_array()?.iter()
.find(|f| f.as_str()?.ends_with(".wasm"))
.and_then(|f| f.as_str().map(PathBuf::from)))
.unwrap_or_else(|| {
eprintln!("Could not determine WASM output path from cargo");
std::process::exit(1);
});
This approach is more complex but eliminates the filename guessing entirely.
Recommended Approach
Go with the simple fix (try both filenames). It's a 10-line change, zero new dependencies, backwards-compatible, and handles all known cases. The cargo --message-format=json approach is better long-term but adds serde_json as a dependency.
Environment
- dwasm v0.1.1
- Rust 1.86 (nightly)
- wasm-bindgen 0.2.114
- Trunk 0.21 (wasm-opt v123)
- VPS: Ubuntu 24.04
Labels
bug, good-first-issue
Summary
dwasmfails at step 2 (wasm-bindgen) for any crate whose name contains hyphens (e.g.dsprint-survey,enterprise-portal). The build succeeds but the WASM file is never found because dwasm looks for the wrong filename.Root Cause
Line 70 in
src/main.rs:This converts
dsprint-survey→dsprint_survey, then on line 92 constructs the WASM path as:But
cargo buildoutputs the WASM file using the original crate name with hyphens intact:The hyphen-to-underscore conversion is correct for Rust
usestatements and forwasm-bindgenoutput filenames (the_bg.wasmand.jsfiles DO use underscores), but it's wrong for the initial cargo build output.wasmfile, which keeps the originalCargo.tomlpackage name.Reproduction
Error output:
Proof the file exists with hyphens:
Affected Crates
Any DIRMACS project with a hyphenated crate name:
dsprint-survey— currently built withtrunkas workaroundenterprise-portal— currently built withtrunkas workaroundProjects without hyphens work fine:
dinkedin,dirmacs-admin(uses underscore internally),ehb-admin,ehb-buddy,eruka-webWait —
dirmacs-adminandehb-adminalso have hyphens but they work. Let me clarify: cargo uses the crate name fromCargo.toml [package] namefor the output binary. The issue is specifically about how cargo names the.wasmoutput vs howwasm-bindgennames its output. Cargo keeps hyphens in the.wasmfilename;wasm-bindgenconverts them to underscores in_bg.wasmand.js.Update after checking: Actually
dirmacs-adminandehb-adminDO have hyphens and DO work with dwasm. So the behavior might depend on the Rust/cargo version or some other factor. The key point is: the.wasmfile intarget/uses the original name with hyphens, and dwasm should look for that first.Proposed Fix
The fix is to try BOTH the hyphenated and underscored filenames when looking for the cargo output. Change line 90-96:
This is backwards-compatible — existing working builds still find the underscore version first, and hyphenated crate names now fall through to the hyphen version.
Alternative (more robust): Query cargo for the actual output path
Instead of guessing the filename, use
cargo metadataor parse the cargo build output (--message-format=json) to get the exact artifact path:This approach is more complex but eliminates the filename guessing entirely.
Recommended Approach
Go with the simple fix (try both filenames). It's a 10-line change, zero new dependencies, backwards-compatible, and handles all known cases. The
cargo --message-format=jsonapproach is better long-term but addsserde_jsonas a dependency.Environment
Labels
bug, good-first-issue