Skip to content

Commit d07ef5a

Browse files
authored
Merge pull request #244 from data-pup/wasm-bindgen-coord
Coordinate wasm-bindgen versions.
2 parents b5be9d0 + 8301613 commit d07ef5a

File tree

7 files changed

+170
-45
lines changed

7 files changed

+170
-45
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ slog-term = "2.4"
2323
slog-async = "2.3"
2424
structopt = "0.2"
2525
toml = "0.4"
26+
which = "2.0.0"
2627

2728
[dev-dependencies]
2829
copy_dir = "0.1.2"

src/bindgen.rs

Lines changed: 108 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,53 @@
33
use emoji;
44
use error::Error;
55
use progressbar::Step;
6-
use std::path::Path;
6+
use std::path::{Path, PathBuf};
77
use std::process::Command;
8+
use which::which;
89
use PBAR;
910

1011
/// Install the `wasm-bindgen` CLI with `cargo install`.
11-
pub fn cargo_install_wasm_bindgen(step: &Step) -> Result<(), Error> {
12-
let msg = format!("{}Installing WASM-bindgen...", emoji::DOWN_ARROW);
12+
pub fn cargo_install_wasm_bindgen(
13+
path: &Path,
14+
version: &str,
15+
install_permitted: bool,
16+
step: &Step,
17+
) -> Result<(), Error> {
18+
// If the `wasm-bindgen` dependency is already met, print a message and return.
19+
if wasm_bindgen_path(path)
20+
.map(|bindgen_path| wasm_bindgen_version_check(&bindgen_path, version))
21+
.unwrap_or(false)
22+
{
23+
let msg = format!("{}wasm-bindgen already installed...", emoji::DOWN_ARROW);
24+
PBAR.step(step, &msg);
25+
return Ok(());
26+
}
27+
28+
// If the `wasm-bindgen` dependency was not met, and installs are not
29+
// permitted, return a configuration error.
30+
if !install_permitted {
31+
let msg = format!("wasm-bindgen v{} is not installed!", version);
32+
return Error::crate_config(&msg);
33+
}
34+
35+
let msg = format!("{}Installing wasm-bindgen...", emoji::DOWN_ARROW);
1336
PBAR.step(step, &msg);
1437
let output = Command::new("cargo")
1538
.arg("install")
16-
.arg("wasm-bindgen-cli")
1739
.arg("--force")
40+
.arg("wasm-bindgen-cli")
41+
.arg("--version")
42+
.arg(version)
43+
.arg("--root")
44+
.arg(path)
1845
.output()?;
1946
if !output.status.success() {
47+
let message = "Installing wasm-bindgen failed".to_string();
2048
let s = String::from_utf8_lossy(&output.stderr);
21-
if s.contains("already exists") {
22-
PBAR.info("wasm-bindgen already installed");
23-
return Ok(());
24-
}
25-
Error::cli("Installing wasm-bindgen failed", s)
49+
Err(Error::Cli {
50+
message,
51+
stderr: s.to_string(),
52+
})
2653
} else {
2754
Ok(())
2855
}
@@ -42,33 +69,81 @@ pub fn wasm_bindgen_build(
4269
PBAR.step(step, &msg);
4370
let binary_name = name.replace("-", "_");
4471
let release_or_debug = if debug { "debug" } else { "release" };
45-
let wasm_path = format!(
46-
"target/wasm32-unknown-unknown/{}/{}.wasm",
47-
release_or_debug, binary_name
48-
);
49-
let dts_arg = if disable_dts == false {
50-
"--typescript"
72+
73+
if let Some(wasm_bindgen_path) = wasm_bindgen_path(path) {
74+
let wasm_path = format!(
75+
"target/wasm32-unknown-unknown/{}/{}.wasm",
76+
release_or_debug, binary_name
77+
);
78+
let dts_arg = if disable_dts == false {
79+
"--typescript"
80+
} else {
81+
"--no-typescript"
82+
};
83+
let target_arg = match target {
84+
"nodejs" => "--nodejs",
85+
_ => "--browser",
86+
};
87+
let bindgen_path = Path::new(&wasm_bindgen_path);
88+
let output = Command::new(bindgen_path)
89+
.current_dir(path)
90+
.arg(&wasm_path)
91+
.arg("--out-dir")
92+
.arg("./pkg")
93+
.arg(dts_arg)
94+
.arg(target_arg)
95+
.output()?;
96+
if !output.status.success() {
97+
let s = String::from_utf8_lossy(&output.stderr);
98+
Error::cli("wasm-bindgen failed to execute properly", s)
99+
} else {
100+
Ok(())
101+
}
51102
} else {
52-
"--no-typescript"
103+
Error::crate_config("Could not find `wasm-bindgen`")
104+
}
105+
}
106+
107+
/// Check if the `wasm-bindgen` dependency is locally satisfied.
108+
fn wasm_bindgen_version_check(bindgen_path: &PathBuf, dep_version: &str) -> bool {
109+
Command::new(bindgen_path)
110+
.arg("--version")
111+
.output()
112+
.ok()
113+
.filter(|output| output.status.success())
114+
.map(|output| {
115+
String::from_utf8_lossy(&output.stdout)
116+
.trim()
117+
.split_whitespace()
118+
.nth(1)
119+
.map(|v| v == dep_version)
120+
.unwrap_or(false)
121+
}).unwrap_or(false)
122+
}
123+
124+
/// Return a `PathBuf` containing the path to either the local wasm-bindgen
125+
/// version, or the globally installed version if there is no local version.
126+
fn wasm_bindgen_path(crate_path: &Path) -> Option<PathBuf> {
127+
// Return the path to the local `wasm-bindgen`, if it exists.
128+
let local_bindgen_path = |crate_path: &Path| -> Option<PathBuf> {
129+
let mut p = crate_path.to_path_buf();
130+
p.push("bin");
131+
p.push("wasm-bindgen");
132+
if p.is_file() {
133+
Some(p)
134+
} else {
135+
None
136+
}
53137
};
54138

55-
let target_arg = match target {
56-
"nodejs" => "--nodejs",
57-
_ => "--browser",
139+
// Return the path to the global `wasm-bindgen`, if it exists.
140+
let global_bindgen_path = || -> Option<PathBuf> {
141+
if let Ok(p) = which("wasm-bindgen") {
142+
Some(p)
143+
} else {
144+
None
145+
}
58146
};
59147

60-
let output = Command::new("wasm-bindgen")
61-
.current_dir(path)
62-
.arg(&wasm_path)
63-
.arg("--out-dir")
64-
.arg("./pkg")
65-
.arg(dts_arg)
66-
.arg(target_arg)
67-
.output()?;
68-
if !output.status.success() {
69-
let s = String::from_utf8_lossy(&output.stderr);
70-
Error::cli("wasm-bindgen failed to execute properly", s)
71-
} else {
72-
Ok(())
73-
}
148+
local_bindgen_path(crate_path).or_else(global_bindgen_path)
74149
}

src/command/build.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) struct Build {
1919
pub disable_dts: bool,
2020
pub target: String,
2121
pub debug: bool,
22+
pub mode: BuildMode,
2223
// build_config: Option<BuildConfig>,
2324
pub crate_name: String,
2425
}
@@ -71,21 +72,26 @@ impl Build {
7172
pub fn try_from_opts(build_opts: BuildOptions) -> Result<Self, Error> {
7273
let crate_path = set_crate_path(build_opts.path);
7374
let crate_name = manifest::get_crate_name(&crate_path)?;
75+
let mode = match build_opts.mode.as_str() {
76+
"no-install" => BuildMode::Noinstall,
77+
_ => BuildMode::Normal,
78+
};
7479
// let build_config = manifest::xxx(&crate_path).xxx();
7580
Ok(Build {
7681
crate_path,
7782
scope: build_opts.scope,
7883
disable_dts: build_opts.disable_dts,
7984
target: build_opts.target,
8085
debug: build_opts.debug,
86+
mode,
8187
// build_config,
8288
crate_name,
8389
})
8490
}
8591

8692
/// Execute this `Build` command.
87-
pub fn run(&mut self, log: &Logger, mode: &BuildMode) -> Result<(), Error> {
88-
let process_steps = Build::get_process_steps(mode);
93+
pub fn run(&mut self, log: &Logger) -> Result<(), Error> {
94+
let process_steps = Build::get_process_steps(&self.mode);
8995

9096
let mut step_counter = Step::new(process_steps.len());
9197

@@ -100,14 +106,14 @@ impl Build {
100106
info!(&log, "Done in {}.", &duration);
101107
info!(
102108
&log,
103-
"Your WASM pkg is ready to publish at {:#?}.",
109+
"Your wasm pkg is ready to publish at {:#?}.",
104110
&self.crate_path.join("pkg")
105111
);
106112

107113
PBAR.message(&format!("{} Done in {}", emoji::SPARKLE, &duration));
108114

109115
PBAR.message(&format!(
110-
"{} Your WASM pkg is ready to publish at {:#?}.",
116+
"{} Your wasm pkg is ready to publish at {:#?}.",
111117
emoji::PACKAGE,
112118
&self.crate_path.join("pkg")
113119
));
@@ -213,8 +219,19 @@ impl Build {
213219
}
214220

215221
fn step_install_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
222+
info!(&log, "Identifying wasm-bindgen dependency...");
223+
let bindgen_version = manifest::get_wasm_bindgen_version(&self.crate_path)?;
216224
info!(&log, "Installing wasm-bindgen-cli...");
217-
bindgen::cargo_install_wasm_bindgen(step)?;
225+
let install_permitted = match self.mode {
226+
BuildMode::Normal => true,
227+
BuildMode::Noinstall => false,
228+
};
229+
bindgen::cargo_install_wasm_bindgen(
230+
&self.crate_path,
231+
&bindgen_version,
232+
install_permitted,
233+
step,
234+
)?;
218235
info!(&log, "Installing wasm-bindgen-cli was successful.");
219236

220237
info!(&log, "Getting the crate name from the manifest...");

src/command/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod pack;
66
mod publish;
77
pub mod utils;
88

9-
use self::build::{Build, BuildMode, BuildOptions};
9+
use self::build::{Build, BuildOptions};
1010
use self::login::login;
1111
use self::pack::pack;
1212
use self::publish::publish;
@@ -79,12 +79,7 @@ pub fn run_wasm_pack(command: Command, log: &Logger) -> result::Result<(), Error
7979
let status = match command {
8080
Command::Build(build_opts) => {
8181
info!(&log, "Running build command...");
82-
let build_mode = match build_opts.mode.as_str() {
83-
"no-install" => BuildMode::Noinstall,
84-
"normal" => BuildMode::Normal,
85-
_ => BuildMode::Normal,
86-
};
87-
Build::try_from_opts(build_opts).and_then(|mut b| b.run(&log, &build_mode))
82+
Build::try_from_opts(build_opts).and_then(|mut b| b.run(&log))
8883
}
8984
Command::Pack { path } => {
9085
info!(&log, "Running pack command...");

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern crate slog;
1919
extern crate slog_async;
2020
extern crate slog_term;
2121
extern crate toml;
22+
extern crate which;
2223

2324
pub mod bindgen;
2425
pub mod build;

src/manifest.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,28 @@ fn check_crate_type(path: &Path) -> Result<(), Error> {
218218
"crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your Cargo.toml file:\n\n[lib]\ncrate-type = [\"cdylib\"]"
219219
)
220220
}
221+
222+
/// Get the version of `wasm-bindgen` specified as a dependency.
223+
pub fn get_wasm_bindgen_version(path: &Path) -> Result<String, Error> {
224+
if let Some(deps) = read_cargo_toml(path)?.dependencies {
225+
match deps.get("wasm_bindgen") {
226+
Some(CargoDependency::Simple(version)) => Ok(version.clone()),
227+
Some(CargoDependency::Detailed(_)) => {
228+
let msg = format!(
229+
"\"{}\" dependency is missing its version number",
230+
style("wasm-bindgen").bold().dim()
231+
);
232+
Err(Error::CrateConfig { message: msg })
233+
}
234+
None => {
235+
let message = format!(
236+
"Ensure that you have \"{}\" as a dependency in your Cargo.toml file:\n[dependencies]\nwasm-bindgen = \"0.2\"",
237+
style("wasm-bindgen").bold().dim());
238+
Err(Error::CrateConfig { message })
239+
}
240+
}
241+
} else {
242+
let message = String::from("Could not find crate dependencies");
243+
Err(Error::CrateConfig { message })
244+
}
245+
}

0 commit comments

Comments
 (0)