diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-08-27 02:12:17 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-27 02:12:17 -0500 |
commit | 0af8bd514838b70fb3bc1d99738b5ff5ab7d7662 (patch) | |
tree | 92213df3a8cc828aedf4c55f842fbace96abe402 | |
parent | bc36f9e4779ad01cf1aeabd0c35d1ea2818fe0a6 (diff) | |
parent | 182682735aadaad8d0e099b41839fb3b0dcf0fdc (diff) |
Auto merge of #44 - fitzgen:use-docopt-for-args, r=emilio
Use docopt for argument parsing
This commit switches bindgen over to using the docopt crate for argument parsing
instead of manual argument parsing. This required two notable changes in the
arguments and flags style:
1. All flags of the form `-foo` are now of the form `--foo`.
2. We can no longer pass unknown flags straight through to clang. Instead, the
user appends `--` after the bindgen flags and input header, after which point
any more flags and arguments get collected and passed to clang. This required
changes to the test runner and the `// bindgen-flags` comments.
r? @emilio
-rw-r--r-- | Cargo.toml | 51 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bin/bindgen.rs | 389 | ||||
-rwxr-xr-x[-rw-r--r--] | src/lib.rs | 0 | ||||
-rw-r--r-- | tests/headers/class_no_members.hpp | 2 | ||||
-rw-r--r-- | tests/headers/class_with_inner_struct.hpp | 2 | ||||
-rw-r--r-- | tests/headers/class_with_typedef.hpp | 2 | ||||
-rw-r--r-- | tests/headers/crtp.hpp | 2 | ||||
-rw-r--r-- | tests/headers/duplicated_constants_in_ns.hpp | 2 | ||||
-rw-r--r-- | tests/headers/enum_explicit_type.hpp | 2 | ||||
-rw-r--r-- | tests/headers/jsval_layout_opaque.hpp | 2 | ||||
-rw-r--r-- | tests/headers/namespace.hpp | 2 | ||||
-rw-r--r-- | tests/headers/only_bitfields.hpp | 2 | ||||
-rw-r--r-- | tests/headers/opaque_typedef.hpp | 2 | ||||
-rw-r--r-- | tests/headers/overflowed_enum.hpp | 2 | ||||
-rw-r--r-- | tests/headers/struct_with_bitfields.h | 2 | ||||
-rw-r--r-- | tests/headers/union_with_anon_struct_bitfield.h | 2 | ||||
-rw-r--r-- | tests/headers/using.hpp | 2 | ||||
-rw-r--r-- | tests/headers/vtable_recursive_sig.hpp | 2 | ||||
-rw-r--r-- | tests/headers/weird_bitfields.hpp | 2 | ||||
-rwxr-xr-x | tests/tools/run-bindgen.py | 35 |
20 files changed, 256 insertions, 251 deletions
@@ -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 |