-
-
Notifications
You must be signed in to change notification settings - Fork 39.4k
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
Add basic support for writing keymaps in Rust #7475
Conversation
Hi! I've tried your fork in OCT (daniel5151@f8e68ae) and it worked. Which is great!
I think it's good if you could also define keymaps, |
It seems linker do not pick symbols from libraries over weak symbols in object files from the first place. What else can we do? |
Why not just Regardless, I'm not sure how well this approach scales, since a quick grep through QMK lists ~290 instances of That said, having users manually write Theoretically, it could be possible to set up some codegen using the Makefile + |
You are right. I thought the order matters but I was wrong. Yet, the order of object files and libraries do matter. I've done further experiment. I removed keymaps from keymap.c and added it to keymap.rs . You just need either one of |
Thank you for your contribution! |
Well, I see no one has gotten a chance to look at this PR / comment on it. Personally, I think it would be awesome to have Rust support in QMK, but if this isn't something people are interested in, then there's no reason to keep this PR open. |
Just adding my vote of interest! Also, AVR targets were recently merged into the nightly compiler. rust-lang/rust#44052 (comment) |
Would love to see this merged! Much better experience than C, IMO. |
I'm all for it! I have a question thouhg: any impact on the hex size? From what I read from the linked blog post, it shouldn't, but I'm not an expert at this low level of the code :) |
Unfortunately we're going to have to skip this at this stage. To put it bluntly, the number of QMK collaborators with the time and appropriate knowledge of Rust for maintaining this (and explaining the implementation to others) doesn't inspire confidence that this will be workable in the long term. Apologies for dragging this on, and whilst we appreciate the amount of work that went into this, it's just not feasible to pull it in at this stage. Sorry! |
All good, and totally understandable! As cool as it would be to see this sort of integration, if the community doesn't have enough people enthusiastic about Rust in QMK (along with having the technical chops willing to support an implementation), then so be it. For anyone stumbling across this PR in the future: please feel free to re-use any code / ideas from this PR, and let me know if you end up making anything particularly interesting with your Rust <-> QMK fusion! As a taste of what could've been: I used this Rust integration to port Zork to my Planck EZ by leveraging an existing Rust Z-Machine emulator (with some light tweaks):
That's the thing about Rust - aside from being great at a language-level, using Rust gives you access to a vast number of libraries from crates.io, making it possible to rapidly implement complex functionality (as opposed to wrestling with Makefiles and how best to integrate a particular C library). |
I won't say RIP because we can dream.
Thank you for proper clarification. |
QMK is great.
Rust is also great.
Wouldn't it be cool to use Rust with QMK?
This PR adds Rust support to QMK in a totally optional and non-intrusive manner. This PR does not provide a complete easy-to-use user facing experience to writing keymaps, and only seeks to lay the foundations of using Rust with QMK,
In other words, this PR is all about integrating Rust with QMK's build system, and setting up some infrastructure to ergonomically use QMK features from Rust (i.e: autogenerated FFI bindings, with corresponding high-level, "idiomatic Rust" wrappers). Future PRs can improve the ergonomics of using Rust with QMK by introducing additional abstractions / macros / wrappers around QMK's FFI.
Description
Disclaimer: I'm definitely not an expert at
make
, and QMK's Makefiles are kind of insane, so if there's a cleaner way to do some of the things I'm doing, please let me know! Feedback / contributions are more than welcome!With that out of the way, here is a brief overview of what this PR adds to QMK:
lib/rust/qmk-sys
andlib/rust/qmk
To make working with QMK from Rust as painless as possible, I've written two Rust crates that act as the "glue" between Rust and QMK.
qmk-sys
usesbindgen
to generate FFI bindings to QMK's C/C++ headers. e.g:void send_string(const char* str);
gets translated intoextern "C" { pub fn send_string(str: *const ctypes::c_char); }
qmk
builds on-top ofqmk-sys
, wrapping the unsafe auto-generated FFI calls in higher-level, safe to use Rust constructs.Makefile additions (in
tmk_core/rules.mk
)Rust support is totally opt-in, enables through the use of several new Makefile options:
RUST_CRATE
: the name of the rust crate with the user's keymapRUST_TARGET
: the platform to generate code for (e.g: thumbv7em-none-eabi)RUST_TOOLCHAIN
: which Rust toolchain to use (e.g: beta, nightly). Defaults to stable.RUST_QMK_FEATURES
: Optional features to enable in theqmk
crate.malloc
, which enables themalloc/free
based global allocatorRUST_QMK_HEADERS
: Additional headers to generate bindings for (inqmk-sys
). e.g: settingRUST_QMK_HEADERS = rgb_matrix.h
will create bindings to the RGB Matrix header file.User keymaps in Rust
While it's definitely not as "seamless" an experience to write keymaps in Rust, all-in-all, it's not too bad (especially considering this is only a first-pass)
cargo new <somename> --lib
in their keymap directoryCargo.toml
file to include[lib] crate-type = ["staticlib"]
RUST_CRATE=<somename>
andRUST_TARGET
in rules.mkAt that point, all gloves are off, and its up to the user to implement whatever QMK methods/structures they so desire. This currently requires writing at least some
extern "C"
functions (to hook into QMK), but it shouldn't be too difficult to abstract these behind a nicer, more idiomatic Rust interface via a future PR to theqmk
crate.Future Work
In the context of this PR:
RUST_TARGET
issue?As mentioned earlier, the goal of this PR is to lay the foundations of using Rust with QMK, not to provide a complete easy-to-use user experience of writing keymaps in Rust.
If this PR gets merged, subsequent PRs can improve the
qmk
andqmk-sys
crates with additional abstractions/safe wrappers over QMK's functionality. For example:qmk
crate. Integrating those macros (or something similar to them) into theqmk
crate would enable any user to define their layout in Rust in a cool and elegant way!send_string
requires unsafe code to call. All a safe wrapper has to do is add a null terminator to the provided string, and call the underlying methodsend_string
, rewritesend_string
in pure Rust, callingsend_char
via the FFI under-the-hood.Oh, and if you want to see an example of something totally awesome that Rust support in QMK might enable, check out this branch of my QMK repo 😄
Known Issues
Rust doesn't support AVR targets. There's an unofficial fork of Rust which does support them, but mainline does not.On the bright side, since AVR isn't supported, we only have to worry about ARM targets, which tend to have a bit more leeway with code-size.process_record_user
).process_record_user
which callsprocess_record_user_rs
, a method that's declared but not defined in the keymap.c file). See the includedrust_example
keymap for an example.If someone with a bit more experience wants to help out and look into some of these issues, that'd be super helpful!
... Thanks for reading this (kinda massive) PR. It's a pretty big change, and one that I'd love to see merged [in some form or another] 😄
Types of Changes
Checklist