Skip to content

Allow adding a linker script in build.rs #7984

Closed
@xobs

Description

@xobs

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:

  1. These are overridden if the RUSTFLAGS variable is set
  2. 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))
  3. 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:

  1. Runtime crates such as cortex-m-rt or riscv-rt can bundle their own linker scripts using their own naming convention for e.g. .bss or .data
  2. We can omit the (unversioned?) .cargo/config file
  3. The flag can be translated as appropriate depending on the linker
  4. 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:

  1. How do we deal with translating linker scripts across linkers? For example, msvc only supports /REBASE, not full scripts.
  2. What about linkers that only accept one linker script?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-build-scriptsArea: build.rs scriptsA-linkageArea: linker issues, dylib, cdylib, shared libraries, soC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions