use std::env;
use std::path::PathBuf;
use std::process::Command;
fn main() {
if env::var("DOCS_RS").is_ok() {
return;
}
let has_cuda_feature = std::env::var("CARGO_FEATURE_CUDA").is_ok();
if !has_cuda_feature {
return;
}
let workspace_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
println!("cargo:warning=Building CUDA FFI stubs (no real CUDA linkage yet)");
let (compiler, obj_ext, lib_prefix, lib_ext, is_msvc) = if cfg!(target_os = "windows") {
if Command::new("cl.exe").arg("/?").output().is_ok() {
("cl.exe", "obj", "", "lib", true)
} else if Command::new("g++").arg("--version").output().is_ok() {
("g++", "o", "lib", "a", false)
} else {
println!("cargo:warning=No suitable C++ compiler found on Windows. Skipping CUDA stub build.");
return;
}
} else if cfg!(target_os = "macos") {
if Command::new("clang++").arg("--version").output().is_ok() {
("clang++", "o", "lib", "a", false)
} else if Command::new("g++").arg("--version").output().is_ok() {
("g++", "o", "lib", "a", false)
} else {
println!(
"cargo:warning=No suitable C++ compiler found on macOS. Skipping CUDA stub build."
);
return;
}
} else {
if Command::new("g++").arg("--version").output().is_ok() {
("g++", "o", "lib", "a", false)
} else if Command::new("clang++").arg("--version").output().is_ok() {
("clang++", "o", "lib", "a", false)
} else {
println!("cargo:warning=No suitable C++ compiler found. Skipping CUDA stub build.");
return;
}
};
let cuda_cpp = PathBuf::from(&workspace_dir).join("src/cuda/cuda_wrapper.cpp");
let cuda_obj = out_dir.join(format!("cuda_wrapper.{}", obj_ext));
let cuda_lib = out_dir.join(format!("{}cuda_wrapper.{}", lib_prefix, lib_ext));
let compile_result = if compiler == "cl.exe" {
let cuda_cpp_str = cuda_cpp.to_string_lossy();
let cuda_obj_str = cuda_obj.to_string_lossy();
Command::new(compiler)
.args([
"/std:c++17",
"/c",
&cuda_cpp_str,
"/O2",
"/DNDEBUG",
&format!("/Fo:{}", cuda_obj_str),
])
.output()
} else {
let cuda_cpp_str = cuda_cpp.to_string_lossy();
let cuda_obj_str = cuda_obj.to_string_lossy();
let mut args = vec![
"-std=c++17",
"-c",
&cuda_cpp_str,
"-O2",
"-DNDEBUG",
"-o",
&cuda_obj_str,
];
if !cfg!(target_os = "windows") {
args.insert(1, "-fPIC");
}
Command::new(compiler).args(args).output()
};
let compile_output = match compile_result {
Ok(output) => output,
Err(e) => {
println!("cargo:warning=Failed to execute {} for CUDA stub compilation: {}. Skipping CUDA stub build.", compiler, e);
return;
}
};
if !compile_output.status.success() {
println!(
"cargo:warning=CUDA stub compilation failed:\n{}\n{}. Skipping CUDA stub build.",
String::from_utf8_lossy(&compile_output.stdout),
String::from_utf8_lossy(&compile_output.stderr)
);
return;
}
let link_result = if is_msvc {
if Command::new("lib.exe").arg("/?").output().is_err() {
println!(
"cargo:warning=lib.exe not found. Skipping CUDA stub static library creation."
);
return;
}
Command::new("lib.exe")
.arg(format!("/OUT:{}", cuda_lib.display()))
.arg(&cuda_obj)
.output()
} else {
if Command::new("ar")
.arg("t")
.arg("/dev/null")
.output()
.is_err()
{
println!("cargo:warning=ar not found. Skipping CUDA stub static library creation.");
return;
}
Command::new("ar")
.arg("rcs")
.arg(&cuda_lib)
.arg(&cuda_obj)
.output()
};
let link_output = match link_result {
Ok(output) => output,
Err(e) => {
println!("cargo:warning=Failed to execute linker for CUDA stub: {}. Skipping CUDA stub build.", e);
return;
}
};
if !link_output.status.success() {
println!(
"cargo:warning=CUDA stub static library creation failed:\n{}\n{}. Skipping CUDA stub build.",
String::from_utf8_lossy(&link_output.stdout),
String::from_utf8_lossy(&link_output.stderr)
);
return;
}
println!("cargo:rustc-link-search=native={}", out_dir.display());
println!("cargo:rustc-link-lib=static=cuda_wrapper");
let target = env::var("TARGET").unwrap_or_else(|_| env::var("HOST").unwrap_or_default());
if target.contains("linux") || target.contains("android") {
println!("cargo:rustc-link-lib=dylib=stdc++");
} else if target.contains("apple") || target.contains("darwin") || target.contains("ios") {
println!("cargo:rustc-link-lib=dylib=c++");
} else if target.contains("windows") && !is_msvc {
println!("cargo:rustc-link-lib=dylib=stdc++");
}
println!("cargo:rerun-if-changed=src/cuda/cuda_wrapper.cpp");
println!("cargo:rerun-if-changed=src/cuda/cuda_wrapper.h");
}