use bindgen::builder;
use cmake::Config;
use subprocess::Exec;
use std::{
env,
fs::{copy, create_dir_all},
path::{Path, PathBuf},
};
const MYSQL_DIR: &str = "mysql-8.0.35";
const LIBSTRINGS: &str = "libstrings.a";
const LIBWRAPPER: &str = "libwrapper.a";
fn download_mysql(out_dir: &Path) {
const URL: &str = "https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.35.tar.gz";
{
Exec::cmd("curl").arg("-s").arg("-L").arg(URL)
| Exec::cmd("tar").arg("-xz").arg("-C").arg(out_dir)
}
.join()
.unwrap();
}
fn make_libstrings(mysql_src: &Path, libdir: &Path, out_dir: &Path) {
println!("cargo:warning=Building libstrings.a");
let dst = Config::new(mysql_src)
.define("FORCE_INSOURCE_BUILD", "1")
.define("DOWNLOAD_BOOST", "1")
.define("WITH_BOOST", out_dir)
.build_target("strings")
.build();
copy(
dst.join("build")
.join("archive_output_directory")
.join(LIBSTRINGS),
Path::new(libdir).join(LIBSTRINGS),
)
.unwrap();
}
fn make_libwrapper(mysql_src: &Path, libdir: &Path, out_dir: &Path) {
println!("cargo:warning=Building libwrapper.a");
cc::Build::new()
.file("wrapper.cc")
.cpp(true)
.include(out_dir.join("build").join("include"))
.include(mysql_src.join("include"))
.flag("-std=c++14")
.cargo_metadata(false)
.compile("wrapper");
copy(out_dir.join(LIBWRAPPER), Path::new(libdir).join(LIBWRAPPER)).unwrap();
}
#[allow(dead_code)]
fn gen_bindings(mysql_src: &Path, out_dir: &Path) {
let builder = builder()
.header("wrapper.hh")
.clang_arg(format!(
"-I{}",
out_dir.join("build").join("include").display()
))
.clang_arg(format!("-I{}", mysql_src.join("include").display()))
.clang_arg("-std=c++14")
.clang_arg("-stdlib=libc++")
.allowlist_recursively(true)
.allowlist_type("decimal_t")
.allowlist_function("c_string2decimal")
.allowlist_function("c_decimal2string")
.allowlist_function("c_decimal2bin")
.allowlist_function("c_bin2decimal")
.allowlist_function("c_decimal_bin_size")
.derive_debug(false)
.use_core()
.generate_comments(false);
let bindings = builder
.generate()
.expect("unable to generate bindings for libstrings");
bindings
.write_to_file(
Path::new("src")
.join("binlog")
.join("decimal")
.join("test")
.join("libstrings_bindings.rs"),
)
.expect("Couldn't write bindings!");
}
fn main() {
if cfg!(all(feature = "test", unix)) {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let mysql_src = out_dir.join(MYSQL_DIR);
let libdir = Path::new("lib")
.join(Path::new(&env::var("CARGO_CFG_TARGET_OS").unwrap()))
.join(env::var("CARGO_CFG_TARGET_ARCH").unwrap());
create_dir_all(&libdir).unwrap();
if !libdir.join(LIBSTRINGS).exists() || !libdir.join(LIBWRAPPER).exists() {
if !mysql_src.exists() {
println!("cargo:warning=Downloading MySql source distribution");
download_mysql(&out_dir);
}
make_libstrings(&mysql_src, &libdir, &out_dir);
make_libwrapper(&mysql_src, &libdir, &out_dir);
}
println!("cargo:rustc-link-search=native={}", libdir.display());
println!("cargo:rustc-link-lib=wrapper");
println!("cargo:rustc-link-lib=strings");
if cfg!(target_os = "macos") {
println!("cargo:rustc-link-lib=c++");
}
}
}