From 9d9c815b5fca96ab081fc578256fadfde8385daa Mon Sep 17 00:00:00 2001 From: Matthias Endler Date: Tue, 17 Mar 2020 22:29:03 +0100 Subject: [PATCH] Add first-class support for binary crates --- src/bindgen.rs | 94 +++++++++++-------- src/build/mod.rs | 7 +- src/command/build.rs | 20 +++- src/command/test.rs | 2 +- src/manifest/mod.rs | 50 ++++++++-- tests/all/build.rs | 59 ++++++++++++ tests/all/license.rs | 10 +- tests/all/lockfile.rs | 8 +- tests/all/manifest.rs | 54 ++++++----- tests/all/utils/fixture.rs | 181 ++++++++++++++++++++++++++++++++++++- 10 files changed, 400 insertions(+), 85 deletions(-) diff --git a/src/bindgen.rs b/src/bindgen.rs index 02d02dce..65177867 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -27,50 +27,64 @@ pub fn wasm_bindgen_build( let out_dir = out_dir.to_str().unwrap(); - let wasm_path = data - .target_directory() - .join("wasm32-unknown-unknown") - .join(release_or_debug) - .join(data.crate_name()) - .with_extension("wasm"); - - let dts_arg = if disable_dts { - "--no-typescript" - } else { - "--typescript" - }; - let bindgen_path = install::get_tool_path(install_status, Tool::WasmBindgen)? - .binary(&Tool::WasmBindgen.to_string())?; - - let mut cmd = Command::new(&bindgen_path); - cmd.arg(&wasm_path) - .arg("--out-dir") - .arg(out_dir) - .arg(dts_arg); - - let target_arg = build_target_arg(target, &bindgen_path)?; - if supports_dash_dash_target(bindgen_path.to_path_buf())? { - cmd.arg("--target").arg(target_arg); - } else { - cmd.arg(target_arg); - } + for target_name in data.targets() { + let wasm_path = { + let wasm_path = data + .target_directory() + .join("wasm32-unknown-unknown") + .join(release_or_debug); + let wasm_path = if data.is_example() { + wasm_path.join("examples") + } else { + wasm_path + }; + wasm_path.join(target_name).with_extension("wasm") + }; - if let Some(value) = out_name { - cmd.arg("--out-name").arg(value); - } + if !wasm_path.exists() { + continue; + } - let profile = data.configured_profile(profile); - if profile.wasm_bindgen_debug_js_glue() { - cmd.arg("--debug"); - } - if !profile.wasm_bindgen_demangle_name_section() { - cmd.arg("--no-demangle"); - } - if profile.wasm_bindgen_dwarf_debug_info() { - cmd.arg("--keep-debug"); + let dts_arg = if disable_dts { + "--no-typescript" + } else { + "--typescript" + }; + + let bindgen_path = install::get_tool_path(install_status, Tool::WasmBindgen)? + .binary(&Tool::WasmBindgen.to_string())?; + + let mut cmd = Command::new(&bindgen_path); + cmd.arg(&wasm_path) + .arg("--out-dir") + .arg(out_dir) + .arg(dts_arg); + + let target_arg = build_target_arg(target, &bindgen_path)?; + if supports_dash_dash_target(bindgen_path)? { + cmd.arg("--target").arg(target_arg); + } else { + cmd.arg(target_arg); + } + + if let Some(value) = out_name { + cmd.arg("--out-name").arg(value); + } + + let profile = data.configured_profile(profile); + if profile.wasm_bindgen_debug_js_glue() { + cmd.arg("--debug"); + } + if !profile.wasm_bindgen_demangle_name_section() { + cmd.arg("--no-demangle"); + } + if profile.wasm_bindgen_dwarf_debug_info() { + cmd.arg("--keep-debug"); + } + + child::run(cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?; } - child::run(cmd, "wasm-bindgen").context("Running the wasm-bindgen CLI")?; Ok(()) } diff --git a/src/build/mod.rs b/src/build/mod.rs index f87133dd..154fc27f 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -76,13 +76,15 @@ fn wasm_pack_local_version() -> Option { pub fn cargo_build_wasm( path: &Path, profile: BuildProfile, + example: &Option, extra_options: &[String], ) -> Result<(), Error> { let msg = format!("{}Compiling to Wasm...", emoji::CYCLONE); PBAR.info(&msg); let mut cmd = Command::new("cargo"); - cmd.current_dir(path).arg("build").arg("--lib"); + + cmd.current_dir(path).arg("build"); if PBAR.quiet() { cmd.arg("--quiet"); @@ -107,6 +109,9 @@ pub fn cargo_build_wasm( } cmd.arg("--target").arg("wasm32-unknown-unknown"); + if let Some(example) = example { + cmd.arg("--example").arg(example); + } cmd.args(extra_options); child::run(cmd, "cargo build").context("Compiling your crate to WebAssembly failed")?; Ok(()) diff --git a/src/command/build.rs b/src/command/build.rs index b1b6eb50..e5071640 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -34,6 +34,7 @@ pub struct Build { pub out_name: Option, pub bindgen: Option, pub cache: Cache, + pub example: Option, pub extra_options: Vec, } @@ -148,6 +149,10 @@ pub struct BuildOptions { /// Sets the output file names. Defaults to package name. pub out_name: Option, + #[structopt(long = "example")] + /// Builds the specified example. + pub example: Option, + #[structopt(last = true)] /// List of extra options to pass to `cargo build` pub extra_options: Vec, @@ -167,6 +172,7 @@ impl Default for BuildOptions { profiling: false, out_dir: String::new(), out_name: None, + example: None, extra_options: Vec::new(), } } @@ -178,7 +184,11 @@ impl Build { /// Construct a build command from the given options. pub fn try_from_opts(build_opts: BuildOptions) -> Result { let crate_path = get_crate_path(build_opts.path)?; - let crate_data = manifest::CrateData::new(&crate_path, build_opts.out_name.clone())?; + let crate_data = manifest::CrateData::new( + &crate_path, + build_opts.out_name.clone(), + build_opts.example.clone(), + )?; let out_dir = crate_path.join(PathBuf::from(build_opts.out_dir)); let dev = build_opts.dev || build_opts.debug; @@ -203,6 +213,7 @@ impl Build { out_name: build_opts.out_name, bindgen: None, cache: cache::get_wasm_pack_cache()?, + example: build_opts.example, extra_options: build_opts.extra_options, }) } @@ -298,7 +309,12 @@ impl Build { fn step_build_wasm(&mut self) -> Result<(), Error> { info!("Building wasm..."); - build::cargo_build_wasm(&self.crate_path, self.profile, &self.extra_options)?; + build::cargo_build_wasm( + &self.crate_path, + self.profile, + &self.example, + &self.extra_options, + )?; info!( "wasm built at {:#?}.", diff --git a/src/command/test.rs b/src/command/test.rs index cc77a104..9337ac93 100644 --- a/src/command/test.rs +++ b/src/command/test.rs @@ -119,7 +119,7 @@ impl Test { } = test_opts; let crate_path = get_crate_path(path)?; - let crate_data = manifest::CrateData::new(&crate_path, None)?; + let crate_data = manifest::CrateData::new(&crate_path, None, None)?; let any_browser = chrome || firefox || safari; if !node && !any_browser { diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 668541ac..06d6e575 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -39,6 +39,7 @@ pub struct CrateData { current_idx: usize, manifest: CargoManifest, out_name: Option, + example: Option, } #[doc(hidden)] @@ -402,7 +403,11 @@ pub struct ManifestAndUnsedKeys { impl CrateData { /// Reads all metadata for the crate whose manifest is inside the directory /// specified by `path`. - pub fn new(crate_path: &Path, out_name: Option) -> Result { + pub fn new( + crate_path: &Path, + out_name: Option, + example: Option, + ) -> Result { let manifest_path = crate_path.join("Cargo.toml"); if !manifest_path.is_file() { bail!( @@ -431,6 +436,7 @@ impl CrateData { manifest, current_idx, out_name, + example, }) } @@ -493,18 +499,30 @@ impl CrateData { Ok(()) } - fn check_crate_type(&self) -> Result<(), Error> { + fn valid_targets(&self) -> impl Iterator { + fn valid(target: &cargo_metadata::Target, example: &Option) -> bool { + if let Some(example) = example { + target.name == *example && target.kind.iter().any(|k| k == "example") + } else { + fn valid_kind(x: &str) -> bool { + x == "cdylib" || x == "bin" + } + target.kind.iter().any(|x| valid_kind(x)) + } + } let pkg = &self.data.packages[self.current_idx]; - let any_cdylib = pkg - .targets + pkg.targets .iter() - .filter(|target| target.kind.iter().any(|k| k == "cdylib")) - .any(|target| target.crate_types.iter().any(|s| s == "cdylib")); - if any_cdylib { + .filter(move |target| valid(target, &self.example)) + } + + fn check_crate_type(&self) -> Result<(), Error> { + let any_valid = self.valid_targets().count() > 0; + if any_valid { return Ok(()); } bail!( - "crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \ + "library crate-type must be cdylib to compile to wasm32-unknown-unknown. Add the following to your \ Cargo.toml file:\n\n\ [lib]\n\ crate-type = [\"cdylib\", \"rlib\"]" @@ -524,6 +542,22 @@ impl CrateData { } } + /// Get the target names that will be built for the current crate. + pub fn targets(&self) -> impl Iterator + '_ { + self.valid_targets().map(|x| { + if x.kind.iter().any(|x| x.ends_with("lib")) { + x.name.replace("-", "_") + } else { + x.name.clone() + } + }) + } + + /// Check if we are building an example. + pub fn is_example(&self) -> bool { + self.example.is_some() + } + /// Get the prefix for output file names pub fn name_prefix(&self) -> String { match &self.out_name { diff --git a/tests/all/build.rs b/tests/all/build.rs index dbcdaaeb..939a314a 100644 --- a/tests/all/build.rs +++ b/tests/all/build.rs @@ -296,6 +296,65 @@ fn build_force() { .success(); } +#[test] +fn bin_crate_behavior_identical() { + let fixture = utils::fixture::bin_crate(); + fixture.install_local_wasm_bindgen(); + fixture + .wasm_pack() + .arg("build") + .arg("--target") + .arg("nodejs") + .assert() + .success(); + let native_output = fixture.command("cargo").arg("run").output().unwrap(); + assert!(native_output.status.success()); + assert_eq!(native_output.stdout, b"Hello, World\n"); + let wasm_output = fixture.command("node").arg("pkg/foo.js").output().unwrap(); + assert!(wasm_output.status.success()); + assert_eq!(wasm_output.stdout, b"Hello, World\n"); +} + +#[test] +fn multi_bin_crate_procs_all() { + let fixture = utils::fixture::multi_bin_crate(); + fixture.install_local_wasm_bindgen(); + fixture + .wasm_pack() + .arg("build") + .arg("--target") + .arg("nodejs") + .assert() + .success(); + let pkg_path = |x: &str| { + let mut path = fixture.path.clone(); + path.push("pkg"); + path.push(x); + path + }; + assert!(pkg_path("foo.js").exists()); + assert!(pkg_path("sample.js").exists()); +} + +#[test] +fn builds_examples() { + let fixture = utils::fixture::bin_example_crate(); + fixture.install_local_wasm_bindgen(); + fixture + .wasm_pack() + .arg("build") + .arg("--target") + .arg("nodejs") + .arg("--example") + .arg("example") + .assert() + .success(); + let mut path = fixture.path.clone(); + path.push("pkg"); + path.push("example.js"); + assert!(path.exists()); +} + #[test] fn build_from_new() { let fixture = utils::fixture::not_a_crate(); diff --git a/tests/all/license.rs b/tests/all/license.rs index cffa7995..eb69ab0b 100644 --- a/tests/all/license.rs +++ b/tests/all/license.rs @@ -12,7 +12,7 @@ fn it_copies_a_license_default_path() { let fixture = fixture::single_license(); let out_dir = fixture.path.join("pkg"); fs::create_dir(&out_dir).expect("should create pkg directory OK"); - let crate_data = CrateData::new(&fixture.path, None); + let crate_data = CrateData::new(&fixture.path, None, None); assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir).is_ok()); @@ -37,7 +37,7 @@ fn it_copies_a_license_provided_path() { let fixture = fixture::single_license(); let out_dir = fixture.path.join("pkg"); fs::create_dir(&out_dir).expect("should create pkg directory OK"); - let crate_data = CrateData::new(&fixture.path, None); + let crate_data = CrateData::new(&fixture.path, None, None); assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir).is_ok()); let crate_license_path = fixture.path.join("LICENSE"); @@ -60,7 +60,7 @@ fn it_copies_all_licenses_default_path() { let fixture = fixture::dual_license(); let out_dir = fixture.path.join("pkg"); fs::create_dir(&out_dir).expect("should create pkg directory OK"); - let crate_data = CrateData::new(&fixture.path, None); + let crate_data = CrateData::new(&fixture.path, None, None); assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir).is_ok()); @@ -95,7 +95,7 @@ fn it_copies_all_licenses_provided_path() { let fixture = fixture::dual_license(); let out_dir = fixture.path.join("pkg"); fs::create_dir(&out_dir).expect("should create pkg directory OK"); - let crate_data = CrateData::new(&fixture.path, None); + let crate_data = CrateData::new(&fixture.path, None, None); assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir).is_ok()); @@ -131,7 +131,7 @@ fn it_copies_a_non_standard_license_provided_path() { let fixture = fixture::non_standard_license(license_file); let out_dir = fixture.path.join("pkg"); fs::create_dir(&out_dir).expect("should create pkg directory OK"); - let crate_data = CrateData::new(&fixture.path, None); + let crate_data = CrateData::new(&fixture.path, None, None); assert!(license::copy_from_crate(&crate_data.unwrap(), &fixture.path, &out_dir).is_ok()); diff --git a/tests/all/lockfile.rs b/tests/all/lockfile.rs index 1a42ce88..d4a4e418 100644 --- a/tests/all/lockfile.rs +++ b/tests/all/lockfile.rs @@ -6,7 +6,7 @@ use wasm_pack::manifest::CrateData; fn it_gets_wasm_bindgen_version() { let fixture = fixture::js_hello_world(); fixture.cargo_check(); - let data = CrateData::new(&fixture.path, None).unwrap(); + let data = CrateData::new(&fixture.path, None, None).unwrap(); let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.37"),); } @@ -15,7 +15,7 @@ fn it_gets_wasm_bindgen_version() { fn it_gets_wasm_bindgen_test_version() { let fixture = fixture::wbg_test_node(); fixture.cargo_check(); - let data = CrateData::new(&fixture.path, None).unwrap(); + let data = CrateData::new(&fixture.path, None, None).unwrap(); let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_test_version(), Some("0.2.37"),); } @@ -60,7 +60,7 @@ fn it_gets_wasm_bindgen_version_in_crate_inside_workspace() { "#, ); fixture.cargo_check(); - let data = CrateData::new(&fixture.path.join("blah"), None).unwrap(); + let data = CrateData::new(&fixture.path.join("blah"), None, None).unwrap(); let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.37"),); } @@ -128,7 +128,7 @@ fn it_gets_wasm_bindgen_version_from_dependencies() { "#, ); fixture.cargo_check(); - let data = CrateData::new(&fixture.path.join("parent"), None).unwrap(); + let data = CrateData::new(&fixture.path.join("parent"), None, None).unwrap(); let lock = Lockfile::new(&data).unwrap(); assert_eq!(lock.wasm_bindgen_version(), Some("0.2.37"),); } diff --git a/tests/all/manifest.rs b/tests/all/manifest.rs index 1f202a20..e25f684a 100644 --- a/tests/all/manifest.rs +++ b/tests/all/manifest.rs @@ -10,7 +10,7 @@ use wasm_pack::{self, license, manifest}; #[test] fn it_gets_the_crate_name_default_path() { let path = &PathBuf::from("."); - let crate_data = manifest::CrateData::new(&path, None).unwrap(); + let crate_data = manifest::CrateData::new(&path, None, None).unwrap(); let name = crate_data.crate_name(); assert_eq!(name, "wasm_pack"); } @@ -18,14 +18,14 @@ fn it_gets_the_crate_name_default_path() { #[test] fn it_gets_the_crate_name_provided_path() { let fixture = fixture::js_hello_world(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); assert_eq!(crate_data.crate_name(), "js_hello_world"); } #[test] fn it_gets_the_default_name_prefix() { let path = &PathBuf::from("."); - let crate_data = manifest::CrateData::new(&path, None).unwrap(); + let crate_data = manifest::CrateData::new(&path, None, None).unwrap(); let name = crate_data.name_prefix(); assert_eq!(name, "wasm_pack"); } @@ -33,7 +33,7 @@ fn it_gets_the_default_name_prefix() { #[test] fn it_gets_the_name_prefix_passed_from_cli() { let path = &PathBuf::from("."); - let crate_data = manifest::CrateData::new(&path, Some("index".to_owned())).unwrap(); + let crate_data = manifest::CrateData::new(&path, Some("index".to_owned()), None).unwrap(); let name = crate_data.name_prefix(); assert_eq!(name, "index"); } @@ -43,7 +43,7 @@ fn it_checks_has_cdylib_default_path() { let fixture = fixture::no_cdylib(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); assert!(crate_data.check_crate_config().is_err()); } @@ -52,23 +52,30 @@ fn it_checks_has_cdylib_provided_path() { let fixture = fixture::js_hello_world(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); crate_data.check_crate_config().unwrap(); } #[test] fn it_checks_has_cdylib_wrong_crate_type() { let fixture = fixture::bad_cargo_toml(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); assert!(crate_data.check_crate_config().is_err()); } +#[test] +fn it_accepts_binary_crates_without_cdylib() { + let fixture = fixture::bin_crate(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); + crate_data.check_crate_config().unwrap(); +} + #[test] fn it_recognizes_a_map_during_depcheck() { let fixture = fixture::serde_feature(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); crate_data.check_crate_config().unwrap(); } @@ -76,7 +83,7 @@ fn it_recognizes_a_map_during_depcheck() { fn it_creates_a_package_json_default_path() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, false, Target::Bundler) @@ -111,7 +118,7 @@ fn it_creates_a_package_json_default_path() { fn it_creates_a_package_json_provided_path() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, false, Target::Bundler) @@ -139,7 +146,7 @@ fn it_creates_a_package_json_provided_path() { fn it_creates_a_package_json_provided_path_with_scope() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &Some("test".to_string()), false, Target::Bundler,) @@ -167,7 +174,7 @@ fn it_creates_a_package_json_provided_path_with_scope() { fn it_creates_a_pkg_json_with_correct_files_on_node() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, false, Target::Nodejs) @@ -202,7 +209,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() { fn it_creates_a_pkg_json_with_correct_files_on_nomodules() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, false, Target::NoModules) @@ -236,7 +243,8 @@ fn it_creates_a_pkg_json_with_correct_files_on_nomodules() { fn it_creates_a_package_json_with_correct_files_when_out_name_is_provided() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, Some("index".to_owned())).unwrap(); + let crate_data = + manifest::CrateData::new(&fixture.path, Some("index".to_owned()), None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, false, Target::Bundler) @@ -267,7 +275,7 @@ fn it_creates_a_package_json_with_correct_files_when_out_name_is_provided() { fn it_creates_a_pkg_json_in_out_dir() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("./custom/out"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, false, Target::Bundler) @@ -282,7 +290,7 @@ fn it_creates_a_pkg_json_in_out_dir() { fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); assert!(crate_data .write_package_json(&out_dir, &None, true, Target::Bundler) @@ -310,7 +318,7 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() { #[test] fn it_errors_when_wasm_bindgen_is_not_declared() { let fixture = fixture::bad_cargo_toml(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); assert!(crate_data.check_crate_config().is_err()); } @@ -342,7 +350,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() { ); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); crate_data @@ -358,7 +366,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() { // When 'homepage' is unavailable let fixture = fixture::js_hello_world(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); crate_data @@ -374,7 +382,7 @@ fn it_does_not_error_when_wasm_bindgen_is_declared() { let fixture = fixture::js_hello_world(); // Ensure that there is a `Cargo.lock`. fixture.cargo_check(); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); crate_data.check_crate_config().unwrap(); } @@ -458,7 +466,7 @@ fn it_lists_license_files_in_files_field_of_package_json() { let fixture = fixture::dual_license(); let out_dir = fixture.path.join("pkg"); - let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap(); + let crate_data = manifest::CrateData::new(&fixture.path, None, None).unwrap(); wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap(); license::copy_from_crate(&crate_data, &fixture.path, &out_dir).unwrap(); @@ -500,7 +508,7 @@ fn it_recurses_up_the_path_to_find_cargo_toml() { "#, ); let path = get_crate_path(None).unwrap(); - let crate_data = manifest::CrateData::new(&path, None).unwrap(); + let crate_data = manifest::CrateData::new(&path, None, None).unwrap(); let name = crate_data.crate_name(); assert_eq!(name, "wasm_pack"); } @@ -522,6 +530,6 @@ fn it_doesnt_recurse_up_the_path_to_find_cargo_toml_when_default() { "#, ); let path = get_crate_path(Some(PathBuf::from("src"))).unwrap(); - let crate_data = manifest::CrateData::new(&path, None); + let crate_data = manifest::CrateData::new(&path, None, None); assert!(crate_data.is_err()); } diff --git a/tests/all/utils/fixture.rs b/tests/all/utils/fixture.rs index 6c7c1c48..190649bc 100644 --- a/tests/all/utils/fixture.rs +++ b/tests/all/utils/fixture.rs @@ -1,5 +1,6 @@ use binary_install::Cache; use std::env; +use std::ffi::OsStr; use std::fs; use std::mem::ManuallyDrop; use std::path::{Path, PathBuf}; @@ -210,6 +211,41 @@ impl Fixture { ) } + /// Add a `src/main.rs` file that contains a "hello world" program. + pub fn hello_world_src_main(&self) -> &Self { + self.file( + "src/main.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + // Import the `console.log` function from the Web. + #[wasm_bindgen] + extern { + #[wasm_bindgen(js_namespace = console, js_name = log)] + fn console_log(s: &str); + } + + // On wasm, print() should forward to console.log. + #[cfg(target_arch = "wasm32")] + fn print(text: &str) { + console_log(text); + } + + // On not-wasm, print() should forward to println!(). + #[cfg(not(target_arch = "wasm32"))] + fn print(text: &str) { + println!("{}", text); + } + + // Write a main() that will print some text. + fn main() { + print("Hello, World"); + } + "#, + ) + } + /// Install a local wasm-bindgen for this fixture. /// /// Takes care not to re-install for every fixture, but only the one time @@ -221,7 +257,7 @@ impl Fixture { static INSTALL_WASM_BINDGEN: Once = Once::new(); let cache = self.cache(); - let version = "0.2.37"; + let version = "0.2.54"; let download = || { if let Ok(download) = @@ -324,6 +360,12 @@ impl Fixture { Cache::at(&self.cache_dir()) } + pub fn command>(&self, program: S) -> Command { + let mut result = Command::new(program); + result.current_dir(&self.path); + result + } + /// The `step_install_wasm_bindgen` and `step_run_wasm_bindgen` steps only /// occur after the `step_build_wasm` step. In order to read the lockfile /// in the test fixture's temporary directory, we should first build the @@ -423,6 +465,143 @@ pub fn no_cdylib() -> Fixture { fixture } +pub fn bin_crate() -> Fixture { + let fixture = Fixture::new(); + fixture.readme().hello_world_src_main().file( + "Cargo.toml", + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "foo" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [dependencies] + wasm-bindgen = "0.2" + + [dev-dependencies] + wasm-bindgen-test = "0.2" + "#, + ); + fixture +} + +pub fn multi_bin_crate() -> Fixture { + let fixture = Fixture::new(); + fixture + .readme() + .hello_world_src_main() + .file( + "src/bin/sample.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + // Import the `console.log` function from the Web. + #[wasm_bindgen] + extern { + #[wasm_bindgen(js_namespace = console, js_name = log)] + fn console_log(s: &str); + } + + // On wasm, print() should forward to console.log. + #[cfg(target_arch = "wasm32")] + fn print(text: &str) { + console_log(text); + } + + // On not-wasm, print() should forward to println!(). + #[cfg(not(target_arch = "wasm32"))] + fn print(text: &str) { + println!("{}", text); + } + + // Write a main() that will print slightly different text. + fn main() { + print("Sample Text"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "foo" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [dependencies] + wasm-bindgen = "0.2" + + [dev-dependencies] + wasm-bindgen-test = "0.2" + "#, + ); + fixture +} + +pub fn bin_example_crate() -> Fixture { + let fixture = Fixture::new(); + fixture + .readme() + .hello_world_src_main() + .file( + "examples/example.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + + // Import the `console.log` function from the Web. + #[wasm_bindgen] + extern { + #[wasm_bindgen(js_namespace = console, js_name = log)] + fn console_log(s: &str); + } + + // On wasm, print() should forward to console.log. + #[cfg(target_arch = "wasm32")] + fn print(text: &str) { + console_log(text); + } + + // On not-wasm, print() should forward to println!(). + #[cfg(not(target_arch = "wasm32"))] + fn print(text: &str) { + println!("{}", text); + } + + // Write a main() that will print slightly different text. + fn main() { + print("Sample Text"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "foo" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [dependencies] + wasm-bindgen = "0.2" + + [dev-dependencies] + wasm-bindgen-test = "0.2" + "#, + ); + fixture +} + pub fn not_a_crate() -> Fixture { let fixture = Fixture::new(); fixture.file("README.md", "This is not a Rust crate!");