Files
teipe/libxkbcommonrs/build.rs
2024-08-18 17:43:59 +02:00

210 lines
5.9 KiB
Rust

use std::{env, path::PathBuf};
use bindgen::callbacks::{EnumVariantValue, ParseCallbacks};
use convert_case::{Case, Casing};
#[derive(Debug)]
struct RemovePrefixesCallback {}
impl RemovePrefixesCallback {
fn new() -> Self {
Self {}
}
fn boxed() -> Box<dyn ParseCallbacks> {
Box::new(Self::new())
}
}
impl ParseCallbacks for RemovePrefixesCallback {
fn item_name(&self, original_item_name: &str) -> Option<String> {
const PREFIXES: &[&str] = &["XKB_", "xkb_"];
let mut ret = None;
for prefix in PREFIXES {
if let Some(name) = original_item_name.strip_prefix(prefix) {
ret = Some(name.to_owned());
break;
}
}
ret
}
fn enum_variant_name(
&self,
enum_name: Option<&str>,
original_variant_name: &str,
_variant_value: EnumVariantValue,
) -> Option<String> {
if enum_name.is_none() {
return self.item_name(original_variant_name);
}
// let original_variant_name = self
// .item_name(original_variant_name)
// .unwrap_or(original_variant_name.to_owned());
let enum_name = enum_name.unwrap();
let enum_name = enum_name.strip_prefix("enum ").unwrap_or(enum_name);
let enum_lower = original_variant_name.to_lowercase();
let diff_index = enum_lower
.chars()
.zip(enum_name.chars())
.enumerate()
.find(|(_i, (v, e))| v != e)
.map(|it| it.0)
.unwrap_or(enum_name.len());
let name = original_variant_name[diff_index..]
.trim_start_matches('_')
.to_case(Case::Pascal);
Some(name)
}
}
#[derive(Debug)]
struct TypedefCallback {}
impl TypedefCallback {
fn new() -> Self {
Self {}
}
fn boxed() -> Box<dyn ParseCallbacks> {
Box::new(Self::new())
}
}
impl ParseCallbacks for TypedefCallback {
fn item_name(&self, original_item_name: &str) -> Option<String> {
if original_item_name == "xkb_keysym_t" {
Some(String::from("Keysym"))
} else {
None
}
}
// fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
// if name.starts_with("XKB_KEY_") {
// Some(IntKind::Custom {
// name: "Keysym",
// is_signed: false,
// })
// } else {
// None
// }
// }
// fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec<String> {
// if (info.name.contains("keysym") && !info.name.contains("flags"))
// || info.name == "Keysym"
// || info.name == "xkb_keysym_t"
// || info.name == "keysym_t"
// {
// panic!("{info:?}");
// vec![
// "PartialEq".to_string(),
// "PartialOrd".to_string(),
// "Ord".to_string(),
// "Eq".to_string(),
// ]
// } else {
// vec![]
// }
// }
}
// #[derive(Debug)]
// struct VariadicsCallback {}
//
// impl VariadicsCallback {
// fn new() -> Self {
// Self {}
// }
// fn boxed() -> Box<dyn ParseCallbacks> {
// Box::new(Self::new())
// }
// }
//
// impl ParseCallbacks for VariadicsCallback {
// fn wrap_as_variadic_fn(&self, name: &str) -> Option<String> {
// panic!("mdr {name}");
// Some(format!("{name}_var"))
// }
// }
fn build_xkb_keysyms() -> anyhow::Result<()> {
let common_bindings = bindgen::builder()
.header("/usr/include/xkbcommon/xkbcommon-keysyms.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.parse_callbacks(RemovePrefixesCallback::boxed())
.parse_callbacks(TypedefCallback::boxed())
.allowlist_var("XKB_.*")
.generate()?;
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let out_file = out_path.join("libxkbcommon-keysyms.rs");
common_bindings
.write_to_file(out_file)
.expect("Couldn't write bindings!");
Ok(())
}
fn build_xkbcommon() -> anyhow::Result<()> {
let common_bindings = bindgen::builder()
.header("ffi/logger.h")
.header("/usr/include/xkbcommon/xkbcommon.h")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.parse_callbacks(RemovePrefixesCallback::boxed())
.parse_callbacks(TypedefCallback::boxed())
// .parse_callbacks(VariadicsCallback::boxed())
.allowlist_item("xkb_.*")
.allowlist_item("log_.*") // Log wrapper
// .allowlist_item("XKB_.*")
.new_type_alias_deref("Keysym")
.no_debug("xkb_keysym_t")
.allowlist_var("XKB_KEYCODE_INVALID")
.allowlist_var("XKB_LAYOUT_INVALID")
.allowlist_var("XKB_LEVEL_INVALID")
.allowlist_var("XKB_MOD_INVALID")
.allowlist_var("XKB_LED_INVALID")
.allowlist_var("XKB_KEYCODE_MAX")
.allowlist_var("XKB_KEYSYM_MAX")
.default_enum_style(bindgen::EnumVariation::NewType {
is_bitfield: false,
is_global: false,
})
.derive_eq(true)
.derive_partialeq(true)
.derive_ord(true)
.derive_partialord(true)
.derive_hash(true)
.generate()?;
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let out_file = out_path.join("libxkbcommon.rs");
common_bindings
.write_to_file(out_file)
.expect("Couldn't write bindings!");
println!("cargo:rustc-link-lib=xkbcommon");
Ok(())
}
fn build_logger() -> anyhow::Result<()> {
cc::Build::new()
.file("ffi/logger.c")
.std("c17")
.warnings(true)
.warnings_into_errors(true)
.extra_warnings(true)
.compile("logger");
Ok(())
}
fn main() -> anyhow::Result<()> {
build_xkbcommon()?;
build_xkb_keysyms()?;
build_logger()?;
Ok(())
}