Skip to content

Commit ab10295

Browse files
michaelwuemilio
authored andcommitted
SM hacks squash
Generate better enums Squash of... Disable prefixing Default to failing on unknown types Add support for Char16 Emit errors for unknown cursor kinds Hack in support for classes Recurse into unexposed decls This fixes functions that use extern "C". Add support for generating unmangled functions Prefix unnamed data structures with the file name Recurse into namespaced things Avoid rust reserved keywords in unmangle func args Don't create variadic unmangled funcs Don't translate typedefs to the same name Ignore operator overloads Avoid templates Handle class declarations Number duplicate demangle functions Implement copy on enums Translate stdint types into standard rust int types Switch enums to i32 for better compatibility Correctly deal with mangled functions with unnamed args Mark unmangling functions as unsafe Attempt to produce structs for C++ classes Convert references Generate better func decls for void returns Make every function callback unsafe Add support for generics in typedefs Add support for class templates Aggressively trim duplicates Don't generate default impl for templates Improve handling of templates Fix function numbering Fix deduplication Make unmangling functions extern "C" Convert all int/float typedefs to standard rust ints/floats This also gives better information to the bitfield parsing and allows uint32_t and other stdint bitfields to be processed properly Add support for wchar Add support for bitfield setter generation Fix floats Squash of... Shorten generated bitfield names Add support for generating whole bitfields Add support for enums nested inside structs/classes Rustup Fixes rust-lang#184. Rustup to b301e02f3 2015-05-19 Inline demangling functions Add support for base classes/types Generate bindings for methods Make duplicate detection less aggressive Avoid converting long/unsigned longs to rust types. This fixes 64/32bit issues in structs. Generate bitfields correctly for typedefs Convert stdint types to rust types Derive Debug on BindgenOptions, Bindings, and LinkType. Remove +'static when writing bindings Generate virtual function tables Resolve some warnings Add NotConst where Constness params are required Generate real bools when applicable Squash of... Add support for comments Improve bitfield support using const fn Add limited support for references Add comments to fields Don't generate empty comments Convert char16_t to u16 rather than i16 Convert signed chars to libc::c_char Fix Cargo.toml rebasing breakage Fix compiler errors This gets bindgen to compile and run again, but all but one `cargo test` tests fail. Not sure if that’s because of mistakes on my part or if the sm-hacks branch never passed those tests. Fix build warnings Use link_name attr for mangled function names Handle mangled global vars Only generate bindings for visible symbols Don't generate arrays for blobs when the length is 1 Name enums inside classes better Handle template args inside typedefs better Filter out duplicate decls better Generate correctly sized enums Squash of... Fix bitfield accessor method generation for bools Insert phantom fields in empty structs Don't mark unmangling methods as extern "C" Add back comment support for functions Add basic annotation support Don't generate univariant enums Add support for hide annotation and adjust syntax Don't generate unsupported structs Don't parse hidden fields Don't derive Copy for structs with destructors Don't implement Clone or Default Derive Clone when deriving Copy Bypass single member unions Disable references in function args for now Remove extra underscore in mangled names on OSX Don't translate private methods Support generating consts from macros that are defined as integer literals. Handle mangling better Squash of... Update README.md for fork Generate docs for enum items Generate docs for typedefs Generate docs for enums Update syntex_syntax to 0.24.* Update clang info in README.md Spit errors and warnings to stdout. The correct thing to do here is to use env_logger, but that was causing cargo troubles for me, and this is preferable to swallowing them. Add the -ignore-functions argument. Handle 1 << 63 as enum value. Don't try to convert standard int types in rust_type_id. It looks like mwu added this, but I'm pretty sure it's a category error. This function appears to be designed to reproducibly permute C identifiers so that they don't conflict with builtin rust types. It's specifically _not_ a type translator (which would happen at the type level, rather than the string level), and using it as such with callers like ctypedef_to_rs causes us to generate things like: type u64 = u64; While processing stdint.h, which is clearly wrong. Stop patching in placeholder names for CompInfo and EnumInfo instances during code generator. As best as I can tell, it's done this way (rather than my way) because bindgen tries to recognize struct and enums typedefs of the form: /* This is a common idiom in C, not so much in C++ */ typdef struct { ... } Foo; The intention, I think, is to avoid generating rust code for a struct with a placeholder name followed by a typedef, and just give the struct the right name initially. This seems like a reasonable goal, though not a particularly important one. However, in my testing this never actually happens, because we end up calling unnamed_name anyway during the GComp(ci) case of gen_mod before we get to evaluting the typedef. So let's just remove that stuff and simplify the code. This lets us remove all the borrow_mut calls during code generation, which seems necessary for soundness. gen: Allow empty union members Use full paths in generation. Fix test compilation parser: Add support for parsing namespaces Partial C++ namespaces support We currently generate the modules as expected, but we don't resolve the names from external namespaces well. Remove unnecesary return statements Put namespaces behind a flag Overall now that they aren't complete still. Moar refactoring Finally take rid of all the warnings Even moar gen: Avoid so much cloning parser: Refactor the way submodules are stored This way we can share the global map, while having each module custom globals. gen: Checkpoint before the refactoring This actually keeps working as before. gen: Make modules (almost) work for typedef'd types We generate almost valid code, we just have to add some use statements. Or maybe is a better idea to add an unintelligible name to the root mod, and actually output a root mod plus a use root::* before. gen: Document the current submodule approach and some desirable alternative gen: Make it actually compilable \o/ gen: Make the code generation usable for every type. There's just an edge case I've detected, and it's when we remove the instantiation of C<int>, and another module uses it, because that means we only know of its existance in that other module. Probably we might want to use cursor_getSemanticParent to get the real class instead of the instantiated, but I'm not too confident about that. Fix a corner case when a template was instantiated in another module. Added an example of the namespace resolution. Don't panic when not finding the specialised template This can be annoying if filtering files out. Straight rebase completed, let's fix that build errors wip Pair up with master nits Update AST Add -no-rename-fields option This is for compatibility between C bindings and C++ bindings (in C `struct Foo` and `enum Foo`, are different, while in C++ they aren't). wip Add enum tests pass, and add C++ tests Make a few more struct-related tests pass
1 parent 6f1904e commit ab10295

22 files changed

+2249
-938
lines changed

README.md

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,37 @@ rust-bindgen
66
[![][travis-status-shield]](https://travis-ci.org/crabtw/rust-bindgen/)
77

88
A binding generator for the rust language.
9+
This is a fork designed to work on Spidermonkey headers.
910
It is ported from [clay's bindgen][].
1011

1112
Requirements
1213
------------
1314

14-
* clang 3.4 and up
15+
* clang 3.7 with patches https://github.com/michaelwu/clang/tree/release_37_smhacks or clang 3.8+
1516

16-
Note: The libclang.so has to be statically linked with LLVM or you will
17-
encounter [issue 89][]. You can also use LD_PRELOAD=/path/to/libclang.so to
18-
workaround the problem.
17+
This bindgen fork requires a patched clang or clang 3.8+ to work properly. This is one way to build a patched clang:
18+
```
19+
git clone https://github.com/llvm-mirror/llvm
20+
cd llvm
21+
git checkout release_37
22+
cd tools
23+
git clone https://github.com/llvm-mirror/clang
24+
cd clang
25+
git remote add mwu https://github.com/michaelwu/clang
26+
git fetch mwu
27+
git checkout release_37_smhacks
28+
cd ../.. # llvm root dir
29+
mkdir build
30+
cd build
31+
../configure --enable-optimized
32+
make
33+
```
34+
35+
Then before building, make sure to export the path to this copy of clang:
36+
37+
export LIBCLANG_PATH=~/llvm/build/Release+Asserts/lib
38+
39+
This path also needs to be set in LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX) when running bindgen.
1940

2041
Building
2142
--------
@@ -71,6 +92,28 @@ Options:
7192
Options other than stated above are passed to clang
7293
```
7394

95+
C++ Usage
96+
---------
97+
This fork of rust-bindgen can handle a number of C++ features. Because it currently uses a fork of clang though, it may require adding extra arguments to find certain headers. On OpenSUSE 13.2, these additional include pathes can be used:
98+
99+
-isystem /usr/lib64/gcc/x86_64-suse-linux/4.8/include -isystem /usr/lib64/gcc/x86_64-suse-linux/4.8/include-fixed
100+
101+
On OSX, this include path seems to work:
102+
103+
-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
104+
105+
When passing in header files, the file will automatically be treated as C++ if it ends in ``.hpp``. If it doesn't, ``-x c++`` can be used to force C++ mode.
106+
107+
Annotations
108+
-----------
109+
The translation of classes, structs, enums, and typedefs can be adjusted using annotations. Annotations are specifically formatted html tags inside doxygen style comments. The opaque annotation instructs bindgen to ignore all fields defined in a struct/class.
110+
111+
/// <div rust-bindgen opaque></div>
112+
113+
The hide annotation instructs bindgen to ignore the struct/class/field/enum completely.
114+
115+
/// <div rust-bindgen hide></div>
116+
74117
Macro Usage
75118
-----------
76119

@@ -118,15 +161,3 @@ main.rs
118161
mod mysql_bindings {
119162
bindgen!("/usr/include/mysql/mysql.h", match="mysql.h", link="mysql")
120163
}
121-
122-
TODO
123-
----
124-
125-
* bitfield accessors
126-
127-
[clay's bindgen]: https://github.com/jckarter/clay/blob/master/tools/bindgen.clay
128-
[crates-version-shield]: https://img.shields.io/crates/v/bindgen.svg?style=flat-square
129-
[crates-downloads-shield]: https://img.shields.io/crates/d/bindgen.svg?style=flat-square
130-
[crates-license-shield]: https://img.shields.io/crates/l/bindgen.svg?style=flat-square
131-
[travis-status-shield]: https://img.shields.io/travis/crabtw/rust-bindgen.svg?label=travis&style=flat-square
132-
[issue 89]: https://github.com/crabtw/rust-bindgen/issues/89

bindgen_plugin/src/bgmacro.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ pub fn bindgen_macro(cx: &mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::Toke
2525
}
2626

2727
// Reparse clang_args as it is passed in string form
28-
let clang_args = visit.options.clang_args.join(" ");
29-
visit.options.clang_args = parse_process_args(&clang_args[..]);
28+
let clang_args = visit.options.clang_args.connect(" ");
29+
visit.options.clang_args = parse_process_args(&clang_args);
3030

3131
if let Some(path) = bindgen::get_include_dir() {
3232
visit.options.clang_args.push("-I".to_owned());
@@ -66,7 +66,7 @@ pub fn bindgen_macro(cx: &mut base::ExtCtxt, sp: codemap::Span, tts: &[ast::Toke
6666
}
6767

6868
Box::new(BindgenResult { items: Some(SmallVector::many(items)) }) as Box<base::MacResult>
69-
69+
7070
}
7171
Err(_) => base::DummyResult::any(sp)
7272
};
@@ -223,7 +223,7 @@ fn parse_macro_opts(cx: &mut base::ExtCtxt, tts: &[ast::TokenTree], visit: &mut
223223
// I'm sure there's a nicer way of doing it
224224
fn as_str<'a>(owned: &'a Option<String>) -> Option<&'a str> {
225225
match owned {
226-
&Some(ref s) => Some(&s[..]),
226+
&Some(ref s) => Some(s),
227227
&None => None
228228
}
229229
}
@@ -289,7 +289,7 @@ fn parse_process_args(s: &str) -> Vec<String> {
289289

290290
if part.len() > 0 {
291291
// Remove any extra whitespace outside the quotes
292-
let part = &part[..].trim();
292+
let part = part.trim();
293293
// Replace quoted characters
294294
let part = part.replace("\\\"", "\"");
295295
let part = part.replace("\\\'", "\'");

build.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::process::Command;
66
const LINUX_CLANG_DIRS: &'static [&'static str] = &[
77
"/usr/lib",
88
"/usr/lib/llvm",
9+
"/usr/lib/llvm-3.8/lib",
910
"/usr/lib/llvm-3.7/lib",
1011
"/usr/lib/llvm-3.6/lib",
1112
"/usr/lib/llvm-3.5/lib",
@@ -21,10 +22,7 @@ const MAC_CLANG_DIR: &'static [&'static str] = &[
2122
const WIN_CLANG_DIRS: &'static [&'static str] = &["C:\\Program Files\\LLVM\\bin", "C:\\Program Files\\LLVM\\lib"];
2223

2324
fn path_exists(path: &Path) -> bool {
24-
match fs::metadata(path) {
25-
Ok(_) => true,
26-
Err(_) => false
27-
}
25+
fs::metadata(path).is_ok()
2826
}
2927

3028
fn main() {
@@ -37,16 +35,16 @@ fn main() {
3735
} else if cfg!(target_os = "macos") {
3836
MAC_CLANG_DIR.iter().map(ToString::to_string).collect()
3937
} else if cfg!(target_os = "windows") {
40-
WIN_CLANG_DIRS.iter().map(ToString::to_string).collect()
38+
WIN_CLANG_DIRS.iter().map(ToString::to_string).collect()
4139
} else {
4240
panic!("Platform not supported");
4341
};
4442

4543
let clang_lib = if cfg!(target_os = "windows") {
46-
format!("libclang{}", env::consts::DLL_SUFFIX)
47-
} else {
48-
format!("{}clang{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)
49-
};
44+
format!("libclang{}", env::consts::DLL_SUFFIX)
45+
} else {
46+
format!("{}clang{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)
47+
};
5048

5149
//may contain path to libclang detected via ldconfig
5250
let mut libclang_path_string = String::new();
@@ -60,7 +58,8 @@ fn main() {
6058
None
6159
}
6260
}).next();
63-
if maybe_clang_dir == None && cfg!(target_os = "linux") {
61+
62+
if maybe_clang_dir.is_none() && cfg!(target_os = "linux") {
6463
//try to find via lddconfig
6564
//may return line, like
6665
//libclang.so.3.7 (libc6,x86-64) => /usr/lib64/libclang.so.3.7

src/bin/bindgen.rs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
#![crate_type = "bin"]
33

44
extern crate bindgen;
5-
#[macro_use] extern crate log;
5+
#[macro_use]
6+
extern crate log;
67

78
use bindgen::{Bindings, BindgenOptions, LinkType, Logger};
89
use std::io;
@@ -16,25 +17,24 @@ struct StdLogger;
1617

1718
impl Logger for StdLogger {
1819
fn error(&self, msg: &str) {
19-
error!("{}", msg);
20+
println!("{}", msg);
2021
}
2122

2223
fn warn(&self, msg: &str) {
23-
warn!("{}", msg);
24+
println!("{}", msg);
2425
}
2526
}
2627

2728
enum ParseResult {
2829
CmdUsage,
29-
ParseOk(BindgenOptions, Box<io::Write+'static>),
30+
ParseOk(BindgenOptions, Box<io::Write>),
3031
ParseErr(String)
3132
}
3233

3334
fn parse_args(args: &[String]) -> ParseResult {
3435
let args_len = args.len();
3536

3637
let mut options: BindgenOptions = Default::default();
37-
options.derive_debug = false;
3838
let mut out = Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>;
3939

4040
if args_len == 0 {
@@ -47,7 +47,7 @@ fn parse_args(args: &[String]) -> ParseResult {
4747
options.links.push((args[ix][2..].to_string(), LinkType::Default));
4848
ix += 1;
4949
} else {
50-
match &args[ix][..] {
50+
match &*args[ix] {
5151
"--help" | "-h" => {
5252
return ParseResult::CmdUsage;
5353
}
@@ -98,12 +98,8 @@ fn parse_args(args: &[String]) -> ParseResult {
9898
options.builtins = true;
9999
ix += 1;
100100
}
101-
"-no-rust-enums" => {
102-
options.rust_enums = false;
103-
ix += 1;
104-
}
105-
"-derive-debug" => {
106-
options.derive_debug = true;
101+
"-ignore-functions" => {
102+
options.ignore_functions = true;
107103
ix += 1;
108104
}
109105
"-allow-unknown-types" => {
@@ -117,6 +113,14 @@ fn parse_args(args: &[String]) -> ParseResult {
117113
options.override_enum_ty = args[ix + 1].clone();
118114
ix += 2;
119115
}
116+
"-enable-cxx-namespaces" => {
117+
options.enable_cxx_namespaces = true;
118+
ix += 1;
119+
}
120+
"-no-type-renaming" => {
121+
options.rename_types = false;
122+
ix += 1;
123+
}
120124
_ => {
121125
options.clang_args.push(args[ix].clone());
122126
ix += 1;
@@ -129,7 +133,7 @@ fn parse_args(args: &[String]) -> ParseResult {
129133
}
130134

131135
fn print_usage(bin: String) {
132-
let mut s = format!("Usage: {} [options] input.h", &bin[..]);
136+
let mut s = format!("Usage: {} [options] input.h", &bin);
133137
s.push_str(
134138
"
135139
Options:
@@ -145,6 +149,10 @@ Options:
145149
matching any rule are bound to.
146150
-builtins Output bindings for builtin definitions
147151
(for example __builtin_va_list)
152+
-ignore-functions Don't generate bindings for functions and methods.
153+
This is useful when you only care about struct layouts.
154+
-enable-cxx-namespaces Enable support for C++ namespaces.
155+
-no-type-renaming Don't rename types.
148156
-allow-unknown-types Don't fail if we encounter types we do not support,
149157
instead treat them as void
150158
-emit-clang-ast Output the ast (for debugging purposes)
@@ -163,14 +171,22 @@ Options:
163171
Options other than stated above are passed to clang.
164172
"
165173
);
166-
print!("{}", &s[..]);
174+
println!("{}", &s);
167175
}
168176

169177
pub fn main() {
170178
let mut bind_args: Vec<_> = env::args().collect();
171179
let bin = bind_args.remove(0);
172180

173-
match parse_args(&bind_args[..]) {
181+
match bindgen::get_include_dir() {
182+
Some(path) => {
183+
bind_args.push("-I".to_owned());
184+
bind_args.push(path);
185+
}
186+
None => (),
187+
}
188+
189+
match parse_args(&bind_args) {
174190
ParseResult::ParseErr(e) => panic!(e),
175191
ParseResult::CmdUsage => print_usage(bin),
176192
ParseResult::ParseOk(options, out) => {
@@ -179,7 +195,7 @@ pub fn main() {
179195
Ok(bindings) => match bindings.write(out) {
180196
Ok(()) => (),
181197
Err(e) => {
182-
logger.error(&format!("Unable to write bindings to file. {}", e)[..]);
198+
logger.error(&format!("Unable to write bindings to file. {}", e));
183199
exit(-1);
184200
}
185201
},

0 commit comments

Comments
 (0)