Description
Some kinds of targets such as embedded devices have special requirements when it comes to linking. On these devices, a linker script is required in order to load various classes of memory at specific offsets. Without this value, a default linker script is used, which very rarely works on embedded targets.
The current approach (decided in rust-embedded/wg#24 (comment)) is to create a per-project .cargo/config
file to pass flags to rustc, however this suffers from a number of drawbacks:
- These are overridden if the
RUSTFLAGS
variable is set - This file depends on the cwd, which means e.g.
cargo build --target riscv32imac-unknown-none-elf -p kernel
can pick up different linker scripts depending on the current directory (Support linker scripts in Cargo.toml / build.rs rust-embedded/wg#432 (comment)) - This file must be copied into every single project, precluding it from being provided by an
-rt
crate.
It would be nice to be able to include a linker script as an artifact from build.rs
by echoing a path to stdout. All of the current examples require users to manually copy this file (e.g. cortex-m-rt or riscv-rt), and the end result of not including this file is either a broken binary or a failed build.
By allowing build.rs
to specify additional linker files, we solve several problems:
- Runtime crates such as
cortex-m-rt
orriscv-rt
can bundle their own linker scripts using their own naming convention for e.g..bss
or.data
- We can omit the (unversioned?)
.cargo/config
file - The flag can be translated as appropriate depending on the linker
- Different crates in a workspace can be built with different linker flags, for example an operating system loader, kernel, and runtime
Appending linker flags to the output seems like it should be similar to how library crates can append libraries to the output, and it shouldn't be considered an error if multiple linker files are included. In fact, the approach that is taken by the current -rt
libraries is to include an mcu-specific linker script alongside an arch-specific crate.
Disadvantages I can see from this approach are:
- How do we deal with translating linker scripts across linkers? For example, msvc only supports
/REBASE
, not full scripts. - What about linkers that only accept one linker script?