Skip to content

Commit b3322dd

Browse files
author
bors-servo
authored
Auto merge of #228 - jdub:clap, r=emilio
Clap your hands say yeah! 👏🏻 In progress port to `clap`, obsoletes the `docopt` port in #202.
2 parents 8d83bdf + dc96c1f commit b3322dd

File tree

4 files changed

+300
-248
lines changed

4 files changed

+300
-248
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ quasi_codegen = "0.20"
2424
[dependencies]
2525
cfg-if = "0.1.0"
2626
clang-sys = "0.8.0"
27+
clap = "2"
2728
lazy_static = "0.1.*"
2829
libc = "0.2"
2930
log = "0.3"

src/bin/bindgen.rs

+18-248
Original file line numberDiff line numberDiff line change
@@ -6,248 +6,14 @@ extern crate env_logger;
66
#[macro_use]
77
extern crate log;
88
extern crate clang_sys;
9+
extern crate clap;
910
extern crate rustc_serialize;
1011

11-
use bindgen::{BindgenOptions, Bindings, LinkType, clang_version};
12-
use std::default::Default;
12+
use bindgen::clang_version;
1313
use std::env;
14-
use std::fs;
15-
use std::io;
16-
use std::path;
17-
use std::process;
1814

19-
const USAGE: &'static str = "
20-
Usage:
21-
bindgen [options] \
22-
[--link=<lib>...] \
23-
[--static-link=<lib>...] \
24-
[--framework-link=<framework>...] \
25-
[--raw-line=<raw>...] \
26-
[--opaque-type=<type>...] \
27-
[--blacklist-type=<type>...] \
28-
[--whitelist-type=<type>...] \
29-
[--whitelist-function=<name>...] \
30-
[--whitelist-var=<name>...] \
31-
[--bitfield-enum=<name>...] \
32-
<input-header> \
33-
[-- <clang-args>...]
34-
35-
bindgen (-h | --help)
36-
37-
Options:
38-
-h, --help Display this help message.
39-
40-
-l=<lib>, --link=<lib> Link to a dynamic library, can be provided
41-
multiple times.
42-
43-
--static-link=<lib> Link to a static library, can be provided
44-
multiple times.
45-
46-
--framework-link=<framework> Link to a framework.
47-
48-
-o=<output-rust-file> Write bindings to <output-rust-file>
49-
(defaults to stdout)
50-
51-
--builtins Output bindings for builtin definitions (for
52-
example __builtin_va_list)
53-
54-
--ignore-functions Don't generate bindings for functions and
55-
methods. This is useful when you only care
56-
about struct layouts.
57-
58-
--ignore-methods Avoid generating all kind of methods.
59-
60-
--enable-cxx-namespaces Enable support for C++ namespaces.
61-
62-
--emit-clang-ast Output the ast (for debugging purposes)
63-
64-
--use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
65-
target be set to (i686|x86_64)-pc-win32
66-
67-
--no-convert-floats Don't convert floats automatically to f32/f64.
68-
69-
--raw-line=<raw> Add a raw line at the beginning of the output.
70-
71-
--no-unstable-rust Avoid generating unstable rust.
72-
73-
--use-core Use built-in types from core instead of std.
74-
75-
--ctypes-prefix=<prefix> Use the given prefix before the raw types
76-
instead of ::std::os::raw::.
77-
78-
--opaque-type=<type> Mark a type as opaque.
79-
80-
--blacklist-type=<type> Mark a type as hidden.
81-
82-
--whitelist-type=<type> Whitelist the type. If this set or any other
83-
of the whitelisting sets is not empty, then
84-
all the non-whitelisted types (or dependant)
85-
won't be generated.
86-
87-
--whitelist-function=<regex> Whitelist all the free-standing functions
88-
matching <regex>. Same behavior on emptyness
89-
than the type whitelisting.
90-
91-
--whitelist-var=<regex> Whitelist all the free-standing variables
92-
matching <regex>. Same behavior on emptyness
93-
than the type whitelisting.
94-
95-
--bitfield-enum=<regex> Mark any enum whose name matches <regex> as a
96-
set of bitfield flags instead of an
97-
enumeration.
98-
99-
--dummy-uses=<path> For testing purposes, generate a C/C++ file
100-
containing dummy uses of all types defined in
101-
the input header.
102-
103-
<clang-args> Options other than stated above are passed
104-
directly through to clang.
105-
";
106-
107-
// FIXME(emilio): Replace this with docopt if/when they fix their exponential
108-
// algorithm for argument parsing.
109-
//
110-
// FIXME(fitzgen): Switch from `BindgenOptions` to the non-deprecated `Builder`.
111-
#[allow(deprecated)]
112-
fn parse_args_or_exit(args: Vec<String>) -> (BindgenOptions, Box<io::Write>) {
113-
let mut options = BindgenOptions::default();
114-
let mut dest_file = None;
115-
let mut source_file = None;
116-
117-
let mut iter = args.into_iter().skip(1);
118-
loop {
119-
let next = match iter.next() {
120-
Some(arg) => arg,
121-
_ => break,
122-
};
123-
124-
match &*next {
125-
"-h" | "--help" => {
126-
println!("{}", USAGE);
127-
process::exit(0);
128-
}
129-
"-l" | "--link" => {
130-
let lib = iter.next().expect("--link needs an argument");
131-
options.links.push((lib, LinkType::Default));
132-
}
133-
"--static-link" => {
134-
let lib = iter.next().expect("--static-link needs an argument");
135-
options.links.push((lib, LinkType::Static));
136-
}
137-
"--framework-link" => {
138-
let lib = iter.next()
139-
.expect("--framework-link needs an argument");
140-
options.links.push((lib, LinkType::Framework));
141-
}
142-
"--raw-line" => {
143-
let line = iter.next().expect("--raw-line needs an argument");
144-
options.raw_lines.push(line);
145-
}
146-
"--opaque-type" => {
147-
let ty_canonical_name = iter.next()
148-
.expect("--opaque-type expects a type");
149-
options.opaque_types.insert(ty_canonical_name);
150-
}
151-
"--blacklist-type" => {
152-
let ty_canonical_name = iter.next()
153-
.expect("--blacklist-type expects a type");
154-
options.hidden_types.insert(ty_canonical_name);
155-
}
156-
"--whitelist-type" => {
157-
let ty_pat = iter.next()
158-
.expect("--whitelist-type expects a type pattern");
159-
options.whitelisted_types.insert(&ty_pat);
160-
}
161-
"--whitelist-function" => {
162-
let function_pat = iter.next()
163-
.expect("--whitelist-function expects a pattern");
164-
options.whitelisted_functions.insert(&function_pat);
165-
}
166-
"--whitelist-var" => {
167-
let var_pat = iter.next()
168-
.expect("--whitelist-var expects a pattern");
169-
options.whitelisted_vars.insert(&var_pat);
170-
}
171-
"--bitfield-enum" => {
172-
let enum_pat = iter.next()
173-
.expect("--bitfield-enum expects a pattern");
174-
options.bitfield_enums.insert(&enum_pat);
175-
}
176-
"--" => {
177-
while let Some(clang_arg) = iter.next() {
178-
options.clang_args.push(clang_arg);
179-
}
180-
}
181-
"--output" | "-o" => {
182-
let out_name = iter.next().expect("-o expects a file name");
183-
dest_file = Some(out_name);
184-
}
185-
"--builtins" => {
186-
options.builtins = true;
187-
}
188-
"--ignore-functions" => {
189-
options.ignore_functions = true;
190-
}
191-
"--ignore-methods" => {
192-
options.ignore_methods = true;
193-
}
194-
"--enable-cxx-namespaces" => {
195-
options.enable_cxx_namespaces = true;
196-
}
197-
"--no-unstable-rust" => {
198-
options.unstable_rust = false;
199-
}
200-
"--use-core" => {
201-
options.use_core = true;
202-
}
203-
"--ctypes-prefix" => {
204-
let prefix = iter.next()
205-
.expect("--ctypes-prefix expects a prefix after it");
206-
options.ctypes_prefix = Some(prefix);
207-
}
208-
"--emit-clang-ast" => {
209-
options.emit_ast = true;
210-
}
211-
"--no-convert-floats" => {
212-
options.convert_floats = false;
213-
}
214-
"--use-msvc-mangling" => {
215-
options.msvc_mangling = true;
216-
}
217-
"--dummy-uses" => {
218-
let dummy_path = iter.next()
219-
.expect("--dummy-uses expects a file path");
220-
options.dummy_uses = Some(dummy_path);
221-
}
222-
other if source_file.is_none() => {
223-
source_file = Some(other.into());
224-
}
225-
other => {
226-
panic!("Unknown option: \"{}\"", other);
227-
}
228-
}
229-
}
230-
231-
if let Some(source_file) = source_file.take() {
232-
options.clang_args.push(source_file);
233-
options.input_header = options.clang_args.last().cloned();
234-
} else {
235-
options.input_header = options.clang_args
236-
.iter()
237-
.find(|arg| arg.ends_with(".h") || arg.ends_with(".hpp"))
238-
.cloned();
239-
}
240-
241-
let out = if let Some(ref path_name) = dest_file {
242-
let path = path::Path::new(path_name);
243-
let file = fs::File::create(path).expect("Opening out file failed");
244-
Box::new(io::BufWriter::new(file)) as Box<io::Write>
245-
} else {
246-
Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
247-
};
248-
249-
(options, out)
250-
}
15+
mod options;
16+
use options::builder_from_flags;
25117

25218
pub fn main() {
25319
log::set_logger(|max_log_level| {
@@ -304,14 +70,18 @@ pub fn main() {
30470
}
30571
}
30672

307-
let (options, out) = parse_args_or_exit(bind_args);
308-
309-
let mut bindings = Bindings::generate(options, None)
310-
.expect("Unable to generate bindings");
311-
312-
bindings.write_dummy_uses()
313-
.expect("Unable to write dummy uses to file.");
314-
315-
bindings.write(out)
316-
.expect("Unable to write bindings to file.");
73+
match builder_from_flags(env::args()) {
74+
Ok((builder, output)) => {
75+
let mut bindings = builder.generate()
76+
.expect("Unable to generate bindings");
77+
bindings.write(output)
78+
.expect("Unable to write output");
79+
bindings.write_dummy_uses()
80+
.expect("Unable to write dummy uses to file.");
81+
}
82+
Err(error) => {
83+
println!("{}", error);
84+
std::process::exit(1);
85+
}
86+
};
31787
}

0 commit comments

Comments
 (0)