Rust: Add experimental support with Ninja
Introduction
CMake is the build system of choice for many existing C and C++
projects. When integrating Rust to such projects, the current practice
is to invoke cargo to build a static library which is then linked by
cmake. While this might be fine when talking about big subsystems, using
cargo does not make sense if the project wants to integrate Rust in
projects such as kernels, where writing individual drivers (which can be
quite small) is concerned. One such example is Zephyr 0.
This PR attempts to add Rust support in a way that can allow adding small chunks of Rust to CMake projects.
My knowledge regarding both CMake and Rustc (I have mostly only used
cargo) are rather limited, I probably didn't do things the most
optimal way. So feel free to point out what can be improved/fixed.
Implementation
The TU for Rust is a crate, not per-source. Rustc expects entry file to TU as input, and cannot work with object files. So we need to have one-step build/link in most cases, similar to what old Swift was doing.
While the files for Rust modules are not added to cmake add_executable/add_library, dep-info file created by rustc is used to trigger rebuilds if any module changes.
Since we need to modify the target generator outputs for one-step build/link setups, only Ninja support is present.
Currently, executable, static library and dynamic library are supported build configurations. Limited support is also present for Rust object libraries. While using object files produced by rustc is not useful in most cases, it can be used directly in no_std contexts such as Linux kernel and RTOS.
I have added 2 simple tests which build and link rust to rust and rust to c executable.
Future Work
- Use more of existing CMake linker stuff.
Rustc allows us to select the linker to use 1. And -C link-args= can
be used to directly pass arguments to the linker. This is quite powerful
and should probably be exposed using CMake at some point. Additionally,
CMake already has support for most linkers, so we can generate linker
flags using it, instead of doing rustc specific things.
- Rlib support
Rustc can also build a "Rust library", which would be better to use in rust to rust linkage cases.
See-also: https://discourse.cmake.org/t/8514/20
Issue: #25492
Topic-rename: rust-support