Skip to content

Latest commit

 

History

History
84 lines (61 loc) · 3.64 KB

0000-linker-customization-convention.md

File metadata and controls

84 lines (61 loc) · 3.64 KB
  • Feature Name: linker_customization_convention
  • Start Date: 2017-05-13
  • RFC PR: (leave this empty)

Summary

Set a convention for passing custom arguments to the linker when using Cargo for embedded development. This RFC proposes adopting a project local configuration file, .cargo/config, to pass the arguments.

Motivation

Embedded development requires precise control over the memory layout of the final binary artifact; this is usually achieved through a mixture of extra linker arguments, object files and linker scripts. There is currently no convention about how to pass extra arguments to the linker using Cargo / rustc but there are currently two approaches used in practice:

  • Write a custom target specification file, usually basing it on a built-in target, and then adding to it the linker arguments in the {pre,,}-link-args fields.

  • Use a project local configuration file, .cargo/config, to pass linker arguments through the target.$T.rustflags variable.

A third alternative would be to add features to Cargo to let it control the linking process through build scripts. This seems unlikely to be implemented in the short term (or ever) as the downsides may outweigh the benefits.

The goal is to RFC is to compare the advantages and disadvantages of each approach and to settle on one of them as a convention.

Rationale

Or, why .cargo/config should be preferred over custom targets for this purpose:

Linker arguments, linker scripts and object files are usually device, board or application specific. IMO, this maps nicely to .cargo/config as it's a project local, and thus an application specific, configuration. OTOH, targets are more global and are meant to be used across projects. Using targets to control the linker at worst implies having one custom target per project.

Using different targets implies having different sysroots, one per target. This is wasteful because custom targets are usually based on built-in targets and just add linker arguments thus the generated sysroots will be exactly the same because linker arguments don't affect code generation.

Using custom targets also makes Xargo a requirement as the a sysroot will have to be compiled on the fly for each target. OTOH, if project local configuration files are used with built-in targets then it'd be possible to not depend on Xargo if the rust-std component is available for the built-in target.

Let me rephrase that last part:

If we settle on .cargo/config as the way to pass arguments to the linker then most projects will switch back to built-in targets. If there's a rust-std component available for those built-in targets then Xargo isn't required to build the application and regular Cargo can be used.

Blockers

For adopting this convention:

As .cargo/config passes arguments to the linker using the rustc interface, currently it's only possible to append arguments to the linker invocation (using -C link-arg{,s}). However, some applications require control over the order of linker arguments; specifically, some arguments (object files) need to be passed to the linker before the Rust object files. rustc doesn't support this scenario ATM but a PR has been sent to allow it via the -Z pre-link-arg{,s} arguments.

Unresolved questions

  • Does .cargo/config cover all the existing use cases?
    • Here's a project with a complex requirement of linker arguments and it's fully supported by the .cargo/config approach.