Bundle standalone binaries in xtask bundle
This commit is contained in:
parent
96ec1da037
commit
7c121d0181
|
@ -138,18 +138,17 @@ pub fn build(packages: &[String], args: &[String]) -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bundle a package that was previoulsly built by a call to [`build()`] using the provided `cargo
|
/// Bundle a package that was previously 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
|
/// 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
|
/// Cargo itself while bundling is sequential. Options from the `bundler.toml` file in the
|
||||||
/// workspace's root are respected (see
|
/// workspace's root are respected (see
|
||||||
/// <https://github.com/robbert-vdh/nih-plug/blob/master/bundler.toml>). This requires the current
|
/// <https://github.com/robbert-vdh/nih-plug/blob/master/bundler.toml>). This requires the current
|
||||||
/// working directory to have been set to the workspace's root using [`chdir_workspace_root()`].
|
/// working directory to have been set to the workspace's root using [`chdir_workspace_root()`].
|
||||||
|
///
|
||||||
|
/// If the package also exposes a binary target in addition to a library (or just a binary, in case
|
||||||
|
/// the binary target has a different name) then this will also be copied into the `bundled`
|
||||||
|
/// directory.
|
||||||
pub fn bundle(package: &str, args: &[String]) -> Result<()> {
|
pub fn bundle(package: &str, args: &[String]) -> Result<()> {
|
||||||
let bundle_name = match load_bundler_config()?.and_then(|c| c.get(package).cloned()) {
|
|
||||||
Some(PackageConfig { name: Some(name) }) => name,
|
|
||||||
_ => package.to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut is_release_build = false;
|
let mut is_release_build = false;
|
||||||
let mut cross_compile_target: Option<String> = None;
|
let mut cross_compile_target: Option<String> = None;
|
||||||
for arg_idx in (0..args.len()).rev() {
|
for arg_idx in (0..args.len()).rev() {
|
||||||
|
@ -175,16 +174,79 @@ pub fn bundle(package: &str, args: &[String]) -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add support for binary targets. This would simply copy/reflink the binary to the
|
// We can bundle both library targets (for plugins) and binary targets (for standalone
|
||||||
// `bundled` directory to make it easier to ship all versions of a plugin.
|
// applications)
|
||||||
let compilation_target = compilation_target(cross_compile_target.as_deref())?;
|
let compilation_target = compilation_target(cross_compile_target.as_deref())?;
|
||||||
let lib_path = target_base(cross_compile_target.as_deref())?
|
let target_base = target_base(cross_compile_target.as_deref())?.join(if is_release_build {
|
||||||
.join(if is_release_build { "release" } else { "debug" })
|
"release"
|
||||||
.join(library_basename(package, compilation_target));
|
} else {
|
||||||
if !lib_path.exists() {
|
"debug"
|
||||||
|
});
|
||||||
|
let bin_path = target_base.join(binary_basename(package, compilation_target));
|
||||||
|
let lib_path = target_base.join(library_basename(package, compilation_target));
|
||||||
|
if !bin_path.exists() && !lib_path.exists() {
|
||||||
bail!("Could not find built library at '{}'", lib_path.display());
|
bail!("Could not find built library at '{}'", lib_path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eprintln!();
|
||||||
|
if bin_path.exists() {
|
||||||
|
bundle_binary(package, &bin_path, compilation_target)?;
|
||||||
|
}
|
||||||
|
if lib_path.exists() {
|
||||||
|
bundle_plugin(package, &lib_path, compilation_target)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bundle a standalone target.
|
||||||
|
fn bundle_binary(
|
||||||
|
package: &str,
|
||||||
|
bin_path: &Path,
|
||||||
|
compilation_target: CompilationTarget,
|
||||||
|
) -> Result<()> {
|
||||||
|
let bundle_name = match load_bundler_config()?.and_then(|c| c.get(package).cloned()) {
|
||||||
|
Some(PackageConfig { name: Some(name) }) => name,
|
||||||
|
_ => package.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// On MacOS the standalone target needs to be in a bundle
|
||||||
|
let standalone_bundle_binary_name =
|
||||||
|
standalone_bundle_binary_name(&bundle_name, compilation_target);
|
||||||
|
let standalone_binary_path = Path::new(BUNDLE_HOME).join(&standalone_bundle_binary_name);
|
||||||
|
|
||||||
|
fs::create_dir_all(standalone_binary_path.parent().unwrap())
|
||||||
|
.context("Could not create standalone bundle directory")?;
|
||||||
|
reflink::reflink_or_copy(&bin_path, &standalone_binary_path)
|
||||||
|
.context("Could not copy binary to standalone bundle")?;
|
||||||
|
|
||||||
|
let standalone_bundle_home = Path::new(BUNDLE_HOME).join(
|
||||||
|
Path::new(&standalone_bundle_binary_name)
|
||||||
|
.components()
|
||||||
|
.next()
|
||||||
|
.expect("Malformed standalone binary path"),
|
||||||
|
);
|
||||||
|
maybe_create_macos_bundle_metadata(package, &standalone_bundle_home, compilation_target)?;
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Created a standalone bundle at '{}'",
|
||||||
|
standalone_bundle_home.display()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bundle all plugin targets for a plugin library.
|
||||||
|
fn bundle_plugin(
|
||||||
|
package: &str,
|
||||||
|
lib_path: &Path,
|
||||||
|
compilation_target: CompilationTarget,
|
||||||
|
) -> Result<()> {
|
||||||
|
let bundle_name = match load_bundler_config()?.and_then(|c| c.get(package).cloned()) {
|
||||||
|
Some(PackageConfig { name: Some(name) }) => name,
|
||||||
|
_ => package.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
// We'll detect the pugin formats supported by the plugin binary and create bundled accordingly
|
// We'll detect the pugin formats supported by the plugin binary and create bundled accordingly
|
||||||
// NOTE: NIH-plug does not support VST2, but we'll support bundling VST2 plugins anyways because
|
// NOTE: NIH-plug does not support VST2, but we'll support bundling VST2 plugins anyways because
|
||||||
// this bundler can also be used standalone.
|
// this bundler can also be used standalone.
|
||||||
|
@ -197,8 +259,6 @@ pub fn bundle(package: &str, args: &[String]) -> Result<()> {
|
||||||
let bundle_vst3 = symbols::exported(&lib_path, "GetPluginFactory")
|
let bundle_vst3 = symbols::exported(&lib_path, "GetPluginFactory")
|
||||||
.with_context(|| format!("Could not parse '{}'", lib_path.display()))?;
|
.with_context(|| format!("Could not parse '{}'", lib_path.display()))?;
|
||||||
let bundled_plugin = bundle_clap || bundle_vst2 || bundle_vst3;
|
let bundled_plugin = bundle_clap || bundle_vst2 || bundle_vst3;
|
||||||
|
|
||||||
eprintln!();
|
|
||||||
if bundle_clap {
|
if bundle_clap {
|
||||||
let clap_bundle_library_name = clap_bundle_library_name(&bundle_name, compilation_target);
|
let clap_bundle_library_name = clap_bundle_library_name(&bundle_name, compilation_target);
|
||||||
let clap_lib_path = Path::new(BUNDLE_HOME).join(&clap_bundle_library_name);
|
let clap_lib_path = Path::new(BUNDLE_HOME).join(&clap_bundle_library_name);
|
||||||
|
@ -346,6 +406,17 @@ fn target_base(cross_compile_target: Option<&str>) -> Result<PathBuf> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The file name of the compiled library for a binary crate.
|
||||||
|
fn binary_basename(package: &str, target: CompilationTarget) -> String {
|
||||||
|
// Cargo will replace dashes with underscores
|
||||||
|
let bin_name = package.replace('-', "_");
|
||||||
|
|
||||||
|
match target {
|
||||||
|
CompilationTarget::Linux(_) | CompilationTarget::MacOS(_) => bin_name,
|
||||||
|
CompilationTarget::Windows(_) => format!("{bin_name}.exe"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The file name of the compiled library for a `cdylib` crate.
|
/// The file name of the compiled library for a `cdylib` crate.
|
||||||
fn library_basename(package: &str, target: CompilationTarget) -> String {
|
fn library_basename(package: &str, target: CompilationTarget) -> String {
|
||||||
// Cargo will replace dashes with underscores
|
// Cargo will replace dashes with underscores
|
||||||
|
@ -358,8 +429,17 @@ fn library_basename(package: &str, target: CompilationTarget) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The filename of the binary target. On macOS this is part of a bundle.
|
||||||
|
fn standalone_bundle_binary_name(package: &str, target: CompilationTarget) -> String {
|
||||||
|
match target {
|
||||||
|
CompilationTarget::Linux(_) => package.to_owned(),
|
||||||
|
CompilationTarget::MacOS(_) => format!("{package}.app/Contents/MacOS/{package}"),
|
||||||
|
CompilationTarget::Windows(_) => format!("{package}.exe"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The filename of the CLAP plugin for Linux and Windows, or the full path to the library file
|
/// The filename of the CLAP plugin for Linux and Windows, or the full path to the library file
|
||||||
/// inside of a CLAP bundle on macOS
|
/// inside of a CLAP bundle on macOS.
|
||||||
fn clap_bundle_library_name(package: &str, target: CompilationTarget) -> String {
|
fn clap_bundle_library_name(package: &str, target: CompilationTarget) -> String {
|
||||||
match target {
|
match target {
|
||||||
CompilationTarget::Linux(_) | CompilationTarget::Windows(_) => format!("{package}.clap"),
|
CompilationTarget::Linux(_) | CompilationTarget::Windows(_) => format!("{package}.clap"),
|
||||||
|
@ -418,6 +498,8 @@ pub fn maybe_create_macos_bundle_metadata(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Use the display name from bundler.toml
|
||||||
|
|
||||||
// TODO: May want to add bundler.toml fields for the identifier, version and signature at some
|
// TODO: May want to add bundler.toml fields for the identifier, version and signature at some
|
||||||
// point.
|
// point.
|
||||||
fs::write(bundle_home.join("Contents").join("PkgInfo"), "BNDL????")
|
fs::write(bundle_home.join("Contents").join("PkgInfo"), "BNDL????")
|
||||||
|
|
Loading…
Reference in a new issue