Skip to content

Commit f294d37

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 624c32c commit f294d37

File tree

3 files changed

+169
-173
lines changed

3 files changed

+169
-173
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

+144-173
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,43 @@
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

11-
use bindgen::{BindgenOptions, Bindings, LinkType, ClangVersion, clang_version};
12-
use std::default::Default;
12+
use bindgen::clang_version;
13+
use docopt::Docopt;
1314
use std::env;
1415
use std::fs;
1516
use std::io;
1617
use std::path;
17-
use std::process;
18+
19+
const PKG_NAME: &'static str = env!("CARGO_PKG_NAME");
20+
const PKG_VERSION: &'static str = env!("CARGO_PKG_VERSION");
1821

1922
const USAGE: &'static str = "
2023
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)
24+
bindgen [options] <input-header> [-- <clang-args>...]
25+
bindgen (--help | --version)
3526
3627
Options:
37-
-h, --help Display this help message.
28+
--help, -h Display this help message.
29+
30+
--version, -V Display version information.
3831
39-
-l=<lib>, --link=<lib> Link to a dynamic library, can be provided
32+
--link=<lib>, -l <lib> ... Link to a dynamic library. Can be provided
4033
multiple times.
4134
42-
--static-link=<lib> Link to a static library, can be provided
35+
--static-link=<lib> ... Link to a static library. Can be provided
4336
multiple times.
4437
45-
--framework-link=<framework> Link to a framework.
38+
--framework-link=<lib> ... Link to a framework. Can be provided
39+
multiple times.
4640
47-
-o=<output-rust-file> Write bindings to <output-rust-file>
48-
(defaults to stdout)
41+
--output=<file>, -o <file> Write Rust bindings to <file>.
4942
5043
--builtins Output bindings for builtin definitions (for
5144
example __builtin_va_list)
@@ -54,172 +47,44 @@ Options:
5447
methods. This is useful when you only care
5548
about struct layouts.
5649
57-
--ignore-methods Avoid generating all kind of methods.
50+
--ignore-methods Avoid generating all kinds of methods.
5851
5952
--enable-cxx-namespaces Enable support for C++ namespaces.
6053
61-
--emit-clang-ast Output the ast (for debugging purposes)
54+
--emit-clang-ast Output the Clang AST for debugging purposes.
6255
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.
56+
--raw-line=<raw> ... Add a raw line at the beginning of the output.
6757
68-
--no-unstable-rust Avoid generating unstable rust.
58+
--no-unstable-rust Avoid generating unstable Rust code.
6959
70-
--opaque-type=<type> Mark a type as opaque.
60+
--opaque-type=<type> ... Mark a type as opaque.
7161
72-
--blacklist-type=<type> Mark a type as hidden.
62+
--blacklist-type=<type> ... Mark a type as hidden.
7363
74-
--whitelist-type=<type> Whitelist the type. If this set or any other
64+
--whitelist-type=<type> ... Whitelist the type. If this set or any other
7565
of the whitelisting sets is not empty, then
76-
all the non-whitelisted types (or dependant)
77-
won't be generated.
66+
all the non-whitelisted types (or anything
67+
that depends on them) won't be generated.
7868
79-
--whitelist-function=<regex> Whitelist all the free-standing functions
80-
matching <regex>. Same behavior on emptyness
81-
than the type whitelisting.
69+
--whitelist-function=<regex> ... Whitelist all the free-standing functions
70+
matching <regex>. Same behavior on emptyness
71+
as whitelisted types.
8272
83-
--whitelist-var=<regex> Whitelist all the free-standing variables
84-
matching <regex>. Same behavior on emptyness
85-
than the type whitelisting.
73+
--whitelist-var=<regex> ... Whitelist all the free-standing variables
74+
matching <regex>. Same behavior on emptyness
75+
as whitelisted types.
8676
8777
--dummy-uses=<path> For testing purposes, generate a C/C++ file
8878
containing dummy uses of all types defined in
8979
the input header.
9080
91-
<clang-args> Options other than stated above are passed
92-
directly through to clang.
93-
";
81+
<clang-args> Pass arguments through to clang.
9482
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-
}
83+
Deprecated:
20284
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-
}
85+
--use-msvc-mangling Handle MSVC C++ ABI mangling; requires that
86+
target be set to (i686|x86_64)-pc-win32.
87+
";
22388

22489
pub fn main() {
22590
log::set_logger(|max_log_level| {
@@ -270,9 +135,115 @@ pub fn main() {
270135
}
271136
}
272137

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

275-
let mut bindings = Bindings::generate(options, None)
246+
let mut bindings = builder.generate()
276247
.expect("Unable to generate bindings");
277248

278249
bindings.write_dummy_uses()

0 commit comments

Comments
 (0)