I figured I'd try here first before raising a github feature request for cargo.
My understanding is typically with embedded platforms there's no standard library. Part of the reason for this is that std includes operating system functionality which isn't needed. But also std covers use of types and functionality assicoated with the heap such as String which isn't available by default.
This hasn't stopped people from trying though to gain access to some of the code libraries already out there. I've seen a few workarounds to this
- With the esp32 platform they've managed to setup they're own std library for ESP32 devices and variants via esp-idf.
- For the stm32 / rpi-pico devices you can use the embedded-alloc or nostd creates to get some of this functionality back (assuming you want to use a heap)
- GitHub - nostd-rs/nostd: Simplify `no_std` development
- GitHub - rust-embedded/embedded-alloc: A heap allocator for embedded systems
- Someone tried a proof of concept using parts of the esp-idf
GitHub - tana/pico-std-rust: Proof-of-concept for using Rust std on RP2040
There's also been some use of cargo +nightly -Zbuild-std=std build
but that's considered something of a hack and not supported / requires nightly.
I think it's also been broken for a few months now as well due to thread_local
- document args for `-Zbuild-std` when folks aren't building everything · Issue #14889 · rust-lang/cargo · GitHub
- Using std in embedded Rust
The end result seems to be lots of different kinds of hacks and fudges as a way of working around the problem if you want to use a library that references std in some small way. Some people you say you shouldn't be using a heap on an embedded device in the first place. Other people like myself like the idea of being able to use the device however we want.
For a top level crate that your working on, you can do something like this for example using the nostd library
[dependencies]
std = { package = "nostd", version = "0.1" }
We still have to add #![no_std]
to the top of main.rs
and we have to manually add in any use statements as this fake std won't be imported / use aliased automatically
use std::string::String;
use std::vec::Vec;
But it does seem the cleanest option so far assuming we use a heap (the rp2350 has 512Kb of memory which can be extended up to 16Mb with PSRAM)
Where this tends to fall down however is a dependency / library that's also trying to use String or some other heap related type.
Currently there's no way to feed in a substitute std library into that dependency without forking it and making changes to it's Cargo.toml file.
I looked into build.rs but that doesn't have the functionality to perform any form of substitution
Programatic access to cargo as a library might be one option but that's not guaranteed to have a stable API I think.
As a suggestion, perhaps a simple option that allows adding a dependency to all packages underneath the current crate (subdepends) via something like a special dependencies.global option
[dependencies.global]
std = { package = "nostd", version = "0.1" }
Or even something that's more specific just for std replacement.
This wouldn't be the only thing you'd need to do though, typically with the normal std library, things tend to be auto imported
(you can use String without use std::string::String;
for example)
So a code change sonewhere else (not sure if it would be under rustc) would be also needed to try and handle this somehow under #![no_std]
environments.
The idea is to gain greater compatibility with existing libraries that were never written with no_std in mind when they were originally written. Also to find a more consistent way to swap out std functionality across the board (for all subdepends) via something like a custom std crate that sits next to the main project.