diff options
author | Jorge Aparicio <japaricious@gmail.com> | 2015-05-23 16:08:09 -0500 |
---|---|---|
committer | Jorge Aparicio <japaricious@gmail.com> | 2015-05-23 16:12:42 -0500 |
commit | e9b2f7a2d401edf6b7662b187bd415253b072df5 (patch) | |
tree | 9165d317553d6b9d280c57d195350ca864341c68 | |
parent | e0367f87c4a3234f3af6d5964792e2c825fe5fe6 (diff) |
add `-I /path/to/clang/include` to clang args used in the `bindgen!` plugin
We do the same thing for the `bindgen` binary (see #196).
-rw-r--r-- | bindgen_plugin/src/bgmacro.rs | 7 | ||||
-rw-r--r-- | src/bin/bindgen.rs | 68 | ||||
-rw-r--r-- | src/lib.rs | 70 |
3 files changed, 76 insertions, 69 deletions
diff --git a/bindgen_plugin/src/bgmacro.rs b/bindgen_plugin/src/bgmacro.rs index 8faac8cc..106b9451 100644 --- a/bindgen_plugin/src/bgmacro.rs +++ b/bindgen_plugin/src/bgmacro.rs @@ -11,7 +11,7 @@ use syntax::parse::token; use syntax::ptr::P; use syntax::util::small_vector::SmallVector; -use bindgen::{Bindings, BindgenOptions, LinkType, Logger}; +use bindgen::{Bindings, BindgenOptions, LinkType, Logger, self}; pub fn bindgen_macro(cx: &mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'static> { let mut visit = BindgenArgsVisitor { @@ -28,6 +28,11 @@ pub fn bindgen_macro(cx: &mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::Toke let clang_args = visit.options.clang_args.connect(" "); visit.options.clang_args = parse_process_args(&clang_args[..]); + if let Some(path) = bindgen::get_include_dir() { + visit.options.clang_args.push("-I".to_owned()); + visit.options.clang_args.push(path); + } + // Set the working dir to the directory containing the invoking rs file so // that clang searches for headers relative to it rather than the crate root let filename = cx.codemap().span_to_filename(sp); diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index 1abccc5d..08267665 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -158,77 +158,11 @@ Options: print!("{}", &s[..]); } -// Get the first directory in PATH that contains a file named "clang". -fn get_clang_dir() -> Option<path::PathBuf>{ - match env::var_os("PATH") { - Some(paths) => { - for p in env::split_paths(&paths) { - let mut bin_path = p.clone(); - bin_path.push("clang"); - match fs::metadata(bin_path) { - Ok(m) => { - if m.is_file() { - return Some(p); - } - } - _ => (), - } - } - None - } - None => 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. -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, - } -} - pub fn main() { let mut bind_args: Vec<_> = env::args().collect(); let bin = bind_args.remove(0); - match get_include_dir() { + match bindgen::get_include_dir() { Some(path) => { bind_args.push("-I".to_owned()); bind_args.push(path); @@ -9,7 +9,8 @@ use std::collections::HashSet; use std::default::Default; use std::io::{Write, self}; use std::fs::OpenOptions; -use std::path::Path; +use std::path::{Path, self}; +use std::{env, fs}; use syntax::ast; use syntax::codemap::{DUMMY_SP, Span}; @@ -250,3 +251,70 @@ fn builder_state() assert!(build.options.clang_args.binary_search(&"example.h".to_string()).is_ok()); assert!(build.options.links.binary_search(&("m".to_string(), LinkType::Static)).is_ok()); } + +// Get the first directory in PATH that contains a file named "clang". +fn get_clang_dir() -> Option<path::PathBuf>{ + match env::var_os("PATH") { + Some(paths) => { + for p in env::split_paths(&paths) { + let mut bin_path = p.clone(); + bin_path.push("clang"); + match fs::metadata(bin_path) { + Ok(m) => { + if m.is_file() { + return Some(p); + } + } + _ => (), + } + } + None + } + None => 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, + } +} |