use std::{
env, fs,
path::{Path, PathBuf},
process::Command,
};
fn main() {
git_submodule_update_init();
fail_on_empty_directory("tugraph-db");
bindgen_tugraph_db();
if std::env::var("DOCS_RS").is_ok() {
return;
}
build_tugraph_db();
}
fn git_submodule_update_init() {
if !Path::new("tugraph-db/LICENSE").exists()
|| !Path::new("tugraph-db/deps/antlr4/LICENSE.txt").exists()
{
run_cmd(Command::new("git").args(["submodule", "update", "--init", "--recursive"]));
}
}
fn run_cmd(cmd: &mut Command) {
println!("Running command: $ {cmd:?}");
match cmd.status().map(|s| (s.success(), s.code())) {
Ok((true, _)) => (),
Ok((false, Some(c))) => panic!("Command failed with error code {c}"),
Ok((false, None)) => panic!("Command got killed"),
Err(e) => panic!("Command failed with error: {e}"),
}
}
fn bindgen_tugraph_db() {
let c_header = tugraph_db_include_dir()
.join("lgraph/c.h")
.into_os_string()
.into_string()
.unwrap();
println!("cargo:rerun-if-changed={}", c_header);
let bindings = bindgen::Builder::default()
.header(c_header)
.derive_debug(false)
.ctypes_prefix("libc")
.size_t_is_usize(true)
.generate()
.expect("unable to generate tugraph-db bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("unable to write tugraph-db bindings");
}
fn tugraph_db_include_dir() -> PathBuf {
let dir = env::var("TUGRAPH_DB_INCLUDE_DIR").unwrap_or("tugraph-db/include".to_string());
PathBuf::from(dir)
}
fn fail_on_empty_directory(name: &str) {
if fs::read_dir(name).unwrap().count() == 0 {
panic!(
"The `{name}` directory is empty, did you forget to pull the submodules? Try `git submodule update --init --recursive`"
);
}
}
fn build_tugraph_db() {
let target = env::var("TARGET").unwrap();
if target != "x86_64-unknown-linux-gnu" {
panic!(
"Your target is {target}, but building tugraph-db is only tested in x86_64-unknown-linux-gnu"
);
}
build_dep();
println!("cargo:rerun-if-env-change=LGRAPH_C_COMPILER");
println!("cargo:rerun-if-env-change=LGRAPH_CXX_COMPILER");
run_cmd(
Command::new("/bin/bash").args([
"-c",
format!(
"
cmake -S tugraph-db -B {build_dir} \
-DCMAKE_CXX_COMPILER={cxx_compiler} \
-DCMAKE_C_COMPILER={c_compiler} \
-DCMAKE_BUILD_TYPE={build_type} \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
&& cmake --build {build_dir} -j {num_jobs} --target lgraph",
c_compiler = c_compiler(),
cxx_compiler = cxx_compiler(),
num_jobs = num_jobs(),
build_dir = build_dir().to_str().unwrap(),
build_type = build_type(),
)
.as_str(),
]),
);
println!("cargo:rustc-link-search=native={}", output_dir().to_str().unwrap());
println!("cargo:rustc-link-lib=dylib=lgraph");
}
fn build_dep() {
let num_jobs = num_jobs();
run_cmd(Command::new("/bin/bash").args([
"-c",
format!("SKIP_WEB=1 tugraph-db/deps/build_deps.sh -j{num_jobs}").as_str(),
]));
}
fn c_compiler() -> String {
env::var("LGRAPH_C_COMPILER").unwrap_or("/usr/bin/gcc".to_string())
}
fn cxx_compiler() -> String {
env::var("LGRAPH_CXX_COMPILER").unwrap_or("/usr/bin/g++".to_string())
}
fn num_jobs() -> String {
env::var("NUM_JOBS").unwrap_or_else(|_| "1".to_string())
}
fn out_dir() -> PathBuf {
PathBuf::from(env::var("OUT_DIR").unwrap())
}
fn build_dir() -> PathBuf {
out_dir().join("build")
}
fn output_dir() -> PathBuf {
build_dir().join("output")
}
fn build_type() -> String {
let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
profile[0..1].to_uppercase() + &profile[1..]
}