Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow adding a linker script in build.rs #7984

Closed
xobs opened this issue Mar 11, 2020 · 10 comments
Closed

Allow adding a linker script in build.rs #7984

xobs opened this issue Mar 11, 2020 · 10 comments
Labels
A-build-scripts Area: build.rs scripts A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

Comments

@xobs
Copy link

xobs commented Mar 11, 2020

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?
@xobs xobs added the C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` label Mar 11, 2020
@jonas-schievink
Copy link
Contributor

The easiest way to support this would be to allow passing arbitrary rustc flags via cargo:rustc-flags=FLAGS. Right now that's limited to -L and -l, while .cargo/config can pass anything.

The flag can be translated as appropriate depending on the linker

This is not really something we need since linker scripts are a GNU LD invention anyways, so linkers supporting them mimic GNU LD's command line options as well.

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.

Note that we do this by having link.x include device.x and memory.x (where the device.x include is injected by the existing build.rs there), so we don't strictly need the ability to pass multiple linker scripts.

@ehuss ehuss added A-build-scripts Area: build.rs scripts A-linkage Area: linker issues, dylib, cdylib, shared libraries, so labels Mar 24, 2020
@stdrc
Copy link

stdrc commented Jan 31, 2021

@xobs This is solved by #8441.

Just pass -Zextra-link-arg flag to cargo and print cargo:rustc-link-arg=-Tpath/to/linker.ld in build.rs.

@xobs
Copy link
Author

xobs commented Feb 1, 2021

I've created a repository to demonstrate that this does make things work: https://github.com/xobs/rust-extra-link-arg-test

What is the process now? Should this issue be closed, or should it stay until it's stabilized?

@AaronKutch
Copy link

These are overridden if the RUSTFLAGS variable is set

I could not figure out for the life of me why I couldn't get the GitHub Actions CI to build a project that I could replicate everywhere else, until today I happened upon this thread with this detail. I had env: RUSTFLAGS: -D warnings at the top of the workflow file, and refactoring so that the flag did not appear in the particular build fixed it.

@anderslanglands
Copy link

We need this functionality in order to add a link statement to the end of the linker invocation for building a crate that links against libstdc++ on CentOS 7 using devtoolset.

Does anyone know when this might be stabilised?

@xobs
Copy link
Author

xobs commented Jun 22, 2021

This now has an issue tracking stabilization: #9426

@hydra
Copy link

hydra commented Sep 15, 2021

I've created a repository to demonstrate that this does make things work: https://github.com/xobs/rust-extra-link-arg-test

I tried this today, and it didn't work using a very recent cargo build.

xobs/rust-extra-link-arg-test#1

@xobs
Copy link
Author

xobs commented Sep 29, 2021

@MrMino
Copy link

MrMino commented Jan 2, 2022

I guess this can be closed now?

@ehuss
Copy link
Contributor

ehuss commented Jan 3, 2022

Yea, seems like this is addressed via rustc-link-arg along with -C link-arg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-scripts Area: build.rs scripts A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`
Projects
None yet
Development

No branches or pull requests

8 participants