cmd(init/build): split init and build

master
csmoe 7 years ago
parent 56f18964f9
commit 7cbfc2e893
  1. 274
      src/command/build.rs
  2. 97
      src/command/init.rs
  3. 69
      src/command/mod.rs
  4. 3
      src/logger.rs

@ -0,0 +1,274 @@
//! Initializing a crate for packing `.wasm`s.
use bindgen;
use build;
use command::utils::{set_crate_path, create_pkg_dir};
use emoji;
use error::Error;
use indicatif::HumanDuration;
use manifest;
use progressbar::Step;
use readme;
use slog::Logger;
use std::time::Instant;
use PBAR;
/// Everything required to configure and run the `wasm-pack init` command.
pub(crate) struct Build {
pub crate_path: String,
pub scope: Option<String>,
pub disable_dts: bool,
pub target: String,
pub debug: bool,
// build_config: Option<BuildConfig>,
pub crate_name: String,
}
/// The `BuildMode` determines which mode of initialization we are running, and
/// what build and install steps we perform.
pub enum BuildMode {
/// Perform all the build and install steps.
Normal,
/// Don't install tools like `wasm-bindgen`, just use the global
/// environment's existing versions to do builds.
Noinstall,
}
/// Everything required to configure and run the `wasm-pack build` command.
#[derive(Debug,StructOpt)]
pub struct BuildOptions {
/// The path to the Rust crate.
pub path: Option<String>,
/// The npm scope to use in package.json, if any.
#[structopt(long = "scope", short = "s")]
pub scope: Option<String>,
#[structopt(long = "mode", short = "m", default_value = "normal")]
/// Sets steps to be run. [possible values: no-install, normal]
pub mode: String,
#[structopt(long = "no-typescript")]
/// By default a *.d.ts file is generated for the generated JS file, but
/// this flag will disable generating this TypeScript file.
pub disable_dts: bool,
#[structopt(long = "target", short = "t", default_value = "browser")]
/// Sets the target environment. [possible values: browser, nodejs]
pub target: String,
#[structopt(long = "debug")]
/// Build without --release.
debug: bool,
// build config from manifest
// build_config: Option<BuildConfig>,
}
impl From<BuildOptions> for Build {
fn from(build_opts: BuildOptions) -> Self {
let crate_path = set_crate_path(build_opts.path);
let crate_name = manifest::get_crate_name(&crate_path).unwrap();
// let build_config = manifest::xxx(&crate_path).xxx();
Build {
crate_path,
scope:build_opts.scope,
disable_dts:build_opts.disable_dts,
target:build_opts.target,
debug:build_opts.debug,
// build_config,
crate_name,
}
}
}
type BuildStep = fn(&mut Build, &Step, &Logger) -> Result<(), Error>;
impl Build {
/// Execute this `Init` command.
pub fn run(&mut self, log: &Logger, mode: BuildMode) -> Result<(), Error> {
let process_steps = Build::get_process_steps(mode);
let mut step_counter = Step::new(process_steps.len());
let started = Instant::now();
for (_, process_step) in process_steps {
process_step(self, &step_counter, log)?;
step_counter.inc();
}
let duration = HumanDuration(started.elapsed());
info!(&log, "Done in {}.", &duration);
info!(
&log,
"Your WASM pkg is ready to publish at {}/pkg.", &self.crate_path
);
PBAR.message(&format!("{} Done in {}", emoji::SPARKLE, &duration));
PBAR.message(&format!(
"{} Your WASM pkg is ready to publish at {}/pkg.",
emoji::PACKAGE,
&self.crate_path
));
Ok(())
}
fn get_process_steps(mode: BuildMode) -> Vec<(&'static str, BuildStep)> {
macro_rules! steps {
($($name:ident),+) => {
{
let mut steps: Vec<(&'static str, BuildStep)> = Vec::new();
$(steps.push((stringify!($name), Build::$name));)*
steps
}
};
($($name:ident,)*) => (steps![$($name),*])
}
match mode {
BuildMode::Normal => steps![
step_check_crate_config,
step_add_wasm_target,
step_build_wasm,
step_create_dir,
step_create_json,
step_copy_readme,
step_install_wasm_bindgen,
step_run_wasm_bindgen,
],
BuildMode::Noinstall => steps![
step_check_crate_config,
step_build_wasm,
step_create_dir,
step_create_json,
step_copy_readme,
step_run_wasm_bindgen
],
}
}
fn step_check_crate_config(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Checking crate configuration...");
manifest::check_crate_config(&self.crate_path, step)?;
info!(&log, "Crate is correctly configured.");
Ok(())
}
fn step_add_wasm_target(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Adding wasm-target...");
build::rustup_add_wasm_target(step)?;
info!(&log, "Adding wasm-target was successful.");
Ok(())
}
fn step_build_wasm(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Building wasm...");
build::cargo_build_wasm(&self.crate_path, self.debug, step)?;
#[cfg(not(target_os = "windows"))]
info!(
&log,
"wasm built at {}/target/wasm32-unknown-unknown/release.", &self.crate_path
);
#[cfg(target_os = "windows")]
info!(
&log,
"wasm built at {}\\target\\wasm32-unknown-unknown\\release.", &self.crate_path
);
Ok(())
}
fn step_create_dir(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Creating a pkg directory...");
create_pkg_dir(&self.crate_path, step)?;
info!(&log, "Created a pkg directory at {}.", &self.crate_path);
Ok(())
}
fn step_create_json(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Writing a package.json...");
manifest::write_package_json(
&self.crate_path,
&self.scope,
self.disable_dts,
&self.target,
step,
)?;
#[cfg(not(target_os = "windows"))]
info!(
&log,
"Wrote a package.json at {}/pkg/package.json.", &self.crate_path
);
#[cfg(target_os = "windows")]
info!(
&log,
"Wrote a package.json at {}\\pkg\\package.json.", &self.crate_path
);
Ok(())
}
fn step_copy_readme(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Copying readme from crate...");
readme::copy_from_crate(&self.crate_path, step)?;
#[cfg(not(target_os = "windows"))]
info!(
&log,
"Copied readme from crate to {}/pkg.", &self.crate_path
);
#[cfg(target_os = "windows")]
info!(
&log,
"Copied readme from crate to {}\\pkg.", &self.crate_path
);
Ok(())
}
fn step_install_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Installing wasm-bindgen-cli...");
bindgen::cargo_install_wasm_bindgen(step)?;
info!(&log, "Installing wasm-bindgen-cli was successful.");
info!(&log, "Getting the crate name from the manifest...");
self.crate_name = manifest::get_crate_name(&self.crate_path)?;
#[cfg(not(target_os = "windows"))]
info!(
&log,
"Got crate name {} from the manifest at {}/Cargo.toml.",
&self.crate_name,
&self.crate_path
);
#[cfg(target_os = "windows")]
info!(
&log,
"Got crate name {} from the manifest at {}\\Cargo.toml.",
&self.crate_name,
&self.crate_path
);
Ok(())
}
fn step_run_wasm_bindgen(&mut self, step: &Step, log: &Logger) -> Result<(), Error> {
info!(&log, "Building the wasm bindings...");
bindgen::wasm_bindgen_build(
&self.crate_path,
&self.crate_name,
self.disable_dts,
&self.target,
self.debug,
step,
)?;
#[cfg(not(target_os = "windows"))]
info!(
&log,
"wasm bindings were built at {}/pkg.", &self.crate_path
);
#[cfg(target_os = "windows")]
info!(
&log,
"wasm bindings were built at {}\\pkg.", &self.crate_path
);
Ok(())
}
}

@ -1,8 +1,6 @@
//! Initializing a crate for packing `.wasm`s.
use bindgen;
use build;
use command::utils::set_crate_path;
use command::utils::{set_crate_path,create_pkg_dir};
use emoji;
use error::Error;
use indicatif::HumanDuration;
@ -43,71 +41,54 @@ pub struct Init {
scope: Option<String>,
disable_dts: bool,
target: String,
// build without --release.
debug: bool,
crate_name: String,
}
type InitStep = fn(&mut Init, &Step, &Logger) -> Result<(), Error>;
/// `Init` options
#[derive(Debug, StructOpt)]
pub struct InitOptions {
/// The path to the Rust crate.
pub path: Option<String>,
impl Init {
/// Construct a new `Init` command.
pub fn new(
path: Option<PathBuf>,
scope: Option<String>,
disable_dts: bool,
target: String,
debug: bool,
) -> Result<Init, Error> {
let crate_path = set_crate_path(path);
let crate_name = manifest::get_crate_name(&crate_path)?;
Ok(Init {
crate_path,
scope,
disable_dts,
target,
debug,
crate_name,
})
}
/// The npm scope to use in package.json, if any.
#[structopt(long = "scope", short = "s")]
pub scope: Option<String>,
fn get_process_steps(mode: InitMode) -> Vec<(&'static str, InitStep)> {
macro_rules! steps {
($($name:ident),+) => {
{
let mut steps: Vec<(&'static str, InitStep)> = Vec::new();
$(steps.push((stringify!($name), Init::$name));)*
steps
}
};
($($name:ident,)*) => (steps![$($name),*])
}
#[structopt(long = "no-typescript")]
/// By default a *.d.ts file is generated for the generated JS file, but
/// this flag will disable generating this TypeScript file.
pub disable_dts: bool,
#[structopt(long = "target", short = "t", default_value = "browser")]
/// Sets the target environment. [possible values: browser, nodejs]
pub target: String,
match mode {
InitMode::Normal => steps![
step_check_crate_config,
step_add_wasm_target,
step_build_wasm,
step_create_dir,
step_create_json,
step_copy_readme,
step_install_wasm_bindgen,
step_run_wasm_bindgen,
],
InitMode::Nobuild => steps![step_create_dir, step_create_json, step_copy_readme,],
InitMode::Noinstall => steps![
step_check_crate_config,
step_build_wasm,
step_create_dir,
step_create_json,
step_copy_readme,
step_run_wasm_bindgen
],
#[structopt(long = "debug")]
/// Build without --release.
pub debug: bool,
}
impl From<InitOptions> for Init {
fn from(init_opts: InitOptions) -> Self {
let crate_path = set_crate_path(init_opts.path);
let crate_name = manifest::get_crate_name(&crate_path).unwrap();
Init {
crate_path,
scope: init_opts.scope,
disable_dts:init_opts.disable_dts,
target:init_opts.target,
debug:init_opts.debug,
}
}
}
type InitStep = fn(&mut Init, &Step, &Logger) -> Result<(), Error>;
impl Init {
/// Execute this `Init` command.
pub fn process(&mut self, log: &Logger, mode: InitMode) -> Result<(), Error> {
let process_steps = Init::get_process_steps(mode);
pub fn run(&mut self, log: &Logger) -> Result<(), Error> {
let process_steps = Init::set_process_steps();
let mut step_counter = Step::new(process_steps.len());

@ -1,15 +1,17 @@
//! CLI command structures, parsing, and execution.
mod build;
pub mod init;
mod login;
mod pack;
mod publish;
pub mod utils;
use self::init::{Init, InitMode};
use self::login::login;
use self::pack::pack;
use self::publish::publish;
use self::build::{Build,BuildMode};
use self::init::Init;
use error::Error;
use slog::Logger;
use std::path::PathBuf;
@ -21,37 +23,16 @@ use PBAR;
pub enum Command {
#[structopt(name = "init")]
/// 🐣 initialize a package.json based on your compiled wasm!
Init {
/// The path to the Rust crate.
#[structopt(parse(from_os_str))]
path: Option<PathBuf>,
/// The npm scope to use in package.json, if any.
#[structopt(long = "scope", short = "s")]
scope: Option<String>,
#[structopt(long = "mode", short = "m", default_value = "normal")]
/// Sets steps to be run. [possible values: no-build, no-install, normal]
mode: String,
#[structopt(long = "no-typescript")]
/// By default a *.d.ts file is generated for the generated JS file, but
/// this flag will disable generating this TypeScript file.
disable_dts: bool,
#[structopt(long = "target", short = "t", default_value = "browser")]
/// Sets the target environment. [possible values: browser, nodejs]
target: String,
Init(init::InitOptions),
#[structopt(long = "debug")]
/// Build without --release.
debug: bool,
},
/// build
#[structopt(name = "build")]
Build(self::build::BuildOptions),
#[structopt(name = "pack")]
/// 🍱 create a tar of your npm package but don't publish!
Pack {
/// The path to the Rust crate.
/// The path to the Rust crate.
#[structopt(parse(from_os_str))]
path: Option<PathBuf>,
},
@ -102,32 +83,18 @@ pub fn run_wasm_pack(command: Command, log: &Logger) -> result::Result<(), Error
// Run the correct command based off input and store the result of it so that we can clear
// the progress bar then return it
let status = match command {
Command::Init {
path,
scope,
mode,
disable_dts,
target,
debug,
} => {
Command::Init(init_opts) => {
info!(&log, "Running init command...");
info!(
&log,
"Path: {:?}, Scope: {:?}, Skip build: {}, Disable Dts: {}, Target: {}, Debug: {}",
&path,
&scope,
&mode,
&disable_dts,
&target,
debug
);
let modetype = match &*mode {
"no-build" => InitMode::Nobuild,
"no-install" => InitMode::Noinstall,
"normal" => InitMode::Normal,
_ => InitMode::Normal,
Init::from(init_opts).run(&log)
}
Command::Build(build_opts) => {
info!(&log, "Running build command...");
let build_mode = match build_opts.mode.as_str() {
"no-install" => BuildMode::Noinstall,
"normal" => BuildMode::Normal,
_ => BuildMode::Normal,
};
Init::new(path, scope, disable_dts, target, debug)?.process(&log, modetype)
Build::from(build_opts).run(&log, build_mode)
}
Command::Pack { path } => {
info!(&log, "Running pack command...");

@ -33,7 +33,8 @@ pub fn new(cmd: &Command, verbosity: u8) -> Result<Logger, Error> {
/// Figure out where to stick the log based off the command arguments given
fn log_file_path(cmd: &Command) -> PathBuf {
let path = match cmd {
Command::Init { path, .. } => path,
Command::Init(init_opts) => &init_opts.path,
Command::Build(build_opts) => &build_opts.path,
Command::Pack { path } => path,
Command::Publish { path } => path,
Command::Login { .. } => &None,

Loading…
Cancel
Save