Skip to content

Clap your hands say yeah! 👏🏻 #228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ quasi_codegen = "0.20"
[dependencies]
cfg-if = "0.1.0"
clang-sys = "0.8.0"
clap = "2"
lazy_static = "0.1.*"
libc = "0.2"
log = "0.3"
Expand Down
266 changes: 18 additions & 248 deletions src/bin/bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,248 +6,14 @@ extern crate env_logger;
#[macro_use]
extern crate log;
extern crate clang_sys;
extern crate clap;
extern crate rustc_serialize;

use bindgen::{BindgenOptions, Bindings, LinkType, clang_version};
use std::default::Default;
use bindgen::clang_version;
use std::env;
use std::fs;
use std::io;
use std::path;
use std::process;

const USAGE: &'static str = "
Usage:
bindgen [options] \
[--link=<lib>...] \
[--static-link=<lib>...] \
[--framework-link=<framework>...] \
[--raw-line=<raw>...] \
[--opaque-type=<type>...] \
[--blacklist-type=<type>...] \
[--whitelist-type=<type>...] \
[--whitelist-function=<name>...] \
[--whitelist-var=<name>...] \
[--bitfield-enum=<name>...] \
<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)

--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.

--ignore-methods Avoid generating all kind of methods.

--enable-cxx-namespaces Enable support for C++ namespaces.

--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

--no-convert-floats Don't convert floats automatically to f32/f64.

--raw-line=<raw> Add a raw line at the beginning of the output.

--no-unstable-rust Avoid generating unstable rust.

--use-core Use built-in types from core instead of std.

--ctypes-prefix=<prefix> Use the given prefix before the raw types
instead of ::std::os::raw::.

--opaque-type=<type> Mark a type as opaque.

--blacklist-type=<type> Mark a type as hidden.

--whitelist-type=<type> Whitelist the type. If this set or any other
of the whitelisting sets is not empty, then
all the non-whitelisted types (or dependant)
won't be generated.

--whitelist-function=<regex> Whitelist all the free-standing functions
matching <regex>. Same behavior on emptyness
than the type whitelisting.

--whitelist-var=<regex> Whitelist all the free-standing variables
matching <regex>. Same behavior on emptyness
than the type whitelisting.

--bitfield-enum=<regex> Mark any enum whose name matches <regex> as a
set of bitfield flags instead of an
enumeration.

--dummy-uses=<path> For testing purposes, generate a C/C++ file
containing dummy uses of all types defined in
the input header.

<clang-args> Options other than stated above are passed
directly through to clang.
";

// FIXME(emilio): Replace this with docopt if/when they fix their exponential
// algorithm for argument parsing.
//
// FIXME(fitzgen): Switch from `BindgenOptions` to the non-deprecated `Builder`.
#[allow(deprecated)]
fn parse_args_or_exit(args: Vec<String>) -> (BindgenOptions, Box<io::Write>) {
let mut options = BindgenOptions::default();
let mut dest_file = None;
let mut source_file = None;

let mut iter = args.into_iter().skip(1);
loop {
let next = match iter.next() {
Some(arg) => arg,
_ => break,
};

match &*next {
"-h" | "--help" => {
println!("{}", USAGE);
process::exit(0);
}
"-l" | "--link" => {
let lib = iter.next().expect("--link needs an argument");
options.links.push((lib, LinkType::Default));
}
"--static-link" => {
let lib = iter.next().expect("--static-link needs an argument");
options.links.push((lib, LinkType::Static));
}
"--framework-link" => {
let lib = iter.next()
.expect("--framework-link needs an argument");
options.links.push((lib, LinkType::Framework));
}
"--raw-line" => {
let line = iter.next().expect("--raw-line needs an argument");
options.raw_lines.push(line);
}
"--opaque-type" => {
let ty_canonical_name = iter.next()
.expect("--opaque-type expects a type");
options.opaque_types.insert(ty_canonical_name);
}
"--blacklist-type" => {
let ty_canonical_name = iter.next()
.expect("--blacklist-type expects a type");
options.hidden_types.insert(ty_canonical_name);
}
"--whitelist-type" => {
let ty_pat = iter.next()
.expect("--whitelist-type expects a type pattern");
options.whitelisted_types.insert(&ty_pat);
}
"--whitelist-function" => {
let function_pat = iter.next()
.expect("--whitelist-function expects a pattern");
options.whitelisted_functions.insert(&function_pat);
}
"--whitelist-var" => {
let var_pat = iter.next()
.expect("--whitelist-var expects a pattern");
options.whitelisted_vars.insert(&var_pat);
}
"--bitfield-enum" => {
let enum_pat = iter.next()
.expect("--bitfield-enum expects a pattern");
options.bitfield_enums.insert(&enum_pat);
}
"--" => {
while let Some(clang_arg) = iter.next() {
options.clang_args.push(clang_arg);
}
}
"--output" | "-o" => {
let out_name = iter.next().expect("-o expects a file name");
dest_file = Some(out_name);
}
"--builtins" => {
options.builtins = true;
}
"--ignore-functions" => {
options.ignore_functions = true;
}
"--ignore-methods" => {
options.ignore_methods = true;
}
"--enable-cxx-namespaces" => {
options.enable_cxx_namespaces = true;
}
"--no-unstable-rust" => {
options.unstable_rust = false;
}
"--use-core" => {
options.use_core = true;
}
"--ctypes-prefix" => {
let prefix = iter.next()
.expect("--ctypes-prefix expects a prefix after it");
options.ctypes_prefix = Some(prefix);
}
"--emit-clang-ast" => {
options.emit_ast = true;
}
"--no-convert-floats" => {
options.convert_floats = false;
}
"--use-msvc-mangling" => {
options.msvc_mangling = true;
}
"--dummy-uses" => {
let dummy_path = iter.next()
.expect("--dummy-uses expects a file path");
options.dummy_uses = Some(dummy_path);
}
other if source_file.is_none() => {
source_file = Some(other.into());
}
other => {
panic!("Unknown option: \"{}\"", other);
}
}
}

if let Some(source_file) = source_file.take() {
options.clang_args.push(source_file);
options.input_header = options.clang_args.last().cloned();
} else {
options.input_header = options.clang_args
.iter()
.find(|arg| arg.ends_with(".h") || arg.ends_with(".hpp"))
.cloned();
}

let out = if let Some(ref path_name) = dest_file {
let path = path::Path::new(path_name);
let file = fs::File::create(path).expect("Opening out file failed");
Box::new(io::BufWriter::new(file)) as Box<io::Write>
} else {
Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
};

(options, out)
}
mod options;
use options::builder_from_flags;

pub fn main() {
log::set_logger(|max_log_level| {
Expand Down Expand Up @@ -304,14 +70,18 @@ pub fn main() {
}
}

let (options, out) = parse_args_or_exit(bind_args);

let mut bindings = Bindings::generate(options, None)
.expect("Unable to generate bindings");

bindings.write_dummy_uses()
.expect("Unable to write dummy uses to file.");

bindings.write(out)
.expect("Unable to write bindings to file.");
match builder_from_flags(env::args()) {
Ok((builder, output)) => {
let mut bindings = builder.generate()
.expect("Unable to generate bindings");
bindings.write(output)
.expect("Unable to write output");
bindings.write_dummy_uses()
.expect("Unable to write dummy uses to file.");
}
Err(error) => {
println!("{}", error);
std::process::exit(1);
}
};
}
Loading