Open ojeda opened 3 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.
These look spot on to me. Thanks for your efforts!
Added links above, thanks a lot @pvdrz! :)
@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
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.
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
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.
I think the bindings should be generated on the fly to ensure they stay up to date, just like bindings_generated.rs.
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?
Indeed. There is already infrastructure to run code written in rust. See for example scripts/generate_rust_target.rs.
Makes sense, thanks for the pointers!
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.
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)
[ ] Support for a GCC-based backend.
[ ] Support non-trivial object-like macros that evaluate to a numeric value when fully expanded.
#define A ((int)1)
.#define
s using_IO*
.[ ] Support aligned members (including structs with bitfields) inside packed structs.
#[repr(C, align(...)]
inside an#[repr(C, packed)]
.struct alt_instr
: https://lore.kernel.org/all/202212272003.rgQDX8DQ-lkp@intel.com/[ ] Support a new "enum variant" kind, similar to
rustified_enum
, that provides a safe method to transform a C enum to Rust.Nice to have (not critical, we could workaround if needed, etc.)
[ ] A way to specify a MSRV, instead of
--rust-target
(which only supports a subset of versions).--rust-target
, the kernel supported Rust 1.78.0+ andbindgen
0.65.1+, thus we picked--rust-target 1.68
, since it is the maximum stable version supported by the--rust-target
flag inbindgen
0.65.1 (and it is lower than our MSRV).[ ] Support for Edition 2024.
[ ]
process_comments
via CLI.Low priority (we will likely not use them in the end)
Done (stabilized, fixed, not needed anymore, etc.)
[x] Support
unsafe_op_in_unsafe_fn
.[x] Support
_Noreturn
,[[noreturn]]
,__attribute__((noreturn))
[x] Support
typedef
s shadowing types e.g.typedef struct T *T;
.maple_*node
s (https://github.com/Rust-for-Linux/linux/issues/795).[x] Take advantage of
feature(core_ffi_c)
andfeature(c_size_t)
.--ctypes-prefix core::ffi
.[x] A way to query the Clang version being used.
[x] Compile-time layout tests.
[x] Support
static inline
functions in headers (by generating a wrapper).bindgen
currently (0.64.0) has experimental support via--wrap-static-fns --experimental
.skbuff.h
has 300+static inline
s: https://lore.kernel.org/rust-for-linux/f28d6403-d042-4ffb-9872-044388d0f9d9@lunn.ch/[x] Raw pointer bitfield accessors.
[x] Rust for Linux in the
bindgen
CI.[x] CI: update to v6.12-rc5.
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.)
[x] C javadoc comments are not Markdown-escaped, triggering
rustdoc
warnings.[x] Attribute
btf_type_tag
makesconst
ness of pointers disappear.[x] "Unable to find libclang" problems (https://github.com/Rust-for-Linux/linux/issues/934), possibly related to Clang 15.
[x]
--wrap-static-fns
generates code thatreturn
s a call to avoid
function.[x]
--wrap-static-fns
generates()
for empty parameter lists.[x] Fix the support for linking
libclang
statically.