#[cfg(feature = "build")]
fn main() {
}
#[cfg(not(feature = "build"))]
fn main() {
use std::env;
use std::path::PathBuf;
use std::process::Command;
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let mut base_dir = manifest_dir.join("sppark");
if !base_dir.exists() {
base_dir = manifest_dir
.parent()
.expect("can't access parent of current directory")
.into();
println!(
"cargo:rerun-if-changed={}",
base_dir.join("ec").to_string_lossy()
);
println!(
"cargo:rerun-if-changed={}",
base_dir.join("ff").to_string_lossy()
);
println!(
"cargo:rerun-if-changed={}",
base_dir.join("ntt").to_string_lossy()
);
println!(
"cargo:rerun-if-changed={}",
base_dir.join("msm").to_string_lossy()
);
println!(
"cargo:rerun-if-changed={}",
base_dir.join("util").to_string_lossy()
);
}
println!("cargo:ROOT={}", base_dir.to_string_lossy());
let all_gpus = base_dir.join("util/all_gpus.cpp");
println!("cargo:rerun-if-env-changed=NVCC");
let mut nvcc = match env::var("NVCC") {
Ok(var) => which::which(var),
Err(_) => which::which("nvcc"),
};
println!("cargo:rerun-if-env-changed=HIPCC");
let mut hipcc = match env::var("HIPCC") {
Ok(var) => which::which(var),
Err(_) => which::which("hipcc"),
};
match (cfg!(feature = "cuda"), cfg!(feature = "rocm")) {
(true, true) => panic!("mutually exclusive features"),
(true, false) => {
if nvcc.is_err() {
panic!("`nvcc` is not available");
}
hipcc = Err(which::Error::CannotFindBinaryPath);
},
(false, true) => {
if hipcc.is_err() {
panic!("`hipcc` is not available");
}
nvcc = Err(which::Error::CannotFindBinaryPath);
},
(false, false) => (),
}
if let Ok(nvcc) = nvcc {
let cuda_version = Command::new(nvcc)
.arg("--version")
.output()
.expect("impossible");
if !cuda_version.status.success() {
panic!("{:?}", cuda_version);
}
let cuda_version = String::from_utf8(cuda_version.stdout).unwrap();
let x = cuda_version
.find("release ")
.expect("can't find \"release X.Y,\" in --version output")
+ 8;
let y = cuda_version[x..]
.find(",")
.expect("can't parse \"release X.Y,\" in --version output");
let v = cuda_version[x..x + y].parse::<f32>().unwrap();
if v < 11.4 {
panic!("Unsupported CUDA version {} < 11.4", v);
}
let cuda_available = env::var_os("OUT_DIR")
.map(PathBuf::from)
.map(|p| p.join("cuda_available"))
.map(|mut p| {
p.set_extension(env::consts::EXE_EXTENSION);
p
})
.expect("$OUT_DIR is not set");
let mut nvcc = cc::Build::new();
nvcc.cuda(true);
let _ = nvcc
.get_compiler()
.to_command()
.arg("src/cuda_available.cpp")
.arg("-o")
.arg(&cuda_available)
.status()
.expect("impossible");
let cuda_available = Command::new(cuda_available).status().expect("impossible");
if cuda_available.success() || hipcc.is_err() {
nvcc.include(&base_dir);
nvcc.file(&all_gpus)
.compile("sppark_cuda");
println!("cargo:rustc-cfg=feature=\"cuda\"");
println!("cargo:TARGET=cuda");
return;
}
}
if let Ok(hipcc) = hipcc {
env::set_var("HIP_PLATFORM", "amd");
let hipcc_version = Command::new(&hipcc)
.arg("--version")
.output()
.expect("impossible");
if !hipcc_version.status.success() {
panic!("{:?}", hipcc_version);
}
let hipcc_version = String::from_utf8(hipcc_version.stdout).unwrap();
let v = hipcc_version
.find("HIP version: ")
.expect(format!("{:?} is not a HIP compiler", hipcc).as_str())
+ 13;
let mut w = hipcc_version[v..]
.find(|c: char| !c.is_digit(10))
.expect("can't parse \"HIP version: \" in `hipcc --version`");
w = w + 1 + hipcc_version[v + w + 1..]
.find(|c: char| !c.is_digit(10))
.expect("can't parse \"HIP version: \" in `hipcc --version`");
let ver = hipcc_version[v..v + w].parse::<f32>().unwrap();
if ver < 5.7 {
panic!("Unsupported HIP version {} < 5.7", ver);
}
let x = hipcc_version
.find("InstalledDir: ")
.expect("can't find \"InstalledDir:\" in `hipcc --version`")
+ 14;
let y = hipcc_version[x..]
.find(char::is_control)
.expect("can't parse \"InstalledDir:\" in `hipcc --version`");
let mut libpath: PathBuf = hipcc_version[x..x + y].into();
while libpath.pop() {
if libpath
.join("lib")
.join(if cfg!(unix) {
"libamdhip64.so"
} else {
"amdhip64.lib"
})
.try_exists()
.is_ok_and(|exists| exists)
{
libpath.push("lib");
break;
}
}
let mut ccmd = cc::Build::new();
ccmd.compiler(hipcc);
ccmd.cpp(true);
ccmd.include(&base_dir);
ccmd.flag("-include").flag("util/cuda2hip.hpp");
ccmd.file(&all_gpus)
.compile("sppark_rocm");
println!("cargo:rustc-cfg=feature=\"rocm\"");
if libpath.parent().is_some() {
println!(
"cargo:rustc-link-search=native={}",
libpath.to_string_lossy()
);
}
println!("cargo:rustc-link-lib=amdhip64");
println!("cargo:TARGET=rocm");
}
}