Add item renaming, prefixing, force including, and excluding
This commit is contained in:
@@ -97,6 +97,19 @@ exclude = ["libc"]
|
||||
# parsing to expand any macros
|
||||
expand = ["euclid"]
|
||||
|
||||
[export]
|
||||
# A list of additional items not used by exported functions to include in
|
||||
# the generated bindings
|
||||
include = ["Foo", "Bar"]
|
||||
# A list of items to not include in the generated bindings
|
||||
exclude = ["Bad"]
|
||||
# A prefix to add before the name of every item
|
||||
prefix = "CAPI_"
|
||||
|
||||
# Table of name conversions to apply to item names
|
||||
[export.rename]
|
||||
"Struct" = "CAPI_Struct"
|
||||
|
||||
[fn]
|
||||
# An optional prefix to put before every function declaration
|
||||
prefix = "string"
|
||||
|
||||
@@ -115,6 +115,30 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
|
||||
self.config.export.include.push(String::from(item_name.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
|
||||
self.config.export.exclude.push(String::from(item_name.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder {
|
||||
self.config.export.rename.insert(String::from(from.as_ref()), String::from(to.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder {
|
||||
self.config.export.prefix = Some(String::from(prefix.as_ref()));
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_parse_deps(mut self, parse_deps: bool) -> Builder {
|
||||
self.config.parse.parse_deps = parse_deps;
|
||||
|
||||
@@ -95,6 +95,45 @@ impl FromStr for Layout {
|
||||
|
||||
deserialize_enum_str!(Layout);
|
||||
|
||||
/// Settings to apply when exporting items.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[serde(default)]
|
||||
pub struct ExportConfig {
|
||||
/// A list of additional items not used by exported functions to include in
|
||||
/// the generated bindings
|
||||
pub include: Vec<String>,
|
||||
/// A list of items to not include in the generated bindings
|
||||
pub exclude: Vec<String>,
|
||||
/// Table of name conversions to apply to item names
|
||||
pub rename: HashMap<String, String>,
|
||||
/// A prefix to add before the name of every item
|
||||
pub prefix: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for ExportConfig {
|
||||
fn default() -> ExportConfig {
|
||||
ExportConfig {
|
||||
include: Vec::new(),
|
||||
exclude: Vec::new(),
|
||||
rename: HashMap::new(),
|
||||
prefix: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExportConfig {
|
||||
pub(crate) fn rename(&self, item_name: &mut String) {
|
||||
if let Some(name) = self.rename.get(item_name) {
|
||||
*item_name = name.clone();
|
||||
}
|
||||
if let Some(ref prefix) = self.prefix {
|
||||
item_name.insert_str(0, &prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings to apply to generated functions.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
@@ -333,6 +372,8 @@ pub struct Config {
|
||||
pub language: Language,
|
||||
/// The configuration options for parsing
|
||||
pub parse: ParseConfig,
|
||||
/// The configuration options for exporting
|
||||
pub export: ExportConfig,
|
||||
/// The configuration options for functions
|
||||
#[serde(rename = "fn")]
|
||||
pub function: FunctionConfig,
|
||||
@@ -368,6 +409,7 @@ impl Default for Config {
|
||||
tab_width: 2,
|
||||
language: Language::Cxx,
|
||||
parse: ParseConfig::default(),
|
||||
export: ExportConfig::default(),
|
||||
function: FunctionConfig::default(),
|
||||
structure: StructConfig::default(),
|
||||
enumeration: EnumConfig::default(),
|
||||
|
||||
@@ -110,6 +110,10 @@ impl Item for Constant {
|
||||
fn container(&self) -> ItemContainer {
|
||||
ItemContainer::Constant(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for Constant {
|
||||
|
||||
@@ -109,6 +109,8 @@ impl Item for Enum {
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
|
||||
if config.language == Language::C
|
||||
&& (config.enumeration.prefix_with_name
|
||||
|| self.annotations.bool("prefix-with-name").unwrap_or(false))
|
||||
|
||||
@@ -78,6 +78,11 @@ impl Function {
|
||||
}
|
||||
|
||||
pub fn rename_for_config(&mut self, config: &Config) {
|
||||
self.ret.rename_for_config(config);
|
||||
for &mut (_, ref mut ty) in &mut self.args {
|
||||
ty.rename_for_config(config);
|
||||
}
|
||||
|
||||
let rules = [
|
||||
self.annotations.parse_atom::<RenameRule>("rename-all"),
|
||||
config.function.rename_args,
|
||||
|
||||
@@ -75,6 +75,10 @@ impl Item for Static {
|
||||
ItemContainer::Static(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
self.ty.rename_for_config(config);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.ty.add_dependencies(library, out);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,11 @@ impl<T: Item + Clone> ItemMap<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rebuild(&mut self) {
|
||||
let old = mem::replace(self, ItemMap::new());
|
||||
old.for_all_items(|x| { self.try_insert(x.clone()); });
|
||||
}
|
||||
|
||||
pub fn try_insert(&mut self, item: T) -> bool {
|
||||
match (item.cfg().is_some(), self.data.get_mut(item.name())) {
|
||||
(true, Some(&mut ItemValue::Cfg(ref mut items))) => {
|
||||
|
||||
@@ -62,6 +62,10 @@ impl Item for OpaqueItem {
|
||||
ItemContainer::OpaqueItem(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, _: &Library, _: &mut Dependencies) {}
|
||||
|
||||
fn instantiate_monomorph(
|
||||
|
||||
@@ -121,7 +121,12 @@ impl Item for Struct {
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
let rules = [
|
||||
config.export.rename(&mut self.name);
|
||||
for &mut (_, ref mut ty, _) in &mut self.fields {
|
||||
ty.rename_for_config(config);
|
||||
}
|
||||
|
||||
let field_rules = [
|
||||
self.annotations.parse_atom::<RenameRule>("rename-all"),
|
||||
config.structure.rename_fields,
|
||||
];
|
||||
@@ -138,7 +143,7 @@ impl Item for Struct {
|
||||
}
|
||||
|
||||
self.fields = overriden_fields;
|
||||
} else if let Some(r) = find_first_some(&rules) {
|
||||
} else if let Some(r) = find_first_some(&field_rules) {
|
||||
self.fields = self.fields
|
||||
.iter()
|
||||
.map(|x| {
|
||||
|
||||
@@ -443,6 +443,33 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rename_for_config(&mut self, config: &Config) {
|
||||
match self {
|
||||
&mut Type::ConstPtr(ref mut ty) => {
|
||||
ty.rename_for_config(config);
|
||||
}
|
||||
&mut Type::Ptr(ref mut ty) => {
|
||||
ty.rename_for_config(config);
|
||||
}
|
||||
&mut Type::Path(ref mut path) => {
|
||||
for generic in &mut path.generics {
|
||||
generic.rename_for_config(config);
|
||||
}
|
||||
config.export.rename(&mut path.name);
|
||||
}
|
||||
&mut Type::Primitive(_) => {}
|
||||
&mut Type::Array(ref mut ty, _) => {
|
||||
ty.rename_for_config(config);
|
||||
}
|
||||
&mut Type::FuncPtr(ref mut ret, ref mut args) => {
|
||||
ret.rename_for_config(config);
|
||||
for arg in args {
|
||||
arg.rename_for_config(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
|
||||
match self {
|
||||
&mut Type::ConstPtr(ref mut ty) => {
|
||||
|
||||
@@ -115,6 +115,11 @@ impl Item for Typedef {
|
||||
ItemContainer::Typedef(self.clone())
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
self.aliased.rename_for_config(config);
|
||||
}
|
||||
|
||||
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
|
||||
self.aliased
|
||||
.add_dependencies_ignoring_generics(&self.generic_params, library, out);
|
||||
|
||||
@@ -122,6 +122,11 @@ impl Item for Union {
|
||||
}
|
||||
|
||||
fn rename_for_config(&mut self, config: &Config) {
|
||||
config.export.rename(&mut self.name);
|
||||
for &mut (_, ref mut ty, _) in &mut self.fields {
|
||||
ty.rename_for_config(config);
|
||||
}
|
||||
|
||||
let rules = [
|
||||
self.annotations.parse_atom::<RenameRule>("rename-all"),
|
||||
config.structure.rename_fields,
|
||||
|
||||
+49
-1
@@ -52,8 +52,8 @@ impl Library {
|
||||
}
|
||||
|
||||
pub fn generate(mut self) -> Result<Bindings, Error> {
|
||||
self.remove_excluded();
|
||||
self.functions.sort_by(|x, y| x.name.cmp(&y.name));
|
||||
|
||||
self.transfer_annotations();
|
||||
self.rename_items();
|
||||
self.simplify_option_to_ptr();
|
||||
@@ -70,6 +70,20 @@ impl Library {
|
||||
self.globals.for_all_items(|global| {
|
||||
global.add_dependencies(&self, &mut dependencies);
|
||||
});
|
||||
for name in &self.config.export.include {
|
||||
if let Some(items) = self.get_items(name) {
|
||||
if !dependencies.items.contains(name) {
|
||||
dependencies.items.insert(name.clone());
|
||||
|
||||
for item in &items {
|
||||
item.deref().add_dependencies(&self, &mut dependencies);
|
||||
}
|
||||
for item in items {
|
||||
dependencies.order.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies.sort();
|
||||
|
||||
@@ -107,6 +121,18 @@ impl Library {
|
||||
None
|
||||
}
|
||||
|
||||
fn remove_excluded(&mut self) {
|
||||
let config = &self.config;
|
||||
self.functions.retain(|x| !config.export.exclude.contains(&x.name));
|
||||
self.enums.filter(|x| config.export.exclude.contains(&x.name));
|
||||
self.structs.filter(|x| config.export.exclude.contains(&x.name));
|
||||
self.unions.filter(|x| config.export.exclude.contains(&x.name));
|
||||
self.opaque_items.filter(|x| config.export.exclude.contains(&x.name));
|
||||
self.typedefs.filter(|x| config.export.exclude.contains(&x.name));
|
||||
self.globals.filter(|x| config.export.exclude.contains(&x.name));
|
||||
self.constants.filter(|x| config.export.exclude.contains(&x.name));
|
||||
}
|
||||
|
||||
fn transfer_annotations(&mut self) {
|
||||
let mut annotations = HashMap::new();
|
||||
|
||||
@@ -198,12 +224,34 @@ impl Library {
|
||||
|
||||
fn rename_items(&mut self) {
|
||||
let config = &self.config;
|
||||
|
||||
self.globals
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.globals.rebuild();
|
||||
|
||||
self.constants
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.constants.rebuild();
|
||||
|
||||
self.structs
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.structs.rebuild();
|
||||
|
||||
self.unions
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.unions.rebuild();
|
||||
|
||||
self.enums
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.enums.rebuild();
|
||||
|
||||
self.opaque_items
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.opaque_items.rebuild();
|
||||
|
||||
self.typedefs
|
||||
.for_all_items_mut(|x| x.rename_for_config(config));
|
||||
self.typedefs.rebuild();
|
||||
|
||||
for item in &mut self.functions {
|
||||
item.rename_for_config(&self.config);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
int32_t x;
|
||||
float y;
|
||||
} A;
|
||||
|
||||
typedef struct {
|
||||
A data;
|
||||
} B;
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
struct A {
|
||||
int32_t x;
|
||||
float y;
|
||||
};
|
||||
|
||||
struct B {
|
||||
A data;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
} // extern "C"
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define C_H 10
|
||||
|
||||
enum C_E {
|
||||
x = 0,
|
||||
y = 1,
|
||||
};
|
||||
typedef uint8_t C_E;
|
||||
|
||||
typedef struct C_A C_A;
|
||||
|
||||
typedef struct C_C C_C;
|
||||
|
||||
typedef struct {
|
||||
int32_t x;
|
||||
float y;
|
||||
} C_AwesomeB;
|
||||
|
||||
typedef union {
|
||||
int32_t x;
|
||||
float y;
|
||||
} C_D;
|
||||
|
||||
typedef C_A C_F;
|
||||
|
||||
extern const int32_t G;
|
||||
|
||||
void root(const C_A *a, C_AwesomeB b, C_C c, C_D d, C_E e, C_F f);
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
static const int32_t C_H = 10;
|
||||
|
||||
enum class C_E : uint8_t {
|
||||
x = 0,
|
||||
y = 1,
|
||||
};
|
||||
|
||||
struct C_A;
|
||||
|
||||
struct C_C;
|
||||
|
||||
struct C_AwesomeB {
|
||||
int32_t x;
|
||||
float y;
|
||||
};
|
||||
|
||||
union C_D {
|
||||
int32_t x;
|
||||
float y;
|
||||
};
|
||||
|
||||
using C_F = C_A;
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern const int32_t G;
|
||||
|
||||
void root(const C_A *a, C_AwesomeB b, C_C c, C_D d, C_E e, C_F f);
|
||||
|
||||
} // extern "C"
|
||||
@@ -0,0 +1,10 @@
|
||||
#[repr(C)]
|
||||
struct A {
|
||||
x: i32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct B {
|
||||
data: A,
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
[export]
|
||||
include = ["B"]
|
||||
@@ -0,0 +1,45 @@
|
||||
struct A {
|
||||
x: i32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct B {
|
||||
x: i32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
union C {
|
||||
x: i32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
union D {
|
||||
x: i32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
enum E {
|
||||
x = 0,
|
||||
y = 1,
|
||||
}
|
||||
|
||||
type F = A;
|
||||
|
||||
#[no_mangle]
|
||||
pub static G: i32 = 10;
|
||||
|
||||
const H: i32 = 10;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn root(
|
||||
a: *const A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
e: E,
|
||||
f: F,
|
||||
) { }
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[export]
|
||||
prefix = "C_"
|
||||
|
||||
[export.rename]
|
||||
"B" = "AwesomeB"
|
||||
Reference in New Issue
Block a user