Joonas Javanainen 6ee5a2867b
Generate bindings for 1.76
cimgui has changed a lot, and the default bindings include a lot of
internal stuff that we (probably) don't want. Therefore we stop checking
out cimgui as a submodule and just use it as a tool instead.
2020-06-05 16:08:40 +03:00

124 lines
3.4 KiB
Rust

extern crate bindgen;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use bindgen::{Bindings, EnumVariation, RustTarget};
use failure::Error;
use std::collections::HashMap;
use std::fs::{read_to_string, File};
use std::io::Read;
use std::path::Path;
#[derive(Deserialize)]
struct StructsAndEnums {
enums: HashMap<String, serde_json::Value>,
structs: HashMap<String, serde_json::Value>,
}
#[derive(Deserialize)]
struct DefinitionArg {
#[serde(rename = "type")]
type_: String,
}
#[derive(Deserialize)]
struct Definition {
#[serde(rename = "argsT")]
args_t: Vec<DefinitionArg>,
ov_cimguiname: String,
}
#[derive(Debug, Clone)]
struct Whitelist {
enums: Vec<String>,
structs: Vec<String>,
definitions: Vec<String>,
}
fn only_key<K, V>((key, _): (K, V)) -> K {
key
}
fn parse_whitelist<R: Read>(
structs_and_enums: R,
definitions: R,
) -> Result<Whitelist, serde_json::Error> {
let StructsAndEnums { enums, structs } = serde_json::from_reader(structs_and_enums)?;
let enums = enums.into_iter().map(only_key).collect();
let structs = structs.into_iter().map(only_key).collect();
let definitions: HashMap<String, Vec<Definition>> = serde_json::from_reader(definitions)?;
let definitions = definitions
.into_iter()
.flat_map(|(_, defs)| defs.into_iter())
.filter_map(|d| {
let uses_va_list = d.args_t.iter().any(|a| a.type_ == "va_list");
if uses_va_list {
None
} else {
Some(d.ov_cimguiname)
}
})
.collect();
Ok(Whitelist {
enums,
structs,
definitions,
})
}
pub fn generate_bindings<P: AsRef<Path>>(
path: &P,
wasm_import_name: Option<String>,
) -> Result<Bindings, Error> {
let path = path.as_ref();
let structs_and_enums = File::open(path.join("structs_and_enums.json"))?;
let definitions = File::open(path.join("definitions.json"))?;
let header = read_to_string(path.join("cimgui.h"))?;
let whitelist = parse_whitelist(structs_and_enums, definitions)?;
let mut builder = bindgen::builder()
.raw_line("#![allow(non_upper_case_globals)]")
.raw_line("#![allow(non_camel_case_types)]")
.raw_line("#![allow(non_snake_case)]")
.raw_line("#![allow(clippy::all)]")
.header_contents("cimgui.h", &header)
.rust_target(RustTarget::Stable_1_40)
.default_enum_style(EnumVariation::Consts)
.size_t_is_usize(true)
.prepend_enum_name(false)
.generate_comments(false)
.layout_tests(true)
.derive_copy(true)
.derive_debug(true)
.derive_default(true)
.derive_hash(true)
.derive_partialeq(true)
.derive_eq(true)
.impl_debug(true)
.rustfmt_bindings(true)
.clang_arg("-DCIMGUI_DEFINE_ENUMS_AND_STRUCTS=1");
if let Some(name) = wasm_import_name {
builder = builder.wasm_import_module_name(name);
}
for e in whitelist.structs {
builder = builder.whitelist_type(format!("^{}", e));
}
for e in whitelist.enums {
builder = builder.whitelist_type(format!("^{}", e));
}
for e in whitelist.definitions {
builder = builder.whitelist_function(format!("^{}", e));
}
let bindings = builder
.generate()
.map_err(|_| format_err!("Failed to generate bindings"))?;
Ok(bindings)
}