Description
I'm developing for an embedded target, but in a setup to run unit tests locally. For this reason we have two workspaces: one for local (host) compilation of most of our code in a lib and another workspace that builds for the embedded target and depends on the same lib. That second workspace is set up for cross compilation.
Looks something like this:
embedded-hal/
├─ src/
└─ Cargo.toml
embedded-lib/
├─ src/
├─ tests/
└─ Cargo.toml <- lib [3]
app/
├─ .cargo/
│ └─ config.toml
├─ src/
└─ Cargo.toml <- embedded workspace [2]
Cargo.toml <- workspace [1]
I can use cargo-show-asm
to display the RISC-V code that I'd like to like like so in the root folder:
cargo asm --target riscv32imc-unknown-none-elf -p embedded-lib --asm 0
But that will then use the default settings for the target whereas I'd like it to use the settings from the embedded workspace (panic abort, lto, etc.). If I try to run in the app
subfolder the lib won't be found.
I can for sure provide the necessary command line arguments for those settings, but is there simpler way to use the profile settings consistently? (set in both the app/Cargo.toml
and in the app/.cargo/config.toml
)
I do get that I can run with --all-crates
in the app
subfolder, but that often leads to the functions that I'm interested being inlined, so it would be great to run it on the library level. (one workaround here is to prevent inlining via attribute in the lib, and I am aware that it's kind of the opposite things... running with the flags I usually have but also not wanting inlining at the same time)
I think that I'm not the only one with a setup like that, it's based on a blog post from Ferrous Systems from a while back: https://ferrous-systems.com/blog/test-embedded-app/
The gory details
The workspace [1]
Cargo.toml
just provides a workspace file for all host-compiled code:
[workspace]
resolver = "2"
members = [
"embedded-lib",
# ...
# no "app" here
]
The embedded workspace [2]
Cargo.toml
is pretty standard for embedded:
[workspace]
[package]
name = "app"
edition = "2021"
version = "0.1.0"
[dependencies]
ric-hal = { path = "../embedded-lib" }
# ...
[profile.release]
panic = "abort"
codegen-units = 1
debug = true # debug symbols are nice and don't increase binary size
lto = true # these optimizations are belong to us
opt-level = 3
And this builds for the embedded target because of the .cargo/config.toml
:
[build]
target = "riscv32imc-unknown-none-elf"
rustflags = "-Z emit-stack-sizes"
The lib [3]
Cargo.toml
is just a standard one, as for any platform-independent lib. Nothing special about it