use cmake::Config;
use std::fs;
use std::path::PathBuf;
use std::process::Command;
fn add_usr_local_link_search_paths_if_needed() {
for dir in ["/usr/local/lib", "/usr/local/lib64"] {
let d = PathBuf::from(dir);
if !d.is_dir() {
continue;
}
let has_glog = d.join("libglog.so").exists() || d.join("libglog.so.1").exists();
let has_gflags = d.join("libgflags.so").exists() || d.join("libgflags.so.2").exists();
if has_glog || has_gflags {
println!("cargo:rustc-link-search=native={}", d.display());
}
}
}
fn has_ccache() -> bool {
if std::env::var_os("CCACHE_DIR").is_none() {
return false;
}
Command::new("ccache")
.arg("--version")
.status()
.map(|status| status.success())
.unwrap_or(false)
}
fn main() {
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
if let Ok(repo_root) = manifest_dir.join("../..").canonicalize() {
if repo_root.join(".git").exists() {
let status = Command::new("git")
.args(&["submodule", "update", "--init", "--recursive"])
.current_dir(&repo_root)
.status();
if let Ok(s) = status {
if !s.success() {
panic!(
"git submodule update --init --recursive failed, please manually execute in repository root"
);
}
}
}
}
let num_jobs = std::env::var("NUM_JOBS")
.ok()
.and_then(|s| s.parse::<u32>().ok())
.or_else(|| {
std::thread::available_parallelism()
.ok()
.map(|p| p.get() as u32)
})
.unwrap_or(1)
.max(1);
let mut config = Config::new("vendor");
config
.define("CMAKE_CXX_STANDARD", "20")
.define("BUILD_FOR_RUST", "ON")
.define("STATIC_ALL_DEPS", "ON")
.define("WITH_UNIT_TESTS", "OFF")
.define("WITH_EXAMPLE", "OFF")
.define("WITH_DB_STRESS", "OFF")
.define("WITH_BENCHMARK", "OFF")
.define("ELOQ_MODULE_ENABLED", "OFF")
.build_arg(format!("-j{}", num_jobs));
if has_ccache() {
config
.define("CMAKE_C_COMPILER_LAUNCHER", "ccache")
.define("CMAKE_CXX_COMPILER_LAUNCHER", "ccache");
}
let dst = config.build();
let build_dir = dst.join("build");
let lib_dir = dst.join("lib");
if !lib_dir.exists() {
fs::create_dir_all(&lib_dir).expect("Failed to create lib dir");
}
let combined_lib = build_dir.join("libeloqstore_combine.so");
let combined_lib_dest = lib_dir.join("libeloqstore_combine.so");
if combined_lib.exists() {
fs::copy(&combined_lib, &combined_lib_dest)
.expect("Failed to copy libeloqstore_combine.so");
if let Ok(out_dir) = std::env::var("OUT_DIR") {
let embedded_lib_path = PathBuf::from(&out_dir).join("libeloqstore_combine.so");
fs::copy(&combined_lib, &embedded_lib_path)
.expect("Failed to copy libeloqstore_combine.so to OUT_DIR for embedding");
}
println!("cargo:rustc-link-search=native={}", lib_dir.display());
let lib_dir_str = lib_dir.display().to_string();
let mut copied_to_target = false;
if let Ok(out_dir) = std::env::var("OUT_DIR") {
let out_path = PathBuf::from(&out_dir);
if let Some(target_profile_dir) = out_path.ancestors().nth(3) {
let target_lib = target_profile_dir.join("libeloqstore_combine.so");
if let Some(parent) = target_lib.parent() {
if fs::create_dir_all(parent).is_ok() {
if fs::copy(&combined_lib_dest, &target_lib).is_ok() {
copied_to_target = true;
}
}
}
if let Some(target_base) = target_profile_dir.parent() {
let other_profile = if target_profile_dir.ends_with("debug") {
target_base.join("release")
} else {
target_base.join("debug")
};
let other_lib = other_profile.join("libeloqstore_combine.so");
if let Some(parent) = other_lib.parent() {
let _ = fs::create_dir_all(parent);
let _ = fs::copy(&combined_lib_dest, &other_lib);
}
}
}
}
if !copied_to_target {
if let Ok(target_dir) = std::env::var("CARGO_TARGET_DIR") {
let target_debug_lib = PathBuf::from(&target_dir)
.join("debug")
.join("libeloqstore_combine.so");
let target_release_lib = PathBuf::from(&target_dir)
.join("release")
.join("libeloqstore_combine.so");
if let Some(parent) = target_debug_lib.parent() {
let _ = fs::create_dir_all(parent);
let _ = fs::copy(&combined_lib_dest, &target_debug_lib);
}
if let Some(parent) = target_release_lib.parent() {
let _ = fs::create_dir_all(parent);
let _ = fs::copy(&combined_lib_dest, &target_release_lib);
}
}
}
println!("cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN/..");
println!("cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN/../..");
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir_str);
let use_static = std::env::var("ELOQSTORE_STATIC_EXE").is_ok();
if use_static {
let static_lib = build_dir.join("libeloqstore.a");
if static_lib.exists() {
fs::copy(&static_lib, lib_dir.join("libeloqstore.a"))
.expect("Failed to copy libeloqstore.a");
println!("cargo:rustc-link-lib=static=eloqstore");
let absl_dir = build_dir.join("external/abseil/absl");
if absl_dir.exists() {
for entry in fs::read_dir(&absl_dir).expect("Failed to read abseil dir") {
let entry = entry.expect("Failed to get entry");
let path = entry.path();
if path.is_dir() {
println!("cargo:rustc-link-search=native={}", path.display());
if let Ok(entries) = fs::read_dir(&path) {
for file_entry in entries {
let file_path = file_entry.expect("Failed to get file").path();
if file_path.extension().map(|e| e == "a").unwrap_or(false) {
let name = file_path.file_stem().unwrap().to_str().unwrap();
if name.starts_with("libabsl_") {
let lib_name = &name[3..];
println!("cargo:rustc-link-lib={}", lib_name);
}
}
}
}
}
}
}
} else {
println!("cargo:warning=Static library not found, falling back to dynamic linking");
println!("cargo:rustc-link-lib=dylib=eloqstore_combine");
}
} else {
println!("cargo:rustc-link-lib=dylib=eloqstore_combine");
}
if use_static {
add_usr_local_link_search_paths_if_needed();
println!("cargo:rustc-link-lib=zstd");
println!("cargo:rustc-link-lib=glog");
println!("cargo:rustc-link-lib=gflags");
println!("cargo:rustc-link-lib=curl");
println!("cargo:rustc-link-lib=crypto");
println!("cargo:rustc-link-lib=ssl");
println!("cargo:rustc-link-lib=uring");
println!("cargo:rustc-link-lib=jsoncpp");
println!("cargo:rustc-link-lib=boost_context");
println!("cargo:rustc-link-lib=aws-cpp-sdk-s3");
println!("cargo:rustc-link-lib=aws-cpp-sdk-core");
println!("cargo:rustc-link-lib=aws-c-event-stream");
println!("cargo:rustc-link-lib=aws-checksums");
println!("cargo:rustc-link-lib=aws-c-auth");
println!("cargo:rustc-link-lib=aws-c-cal");
println!("cargo:rustc-link-lib=aws-c-common");
}
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=stdc++");
if !use_static {
println!("cargo:rustc-link-lib=zstd");
}
} else {
let src_lib = build_dir.join("libeloqstore.a");
if src_lib.exists() {
fs::copy(&src_lib, lib_dir.join("libeloqstore.a"))
.expect("Failed to copy libeloqstore.a");
}
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-lib=static=eloqstore");
let absl_dir = build_dir.join("external/abseil/absl");
if absl_dir.exists() {
for entry in fs::read_dir(&absl_dir).expect("Failed to read abseil dir") {
let entry = entry.expect("Failed to get entry");
let path = entry.path();
if path.is_dir() {
println!("cargo:rustc-link-search=native={}", path.display());
}
}
for entry in fs::read_dir(&absl_dir).expect("Failed to read abseil dir") {
let entry = entry.expect("Failed to get entry");
let path = entry.path();
if path.is_dir() {
if let Ok(entries) = fs::read_dir(&path) {
for file_entry in entries {
let file_path = file_entry.expect("Failed to get file").path();
if file_path.extension().map(|e| e == "a").unwrap_or(false) {
let name = file_path.file_stem().unwrap().to_str().unwrap();
if name.starts_with("libabsl_") {
let lib_name = &name[3..];
println!("cargo:rustc-link-lib={}", lib_name);
}
}
}
}
}
}
}
add_usr_local_link_search_paths_if_needed();
println!("cargo:rustc-link-lib=zstd");
println!("cargo:rustc-link-lib=glog");
println!("cargo:rustc-link-lib=gflags");
println!("cargo:rustc-link-lib=curl");
println!("cargo:rustc-link-lib=crypto");
println!("cargo:rustc-link-lib=ssl");
println!("cargo:rustc-link-lib=uring");
println!("cargo:rustc-link-lib=jsoncpp");
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=boost_context");
println!("cargo:rustc-link-lib=aws-cpp-sdk-s3");
println!("cargo:rustc-link-lib=aws-cpp-sdk-core");
println!("cargo:rustc-link-lib=aws-c-event-stream");
println!("cargo:rustc-link-lib=aws-checksums");
println!("cargo:rustc-link-lib=aws-c-auth");
println!("cargo:rustc-link-lib=aws-c-cal");
println!("cargo:rustc-link-lib=aws-c-common");
println!("cargo:rustc-link-lib=stdc++");
}
let include_path = PathBuf::from("vendor/include");
println!("cargo:include={}", include_path.display());
println!("cargo:rerun-if-changed=vendor/CMakeLists.txt");
println!("cargo:rerun-if-changed=vendor/src/");
println!("cargo:rerun-if-changed=vendor/include/");
println!("cargo:rerun-if-changed=../../.gitmodules");
println!("cargo:rerun-if-changed=../../external/");
}