diff --git a/Cargo.toml b/Cargo.toml index d11f8ec..9fd4184 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,3 +52,6 @@ todo = "warn" unimplemented = "warn" use_self = "warn" or_fun_call = "warn" + +[build-dependencies] +bindgen = "0.73.2" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..e6ae3bd --- /dev/null +++ b/build.rs @@ -0,0 +1,37 @@ +//! Generates `engine_api.rs` from the arcus-memcached headers at the crate root. + +use std::env; +use std::error::Error; +use std::path::{Path, PathBuf}; + +const ENGINE_HEADER: &str = "include/memcached/engine.h"; +const CONFIG_FILES: [&str; 2] = ["config.h", "config_static.h"]; +const COPY_HINT: &str = "Copy config.h, config_static.h and include/memcached/*.h from a \ + configured arcus-memcached tree to the crate root."; + +fn main() -> Result<(), Box> { + println!("cargo:rerun-if-changed=include"); + for name in CONFIG_FILES { + println!("cargo:rerun-if-changed={name}"); + } + + for path in [ENGINE_HEADER].iter().chain(&CONFIG_FILES) { + if !Path::new(path).is_file() { + return Err(format!("{path} is missing. {COPY_HINT}").into()); + } + } + + let out = PathBuf::from(env::var("OUT_DIR")?).join("engine_api.rs"); + + bindgen::Builder::default() + .header(ENGINE_HEADER) + .clang_arg("-Iinclude") + .clang_arg("-I.") + .clang_args(["-include", "config.h"]) + .allowlist_file(".*memcached/.*\\.h") + .generate() + .map_err(|e| format!("{}. {COPY_HINT}", e.to_string().trim_end()))? + .write_to_file(out)?; + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index b93cf3f..69aaf28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +mod memcached; + pub fn add(left: u64, right: u64) -> u64 { left + right } diff --git a/src/memcached.rs b/src/memcached.rs new file mode 100644 index 0000000..751146f --- /dev/null +++ b/src/memcached.rs @@ -0,0 +1,3 @@ +//! The interface memcached gives an extension and its engine. + +pub mod ffi; diff --git a/src/memcached/ffi.rs b/src/memcached/ffi.rs new file mode 100644 index 0000000..3caf55e --- /dev/null +++ b/src/memcached/ffi.rs @@ -0,0 +1,19 @@ +//! Raw bindings to the arcus-memcached headers, generated by `build.rs`. + +// Generated code: which of these fire depends on the headers, so `expect` would turn a header +// update into an "unfulfilled expectation" warning. +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_qualifications, + clippy::all, + clippy::nursery, + clippy::pedantic, + clippy::restriction, + reason = "bindgen output: it keeps the C names, emits every declaration whether used or \ + not, and carries its own `#[allow]`s" +)] + +include!(concat!(env!("OUT_DIR"), "/engine_api.rs"));