Rust-for-Linux / linux

Adding support for the Rust language to the Linux kernel.
https://rust-for-linux.com
Other
4k stars 431 forks source link

`bindgen` wanted features & bugfixes #353

Open ojeda opened 3 years ago

ojeda commented 3 years ago

Note: see as well the "rust-for-linux" label in bindgen: https://github.com/rust-lang/rust-bindgen/labels/rust-for-linux.

Features that we would like to see

Required (we almost certainly want them)

Nice to have (not critical, we could workaround if needed, etc.)

Low priority (we will likely not use them in the end)

Done (stabilized, fixed, not needed anymore, etc.)


Bugs that we would like to see fixed

Required (we almost certainly want them)

Nice to have (probably not critical, we could workaround if needed, etc.)

Low priority (we will likely not use them in the end)

Done (stabilized, fixed, or not needed anymore, etc.)

pvdrz commented 2 years ago

Hi everyone!

I have opened some PRs on bindgen adding some features you needed:

I'd be happy to hear if the PRs here actually provide what you need.

alex commented 2 years ago

These look spot on to me. Thanks for your efforts!

ojeda commented 2 years ago

Added links above, thanks a lot @pvdrz! :)

dwlsalmeida commented 1 year ago

@ojeda Hey Miguel, is there a workaround in place for this?

Support function-like macros that use other macros and that evaluate to a numeric value when fully expanded (e.g. for Linux ioctl #defines using _IO*).

I am trying to write a v4l2 driver and one of the issues I found was that the pixel formats bindings are not generated by bindgen because the V4L2_PIXFMT* stuff is defined using the v4l2_fourcc macro

ojeda commented 1 year ago

For something like pixel formats that are stable (given they are in uapi, right?), I guess the easiest is re-implementing them on the Rust side, especially if you want to give them a proper type etc. anyway. Probably using a small temporary script to perform the bulk of the conversion.

Otherwise, if performance is not too much of a concern (even if cross-language LTO could reduce the cost at some point), one alternative is "executing" the macro at runtime by providing a C function that does it for the Rust side. In your case this one is likely not interesting because the important bits are the parameters to the macro, rather than the macro itself.

bjorn3 commented 1 year ago

For the drm fourcc pixel format codes, the drm-fourcc crate has some code which fetches all #define from the header, generates a constant for each #define in a new header and then runs bindgen on the generated header: https://github.com/danielzfranklin/drm-fourcc-rs/blob/main/build.rs

dwlsalmeida commented 1 year ago

One question though, suppose I use the approach suggested by @bjorn3

Do I commit the bindings I generate? Asking because apparently bindings_generated.rs is not part of the kernel per-se and is only generated during build time.

bjorn3 commented 1 year ago

I think the bindings should be generated on the fly to ensure they stay up to date, just like bindings_generated.rs.

dwlsalmeida commented 1 year ago

well, in which case I suppose that the code to generate them (i.e. something similar to the code in the drm-fourcc crate) would have to be integrated into the kernel build system somehow?

bjorn3 commented 1 year ago

Indeed. There is already infrastructure to run code written in rust. See for example scripts/generate_rust_target.rs.

dwlsalmeida commented 1 year ago

Makes sense, thanks for the pointers!

ojeda commented 1 year ago

It depends. If these constants are strictly stable (unlike many kernel APIs that you may see in bindings_generated.rs), you have the possibility to commit them, but in that case I would recommend writing directly in Rust what you need (rather than raw bindings that then you wrap). This is why I mentioned above the stability. You could also have a test to verify both sides match, though that could be a one-off thing.

If you go the generated route (which many times is the only way), then indeed, you could use a host program (it does not necessarily need to be written in Rust, but as @bjorn3 mentions, the support is there, so I would recommend it -- though currently you will only have the Rust standard library available, e.g. no regex). This approach has the drawback of adding complexity (the host program) and, depending on how you implement/parse the C header, you may introduce constraints on the C side. Another similar option is a proc macro, but that is slower (triggered every time you recompile the kernel crate, which would be unneeded -- you only need to do it once) and non-"pure" (in the "do not use the environment from a proc macro" sense).

Another angle to think about is whether new constants will appear frequently or not.