Add support for static items

This commit is contained in:
Ryan Hunt 2017-10-19 00:18:53 -04:00
parent d38ffa5f7d
commit e6ad035471
9 changed files with 194 additions and 7 deletions

15
compile-tests/static.rs Normal file
View File

@ -0,0 +1,15 @@
static NUMBER: i32 = 10;
static STRING: &'static libc::c_char = "hello world";
#[repr(C)]
struct Foo {
}
struct Bar {
}
static mut FOO: Foo = Foo { };
static BAR: Bar = Bar { };
#[no_mangle]
extern "C" fn root() { }

View File

@ -8,12 +8,13 @@ use std::path;
use std::fs;
use bindgen::config::{Config, Language};
use bindgen::ir::{Constant, ItemContainer, Function};
use bindgen::ir::{Constant, ItemContainer, Function, Static};
use bindgen::monomorph::TemplateSpecialization;
use bindgen::writer::{ListType, Source, SourceWriter};
pub struct Bindings {
config: Config,
globals: Vec<Static>,
constants: Vec<Constant>,
items: Vec<ItemContainer>,
functions: Vec<Function>,
@ -23,11 +24,13 @@ pub struct Bindings {
impl Bindings {
pub fn new(config: Config,
constants: Vec<Constant>,
globals: Vec<Static>,
items: Vec<ItemContainer>,
functions: Vec<Function>,
template_specializations: Vec<TemplateSpecialization>) -> Bindings {
Bindings {
config: config,
globals: globals,
constants: constants,
items: items,
functions: functions,
@ -105,7 +108,8 @@ impl Bindings {
out.new_line_if_not_start();
match item {
&ItemContainer::Constant(ref x) => x.write(&self.config, &mut out),
&ItemContainer::Constant(..) => unreachable!(),
&ItemContainer::Static(..) => unreachable!(),
&ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
&ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
&ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
@ -117,6 +121,12 @@ impl Bindings {
out.new_line();
}
for global in &self.globals {
out.new_line_if_not_start();
global.write(&self.config, &mut out);
out.new_line();
}
if let Some(ref f) = self.config.autogen_warning {
out.new_line_if_not_start();
out.write(&f);

View File

@ -9,7 +9,7 @@ use syn;
use bindgen::cargo::Cargo;
use bindgen::config::Config;
use bindgen::ir::{AnnotationSet, Cfg, Constant, Documentation, Enum, Function};
use bindgen::ir::{ItemMap, OpaqueItem, Specialization, Struct, Typedef};
use bindgen::ir::{ItemMap, OpaqueItem, Specialization, Static, Struct, Typedef};
use bindgen::library::Library;
use bindgen::rust_lib;
use bindgen::utilities::{SynAbiHelpers, SynItemHelpers};
@ -81,6 +81,7 @@ impl LibraryBuilder {
Ok(Library::new(self.config,
result.constants,
result.globals,
result.enums,
result.structs,
result.opaque_items,
@ -93,6 +94,7 @@ impl LibraryBuilder {
#[derive(Debug, Clone)]
struct LibraryParseResult {
constants: ItemMap<Constant>,
globals: ItemMap<Static>,
enums: ItemMap<Enum>,
structs: ItemMap<Struct>,
opaque_items: ItemMap<OpaqueItem>,
@ -106,6 +108,7 @@ impl LibraryParseResult {
LibraryParseResult {
enums: ItemMap::new(),
constants: ItemMap::new(),
globals: ItemMap::new(),
structs: ItemMap::new(),
opaque_items: ItemMap::new(),
typedefs: ItemMap::new(),
@ -179,6 +182,14 @@ impl LibraryParseResult {
ty,
expr);
}
syn::ItemKind::Static(ref ty, ref mutability, ref _expr) => {
self.load_syn_static(binding_crate_name,
crate_name,
mod_cfg,
item,
ty,
mutability);
}
syn::ItemKind::Struct(ref variant, ref generics) => {
self.load_syn_struct(crate_name, mod_cfg, item, variant, generics);
}
@ -322,6 +333,42 @@ impl LibraryParseResult {
}
}
/// Loads a `static` declaration
fn load_syn_static(&mut self,
binding_crate_name: &str,
crate_name: &str,
mod_cfg: &Option<Cfg>,
item: &syn::Item,
ty: &syn::Ty,
mutability: &syn::Mutability) {
if crate_name != binding_crate_name {
info!("Skip {}::{} - (static's outside of the binding crate are not used).",
crate_name,
&item.ident);
return;
}
let static_name = item.ident.to_string();
match Static::load(static_name.clone(),
ty,
mutability,
&item.attrs,
mod_cfg) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
self.globals.try_insert(constant);
}
Err(msg) => {
warn!("Skip {}::{} - ({})",
crate_name,
&item.ident,
msg);
}
}
}
/// Loads a `struct` declaration
fn load_syn_struct(&mut self,
crate_name: &str,

94
src/bindgen/ir/global.rs Normal file
View File

@ -0,0 +1,94 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::io::Write;
use syn;
use bindgen::config::Config;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{AnnotationSet, Cfg, Documentation, Item, ItemContainer, Specialization, Type};
use bindgen::library::Library;
use bindgen::writer::{Source, SourceWriter};
#[derive(Debug, Clone)]
pub struct Static {
pub name: String,
pub ty: Type,
pub mutable: bool,
pub cfg: Option<Cfg>,
pub annotations: AnnotationSet,
pub documentation: Documentation,
}
impl Static {
pub fn load(name: String,
ty: &syn::Ty,
mutable: &syn::Mutability,
attrs: &Vec<syn::Attribute>,
mod_cfg: &Option<Cfg>) -> Result<Static, String>
{
let ty = Type::load(ty)?;
if ty.is_none() {
return Err("Cannot have a zero sized static definition.".to_owned());
}
let ty = ty.unwrap();
let mutable = mutable == &syn::Mutability::Mutable;
Ok(Static {
name: name,
ty: ty,
mutable: mutable,
cfg: Cfg::append(mod_cfg, Cfg::load(attrs)),
annotations: AnnotationSet::load(attrs)?,
documentation: Documentation::load(attrs),
})
}
}
impl Item for Static {
fn name(&self) -> &str {
&self.name
}
fn cfg(&self) -> &Option<Cfg> {
&self.cfg
}
fn annotations(&self) -> &AnnotationSet {
&self.annotations
}
fn annotations_mut(&mut self) -> &mut AnnotationSet {
&mut self.annotations
}
fn container(&self) -> ItemContainer {
ItemContainer::Static(self.clone())
}
fn specialize(&self, _library: &Library, _aliasee: &Specialization) -> Result<Box<Item>, String> {
unreachable!();
}
fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
self.ty.add_dependencies(library, out);
}
}
impl Source for Static {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
out.write("extern ");
if let Type::ConstPtr(..) = self.ty { } else {
if !self.mutable {
out.write("const ");
}
}
self.ty.write(config, out);
out.write(&format!(" {};", self.name));
}
}

View File

@ -7,7 +7,7 @@ use std::mem;
use bindgen::config::Config;
use bindgen::dependencies::Dependencies;
use bindgen::ir::{AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Specialization, Struct, Type, Typedef};
use bindgen::ir::{AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Specialization, Static, Struct, Type, Typedef};
use bindgen::library::Library;
use bindgen::monomorph::Monomorphs;
@ -30,6 +30,7 @@ pub trait Item {
#[derive(Debug, Clone)]
pub enum ItemContainer {
Constant(Constant),
Static(Static),
OpaqueItem(OpaqueItem),
Struct(Struct),
Enum(Enum),
@ -41,6 +42,7 @@ impl ItemContainer {
pub fn deref(&self) -> &Item {
match self {
&ItemContainer::Constant(ref x) => x,
&ItemContainer::Static(ref x) => x,
&ItemContainer::OpaqueItem(ref x) => x,
&ItemContainer::Struct(ref x) => x,
&ItemContainer::Enum(ref x) => x,

View File

@ -7,6 +7,7 @@ pub mod cfg;
pub mod constant;
pub mod enumeration;
pub mod function;
pub mod global;
pub mod item;
pub mod opaque;
pub mod path;
@ -22,6 +23,7 @@ pub use self::cfg::*;
pub use self::constant::*;
pub use self::enumeration::*;
pub use self::function::*;
pub use self::global::*;
pub use self::item::*;
pub use self::opaque::*;
pub use self::path::*;

View File

@ -65,8 +65,11 @@ impl Specialization {
}
match items[0] {
ItemContainer::Constant(ref aliased) => {
aliased.specialize(library, self)
ItemContainer::Constant(..) => {
unreachable!()
}
ItemContainer::Static(..) => {
unreachable!()
}
ItemContainer::OpaqueItem(ref aliased) => {
aliased.specialize(library, self)

View File

@ -398,6 +398,9 @@ impl Type {
ItemContainer::Constant(..) => {
warn!("Cannot instantiate a generic constant.")
},
ItemContainer::Static(..) => {
warn!("Cannot instantiate a generic static.")
},
ItemContainer::OpaqueItem(ref x) => {
x.instantiate_monomorph(&path.generics, out);
},

View File

@ -9,13 +9,14 @@ use bindgen::bindings::Bindings;
use bindgen::config::{Config, Language};
use bindgen::dependencies::Dependencies;
use bindgen::ir::{Constant, Enum, Function, ItemContainer, ItemMap, Item};
use bindgen::ir::{OpaqueItem, Path, Specialization, Struct, Typedef};
use bindgen::ir::{OpaqueItem, Path, Specialization, Static, Struct, Typedef};
use bindgen::monomorph::{Monomorphs, TemplateSpecialization};
#[derive(Debug, Clone)]
pub struct Library {
config: Config,
constants: ItemMap<Constant>,
globals: ItemMap<Static>,
enums: ItemMap<Enum>,
structs: ItemMap<Struct>,
opaque_items: ItemMap<OpaqueItem>,
@ -28,6 +29,7 @@ pub struct Library {
impl Library {
pub fn new(config: Config,
constants: ItemMap<Constant>,
globals: ItemMap<Static>,
enums: ItemMap<Enum>,
structs: ItemMap<Struct>,
opaque_items: ItemMap<OpaqueItem>,
@ -37,6 +39,7 @@ impl Library {
Library {
config: config,
constants: constants,
globals: globals,
enums: enums,
structs: structs,
opaque_items: opaque_items,
@ -58,6 +61,9 @@ impl Library {
for function in &self.functions {
function.add_dependencies(&self, &mut dependencies);
}
self.globals.for_all_items(|global| {
global.add_dependencies(&self, &mut dependencies);
});
if self.config.structure.generic_template_specialization &&
self.config.language == Language::Cxx {
@ -70,11 +76,13 @@ impl Library {
let items = dependencies.order;
let constants = self.constants.to_vec();
let globals = self.globals.to_vec();
let functions = mem::replace(&mut self.functions, Vec::new());
let template_specializations = mem::replace(&mut self.template_specializations, Vec::new());
Ok(Bindings::new(self.config.clone(),
constants,
globals,
items,
functions,
template_specializations))
@ -105,6 +113,9 @@ impl Library {
ItemContainer::Constant(x) => {
self.constants.try_insert(x);
},
ItemContainer::Static(x) => {
self.globals.try_insert(x);
},
ItemContainer::OpaqueItem(x) => {
self.opaque_items.try_insert(x);
},