Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std dependencies when use_core is used: new approach #1583

Open
hellow554 opened this issue Jun 26, 2019 · 18 comments
Open

std dependencies when use_core is used: new approach #1583

hellow554 opened this issue Jun 26, 2019 · 18 comments

Comments

@hellow554
Copy link

hellow554 commented Jun 26, 2019

Bindgen Invocation

$ bindgen /usr/include/stdint.h --use-core | rg 'std'

Actual Results

pub type __u_char = ::std::os::raw::c_uchar;
pub type __u_short = ::std::os::raw::c_ushort;
pub type __u_int = ::std::os::raw::c_uint;
pub type __u_long = ::std::os::raw::c_ulong;
pub type __int8_t = ::std::os::raw::c_schar;
pub type __uint8_t = ::std::os::raw::c_uchar;
pub type __int16_t = ::std::os::raw::c_short;
pub type __uint16_t = ::std::os::raw::c_ushort;
pub type __int32_t = ::std::os::raw::c_int;
pub type __uint32_t = ::std::os::raw::c_uint;
[...]

Expected Results

This is mostly a dupe/expansion of #1015, #448, #628, #1439.

I'm afraid that you don't like the discussion anymore, but in my eyes this isn't closed. If I want to build a !#[no_std] crate which relies on "no std" c libraries, it isn't possible in the current form.

I know, that some of types can't be expressed in core(, but e.g. why is int8_t defined as c_schar instead of i8?), but currently my workaround is to opaque all the types. This isn't feasible. The workaround with libc is also not possible for me, because I don't have a libc running on bare metal.

Bindgen should be able to deduce the types, because it knows the target and therefore knows what c_uchar, c_ushort, ... are, e.g. if they are u8 or u16 or anything else. They can be mapped directly to the corresponding types.

What I would like to see is either an option to skip all std dependent types (e.g. by using --skip-std-types). I see two possibilities here:

  1. The type isn't used at all the and the compiler won't notice anything
  2. The type is used and rust will throw an error, that the type hasn't been found.

One could also print a message to stdout, that a specific type (e.g. clock_t) has been skipped, because of that option above.

Is that something one could provide? What alternatives are (expect for blacklisting all the types :|).

@hellow554
Copy link
Author

hellow554 commented Jun 26, 2019

Maybe one could also provide meta variables, which is then an alias for e.g. std::os::raw::c_int, e.g.

pub type r_c_int = std::os::raw::c_int;
[...]
pub type __int32_t = r_c_int;
pub type __mode_t = r_c_int;
[...]

and then I only have to specify the types r_c_int which can be done by using the blacklist feature again :)

@emilio
Copy link
Contributor

emilio commented Jun 26, 2019

The expected way to use --use-core is also using --ctypes-prefix.

So ./target/debug/bindgen /usr/include/stdint.h --use-core --ctypes-prefix=libc, for example.

You can perfectly do something like: ./target/debug/bindgen /usr/include/stdint.h --use-core --ctypes-prefix=myctypes

And define something like:

pub mod myctypes {
    pub type c_int = i64; // yolo
}

It's not clear to me how that is different from your proposed solution, or am I missing something?

@emilio
Copy link
Contributor

emilio commented Jun 26, 2019

I know, that some of types can't be expressed in core(, but e.g. why is int8_t defined as c_schar instead of i8?), but currently my workaround is to opaque all the types. This isn't feasible. The workaround with libc is also not possible for me, because I don't have a libc running on bare metal.

int8_t is treated internally in bindgen as i8, __int8_t, which is what you show above, is a typedef that your standard C headers happen to have.

@hellow554
Copy link
Author

hellow554 commented Jun 27, 2019

So ./target/debug/bindgen /usr/include/stdint.h --use-core --ctypes-prefix=libc, for example.

As said, libc is not feasible here :/

You can perfectly do something like: ./target/debug/bindgen /usr/include/stdint.h --use-core --ctypes-prefix=myctypes

But I do not know the types, but my compiler does (I honestly don't care if an int is 16 or 32 bits wide and I don't think this is an ideal solution that the user should supply the exact types).

I'm not really sure how to handle this, but IMHO the --use-core experience is not very ideal and lead to some frustration when I first used it.

@emilio
Copy link
Contributor

emilio commented Jun 27, 2019

Ah, I see. So what you want is a way to generate bindings for whatever target clang bindgen invoked against, is that right?

That means that the bindings will no longer be portable, but maybe that's ok as long as you opt into that.

@cquartier
Copy link

I just want to add I'm in the same predicament. Bare metal embedded, no libc. I don't care about portability of the bindings I'm generating for a specific hardware target, what I want is for bindgen to generate no_std bindings without having to hand-define all the c_types, which seems to be the case.

@emilio
Copy link
Contributor

emilio commented Jul 24, 2019

Ok, so I'll assume #1583 (comment) is the right understanding of the issue.

If so, this should be pretty easy to implement. Just add a new switch and then in this match here:

TypeKind::Int(ik) => {

We need to do something similar to what we do for wchar_t already, but instead of doing it when parsing the type we should do it later. Indeed, there's no reason wchar_t works that way so I sent #1596 to clean it up.

Doing the same for the other integer types under a flag should be pretty straight-forward.

@Michael-F-Bryan
Copy link
Contributor

Has there been any further work towards this issue?

It feels a bit odd to require users to specify their definition of c_int and friends using --ctypes-prefix, especially when a lot of my headers explicitly use the types from stdint.h (i.e. int32_t and uint8_t) which have unambiguous equivalents in Rust.

@deliciouslytyped
Copy link

deliciouslytyped commented Jan 25, 2020

I've also run into this, I'm trying to generate bindings for GRUB. Is there anything I can do, or do I need to figure out what types the c types correspond to and map them by hand?

@deliciouslytyped
Copy link

deliciouslytyped commented Jan 25, 2020

https://github.com/rust-lang/libc seems to suggest it might be possible to use libc with no_std? std: by default libc links to the standard library. Disable this feature remove this dependency and be able to use libc in #![no_std] crates.

Is it possible to use libc's types without needing to actually link / whatever the binary to the final result?

Edit: after grepping a bit, if I did it right, it seems like I really only need to map 12 or so simple basic types, so maybe it's not so bad.
Edit 2: assuming this is correct, it seems easy enough to copy: https://github.com/rust-lang/libc/blob/58b2706e75df705813dd94c50b1f18e852519c33/src/unix/mod.rs

@emilio
Copy link
Contributor

emilio commented Jan 26, 2020

Yeah. Alternatively as a reply to the comments above no, there hasn't been any work towards this feature, but #1583 (comment) should still be an accurate description of what needs to get done.

I don't plan to work on this myself but I'll happily review a patch or mentor someone interested in doing so.

@markushx
Copy link

I found the hints in https://docs.rust-embedded.org/book/interoperability/c-with-rust.html#automatically-generating-the-interface useful:

[dependencies]
cty = "0.2.1"
let bindings = bindgen::Builder::default()
    .use_core()
    .ctypes_prefix("cty");

@Finomnis
Copy link

Finomnis commented Oct 3, 2022

Since Rust 1.64.0 this is now possible:

let bindings = bindgen::Builder::default()
    .use_core()
    .ctypes_prefix("::core::ffi");

Although a couple of types are still missing at the time of writing; among them are:

  • c_size_t
  • c_ssize_t
  • c_ptrdiff_t

@pvdrz
Copy link
Contributor

pvdrz commented Oct 3, 2022

This might be relevant: #1663 (comment)

@Finomnis
Copy link

Finomnis commented Oct 3, 2022

@pvdrz Why use clang/llvm to figure this out if it is natively supported by core now? Or are you talking about size_t?

@pvdrz
Copy link
Contributor

pvdrz commented Oct 3, 2022

Although a couple of types are still missing at the time of writing; among them are:

* `c_size_t`

* `c_ssize_t`

* `c_ptrdiff_t`

I could see these working on a nightly rust target. Implementing this change wouldn't be that hard.

@pvdrz Why use clang/llvm to figure this out if it is natively supported by core now? Or are you talking about size_t?

If you're not interested in portability and you cannot use rust 1.64 for whatever reason you'd be better using the sized integer types that rust provides instead.

@Finomnis
Copy link

Finomnis commented Oct 10, 2022

@pvdrz I see a lot of "if"s there. But I'd argue "if" you are generating the ffis statically (meaning, once and commit them to git instead of at compile time), the core::ffi types would be the way better choice.

@pvdrz
Copy link
Contributor

pvdrz commented Oct 10, 2022

@pvdrz I see a lot of "if"s there. But I'd argue "if" you are generating the ffis statically (meaning, once and commit them to git instead of at compile time), the core::ffi types would be the way better choice.

yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants