|
|
|
use std::env;
|
|
|
|
use std::fs;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
fn link(name: &str, bundled: bool) {
|
|
|
|
use std::env::var;
|
|
|
|
let target = var("TARGET").unwrap();
|
|
|
|
let target: Vec<_> = target.split('-').collect();
|
|
|
|
if target.get(2) == Some(&"windows") {
|
|
|
|
println!("cargo:rustc-link-lib=dylib={}", name);
|
|
|
|
if bundled && target.get(3) == Some(&"gnu") {
|
|
|
|
let dir = var("CARGO_MANIFEST_DIR").unwrap();
|
|
|
|
println!("cargo:rustc-link-search=native={}/{}", dir, target[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fail_on_empty_directory(name: &str) {
|
|
|
|
if fs::read_dir(name).unwrap().count() == 0 {
|
|
|
|
println!(
|
|
|
|
"The `{}` directory is empty, did you forget to pull the submodules?",
|
|
|
|
name
|
|
|
|
);
|
|
|
|
println!("Try `git submodule update --init --recursive`");
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn rocksdb_include_dir() -> String {
|
|
|
|
match env::var("ROCKSDB_INCLUDE_DIR") {
|
|
|
|
Ok(val) => val,
|
|
|
|
Err(_) => "rocksdb/include".to_string(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bindgen_rocksdb() {
|
|
|
|
let bindings = bindgen::Builder::default()
|
|
|
|
.header(rocksdb_include_dir() + "/rocksdb/c.h")
|
|
|
|
.derive_debug(false)
|
|
|
|
.blacklist_type("max_align_t") // https://github.com/rust-lang-nursery/rust-bindgen/issues/550
|
|
|
|
.ctypes_prefix("libc")
|
|
|
|
.size_t_is_usize(true)
|
|
|
|
.generate()
|
|
|
|
.expect("unable to generate rocksdb bindings");
|
|
|
|
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
bindings
|
|
|
|
.write_to_file(out_path.join("bindings.rs"))
|
|
|
|
.expect("unable to write rocksdb bindings");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_rocksdb() {
|
|
|
|
let target = env::var("TARGET").unwrap();
|
|
|
|
|
|
|
|
let mut config = cc::Build::new();
|
|
|
|
config.include("rocksdb/include/");
|
|
|
|
config.include("rocksdb/");
|
|
|
|
config.include("rocksdb/third-party/gtest-1.8.1/fused-src/");
|
|
|
|
|
|
|
|
if cfg!(feature = "snappy") {
|
|
|
|
config.define("SNAPPY", Some("1"));
|
|
|
|
config.include("snappy/");
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg!(feature = "lz4") {
|
|
|
|
config.define("LZ4", Some("1"));
|
|
|
|
config.include("lz4/lib/");
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg!(feature = "zstd") {
|
|
|
|
config.define("ZSTD", Some("1"));
|
|
|
|
config.include("zstd/lib/");
|
|
|
|
config.include("zstd/lib/dictBuilder/");
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg!(feature = "zlib") {
|
|
|
|
config.define("ZLIB", Some("1"));
|
|
|
|
config.include("zlib/");
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg!(feature = "bzip2") {
|
|
|
|
config.define("BZIP2", Some("1"));
|
|
|
|
config.include("bzip2/");
|
|
|
|
}
|
|
|
|
|
|
|
|
config.include(".");
|
|
|
|
config.define("NDEBUG", Some("1"));
|
|
|
|
|
|
|
|
let mut lib_sources = include_str!("rocksdb_lib_sources.txt")
|
|
|
|
.trim()
|
|
|
|
.split('\n')
|
|
|
|
.map(str::trim)
|
|
|
|
.collect::<Vec<&'static str>>();
|
|
|
|
|
|
|
|
// We have a pregenerated a version of build_version.cc in the local directory
|
|
|
|
lib_sources = lib_sources
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.filter(|file| *file != "util/build_version.cc")
|
|
|
|
.collect::<Vec<&'static str>>();
|
|
|
|
|
|
|
|
if target.contains("x86_64") {
|
|
|
|
// This is needed to enable hardware CRC32C. Technically, SSE 4.2 is
|
|
|
|
// only available since Intel Nehalem (about 2010) and AMD Bulldozer
|
|
|
|
// (about 2011).
|
|
|
|
config.define("HAVE_SSE42", Some("1"));
|
|
|
|
config.flag_if_supported("-msse2");
|
|
|
|
config.flag_if_supported("-msse4.1");
|
|
|
|
config.flag_if_supported("-msse4.2");
|
|
|
|
|
|
|
|
if !target.contains("android") {
|
|
|
|
config.define("HAVE_PCLMUL", Some("1"));
|
|
|
|
config.flag_if_supported("-mpclmul");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if target.contains("darwin") {
|
|
|
|
config.define("OS_MACOSX", Some("1"));
|
|
|
|
config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
|
|
|
|
config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
|
|
|
|
} else if target.contains("android") {
|
|
|
|
config.define("OS_ANDROID", Some("1"));
|
|
|
|
config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
|
|
|
|
config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
|
|
|
|
} else if target.contains("linux") {
|
|
|
|
config.define("OS_LINUX", Some("1"));
|
|
|
|
config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
|
|
|
|
config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
|
|
|
|
} else if target.contains("freebsd") {
|
|
|
|
config.define("OS_FREEBSD", Some("1"));
|
|
|
|
config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
|
|
|
|
config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
|
|
|
|
} else if target.contains("windows") {
|
|
|
|
link("rpcrt4", false);
|
|
|
|
link("shlwapi", false);
|
|
|
|
config.define("OS_WIN", Some("1"));
|
|
|
|
config.define("ROCKSDB_WINDOWS_UTF8_FILENAMES", Some("1"));
|
|
|
|
if &target == "x86_64-pc-windows-gnu" {
|
|
|
|
// Tell MinGW to create localtime_r wrapper of localtime_s function.
|
|
|
|
config.define("_POSIX_C_SOURCE", None);
|
|
|
|
// Tell MinGW to use at least Windows Vista headers instead of the ones of Windows XP.
|
|
|
|
// (This is minimum supported version of rocksdb)
|
|
|
|
config.define("_WIN32_WINNT", Some("0x0600"));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove POSIX-specific sources
|
|
|
|
lib_sources = lib_sources
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.filter(|file| match *file {
|
|
|
|
"port/port_posix.cc" | "env/env_posix.cc" | "env/fs_posix.cc"
|
|
|
|
| "env/io_posix.cc" => false,
|
|
|
|
_ => true,
|
|
|
|
})
|
|
|
|
.collect::<Vec<&'static str>>();
|
|
|
|
|
|
|
|
// Add Windows-specific sources
|
|
|
|
lib_sources.push("port/win/port_win.cc");
|
|
|
|
lib_sources.push("port/win/env_win.cc");
|
|
|
|
lib_sources.push("port/win/env_default.cc");
|
|
|
|
lib_sources.push("port/win/win_logger.cc");
|
|
|
|
lib_sources.push("port/win/io_win.cc");
|
|
|
|
lib_sources.push("port/win/win_thread.cc");
|
|
|
|
}
|
|
|
|
|
|
|
|
if target.contains("msvc") {
|
|
|
|
config.flag("-EHsc");
|
|
|
|
} else {
|
|
|
|
config.flag(&cxx_standard());
|
|
|
|
// this was breaking the build on travis due to
|
|
|
|
// > 4mb of warnings emitted.
|
|
|
|
config.flag("-Wno-unused-parameter");
|
|
|
|
}
|
|
|
|
|
|
|
|
for file in lib_sources {
|
|
|
|
let file = "rocksdb/".to_string() + file;
|
|
|
|
config.file(&file);
|
|
|
|
}
|
|
|
|
|
|
|
|
config.file("build_version.cc");
|
|
|
|
|
|
|
|
config.cpp(true);
|
|
|
|
config.compile("librocksdb.a");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_snappy() {
|
|
|
|
let target = env::var("TARGET").unwrap();
|
|
|
|
let endianness = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap();
|
|
|
|
let mut config = cc::Build::new();
|
|
|
|
|
|
|
|
config.include("snappy/");
|
|
|
|
config.include(".");
|
|
|
|
config.define("NDEBUG", Some("1"));
|
|
|
|
config.extra_warnings(false);
|
|
|
|
|
|
|
|
if target.contains("msvc") {
|
|
|
|
config.flag("-EHsc");
|
|
|
|
} else {
|
|
|
|
// Snappy requires C++11.
|
|
|
|
// See: https://github.com/google/snappy/blob/master/CMakeLists.txt#L32-L38
|
|
|
|
config.flag("-std=c++11");
|
|
|
|
}
|
|
|
|
|
|
|
|
if endianness == "big" {
|
|
|
|
config.define("SNAPPY_IS_BIG_ENDIAN", Some("1"));
|
|
|
|
}
|
|
|
|
|
|
|
|
config.file("snappy/snappy.cc");
|
|
|
|
config.file("snappy/snappy-sinksource.cc");
|
|
|
|
config.file("snappy/snappy-c.cc");
|
|
|
|
config.cpp(true);
|
|
|
|
config.compile("libsnappy.a");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_lz4() {
|
|
|
|
let mut compiler = cc::Build::new();
|
|
|
|
|
|
|
|
compiler
|
|
|
|
.file("lz4/lib/lz4.c")
|
|
|
|
.file("lz4/lib/lz4frame.c")
|
|
|
|
.file("lz4/lib/lz4hc.c")
|
|
|
|
.file("lz4/lib/xxhash.c");
|
|
|
|
|
|
|
|
compiler.opt_level(3);
|
|
|
|
|
|
|
|
let target = env::var("TARGET").unwrap();
|
|
|
|
|
|
|
|
if &target == "i686-pc-windows-gnu" {
|
|
|
|
compiler.flag("-fno-tree-vectorize");
|
|
|
|
}
|
|
|
|
|
|
|
|
compiler.compile("liblz4.a");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_zstd() {
|
|
|
|
let mut compiler = cc::Build::new();
|
|
|
|
|
|
|
|
compiler.include("zstd/lib/");
|
|
|
|
compiler.include("zstd/lib/common");
|
|
|
|
compiler.include("zstd/lib/legacy");
|
|
|
|
|
|
|
|
let globs = &[
|
|
|
|
"zstd/lib/common/*.c",
|
|
|
|
"zstd/lib/compress/*.c",
|
|
|
|
"zstd/lib/decompress/*.c",
|
|
|
|
"zstd/lib/dictBuilder/*.c",
|
|
|
|
"zstd/lib/legacy/*.c",
|
|
|
|
];
|
|
|
|
|
|
|
|
for pattern in globs {
|
|
|
|
for path in glob::glob(pattern).unwrap() {
|
|
|
|
let path = path.unwrap();
|
|
|
|
compiler.file(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
compiler.opt_level(3);
|
|
|
|
compiler.extra_warnings(false);
|
|
|
|
|
|
|
|
compiler.define("ZSTD_LIB_DEPRECATED", Some("0"));
|
|
|
|
compiler.compile("libzstd.a");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_zlib() {
|
|
|
|
let mut compiler = cc::Build::new();
|
|
|
|
|
|
|
|
let globs = &["zlib/*.c"];
|
|
|
|
|
|
|
|
for pattern in globs {
|
|
|
|
for path in glob::glob(pattern).unwrap() {
|
|
|
|
let path = path.unwrap();
|
|
|
|
compiler.file(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
compiler.flag_if_supported("-Wno-implicit-function-declaration");
|
|
|
|
compiler.opt_level(3);
|
|
|
|
compiler.extra_warnings(false);
|
|
|
|
compiler.compile("libz.a");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_bzip2() {
|
|
|
|
let mut compiler = cc::Build::new();
|
|
|
|
|
|
|
|
compiler
|
|
|
|
.file("bzip2/blocksort.c")
|
|
|
|
.file("bzip2/bzlib.c")
|
|
|
|
.file("bzip2/compress.c")
|
|
|
|
.file("bzip2/crctable.c")
|
|
|
|
.file("bzip2/decompress.c")
|
|
|
|
.file("bzip2/huffman.c")
|
|
|
|
.file("bzip2/randtable.c");
|
|
|
|
|
|
|
|
compiler
|
|
|
|
.define("_FILE_OFFSET_BITS", Some("64"))
|
|
|
|
.define("BZ_NO_STDIO", None);
|
|
|
|
|
|
|
|
compiler.extra_warnings(false);
|
|
|
|
compiler.opt_level(3);
|
|
|
|
compiler.extra_warnings(false);
|
|
|
|
compiler.compile("libbz2.a");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn try_to_find_and_link_lib(lib_name: &str) -> bool {
|
|
|
|
if let Ok(lib_dir) = env::var(&format!("{}_LIB_DIR", lib_name)) {
|
|
|
|
println!("cargo:rustc-link-search=native={}", lib_dir);
|
|
|
|
let mode = match env::var_os(&format!("{}_STATIC", lib_name)) {
|
|
|
|
Some(_) => "static",
|
|
|
|
None => "dylib",
|
|
|
|
};
|
|
|
|
println!("cargo:rustc-link-lib={}={}", mode, lib_name.to_lowercase());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cxx_standard() -> String {
|
|
|
|
env::var("ROCKSDB_CXX_STD").map_or("-std=c++11".to_owned(), |cxx_std| {
|
|
|
|
if !cxx_std.starts_with("-std=") {
|
|
|
|
format!("-std={}", cxx_std)
|
|
|
|
} else {
|
|
|
|
cxx_std
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
println!("cargo:rerun-if-changed=build.rs");
|
|
|
|
|
|
|
|
bindgen_rocksdb();
|
|
|
|
|
|
|
|
if !try_to_find_and_link_lib("ROCKSDB") {
|
|
|
|
println!("cargo:rerun-if-changed=rocksdb/");
|
|
|
|
fail_on_empty_directory("rocksdb");
|
|
|
|
build_rocksdb();
|
|
|
|
}
|
|
|
|
if cfg!(feature = "snappy") && !try_to_find_and_link_lib("SNAPPY") {
|
|
|
|
println!("cargo:rerun-if-changed=snappy/");
|
|
|
|
fail_on_empty_directory("snappy");
|
|
|
|
build_snappy();
|
|
|
|
}
|
|
|
|
if cfg!(feature = "lz4") && !try_to_find_and_link_lib("LZ4") {
|
|
|
|
println!("cargo:rerun-if-changed=lz4/");
|
|
|
|
fail_on_empty_directory("lz4");
|
|
|
|
build_lz4();
|
|
|
|
}
|
|
|
|
if cfg!(feature = "zstd") && !try_to_find_and_link_lib("ZSTD") {
|
|
|
|
println!("cargo:rerun-if-changed=zstd/");
|
|
|
|
fail_on_empty_directory("zstd");
|
|
|
|
build_zstd();
|
|
|
|
}
|
|
|
|
if cfg!(feature = "zlib") && !try_to_find_and_link_lib("Z") {
|
|
|
|
println!("cargo:rerun-if-changed=zlib/");
|
|
|
|
fail_on_empty_directory("zlib");
|
|
|
|
build_zlib();
|
|
|
|
}
|
|
|
|
if cfg!(feature = "bzip2") && !try_to_find_and_link_lib("BZ2") {
|
|
|
|
println!("cargo:rerun-if-changed=bzip2/");
|
|
|
|
fail_on_empty_directory("bzip2");
|
|
|
|
build_bzip2();
|
|
|
|
}
|
|
|
|
}
|