use std::env;
use std::path::PathBuf;
fn cuda_library_path() -> Vec<PathBuf> {
if let Ok(path) = env::var("CUDA_LIBRARY_PATH") {
let split_char = if cfg!(target_os = "windows") {
";"
} else {
":"
};
path.split(split_char).map(PathBuf::from).collect()
} else {
vec![]
}
}
fn find_cuda_windows() -> Vec<PathBuf> {
let candidates = cuda_library_path();
if candidates.is_empty() {
return candidates;
}
if let Ok(path) = env::var("CUDA_PATH") {
let target = env::var("TARGET").expect("cargo target");
let target_components: Vec<_> = target.as_str().split('-').collect();
if target_components[2] != "windows" {
println!(
"cargo:warning=CUDA_PATH env variable is used on Windows, yet build target is {}",
target
);
return vec![];
}
debug_assert_eq!(
target_components.get(1).copied(),
Some("pc"),
"Expected a Windows target to have the second component be 'pc'. Target: {}",
target
);
let lib_path = match target_components.first().copied() {
Some("x86_64") => "x64",
None => {
println!("cargo:warning=missing architecture");
return vec![];
}
_ => {
println!(
"cargo:warning=unsupported architecture {}",
target_components[0]
);
return vec![];
}
};
return vec![PathBuf::from(path).join("lib").join(lib_path)];
}
vec![]
}
fn find_cuda_unix() -> Vec<PathBuf> {
let mut candidates = cuda_library_path();
candidates.extend([PathBuf::from("/opt/cuda"), PathBuf::from("/usr/local/cuda")]);
candidates.extend(
glob::glob("/usr/local/cuda-*")
.expect("glob cuda")
.filter_map(Result::ok),
);
let mut valid_paths = vec![];
for base in &candidates {
let lib = PathBuf::from(base).join("lib64");
if lib.is_dir() {
valid_paths.extend([lib.clone(), lib.join("stubs")]);
}
let base = base.join("targets/x86_64-linux");
if base.join("include/cuda.h").is_file() {
valid_paths.extend([base.join("lib"), base.join("lib/stubs")]);
continue;
}
}
valid_paths
}
pub fn find_cuda() -> Vec<PathBuf> {
if cfg!(target_os = "windows") {
find_cuda_windows()
} else {
find_cuda_unix()
}
}