diff --git a/src/bindgen.rs b/src/bindgen.rs index e75610fc..796fb97f 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -21,9 +21,10 @@ pub fn wasm_bindgen_build( profile: BuildProfile, extra_options: &Vec, ) -> Result<(), failure::Error> { - let release_or_debug = match profile { + let release_or_debug_or_profile = match profile { BuildProfile::Release | BuildProfile::Profiling => "release", BuildProfile::Dev => "debug", + BuildProfile::Profile(ref profile) => profile, }; let out_dir = out_dir.to_str().unwrap(); @@ -42,7 +43,7 @@ pub fn wasm_bindgen_build( let wasm_path = target_directory .join("wasm32-unknown-unknown") - .join(release_or_debug) + .join(release_or_debug_or_profile) .join(data.crate_name()) .with_extension("wasm"); diff --git a/src/build/mod.rs b/src/build/mod.rs index c19d12ac..a3de7d13 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::Profile(profile) => { + cmd.arg("--profile").arg(profile); + } } cmd.arg("--target").arg("wasm32-unknown-unknown"); diff --git a/src/command/build.rs b/src/command/build.rs index 12f3d3d0..476e8feb 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -95,7 +95,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, @@ -103,6 +103,8 @@ pub enum BuildProfile { Release, /// Enable optimizations and debug info. Disable assertions. Profiling, + /// Enable custom user defined profile settings. + Profile(String), } /// Everything required to configure and run the `wasm-pack build` command. @@ -136,6 +138,10 @@ pub struct BuildOptions { /// Sets the target environment. [possible values: bundler, nodejs, web, no-modules] pub target: Target, + #[structopt(long = "profile")] + /// Sets the custom user defined profile. + pub profile: Option, + #[structopt(long = "debug")] /// Deprecated. Renamed to `--dev`. pub debug: bool, @@ -174,6 +180,7 @@ impl Default for BuildOptions { mode: InstallMode::default(), disable_dts: false, target: Target::default(), + profile: None, debug: false, dev: false, release: false, @@ -203,13 +210,14 @@ impl Build { let out_dir = crate_path.join(PathBuf::from(build_opts.out_dir)); 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.clone()) { + (false, false, false, None) | (false, true, false, None) => BuildProfile::Release, + (true, false, false, None) => BuildProfile::Dev, + (false, false, true, None) => BuildProfile::Profiling, + (_, _, _, Some(profile)) => BuildProfile::Profile(profile), // Unfortunately, `structopt` 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 a --dev, --release, or --profiling flag, or a --profile flag with a custom user defined profile."), }; Ok(Build { @@ -319,7 +327,7 @@ 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.clone(), &self.extra_options)?; info!( "wasm built at {:#?}.", @@ -392,7 +400,7 @@ impl Build { &self.out_name, self.disable_dts, self.target, - self.profile, + self.profile.clone(), &self.extra_options, )?; info!("wasm bindings were built at {:#?}.", &self.out_dir); @@ -402,7 +410,7 @@ impl Build { fn step_run_wasm_opt(&mut self) -> Result<(), Error> { let 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 6a483523..3ff9bd38 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -92,6 +92,11 @@ struct CargoWasmPackProfiles { deserialize_with = "CargoWasmPackProfile::deserialize_profiling" )] profiling: CargoWasmPackProfile, + #[serde( + default = "CargoWasmPackProfile::default_profiling", + deserialize_with = "CargoWasmPackProfile::deserialize_profile" + )] + profile: CargoWasmPackProfile, } impl Default for CargoWasmPackProfiles { @@ -100,6 +105,7 @@ impl Default for CargoWasmPackProfiles { dev: CargoWasmPackProfile::default_dev(), release: CargoWasmPackProfile::default_release(), profiling: CargoWasmPackProfile::default_profiling(), + profile: CargoWasmPackProfile::default_profile(), } } } @@ -318,6 +324,17 @@ impl CargoWasmPackProfile { } } + fn default_profile() -> Self { + CargoWasmPackProfile { + wasm_bindgen: CargoWasmPackProfileWasmBindgen { + debug_js_glue: Some(false), + demangle_name_section: Some(true), + dwarf_debug_info: Some(false), + }, + wasm_opt: Some(CargoWasmPackProfileWasmOpt::Enabled(true)), + } + } + fn deserialize_dev<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -345,6 +362,15 @@ impl CargoWasmPackProfile { Ok(profile) } + fn deserialize_profile<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut profile = >::deserialize(deserializer)?.unwrap_or_default(); + profile.update_with_defaults(&Self::default_profile()); + Ok(profile) + } + fn update_with_defaults(&mut self, defaults: &Self) { macro_rules! d { ( $( $path:ident ).* ) => { @@ -497,6 +523,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::Profile(_) => &self.manifest.package.metadata.wasm_pack.profile.profile, } } diff --git a/tests/all/build.rs b/tests/all/build.rs index 4524498d..a1cf4b86 100644 --- a/tests/all/build.rs +++ b/tests/all/build.rs @@ -182,6 +182,56 @@ fn build_different_profiles() { } } +#[test] +fn build_with_profile_flag() { + let fixture = utils::fixture::Fixture::new(); + fixture + .readme() + .file( + "Cargo.toml", + r#" + [package] + authors = ["The wasm-pack developers"] + description = "so awesome rust+wasm package" + license = "WTFPL" + name = "somename" + repository = "https://github.com/rustwasm/wasm-pack.git" + version = "0.1.0" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + wasm-bindgen = "0.2" + + [profile.wasm-release] + inherits = "release" + opt-level = "z" + lto = "fat" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate wasm_bindgen; + use wasm_bindgen::prelude::*; + #[wasm_bindgen] + pub fn method() -> i32 { + 2 + } + "#, + ); + + fixture.install_local_wasm_bindgen(); + fixture + .wasm_pack() + .arg("build") + .arg("--profile") + .arg("wasm-release") + .assert() + .success(); +} + #[test] fn build_with_and_without_wasm_bindgen_debug() { for debug in [true, false].iter().cloned() {