use std::env;
use std::path::PathBuf;
use std::process;
fn main() {
let (include_dir, lib_dir) = resolve_usd_paths();
let lib_prefix = env::var("USD_LIB_PREFIX").unwrap_or_default();
let monolithic = env::var("USD_MONOLITHIC")
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
.unwrap_or(false);
let link_python = env::var("USD_LINK_PYTHON").unwrap_or_else(|_| "framework".to_string());
let mut usd_libs: Vec<&str> = if monolithic {
vec!["usd_ms"]
} else {
vec![
"usd", "usdGeom", "usdLux", "usdShade", "sdf", "ar", "pcp", "plug", "kind",
"vt", "gf", "tf", "work", "trace", "js", "arch", "ts",
"hd", "hf", "hdsi", "usdImaging",
"hdx", "hgi", "usdImagingGL", "glf",
]
};
if link_python != "none" && !monolithic {
usd_libs.push("python");
usd_libs.push("boost");
}
for lib in &usd_libs {
println!("cargo:rustc-link-lib=dylib={}{}", lib_prefix, lib);
}
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display());
if let Some(parent) = lib_dir.parent() {
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", parent.display());
}
match link_python.as_str() {
"framework" => {
let fw_name = env::var("USD_PYTHON_FRAMEWORK").unwrap_or_else(|_| "Python".into());
if let Ok(fw_dir) = env::var("USD_PYTHON_FRAMEWORK_DIR") {
println!("cargo:rustc-link-search=framework={}", fw_dir);
let inside_fw = PathBuf::from(&fw_dir).join(format!("{}.framework", fw_name));
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", inside_fw.display());
}
println!("cargo:rustc-link-lib=framework={}", fw_name);
}
"lib" => {
if let Ok(py_lib_dir) = env::var("USD_PYTHON_LIB_DIR") {
println!("cargo:rustc-link-search=native={}", py_lib_dir);
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", py_lib_dir);
}
let py_lib = env::var("USD_PYTHON_LIB_NAME").unwrap_or_else(|_| "python3.11".into());
println!("cargo:rustc-link-lib=dylib={}", py_lib);
}
"none" => {}
other => {
eprintln!("hydra-rs build.rs: USD_LINK_PYTHON={:?} not understood", other);
process::exit(1);
}
}
let mut build = cxx_build::bridge("src/lib.rs");
build
.file("cpp/hydra_bridge.cpp")
.include(&include_dir)
.include("cpp")
.flag_if_supported("-std=c++17")
.flag_if_supported("-Wno-deprecated-declarations");
if let Ok(py_inc) = env::var("USD_PYTHON_INCLUDE_DIR") {
build.include(py_inc);
}
build.compile("hydra_rs_bridge");
println!("cargo:rerun-if-changed=cpp/hydra_bridge.h");
println!("cargo:rerun-if-changed=cpp/hydra_bridge.cpp");
println!("cargo:rerun-if-changed=src/lib.rs");
println!("cargo:rerun-if-changed=build.rs");
for var in [
"USD_INSTALL_DIR", "USD_INCLUDE_DIR", "USD_LIB_DIR", "USD_LIB_PREFIX",
"USD_MONOLITHIC", "USD_PYTHON_INCLUDE_DIR", "USD_LINK_PYTHON",
"USD_PYTHON_FRAMEWORK_DIR", "USD_PYTHON_FRAMEWORK", "USD_PYTHON_LIB_DIR",
"USD_PYTHON_LIB_NAME", "PXR_CMAKE_PREFIX",
] {
println!("cargo:rerun-if-env-changed={}", var);
}
}
fn resolve_usd_paths() -> (PathBuf, PathBuf) {
let explicit_include = env::var("USD_INCLUDE_DIR").ok().map(PathBuf::from);
let explicit_lib = env::var("USD_LIB_DIR").ok().map(PathBuf::from);
if let (Some(inc), Some(lib)) = (explicit_include.clone(), explicit_lib.clone()) {
return validate(inc, lib);
}
let install = env::var("USD_INSTALL_DIR")
.ok()
.or_else(|| env::var("PXR_CMAKE_PREFIX").ok());
if let Some(install) = install {
let install = PathBuf::from(install);
let inc = explicit_include.unwrap_or_else(|| install.join("include"));
let lib = explicit_lib.unwrap_or_else(|| install.join("lib"));
return validate(inc, lib);
}
eprintln!(
"hydra-rs build.rs: no USD install configured.\n\
Set USD_INSTALL_DIR (with include/+lib/), or USD_INCLUDE_DIR+USD_LIB_DIR."
);
process::exit(1);
}
fn validate(include_dir: PathBuf, lib_dir: PathBuf) -> (PathBuf, PathBuf) {
if !include_dir
.join("pxr/imaging/hd/rendererPluginRegistry.h")
.exists()
{
eprintln!(
"hydra-rs build.rs: Hydra headers not found.\n\
Expected pxr/imaging/hd/rendererPluginRegistry.h under: {}",
include_dir.display()
);
process::exit(1);
}
if !lib_dir.is_dir() {
eprintln!("hydra-rs build.rs: lib dir does not exist: {}", lib_dir.display());
process::exit(1);
}
(include_dir, lib_dir)
}