From 3d03032cf73ad1866f33894452653483d28daaac Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 6 Nov 2018 13:23:45 -0800 Subject: [PATCH] Add three build profiles and infrastructure for their toml config Fixes #153 Fixes #160 --- src/bindgen.rs | 10 +++++--- src/build.rs | 24 ++++++++++++++--- src/command/build.rs | 52 ++++++++++++++++++++++++++++++++----- src/manifest/mod.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++ tests/all/build.rs | 20 +++++++++++++++ 5 files changed, 154 insertions(+), 13 deletions(-) diff --git a/src/bindgen.rs b/src/bindgen.rs index 7cab450e4..094147df2 100644 --- a/src/bindgen.rs +++ b/src/bindgen.rs @@ -2,6 +2,7 @@ use binaries::{Cache, Download}; use child; +use command::build::BuildProfile; use emoji; use failure::{self, ResultExt}; use manifest::CrateData; @@ -145,14 +146,17 @@ pub fn wasm_bindgen_build( out_dir: &Path, disable_dts: bool, target: &str, - debug: bool, + profile: BuildProfile, step: &Step, log: &Logger, ) -> Result<(), failure::Error> { let msg = format!("{}Running WASM-bindgen...", emoji::RUNNER); PBAR.step(step, &msg); - let release_or_debug = if debug { "debug" } else { "release" }; + let release_or_debug = match profile { + BuildProfile::Release | BuildProfile::Profiling => "release", + BuildProfile::Dev => "debug", + }; let out_dir = out_dir.to_str().unwrap(); @@ -181,7 +185,7 @@ pub fn wasm_bindgen_build( .arg(dts_arg) .arg(target_arg); - if debug { + if profile.debug_info_is_enabled() { cmd.arg("--debug"); } diff --git a/src/build.rs b/src/build.rs index 327bf055c..9b72ae075 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,6 +1,7 @@ //! Building a Rust crate into a `.wasm` binary. use child; +use command::build::BuildProfile; use emoji; use failure::{Error, ResultExt}; use progressbar::Step; @@ -62,13 +63,30 @@ pub fn rustup_add_wasm_target(log: &Logger, step: &Step) -> Result<(), Error> { } /// Run `cargo build` targetting `wasm32-unknown-unknown`. -pub fn cargo_build_wasm(log: &Logger, path: &Path, debug: bool, step: &Step) -> Result<(), Error> { +pub fn cargo_build_wasm( + log: &Logger, + path: &Path, + profile: BuildProfile, + step: &Step, +) -> Result<(), Error> { let msg = format!("{}Compiling to WASM...", emoji::CYCLONE); PBAR.step(step, &msg); let mut cmd = Command::new("cargo"); cmd.current_dir(path).arg("build").arg("--lib"); - if !debug { - cmd.arg("--release"); + match profile { + BuildProfile::Profiling => { + // Force enable debug info, because builds that use the release + // cargo profile disables debug info. + cmd.env("RUSTFLAGS", "-g"); + cmd.arg("--release"); + } + BuildProfile::Release => { + cmd.arg("--release"); + } + BuildProfile::Dev => { + // Plain cargo builds use the dev cargo profile, which includes + // debug info by default. + } } cmd.arg("--target").arg("wasm32-unknown-unknown"); child::run(log, cmd, "cargo build").context("Compiling your crate to WebAssembly failed")?; diff --git a/src/command/build.rs b/src/command/build.rs index 34c79f4d3..ee91f2597 100644 --- a/src/command/build.rs +++ b/src/command/build.rs @@ -25,9 +25,8 @@ pub struct Build { pub scope: Option, pub disable_dts: bool, pub target: String, - pub debug: bool, + pub profile: BuildProfile, pub mode: BuildMode, - // build_config: Option, pub out_dir: PathBuf, pub bindgen: Option, pub cache: Cache, @@ -64,6 +63,28 @@ impl FromStr for BuildMode { } } +/// The build profile controls whether optimizations, debug info, and assertions +/// are enabled or disabled. +#[derive(Clone, Copy, Debug)] +pub enum BuildProfile { + /// Enable assertions and debug info. Disable optimizations. + Dev, + /// Enable optimizations. Disable assertions and debug info. + Release, + /// Enable optimizations and debug info. Disable assertions. + Profiling, +} + +impl BuildProfile { + /// Is debug info enabled for this profile? + pub fn debug_info_is_enabled(&self) -> bool { + match self { + BuildProfile::Dev | BuildProfile::Profiling => true, + BuildProfile::Release => false, + } + } +} + /// Everything required to configure and run the `wasm-pack build` command. #[derive(Debug, StructOpt)] pub struct BuildOptions { @@ -97,6 +118,14 @@ pub struct BuildOptions { /// optimizations. dev: bool, + #[structopt(long = "release")] + /// Create a release build. Enable optimizations and disable debug info. + release: bool, + + #[structopt(long = "profiling")] + /// Create a profiling build. Enable optimizations and debug info. + profiling: bool, + #[structopt(long = "out-dir", short = "d", default_value = "pkg")] /// Sets the output directory with a relative path. pub out_dir: String, @@ -110,16 +139,25 @@ impl Build { let crate_path = set_crate_path(build_opts.path)?; let crate_data = manifest::CrateData::new(&crate_path)?; let out_dir = crate_path.join(PathBuf::from(build_opts.out_dir)); - // let build_config = manifest::xxx(&crate_path).xxx(); + + 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, + // 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"), + }; + Ok(Build { crate_path, crate_data, scope: build_opts.scope, disable_dts: build_opts.disable_dts, target: build_opts.target, - debug: build_opts.dev || build_opts.debug, + profile, mode: build_opts.mode, - // build_config, out_dir, bindgen: None, cache: Cache::new()?, @@ -227,7 +265,7 @@ impl Build { fn step_build_wasm(&mut self, step: &Step, log: &Logger) -> Result<(), Error> { info!(&log, "Building wasm..."); - build::cargo_build_wasm(log, &self.crate_path, self.debug, step)?; + build::cargo_build_wasm(log, &self.crate_path, self.profile, step)?; info!( &log, @@ -302,7 +340,7 @@ impl Build { &self.out_dir, self.disable_dts, &self.target, - self.debug, + self.profile, step, log, )?; diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index e418cd3f9..1e502a6da 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -26,6 +26,10 @@ pub struct CrateData { #[derive(Deserialize)] struct CargoManifest { package: CargoPackage, + + #[serde(default)] + #[allow(dead_code)] + metadata: CargoMetadata, } #[derive(Deserialize)] @@ -36,6 +40,63 @@ struct CargoPackage { repository: Option, } +#[derive(Default, Deserialize)] +struct CargoMetadata { + #[serde(rename = "wasm-pack")] + #[allow(dead_code)] + wasm_pack: CargoWasmPack, +} + +#[derive(Default, Deserialize)] +struct CargoWasmPack { + #[allow(dead_code)] + profile: CargoWasmPackProfiles, +} + +#[derive(Deserialize)] +struct CargoWasmPackProfiles { + #[allow(dead_code)] + dev: CargoWasmPackProfile, + + #[allow(dead_code)] + release: CargoWasmPackProfile, + + #[allow(dead_code)] + profiling: CargoWasmPackProfile, +} + +impl Default for CargoWasmPackProfiles { + fn default() -> CargoWasmPackProfiles { + let dev = CargoWasmPackProfile::dev(); + let release = CargoWasmPackProfile::release(); + let profiling = CargoWasmPackProfile::profiling(); + CargoWasmPackProfiles { + dev, + release, + profiling, + } + } +} + +#[derive(Deserialize)] +struct CargoWasmPackProfile { + // This is where wasm-opt, wasm-snip, etc configuration will go. +} + +impl CargoWasmPackProfile { + fn dev() -> CargoWasmPackProfile { + CargoWasmPackProfile {} + } + + fn release() -> CargoWasmPackProfile { + CargoWasmPackProfile {} + } + + fn profiling() -> CargoWasmPackProfile { + CargoWasmPackProfile {} + } +} + struct NpmData { name: String, files: Vec, diff --git a/tests/all/build.rs b/tests/all/build.rs index 91a15e084..1878a0125 100644 --- a/tests/all/build.rs +++ b/tests/all/build.rs @@ -125,3 +125,23 @@ fn renamed_crate_name_works() { .unwrap(); fixture.run(cli.cmd).unwrap(); } + +#[test] +fn build_different_profiles() { + let fixture = utils::fixture::js_hello_world(); + fixture.install_local_wasm_bindgen(); + + for profile in ["--dev", "--debug", "--profiling", "--release"] + .iter() + .cloned() + { + let cli = Cli::from_iter_safe(vec![ + "wasm-pack", + "build", + profile, + &fixture.path.display().to_string(), + ]) + .unwrap(); + fixture.run(cli.cmd).unwrap(); + } +}