diff --git a/src/bindgen.rs b/src/bindgen.rs index acf369f..e57d2e4 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -23,9 +23,10 @@ pub fn wasm_bindgen_build( profile: BuildProfile, extra_options: &Vec, ) -> Result<()> { - let release_or_debug = match profile { + let profile_name = match profile.clone() { BuildProfile::Release | BuildProfile::Profiling => "release", BuildProfile::Dev => "debug", + BuildProfile::Custom(profile_name) => &profile_name.clone(), }; let out_dir = out_dir.to_str().unwrap(); @@ -41,7 +42,7 @@ pub fn wasm_bindgen_build( let wasm_path = target_directory .join("wasm32-unknown-unknown") - .join(release_or_debug) + .join(profile_name) .join(data.crate_name()) .with_extension("wasm"); diff --git a/src/build/mod.rs b/src/build/mod.rs index d657071..ee2963e 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -104,6 +104,9 @@ pub fn cargo_build_wasm( // Plain cargo builds use the dev cargo profile, which includes // debug info by default. } + BuildProfile::Custom(arg) => { + cmd.arg("--profile").arg(arg); + } } cmd.arg("--target").arg("wasm32-unknown-unknown"); diff --git a/src/command/build.rs b/src/command/build.rs index 9960c96..11d3ab9 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -100,7 +100,7 @@ impl FromStr for Target { /// The build profile controls whether optimizations, debug info, and assertions /// are enabled or disabled. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub enum BuildProfile { /// Enable assertions and debug info. Disable optimizations. Dev, @@ -108,6 +108,8 @@ pub enum BuildProfile { Release, /// Enable optimizations and debug info. Disable assertions. Profiling, + /// User-defined profile with --profile flag + Custom(String), } /// Everything required to configure and run the `wasm-pack build` command. @@ -160,6 +162,10 @@ pub struct BuildOptions { /// Create a profiling build. Enable optimizations and debug info. pub profiling: bool, + #[clap(long = "profile")] + /// User-defined profile with --profile flag + pub profile: Option, + #[clap(long = "out-dir", short = 'd', default_value = "pkg")] /// Sets the output directory with a relative path. pub out_dir: String, @@ -196,6 +202,7 @@ impl Default for BuildOptions { no_opt: false, release: false, profiling: false, + profile: None, out_dir: String::new(), out_name: None, extra_options: Vec::new(), @@ -221,13 +228,19 @@ impl Build { let out_dir = crate_path.join(PathBuf::from(build_opts.out_dir)).clean(); let dev = build_opts.dev || build_opts.debug; - let profile = match (dev, build_opts.release, build_opts.profiling) { - (false, false, false) | (false, true, false) => BuildProfile::Release, - (true, false, false) => BuildProfile::Dev, - (false, false, true) => BuildProfile::Profiling, + let profile = match ( + dev, + build_opts.release, + build_opts.profiling, + build_opts.profile, + ) { + (false, false, false, None) | (false, true, false, None) => BuildProfile::Release, + (true, false, false, None) => BuildProfile::Dev, + (false, false, true, None) => BuildProfile::Profiling, + (false, false, false, Some(profile)) => BuildProfile::Custom(profile), // Unfortunately, `clap` doesn't expose clap's `conflicts_with` // functionality yet, so we have to implement it ourselves. - _ => bail!("Can only supply one of the --dev, --release, or --profiling flags"), + _ => bail!("Can only supply one of the --dev, --release, --profiling, or --profile 'name' flags"), }; Ok(Build { @@ -355,7 +368,7 @@ impl Build { fn step_build_wasm(&mut self) -> Result<()> { info!("Building wasm..."); - build::cargo_build_wasm(&self.crate_path, self.profile, &self.extra_options)?; + build::cargo_build_wasm(&self.crate_path, self.profile.clone(), &self.extra_options)?; info!( "wasm built at {:#?}.", @@ -430,7 +443,7 @@ impl Build { self.weak_refs, self.reference_types, self.target, - self.profile, + self.profile.clone(), &self.extra_options, )?; info!("wasm bindings were built at {:#?}.", &self.out_dir); @@ -440,7 +453,7 @@ impl Build { fn step_run_wasm_opt(&mut self) -> Result<()> { let mut args = match self .crate_data - .configured_profile(self.profile) + .configured_profile(self.profile.clone()) .wasm_opt_args() { Some(args) => args, diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 342fc57..00b36c7 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -85,6 +85,12 @@ struct CargoWasmPackProfiles { deserialize_with = "CargoWasmPackProfile::deserialize_profiling" )] profiling: CargoWasmPackProfile, + + #[serde( + default = "CargoWasmPackProfile::default_custom", + deserialize_with = "CargoWasmPackProfile::deserialize_custom" + )] + custom: CargoWasmPackProfile, } impl Default for CargoWasmPackProfiles { @@ -93,6 +99,7 @@ impl Default for CargoWasmPackProfiles { dev: CargoWasmPackProfile::default_dev(), release: CargoWasmPackProfile::default_release(), profiling: CargoWasmPackProfile::default_profiling(), + custom: CargoWasmPackProfile::default_custom(), } } } @@ -305,6 +312,18 @@ impl CargoWasmPackProfile { } } + fn default_custom() -> Self { + CargoWasmPackProfile { + wasm_bindgen: CargoWasmPackProfileWasmBindgen { + debug_js_glue: Some(false), + demangle_name_section: Some(true), + dwarf_debug_info: Some(false), + omit_default_module_path: Some(false), + }, + wasm_opt: Some(CargoWasmPackProfileWasmOpt::Enabled(true)), + } + } + fn deserialize_dev<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -332,6 +351,15 @@ impl CargoWasmPackProfile { Ok(profile) } + fn deserialize_custom<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut profile = >::deserialize(deserializer)?.unwrap_or_default(); + profile.update_with_defaults(&Self::default_custom()); + Ok(profile) + } + fn update_with_defaults(&mut self, defaults: &Self) { macro_rules! d { ( $( $path:ident ).* ) => { @@ -490,6 +518,7 @@ impl CrateData { BuildProfile::Dev => &self.manifest.package.metadata.wasm_pack.profile.dev, BuildProfile::Profiling => &self.manifest.package.metadata.wasm_pack.profile.profiling, BuildProfile::Release => &self.manifest.package.metadata.wasm_pack.profile.release, + BuildProfile::Custom(_) => &self.manifest.package.metadata.wasm_pack.profile.custom, } } diff --git a/tests/all/build.rs b/tests/all/build.rs index 4e89e2c..01f0ec3 100644 --- a/tests/all/build.rs +++ b/tests/all/build.rs @@ -212,6 +212,21 @@ fn build_different_profiles() { } } +#[test] +fn build_custom_profile() { + let profile_name = "my-custom-profile"; + let fixture = utils::fixture::js_hello_world_with_custom_profile(profile_name); + fixture.install_local_wasm_bindgen(); + + fixture + .wasm_pack() + .arg("build") + .arg("--profile") + .arg(profile_name) + .assert() + .success(); +} + #[test] fn build_with_and_without_wasm_bindgen_debug() { for debug in [true, false].iter().cloned() { diff --git a/tests/all/utils/fixture.rs b/tests/all/utils/fixture.rs index 188a460..7f08948 100644 --- a/tests/all/utils/fixture.rs +++ b/tests/all/utils/fixture.rs @@ -154,6 +154,49 @@ impl Fixture { ) } + /// Add a `Cargo.toml` with a correctly configured `wasm-bindgen` + /// dependency, `wasm-bindgen-test` dev-dependency, and `crate-type = + /// ["cdylib"]`. + /// + /// `name` is the crate's name. + /// `profile` is the custom profile name. + pub fn cargo_toml_with_custom_profile(&self, name: &str, profile_name: &str) -> &Self { + self.file( + "Cargo.toml", + &format!( + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "{}" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + # Note that this uses and `=` dependency because there are + # various tests which assert that the version of wasm + # bindgen downloaded is what we expect, and if `=` is + # removed then it will download whatever the newest version + # of wasm-bindgen is which may not be what's listed here. + wasm-bindgen = "=0.2.74" + + [dev-dependencies] + wasm-bindgen-test = "0.3" + + [profile.{}] + inherits = "release" + opt-level = 'z' + lto = true + "#, + name, profile_name + ), + ) + } + /// Add a `Cargo.toml` with a correctly configured `wasm-bindgen` /// dependency, `wasm-bindgen-test` dev-dependency, and `crate-type = /// ["cdylib"]`. @@ -404,6 +447,15 @@ pub fn js_hello_world() -> Fixture { fixture } +pub fn js_hello_world_with_custom_profile(profile_name: &str) -> Fixture { + let fixture = Fixture::new(); + fixture + .readme() + .cargo_toml_with_custom_profile("js-hello-world", profile_name) + .hello_world_src_lib(); + fixture +} + pub fn no_cdylib() -> Fixture { let fixture = Fixture::new(); fixture.readme().hello_world_src_lib().file(