Rust is now mainstream for desktop and cloud applications. As such, components like compilers, build tools, etc. can be easily installed, and integration into the desired operating system is straightforward. Rust has also become part of the Linux kernel and thus allows the development of kernel modules in Rust.
But what about the use of Rust on embedded Linux platforms and distributions that are created using Yocto, for example?
How do I get Rust into my Yocto build?
It’s already there!
Rust and the necessary toolchain are probably already available in your Yocto build, because Rust has been part of openembedded-core since Yocto Honister. This means that no additional layers are needed. All dependencies and recipes are already available in poky/meta.
| Rust version | Yocto version (selection) |
| 1.84.1 | Walnascar |
| 1.75 | Scarthgap |
| 1.59 | Kirkstone |
| 1.54 | Honister |
I would like to use a more recent version of Rust
If you need to use both an older Yocto version and a new Rust version, for example because you need the Rust 2024 Edition, special Yocto layers can be used.
LTS mixins
With the lts-rust-mixin layer, a current Rust version can be used. In this layer there are backports of current Rust versions for a few older Yocto versions. The layer can be added as usual to BBLAYERS in bblayers.conf, with the appropriate commit checked out.
Rust binary
The meta-rust-bin layer also pursues the goal of a backport from modern Rust to older Yocto versions. In contrast to the usual approach in Yocto of compiling all tools on the host, this layer provides binaries directly – with all the advantages and disadvantages of pre-compiled tools. The layer is added to bblayers.conf as described above. In recipes, you must make sure not to use inherit cargo, but inherit cargo_bin to clearly specify which variant you want to use.
Meta Rust
The historical layer meta-rust meta-rust need not (and should not) be used in a normal Yocto distribution, as the code is already contained in other layers.

Ready for the Rust challenge?
Rust Programming Language Quiz
Put your knowledge to the test! Take our quiz for software developers and find out how much you know about Rust.
What do I have to do to integrate a Rust application into my system?
Integrating a Rust application into a system is not really any different from integrating a “C/C++” application. Let’s take a look at a potential scenario:
- Yocto version is Scarthgap with lts-rust-mixin
lts-rust-mixin - The application is available on GitHub. Although the application is simple, it does have some dependencies in the form of crates.
Project setup
The lts-rust-mixin layer must be added to bblayers.conf.
In local.conf, or better in a separate distro.conf, Rust is activated and the version specified. It is not imperative to specify the Rust version, but it is helpful as an error message appears if the lts-rust-mixin layer is configured incorrectly.
DISTRO_FEATURES:append = " rust"
RUST_VERSION = "1.85.1"
CARGO_VERSION = "1.85.1"
Yocto recipe
The recipe is independent of how Rust is activated for this system. Here is a minimal but complete recipe for compiling the application and installing it on the target system.
(1)
SUMMARY = "Simple Webserver"
DESCRIPTION = "A simple webserver in async rust"
HOMEPAGE = "https://github.com/<user>/simple_srv_rs"
LICENSE = "MIT"
LIC_FILES_CHKSUM = file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302
(2)
TAG = "0.1.6"
SRC_URI = "git://github.com/<user>/simple_srv_rs.git;branch=async_server;tag=v${TAG};protocol=https"
S = "${WORKDIR}/git"
(3)
TARGET_BIN_NAME= "webserver-rs" # Must match the project name in Cargo.toml
(4)
inherit cargo
do_fetch[network] = "1"
do_compile[network] = "1"
CARGO_BUILD_FLAGS:remove = "--frozen"
CARGO_DISABLE_BITBAKE_VENDORING = "1"
(5)
do_install() {
install -d ${D}${bindir}
install -m 0755 ${B}/target/${RUST_TARGET_SYS}/release/${TARGET_BIN_NAME} ${D}${bindir}/${TARGET_BIN_NAME}
# --- other install tasks ---
}
FILES:${PN} += "${bindir}/${TARGET_BIN_NAME}"
- Header with the necessary names and the licence with the appropriate hash.
- The desired git tag from the desired branch is used.
- Bitbake makes a poor attempt at the name of the application. The variable is used to install the application.
- Derive from the
cargoclass so that the subsequent commands and variables are known. Therustclass is not usually needed.
Network access is required to download crates.CARGO_BUILD_FLAGS:remove = "—frozen"
The flag—frozenmeans—lockedand—offlinetogether. If—frozenis removed from the recipe, cargo has access to the web to download crates. For the build in a CI, or for other reasons, you can leave the download to Bitbake. More on this later. Disabled vendoring means that all dependencies must be downloaded. - The application is installed on the target system.
RUST_TARGET_SYSis derived from the Rust target triple, i.e. something likearmv7-unknown-linux-gnueabihf. A release build is created by default.
Be future-proof
Rust Transition Service
Regulatory pressure to make software more secure, efficient and cost-effective is constantly growing. Rust relieves this pressure.
Dependencies managed by Yocto
You often want the crates to be managed by Yocto. For example, if all dependencies are to be cached in the CI/CD pipeline. For this to be possible, the dependencies must be specified in the recipe in the form:
SRC_URI += " \
crate://crates.io/addr2line/0.24.2 \
"
SRC_URI[addr2line-0.24.2.sha256sum] = "dfb..1c1"
A non-trivial application already has several dozen dependencies. To ensure that the recipe remains readable and to enable automation, it is advisable to pack these dependencies into a <recipe>-crates.inc file.
There are different ways to list the dependencies together with their checksum in this file.
- The Bitbake command
bitbake -c update_crates<recipe>. This readscargo.lockand creates the<recipe>-crates.incfile.
This command must be executed manually if the application version changes. - Self-made script that is executed first in the recipe.
cargo bitbakeis not an option. Although this tool is recommended everywhere, the recipes generated are unusable, partly because the checksums are not integrated.
Here is the recipe from earlier, but following this approach:
SUMMARY = "Simple Webserver"
DESCRIPTION = "A simple webserver in async rust"
HOMEPAGE = "https://github.com/<user>/simple_srv_rs"
LICENSE = "MIT"
LIC_FILES_CHKSUM = file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302
(1)
inherit cargo
inherit cargo-update-recipe-crates
(2)
require ${BPN}-crates.inc
TAG = "0.1.6"
SRC_URI = "git://github.com/<user>/simple_srv_rs.git;branch=async_server;tag=v${TAG};protocol=https"
S = "${WORKDIR}/git"
TARGET_BIN_NAME = "webserver-rs"
(3)
# Keep network access during fetch so that the initial download is possible
do_fetch[network] = "1"
# Remove network access during build since we have all dependencies
do_compile[network] = "0"
do_install() {
install -d ${D}${bindir}
install -m 0755 ${B}/target/${RUST_TARGET_SYS}/release/${TARGET_BIN_NAME} ${D}${bindir}/${TARGET_BIN_NAME}
# --- other install tasks ---
}
FILES:${PN} += "${bindir}/${TARGET_BIN_NAME}"
inherit cargo-update-recipe-cratesis required to execute thebitbake -c update_crates<recipe>command..- The file with the dependencies is used.
- Network access is no longer required during compilation. However, in order to receive the crates initially, network access is required for the fetch.
CARGO_DISABLE_BITBAKE_VENDORINGis set tofalseby default.
Conclusion
Rust is now on embedded Linux systems and the procedure described here can be used to integrate a simple but complete application with Yocto into a Linux system. The long dependency lists must be maintained, but the right tools do the heavy lifting for you.
THIS MIGHT ALSO INTEREST YOU
How to integrate Rust into C/C++ projects
Rust: Tools for reliable dependency management
Successfully introducing Rust into your team
