diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e7b64989..2d2a2c05a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,10 @@ option(HAVE_DEBUG_MM "debugging oriented memory management disabled by default" option(COVERAGE "code coverage" OFF) option(HAVE_RUST "rust bindings not built by default" OFF) +if(HAVE_RUST) + option(RUST_VERBOSE_BUILD "pass -vv to cargo compilation" OFF) +endif() + if(BUILD_AND_INSTALL_CHECK) # (simms) What follows is a crime against build systems as we run the build/install # for the check library up front, during the planning phase. @@ -148,18 +152,21 @@ endif(CHECK_FOUND) find_package(Threads) + +# where to find include files +include_directories( + ${include_directories} + "${PROJECT_BINARY_DIR}" + "include") + if(HAVE_RUST) enable_language(Rust) include(CMakeCargo) add_subdirectory(rust) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHAVE_RUST=1") endif() -# where to find include files -include_directories(${include_directories} - "${PROJECT_BINARY_DIR}" - "include") - ################### # things to build # ################### diff --git a/cmake/CMakeCargo.cmake b/cmake/CMakeCargo.cmake index 975b0ccd2..81920f8e7 100644 --- a/cmake/CMakeCargo.cmake +++ b/cmake/CMakeCargo.cmake @@ -5,7 +5,7 @@ function(cargo_set_lib_target LIB_NAME) else() set(LIB_TARGET "i686-pc-windows-msvc" PARENT_SCOPE) endif() - elseif(ANDROID) + elseif(ANDROID) if(ANDROID_SYSROOT_ABI STREQUAL "x86") set(LIB_TARGET "i686-linux-android" PARENT_SCOPE) elseif(ANDROID_SYSROOT_ABI STREQUAL "x86_64") @@ -16,10 +16,10 @@ function(cargo_set_lib_target LIB_NAME) set(LIB_TARGET "aarch64-linux-android" PARENT_SCOPE) endif() elseif(IOS) - set(LIB_TARGET "universal" PARENT_SCOPE) + set(LIB_TARGET "universal" PARENT_SCOPE) elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin) set(LIB_TARGET "x86_64-apple-darwin" PARENT_SCOPE) - else() + else() if(RUST_USE_MUSL) set(RUST_LIBC_NAME "musl") else() @@ -58,12 +58,16 @@ function(cargo_build) get_filename_component(SHARED_LIB_FILE "${LIB_BASE_DIR}/${SHARED_LIB_FNAME}" ABSOLUTE) get_filename_component(STATIC_LIB_FILE "${LIB_BASE_DIR}/${STATIC_LIB_FNAME}" ABSOLUTE) - if(IOS) - set(CARGO_ARGS "lipo") - else() - set(CARGO_ARGS "build") - list(APPEND CARGO_ARGS "--target" ${LIB_TARGET}) - endif() + if(IOS) + set(CARGO_ARGS "lipo") + else() + set(CARGO_ARGS "build") + list(APPEND CARGO_ARGS "--target" ${LIB_TARGET}) + endif() + + if(RUST_VERBOSE_BUILD) + list(APPEND CARGO_ARGS "-vv") + endif() if(${LIB_BUILD_TYPE} STREQUAL "release") list(APPEND CARGO_ARGS "--release") diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 0dd65e2f3..5ae870301 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -79,6 +79,7 @@ name = "cc_binding" version = "0.1.0" dependencies = [ "bindgen 0.37.4 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/rust/cc_binding/Cargo.toml b/rust/cc_binding/Cargo.toml index 03d5ddc51..0ad06b1df 100644 --- a/rust/cc_binding/Cargo.toml +++ b/rust/cc_binding/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Jonathan Simms "] [build-dependencies] bindgen = "0.37.0" +failure = "~0.1.1" [lib] name = "cc_binding" diff --git a/rust/cc_binding/build.rs b/rust/cc_binding/build.rs index 9960c66d1..4e6dc243d 100644 --- a/rust/cc_binding/build.rs +++ b/rust/cc_binding/build.rs @@ -1,11 +1,19 @@ extern crate bindgen; +#[macro_use] +extern crate failure; use std::env; use std::fs; use std::io; -use std::path::PathBuf; +use std::io::BufReader; use std::io::prelude::*; +use std::ffi::OsString; use std::os::unix::fs as unix_fs; +use std::path::Path; +use std::path::PathBuf; +use std::result; + +type Result = result::Result; fn get_cmake_binary_dir() -> io::Result { // this file is written by cmake on each run, updated with the location of @@ -17,6 +25,28 @@ fn get_cmake_binary_dir() -> io::Result { Ok(String::from(buf.trim_right())) } +const CMAKE_CACHE: &str = "CMakeCache.txt"; +const CCOMMON_BINARY_DIR_KEY: &str = "ccommon_BINARY_DIR:STATIC"; + +fn get_cmake_cache_value(binary_dir: &Path, key: &str) -> Result> { + let cache_path = binary_dir.join(CMAKE_CACHE); + let fp = BufReader::new(fs::File::open(cache_path)?); + + for x in fp.lines() { + let line = x?; + let needle = format!("{}=", key); + if line.starts_with(&needle[..]) { + if let Some(v) = line.rsplit("=").take(1).last() { + return Ok(Some(v.to_owned())) + } else { + bail!("bad line: {:#?}", line); + } + } + } + + Ok(None) +} + fn main() { println!("cargo:rustc-link-lib=static=ccommon-1.2.0"); @@ -32,17 +62,26 @@ fn main() { let mut config_h_dir = cbd.clone(); config_h_dir.push("ccommon"); - let mut lib_dir = cbd.clone(); - lib_dir.push("lib"); + let lib_dir: String = { + let cbd = get_cmake_cache_value(&cbd, CCOMMON_BINARY_DIR_KEY) + .map(|o| o.map(OsString::from)) + .unwrap() + .expect( + format!("could not find {} in {}", CCOMMON_BINARY_DIR_KEY, CMAKE_CACHE).as_ref() + ); + + let cbd = Path::new(&cbd); + cbd.join("lib").to_str().unwrap().to_string() + }; - println!("cargo:rustc-link-search=native={}", lib_dir.to_str().unwrap()); + println!("cargo:rustc-link-search=native={}", lib_dir); let bindings = bindgen::Builder::default() .clang_args(vec![ "-I", include_path.to_str().unwrap(), "-I", config_h_dir.to_str().unwrap(), "-I", cbd.to_str().unwrap(), - "-L", lib_dir.to_str().unwrap(), + "-L", &lib_dir, ]) .header("wrapper.h") .blacklist_type("max_align_t") // https://github.com/rust-lang-nursery/rust-bindgen/issues/550 diff --git a/rust/ccommon_rs/src/bstring.rs b/rust/ccommon_rs/src/bstring.rs index b7eef4fb4..f8588d608 100644 --- a/rust/ccommon_rs/src/bstring.rs +++ b/rust/ccommon_rs/src/bstring.rs @@ -33,6 +33,7 @@ use std::mem; use std::ops::{Deref, DerefMut}; use std::slice; use std::str; +use std::borrow::BorrowMut; pub type CCbstring = bind::bstring; @@ -87,7 +88,7 @@ impl BStr { } #[inline] - fn as_ptr(&self) -> *mut CCbstring { + pub fn as_ptr(&self) -> *mut CCbstring { self as *const _ as *mut _ } } @@ -108,6 +109,30 @@ impl DerefMut for BStr { } } +impl AsRef for BStr { + fn as_ref(&self) -> &CCbstring { + unsafe { &*self.as_ptr() } + } +} + +impl AsMut for BStr { + fn as_mut(&mut self) -> &mut CCbstring { + unsafe { &mut *(self.as_ptr() as *mut _)} + } +} + +impl Borrow for BStr { + fn borrow(&self) -> &CCbstring { + unsafe { &*self.as_ptr() } + } +} + +impl BorrowMut for BStr { + fn borrow_mut(&mut self) -> &mut CCbstring { + unsafe { &mut *(self.as_ptr() as *mut _)} + } +} + impl ToOwned for BStr { type Owned = BString; @@ -239,6 +264,7 @@ impl BString { /// /// This method will panic if `src.len() != self.len()` #[inline] + #[allow(dead_code)] fn copy_from_slice(&mut self, src: &[u8]) { assert_eq!(src.len(), self.len()); (&mut (**self)).copy_from_slice(&src[..]); @@ -446,7 +472,7 @@ mod test { { let mut c = Cursor::new(&mut x[..]); let f = "fantastic".as_bytes(); - c.seek(SeekFrom::End(-9)); + c.seek(SeekFrom::End(-9)).unwrap(); let sz = c.write(&f[..]).unwrap(); assert_eq!(sz, f.len());