use std::path::{Path, PathBuf};
fn split_paths(paths: &str) -> Vec<String> {
let split_char = if cfg!(windows) { ";" } else { ":" };
paths.split(split_char).map(|path| path.to_string()).collect()
}
const LIB_CANDIDATES: &[&str] = &[
"",
"lib",
"lib/stubs",
"lib/x64",
"lib/Win32",
"lib/x86_64",
"lib/x86_64-linux-gnu",
"lib64",
"lib64/stubs",
"targets/x86_64-linux",
"targets/x86_64-linux/lib",
"targets/x86_64-linux/lib/stubs",
];
fn link_search_paths(env_candidates: &[&str], typical_locations: &[&str]) -> Vec<PathBuf> {
let env_roots = env_candidates
.iter()
.filter_map(|var| std::env::var(var).ok())
.flat_map(|path| split_paths(&path))
.filter(|path| !path.is_empty())
.collect::<Vec<_>>();
let roots = if env_roots.is_empty() {
typical_locations.iter().map(|path| path.to_string()).collect()
} else {
env_roots
};
let mut paths = vec![];
for root in roots {
for lib in LIB_CANDIDATES {
let path = Path::new(&root).join(lib);
if path.is_dir() {
let path = std::fs::canonicalize(&path).unwrap_or(path);
if !paths.contains(&path) {
paths.push(path);
}
}
}
}
paths
}
fn dir_contains_libcuest(path: &Path) -> bool {
std::fs::read_dir(path)
.map(|entries| {
entries.filter_map(Result::ok).any(|entry| {
let name = entry.file_name();
let name = name.to_string_lossy();
name.starts_with("libcuest.") || name == "cuest.lib"
})
})
.unwrap_or(false)
}
fn main() {
if std::env::var("CARGO_FEATURE_DYNAMIC_LOADING").is_ok() {
return;
}
let env_cuest =
["CUEST_LIB_DIR", "REST_EXT_DIR", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "PATH"];
let env_cuda = ["CUDA_HOME", "CUDA_PATH", "CUDA_ROOT", "CUDA_TOOLKIT_ROOT_DIR"];
for env_var in env_cuest.iter().chain(env_cuda.iter()) {
if let Ok(path) = std::env::var(env_var) {
println!("cargo:rerun-if-env-changed={env_var}");
println!("cargo:rerun-if-changed={path}");
}
}
let paths_cuest =
link_search_paths(&env_cuest, &["/usr", "/usr/local", "/usr/local/share", "/opt"]);
let paths_cuda = link_search_paths(&env_cuda, &[
"/usr/local/cuda",
"/opt/cuda",
"/usr/lib/cuda",
"/usr",
"/usr/local",
]);
for path in paths_cuest.iter().chain(paths_cuda.iter()) {
println!("cargo:rustc-link-search=native={}", path.display());
}
if !paths_cuest.iter().any(|path| dir_contains_libcuest(path)) {
println!(
"cargo:warning=libcuest library not found in the candidate search paths; \
static linking will likely fail. Set CUEST_LIB_DIR (or REST_EXT_DIR) to the \
cuEST installation prefix, or keep the default `dynamic_loading` feature."
);
}
println!("cargo:rustc-link-lib=cuest");
println!("cargo:rustc-link-lib=cublas");
println!("cargo:rustc-link-lib=cusolver");
}