aboutsummaryrefslogtreecommitdiff
path: root/rustables/build.rs
diff options
context:
space:
mode:
authorlafleur <lafleur@boum.org>2021-11-07 14:19:37 +0100
committerlafleur <lafleur@boum.org>2021-11-07 14:19:37 +0100
commit1e33e3ab0790d977add329e9686b4b9e5570ba3c (patch)
treeeb55ce7ff42be89be640ce2330e2503349267798 /rustables/build.rs
parent55d9bf885e009953a0001062b2b60c21e8322a31 (diff)
call bindgen on build in rustables
Diffstat (limited to 'rustables/build.rs')
-rw-r--r--rustables/build.rs132
1 files changed, 122 insertions, 10 deletions
diff --git a/rustables/build.rs b/rustables/build.rs
index fee34ff..180e06b 100644
--- a/rustables/build.rs
+++ b/rustables/build.rs
@@ -1,13 +1,64 @@
use bindgen;
-
+use lazy_static::lazy_static;
+use regex::{Captures, Regex};
+use pkg_config;
+use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::borrow::Cow;
-use lazy_static::lazy_static;
-use regex::{Captures, Regex};
+const SYS_HEADER_FILE: &str = "wrapper.h";
+const SYS_BINDINGS_FILE: &str = "src/sys.rs";
+const TESTS_HEADER_FILE: &str = "tests_wrapper.h";
+const TESTS_BINDINGS_FILE: &str = "tests/sys.rs";
+const MIN_LIBNFTNL_VERSION: &str = "1.0.6";
+
+
+fn get_env(var: &'static str) -> Option<PathBuf> {
+ println!("cargo:rerun-if-env-changed={}", var);
+ env::var_os(var).map(PathBuf::from)
+}
+
+/// Set env vars to help rustc find linked libraries.
+fn setup_libs() {
+ if let Some(lib_dir) = get_env("LIBNFTNL_LIB_DIR") {
+ if !lib_dir.is_dir() {
+ panic!(
+ "libnftnl library directory does not exist: {}",
+ lib_dir.display()
+ );
+ }
+ println!("cargo:rustc-link-search=native={}", lib_dir.display());
+ println!("cargo:rustc-link-lib=nftnl");
+ } else {
+ // Trying with pkg-config instead
+ println!("Minimum libnftnl version: {}", MIN_LIBNFTNL_VERSION);
+ pkg_config::Config::new()
+ .atleast_version(MIN_LIBNFTNL_VERSION)
+ .probe("libnftnl")
+ .unwrap();
+ }
+
+ if let Some(lib_dir) = get_env("LIBMNL_LIB_DIR") {
+ if !lib_dir.is_dir() {
+ panic!(
+ "libmnl library directory does not exist: {}",
+ lib_dir.display()
+ );
+ }
+ println!("cargo:rustc-link-search=native={}", lib_dir.display());
+ println!("cargo:rustc-link-lib=mnl");
+ } else {
+ // Trying with pkg-config instead
+ pkg_config::Config::new()
+ .atleast_version("1.0.0")
+ .probe("libmnl")
+ .unwrap();
+ }
+}
+
/// Recast nft_*_attributes from u32 to u16 in header file `before`.
fn reformat_units(before: &str) -> Cow<str> {
lazy_static! {
@@ -18,31 +69,92 @@ fn reformat_units(before: &str) -> Cow<str> {
})
}
-fn main() {
+fn generate_consts() {
// Tell cargo to invalidate the built crate whenever the headers change.
- println!("cargo:rerun-if-changed=wrapper.h");
+ println!("cargo:rerun-if-changed={}", SYS_HEADER_FILE);
let bindings = bindgen::Builder::default()
- .header("wrapper.h")
+ .header(SYS_HEADER_FILE)
.generate_comments(false)
.prepend_enum_name(false)
+ .use_core()
+ .whitelist_function("^nftnl_.+$")
+ .whitelist_type("^nftnl_.+$")
+ .whitelist_var("^nftnl_.+$")
+ .whitelist_var("^NFTNL_.+$")
+ .blacklist_type("(FILE|iovec)")
+ .blacklist_type("^_IO_.+$")
+ .blacklist_type("^__.+$")
+ .blacklist_type("nlmsghdr")
+ .raw_line("#![allow(non_camel_case_types)]\n\n")
+ .raw_line("pub use libc;")
+ .raw_line("use libc::{c_char, c_int, c_ulong, c_void, iovec, nlmsghdr, FILE};")
+ .raw_line("use core::option::Option;")
+ .ctypes_prefix("libc")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
- .expect("Unable to generate bindings");
+ .expect("Error: unable to generate bindings");
+
+ let mut s = bindings.to_string()
+ // Add newlines because in alpine bindgen doesn't add them after
+ // statements.
+ .replace(" ; ", ";\n")
+ .replace("#[derive(Debug, Copy, Clone)]", "");
+ let re = Regex::new(r"libc::(c_[a-z]*)").unwrap();
+ s = re.replace_all(&s, "$1").into();
+ let re = Regex::new(r"::core::option::(Option)").unwrap();
+ s = re.replace_all(&s, "$1").into();
+ let re = Regex::new(r"_bindgen_ty_[0-9]+").unwrap();
+ s = re.replace_all(&s, "u32").into();
+ // Change struct bodies to c_void.
+ let re = Regex::new(r"(pub struct .*) \{\n *_unused: \[u8; 0\],\n\}\n").unwrap();
+ s = re.replace_all(&s, "$1(c_void);\n").into();
+ let re = Regex::new(r"pub type u32 = u32;\n").unwrap();
+ s = re.replace_all(&s, "").into();
+
+ // Write the bindings to the rust header file.
+ let out_path = PathBuf::from(SYS_BINDINGS_FILE);
+ File::create(out_path)
+ .expect("Error: could not create rust header file.")
+ .write_all(&s.as_bytes())
+ .expect("Error: could not write to the rust header file.");
+}
+
+fn generate_test_consts() {
+ // Tell cargo to invalidate the built crate whenever the headers change.
+ println!("cargo:rerun-if-changed={}", TESTS_HEADER_FILE);
+
+ let bindings = bindgen::Builder::default()
+ .header(TESTS_HEADER_FILE)
+ .generate_comments(false)
+ .prepend_enum_name(false)
+ .raw_line("#![allow(non_camel_case_types, dead_code)]\n\n")
+ // Tell cargo to invalidate the built crate whenever any of the
+ // included header files changed.
+ .parse_callbacks(Box::new(bindgen::CargoCallbacks))
+ // Finish the builder and generate the bindings.
+ .generate()
+ // Unwrap the Result and panic on failure.
+ .expect("Error: unable to generate bindings needed for tests.");
// Add newlines because in alpine bindgen doesn't add them after statements.
let s = bindings.to_string().replace(" ; ", ";\n");
let s = reformat_units(&s);
- let h = String::from("#![allow(non_camel_case_types, dead_code)]\n\n") + &s;
// Write the bindings to the rust header file.
- let out_path = PathBuf::from("src/tests/bindings.rs");
+ let out_path = PathBuf::from(TESTS_BINDINGS_FILE);
File::create(out_path)
.expect("Error: could not create rust header file.")
- .write_all(&h.as_bytes())
+ .write_all(&s.as_bytes())
.expect("Error: could not write to the rust header file.");
}
+
+fn main() {
+ setup_libs();
+ generate_consts();
+ generate_test_consts();
+}