summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml51
-rwxr-xr-x[-rw-r--r--]src/bin/bindgen.rs389
-rwxr-xr-x[-rw-r--r--]src/lib.rs0
-rw-r--r--tests/headers/class_no_members.hpp2
-rw-r--r--tests/headers/class_with_inner_struct.hpp2
-rw-r--r--tests/headers/class_with_typedef.hpp2
-rw-r--r--tests/headers/crtp.hpp2
-rw-r--r--tests/headers/duplicated_constants_in_ns.hpp2
-rw-r--r--tests/headers/enum_explicit_type.hpp2
-rw-r--r--tests/headers/jsval_layout_opaque.hpp2
-rw-r--r--tests/headers/namespace.hpp2
-rw-r--r--tests/headers/only_bitfields.hpp2
-rw-r--r--tests/headers/opaque_typedef.hpp2
-rw-r--r--tests/headers/overflowed_enum.hpp2
-rw-r--r--tests/headers/struct_with_bitfields.h2
-rw-r--r--tests/headers/union_with_anon_struct_bitfield.h2
-rw-r--r--tests/headers/using.hpp2
-rw-r--r--tests/headers/vtable_recursive_sig.hpp2
-rw-r--r--tests/headers/weird_bitfields.hpp2
-rwxr-xr-xtests/tools/run-bindgen.py35
20 files changed, 256 insertions, 251 deletions
diff --git a/Cargo.toml b/Cargo.toml
index f9a9c6b7..04a13eb4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,38 +1,49 @@
[package]
-name = "bindgen"
-version = "0.16.0"
-description = "A binding generator for Rust"
authors = ["Jyun-Yan You <jyyou.tw@gmail.com>"]
-license = "BSD-3-Clause"
+build = "build.rs"
+description = "A binding generator for Rust"
homepage = "https://github.com/crabtw/rust-bindgen"
-repository = "https://github.com/crabtw/rust-bindgen"
+keywords = ["bindings", "ffi", "code-generation"]
+license = "BSD-3-Clause"
+name = "bindgen"
readme = "README.md"
-keywords = [ "bindings", "ffi", "code-generation" ]
-build = "build.rs"
+repository = "https://github.com/crabtw/rust-bindgen"
+version = "0.16.0"
-[dependencies]
-aster = { version = "0.21.1", features = ["with-syntex"] }
-quasi = { version = "0.15", features = ["with-syntex"] }
-clippy = { version = "*", optional = true }
-syntex_syntax = "0.38"
-log = "0.3.*"
-libc = "0.2.*"
-clang-sys = "0.8.0"
+[[bin]]
+doc = false
+name = "bindgen"
[build-dependencies]
quasi_codegen = "0.15"
+[dependencies]
+clang-sys = "0.8.0"
+docopt = "0.6.82"
+libc = "0.2.*"
+log = "0.3.*"
+rustc-serialize = "0.3.19"
+syntex_syntax = "0.38"
+
+[dependencies.aster]
+features = ["with-syntex"]
+version = "0.21.1"
+
+[dependencies.clippy]
+optional = true
+version = "*"
+
+[dependencies.quasi]
+features = ["with-syntex"]
+version = "0.15"
+
[features]
-static = []
llvm_stable = []
+static = []
[lib]
name = "bindgen"
path = "src/lib.rs"
-[[bin]]
-name = "bindgen"
-doc = false
-
[[test]]
name = "tests"
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs
index 08eb2d89..fbd3c457 100644..100755
--- a/src/bin/bindgen.rs
+++ b/src/bin/bindgen.rs
@@ -3,8 +3,11 @@
extern crate bindgen;
#[macro_use]
+extern crate docopt;
+#[macro_use]
extern crate log;
extern crate clang_sys;
+extern crate rustc_serialize;
use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
use std::io;
@@ -26,214 +29,177 @@ impl Logger for StdLogger {
}
}
-enum ParseResult {
- CmdUsage,
- ParseOk(BindgenOptions, Box<io::Write>),
- ParseErr(String)
+const USAGE: &'static str = "
+Usage:
+ bindgen [options] \
+ [--link=<lib>...] \
+ [--static-link=<lib>...] \
+ [--framework-link=<framework>...] \
+ [--match=<name>...] \
+ [--raw-line=<raw>...] \
+ [--dtor-attr=<attr>...] \
+ [--opaque-type=<type>...] \
+ [--blacklist-type=<type>...] \
+ <input-header> \
+ [-- <clang-args>...]
+
+ bindgen (-h | --help)
+
+Options:
+ -h, --help Display this help message.
+
+ -l=<lib>, --link=<lib> Link to a dynamic library, can be provided
+ multiple times.
+
+ --static-link=<lib> Link to a static library, can be provided
+ multiple times.
+
+ --framework-link=<framework> Link to a framework.
+
+ -o=<output-rust-file> Write bindings to <output-rust-file>
+ (defaults to stdout)
+
+ --match=<name> Only output bindings for definitions from
+ files whose name contains <name>. If multiple
+ match options are provided, files matching any
+ rule are bound to.
+
+ --builtins Output bindings for builtin definitions (for
+ example __builtin_va_list)
+
+ --ignore-functions Don't generate bindings for functions and
+ methods. This is useful when you only care
+ about struct layouts.
+
+ --enable-cxx-namespaces Enable support for C++ namespaces.
+
+ --no-type-renaming Don't rename types.
+
+ --allow-unknown-types Don't fail if we encounter types we do not
+ support, instead treat them as void
+
+ --emit-clang-ast Output the ast (for debugging purposes)
+
+ --use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
+ target be set to (i686|x86_64)-pc-win32
+
+ --override-enum-type=<type> Override enum type, type name could be
+ uchar
+ schar
+ ushort
+ sshort
+ uint
+ sint
+ ulong
+ slong
+ ulonglong
+ slonglong
+
+ --raw-line=<raw> TODO
+ --dtor-attr=<attr> TODO
+ --no-class-constants TODO
+ --no-unstable-rust TODO
+ --no-namespaced-constants TODO
+ --no-bitfield-methods TODO
+ --ignore-methods TODO
+ --opaque-type=<type> TODO
+ --blacklist-type=<type> TODO
+
+ <clang-args> Options other than stated above are passed
+ directly through to clang.
+";
+
+#[derive(Debug, RustcDecodable)]
+struct Args {
+ arg_input_header: String,
+ flag_link: Vec<String>,
+ flag_static_link: Vec<String>,
+ flag_framework_link: Vec<String>,
+ flag_o: Option<String>,
+ flag_match: Vec<String>,
+ flag_builtins: bool,
+ flag_ignore_functions: bool,
+ flag_enable_cxx_namespaces: bool,
+ flag_no_type_renaming: bool,
+ flag_allow_unknown_types: bool,
+ flag_emit_clang_ast: bool,
+ flag_use_msvc_mangling: bool,
+ flag_override_enum_type: String,
+ flag_raw_line: Vec<String>,
+ flag_dtor_attr: Vec<String>,
+ flag_no_class_constants: bool,
+ flag_no_unstable_rust: bool,
+ flag_no_namespaced_constants: bool,
+ flag_no_bitfield_methods: bool,
+ flag_ignore_methods: bool,
+ flag_opaque_type: Vec<String>,
+ flag_blacklist_type: Vec<String>,
+ arg_clang_args: Vec<String>,
}
-fn parse_args(args: &[String]) -> ParseResult {
- let args_len = args.len();
+type ParseResult<T> = Result<T, String>;
- let mut options: BindgenOptions = Default::default();
- let mut out = Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>;
+impl Into<ParseResult<(BindgenOptions, Box<io::Write>)>> for Args {
+ fn into(mut self) -> Result<(BindgenOptions, Box<io::Write>), String> {
+ let mut options: BindgenOptions = Default::default();
- if args_len == 0 {
- return ParseResult::CmdUsage;
- }
+ options.clang_args.push(self.arg_input_header);
- let mut ix: usize = 0;
- while ix < args_len {
- if args[ix].len() > 2 && &args[ix][..2] == "-l" {
- options.links.push((args[ix][2..].to_string(), LinkType::Default));
- ix += 1;
- } else {
- match &*args[ix] {
- "--help" | "-h" => {
- return ParseResult::CmdUsage;
- }
- "-emit-clang-ast" => {
- options.emit_ast = true;
- ix += 1;
- }
- "-o" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing output filename".to_string());
- }
- let path = path::Path::new(&args[ix + 1]);
- match fs::File::create(&path) {
- Ok(f) => { out = Box::new(io::BufWriter::new(f)) as Box<io::Write>; }
- Err(_) => { return ParseResult::ParseErr(format!("Open {} failed", args[ix + 1])); }
- }
- ix += 2;
- }
- "-l" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing link name".to_string());
- }
- options.links.push((args[ix + 1].clone(), LinkType::Default));
- ix += 2;
- }
- "-static-link" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing link name".to_string());
- }
- options.links.push((args[ix + 1].clone(), LinkType::Static));
- ix += 2;
- }
- "-framework-link" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing link name".to_string());
- }
- options.links.push((args[ix + 1].clone(), LinkType::Framework));
- ix += 2;
- }
- "-match" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing match pattern".to_string());
- }
- options.match_pat.push(args[ix + 1].clone());
- ix += 2;
- }
- "-blacklist-type" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing blacklist type name".to_string());
- }
- options.blacklist_type.push(args[ix + 1].clone());
- ix += 2;
- }
- "-opaque-type" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing opaque type name".to_string());
- }
- options.opaque_types.push(args[ix + 1].clone());
- ix += 2;
- }
- "-builtins" => {
- options.builtins = true;
- ix += 1;
- }
- "-ignore-functions" => {
- options.ignore_functions = true;
- ix += 1;
- }
- "-ignore-methods" => {
- options.ignore_methods = true;
- ix += 1;
- }
- "-no-bitfield-methods" => {
- options.gen_bitfield_methods = false;
- ix += 1;
- }
- "-no-namespaced-constants" => {
- options.namespaced_constants = false;
- ix += 1;
- }
- "-no-unstable-rust" => {
- options.unstable_rust = false;
- ix += 1;
- }
- "-no-class-constants" => {
- options.class_constants = false;
- ix += 1;
- }
- "-dtor-attr" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing dtor attr".to_string());
- }
- options.dtor_attrs.push(args[ix + 1].clone());
- ix += 2;
- }
- "-allow-unknown-types" => {
- options.fail_on_unknown_type = false;
- ix += 1;
- }
- "-override-enum-type" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing enum type".to_string());
- }
- options.override_enum_ty = args[ix + 1].clone();
- ix += 2;
- }
- "-enable-cxx-namespaces" => {
- options.enable_cxx_namespaces = true;
- ix += 1;
- }
- "-no-type-renaming" => {
- options.rename_types = false;
- ix += 1;
- }
- "-raw-line" => {
- if ix + 1 >= args_len {
- return ParseResult::ParseErr("Missing raw-line argument".to_string());
- }
- options.raw_lines.push(args[ix + 1].clone());
- ix += 2;
- }
- "-use-msvc-mangling" => {
- options.msvc_mangling = true;
- ix += 1;
- }
- _ => {
- options.clang_args.push(args[ix].clone());
- ix += 1;
- }
- }
+ for lib in self.flag_link.drain(..) {
+ options.links.push((lib, LinkType::Default));
}
- }
- return ParseResult::ParseOk(options, out);
-}
+ for lib in self.flag_static_link.drain(..) {
+ options.links.push((lib, LinkType::Static));
+ }
-fn print_usage(bin: String) {
- let mut s = format!("Usage: {} [options] input.h", &bin);
- s.push_str(
-"
-Options:
- -h or --help Display help message
- -l <name> or -l<name> Link to a dynamic library, can be provided
- multiple times
- -static-link <name> Link to a static library
- -framework-link <name> Link to a framework
- -o <output.rs> Write bindings to <output.rs> (default stdout)
- -match <name> Only output bindings for definitions from files
- whose name contains <name>
- If multiple -match options are provided, files
- matching any rule are bound to.
- -builtins Output bindings for builtin definitions
- (for example __builtin_va_list)
- -ignore-functions Don't generate bindings for functions and methods.
- This is useful when you only care about struct layouts.
- -enable-cxx-namespaces Enable support for C++ namespaces.
- -no-type-renaming Don't rename types.
- -allow-unknown-types Don't fail if we encounter types we do not support,
- instead treat them as void
- -emit-clang-ast Output the ast (for debugging purposes)
- -use-msvc-mangling Handle MSVC C++ ABI mangling; requires that --target
- be set to (i686|x86_64)-pc-win32
- -override-enum-type <type> Override enum type, type name could be
- uchar
- schar
- ushort
- sshort
- uint
- sint
- ulong
- slong
- ulonglong
- slonglong
-
- Options other than stated above are passed to clang.
-"
- );
- println!("{}", &s);
+ for lib in self.flag_framework_link.drain(..) {
+ options.links.push((lib, LinkType::Framework));
+ }
+
+ let out = if let Some(ref path_name) = self.flag_o {
+ let path = path::Path::new(path_name);
+ let file = try!(fs::File::create(path).map_err(|_| {
+ format!("Opening {} failed", path_name)
+ }));
+ Box::new(io::BufWriter::new(file)) as Box<io::Write>
+ } else {
+ Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
+ };
+
+ options.match_pat.extend(self.flag_match.drain(..));
+ options.builtins = self.flag_builtins;
+ options.ignore_functions = self.flag_ignore_functions;
+ options.enable_cxx_namespaces = self.flag_enable_cxx_namespaces;
+ options.rename_types = !self.flag_no_type_renaming;
+ options.fail_on_unknown_type = !self.flag_allow_unknown_types;
+ options.emit_ast = self.flag_emit_clang_ast;
+ options.msvc_mangling = self.flag_use_msvc_mangling;
+ options.override_enum_ty = self.flag_override_enum_type;
+ options.raw_lines.extend(self.flag_raw_line.drain(..));
+ options.dtor_attrs.extend(self.flag_dtor_attr.drain(..));
+ options.class_constants = !self.flag_no_class_constants;
+ options.unstable_rust = !self.flag_no_unstable_rust;
+ options.namespaced_constants = !self.flag_no_namespaced_constants;
+ options.gen_bitfield_methods = !self.flag_no_bitfield_methods;
+ options.ignore_methods = self.flag_ignore_methods;
+ options.opaque_types.extend(self.flag_opaque_type.drain(..));
+ options.blacklist_type.extend(self.flag_blacklist_type.drain(..));
+ options.clang_args.extend(self.arg_clang_args.drain(..));
+
+ Ok((options, out))
+ }
}
pub fn main() {
let mut bind_args: Vec<_> = env::args().collect();
- let bin = bind_args.remove(0);
if let Some(clang) = clang_sys::support::Clang::find(None) {
+ let has_clang_args = bind_args.iter().rposition(|arg| *arg == "--").is_some();
+ if !has_clang_args {
+ bind_args.push("--".to_owned());
+ }
+
// 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() {
@@ -243,21 +209,28 @@ pub fn main() {
}
}
- match parse_args(&bind_args) {
- ParseResult::ParseErr(e) => panic!(e),
- ParseResult::CmdUsage => print_usage(bin),
- ParseResult::ParseOk(options, out) => {
- let logger = StdLogger;
- match Bindings::generate(&options, Some(&logger as &Logger), None) {
- Ok(bindings) => match bindings.write(out) {
- Ok(()) => (),
- Err(e) => {
- logger.error(&format!("Unable to write bindings to file. {}", e));
- exit(-1);
- }
- },
- Err(()) => exit(-1)
+ let args: Args = docopt::Docopt::new(USAGE)
+ .and_then(|d| d.argv(bind_args.iter()).decode())
+ .unwrap_or_else(|e| e.exit());
+
+ let logger = StdLogger;
+ let result: ParseResult<_> = args.into();
+ let (options, out) = result.unwrap_or_else(|msg| {
+ logger.error(&msg);
+ exit(-1);
+ });
+
+ match Bindings::generate(&options, Some(&logger as &Logger), None) {
+ Ok(bindings) => match bindings.write(out) {
+ Ok(()) => (),
+ Err(e) => {
+ logger.error(&format!("Unable to write bindings to file. {}", e));
+ exit(-1);
}
+ },
+ Err(()) => {
+ logger.error("Failed to generate bindings".into());
+ exit(-1);
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index a6b33c8e..a6b33c8e 100644..100755
--- a/src/lib.rs
+++ b/src/lib.rs
diff --git a/tests/headers/class_no_members.hpp b/tests/headers/class_no_members.hpp
index b8e1b2fa..a4483558 100644
--- a/tests/headers/class_no_members.hpp
+++ b/tests/headers/class_no_members.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11
+// bindgen-flags: -- -std=c++11
class whatever {
};
diff --git a/tests/headers/class_with_inner_struct.hpp b/tests/headers/class_with_inner_struct.hpp
index c96b0daf..ec729fe6 100644
--- a/tests/headers/class_with_inner_struct.hpp
+++ b/tests/headers/class_with_inner_struct.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11
+// bindgen-flags: -- -std=c++11
class A {
unsigned c;
diff --git a/tests/headers/class_with_typedef.hpp b/tests/headers/class_with_typedef.hpp
index a9ad3823..f36c7b5d 100644
--- a/tests/headers/class_with_typedef.hpp
+++ b/tests/headers/class_with_typedef.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-type-renaming
+// bindgen-flags: --no-type-renaming
typedef int AnotherInt;
diff --git a/tests/headers/crtp.hpp b/tests/headers/crtp.hpp
index 3a3eeb60..1f799b3d 100644
--- a/tests/headers/crtp.hpp
+++ b/tests/headers/crtp.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-type-renaming
+// bindgen-flags: --no-type-renaming
template<class T>
class Base {};
diff --git a/tests/headers/duplicated_constants_in_ns.hpp b/tests/headers/duplicated_constants_in_ns.hpp
index 1f20af35..42197a16 100644
--- a/tests/headers/duplicated_constants_in_ns.hpp
+++ b/tests/headers/duplicated_constants_in_ns.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-namespaced-constants
+// bindgen-flags: --no-namespaced-constants
namespace foo {
const int FOO = 4;
}
diff --git a/tests/headers/enum_explicit_type.hpp b/tests/headers/enum_explicit_type.hpp
index b99951ba..4acb3f15 100644
--- a/tests/headers/enum_explicit_type.hpp
+++ b/tests/headers/enum_explicit_type.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11
+// bindgen-flags: -- -std=c++11
enum Foo: unsigned char {
Bar = 0,
diff --git a/tests/headers/jsval_layout_opaque.hpp b/tests/headers/jsval_layout_opaque.hpp
index db09cb54..d432d8d3 100644
--- a/tests/headers/jsval_layout_opaque.hpp
+++ b/tests/headers/jsval_layout_opaque.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11 -match jsval_layout_opaque.hpp -no-type-renaming -no-unstable-rust
+// bindgen-flags: --match jsval_layout_opaque.hpp --no-type-renaming --no-unstable-rust -- -std=c++11
#include <stdint.h>
#include <stddef.h>
diff --git a/tests/headers/namespace.hpp b/tests/headers/namespace.hpp
index e69158d7..65788539 100644
--- a/tests/headers/namespace.hpp
+++ b/tests/headers/namespace.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -enable-cxx-namespaces
+// bindgen-flags: --enable-cxx-namespaces
void top_level();
diff --git a/tests/headers/only_bitfields.hpp b/tests/headers/only_bitfields.hpp
index 30a75ebb..84db0586 100644
--- a/tests/headers/only_bitfields.hpp
+++ b/tests/headers/only_bitfields.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-unstable-rust
+// bindgen-flags: --no-unstable-rust
class C {
bool a: 1;
bool b: 7;
diff --git a/tests/headers/opaque_typedef.hpp b/tests/headers/opaque_typedef.hpp
index 23bb363a..2d9a5781 100644
--- a/tests/headers/opaque_typedef.hpp
+++ b/tests/headers/opaque_typedef.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11
+// bindgen-flags: -- -std=c++11
template<typename T>
class RandomTemplate;
diff --git a/tests/headers/overflowed_enum.hpp b/tests/headers/overflowed_enum.hpp
index 6ddc7349..1f2075a5 100644
--- a/tests/headers/overflowed_enum.hpp
+++ b/tests/headers/overflowed_enum.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11 -Wno-narrowing
+// bindgen-flags: -- -std=c++11 -Wno-narrowing
enum Foo {
BAP_ARM = 0x93fcb9,
diff --git a/tests/headers/struct_with_bitfields.h b/tests/headers/struct_with_bitfields.h
index b994da4e..107fb136 100644
--- a/tests/headers/struct_with_bitfields.h
+++ b/tests/headers/struct_with_bitfields.h
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-unstable-rust
+// bindgen-flags: --no-unstable-rust
struct bitfield {
unsigned short
a :1,
diff --git a/tests/headers/union_with_anon_struct_bitfield.h b/tests/headers/union_with_anon_struct_bitfield.h
index 5a6fc7bc..24c7dce8 100644
--- a/tests/headers/union_with_anon_struct_bitfield.h
+++ b/tests/headers/union_with_anon_struct_bitfield.h
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-unstable-rust
+// bindgen-flags: --no-unstable-rust
union foo {
int a;
struct {
diff --git a/tests/headers/using.hpp b/tests/headers/using.hpp
index fb848fd6..ba07b9c8 100644
--- a/tests/headers/using.hpp
+++ b/tests/headers/using.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11
+// bindgen-flags: -- -std=c++11
template<typename T>
class Point {
diff --git a/tests/headers/vtable_recursive_sig.hpp b/tests/headers/vtable_recursive_sig.hpp
index 4e5af806..1556f866 100644
--- a/tests/headers/vtable_recursive_sig.hpp
+++ b/tests/headers/vtable_recursive_sig.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -std=c++11 -no-type-renaming
+// bindgen-flags: --no-type-renaming -- -std=c++11
class Derived;
class Base {
diff --git a/tests/headers/weird_bitfields.hpp b/tests/headers/weird_bitfields.hpp
index e8287507..755681c1 100644
--- a/tests/headers/weird_bitfields.hpp
+++ b/tests/headers/weird_bitfields.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: -no-unstable-rust
+// bindgen-flags: --no-unstable-rust
// You can guess where this is taken from...
enum nsStyleSVGOpacitySource {
eStyleSVGOpacitySource_Normal,
diff --git a/tests/tools/run-bindgen.py b/tests/tools/run-bindgen.py
index 2054924f..bb58bc3a 100755
--- a/tests/tools/run-bindgen.py
+++ b/tests/tools/run-bindgen.py
@@ -6,27 +6,48 @@ import subprocess
import tempfile
BINDGEN_FLAGS_PREFIX = "// bindgen-flags: ";
+CLANG_FLAGS_SEPARATOR = "-- "
COMMON_PRELUDE = """
#![allow(non_snake_case)]
"""
if len(sys.argv) != 4:
print("Usage: {} [bindgen-path] [c-path] [rust-path]\n".format(sys.argv[0]))
+ sys.exit(1)
+
+[_, bindgen_path, c_path, rust_path] = sys.argv
+
+flags = []
+clang_flags = []
-flags = [];
with open(sys.argv[2]) as f:
for line in f:
if line.startswith(BINDGEN_FLAGS_PREFIX):
- flags = line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(' ')
+ flags = line.strip().split(BINDGEN_FLAGS_PREFIX)[1]
+
+ try:
+ idx = flags.index(CLANG_FLAGS_SEPARATOR)
+ clang_flags = flags[idx + len(CLANG_FLAGS_SEPARATOR):].split(" ")
+ flags = flags[:idx]
+ except ValueError:
+ pass
-base_command = [sys.argv[1], "-o", sys.argv[3]]
+ flags = flags.split(" ")
+ break
-for line in COMMON_PRELUDE.split('\n'):
- flags.append("-raw-line")
+base_command = [bindgen_path, "-o", rust_path]
+
+for line in COMMON_PRELUDE.split("\n"):
+ flags.append("--raw-line")
flags.append(line)
-base_command.extend(flags);
-base_command.append(sys.argv[2]);
+base_command.extend(flags)
+base_command.append(c_path)
+
+if len(clang_flags):
+ base_command.append("--")
+ base_command.extend(clang_flags)
+
env = os.environ.copy()
# El Capitan likes to unset dyld variables