Merge pull request #216 from csmoe/build

Split init into init and build
master
ashley williams 7 years ago committed by GitHub
commit 883cae220c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      README.md
  2. 73
      docs/build.md
  3. 33
      docs/init.md
  4. 229
      src/command/build.rs
  5. 69
      src/command/mod.rs
  6. 14
      src/command/utils.rs
  7. 2
      src/logger.rs
  8. 6
      src/main.rs
  9. 10
      tests/all/manifest.rs

@ -29,9 +29,10 @@ visiting that repo!
## 🎙 Commands
- [`init`](docs/init.md): [**Deprecated**] Initialize an npm wasm pkg from a rustwasm crate
- [`build`](docs/build.md): Generate an npm wasm pkg from a rustwasm crate
- [`init`](docs/init.md): Generate an npm wasm pkg from a rustwasm crate
- [`pack`](docs/pack-and-publish.md): Create a tarball of your rustwasm pkg
- [`publish`](docs/publish.md): Publish your rustwasm pkg to a registry
- [`pack` and `publish`](docs/pack-and-publish.md): Create a tarball of your rustwasm pkg and/or publish to a registry
## 📝 Logging
@ -89,7 +90,7 @@ check out our [contribution policy].
```
5. Install this tool: `cargo install wasm-pack`
6. Run `wasm-pack init`, optionally, pass a path to a dir or a scope (see above for details)
6. Run `wasm-pack build`, optionally, pass a path to a dir or a scope (see above for details)
7. This tool generates files in a `pkg` dir
8. To publish to npm, run `wasm-pack publish`. You may need to login to the
registry you want to publish to. You can login using `wasm-pack login`.

@ -0,0 +1,73 @@
# wasm-pack build
The `wasm-pack build` command creates the files neccessary for JavaScript
interoperability and for publishing a package to npm. This involves compiling
your code to wasm and generating a pkg folder. This pkg folder will contain the
wasm binary, a JS wrapper file, your `README`, and a `package.json` file.
## Path
The `wasm-pack build` command can be given an optional path argument, e.g.:
```
wasm-pack build examples/js-hello-world
```
This path should point to a directory that contains a `Cargo.toml` file. If no
path is given, the `build` command will run in the current directory.
## Debug
The init command accepts an optional `--debug` argument. This will build the
output package using cargo's
[default non-release profile][cargo-profile-sections-documentation]. Building
this way is faster but applies few optimizations to the output, and enables
debug assertions and other runtime correctness checks.
The exact meaning of this flag may evolve as the platform matures.
[cargo-profile-sections-documentation]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections
## Target
The `build` command accepts a `--target` argument. This will customize the output files
to align with a particular type of JS module. This allows wasm-pack to generate either
ES6 modules or CommonJS modules for use in browser and in NodeJS. Defaults to `browser`.
The options are:
```
wasm-pack build --target nodejs
```
| Option | Description |
|-----------|-----------------------------------------------------------------------------------------------------------------|
| `nodejs` | Outputs JS that uses CommonJS modules, for use with a `require` statement. |
| `browser` | Outputs JS that uses ES6 modules, primarily for use with `import` statements and/or bundlers such as `webpack`. |
## Scope
The init command also accepts an optional `--scope` argument. This will scope
your package name, which is useful if your package name might conflict with
something in the public registry. For example:
```
wasm-pack build examples/js-hello-world --scope test
```
This command would create a `package.json` file for a package called
`@test/js-hello-world`. For more information about scoping, you can refer to
the npm documentation [here][npm-scope-documentation].
[npm-scope-documentation]: https://docs.npmjs.com/misc/scope
## Mode
The `build` command accepts an optional `--mode` argument.
```
wasm-pack build examples/js-hello-world --mode no-install
```
| Option | Description |
|---------------|------------------------------------------------------------------------------------------|
| `no-install` | `wasm-pack init` implicitly and create wasm binding without installing `wasm-bindgen`. |
| `normal` | do all the stuffs of `no-install` with installed `wasm-bindgen`. |

@ -1,9 +1,9 @@
# wasm-pack init
# wasm-pack init(Deprecated)
The `wasm-pack init` command creates the files neccessary for JavaScript
interoperability and for publishing a package to npm. This involves compiling
your code to wasm and generating a pkg folder. This pkg folder will contain the
wasm binary, a JS wrapper file, your `README`, and a `package.json` file.
interoperability and for publishing a package to npm. This involves
generating a pkg folder. This pkg folder will contain the
`README` and a `package.json` file.
## Path
@ -46,27 +46,4 @@ This command would create a `package.json` file for a package called
`@test/js-hello-world`. For more information about scoping, you can refer to
the npm documentation [here][npm-scope-documentation].
## Debug
The init command accepts an optional `--debug` argument. This will build the
output package using cargo's
[default non-release profile][cargo-profile-sections-documentation]. Building
this way is faster but applies few optimizations to the output, and enables
debug assertions and other runtime correctness checks.
The exact meaning of this flag may evolve as the platform matures.
[npm-scope-documentation]: https://docs.npmjs.com/misc/scope
[cargo-profile-sections-documentation]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-profile-sections
## Skipping build
The init command accepts an optional `--skip-build` argument.
This will deactivate those steps:
- installing wasm target (via cargo)
- compiling the code to wasm
- installing wasm-bindgen (via rustup)
- running wasm-bindgen on the built wasm
Basically it will remains only the steps that update the metadata of `package.json`.
[npm-scope-documentation]: https://docs.npmjs.com/misc/scope

@ -1,8 +1,6 @@
//! Initializing a crate for packing `.wasm`s.
use bindgen;
use build;
use command::utils::set_crate_path;
use command::utils::{create_pkg_dir, set_crate_path};
use emoji;
use error::Error;
use indicatif::HumanDuration;
@ -10,104 +8,85 @@ use manifest;
use progressbar::Step;
use readme;
use slog::Logger;
use std::fs;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::time::Instant;
use PBAR;
/// Construct our `pkg` directory in the crate.
pub fn create_pkg_dir(path: &Path, step: &Step) -> Result<(), Error> {
let msg = format!("{}Creating a pkg directory...", emoji::FOLDER);
PBAR.step(step, &msg);
let pkg_dir_path = path.join("pkg");
fs::create_dir_all(pkg_dir_path)?;
Ok(())
/// Everything required to configure and run the `wasm-pack init` command.
pub(crate) struct Build {
pub crate_path: PathBuf,
pub scope: Option<String>,
pub disable_dts: bool,
pub target: String,
pub debug: bool,
// build_config: Option<BuildConfig>,
pub crate_name: String,
}
/// The `InitMode` determines which mode of initialization we are running, and
/// The `BuildMode` determines which mode of initialization we are running, and
/// what build and install steps we perform.
pub enum InitMode {
pub enum BuildMode {
/// Perform all the build and install steps.
Normal,
/// Don't build the crate as a `.wasm` but do install tools and create
/// meta-data.
Nobuild,
/// 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 init` command.
pub struct Init {
crate_path: PathBuf,
scope: Option<String>,
disable_dts: bool,
target: String,
/// Everything required to configure and run the `wasm-pack build` command.
#[derive(Debug, StructOpt)]
pub struct BuildOptions {
/// The path to the Rust crate.
#[structopt(parse(from_os_str))]
pub path: Option<PathBuf>,
/// 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,
crate_name: String,
// build config from manifest
// build_config: Option<BuildConfig>,
}
type InitStep = fn(&mut Init, &Step, &Logger) -> Result<(), Error>;
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 {
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,
disable_dts,
target,
debug,
scope: build_opts.scope,
disable_dts: build_opts.disable_dts,
target: build_opts.target,
debug: build_opts.debug,
// build_config,
crate_name,
})
}
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),*])
}
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
],
}
}
}
type BuildStep = fn(&mut Build, &Step, &Logger) -> Result<(), Error>;
/// Execute this `Init` command.
pub fn process(&mut self, log: &Logger, mode: InitMode) -> Result<(), Error> {
let process_steps = Init::get_process_steps(mode);
impl Build {
/// Execute this `Build` 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());
@ -136,6 +115,39 @@ impl Init {
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)?;
@ -235,60 +247,3 @@ impl Init {
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn init_normal_build() {
let steps: Vec<&str> = Init::get_process_steps(InitMode::Normal)
.into_iter()
.map(|(n, _)| n)
.collect();
assert_eq!(
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"
]
);
}
#[test]
fn init_skip_build() {
let steps: Vec<&str> = Init::get_process_steps(InitMode::Nobuild)
.into_iter()
.map(|(n, _)| n)
.collect();
assert_eq!(
steps,
["step_create_dir", "step_create_json", "step_copy_readme"]
);
}
#[test]
fn init_skip_install() {
let steps: Vec<&str> = Init::get_process_steps(InitMode::Noinstall)
.into_iter()
.map(|(n, _)| n)
.collect();
assert_eq!(
steps,
[
"step_check_crate_config",
"step_build_wasm",
"step_create_dir",
"step_create_json",
"step_copy_readme",
"step_run_wasm_bindgen"
]
);
}
}

@ -1,12 +1,12 @@
//! CLI command structures, parsing, and execution.
pub mod init;
mod build;
mod login;
mod pack;
mod publish;
pub mod utils;
use self::init::{Init, InitMode};
use self::build::{Build, BuildMode, BuildOptions};
use self::login::login;
use self::pack::pack;
use self::publish::publish;
@ -19,39 +19,14 @@ use PBAR;
/// The various kinds of commands that `wasm-pack` can execute.
#[derive(Debug, StructOpt)]
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,
#[structopt(long = "debug")]
/// Build without --release.
debug: bool,
},
/// 🏗 build your npm package!
#[structopt(name = "build", alias = "init")]
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 +77,14 @@ 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,
} => {
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,
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...");

@ -1,6 +1,11 @@
//! Utility functions for commands.
use emoji;
use error::Error;
use progressbar::Step;
use std::fs;
use std::path::{Path, PathBuf};
use PBAR;
/// If an explicit path is given, then use it, otherwise assume the current
/// directory is the crate path.
@ -13,6 +18,15 @@ pub fn set_crate_path(path: Option<PathBuf>) -> PathBuf {
crate_path
}
/// Construct our `pkg` directory in the crate.
pub fn create_pkg_dir(path: &Path, step: &Step) -> Result<(), Error> {
let msg = format!("{}Creating a pkg directory...", emoji::FOLDER);
PBAR.step(step, &msg);
let pkg_dir_path = path.join("pkg");
fs::create_dir_all(pkg_dir_path)?;
Ok(())
}
/// Locates the pkg directory from a specific path
/// Returns None if unable to find the 'pkg' directory
pub fn find_pkg_directory(path: &Path) -> Option<PathBuf> {

@ -33,7 +33,7 @@ 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::Build(build_opts) => &build_opts.path,
Command::Pack { path } => path,
Command::Publish { path } => path,
Command::Login { .. } => &None,

@ -5,6 +5,7 @@ extern crate structopt;
extern crate wasm_pack;
use failure::Fail;
use std::env;
use structopt::StructOpt;
use wasm_pack::{command::run_wasm_pack, error::Error, logger, Cli};
@ -20,6 +21,11 @@ fn main() {
}
fn run() -> Result<(), Error> {
// Deprecate `init`
if let Some("init") = env::args().nth(1).as_ref().map(|arg| arg.as_str()) {
println!("wasm-pack init is deprecated, consider using wasm-pack build");
}
let args = Cli::from_args();
let log = logger::new(&args.cmd, args.verbosity)?;
run_wasm_pack(args.cmd, &log)?;

@ -55,7 +55,7 @@ fn it_recognizes_a_map_during_depcheck() {
fn it_creates_a_package_json_default_path() {
let fixture = fixture::fixture(".");
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::init::create_pkg_dir(&fixture.path, &step).unwrap();
wasm_pack::command::utils::create_pkg_dir(&fixture.path, &step).unwrap();
assert!(manifest::write_package_json(&fixture.path, &None, false, "", &step).is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
assert!(fs::metadata(package_json_path).is_ok());
@ -83,7 +83,7 @@ fn it_creates_a_package_json_default_path() {
fn it_creates_a_package_json_provided_path() {
let fixture = fixture::fixture("tests/fixtures/js-hello-world");
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::init::create_pkg_dir(&fixture.path, &step).unwrap();
wasm_pack::command::utils::create_pkg_dir(&fixture.path, &step).unwrap();
assert!(manifest::write_package_json(&fixture.path, &None, false, "", &step).is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
assert!(fs::metadata(package_json_path).is_ok());
@ -104,7 +104,7 @@ fn it_creates_a_package_json_provided_path() {
fn it_creates_a_package_json_provided_path_with_scope() {
let fixture = fixture::fixture("tests/fixtures/scopes");
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::init::create_pkg_dir(&fixture.path, &step).unwrap();
wasm_pack::command::utils::create_pkg_dir(&fixture.path, &step).unwrap();
assert!(
manifest::write_package_json(&fixture.path, &Some("test".to_string()), false, "", &step)
.is_ok()
@ -128,7 +128,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::fixture(".");
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::init::create_pkg_dir(&fixture.path, &step).unwrap();
wasm_pack::command::utils::create_pkg_dir(&fixture.path, &step).unwrap();
assert!(manifest::write_package_json(&fixture.path, &None, false, "nodejs", &step).is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
assert!(fs::metadata(package_json_path).is_ok());
@ -157,7 +157,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() {
fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
let fixture = fixture::fixture(".");
let step = wasm_pack::progressbar::Step::new(1);
wasm_pack::command::init::create_pkg_dir(&fixture.path, &step).unwrap();
wasm_pack::command::utils::create_pkg_dir(&fixture.path, &step).unwrap();
assert!(manifest::write_package_json(&fixture.path, &None, true, "", &step).is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
assert!(fs::metadata(package_json_path).is_ok());

Loading…
Cancel
Save