Skip to content

Commit

Permalink
feat(build): is-child argument
Browse files Browse the repository at this point in the history
is-child can be passed as argument to wasm-pack build for generating
packages with multiple build targets
  • Loading branch information
Tarnadas committed Oct 25, 2019
1 parent 88ca2bc commit 955b9f0
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 21 deletions.
17 changes: 17 additions & 0 deletions docs/src/commands/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ wasm-pack build examples/js-hello-world --mode no-install
| `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`. |

## Multiple build targets per package

The `build` command accepts an optional `--is-child` argument.
```
wasm-pack build examples/js-hello-world --is-child --out-name child
```

This command will extend a previously generated package, which makes it possible to have multiple build targets per package.
For example it would be feasible to have an optimized build for web and Node.

Following is an example which will use the wee_alloc feature for web, because size is more crucial whereas Node should be optimized for speed.

```
wasm-pack build examples/js-hello-world --out-dir pkg -- --features "wee_alloc"
wasm-pack build examples/js-hello-world --out-dir pkg --out-name js-hello-node --is-child
```

## Extra options

The `build` command can pass extra options straight to `cargo build` even if they are not
Expand Down
14 changes: 14 additions & 0 deletions src/command/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct Build {
pub mode: InstallMode,
pub out_dir: PathBuf,
pub out_name: Option<String>,
pub is_child: bool,
pub bindgen: Option<Download>,
pub cache: Cache,
pub extra_options: Vec<String>,
Expand Down Expand Up @@ -148,6 +149,10 @@ pub struct BuildOptions {
/// Sets the output file names. Defaults to package name.
pub out_name: Option<String>,

#[structopt(long = "is-child")]
/// Won't generate package metadata. Instead adds output to existing package given by `out-dir`.
pub is_child: bool,

#[structopt(last = true)]
/// List of extra options to pass to `cargo build`
pub extra_options: Vec<String>,
Expand All @@ -167,6 +172,7 @@ impl Default for BuildOptions {
profiling: false,
out_dir: String::new(),
out_name: None,
is_child: false,
extra_options: Vec::new(),
}
}
Expand Down Expand Up @@ -201,6 +207,7 @@ impl Build {
mode: build_opts.mode,
out_dir,
out_name: build_opts.out_name,
is_child: build_opts.is_child,
bindgen: None,
cache: cache::get_wasm_pack_cache()?,
extra_options: build_opts.extra_options,
Expand Down Expand Up @@ -324,6 +331,7 @@ impl Build {
&self.scope,
self.disable_dts,
self.target,
self.is_child,
)?;
info!(
"Wrote a package.json at {:#?}.",
Expand All @@ -333,13 +341,19 @@ impl Build {
}

fn step_copy_readme(&mut self) -> Result<(), Error> {
if self.is_child {
return Ok(());
}
info!("Copying readme from crate...");
readme::copy_from_crate(&self.crate_path, &self.out_dir)?;
info!("Copied readme from crate to {:#?}.", &self.out_dir);
Ok(())
}

fn step_copy_license(&mut self) -> Result<(), failure::Error> {
if self.is_child {
return Ok(());
}
info!("Copying license from crate...");
license::copy_from_crate(&self.crate_data, &self.crate_path, &self.out_dir)?;
info!("Copied license from crate to {:#?}.", &self.out_dir);
Expand Down
40 changes: 35 additions & 5 deletions src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,13 +560,43 @@ impl CrateData {
scope: &Option<String>,
disable_dts: bool,
target: Target,
is_child: bool,
) -> Result<(), Error> {
let pkg_file_path = out_dir.join("package.json");
let npm_data = match target {
Target::Nodejs => self.to_commonjs(scope, disable_dts, out_dir),
Target::NoModules => self.to_nomodules(scope, disable_dts, out_dir),
Target::Bundler => self.to_esmodules(scope, disable_dts, out_dir),
Target::Web => self.to_web(scope, disable_dts, out_dir),
let npm_data = if is_child {
let npm_json = match fs::read_to_string(&pkg_file_path) {
Ok(file) => file,
Err(_) => bail!(
"--is-child was provided, but given --out-dir path does not contain a package.json. \
Please make sure, that you compile the parent directory to the same --out-dir"),
};
let mut npm_data: NpmPackage = serde_json::from_str(&npm_json)?;
let name_prefix = self.name_prefix();

let wasm_file = format!("{}_bg.wasm", name_prefix);
npm_data.add_file(wasm_file);

let js_file = format!("{}.js", name_prefix);
npm_data.add_file(js_file);

if let Target::Nodejs = target {
let js_bg_file = format!("{}_bg.js", name_prefix);
npm_data.add_file(js_bg_file);
}

if !disable_dts {
let dts_file = format!("{}.d.ts", name_prefix);
npm_data.add_file(dts_file);
}

npm_data
} else {
match target {
Target::Nodejs => self.to_commonjs(scope, disable_dts, out_dir),
Target::NoModules => self.to_nomodules(scope, disable_dts, out_dir),
Target::Bundler => self.to_esmodules(scope, disable_dts, out_dir),
Target::Web => self.to_web(scope, disable_dts, out_dir),
}
};

let npm_json = serde_json::to_string_pretty(&npm_data)?;
Expand Down
2 changes: 1 addition & 1 deletion src/manifest/npm/commonjs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use manifest::npm::repository::Repository;

#[derive(Serialize)]
#[derive(Deserialize, Serialize)]
pub struct CommonJSPackage {
pub name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
Expand Down
2 changes: 1 addition & 1 deletion src/manifest/npm/esmodules.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use manifest::npm::repository::Repository;

#[derive(Serialize)]
#[derive(Deserialize, Serialize)]
pub struct ESModulesPackage {
pub name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
Expand Down
12 changes: 11 additions & 1 deletion src/manifest/npm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,20 @@ pub use self::commonjs::CommonJSPackage;
pub use self::esmodules::ESModulesPackage;
pub use self::nomodules::NoModulesPackage;

#[derive(Serialize)]
#[derive(Deserialize, Serialize)]
#[serde(untagged)]
pub enum NpmPackage {
CommonJSPackage(CommonJSPackage),
ESModulesPackage(ESModulesPackage),
NoModulesPackage(NoModulesPackage),
}

impl NpmPackage {
pub fn add_file(&mut self, file: String) {
match self {
Self::CommonJSPackage(pkg) => pkg.files.push(file),
Self::ESModulesPackage(pkg) => pkg.files.push(file),
Self::NoModulesPackage(pkg) => pkg.files.push(file),
}
}
}
2 changes: 1 addition & 1 deletion src/manifest/npm/nomodules.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use manifest::npm::repository::Repository;

#[derive(Serialize)]
#[derive(Deserialize, Serialize)]
pub struct NoModulesPackage {
pub name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
Expand Down
2 changes: 1 addition & 1 deletion src/manifest/npm/repository.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[derive(Serialize)]
#[derive(Deserialize, Serialize)]
pub struct Repository {
#[serde(rename = "type")]
pub ty: String,
Expand Down
88 changes: 77 additions & 11 deletions tests/all/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ fn it_creates_a_package_json_default_path() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Bundler)
.write_package_json(&out_dir, &None, false, Target::Bundler, false)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
Expand Down Expand Up @@ -114,7 +114,7 @@ fn it_creates_a_package_json_provided_path() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Bundler)
.write_package_json(&out_dir, &None, false, Target::Bundler, false)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
Expand Down Expand Up @@ -142,7 +142,13 @@ fn it_creates_a_package_json_provided_path_with_scope() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &Some("test".to_string()), false, Target::Bundler,)
.write_package_json(
&out_dir,
&Some("test".to_string()),
false,
Target::Bundler,
false
)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
Expand Down Expand Up @@ -170,7 +176,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Nodejs)
.write_package_json(&out_dir, &None, false, Target::Nodejs, false)
.is_ok());
let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap();
Expand Down Expand Up @@ -205,7 +211,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_nomodules() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::NoModules)
.write_package_json(&out_dir, &None, false, Target::NoModules, false)
.is_ok());
let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap();
Expand Down Expand Up @@ -239,7 +245,7 @@ fn it_creates_a_package_json_with_correct_files_when_out_name_is_provided() {
let crate_data = manifest::CrateData::new(&fixture.path, Some("index".to_owned())).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Bundler)
.write_package_json(&out_dir, &None, false, Target::Bundler, false)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
Expand Down Expand Up @@ -270,7 +276,7 @@ fn it_creates_a_pkg_json_in_out_dir() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Bundler)
.write_package_json(&out_dir, &None, false, Target::Bundler, false)
.is_ok());

let package_json_path = &fixture.path.join(&out_dir).join("package.json");
Expand All @@ -285,7 +291,7 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, true, Target::Bundler)
.write_package_json(&out_dir, &None, true, Target::Bundler, false)
.is_ok());
let package_json_path = &out_dir.join("package.json");
fs::metadata(package_json_path).unwrap();
Expand All @@ -307,13 +313,73 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
assert_eq!(actual_files, expected_files);
}

#[test]
fn it_creates_a_package_json_with_correct_files_when_is_child_is_provided() {
let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg");
let crate_data = manifest::CrateData::new(&fixture.path, Some("index".to_owned())).unwrap();
let crate_data_child =
manifest::CrateData::new(&fixture.path, Some("child".to_owned())).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Web, false)
.is_ok());
assert!(crate_data_child
.write_package_json(&out_dir, &None, false, Target::Web, true)
.is_ok());
let package_json_path = &fixture.path.join("pkg").join("package.json");
fs::metadata(package_json_path).unwrap();
utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
assert_eq!(pkg.name, "js-hello-world");
assert_eq!(pkg.repository.ty, "git");
assert_eq!(
pkg.repository.url,
"https://github.com/rustwasm/wasm-pack.git"
);
assert_eq!(pkg.module, "index.js");
assert_eq!(pkg.types, "index.d.ts");
assert_eq!(pkg.side_effects, false);

let actual_files: HashSet<String> = pkg.files.into_iter().collect();
let expected_files: HashSet<String> = [
"index_bg.wasm",
"index.d.ts",
"index.js",
"child_bg.wasm",
"child.d.ts",
"child.js",
]
.iter()
.map(|&s| String::from(s))
.collect();
assert_eq!(actual_files, expected_files);
}

#[test]
fn it_errors_when_wasm_bindgen_is_not_declared() {
let fixture = fixture::bad_cargo_toml();
let crate_data = manifest::CrateData::new(&fixture.path, None).unwrap();
assert!(crate_data.check_crate_config().is_err());
}

#[test]
fn it_errors_when_out_dir_of_child_does_not_exist() {
let fixture = fixture::js_hello_world();
let out_dir = fixture.path.join("pkg");
let out_dir_child = fixture.path.join("pkg-child");
let crate_data = manifest::CrateData::new(&fixture.path, Some("index".to_owned())).unwrap();
let crate_data_child =
manifest::CrateData::new(&fixture.path, Some("child".to_owned())).unwrap();
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
assert!(crate_data
.write_package_json(&out_dir, &None, false, Target::Web, false)
.is_ok());
assert!(crate_data_child
.write_package_json(&out_dir_child, &None, false, Target::Web, true)
.is_err());
}

#[test]
fn it_sets_homepage_field_if_available_in_cargo_toml() {
// When 'homepage' is available
Expand Down Expand Up @@ -346,7 +412,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() {

wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
crate_data
.write_package_json(&out_dir, &None, true, Target::Bundler)
.write_package_json(&out_dir, &None, true, Target::Bundler, false)
.unwrap();

let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
Expand All @@ -362,7 +428,7 @@ fn it_sets_homepage_field_if_available_in_cargo_toml() {

wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
crate_data
.write_package_json(&out_dir, &None, true, Target::Bundler)
.write_package_json(&out_dir, &None, true, Target::Bundler, false)
.unwrap();

let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
Expand Down Expand Up @@ -463,7 +529,7 @@ fn it_lists_license_files_in_files_field_of_package_json() {
wasm_pack::command::utils::create_pkg_dir(&out_dir).unwrap();
license::copy_from_crate(&crate_data, &fixture.path, &out_dir).unwrap();
crate_data
.write_package_json(&out_dir, &None, false, Target::Bundler)
.write_package_json(&out_dir, &None, false, Target::Bundler, false)
.unwrap();

let package_json_path = &fixture.path.join("pkg").join("package.json");
Expand Down

0 comments on commit 955b9f0

Please sign in to comment.