rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.42k stars 694 forks source link

#include <stdlib.h> makes bindgen generate hundreds of irrelevant definitions #1212

Closed kornelski closed 6 years ago

kornelski commented 6 years ago

Input C/C++ Header

#include <stdlib.h>
struct Foo {};

Bindgen Invocation

$ bindgen input.h

on macOS High Sierra.

Actual Results

pub const NL_LANGMAX: ::std::os::raw::c_uint = 14;
pub const NL_MSGMAX: ::std::os::raw::c_uint = 32767;
pub const NL_NMAX: ::std::os::raw::c_uint = 1;
pub const NL_SETMAX: ::std::os::raw::c_uint = 255;
pub const NL_TEXTMAX: ::std::os::raw::c_uint = 2048;
pub const _XOPEN_IOV_MAX: ::std::os::raw::c_uint = 16;
pub const IOV_MAX: ::std::os::raw::c_uint = 1024;
pub const _XOPEN_NAME_MAX: ::std::os::raw::c_uint = 255;
pub const _XOPEN_PATH_MAX: ::std::os::raw::c_uint = 1024;
pub const __MAC_10_0: ::std::os::raw::c_uint = 1000;
pub const __MAC_10_1: ::std::os::raw::c_uint = 1010;
pub const __MAC_10_2: ::std::os::raw::c_uint = 1020;
pub const __MAC_10_3: ::std::os::raw::c_uint = 1030;
pub const __MAC_10_4: ::std::os::raw::c_uint = 1040;
pub const __MAC_10_5: ::std::os::raw::c_uint = 1050;
pub const __MAC_10_6: ::std::os::raw::c_uint = 1060;
pub const __MAC_10_7: ::std::os::raw::c_uint = 1070;
pub const __MAC_10_8: ::std::os::raw::c_uint = 1080;
pub const __MAC_10_9: ::std::os::raw::c_uint = 1090;
pub const __MAC_10_10: ::std::os::raw::c_uint = 101000;
pub const __MAC_10_10_2: ::std::os::raw::c_uint = 101002;
pub const __MAC_10_10_3: ::std::os::raw::c_uint = 101003;
pub const __MAC_10_11: ::std::os::raw::c_uint = 101100;
pub const __MAC_10_11_2: ::std::os::raw::c_uint = 101102;
pub const __MAC_10_11_3: ::std::os::raw::c_uint = 101103;
pub const __MAC_10_11_4: ::std::os::raw::c_uint = 101104;
pub const __MAC_10_12: ::std::os::raw::c_uint = 101200;
pub const __MAC_10_12_1: ::std::os::raw::c_uint = 101201;
pub const __MAC_10_12_2: ::std::os::raw::c_uint = 101202;
pub const __MAC_10_12_4: ::std::os::raw::c_uint = 101204;
pub const __MAC_10_13: ::std::os::raw::c_uint = 101300;
pub const __MAC_10_13_1: ::std::os::raw::c_uint = 101301;
pub const __MAC_10_13_2: ::std::os::raw::c_uint = 101302;
pub const __IPHONE_2_0: ::std::os::raw::c_uint = 20000;
pub const __IPHONE_2_1: ::std::os::raw::c_uint = 20100;
pub const __IPHONE_2_2: ::std::os::raw::c_uint = 20200;
pub const __IPHONE_3_0: ::std::os::raw::c_uint = 30000;
pub const __IPHONE_3_1: ::std::os::raw::c_uint = 30100;
pub const __IPHONE_3_2: ::std::os::raw::c_uint = 30200;
pub const __IPHONE_4_0: ::std::os::raw::c_uint = 40000;
pub const __IPHONE_4_1: ::std::os::raw::c_uint = 40100;
pub const __IPHONE_4_2: ::std::os::raw::c_uint = 40200;
pub const __IPHONE_4_3: ::std::os::raw::c_uint = 40300;
pub const __IPHONE_5_0: ::std::os::raw::c_uint = 50000;
pub const __IPHONE_5_1: ::std::os::raw::c_uint = 50100;
pub const __IPHONE_6_0: ::std::os::raw::c_uint = 60000;
pub const __IPHONE_6_1: ::std::os::raw::c_uint = 60100;
pub const __IPHONE_7_0: ::std::os::raw::c_uint = 70000;
…
pub type __darwin_mbstate_t = __mbstate_t;
pub type __darwin_ptrdiff_t = ::std::os::raw::c_int;
pub type __darwin_size_t = ::std::os::raw::c_ulong;
pub type __darwin_va_list = __builtin_va_list;
pub type __darwin_wchar_t = ::std::os::raw::c_int;
pub type __darwin_rune_t = __darwin_wchar_t;
pub type __darwin_wint_t = ::std::os::raw::c_int;
pub type __darwin_clock_t = ::std::os::raw::c_ulong;
pub type __darwin_socklen_t = __uint32_t;
pub type __darwin_ssize_t = ::std::os::raw::c_long;
pub type __darwin_time_t = ::std::os::raw::c_long;
pub type __darwin_blkcnt_t = __int64_t;
pub type __darwin_blksize_t = __int32_t;
pub type __darwin_dev_t = __int32_t;
…
#[derive(Copy, Clone)]
pub struct _opaque_pthread_attr_t {
    pub __sig: ::std::os::raw::c_long,
    pub __opaque: [::std::os::raw::c_char; 36usize],
}
…
extern "C" {
    #[link_name = "\u{1}_tzname"]
    pub static mut tzname: [*mut ::std::os::raw::c_char; 0usize];
}
extern "C" {
    #[link_name = "\u{1}_getdate_err"]
    pub static mut getdate_err: ::std::os::raw::c_int;
}
extern "C" {
    #[link_name = "\u{1}_daylight"]
    pub static mut daylight: ::std::os::raw::c_int;
}
extern "C" {
    #[link_name = "\u{1}_asctime"]
    pub fn asctime(arg1: *const tm) -> *mut ::std::os::raw::c_char;
}
extern "C" {
    #[link_name = "\u{1}_clock"]
    pub fn clock() -> clock_t;
}
…
etc, etc.

Expected Results

struct Foo {}

i.e. include of system headers should not cause any output, unless some type from the header is actually used. Then it should only pull definition of that type, rather than open floodgates to whatever the OS puts in there. Total blacklisting of all items from all system headers would be fine, too. I prefer to add them from the libc crate.


This is a problem, because:

emilio commented 6 years ago

That is expected. You're supposed to be using the whitelisting / blacklisting bits which should leave out everything unneeded. In this case you'd call bindgen like binden input.h --whitelist-type Foo. Is that not working for some reason?

kornelski commented 6 years ago

When I make bindings for 3rd party code I don't know all the types. I'd rather allow/block by directory (e.g. everything from ./vendor/, nothing from /usr/).

kornelski commented 6 years ago

Because of documentation error (#1214) I thought whitelisting would be unusable, but with regex support the whitelist workflow is not too bad. It's just I didn't expect it to be necessary, and hoped for the default invocation to be smarter.

emilio commented 6 years ago

Right, whitelisting by directory was considered and it's not fun. For easy cases it's fine, but given you can declare the same type in multiple places, and then not define it, it can be unclear which directory a type belongs to.

rubberduck203 commented 4 years ago

@kornelski I'm trying to understand how you actually solved this problem. Do you have an example of how you removed all things Darwin from the generated code?

kornelski commented 4 years ago

I haven't solved it. I've closed the issue because @emilio's comment sounded like it's a "wontfix" problem.

Bindgen still generates unwanted symbols, and I just delete the garbage by hand.

For some things I've also used my citrus, which can filter out system header symbols better.

rubberduck203 commented 4 years ago

Ahh. Ok. Got it. Thanks for responding.