rust_usd_build/lib.rs
1//! Build-script helpers for downstream crates that link `rust-usd`.
2//!
3//! `rust-usd`'s own `build.rs` emits the rpath args its examples need at
4//! runtime, but `cargo:rustc-link-arg` only applies to the immediate target.
5//! Downstream binaries / examples have to re-emit the same rpaths or the
6//! dynamic loader can't find `libpxr_*.dylib` at startup.
7//!
8//! Add this crate as a build-dependency and call [`emit_runtime_rpath`] from
9//! your own `build.rs`:
10//!
11//! ```ignore
12//! fn main() {
13//! rust_usd_build::emit_runtime_rpath();
14//! }
15//! ```
16//!
17//! It reads the same environment variables `rust-usd`'s build script does
18//! and is a no-op if none of them are set, so consumers can leave the call
19//! in unconditionally even on CI machines without a USD install.
20
21use std::env;
22use std::path::PathBuf;
23
24/// Emit the `cargo:rustc-link-arg` directives needed for downstream
25/// executables to find OpenUSD's dylibs at runtime via `@rpath`.
26///
27/// Reads `USD_LIB_DIR` (or `USD_INSTALL_DIR/lib`) and the Python framework
28/// vars `USD_LINK_PYTHON` / `USD_PYTHON_FRAMEWORK_DIR` /
29/// `USD_PYTHON_FRAMEWORK` / `USD_PYTHON_LIB_DIR`, and re-emits matching
30/// `-Wl,-rpath` link args. Idempotent if no relevant env vars are set.
31pub fn emit_runtime_rpath() {
32 let lib_dir = resolve_lib_dir();
33 let link_python = env::var("USD_LINK_PYTHON").unwrap_or_else(|_| "framework".into());
34
35 if let Some(lib_dir) = lib_dir {
36 println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir.display());
37 if let Some(parent) = lib_dir.parent() {
38 println!("cargo:rustc-link-arg=-Wl,-rpath,{}", parent.display());
39 }
40 }
41
42 match link_python.as_str() {
43 "framework" => {
44 if let Ok(fw_dir) = env::var("USD_PYTHON_FRAMEWORK_DIR") {
45 let fw_name = env::var("USD_PYTHON_FRAMEWORK").unwrap_or_else(|_| "Python".into());
46 let inside_fw = PathBuf::from(&fw_dir).join(format!("{}.framework", fw_name));
47 println!("cargo:rustc-link-arg=-Wl,-rpath,{}", inside_fw.display());
48 }
49 }
50 "lib" => {
51 if let Ok(py_lib_dir) = env::var("USD_PYTHON_LIB_DIR") {
52 println!("cargo:rustc-link-arg=-Wl,-rpath,{}", py_lib_dir);
53 }
54 }
55 _ => {}
56 }
57
58 for var in [
59 "USD_LIB_DIR",
60 "USD_INSTALL_DIR",
61 "USD_LINK_PYTHON",
62 "USD_PYTHON_FRAMEWORK_DIR",
63 "USD_PYTHON_FRAMEWORK",
64 "USD_PYTHON_LIB_DIR",
65 ] {
66 println!("cargo:rerun-if-env-changed={}", var);
67 }
68}
69
70fn resolve_lib_dir() -> Option<PathBuf> {
71 if let Ok(dir) = env::var("USD_LIB_DIR") {
72 return Some(PathBuf::from(dir));
73 }
74 if let Ok(install) = env::var("USD_INSTALL_DIR") {
75 return Some(PathBuf::from(install).join("lib"));
76 }
77 if let Ok(prefix) = env::var("PXR_CMAKE_PREFIX") {
78 return Some(PathBuf::from(prefix).join("lib"));
79 }
80 None
81}