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

Generate bindings once for all platforms and architectures #176

Merged
merged 3 commits into from
Nov 3, 2023

Conversation

ids1024
Copy link
Member

@ids1024 ids1024 commented Oct 24, 2023

The same drm headers are used for all architectures, and for the BSDs. There are only a couple typedefs that differ.

This uses linux-raw-sys to define __kernel_size_t on Linux, and libc::size_t on the BSDs.

I guess CI needs to be updated for this. Not sure if there would be a good way to automatically test that the bindings are correct for multiple architectures.

@ids1024 ids1024 mentioned this pull request Oct 24, 2023
Comment on lines 6 to 10
#[cfg(any(target_os = "android", target_os = "linux"))]
extern crate linux_raw_sys;

#[cfg(not(any(target_os = "android", target_os = "linux")))]
extern crate libc;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still needed if we were to set edition 2018?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the extern crate lines would be unnecessary in edition 2018 or later.

Copy link
Contributor

@MarijnS95 MarijnS95 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what would limit us from setting it to 2018, given that the MSRV is already at 1.65 and drm-sys can't be compiled with much older Rust anyway?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, with the current MSRV I don't think there's any reason not to update to the current 2021 edition.

Comment on lines +17 to +22
fn blocklisted_type_implements_trait(
&self,
name: &str,
_derive_trait: DeriveTrait,
) -> Option<ImplementsTrait> {
if name == "__kernel_size_t" || name == "drm_handle_t" {
Some(ImplementsTrait::Yes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to go to the (imo rather vague) bindgen documentation to figure out that this is telling bindgen that these types implement a bunch of ("standard"??) traits, so that any struct using these types could also automatically derive() those traits (all of them?).

Perhaps a doc-comment could complement this nicely?

Copy link
Contributor

@MarijnS95 MarijnS95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really like the simplification this provides 👌

@ids1024
Copy link
Member Author

ids1024 commented Oct 25, 2023

I guess if the drm headers are the same across operating systems and architectures, but have potential differences in the system headers they include and in an #if condition, this could be checked automatically by running bindgen for multiple platforms with the same drm header. Then it should find exactly identical results when we blocklist the parts that differ here.

But this should be correct currently, I doubt more differences will be added in the future, and they should be somewhat obvious looking at changes to bindings.rs.

@Drakulix
Copy link
Member

I guess if the drm headers are the same across operating systems and architectures, but have potential differences in the system headers they include and in an #if condition, this could be checked automatically by running bindgen for multiple platforms with the same drm header. Then it should find exactly identical results when we blocklist the parts that differ here.

But this should be correct currently, I doubt more differences will be added in the future, and they should be somewhat obvious looking at changes to bindings.rs.

Right, CI should probably still use one architecture to generate the bindings (e.g. x86_64, given that is the least overhead) and then run the other architectures just to compare and fail the test if they differ.

Like that the crate can theoretically support anything, but we still would have a set of well tested architectures.

Given #175 we probably would also want to add testing for riscv in this PR, no?

@ids1024
Copy link
Member Author

ids1024 commented Oct 27, 2023

It's possible to generate bindings for headers on a specific architecture with something like:

apt-get install --yes wget linux-libc-dev-riscv64-cross bindgen libclang-dev rustfmt
wget https://github.com/torvalds/linux/raw/master/include/uapi/drm/drm.h
wget https://github.com/torvalds/linux/raw/master/include/uapi/drm/drm_mode.h
bindgen drm.h -- -D __user= -isysroot /usr/riscv64-linux-gnu

(Though that particular bindgen invocation doesn't generate exactly what we want.)

Then we can generate up-to-date bindings easily on CI, and verify that there aren't platform differences for any of the architectures Debian has compilers for.

Does it still make sense to have a use_bindgen feature flag if the pre-generated bindings work across platforms?

@Drakulix
Copy link
Member

Does it still make sense to have a use_bindgen feature flag if the pre-generated bindings work across platforms?

Depends on how up-to-date our bindings are. I guess it doesn't hurt to keep it around?

@ids1024 ids1024 marked this pull request as ready for review November 2, 2023 22:47
@ids1024
Copy link
Member Author

ids1024 commented Nov 2, 2023

Updated with CI changes to pull headers from Linux git repo, generate on all tested architectures, and compare to verify they are the same.

The same drm headers are used for all architectures, and for the BSDs.
There are only a couple typedefs that differ.

This uses `linux-raw-sys` to define `__kernel_size_t` on Linux, and
`libc::size_t` on the BSDs.
This pulls bindings from the Linux kernel repository, so we do not
depend on Ubuntu packages, or hacks to use packages from a different
arch. The parts that potentially differ are from sysroot headers.

CI compares each version of generated bindings against the x86_64
version, and fails if they do not all match.

This also adds `riscv64gc-unknown-linux-gnu` as a tested target.

Resolves Smithay#165.
Rust 1.65 is already required.
Copy link
Member

@Drakulix Drakulix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing. Thanks a bunch!

@Drakulix Drakulix merged commit ec52ef7 into Smithay:develop Nov 3, 2023
16 checks passed
@ids1024 ids1024 deleted the bindings branch November 3, 2023 15:54
ids1024 added a commit to ids1024/gbm.rs that referenced this pull request Nov 14, 2023
Drakulix pushed a commit to Smithay/gbm.rs that referenced this pull request Nov 14, 2023
ids1024 added a commit to ids1024/input.rs that referenced this pull request Jan 16, 2024
Based on the CI in
Smithay/drm-rs#176.

`libinput_log_set_handler` is disabled, since it requires `va_list`.
That doesn't seem practical to support until `std::ffi::VaList` is
stable.

I don't think BSDs should be different here, but I haven't tested it
yet. CI confirms that the bindings are the same on Linux for tested
architectures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants