Cross-compile profile from different workspace
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
How do you compile stuff for your embedded setup? Something like cargo asm --manifest-path app/Cargo.toml -p embedded-lib whatever maybe?
Typically I cd into the app folder and run cargo build there.
If I run cargo asm --manifest-path app/Cargo.toml -p embedded-lib whatever I get the same error as if I'd cdd into the app folder: Error: Package 'embedded-lib' is not found
Is this code publicly available? Or can you make a small sample I can fork and mess with?
Our full code is not available, but I can strip it down for you to have an example - please give me one to two days.
Sure. You can also try running cargo asm -vvv --manifest-path ... and cargo build -v and look for anything obvious...
Sorry for the long wait, had to play around some to make it visible... (and then I forgot to send it off after typing 🤦 )
I attached the zip with the repro.
If I now run
repro$ cargo asm --target riscv32imc-unknown-none-elf -p embedded-lib --lib --asm
Then I'll get the output with the profile of the PC workspace used (which I configured to disable the optimizier to make this more visible) - what would be great would be to have it use the profile in the app folder. We can do this by running in the app folder
repro/app$ cargo asm --all-crates --target riscv32imc-unknown-none-elf --bin app --asm
but this somehow defeats the advantage of running cargo asm --lib where running on the lib only
All the commands you gave me are failing with rustc/cargo complaining about missing stuff, probably my crosscompilation pipeline is not configured at all, but I managed to reproduce your error from this command cargo asm --manifest-path app/Cargo.toml -p embedded-lib whatever and pushed a branch called include-deps that actually includes dependencies (embedded-lib in this case) into a search space. It prints something for me. Can you check if it helps with your problem?