#[cfg(not(feature = "static-link"))] mod imp { pub fn build() { rocksdb(); } #[cfg(unix)] fn rocksdb() { println!("cargo:rustc-link-lib=dylib=rocksdb"); } #[cfg(windows)] fn rocksdb() { println!("cargo:rustc-link-lib=rocksdb"); for lib in env!("LIB").split(";") { if !lib.is_empty() { println!("cargo:rustc-link-search=native={}", lib); } } println!("cargo:rustc-link-lib=static=shlwapi"); println!("cargo:rustc-link-lib=static=rpcrt4"); } } #[cfg(feature = "static-link")] mod imp { use std::env; use std::fs; use std::path::Path; use std::process::Command; pub fn build() { println!("cargo:warning=static link feature enabled, it'll take minutes to finish compiling..."); #[cfg(feature = "snappy")] snappy(); #[cfg(feature = "zlib")] zlib(); #[cfg(feature = "bzip2")] bzip2(); #[cfg(feature = "lz4")] lz4(); #[cfg(feature = "zstd")] zstd(); rocksdb(); } #[cfg(feature = "snappy")] fn snappy() { if !Path::new("snappy/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "snappy"]) .status(); } // cmake can only have 1 run in 1 crate // or else the `build` directory will be overwritten let out_dir = env::var("OUT_DIR").unwrap(); let this_out_dir = Path::new(&out_dir).join("snappy_out"); let _ = fs::create_dir(&this_out_dir); let dst = cmake::Config::new("snappy") .define("CMAKE_POSITION_INDEPENDENT_CODE", "ON") .build_target("snappy") .out_dir(this_out_dir) .very_verbose(true) .uses_cxx11() .build(); println!("cargo:rustc-link-search=native={}/build/", dst.display()); println!("cargo:rustc-link-lib=static=snappy"); } #[cfg(feature = "zlib")] fn zlib() { if !Path::new("zlib/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "zlib"]) .status(); } Command::new(env::current_dir().unwrap().join("zlib/configure")) .current_dir(env::current_dir().unwrap().join("zlib")) .arg("--static") .output() .expect("failed to execute ./configure"); let mut cfg = ::cc::Build::new(); cfg.warnings(false); cfg.include("zlib"); // TODO: borrow following list form Makefile let filez = "adler32.c crc32.c deflate.c infback.c inffast.c inflate.c inftrees.c trees.c zutil.c"; let fileg = "compress.c uncompr.c gzclose.c gzlib.c gzread.c gzwrite.c"; for file in filez.split(" ") { cfg.file(format!("zlib/{}", file)); } for file in fileg.split(" ") { cfg.file(format!("zlib/{}", file)); } cfg.pic(true); cfg.opt_level(2); cfg.compile("libz.a"); } // Yes, copied from alexcrichton/bzip2-rs #[cfg(feature = "bzip2")] fn bzip2() { if !Path::new("bzip2/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "bzip2"]) .status(); } let mut cfg = ::cc::Build::new(); if cfg!(windows) { cfg.define("_WIN32", None); cfg.define("BZ_EXPORT", None); } cfg.include("bzip2") .define("_FILE_OFFSET_BITS", Some("64")) .define("BZ_NO_STDIO", None) .opt_level(2) .warnings(false) .file("bzip2/blocksort.c") .file("bzip2/huffman.c") .file("bzip2/crctable.c") .file("bzip2/randtable.c") .file("bzip2/compress.c") .file("bzip2/decompress.c") .file("bzip2/bzlib.c") .compile("libbz2.a"); } #[cfg(feature = "lz4")] fn lz4() { if !Path::new("lz4/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "lz4"]) .status(); } ::cc::Build::new() .warnings(false) .include("lz4/lib") .opt_level(2) .pic(true) .file("lz4/lib/lz4.c") .file("lz4/lib/lz4frame.c") .file("lz4/lib/lz4hc.c") .file("lz4/lib/xxhash.c") .compile("liblz4.a"); } #[cfg(feature = "zstd")] fn zstd() { if !Path::new("zstd/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "zstd"]) .status(); } let files = [ "zstd/lib/common/entropy_common.c", "zstd/lib/common/error_private.c", "zstd/lib/common/fse_decompress.c", "zstd/lib/common/pool.c", "zstd/lib/common/threading.c", "zstd/lib/common/xxhash.c", "zstd/lib/common/zstd_common.c", "zstd/lib/compress/fse_compress.c", "zstd/lib/compress/huf_compress.c", "zstd/lib/compress/zstd_compress.c", "zstd/lib/compress/zstdmt_compress.c", "zstd/lib/decompress/huf_decompress.c", "zstd/lib/decompress/zstd_decompress.c", "zstd/lib/dictBuilder/cover.c", "zstd/lib/dictBuilder/divsufsort.c", "zstd/lib/dictBuilder/zdict.c", ]; ::cc::Build::new() .define("ZSTD_LEGACY_SUPPORT", Some("0")) .include("zstd/lib") .include("zstd/lib/common") .opt_level(3) .warnings(false) .files(&files) .compile("libzstd.a"); } fn rocksdb() { if !Path::new("rocksdb/.git").exists() { let _ = Command::new("git") .args(&["submodule", "update", "--init", "rocksdb"]) .status(); } let mut cfg = cmake::Config::new("rocksdb"); #[cfg(feature = "snappy")] { let src = std::env::current_dir().unwrap(); let out_dir = env::var("OUT_DIR").unwrap(); let snappy_out_dir = Path::new(&out_dir).join("snappy_out"); // FIXME: how to use cmake's define? cfg.cxxflag("-DSNAPPY"); cfg.cxxflag(format!("-I{}", src.join("snappy").display())); // snappy-stubs-public.h cfg.cxxflag(format!("-I{}", snappy_out_dir.join("build").display())); } #[cfg(feature = "zlib")] { cfg.cxxflag("-DZLIB"); cfg.cxxflag("-Izlib"); } #[cfg(feature = "bzip2")] { cfg.cxxflag("-DBZIP2"); cfg.cxxflag("-Ibzip2"); } #[cfg(feature = "lz4")] { cfg.cxxflag("-DLZ4"); cfg.cxxflag("-Ilz4/lib"); } #[cfg(feature = "zstd")] { cfg.cxxflag("-DZSTD"); cfg.cxxflag("-Izstd/lib"); } let dst = cfg // .define("CMAKE_BUILD_TYPE", "Release") // RelWithDebInfo .define("WITH_GFLAGS", "OFF") .build_target("rocksdb") .build(); println!("cargo:rustc-link-search=native={}/build/", dst.display()); println!("cargo:rustc-link-lib=static=rocksdb"); } } fn main() { if cfg!(not(target_pointer_width = "64")) { panic!("only 64 bit system supported"); } println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=src/c.rs"); println!("cargo:rerun-if-changed=src/lib.rs"); imp::build(); let mut build = ::cc::Build::new(); #[cfg(feature = "static-link")] build.include("rocksdb/include"); #[cfg(unix)] { build.flag("-std=c++14"); build.flag("-fno-rtti"); } #[cfg(windows)] { let lib = vcpkg::Config::new() .emit_includes(true) .find_package("rocksdb") .unwrap(); for inc in lib.include_paths { build.include(inc); } } build .cpp(true) .pic(true) .opt_level(2) .warnings(false) .include(".") .file("rocks/cache.cc") .file("rocks/comparator.cc") .file("rocks/convenience.cc") .file("rocks/db.cc") .file("rocks/db_dump_tool.cc") .file("rocks/env.cc") .file("rocks/filter_policy.cc") .file("rocks/iostats_context.cc") .file("rocks/iterator.cc") .file("rocks/metadata.cc") .file("rocks/options.cc") .file("rocks/perf_context.cc") .file("rocks/perf_level.cc") .file("rocks/rate_limiter.cc") .file("rocks/slice.cc") .file("rocks/snapshot.cc") .file("rocks/sst_file_writer.cc") .file("rocks/statistics.cc") .file("rocks/status.cc") .file("rocks/table.cc") .file("rocks/table_properties.cc") .file("rocks/transaction_log.cc") .file("rocks/universal_compaction.cc") .file("rocks/util.cc") .file("rocks/write_batch.cc") .file("rocks/write_buffer_manager.cc") .file("rocks/debug.cc") .file("rocks/listener.cc") .file("rocks/compaction_job_stats.cc") .file("rocks/thread_status.cc") .file("rocks/options_util.cc") .compile("librocksdb_wrap"); }