See also
https://peter-kehl.github.io/embedded_low_level_rust
for building and testing no_std/no_std_heap/std libraries on desktop. That
also shows any source code included below.
Rust macros for ergonomic conditional compilation based on no_std,
no_std_heap and std
features.
The feature names used/referred-to by these macros are not, and cannot be, configurable. The above three feature names had to be hard-coded. (Explanation of those features is later in this document.)
TODO include Cargo.toml
Basic conditional feature-based compilation is easy. It can be as simple as using:
TODO EXAMPLE
But if you depend on compound conditions, it gets repetitive. It clutters the code. Hence suggest using macros.
New to Rust? Any identifier following by an exclamation mark ! indicates a
macro invocation. (Another type of macros, called attribute macros, start with a
hash #.)
TODO EXAMPLE
- any heap-less
no_stdlibrary will work for any purpose:no_stdwithout heap, with heap orstd - but some
no_stdlibraries may have both heap-less and heap parts. For example: extra functions orenumvariants that work withalloc::boxed::Box,alloc::vec::Vec,alloc::string::String... - We could have heap functions defined in separate traits in a separate (heap)
library, but that makes types complicated. And we can't add variants to an
existing
enumfrom another crate. - If you provide functionality for both heap and heap-less, have a
feature
called
no_std_heap(or similar). Then conditionally compile such functionality (see later in this document).
- "Controversial," but proactive & clear
- If your library can provide extra functionality in
std, (like usingHashMap)- have a feature for that (called, for example,
std) - have a feature for
no_std, too - Make those two features mutually exclusive (by a compile-time check). That is against the cargo book's general recommendation, but they do mention this option.
- require maximum one of those two features to be used
- this makes any consumer crate explicit about whether they require
stdorno_std - benefits
- any conflicts between dependencies (one using
stdbut another usingno_stdof the same crate) are reported clearly - it simplifies troubleshooting of consumer crates and also of your library
- it allows to differentiate (a small set of) consumer mid/higher level
libraries that are
std/no_std-agnostic. They import anstd/no_std-aware library, but thestd/no_stdchoice is left for the higher consumer. Such a consumer library would use thestd/no_stdaware library through abstractions that arestd/no_std-independent. This differentiation is not possible under the cargo book's general recommendation. Seeslicing_any_std_testlater in this document.
- any conflicts between dependencies (one using
- of course, all
no_stdfunctionality is available understdfeature, too no_std_heapextends functionality ofno_std. You could makeno_std_heapimplyno_stdand be usable even withoutno_std, but then your documentation and compile checks (no_std_heapvsstd) would get complicated. Instead, may I suggest to haveno_std_heaprequireno_std. Then the exclusion checks are betweenno_stdandstdonly.
- have a feature for that (called, for example,
- If your library can provide extra functionality in
If your no_std_heap or std code needs extra dependencies, use
Features >
Optional
dependencies.
TODO ranging -> slicing example