summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml3
-rw-r--r--src/bin/bindgen.rs13
-rw-r--r--src/gen.rs138
-rw-r--r--src/lib.rs74
4 files changed, 95 insertions, 133 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0261c19d..50a84b66 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,8 @@ build = "build.rs"
clippy = { version = "*", optional = true }
log = "0.3.*"
libc = "0.2.*"
-syntex_syntax = "0.32"
+syntex_syntax = "0.37"
+clang-sys = "0.7.2"
[features]
static = []
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs
index fd0a7ffe..228c5f95 100644
--- a/src/bin/bindgen.rs
+++ b/src/bin/bindgen.rs
@@ -4,6 +4,7 @@
extern crate bindgen;
#[macro_use]
extern crate log;
+extern crate clang_sys;
use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
@@ -214,12 +215,14 @@ pub fn main() {
let mut bind_args: Vec<_> = env::args().collect();
let bin = bind_args.remove(0);
- match bindgen::get_include_dir() {
- Some(path) => {
- bind_args.push("-I".to_owned());
- bind_args.push(path);
+ if let Some(clang) = clang_sys::support::Clang::find(None) {
+ // TODO: distinguish C and C++ paths? C++'s should be enough, I guess.
+ for path in clang.cpp_search_paths.into_iter() {
+ if let Ok(path) = path.into_os_string().into_string() {
+ bind_args.push("-isystem".to_owned());
+ bind_args.push(path);
+ }
}
- None => (),
}
match parse_args(&bind_args) {
diff --git a/src/gen.rs b/src/gen.rs
index 7393ac43..d6b43ff9 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -150,21 +150,17 @@ fn enum_name(ctx: &GenCtx, name: &str) -> String {
fn gen_unmangle_method(ctx: &mut GenCtx,
v: &VarInfo,
counts: &mut HashMap<String, isize>,
- self_kind: ast::SelfKind)
+ self_kind: Option<ast::Mutability>)
-> ast::ImplItem {
- let fndecl;
+ let mut fndecl;
let mut args = vec![];
- match self_kind {
- ast::SelfKind::Static => (),
- ast::SelfKind::Region(_, mutable, _) => {
- let selfexpr = match mutable {
- ast::Mutability::Immutable => quote_expr!(&ctx.ext_cx, &*self),
- ast::Mutability::Mutable => quote_expr!(&ctx.ext_cx, &mut *self),
- };
- args.push(selfexpr);
- },
- _ => unreachable!()
+ if let Some(mutability) = self_kind {
+ let selfexpr = match mutability {
+ ast::Mutability::Immutable => quote_expr!(&ctx.ext_cx, &*self),
+ ast::Mutability::Mutable => quote_expr!(&ctx.ext_cx, &mut *self),
+ };
+ args.push(selfexpr);
}
match v.ty {
@@ -173,13 +169,12 @@ fn gen_unmangle_method(ctx: &mut GenCtx,
&*sig.ret_ty, sig.args.as_slice(),
false);
let mut unnamed: usize = 0;
- let iter = if args.len() > 0 {
+ let iter = if !args.is_empty() {
sig.args[1..].iter()
} else {
sig.args.iter()
};
- for arg in iter {
- let (ref n, _) = *arg;
+ for &(ref n, _) in iter {
let argname = if n.is_empty() {
unnamed += 1;
format!("arg{}", unnamed)
@@ -197,7 +192,7 @@ fn gen_unmangle_method(ctx: &mut GenCtx,
})
}),
span: ctx.span,
- attrs: None,
+ attrs: ast::ThinVec::new(),
};
args.push(P(expr));
}
@@ -205,38 +200,71 @@ fn gen_unmangle_method(ctx: &mut GenCtx,
_ => unreachable!()
};
+
+ if let Some(mutability) = self_kind {
+ assert!(!fndecl.inputs.is_empty());
+ fndecl.inputs[0] = ast::Arg {
+ ty: P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::TyKind::Rptr(None, ast::MutTy {
+ ty: P(ast::Ty {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::TyKind::ImplicitSelf,
+ span: ctx.span
+ }),
+ mutbl: mutability,
+ }),
+ span: ctx.span,
+ }),
+ pat: P(ast::Pat {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable),
+ respan(ctx.span, ctx.ext_cx.ident_of("self")),
+ None),
+ span: ctx.span,
+ }),
+ id: ast::DUMMY_NODE_ID,
+ };
+ }
+
let sig = ast::MethodSig {
unsafety: ast::Unsafety::Unsafe,
abi: Abi::Rust,
decl: P(fndecl),
generics: empty_generics(),
- explicit_self: respan(ctx.span, self_kind),
constness: ast::Constness::NotConst,
};
- let block = ast::Block {
- stmts: vec![],
- expr: Some(P(ast::Expr {
- id: ast::DUMMY_NODE_ID,
- node: ast::ExprKind::Call(
- P(ast::Expr {
- id: ast::DUMMY_NODE_ID,
- node: ast::ExprKind::Path(None, ast::Path {
- span: ctx.span,
- global: false,
- segments: vec!(ast::PathSegment {
- identifier: ctx.ext_cx.ident_of(&v.mangled),
- parameters: ast::PathParameters::none()
- })
- }),
+ let call = P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ExprKind::Call(
+ P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ExprKind::Path(None, ast::Path {
span: ctx.span,
- attrs: None,
+ global: false,
+ segments: vec![ast::PathSegment {
+ identifier: ctx.ext_cx.ident_of(&v.mangled),
+ parameters: ast::PathParameters::none()
+ }]
}),
- args
- ),
- span: ctx.span,
- attrs: None,
- })),
+ span: ctx.span,
+ attrs: ast::ThinVec::new(),
+ }),
+ args
+ ),
+ span: ctx.span,
+ attrs: ast::ThinVec::new(),
+ });
+
+ let block = ast::Block {
+ stmts: vec![
+ ast::Stmt {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::StmtKind::Expr(call),
+ span: ctx.span,
+ }
+ ],
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Default,
span: ctx.span
@@ -282,16 +310,12 @@ pub fn gen_mods(links: &[(String, LinkType)],
// Create a dummy ExtCtxt. We only need this for string interning and that uses TLS.
let mut features = Features::new();
features.quote = true;
- let cfg = ExpansionConfig {
- crate_name: "xxx".to_owned(),
- features: Some(&features),
- recursion_limit: 64,
- trace_mac: false,
- };
- let sess = &parse::ParseSess::new();
- let mut feature_gated_cfgs = vec![];
+
+ let cfg = ExpansionConfig::default("xxx".to_owned());
+ let sess = parse::ParseSess::new();
+ let mut loader = base::DummyMacroLoader;
let mut ctx = GenCtx {
- ext_cx: base::ExtCtxt::new(sess, vec![], cfg, &mut feature_gated_cfgs),
+ ext_cx: base::ExtCtxt::new(&sess, vec![], cfg, &mut loader),
options: options,
span: span,
module_map: map,
@@ -1220,11 +1244,11 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
TFuncPtr(ref sig) => {
let name = v.mangled.clone();
let explicit_self = if v.is_static {
- ast::SelfKind::Static
+ None
} else if v.is_const {
- ast::SelfKind::Region(None, ast::Mutability::Immutable, ctx.ext_cx.ident_of("self"))
+ Some(ast::Mutability::Immutable)
} else {
- ast::SelfKind::Region(None, ast::Mutability::Mutable, ctx.ext_cx.ident_of("self"))
+ Some(ast::Mutability::Mutable)
};
unmangledlist.push(gen_unmangle_method(ctx, &v, &mut unmangle_count, explicit_self));
mangledlist.push(cfunc_to_rs(ctx, name, String::new(), String::new(),
@@ -1698,8 +1722,6 @@ fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String,
variadic: false
};
- let stmts = Vec::with_capacity(bitfields.len() + 1);
-
let mut offset = 0;
let mut exprs = quote_expr!(&ctx.ext_cx, 0);
@@ -1721,8 +1743,13 @@ fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String,
}
let block = ast::Block {
- stmts: stmts,
- expr: Some(exprs),
+ stmts: vec![
+ ast::Stmt {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::StmtKind::Expr(exprs),
+ span: ctx.span,
+ }
+ ],
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Default,
span: ctx.span
@@ -1734,7 +1761,6 @@ fn gen_fullbitfield_method(ctx: &mut GenCtx, bindgen_name: &String,
abi: Abi::Rust,
decl: P(fndecl),
generics: empty_generics(),
- explicit_self: respan(ctx.span, ast::SelfKind::Static),
constness: ast::Constness::Const,
}, P(block)
);
@@ -2151,7 +2177,7 @@ fn mk_arrty(ctx: &GenCtx, base: &ast::Ty, n: usize) -> ast::Ty {
id: ast::DUMMY_NODE_ID,
node: sz,
span: ctx.span,
- attrs: None,
+ attrs: ast::ThinVec::new(),
})
);
diff --git a/src/lib.rs b/src/lib.rs
index 24876cc9..a72e9584 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -7,6 +7,7 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate syntex_syntax as syntax;
+extern crate clang_sys;
extern crate libc;
#[macro_use]
extern crate log;
@@ -15,8 +16,7 @@ use std::collections::HashSet;
use std::default::Default;
use std::io::{Write, self};
use std::fs::OpenOptions;
-use std::path::{Path, self};
-use std::{env, fs};
+use std::path::Path;
use syntax::ast;
use syntax::codemap::{DUMMY_SP, Span};
@@ -332,8 +332,7 @@ fn builtin_names() -> HashSet<String> {
}
#[test]
-fn builder_state()
-{
+fn builder_state() {
let logger = DummyLogger;
let mut build = builder();
{
@@ -345,70 +344,3 @@ fn builder_state()
assert!(build.options.clang_args.binary_search(&"example.h".to_owned()).is_ok());
assert!(build.options.links.binary_search(&("m".to_owned(), LinkType::Static)).is_ok());
}
-
-// Get the first directory in PATH that contains a file named "clang".
-fn get_clang_dir() -> Option<path::PathBuf>{
- if let Some(paths) = env::var_os("PATH") {
- for mut path in env::split_paths(&paths) {
- path.push("clang");
- if let Ok(real_path) = fs::canonicalize(&path) {
- if fs::metadata(&real_path).iter().any(|m| m.is_file()) &&
- real_path
- .file_name()
- .and_then(|f| f.to_str())
- .iter()
- .any(|&f| f.starts_with("clang")) {
- if let Some(dir) = real_path.parent() {
- return Some(dir.to_path_buf())
- }
- }
- }
- }
- }
- None
-}
-
-// Try to find the directory that contains clang's bundled headers. Clang itself does something
-// very similar: it takes the parent directory of the current executable, appends
-// "../lib/clang/<VERSIONSTRING>/include". We have two problems emulating this behaviour:
-// * We don't have a very good way of finding the clang executable, but can fake this by
-// searching $PATH and take one directory that contains "clang".
-// * We don't have access to <VERSIONSTRING>. There is clang_getClangVersion(), but it returns
-// a human-readable description string which is not guaranteed to be stable and a pain to parse.
-// We work around that by just taking the first directory in ../lib/clang and hope it's the
-// current version.
-// TODO: test if this works on Windows at all.
-#[doc(hidden)]
-pub fn get_include_dir() -> Option<String> {
- match get_clang_dir() {
- Some(mut p) => {
- p.push("..");
- p.push("lib");
- p.push("clang");
-
- let dir_iter = match fs::read_dir(p) {
- Ok(dir_iter) => dir_iter,
- _ => return None
- };
- for dir in dir_iter {
- match dir {
- Ok(dir) => {
- // Let's take the first dir. In my case, there's only one directory
- // there anyway.
- let mut p = dir.path();
- p.push("include");
- match p.into_os_string().into_string() {
- Ok(s) => return Some(s),
- // We found the directory, but can't access it as it contains
- // invalid unicode.
- _ => return None,
- }
- }
- _ => return None,
- }
- }
- None
- }
- None => None,
- }
-}