summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--libbindgen/build.rs39
-rw-r--r--libbindgen/src/clang.rs14
-rw-r--r--libbindgen/src/codegen/mod.rs23
-rw-r--r--libbindgen/src/lib.rs10
-rw-r--r--libbindgen/tests/tests.rs58
-rw-r--r--src/options.rs7
7 files changed, 99 insertions, 53 deletions
diff --git a/.travis.yml b/.travis.yml
index 98073e00..17beccc6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,7 +12,6 @@ os:
rust:
- stable
- - nightly
env:
- CARGO_TARGET_DIR=/tmp/bindgen LLVM_VERSION=3.8 BINDGEN_FEATURES=llvm_stable
diff --git a/libbindgen/build.rs b/libbindgen/build.rs
index b9cf3e60..228a7f22 100644
--- a/libbindgen/build.rs
+++ b/libbindgen/build.rs
@@ -1,10 +1,9 @@
mod codegen {
extern crate quasi_codegen;
use std::path::Path;
- use std::env;
pub fn main() {
- let out_dir = env::var_os("OUT_DIR").unwrap();
+ let out_dir = Path::new(env!("OUT_DIR"));
let src = Path::new("src/codegen/mod.rs");
let dst = Path::new(&out_dir).join("codegen.rs");
@@ -14,6 +13,42 @@ mod codegen {
}
}
+mod testgen {
+ use std::char;
+ use std::ffi::OsStr;
+ use std::fs::{self, File};
+ use std::io::Write;
+ use std::path::Path;
+
+ pub fn main() {
+ let out_dir = Path::new(env!("OUT_DIR"));
+ let mut dst = File::create(Path::new(&out_dir).join("tests.rs")).unwrap();
+
+ let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
+ let headers_dir = manifest_dir.join("tests").join("headers");
+
+ let entries = fs::read_dir(headers_dir)
+ .expect("Couldn't read headers dir")
+ .map(|result| result.expect("Couldn't read header file"));
+
+ for entry in entries {
+ match entry.path().extension().and_then(OsStr::to_str) {
+ Some("h") | Some("hpp") => {
+ let func = entry.file_name().to_str().unwrap()
+ .replace(|c| !char::is_alphanumeric(c), "_")
+ .replace("__", "_")
+ .to_lowercase();
+ let _ = writeln!(dst, "test_header!(header_{}, {:?});",
+ func, entry.path());
+ }
+ _ => {}
+ }
+ }
+ let _ = dst.flush();
+ }
+}
+
fn main() {
codegen::main();
+ testgen::main();
}
diff --git a/libbindgen/src/clang.rs b/libbindgen/src/clang.rs
index 7da755ea..d10457b3 100644
--- a/libbindgen/src/clang.rs
+++ b/libbindgen/src/clang.rs
@@ -1235,21 +1235,23 @@ pub fn type_to_str(x: Enum_CXTypeKind) -> String {
/// Dump the Clang AST to stdout for debugging purposes.
pub fn ast_dump(c: &Cursor, depth: isize) -> Enum_CXVisitorResult {
fn print_indent(depth: isize, s: &str) {
- let mut i = 0;
- while i < depth {
+ for _ in 0..depth {
print!("\t");
- i += 1;
}
println!("{}", s);
}
- let ct = c.cur_type().kind();
+
print_indent(depth,
- &format!("({} {} {}",
+ &format!("(kind: {}, spelling: {}, type: {}",
kind_to_str(c.kind()),
c.spelling(),
- type_to_str(ct)));
+ type_to_str(c.cur_type().kind())));
+
+ // Recurse.
c.visit(|s| ast_dump(&s, depth + 1));
+
print_indent(depth, ")");
+
CXChildVisit_Continue
}
diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs
index 8e04fd7c..99ec56f4 100644
--- a/libbindgen/src/codegen/mod.rs
+++ b/libbindgen/src/codegen/mod.rs
@@ -228,9 +228,12 @@ impl CodeGenerator for Item {
result: &mut CodegenResult,
_extra: &()) {
if self.is_hidden(ctx) || result.seen(self.id()) {
+ debug!("<Item as CodeGenerator>::codegen: Ignoring hidden or seen: self = {:?}", self);
return;
}
+ debug!("<Item as CodeGenerator>::codegen: self = {:?}", self);
+
result.set_seen(self.id());
match *self.kind() {
@@ -264,6 +267,8 @@ impl CodeGenerator for Module {
ctx: &BindgenContext,
result: &mut CodegenResult,
item: &Item) {
+ debug!("<Module as CodeGenerator>::codegen: item = {:?}", item);
+
if !ctx.options().enable_cxx_namespaces {
for child in self.children() {
ctx.resolve_item(*child).codegen(ctx, result, &());
@@ -299,6 +304,8 @@ impl CodeGenerator for Var {
ctx: &BindgenContext,
result: &mut CodegenResult,
item: &Item) {
+ debug!("<Var as CodeGenerator>::codegen: item = {:?}", item);
+
let canonical_name = item.canonical_name(ctx);
if result.seen_var(&canonical_name) {
@@ -349,6 +356,8 @@ impl CodeGenerator for Type {
ctx: &BindgenContext,
result: &mut CodegenResult,
item: &Item) {
+ debug!("<Type as CodeGenerator>::codegen: item = {:?}", item);
+
match *self.kind() {
TypeKind::Void |
TypeKind::NullPtr |
@@ -600,6 +609,9 @@ impl CodeGenerator for CompInfo {
result: &mut CodegenResult,
item: &Item) {
use aster::struct_field::StructFieldBuilder;
+
+ debug!("<CompInfo as CodeGenerator>::codegen: item = {:?}", item);
+
// Don't output classes with template parameters that aren't types, and
// also don't output template specializations, neither total or partial.
//
@@ -1361,6 +1373,8 @@ impl CodeGenerator for Enum {
ctx: &BindgenContext,
result: &mut CodegenResult,
item: &Item) {
+ debug!("<Enum as CodeGenerator>::codegen: item = {:?}", item);
+
let name = item.canonical_name(ctx);
let enum_ty = item.expect_type();
let layout = enum_ty.layout(ctx);
@@ -1800,6 +1814,8 @@ impl CodeGenerator for Function {
ctx: &BindgenContext,
result: &mut CodegenResult,
item: &Item) {
+ debug!("<Function as CodeGenerator>::codegen: item = {:?}", item);
+
let name = self.name();
let mut canonical_name = item.canonical_name(ctx);
let mangled_name = self.mangled_name();
@@ -1892,6 +1908,13 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
let whitelisted_items: ItemSet = context.whitelisted_items().collect();
+ if context.options().emit_ir {
+ for &id in whitelisted_items.iter() {
+ let item = context.resolve_item(id);
+ println!("ir: {:?} = {:#?}", id, item);
+ }
+ }
+
for &id in whitelisted_items.iter() {
let item = context.resolve_item(id);
diff --git a/libbindgen/src/lib.rs b/libbindgen/src/lib.rs
index d0ca7b03..e4923b77 100644
--- a/libbindgen/src/lib.rs
+++ b/libbindgen/src/lib.rs
@@ -225,6 +225,12 @@ impl Builder {
self
}
+ /// Emit IR.
+ pub fn emit_ir(mut self) -> Builder {
+ self.options.emit_ir = true;
+ self
+ }
+
/// Enable C++ namespaces.
pub fn enable_cxx_namespaces(mut self) -> Builder {
self.options.enable_cxx_namespaces = true;
@@ -314,6 +320,9 @@ pub struct BindgenOptions {
/// True if we should dump the Clang AST for debugging purposes.
pub emit_ast: bool,
+ /// True if we should dump our internal IR for debugging purposes.
+ pub emit_ir: bool,
+
/// True if we should ignore functions and only generate bindings for
/// structures, types, and methods.
pub ignore_functions: bool,
@@ -380,6 +389,7 @@ impl Default for BindgenOptions {
builtins: false,
links: vec![],
emit_ast: false,
+ emit_ir: false,
ignore_functions: false,
ignore_methods: false,
derive_debug: true,
diff --git a/libbindgen/tests/tests.rs b/libbindgen/tests/tests.rs
index c9826260..c0786406 100644
--- a/libbindgen/tests/tests.rs
+++ b/libbindgen/tests/tests.rs
@@ -6,10 +6,9 @@ extern crate libbindgen;
extern crate log;
extern crate shlex;
-use std::env;
use std::fs;
use std::io::{BufRead, BufReader, Error, ErrorKind, Read};
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
#[path="../../src/options.rs"]
mod options;
@@ -93,46 +92,17 @@ fn create_bindgen_builder(header: &PathBuf)
builder_from_flags(args).map(|(builder, _)| builder.no_unstable_rust())
}
-#[test]
-fn run_bindgen_tests() {
- log::set_logger(|max_log_level| {
- use env_logger::Logger;
- let env_logger = Logger::new();
- max_log_level.set(env_logger.filter());
- Box::new(env_logger)
- })
- .expect("Failed to set logger.");
-
- let manifest_env = env::var("CARGO_MANIFEST_DIR")
- .expect("CARGO_MANIFEST_DIR not set!");
- let manifest_dir = Path::new(&manifest_env);
- let headers_dir = manifest_dir.join("tests").join("headers");
-
- let entries = fs::read_dir(&headers_dir)
- .expect("Couldn't read headers dir")
- .map(|result| result.expect("Couldn't read header file"));
-
- let headers: Vec<_> = entries.filter_map(|entry| {
- match entry.path().extension().and_then(|s| s.to_str()) {
- Some("h") | Some("hpp") => Some(entry.path()),
- _ => None,
- }
- })
- .collect();
-
- let failures: Vec<_> = headers.iter()
- .filter_map(|header| {
- create_bindgen_builder(header)
- .and_then(|builder| compare_generated_header(header, builder))
- .err()
- })
- .collect();
-
- let num_failures = failures.len();
-
- if num_failures > 0 {
- panic!("{} test{} failed!",
- num_failures,
- if num_failures > 1 {"s"} else {""});
- }
+macro_rules! test_header {
+ ($function:ident, $header:expr) => (
+ #[test]
+ fn $function() {
+ let header = PathBuf::from($header);
+ let _ = create_bindgen_builder(&header)
+ .and_then(|builder| compare_generated_header(&header, builder))
+ .map_err(|err| panic!(format!("{}", err)) );
+ }
+ )
}
+
+// This file is generated by build.rs
+include!(concat!(env!("OUT_DIR"), "/tests.rs"));
diff --git a/src/options.rs b/src/options.rs
index c3c6a1f2..2ea74a27 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -52,6 +52,9 @@ pub fn builder_from_flags<I>(args: I)
Arg::with_name("emit-clang-ast")
.long("emit-clang-ast")
.help("Output the Clang AST for debugging purposes."),
+ Arg::with_name("emit-ir")
+ .long("emit-ir")
+ .help("Output our internal IR for debugging purposes."),
Arg::with_name("enable-cxx-namespaces")
.long("enable-cxx-namespaces")
.help("Enable support for C++ namespaces."),
@@ -183,6 +186,10 @@ pub fn builder_from_flags<I>(args: I)
builder = builder.emit_clang_ast();
}
+ if matches.is_present("emit-ir") {
+ builder = builder.emit_ir();
+ }
+
if matches.is_present("enable-cxx-namespaces") {
builder = builder.enable_cxx_namespaces();
}