|
| 1 | +// Copyright (c) 2025 Anatoly Ikorsky |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 |
| 4 | +// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT |
| 5 | +// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| 6 | +// option. All files in the project carrying such notice may not be copied, |
| 7 | +// modified, or distributed except according to those terms. |
| 8 | + |
| 9 | +#![cfg(all(feature = "test", unix))] |
| 10 | + |
| 11 | +use bindgen::builder; |
| 12 | +use cmake::Config; |
| 13 | +use subprocess::Exec; |
| 14 | + |
| 15 | +use std::{ |
| 16 | + env, |
| 17 | + fs::{copy, create_dir_all}, |
| 18 | + path::{Path, PathBuf}, |
| 19 | +}; |
| 20 | + |
| 21 | +const MYSQL_DIR: &str = "mysql-8.0.35"; |
| 22 | + |
| 23 | +const LIBSTRINGS: &str = "libstrings.a"; |
| 24 | +const LIBWRAPPER: &str = "libwrapper.a"; |
| 25 | + |
| 26 | +/// Returns mysql source path. |
| 27 | +fn download_mysql(out_dir: &Path) { |
| 28 | + const URL: &str = "https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.35.tar.gz"; |
| 29 | + { |
| 30 | + Exec::cmd("curl").arg("-s").arg("-L").arg(URL) |
| 31 | + | Exec::cmd("tar").arg("-xz").arg("-C").arg(out_dir) |
| 32 | + } |
| 33 | + .join() |
| 34 | + .unwrap(); |
| 35 | +} |
| 36 | + |
| 37 | +fn make_libstrings(mysql_src: &Path, libdir: &Path, out_dir: &Path) { |
| 38 | + println!("cargo:warning=Building libstrings.a"); |
| 39 | + let dst = Config::new(mysql_src) |
| 40 | + .define("FORCE_INSOURCE_BUILD", "1") |
| 41 | + .define("DOWNLOAD_BOOST", "1") |
| 42 | + .define("WITH_BOOST", out_dir) |
| 43 | + .build_target("strings") |
| 44 | + .build(); |
| 45 | + |
| 46 | + copy( |
| 47 | + dst.join("build") |
| 48 | + .join("archive_output_directory") |
| 49 | + .join(LIBSTRINGS), |
| 50 | + Path::new(libdir).join(LIBSTRINGS), |
| 51 | + ) |
| 52 | + .unwrap(); |
| 53 | +} |
| 54 | + |
| 55 | +fn make_libwrapper(mysql_src: &Path, libdir: &Path, out_dir: &Path) { |
| 56 | + println!("cargo:warning=Building libwrapper.a"); |
| 57 | + cc::Build::new() |
| 58 | + .file("wrapper.cc") |
| 59 | + .cpp(true) |
| 60 | + .include(out_dir.join("build").join("include")) |
| 61 | + .include(mysql_src.join("include")) |
| 62 | + .flag("-std=c++14") |
| 63 | + .cargo_metadata(false) |
| 64 | + .compile("wrapper"); |
| 65 | + copy(out_dir.join(LIBWRAPPER), Path::new(libdir).join(LIBWRAPPER)).unwrap(); |
| 66 | +} |
| 67 | + |
| 68 | +#[allow(dead_code)] |
| 69 | +fn gen_bindings(mysql_src: &Path, out_dir: &Path) { |
| 70 | + let builder = builder() |
| 71 | + .header("wrapper.hh") |
| 72 | + .clang_arg(format!( |
| 73 | + "-I{}", |
| 74 | + out_dir.join("build").join("include").display() |
| 75 | + )) |
| 76 | + .clang_arg(format!("-I{}", mysql_src.join("include").display())) |
| 77 | + .clang_arg("-std=c++14") |
| 78 | + .clang_arg("-stdlib=libc++") |
| 79 | + .allowlist_recursively(true) |
| 80 | + .allowlist_type("decimal_t") |
| 81 | + .allowlist_function("c_string2decimal") |
| 82 | + .allowlist_function("c_decimal2string") |
| 83 | + .allowlist_function("c_decimal2bin") |
| 84 | + .allowlist_function("c_bin2decimal") |
| 85 | + .allowlist_function("c_decimal_bin_size") |
| 86 | + .derive_debug(false) |
| 87 | + .use_core() |
| 88 | + .generate_comments(false); |
| 89 | + let bindings = builder |
| 90 | + .generate() |
| 91 | + .expect("unable to generate bindings for libstrings"); |
| 92 | + bindings |
| 93 | + .write_to_file( |
| 94 | + Path::new("src") |
| 95 | + .join("binlog") |
| 96 | + .join("decimal") |
| 97 | + .join("test") |
| 98 | + .join("libstrings_bindings.rs"), |
| 99 | + ) |
| 100 | + .expect("Couldn't write bindings!"); |
| 101 | +} |
| 102 | + |
| 103 | +pub fn build_test_libs() { |
| 104 | + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); |
| 105 | + let mysql_src = out_dir.join(MYSQL_DIR); |
| 106 | + let libdir = Path::new("lib") |
| 107 | + .join(Path::new(&env::var("CARGO_CFG_TARGET_OS").unwrap())) |
| 108 | + .join(env::var("CARGO_CFG_TARGET_ARCH").unwrap()); |
| 109 | + |
| 110 | + create_dir_all(&libdir).unwrap(); |
| 111 | + |
| 112 | + if !libdir.join(LIBSTRINGS).exists() || !libdir.join(LIBWRAPPER).exists() { |
| 113 | + if !mysql_src.exists() { |
| 114 | + println!("cargo:warning=Downloading MySql source distribution"); |
| 115 | + download_mysql(&out_dir); |
| 116 | + } |
| 117 | + make_libstrings(&mysql_src, &libdir, &out_dir); |
| 118 | + make_libwrapper(&mysql_src, &libdir, &out_dir); |
| 119 | + // uncomment if mysql-server version bumped |
| 120 | + // gen_bindings(&mysql_src, &out_dir); |
| 121 | + } |
| 122 | + |
| 123 | + println!("cargo:rustc-link-search=native={}", libdir.display()); |
| 124 | + println!("cargo:rustc-link-lib=wrapper"); |
| 125 | + println!("cargo:rustc-link-lib=strings"); |
| 126 | + if cfg!(target_os = "macos") { |
| 127 | + println!("cargo:rustc-link-lib=c++"); |
| 128 | + } |
| 129 | +} |
0 commit comments