wasm_pack/
bindgen.rs

1//! Functionality related to running `wasm-bindgen`.
2
3use crate::child;
4use crate::command::build::{BuildProfile, Target};
5use crate::install::{self, Tool};
6use crate::manifest::CrateData;
7use anyhow::{bail, Context, Result};
8use semver;
9use std::path::Path;
10use std::process::Command;
11
12/// Run the `wasm-bindgen` CLI to generate bindings for the current crate's
13/// `.wasm`.
14pub fn wasm_bindgen_build(
15    data: &CrateData,
16    install_status: &install::Status,
17    out_dir: &Path,
18    out_name: &Option<String>,
19    disable_dts: bool,
20    weak_refs: bool,
21    reference_types: bool,
22    target: Target,
23    profile: BuildProfile,
24    extra_options: &Vec<String>,
25) -> Result<()> {
26    let release_or_debug = match profile {
27        BuildProfile::Release | BuildProfile::Profiling => "release",
28        BuildProfile::Dev => "debug",
29    };
30
31    let out_dir = out_dir.to_str().unwrap();
32
33    let target_directory = {
34        let mut has_target_dir_iter = extra_options.iter();
35        has_target_dir_iter
36            .find(|&it| it == "--target-dir")
37            .and_then(|_| has_target_dir_iter.next())
38            .map(Path::new)
39            .unwrap_or(data.target_directory())
40    };
41
42    let wasm_path = target_directory
43        .join("wasm32-unknown-unknown")
44        .join(release_or_debug)
45        .join(data.crate_name())
46        .with_extension("wasm");
47
48    let dts_arg = if disable_dts {
49        "--no-typescript"
50    } else {
51        "--typescript"
52    };
53    let bindgen_path = install::get_tool_path(install_status, Tool::WasmBindgen)?
54        .binary(&Tool::WasmBindgen.to_string())?;
55
56    let mut cmd = Command::new(&bindgen_path);
57    cmd.arg(&wasm_path)
58        .arg("--out-dir")
59        .arg(out_dir)
60        .arg(dts_arg);
61
62    if weak_refs {
63        cmd.arg("--weak-refs");
64    }
65
66    if reference_types {
67        cmd.arg("--reference-types");
68    }
69
70    let target_arg = build_target_arg(target, &bindgen_path)?;
71    if supports_dash_dash_target(&bindgen_path)? {
72        cmd.arg("--target").arg(target_arg);
73    } else {
74        cmd.arg(target_arg);
75    }
76
77    if let Some(value) = out_name {
78        cmd.arg("--out-name").arg(value);
79    }
80
81    let profile = data.configured_profile(profile);
82    if profile.wasm_bindgen_debug_js_glue() {
83        cmd.arg("--debug");
84    }
85    if !profile.wasm_bindgen_demangle_name_section() {
86        cmd.arg("--no-demangle");
87    }
88    if profile.wasm_bindgen_dwarf_debug_info() {
89        cmd.arg("--keep-debug");
90    }
91    if profile.wasm_bindgen_omit_default_module_path() {
92        cmd.arg("--omit-default-module-path");
93    }
94
95    child::run(cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?;
96    Ok(())
97}
98
99/// Check if the `wasm-bindgen` dependency is locally satisfied for the web target
100fn supports_web_target(cli_path: &Path) -> Result<bool> {
101    let cli_version = semver::Version::parse(&install::get_cli_version(
102        &install::Tool::WasmBindgen,
103        cli_path,
104    )?)?;
105    let expected_version = semver::Version::parse("0.2.39")?;
106    Ok(cli_version >= expected_version)
107}
108
109/// Check if the `wasm-bindgen` dependency is locally satisfied for the --target flag
110fn supports_dash_dash_target(cli_path: &Path) -> Result<bool> {
111    let cli_version = semver::Version::parse(&install::get_cli_version(
112        &install::Tool::WasmBindgen,
113        cli_path,
114    )?)?;
115    let expected_version = semver::Version::parse("0.2.40")?;
116    Ok(cli_version >= expected_version)
117}
118
119fn build_target_arg(target: Target, cli_path: &Path) -> Result<String> {
120    if !supports_dash_dash_target(cli_path)? {
121        Ok(build_target_arg_legacy(target, cli_path)?)
122    } else {
123        Ok(target.to_string())
124    }
125}
126
127fn build_target_arg_legacy(target: Target, cli_path: &Path) -> Result<String> {
128    log::info!("Your version of wasm-bindgen is out of date. You should consider updating your Cargo.toml to a version >= 0.2.40.");
129    let target_arg = match target {
130        Target::Nodejs => "--nodejs",
131        Target::NoModules => "--no-modules",
132        Target::Web => {
133            if supports_web_target(cli_path)? {
134                "--web"
135            } else {
136                bail!("Your current version of wasm-bindgen does not support the 'web' target. Please update your project to wasm-bindgen version >= 0.2.39.")
137            }
138        }
139        Target::Bundler => "--browser",
140        Target::Deno => "--deno",
141    };
142    Ok(target_arg.to_string())
143}