diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-01-22 12:58:12 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-01-23 10:22:08 +0100 |
commit | b83da2729fc83663f979da05201920e039ae3c3f (patch) | |
tree | 27e1c8b1b7f0fef74b064740238da843d4cfc1f6 /src/options.rs | |
parent | 7373a4258f652c23e5fe00ad14740393caa40082 (diff) |
Unify under the `bindgen` name.
Diffstat (limited to 'src/options.rs')
-rw-r--r-- | src/options.rs | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/src/options.rs b/src/options.rs new file mode 100644 index 00000000..3456bfea --- /dev/null +++ b/src/options.rs @@ -0,0 +1,311 @@ +use clap::{App, Arg}; +use bindgen::{Builder, CodegenConfig, builder}; +use std::fs::File; +use std::io::{self, Error, ErrorKind}; + +/// Construct a new [`Builder`](./struct.Builder.html) from command line flags. +pub fn builder_from_flags<I>(args: I) + -> Result<(Builder, Box<io::Write>), io::Error> + where I: Iterator<Item = String>, +{ + let matches = App::new("bindgen") + .version(env!("CARGO_PKG_VERSION")) + .about("Generates Rust bindings from C/C++ headers.") + .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...") + .args(&[ + Arg::with_name("header") + .help("C or C++ header file") + .required(true), + Arg::with_name("bitfield-enum") + .long("bitfield-enum") + .help("Mark any enum whose name matches <regex> as a set of \ + bitfield flags instead of an enumeration.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("blacklist-type") + .long("blacklist-type") + .help("Mark a type as hidden.") + .value_name("type") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("builtins") + .long("builtins") + .help("Output bindings for builtin definitions, e.g. \ + __builtin_va_list."), + Arg::with_name("ctypes-prefix") + .long("ctypes-prefix") + .help("Use the given prefix before raw types instead of \ + ::std::os::raw.") + .value_name("prefix") + .takes_value(true), + // All positional arguments after the end of options marker, `--` + Arg::with_name("clang-args") + .multiple(true), + Arg::with_name("dummy-uses") + .long("dummy-uses") + .help("For testing purposes, generate a C/C++ file containing \ + dummy uses of all types defined in the input header.") + .takes_value(true), + Arg::with_name("emit-clang-ast") + .long("emit-clang-ast") + .help("Output the Clang AST for debugging purposes."), + Arg::with_name("emit-ir") + .long("emit-ir") + .help("Output our internal IR for debugging purposes."), + Arg::with_name("enable-cxx-namespaces") + .long("enable-cxx-namespaces") + .help("Enable support for C++ namespaces."), + Arg::with_name("disable-name-namespacing") + .long("disable-name-namespacing") + .help("Disable name namespacing if namespaces are disabled."), + Arg::with_name("framework") + .long("framework-link") + .help("Link to framework.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("ignore-functions") + .long("ignore-functions") + .help("Do not generate bindings for functions or methods. This \ + is useful when you only care about struct layouts."), + Arg::with_name("generate") + .long("generate") + .help("Generate a given kind of items, split by commas. \ + Valid values are \"functions\",\"types\", \"vars\" and \ + \"methods\".") + .takes_value(true), + Arg::with_name("ignore-methods") + .long("ignore-methods") + .help("Do not generate bindings for methods."), + Arg::with_name("dynamic") + .short("l") + .long("link") + .help("Link to dynamic library.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("no-convert-floats") + .long("no-convert-floats") + .help("Don't automatically convert floats to f32/f64."), + Arg::with_name("no-unstable-rust") + .long("no-unstable-rust") + .help("Do not generate unstable Rust code.") + .multiple(true), // FIXME: Pass legacy test suite + Arg::with_name("opaque-type") + .long("opaque-type") + .help("Mark a type as opaque.") + .value_name("type") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("output") + .short("o") + .long("output") + .help("Write Rust bindings to <output>.") + .takes_value(true), + Arg::with_name("raw-line") + .long("raw-line") + .help("Add a raw line of Rust code at the beginning of output.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("static") + .long("static-link") + .help("Link to static library.") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("use-core") + .long("use-core") + .help("Use types from Rust core instead of std."), + Arg::with_name("conservative-inline-namespaces") + .long("conservative-inline-namespaces") + .help("Conservatively generate inline namespaces to avoid name \ + conflicts."), + Arg::with_name("use-msvc-mangling") + .long("use-msvc-mangling") + .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."), + Arg::with_name("whitelist-function") + .long("whitelist-function") + .help("Whitelist all the free-standing functions matching \ + <regex>. Other non-whitelisted functions will not be \ + generated.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("whitelist-type") + .long("whitelist-type") + .help("Whitelist the type. Other non-whitelisted types will \ + not be generated.") + .value_name("type") + .takes_value(true) + .multiple(true) + .number_of_values(1), + Arg::with_name("whitelist-var") + .long("whitelist-var") + .help("Whitelist all the free-standing variables matching \ + <regex>. Other non-whitelisted variables will not be \ + generated.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), + ]) // .args() + .get_matches_from(args); + + let mut builder = builder(); + + if let Some(header) = matches.value_of("header") { + builder = builder.header(header); + } else { + return Err(Error::new(ErrorKind::Other, "Header not found")); + } + + if let Some(bitfields) = matches.values_of("bitfield-enum") { + for regex in bitfields { + builder = builder.bitfield_enum(regex); + } + } + + if let Some(hidden_types) = matches.values_of("blacklist-type") { + for ty in hidden_types { + builder = builder.hide_type(ty); + } + } + + if matches.is_present("builtins") { + builder = builder.emit_builtins(); + } + + if let Some(prefix) = matches.value_of("ctypes-prefix") { + builder = builder.ctypes_prefix(prefix); + } + + if let Some(dummy) = matches.value_of("dummy-uses") { + builder = builder.dummy_uses(dummy); + } + + if let Some(links) = matches.values_of("dynamic") { + for library in links { + builder = builder.link(library); + } + } + + if let Some(what_to_generate) = matches.value_of("generate") { + let mut config = CodegenConfig::nothing(); + for what in what_to_generate.split(",") { + match what { + "functions" => config.functions = true, + "types" => config.types = true, + "vars" => config.vars = true, + "methods" => config.methods = true, + _ => { + return Err(Error::new(ErrorKind::Other, + "Unknown generate item")); + } + } + } + builder = builder.with_codegen_config(config); + } + + if matches.is_present("emit-clang-ast") { + builder = builder.emit_clang_ast(); + } + + if matches.is_present("emit-ir") { + builder = builder.emit_ir(); + } + + if matches.is_present("enable-cxx-namespaces") { + builder = builder.enable_cxx_namespaces(); + } + + if matches.is_present("disable-name-namespacing") { + builder = builder.disable_name_namespacing(); + } + + if let Some(links) = matches.values_of("framework") { + for framework in links { + builder = builder.link_framework(framework); + } + } + + if matches.is_present("ignore-functions") { + builder = builder.ignore_functions(); + } + + if matches.is_present("ignore-methods") { + builder = builder.ignore_methods(); + } + + if matches.is_present("no-unstable-rust") { + builder = builder.no_unstable_rust(); + } + + if matches.is_present("no-convert-floats") { + builder = builder.no_convert_floats(); + } + + if let Some(opaque_types) = matches.values_of("opaque-type") { + for ty in opaque_types { + builder = builder.opaque_type(ty); + } + } + + if let Some(lines) = matches.values_of("raw-line") { + for line in lines { + builder = builder.raw_line(line); + } + } + + if let Some(links) = matches.values_of("static") { + for library in links { + builder = builder.link_static(library); + } + } + + if matches.is_present("use-core") { + builder = builder.use_core(); + } + + if matches.is_present("conservative-inline-namespaces") { + builder = builder.conservative_inline_namespaces(); + } + + if let Some(whitelist) = matches.values_of("whitelist-function") { + for regex in whitelist { + builder = builder.whitelisted_function(regex); + } + } + + if let Some(whitelist) = matches.values_of("whitelist-type") { + for regex in whitelist { + builder = builder.whitelisted_type(regex); + } + } + + if let Some(whitelist) = matches.values_of("whitelist-var") { + for regex in whitelist { + builder = builder.whitelisted_var(regex); + } + } + + if let Some(args) = matches.values_of("clang-args") { + for arg in args { + builder = builder.clang_arg(arg); + } + } + + let output = if let Some(path) = matches.value_of("output") { + let file = try!(File::create(path)); + Box::new(io::BufWriter::new(file)) as Box<io::Write> + } else { + Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write> + }; + + Ok((builder, output)) +} |