From a83cbf8acabb5aaf6baaec69f5e5d608c94bc600 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Thu, 10 Feb 2022 20:44:47 +0100 Subject: [PATCH] Support cross compiling in xtask bundle --- xtask/src/main.rs | 146 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 101 insertions(+), 45 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 75be0ce6..6dec0ad8 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -3,7 +3,8 @@ use std::fs; use std::path::Path; use std::process::Command; -const USAGE_STRING: &str = "Usage: cargo xtask bundle [--release] [--bundle-vst3]"; +const USAGE_STRING: &str = + "Usage: cargo xtask bundle [--release] [--target ] [--bundle-vst3]"; fn main() -> Result<()> { let project_root = Path::new(env!("CARGO_MANIFEST_DIR")) @@ -18,21 +19,22 @@ fn main() -> Result<()> { .context(format!("Missing command name\n\n{USAGE_STRING}"))?; match command.as_str() { "bundle" => { - let target = args + let package = args .next() - .context(format!("Missing target name\n\n{USAGE_STRING}"))?; + .context(format!("Missing package name\n\n{USAGE_STRING}"))?; let other_args: Vec<_> = args.collect(); - bundle(&target, other_args) + bundle(&package, other_args) } _ => bail!("Unknown command '{command}'\n\n{USAGE_STRING}"), } } // TODO: This probably needs more work for macOS. I don't know, I don't have a Mac. -fn bundle(target: &str, mut args: Vec) -> Result<()> { +fn bundle(package: &str, mut args: Vec) -> Result<()> { let mut is_release_build = false; let mut bundle_vst3 = false; + let mut cross_compile_target: Option = None; for arg_idx in (0..args.len()).rev() { let arg = &args[arg_idx]; match arg.as_str() { @@ -41,6 +43,21 @@ fn bundle(target: &str, mut args: Vec) -> Result<()> { args.remove(arg_idx); } "--release" => is_release_build = true, + "--target" => { + // When cross compiling we should generate the correct bundle type + cross_compile_target = Some( + args.get(arg_idx + 1) + .context("Missing cross-compile target")? + .to_owned(), + ); + } + arg if arg.starts_with("--target=") => { + cross_compile_target = Some( + arg.strip_prefix("--target=") + .context("Missing cross-compile target")? + .to_owned(), + ); + } _ => (), } } @@ -48,24 +65,27 @@ fn bundle(target: &str, mut args: Vec) -> Result<()> { let status = Command::new("cargo") .arg("build") .arg("-p") - .arg(target) + .arg(package) .args(args) .status() - .context(format!("Could not call cargo to build {target}"))?; + .context(format!("Could not call cargo to build {package}"))?; if !status.success() { - bail!("Could not build {}", target); + bail!("Could not build {}", package); } - let lib_path = Path::new("target") + let lib_path = Path::new(target_base(cross_compile_target.as_deref())?) .join(if is_release_build { "release" } else { "debug" }) - .join(library_name(target)); + .join(library_basename(package, cross_compile_target.as_deref())?); if !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 bundle_vst3 { - let vst3_lib_path = Path::new("target").join(vst3_bundle_library_name(target)); + let vst3_lib_path = Path::new("target").join(vst3_bundle_library_name( + package, + cross_compile_target.as_deref(), + )?); let vst3_bundle_home = vst3_lib_path .parent() .unwrap() @@ -86,45 +106,81 @@ fn bundle(target: &str, mut args: Vec) -> Result<()> { Ok(()) } -#[cfg(target_os = "linux")] -fn library_name(target: &str) -> String { - format!("lib{target}.so") +fn target_base(cross_compile_target: Option<&str>) -> Result<&'static str> { + match cross_compile_target { + Some("x86_64-unknown-linux-gnu") => Ok("target/x86_64-unknown-linux-gnu"), + Some("x86_64-pc-windows-gnu") => Ok("target/x86_64-pc-windows-gnu"), + Some("x86_64-apple-darwin") => Ok("target/x86_64-apple-darwin"), + Some(target) => bail!("Unhandled cross-compilation target: {}", target), + None => Ok("target"), + } } -#[cfg(target_os = "macos")] -fn library_name(target: &str) -> String { - format!("lib{target}.dylib") -} +fn library_basename(package: &str, cross_compile_target: Option<&str>) -> Result { + fn library_basename_linux(package: &str) -> String { + format!("lib{package}.so") + } + fn library_basename_macos(package: &str) -> String { + format!("lib{package}.dylib") + } + fn library_basename_windows(package: &str) -> String { + format!("{package}.dll") + } -#[cfg(target_os = "windows")] -fn library_name(target: &str) -> String { - format!("{target}.dll") + match cross_compile_target { + Some("x86_64-unknown-linux-gnu") => Ok(library_basename_linux(package)), + Some("x86_64-apple-darwin") => Ok(library_basename_macos(package)), + Some("x86_64-pc-windows-gnu") => Ok(library_basename_windows(package)), + Some(target) => bail!("Unhandled cross-compilation target: {}", target), + None => { + #[cfg(target_os = "linux")] + return Ok(library_basename_linux(package)); + #[cfg(target_os = "macos")] + return Ok(library_basename_macos(package)); + #[cfg(target_os = "windows")] + return Ok(library_basename_windows(package)); + } + } } // See https://developer.steinberg.help/display/VST/Plug-in+Format+Structure -#[cfg(all(target_os = "linux", target_arch = "x86_64"))] -fn vst3_bundle_library_name(target: &str) -> String { - format!("{target}.vst3/Contents/x86_64-linux/{target}.so") -} +fn vst3_bundle_library_name(package: &str, cross_compile_target: Option<&str>) -> Result { + fn vst3_bundle_library_name_linux_x86_64(package: &str) -> String { + format!("{package}.vst3/Contents/x86_64-linux/{package}.so") + } + #[allow(dead_code)] + fn vst3_bundle_library_name_linux_x86(package: &str) -> String { + format!("{package}.vst3/Contents/i386-linux/{package}.so") + } + // TODO: This should be a Mach-O bundle, not sure how that works + fn vst3_bundle_library_name_macos(package: &str) -> String { + format!("{package}.vst3/Contents/MacOS/{package}") + } + fn vst3_bundle_library_name_windows_x86_64(package: &str) -> String { + format!("{package}.vst3/Contents/x86_64-win/{package}.vst3") + } + #[allow(dead_code)] + fn vst3_bundle_library_name_windows_x86(package: &str) -> String { + format!("{package}.vst3/Contents/x86-win/{package}.vst3") + } -#[cfg(all(target_os = "linux", target_arch = "x86"))] -fn vst3_bundle_library_name(target: &str) -> String { - format!("{target}.vst3/Contents/i386-linux/{target}.so") -} - -// TODO: This should be a Mach-O bundle, not sure how that works -#[cfg(target_os = "macos")] -fn vst3_bundle_library_name(target: &str) -> String { - format!("{target}.vst3/Contents/MacOS/{target}") -} - -#[cfg(all(target_os = "windows", target_arch = "x86_64"))] -fn vst3_bundle_library_name(target: &str) -> String { - format!("{target}.vst3/Contents/x86_64-win/{target}.vst3") -} - -#[cfg(all(target_os = "windows", target_arch = "x86"))] -fn vst3_bundle_library_name(target: &str) -> String { - format!("{target}.vst3/Contents/x86-win/{target}.vst3") + match cross_compile_target { + Some("x86_64-unknown-linux-gnu") => Ok(vst3_bundle_library_name_linux_x86_64(package)), + Some("x86_64-apple-darwin") => Ok(vst3_bundle_library_name_macos(package)), + Some("x86_64-pc-windows-gnu") => Ok(vst3_bundle_library_name_windows_x86_64(package)), + Some(target) => bail!("Unhandled cross-compilation target: {}", target), + None => { + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] + return Ok(vst3_bundle_library_name_linux_x86_64(package)); + #[cfg(all(target_os = "linux", target_arch = "x86"))] + return Ok(vst3_bundle_library_name_linux_x86(package)); + #[cfg(target_os = "macos")] + return Ok(vst3_bundle_library_name_macos(package)); + #[cfg(all(target_os = "windows", target_arch = "x86_64"))] + return Ok(vst3_bundle_library_name_windows_x86_64(package)); + #[cfg(all(target_os = "windows", target_arch = "x86"))] + return Ok(vst3_bundle_library_name_windows_x86(package)); + } + } }