Skip to content

Commit 4214eb0

Browse files
bors[bot]japaric
andcommitted
Merge #196
196: PSA notice for upcoming Cortex-M breakage r=japaric a=japaric This is the PSA we'll put up when the default linker of the Cortex-M targets changes. I'm putting it up for early review. It's OK to merge it before the breaking change occurs. r? @rust-embedded/resources Co-authored-by: Jorge Aparicio <[email protected]>
2 parents 621e09c + a93d994 commit 4214eb0

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
> PSA: building binaries and cdylibs for the ARM Cortex-M architecture will break with today's nightly
2+
3+
The default linker for the 4 ARM Cortex-M targets listed below has changed from
4+
`arm-none-eabi-gcc` to `rust-lld` in the latest nightly.
5+
6+
- `thumbv6m-none-eabi`
7+
- `thumbv7m-none-eabi`
8+
- `thumbv7em-none-eabi`
9+
- `thumbv7em-none-eabihf`
10+
11+
This will break the builds of *binaries* and *cdylibs* that were using the
12+
old default linker (`arm-none-eabi-gcc`) *and* additionally pass extra flags to
13+
the linker using any of these rustc flags: `-C link-arg`, `-C link-args`, `-Z
14+
pre-link-arg` or `-Z pre-link-args`. Building libraries (`rlib`s and
15+
`staticlib`s) is not affected by this change.
16+
17+
This change won't affect stable users when it reaches the 1.30 release because,
18+
as of 1.28, it's not possible to build binaries or cdylibs for those targets on
19+
the stable channel. Building libraries for those targets is possible on stable
20+
but it's not affected by this change.
21+
22+
### Rationale
23+
24+
This breaking change was intentional.
25+
26+
We, the [embedded WG], wanted to reduce the number of external tools required to
27+
build embedded programs for the ARM Cortex-M architecture. By switching the
28+
default linker to the LLD linker that's shipped with the Rust toolchain the user
29+
no longer needs to install an ARM linker (like `arm-none-eabi-gcc` or
30+
`arm-none-eabi-ld`) to build Rust programs.
31+
32+
[embedded WG]: https://github.com/rust-embedded/wg
33+
34+
Before landing this change we first [consulted] with the community if they
35+
thought this breaking change was worth it. We received over 20 positive responses
36+
representing the Cortex-M team (part of the embedded WG), the Tock OS project,
37+
the embed-rs organization and independent developers.
38+
39+
The consensus was that it was worth to make the default configuration more self
40+
contained and that if we were to make the change it had to be made before it
41+
became possible to build binaries on stable otherwise it wouldn't be possible
42+
to make this change without breaking stable builds.
43+
44+
[consulted]: https://github.com/rust-embedded/wg/issues/160
45+
46+
### How to fix your build
47+
48+
If you are affected by this change you'll observe a linker error with a message
49+
similar to one shown below:
50+
51+
``` console
52+
$ # these are the custom linker flags of the project
53+
$ cat .cargo/config
54+
```
55+
56+
``` toml
57+
[target.thumbv7m-none-eabi]
58+
runner = 'arm-none-eabi-gdb'
59+
rustflags = [
60+
"-C", "link-arg=-Wl,-Tlink.x",
61+
"-C", "link-arg=-nostartfiles",
62+
]
63+
64+
[build]
65+
target = "thumbv7m-none-eabi"
66+
```
67+
68+
```
69+
$ cargo build
70+
error: linking with `rust-lld` failed: exit code: 1
71+
|
72+
= note: "rust-lld" "-flavor" "gnu" (..)
73+
= note: rust-lld: error: unknown argument: -Wl,-Tlink.x
74+
rust-lld: error: unknown argument: -nostartfiles
75+
```
76+
77+
There are two ways to fix the problem.
78+
79+
#### Option A: switch back to GCC
80+
81+
The easiest way is to switch back to using `arm-none-eabi-gcc` as the linker. To
82+
do so pass the flag `-C linker=arm-none-eabi-gcc` to rustc. In the above example
83+
you can do that in the `.cargo/config` file.
84+
85+
``` console
86+
$ # these are the custom linker flags of the project
87+
$ cat .cargo/config
88+
```
89+
90+
``` toml
91+
[target.thumbv7m-none-eabi]
92+
runner = 'arm-none-eabi-gdb'
93+
rustflags = [
94+
"-C", "linker=arm-none-eabi-gcc", # ADDED
95+
"-C", "link-arg=-Wl,-Tlink.x",
96+
"-C", "link-arg=-nostartfiles",
97+
]
98+
99+
[build]
100+
target = "thumbv7m-none-eabi"
101+
```
102+
103+
```
104+
$ cargo build && echo It works now
105+
It works now
106+
```
107+
108+
#### Option B: tweak the additional linker arguments
109+
110+
The other option is to tweak the additional linker arguments so they'll be
111+
accepted by LLD. In the above example the `-nostartfiles` flag can be dropped
112+
because that's the default behavior of LLD, and the flags prefixed by `-Wl,`
113+
will have to lose their prefix.
114+
115+
``` console
116+
$ # these are the custom linker flags of the project
117+
$ cat .cargo/config
118+
```
119+
120+
``` toml
121+
[target.thumbv7m-none-eabi]
122+
runner = 'arm-none-eabi-gdb'
123+
rustflags = [
124+
"-C", "link-arg=-Tlink.x", # CHANGED
125+
# "-C", "link-arg=-nostartfiles", # REMOVED
126+
]
127+
128+
[build]
129+
target = "thumbv7m-none-eabi"
130+
```
131+
132+
``` console
133+
$ cargo build && echo It works now
134+
It works now
135+
```
136+
137+
With this approach your build will no longer depend on an external linker.
138+
139+
#### Should I prefer option A or B?
140+
141+
If you are linking to a system installed C library like `newlib-arm-none-eabi`
142+
then you should continue to use GCC. The default library search path of
143+
`arm-none-eabi-gcc` includes the path to those libraries.
144+
145+
If you are not linking to any C code then you should prefer LLD then you won't
146+
need to install the `arm-none-eabi` toolchain.

0 commit comments

Comments
 (0)