Skip to content

Commit 54801f4

Browse files
committed
Re-introduce docopt
Fixes rust-lang#87. - Tidy up usage string - Switch to using bindgen::Builder directly in main() - Builder required some new methods - `--use-msvc-mangling` appears to be deprecated, and is only referenced in `src/lib.rs`. I have added a Deprecated section to the usage string so using the flag doesn't cause errors - `--emit-clang-ast` doesn't currently disable output of Rust bindings, might have to do something tricky here - Added `--version` based on CARGO_PKG_* - Need to add some error handling to `<input-header>`
1 parent f498903 commit 54801f4

File tree

3 files changed

+172
-171
lines changed

3 files changed

+172
-171
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+
docopt = "0.6"
2728
lazy_static = "0.1.*"
2829
libc = "0.2"
2930
log = "0.3"

src/bin/bindgen.rs

+147-171
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,48 @@
22
#![crate_type = "bin"]
33

44
extern crate bindgen;
5+
extern crate docopt;
56
extern crate env_logger;
67
#[macro_use]
78
extern crate log;
89
extern crate clang_sys;
910
extern crate rustc_serialize;
1011

12+
<<<<<<< HEAD
1113
use bindgen::{BindgenOptions, Bindings, ClangVersion, LinkType, clang_version};
1214
use std::default::Default;
15+
=======
16+
use bindgen::clang_version;
17+
use docopt::Docopt;
18+
>>>>>>> Re-introduce docopt
1319
use std::env;
1420
use std::fs;
1521
use std::io;
1622
use std::path;
17-
use std::process;
23+
24+
const PKG_NAME: &'static str = env!("CARGO_PKG_NAME");
25+
const PKG_VERSION: &'static str = env!("CARGO_PKG_VERSION");
1826

1927
const USAGE: &'static str = "
2028
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-
<input-header> \
32-
[-- <clang-args>...]
33-
34-
bindgen (-h | --help)
29+
bindgen [options] <input-header> [-- <clang-args>...]
30+
bindgen (--help | --version)
3531
3632
Options:
37-
-h, --help Display this help message.
33+
--help, -h Display this help message.
34+
35+
--version, -V Display version information.
3836
39-
-l=<lib>, --link=<lib> Link to a dynamic library, can be provided
37+
--link=<lib>, -l <lib> ... Link to a dynamic library. Can be provided
4038
multiple times.
4139
42-
--static-link=<lib> Link to a static library, can be provided
40+
--static-link=<lib> ... Link to a static library. Can be provided
4341
multiple times.
4442
45-
--framework-link=<framework> Link to a framework.
43+
--framework-link=<lib> ... Link to a framework. Can be provided
44+
multiple times.
4645
47-
-o=<output-rust-file> Write bindings to <output-rust-file>
48-
(defaults to stdout)
46+
--output=<file>, -o <file> Write Rust bindings to <file>.
4947
5048
--builtins Output bindings for builtin definitions (for
5149
example __builtin_va_list)
@@ -54,172 +52,44 @@ Options:
5452
methods. This is useful when you only care
5553
about struct layouts.
5654
57-
--ignore-methods Avoid generating all kind of methods.
55+
--ignore-methods Avoid generating all kinds of methods.
5856
5957
--enable-cxx-namespaces Enable support for C++ namespaces.
6058
61-
--emit-clang-ast Output the ast (for debugging purposes)
59+
--emit-clang-ast Output the Clang AST for debugging purposes.
6260
63-
--use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
64-
target be set to (i686|x86_64)-pc-win32
65-
66-
--raw-line=<raw> Add a raw line at the beginning of the output.
61+
--raw-line=<raw> ... Add a raw line at the beginning of the output.
6762
68-
--no-unstable-rust Avoid generating unstable rust.
63+
--no-unstable-rust Avoid generating unstable Rust code.
6964
70-
--opaque-type=<type> Mark a type as opaque.
65+
--opaque-type=<type> ... Mark a type as opaque.
7166
72-
--blacklist-type=<type> Mark a type as hidden.
67+
--blacklist-type=<type> ... Mark a type as hidden.
7368
74-
--whitelist-type=<type> Whitelist the type. If this set or any other
69+
--whitelist-type=<type> ... Whitelist the type. If this set or any other
7570
of the whitelisting sets is not empty, then
76-
all the non-whitelisted types (or dependant)
77-
won't be generated.
71+
all the non-whitelisted types (or anything
72+
that depends on them) won't be generated.
7873
79-
--whitelist-function=<regex> Whitelist all the free-standing functions
80-
matching <regex>. Same behavior on emptyness
81-
than the type whitelisting.
74+
--whitelist-function=<regex> ... Whitelist all the free-standing functions
75+
matching <regex>. Same behavior on emptyness
76+
as whitelisted types.
8277
83-
--whitelist-var=<regex> Whitelist all the free-standing variables
84-
matching <regex>. Same behavior on emptyness
85-
than the type whitelisting.
78+
--whitelist-var=<regex> ... Whitelist all the free-standing variables
79+
matching <regex>. Same behavior on emptyness
80+
as whitelisted types.
8681
8782
--dummy-uses=<path> For testing purposes, generate a C/C++ file
8883
containing dummy uses of all types defined in
8984
the input header.
9085
91-
<clang-args> Options other than stated above are passed
92-
directly through to clang.
93-
";
86+
<clang-args> Pass arguments through to clang.
9487
95-
// FIXME(emilio): Replace this with docopt if/when they fix their exponential
96-
// algorithm for argument parsing.
97-
//
98-
// FIXME(fitzgen): Switch from `BindgenOptions` to the non-deprecated `Builder`.
99-
#[allow(deprecated)]
100-
fn parse_args_or_exit(args: Vec<String>) -> (BindgenOptions, Box<io::Write>) {
101-
let mut options = BindgenOptions::default();
102-
let mut dest_file = None;
103-
let mut source_file = None;
104-
105-
let mut iter = args.into_iter().skip(1);
106-
loop {
107-
let next = match iter.next() {
108-
Some(arg) => arg,
109-
_ => break,
110-
};
111-
112-
match &*next {
113-
"-h" | "--help" => {
114-
println!("{}", USAGE);
115-
process::exit(0);
116-
}
117-
"-l" | "--link" => {
118-
let lib = iter.next().expect("--link needs an argument");
119-
options.links.push((lib, LinkType::Default));
120-
}
121-
"--static-link" => {
122-
let lib = iter.next().expect("--static-link needs an argument");
123-
options.links.push((lib, LinkType::Static));
124-
}
125-
"--framework-link" => {
126-
let lib = iter.next()
127-
.expect("--framework-link needs an argument");
128-
options.links.push((lib, LinkType::Framework));
129-
}
130-
"--raw-line" => {
131-
let line = iter.next().expect("--raw-line needs an argument");
132-
options.raw_lines.push(line);
133-
}
134-
"--opaque-type" => {
135-
let ty_canonical_name = iter.next()
136-
.expect("--opaque-type expects a type");
137-
options.opaque_types.insert(ty_canonical_name);
138-
}
139-
"--blacklist-type" => {
140-
let ty_canonical_name = iter.next()
141-
.expect("--blacklist-type expects a type");
142-
options.hidden_types.insert(ty_canonical_name);
143-
}
144-
"--whitelist-type" => {
145-
let ty_pat = iter.next()
146-
.expect("--whitelist-type expects a type pattern");
147-
options.whitelisted_types.insert(&ty_pat);
148-
}
149-
"--whitelist-function" => {
150-
let function_pat = iter.next()
151-
.expect("--whitelist-function expects a pattern");
152-
options.whitelisted_functions.insert(&function_pat);
153-
}
154-
"--whitelist-var" => {
155-
let var_pat = iter.next()
156-
.expect("--whitelist-var expects a pattern");
157-
options.whitelisted_vars.insert(&var_pat);
158-
}
159-
"--" => {
160-
while let Some(clang_arg) = iter.next() {
161-
options.clang_args.push(clang_arg);
162-
}
163-
}
164-
"--output" | "-o" => {
165-
let out_name = iter.next().expect("-o expects a file name");
166-
dest_file = Some(out_name);
167-
}
168-
"--builtins" => {
169-
options.builtins = true;
170-
}
171-
"--ignore-functions" => {
172-
options.ignore_functions = true;
173-
}
174-
"--ignore-methods" => {
175-
options.ignore_methods = true;
176-
}
177-
"--enable-cxx-namespaces" => {
178-
options.enable_cxx_namespaces = true;
179-
}
180-
"--no-unstable-rust" => {
181-
options.unstable_rust = false;
182-
}
183-
"--emit-clang-ast" => {
184-
options.emit_ast = true;
185-
}
186-
"--use-msvc-mangling" => {
187-
options.msvc_mangling = true;
188-
}
189-
"--dummy-uses" => {
190-
let dummy_path = iter.next()
191-
.expect("--dummy-uses expects a file path");
192-
options.dummy_uses = Some(dummy_path);
193-
}
194-
other if source_file.is_none() => {
195-
source_file = Some(other.into());
196-
}
197-
other => {
198-
panic!("Unknown option: \"{}\"", other);
199-
}
200-
}
201-
}
88+
Deprecated:
20289
203-
if let Some(source_file) = source_file.take() {
204-
options.clang_args.push(source_file);
205-
options.input_header = options.clang_args.last().cloned();
206-
} else {
207-
options.input_header = options.clang_args
208-
.iter()
209-
.find(|arg| arg.ends_with(".h") || arg.ends_with(".hpp"))
210-
.cloned();
211-
}
212-
213-
let out = if let Some(ref path_name) = dest_file {
214-
let path = path::Path::new(path_name);
215-
let file = fs::File::create(path).expect("Opening out file failed");
216-
Box::new(io::BufWriter::new(file)) as Box<io::Write>
217-
} else {
218-
Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
219-
};
220-
221-
(options, out)
222-
}
90+
--use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
91+
target be set to (i686|x86_64)-pc-win32.
92+
";
22393

22494
pub fn main() {
22595
log::set_logger(|max_log_level| {
@@ -276,9 +146,115 @@ pub fn main() {
276146
}
277147
}
278148

279-
let (options, out) = parse_args_or_exit(bind_args);
149+
let args = Docopt::new(USAGE)
150+
.and_then(|dopt| dopt.parse())
151+
.unwrap_or_else(|e| e.exit());
152+
153+
if args.get_bool("--version") {
154+
println!("{} v{}", PKG_NAME, PKG_VERSION);
155+
std::process::exit(0);
156+
}
157+
158+
let mut builder = bindgen::builder();
159+
160+
// Input header
161+
let header = args.get_str("<input-header>");
162+
if header != "" {
163+
builder = builder.header(header);
164+
}
165+
166+
// Output file or stdout
167+
let output = args.get_str("--output");
168+
let out = if output != "" {
169+
let path = path::Path::new(output);
170+
let file = fs::File::create(path).expect("Opening output file failed.");
171+
Box::new(io::BufWriter::new(file)) as Box<io::Write>
172+
} else {
173+
Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
174+
};
175+
176+
// Emit C/C++ type uses file for testing
177+
let dummy_uses = args.get_str("--dummy-uses");
178+
if dummy_uses != "" {
179+
builder = builder.dummy_uses(dummy_uses);
180+
}
181+
182+
if args.get_bool("--builtins") {
183+
builder = builder.emit_builtins();
184+
}
185+
186+
if args.get_bool("--emit-clang-ast") {
187+
builder = builder.emit_clang_ast();
188+
}
189+
190+
if args.get_bool("--enable-cxx-namespaces") {
191+
builder = builder.enable_cxx_namespaces();
192+
}
193+
194+
if args.get_bool("--ignore-functions") {
195+
builder = builder.ignore_functions();
196+
}
197+
198+
if args.get_bool("--ignore-methods") {
199+
builder = builder.ignore_methods();
200+
}
201+
202+
// Do not generate unstable Rust code
203+
if args.get_bool("--no-unstable-rust") {
204+
builder = builder.no_unstable_rust();
205+
}
206+
207+
// Shared library links
208+
for link in args.get_vec("--link") {
209+
builder = builder.link(link);
210+
}
211+
212+
// Static library links
213+
for link in args.get_vec("--static-link") {
214+
builder = builder.link_static(link);
215+
}
216+
217+
// Framework links
218+
for link in args.get_vec("--framework-link") {
219+
builder = builder.link_framework(link);
220+
}
221+
222+
// Raw lines to add at top of output
223+
for line in args.get_vec("--raw-line") {
224+
builder = builder.raw_line(line);
225+
}
226+
227+
// Hidden types
228+
for arg in args.get_vec("--blacklist-type") {
229+
builder = builder.hide_type(arg);
230+
}
231+
232+
// Opaque types
233+
for arg in args.get_vec("--opaque-type") {
234+
builder = builder.opaque_type(arg);
235+
}
236+
237+
// Whitelisted types
238+
for regex in args.get_vec("--whitelist-type") {
239+
builder = builder.whitelisted_type(regex);
240+
}
241+
242+
// Whitelisted functions
243+
for regex in args.get_vec("--whitelist-function") {
244+
builder = builder.whitelisted_function(regex);
245+
}
246+
247+
// Whitelisted variables
248+
for regex in args.get_vec("--whitelist-var") {
249+
builder = builder.whitelisted_var(regex);
250+
}
251+
252+
// Clang parameters
253+
for arg in args.get_vec("<clang-args>") {
254+
builder = builder.clang_arg(arg);
255+
}
280256

281-
let mut bindings = Bindings::generate(options, None)
257+
let mut bindings = builder.generate()
282258
.expect("Unable to generate bindings");
283259

284260
bindings.write_dummy_uses()

0 commit comments

Comments
 (0)