use std::process::Command;
fn main() {
#[cfg(feature = "embedded-python")]
pyo3_build_config::use_pyo3_cfgs();
println!("cargo:rerun-if-env-changed=PYO3_PYTHON");
println!("cargo:rerun-if-env-changed=VIRTUAL_ENV");
println!("cargo:rerun-if-env-changed=RPYTEST_PYTHON");
#[cfg(target_os = "macos")]
fix_macos_libpython_install_name();
}
#[cfg(target_os = "macos")]
fn fix_macos_libpython_install_name() {
let python = std::env::var("PYO3_PYTHON").unwrap_or_else(|_| "python3".to_string());
let output = Command::new(&python)
.args([
"-c",
"import sysconfig; print(sysconfig.get_config_var('LIBDIR')); print(sysconfig.get_config_var('LDLIBRARY'))",
])
.output();
let (libdir, ldlibrary) = match output {
Ok(ref out) if out.status.success() => {
let stdout = String::from_utf8_lossy(&out.stdout);
let mut lines = stdout.trim().lines();
let libdir = lines.next().unwrap_or("").to_string();
let ldlibrary = lines.next().unwrap_or("").to_string();
(libdir, ldlibrary)
}
_ => {
eprintln!(
"cargo:warning=Could not determine Python LIBDIR/LDLIBRARY from `{python}`. \
The binary may fail to find libpython at runtime."
);
return;
}
};
if libdir.is_empty() || ldlibrary.is_empty() {
return;
}
let dylib_path = format!("{libdir}/{ldlibrary}");
let otool_output = Command::new("otool").args(["-D", &dylib_path]).output();
let current_install_name = match otool_output {
Ok(ref out) if out.status.success() => {
let stdout = String::from_utf8_lossy(&out.stdout);
stdout.trim().lines().nth(1).unwrap_or("").to_string()
}
_ => return,
};
if current_install_name == dylib_path {
return;
}
eprintln!(
"cargo:warning=Fixing libpython install_name: {current_install_name} -> {dylib_path}"
);
let result = Command::new("install_name_tool")
.args(["-id", &dylib_path, &dylib_path])
.status();
match result {
Ok(status) if status.success() => {
eprintln!("cargo:warning=Successfully fixed libpython install_name");
}
Ok(status) => {
eprintln!(
"cargo:warning=install_name_tool exited with status {status}. \
Falling back to rpath approach."
);
println!("cargo:rustc-link-arg=-Wl,-rpath,{libdir}");
}
Err(e) => {
eprintln!(
"cargo:warning=Failed to run install_name_tool: {e}. \
Falling back to rpath approach."
);
println!("cargo:rustc-link-arg=-Wl,-rpath,{libdir}");
}
}
}