1use 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
12pub 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
99fn 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
109fn 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}