diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbaaf3c4ee..8c34710713 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,6 +15,7 @@ out to us in a GitHub issue, or stop by - [Overview](#overview) - [Running All Tests](#running-all-tests) - [Authoring New Tests](#authoring-new-tests) +- [Generating Graphviz Dot File](#generating-graphviz-dot-file) - [Automatic code formatting](#automatic-code-formatting) - [Debug Logging](#debug-logging) - [Using `creduce` to Minimize Test Cases](#using-creduce-to-minimize-test-cases) @@ -112,6 +113,27 @@ Then verify the new Rust bindings compile and pass some basic tests: $ cargo test -p tests_expectations ``` +## Generating Graphviz Dot Files + +We have a special thing which will help you debug your codegen context if something +will go wrong. It will generate a [`graphviz`](http://graphviz.org/pdf/dotguide.pdf) +dot file and then you can create a PNG from it with `graphviz` tool in your OS. + +Here is an example how it could be done: + +``` +$ cargo run -- example.hpp --emit-ir-graphviz output.dot +``` + +It will generate your graphviz dot file and then you will need tog +create a PNG from it with `graphviz`. + +Something like this: + +``` +$ dot -Tpng output.dot -o output.png +``` + ## Automatic code formatting We use [`rustfmt`](https://github.com/rust-lang-nursery/rustfmt) to enforce a diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 92e3487410..ad6736b074 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2499,6 +2499,13 @@ pub fn codegen(context: &mut BindgenContext) -> Vec
> {
}
}
+ if let Some(path) = context.options().emit_ir_graphviz.as_ref() {
+ match context.emit_ir_graphviz(path.clone()) {
+ Ok(()) => info!("Your dot file was generated successfully into: {}", path),
+ Err(e) => error!("{}", e),
+ }
+ }
+
context.resolve_item(context.root_module())
.codegen(context, &mut result, &whitelisted_items, &());
diff --git a/src/ir/context.rs b/src/ir/context.rs
index d2fb2befc6..7383c09a4c 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -5,7 +5,7 @@ use super::int::IntKind;
use super::item::{Item, ItemCanonicalPath, ItemSet};
use super::item_kind::ItemKind;
use super::module::{Module, ModuleKind};
-use super::traversal::{self, Edge, ItemTraversal};
+use super::traversal::{self, Edge, ItemTraversal, Trace};
use super::ty::{FloatKind, TemplateDeclaration, Type, TypeKind};
use BindgenOptions;
use cexpr;
@@ -18,6 +18,8 @@ use std::cell::Cell;
use std::collections::{HashMap, hash_map};
use std::collections::btree_map::{self, BTreeMap};
use std::fmt;
+use std::fs::File;
+use std::io::{self, Write};
use std::iter::IntoIterator;
use syntax::ast::Ident;
use syntax::codemap::{DUMMY_SP, Span};
@@ -1109,6 +1111,33 @@ impl<'ctx> BindgenContext<'ctx> {
&self.options
}
+ /// Output graphviz dot file.
+ pub fn emit_ir_graphviz(&self, path: String) -> io::Result<()> {
+ let file = try!(File::create(path));
+ let mut dot_file = io::BufWriter::new(file);
+ writeln!(&mut dot_file, "digraph {{")?;
+
+ let mut err: Option \
+
\
+ >]",
+ self.id.as_usize(),
+ self.name(ctx).get(),
+ self.kind.kind_name())
+ }
+
/// Get this `Item`'s parent's identifier.
///
/// For the root module, the parent's ID is its own ID.
diff --git a/src/ir/item_kind.rs b/src/ir/item_kind.rs
index d9e4690cb4..3ff0673169 100644
--- a/src/ir/item_kind.rs
+++ b/src/ir/item_kind.rs
@@ -32,6 +32,16 @@ impl ItemKind {
}
}
+ /// Transform our `ItemKind` into a string.
+ pub fn kind_name(&self) -> &'static str {
+ match *self {
+ ItemKind::Module(..) => "Module",
+ ItemKind::Type(..) => "Type",
+ ItemKind::Function(..) => "Function",
+ ItemKind::Var(..) => "Var"
+ }
+ }
+
/// Is this a module?
pub fn is_module(&self) -> bool {
self.as_module().is_some()
diff --git a/src/lib.rs b/src/lib.rs
index 7bf9806487..42363ebdb1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -175,6 +175,13 @@ impl Builder {
self
}
+ /// Set the output graphviz file.
+ pub fn emit_ir_graphviz \
+ ItemId({}) \
+ name {} \
+ kind {}