use std::env;
use std::path::PathBuf;
use std::process::Command;
fn main() {
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let is_desktop = matches!(target_os.as_str(), "macos" | "linux" | "windows");
let current_dir = env::current_dir().unwrap();
let in_publish_verify = current_dir
.to_str()
.map(|s| s.contains("/target/package/"))
.unwrap_or(false);
let vst3_sdk_path = if is_desktop && !in_publish_verify {
ensure_vst3_sdk()
} else {
if in_publish_verify {
eprintln!("Skipping VST3 SDK auto-clone for cargo publish (VST3 support disabled)");
} else {
eprintln!("Skipping VST3 SDK setup for {} (VST3 only supported on desktop platforms)", target_os);
}
None
};
let enable_asan = env::var("CARGO_FEATURE_ASAN").is_ok() || env::var("ENABLE_ASAN").is_ok();
let mut config = cmake::Config::new("rack-sys");
config
.define("CMAKE_BUILD_TYPE", "Release")
.define("BUILD_TESTS", "OFF");
if let Some(sdk_path) = vst3_sdk_path {
config.define("VST3_SDK_PATH", sdk_path.to_str().unwrap());
eprintln!("Configuring CMake with VST3 SDK at: {}", sdk_path.display());
}
if enable_asan {
config.define("ENABLE_ASAN", "ON");
eprintln!("Building with AddressSanitizer enabled");
}
let dst = config.build();
let lib_name = "rack_sys";
println!("cargo:rustc-link-search=native={}/lib", dst.display());
println!("cargo:rustc-link-lib=static={}", lib_name);
match target_os.as_str() {
"macos" | "ios" | "tvos" | "watchos" => {
link_apple_frameworks(&target_os);
println!("cargo:rustc-link-lib=c++");
}
"linux" => {
println!("cargo:rustc-link-lib=stdc++");
println!("cargo:rustc-link-lib=dl");
}
"windows" => {
}
_ => {
eprintln!("Warning: Unsupported target OS: {}", target_os);
}
}
if enable_asan {
println!("cargo:rustc-link-arg=-fsanitize=address");
println!("cargo:rustc-link-arg=-fno-optimize-sibling-calls");
println!("cargo:rustc-link-arg=-fsanitize-address-use-after-scope");
println!("cargo:rustc-link-arg=-fno-omit-frame-pointer");
}
println!("cargo:rerun-if-changed=rack-sys/src");
println!("cargo:rerun-if-changed=rack-sys/include");
println!("cargo:rerun-if-changed=rack-sys/CMakeLists.txt");
println!("cargo:rerun-if-changed=rack-sys/external/vst3sdk");
eprintln!(
"Building rack-sys for target: {} ({})",
env::var("TARGET").unwrap(),
target_os
);
}
fn link_apple_frameworks(target_os: &str) {
println!("cargo:rustc-link-lib=framework=AudioToolbox");
println!("cargo:rustc-link-lib=framework=CoreAudio");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=CoreAudioKit");
let is_ios_family = target_os == "ios" || target_os.contains("vision");
if is_ios_family {
println!("cargo:rustc-link-lib=framework=UIKit");
eprintln!("Building rack-sys for iOS/visionOS (GUI provided by app extensions)");
} else {
println!("cargo:rustc-link-lib=framework=AppKit");
eprintln!("Building rack-sys for macOS (GUI enabled)");
}
}
fn ensure_vst3_sdk() -> Option<PathBuf> {
let vst3_sdk_path = PathBuf::from("rack-sys/external/vst3sdk");
let sdk_exists = vst3_sdk_path.exists()
&& vst3_sdk_path.join("CMakeLists.txt").exists()
&& vst3_sdk_path.join("pluginterfaces").exists();
if sdk_exists {
eprintln!("VST3 SDK found at {}", vst3_sdk_path.display());
return Some(vst3_sdk_path);
}
eprintln!("VST3 SDK not found in source tree, attempting to clone...");
let current_dir = env::current_dir().unwrap();
let in_cargo_registry = current_dir
.to_str()
.map(|s| s.contains("/.cargo/registry/"))
.unwrap_or(false);
let clone_target = if in_cargo_registry {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let sdk_path = out_dir.join("vst3sdk");
eprintln!("Building from crates.io - will clone VST3 SDK to OUT_DIR: {}", sdk_path.display());
sdk_path
} else {
vst3_sdk_path.clone()
};
if clone_target.exists() && clone_target.join("CMakeLists.txt").exists() {
eprintln!("VST3 SDK already exists at {}", clone_target.display());
return Some(clone_target);
}
if !in_cargo_registry {
let submodule_init = Command::new("git")
.args(&["submodule", "update", "--init", "--recursive", "rack-sys/external/vst3sdk"])
.current_dir(¤t_dir)
.output();
if let Ok(output) = submodule_init {
if output.status.success() && vst3_sdk_path.join("CMakeLists.txt").exists() {
eprintln!("VST3 SDK initialized via git submodule");
return Some(vst3_sdk_path);
}
}
}
eprintln!("Cloning VST3 SDK to {}...", clone_target.display());
if let Some(parent) = clone_target.parent() {
std::fs::create_dir_all(parent).ok();
}
let clone_result = Command::new("git")
.args(&[
"clone",
"--recursive",
"--depth=1", "https://github.com/steinbergmedia/vst3sdk.git",
clone_target.to_str().unwrap(),
])
.status();
match clone_result {
Ok(status) if status.success() => {
eprintln!("VST3 SDK cloned successfully to {}", clone_target.display());
Some(clone_target)
}
Ok(status) => {
eprintln!(
"Warning: Failed to clone VST3 SDK (exit code: {:?})",
status.code()
);
eprintln!("VST3 support will be disabled.");
None
}
Err(e) => {
eprintln!("Warning: Failed to execute git clone: {}", e);
eprintln!("VST3 support will be disabled.");
eprintln!("Ensure git is installed to enable VST3 support.");
None
}
}
}