From 3be99f4e8e19a4213a3620dcf6f9840ca2d7bf78 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Tue, 8 Mar 2022 11:50:36 +0100 Subject: [PATCH] Split up building and bunding for parallel builds This helps a lot when using the -p option to bundle multiple packages. --- nih_plug_xtask/src/lib.rs | 49 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/nih_plug_xtask/src/lib.rs b/nih_plug_xtask/src/lib.rs index 37a9aa63..429f1453 100644 --- a/nih_plug_xtask/src/lib.rs +++ b/nih_plug_xtask/src/lib.rs @@ -63,8 +63,10 @@ pub fn main_with_args(command_name: &str, mut args: impl Iterator .context(format!("Missing command name\n\n{usage_string}",))?; match command.as_str() { "bundle" => { - // For convenience's sake we'll allow building multiple packages with -p just like carg - // obuild, but you can also build a single package without specifying -p + // For convenience's sake we'll allow building multiple packages with `-p` just like + // carg obuild, but you can also build a single package without specifying `-p`. Since + // multiple packages can be built in parallel if we pass all of these flags to a single + // `cargo build` we'll first build all of these packages and only then bundle them. let mut args = args.peekable(); let mut packages = Vec::new(); if args.peek().map(|s| s.as_str()) == Some("-p") { @@ -82,9 +84,11 @@ pub fn main_with_args(command_name: &str, mut args: impl Iterator }; let other_args: Vec<_> = args.collect(); + // As explained above, for efficiency's sake this is a two step process + build(&packages, &other_args)?; + bundle(&packages[0], &other_args)?; for package in packages.into_iter().skip(1) { - eprintln!(); bundle(&package, &other_args)?; } @@ -105,8 +109,32 @@ pub fn chdir_workspace_root() -> Result<()> { std::env::set_current_dir(project_root).context("Could not change to project root directory") } -/// Bundle a package using the provided `cargo build` arguments. Options from the `bundler.toml` -/// file in the workspace's root are respected (see +/// Build one or more packages using the provided `cargo build` arguments. This should be caleld +/// before callingq [`bundle()`]. This requires the current working directory to have been set to +/// the workspace's root using [`chdir_workspace_root()`]. +pub fn build(packages: &[String], args: &[String]) -> Result<()> { + let package_args = packages.iter().flat_map(|package| ["-p", package]); + + let status = Command::new("cargo") + .arg("build") + .args(package_args) + .args(args) + .status() + .context(format!( + "Could not call cargo to build {}", + packages.join(", ") + ))?; + if !status.success() { + bail!("Could not build {}", packages.join(", ")); + } else { + Ok(()) + } +} + +/// Bundle a package that was previoulsly built by a call to [`build()`] using the provided `cargo +/// build` arguments. These two functions are split up because building can be done in parallel by +/// Cargo itself while bundling is sequential. Options from the `bundler.toml` file in the +/// workspace's root are respected (see /// ). This requires the current /// working directory to have been set to the workspace's root using [`chdir_workspace_root()`]. pub fn bundle(package: &str, args: &[String]) -> Result<()> { @@ -140,17 +168,6 @@ pub fn bundle(package: &str, args: &[String]) -> Result<()> { } } - let status = Command::new("cargo") - .arg("build") - .arg("-p") - .arg(package) - .args(args) - .status() - .context(format!("Could not call cargo to build {package}"))?; - if !status.success() { - bail!("Could not build {}", package); - } - let compilation_target = compilation_target(cross_compile_target.as_deref())?; let lib_path = Path::new(target_base(cross_compile_target.as_deref())?) .join(if is_release_build { "release" } else { "debug" })