use std::env;
use std::path::PathBuf;
use std::process::Command;
fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let local_neug_dir = manifest_dir.parent().unwrap().join("neug-cpp");
let neug_dir = if local_neug_dir.join("CMakeLists.txt").exists() {
println!(
"cargo:warning=Using local neug-cpp submodule at {}",
local_neug_dir.display()
);
local_neug_dir.clone()
} else {
let download_dir = out_dir.join("neug-cpp");
if !download_dir.exists() {
let git_ref = env::var("NEUG_GIT_REF").unwrap_or_else(|_| "main".to_string());
println!(
"cargo:warning=Downloading alibaba/neug {} into {}...",
git_ref,
download_dir.display()
);
let status = Command::new("git")
.args([
"clone",
"--recursive",
"--depth",
"1",
"--branch",
&git_ref,
"https://github.com/alibaba/neug.git",
download_dir.to_str().unwrap(),
])
.status()
.expect("Failed to run git clone");
if !status.success() {
panic!("Failed to clone neug repository");
}
let arrow_cmake = download_dir.join("cmake/BuildArrowAsThirdParty.cmake");
let cmake_content = std::fs::read_to_string(&arrow_cmake).unwrap();
let new_content = cmake_content.replace(
"https://graphscope.oss-cn-beijing.aliyuncs.com/apache-arrow-${ARROW_VERSION}.tar.gz",
"https://github.com/apache/arrow/archive/refs/tags/apache-arrow-${ARROW_VERSION}.tar.gz"
);
std::fs::write(&arrow_cmake, new_content).unwrap();
}
download_dir
};
let mut config = cmake::Config::new(&neug_dir);
config
.define("BUILD_TESTS", "OFF")
.define("BUILD_EXAMPLES", "OFF")
.define("BUILD_HTTP_SERVER", "OFF");
if Command::new("sccache").arg("--version").output().is_ok() {
config.define("CMAKE_C_COMPILER_LAUNCHER", "sccache");
config.define("CMAKE_CXX_COMPILER_LAUNCHER", "sccache");
} else if Command::new("ccache").arg("--version").output().is_ok() {
config.define("CMAKE_C_COMPILER_LAUNCHER", "ccache");
config.define("CMAKE_CXX_COMPILER_LAUNCHER", "ccache");
}
if let Ok(jobs) = env::var("ZVEC_BUILD_PARALLEL") {
unsafe { env::set_var("CMAKE_BUILD_PARALLEL_LEVEL", jobs) };
}
let dst = config.build();
println!("cargo:rustc-link-search=native={}/lib", dst.display());
println!("cargo:rustc-link-search=native={}/lib64", dst.display());
println!("cargo:rustc-link-lib=dylib=neug");
let mut build = cc::Build::new();
build
.cpp(true)
.std("c++20")
.file("c_api.cpp")
.include(format!("{}/include", neug_dir.display()))
.include(format!("{}/include", dst.display()));
if Command::new("sccache").arg("--version").output().is_ok() {
build.compiler("sccache c++");
} else if Command::new("ccache").arg("--version").output().is_ok() {
build.compiler("ccache c++");
}
build.compile("neug_c_api");
println!("cargo:rerun-if-changed=c_api.h");
println!("cargo:rerun-if-changed=c_api.cpp");
if neug_dir == local_neug_dir {
println!("cargo:rerun-if-changed=../neug-cpp/CMakeLists.txt");
}
let bindings = bindgen::Builder::default()
.header("c_api.h")
.clang_arg("-xc++")
.clang_arg("-std=c++20")
.clang_arg(format!("-I{}/include", dst.display()))
.clang_arg(format!("-I{}/include", neug_dir.display()))
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.allowlist_type("neug_.*")
.allowlist_function("neug_.*")
.allowlist_var("neug_.*")
.layout_tests(false)
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_dir.join("bindings.rs"))
.expect("Couldn't write bindings!");
}