summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorge Aparicio <japaricious@gmail.com>2015-05-23 16:08:09 -0500
committerJorge Aparicio <japaricious@gmail.com>2015-05-23 16:12:42 -0500
commite9b2f7a2d401edf6b7662b187bd415253b072df5 (patch)
tree9165d317553d6b9d280c57d195350ca864341c68
parente0367f87c4a3234f3af6d5964792e2c825fe5fe6 (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.rs7
-rw-r--r--src/bin/bindgen.rs68
-rw-r--r--src/lib.rs70
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);
diff --git a/src/lib.rs b/src/lib.rs
index 6324785c..4b440647 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,
+ }
+}