use std::env;
use std::path::PathBuf;
use std::process::Command;
const INCLUDE_PATH: &str = "nng/include";
#[cfg(feature = "build-bindgen")]
fn generate_lib() {
println!("Generates bindings...");
#[derive(Debug)]
struct ParseCallbacks;
impl bindgen::callbacks::ParseCallbacks for ParseCallbacks {
fn int_macro(&self, name: &str, _value: i64) -> Option<bindgen::callbacks::IntKind> {
if name.starts_with("NNG") {
Some(bindgen::callbacks::IntKind::Int)
} else {
None
}
}
}
use std::path::PathBuf;
const PREPEND_LIB: &'static str = "
#![no_std]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
pub const NNG_OPT_SOCKNAME: &[u8] = b\"socket-name\0\";
pub const NNG_OPT_RAW: &[u8] = b\"raw\0\";
pub const NNG_OPT_PROTO: &[u8] = b\"protocol\0\";
pub const NNG_OPT_PROTONAME: &[u8] = b\"protocol-name\0\";
pub const NNG_OPT_PEER: &[u8] = b\"peer\0\";
pub const NNG_OPT_PEERNAME: &[u8] = b\"peer-name\0\";
pub const NNG_OPT_RECVBUF: &[u8] = b\"recv-buffer\0\";
pub const NNG_OPT_SENDBUF: &[u8] = b\"send-buffer\0\";
pub const NNG_OPT_RECVFD: &[u8] = b\"recv-fd\0\";
pub const NNG_OPT_SENDFD: &[u8] = b\"send-fd\0\";
pub const NNG_OPT_RECVTIMEO: &[u8] = b\"recv-timeout\0\";
pub const NNG_OPT_SENDTIMEO: &[u8] = b\"send-timeout\0\";
pub const NNG_OPT_LOCADDR: &[u8] = b\"local-address\0\";
pub const NNG_OPT_REMADDR: &[u8] = b\"remote-address\0\";
pub const NNG_OPT_URL: &[u8] = b\"url\0\";
pub const NNG_OPT_MAXTTL: &[u8] = b\"ttl-max\0\";
pub const NNG_OPT_RECVMAXSZ: &[u8] = b\"recv-size-max\0\";
pub const NNG_OPT_RECONNMINT: &[u8] = b\"reconnect-time-min\0\";
pub const NNG_OPT_RECONNMAXT: &[u8] = b\"reconnect-time-max\0\";
pub const NNG_OPT_PEER_GID: &[u8] = b\"ipc:peer-gid\0\";
pub const NNG_OPT_PEER_PID: &[u8] = b\"ipc:peer-pid\0\";
pub const NNG_OPT_PEER_UID: &[u8] = b\"ipc:peer-uid\0\";
pub const NNG_OPT_PEER_ZONEID: &[u8] = b\"ipc:peer-zoneid\0\";
pub const NNG_OPT_SUB_SUBSCRIBE: &[u8] = b\"sub:subscribe\0\";
pub const NNG_OPT_SUB_UNSUBSCRIBE: &[u8] = b\"sub:unsubscribe\0\";
pub const NNG_OPT_SUB_PREFNEW: &[u8] = b\"sub:prefnew\0\";
pub const NNG_OPT_PAIR1_POLY: &[u8] = b\"pair1:polyamorous\0\";
pub const NNG_OPT_REQ_RESENDTIME: &[u8] = b\"req:resend-time\0\";
pub const NNG_OPT_REQ_RESENDTICK: &[u8] = b\"req:resend-tick\0\";
pub const NNG_OPT_SURVEYOR_SURVEYTIME: &[u8] = b\"surveyor:survey-time\0\";
pub const NNG_OPT_TLS_AUTH_MODE: &[u8] = b\"tls-authmode\0\";
pub const NNG_OPT_TLS_CA_FILE: &[u8] = b\"tls-ca-file\0\";
pub const NNG_OPT_TLS_CERT_KEY_FILE: &[u8] = b\"tls-cert-key-file\0\";
pub const NNG_OPT_TLS_CONFIG: &[u8] = b\"tls-config\0\";
pub const NNG_OPT_TLS_SERVER_NAME: &[u8] = b\"tls-server-name\0\";
pub const NNG_OPT_TLS_VERIFIED: &[u8] = b\"tls-verified\0\";
pub const NNG_OPT_TLS_PEER_CN: &[u8] = b\"tls-peer-cn\0\";
pub const NNG_OPT_TLS_PEER_ALT_NAMES: &[u8] = b\"tls-peer-alt-names\0\";
pub const NNG_FLAG_ALLOC: core::ffi::c_int = 1;
pub const NNG_FLAG_NONBLOCK: core::ffi::c_int = 2;
";
let out = PathBuf::new().join("src").join("lib.rs");
let mut builder = bindgen::Builder::default();
let paths = [
"nng.h",
"protocol/bus0/bus.h",
"protocol/pair0/pair.h",
"protocol/pair1/pair.h",
"protocol/pipeline0/pull.h",
"protocol/pipeline0/push.h",
"protocol/pubsub0/pub.h",
"protocol/pubsub0/sub.h",
"protocol/reqrep0/rep.h",
"protocol/reqrep0/req.h",
"protocol/survey0/respond.h",
"protocol/survey0/survey.h",
"transport/inproc/inproc.h",
"transport/ipc/ipc.h",
"transport/tcp/tcp.h",
"transport/tls/tls.h",
"transport/ws/websocket.h",
"supplemental/http/http.h",
"supplemental/tls/tls.h",
"supplemental/util/platform.h",
];
for path in paths {
builder = builder.header(format!("{INCLUDE_PATH}/nng/{path}"));
}
let bindings = builder
.raw_line(PREPEND_LIB)
.ctypes_prefix("core::ffi")
.use_core()
.generate_comments(false)
.layout_tests(false)
.size_t_is_usize(true)
.sort_semantically(true)
.merge_extern_blocks(true)
.default_enum_style(bindgen::EnumVariation::ModuleConsts)
.allowlist_type("nng.+")
.allowlist_function("nng.+")
.clang_arg(format!("-I{INCLUDE_PATH}"))
.parse_callbacks(Box::new(ParseCallbacks))
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out)
.expect("Couldn't write bindings!");
}
#[cfg(not(feature = "build-bindgen"))]
fn generate_lib() {}
fn get_android_vars() -> Option<(PathBuf, &'static str)> {
if let Ok(android_ndk) = env::var("ANDROID_NDK_HOME") {
let mut toolchain_file = PathBuf::new();
toolchain_file.push(android_ndk);
toolchain_file.push("build");
toolchain_file.push("cmake");
toolchain_file.push("android.toolchain.cmake");
let target = env::var("TARGET").unwrap();
let abi = match target.as_str() {
"armv7-linux-androideabi" => "armeabi-v7a",
"aarch64-linux-android" => "arm64-v8a",
"i686-linux-android" => "x86",
"x86_64-linux-android" => "x86_64",
_ => return None,
};
Some((toolchain_file, abi))
} else {
None
}
}
fn set_cmake_define_if_present(config: &mut cmake::Config, name: &str) {
if let Ok(value) = env::var(name) {
config.define(name, value);
} else if let Ok(value) = env::var(format!("CARGO_NDK_{}", name)) {
config.define(name, value);
} else {
println!("cargo:warning=Unable to find Android env variable '{}'. Hope for good default...", name);
}
}
#[cfg(feature = "tls")]
fn build_mbedtls(nng: &mut cmake::Config, is_ninja: bool) {
const MBEDTLS: &str = "mbedtls-2.28.9";
let mut config = cmake::Config::new(MBEDTLS);
if let Some((toolchain_file, abi)) = get_android_vars() {
config.define("CMAKE_TOOLCHAIN_FILE", toolchain_file);
config.define("ANDROID_ABI", abi);
set_cmake_define_if_present(&mut config, "ANDROID_PLATFORM");
set_cmake_define_if_present(&mut config, "ANDROID_STL");
set_cmake_define_if_present(&mut config, "ANDROID_ARM_MODE");
set_cmake_define_if_present(&mut config, "ANDROID_ARM_NEON");
}
if is_ninja {
config.generator("Ninja");
}
config.define("ENABLE_PROGRAMS", "OFF");
config.define("ENABLE_TESTING", "OFF");
let dest = config.build();
nng.define("MBEDTLS_ROOT_DIR", &dest);
println!("cargo:rustc-link-lib=static=mbedcrypto");
println!("cargo:rustc-link-lib=static=mbedtls");
println!("cargo:rustc-link-lib=static=mbedx509");
println!("cargo:rustc-link-search=native={}", dest.as_path().join("lib").display());
#[cfg(target_os = "linux")]
println!("cargo:rustc-link-search=native={}", dest.as_path().join("lib64").display());
}
fn build() {
let abs_include =
std::fs::canonicalize(INCLUDE_PATH).expect("To get absolute path to brotlie include");
let is_ninja = Command::new("ninja")
.arg("--version")
.status()
.map(|status| status.success())
.unwrap_or(false);
println!("cargo:include={}", abs_include.display());
let mut config = cmake::Config::new("nng");
if let Some((toolchain_file, abi)) = get_android_vars() {
config.define("CMAKE_TOOLCHAIN_FILE", toolchain_file);
config.define("ANDROID_ABI", abi);
set_cmake_define_if_present(&mut config, "ANDROID_PLATFORM");
set_cmake_define_if_present(&mut config, "ANDROID_STL");
set_cmake_define_if_present(&mut config, "ANDROID_ARM_MODE");
set_cmake_define_if_present(&mut config, "ANDROID_ARM_NEON");
}
if is_ninja {
config.generator("Ninja");
}
config.define("NNG_TESTS", "OFF");
config.define("NNG_ENABLE_COMPAT", "OFF");
config.define("NNG_TRANSPORT_FDC", "OFF");
config.define("NNG_ENABLE_COVERAGE", "OFF");
#[cfg(not(feature = "stats"))]
config.define("NNG_ENABLE_STATS", "OFF");
#[cfg(feature = "stats")]
config.define("NNG_ENABLE_STATS", "ON");
#[cfg(not(feature = "http"))]
config.define("NNG_ENABLE_HTTP", "OFF");
#[cfg(feature = "http")]
config.define("NNG_ENABLE_HTTP", "ON");
#[cfg(not(feature = "websocket"))]
{
config.define("NNG_TRANSPORT_WS", "OFF");
config.define("NNG_TRANSPORT_WSS", "OFF");
}
#[cfg(feature = "websocket")]
{
config.define("NNG_TRANSPORT_WS", "ON");
#[cfg(feature = "tls")]
config.define("NNG_TRANSPORT_WSS", "ON");
}
#[cfg(not(feature = "tls"))]
{
config.define("NNG_TRANSPORT_TLS", "OFF");
config.define("NNG_ENABLE_TLS", "OFF");
}
#[cfg(feature = "tls")]
{
build_mbedtls(&mut config, is_ninja);
config.define("NNG_TRANSPORT_TLS", "ON");
config.define("NNG_ENABLE_TLS", "ON");
}
println!("cargo:rustc-link-lib=static=nng");
let dest = config.build();
println!("cargo:rustc-link-search=native={}", dest.as_path().join("lib").display());
#[cfg(target_os = "linux")]
println!("cargo:rustc-link-search=native={}", dest.as_path().join("lib64").display());
}
fn main() {
generate_lib();
build();
}