Skip to content

Commit 4d10be2

Browse files
Merge #67
67: Add notes about creating a custom target r=therealprof a=lights0123 As we were discussing rust-lang/rust#58500, I realized that there is nowhere other than community blogs that actually discusses *how* to create a new target. This adds new documentation about creating custom targets and common pitfalls that you may encounter. Co-authored-by: lights0123 <[email protected]> Co-authored-by: Ben Schattinger <[email protected]>
2 parents bc5cff2 + c0cbfb7 commit 4d10be2

File tree

7 files changed

+395
-130
lines changed

7 files changed

+395
-130
lines changed

ci/asm/app/release.objdump

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ main:
1111
trap
1212

1313
Reset:
14-
bl #-0x6
14+
push {r7, lr}
15+
mov r7, sp
16+
bl #-0xa
1517
trap
1618

1719
DefaultExceptionHandler:
@@ -22,4 +24,4 @@ UsageFault:
2224

2325
HardFaultTrampoline:
2426
mrs r0, msp
25-
b #-0x14 <HardFault>
27+
b #-0x18 <HardFault>

ci/asm/app/release.vector_table

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
app: file format ELF32-arm-little
33

44
Contents of section .vector_table:
5-
0000 00000120 45000000 4b000000 4d000000 ... E...K...M...
6-
0010 4b000000 4b000000 4b000000 00000000 K...K...K.......
7-
0020 00000000 00000000 00000000 4b000000 ............K...
8-
0030 00000000 00000000 4b000000 4b000000 ........K...K...
5+
0000 00000120 45000000 4f000000 51000000 ... E...O...Q...
6+
0010 4f000000 4f000000 4f000000 00000000 O...O...O.......
7+
0020 00000000 00000000 00000000 4f000000 ............O...
8+
0030 00000000 00000000 4f000000 4f000000 ........O...O...

ci/main/app/app.objdump

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ main:
1212
b #-4 <main+0x8>
1313

1414
Reset:
15-
bl #-14
15+
push {r7, lr}
16+
mov r7, sp
17+
bl #-18
1618
trap

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
- [DMA](./dma.md)
1212
---
1313
[A note on compiler support](./compiler-support.md)
14+
[Creating a custom target](./custom-target.md)

src/compiler-support.md

+133-119
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# A note on compiler support
22

33
This book makes use of a built-in *compiler* target, the `thumbv7m-none-eabi`, for which the Rust
4-
team distributes a `rust-std` component, which is a pre-compiled collection of crates like [`core`] and [`std`].
4+
team distributes a `rust-std` component, which is a pre-compiled collection of crates like [`core`]
5+
and [`std`].
56

67
[`core`]: https://doc.rust-lang.org/core/index.html
78
[`std`]: https://doc.rust-lang.org/std/index.html
89

9-
If you want to attempt replicating the contents of this book for a different target architecture, you
10-
need to take into account the different levels of support that Rust provides for (compilation)
10+
If you want to attempt replicating the contents of this book for a different target architecture,
11+
you need to take into account the different levels of support that Rust provides for (compilation)
1112
targets.
1213

1314
## LLVM support
@@ -64,7 +65,8 @@ changes.
6465

6566
On the other hand, if LLVM doesn't support the architecture, but a fork of LLVM does, you will have
6667
to replace the original version of LLVM with the fork before building `rustc`. The Rust build system
67-
allows this and in principle it should just require changing the `llvm` submodule to point to the fork.
68+
allows this and in principle it should just require changing the `llvm` submodule to point to the
69+
fork.
6870

6971
If your target architecture is only supported by some vendor provided GCC, you have the option of
7072
using [`mrustc`], an unofficial Rust compiler, to translate your Rust program into C code and then
@@ -75,61 +77,90 @@ compile that using GCC.
7577
## Built-in target
7678

7779
A compilation target is more than just its architecture. Each target has a [specification]
78-
associated to it that describes, among other things, its architecture, its operating system
79-
and the default linker.
80+
associated to it that describes, among other things, its architecture, its operating system and the
81+
default linker.
8082

8183
[specification]: https://github.com/rust-lang/rfcs/blob/master/text/0131-target-specification.md
8284

83-
The Rust compiler knows about several targets. These are said to be *built into* the compiler and
84-
can be listed by running the following command:
85+
The Rust compiler knows about several targets. These are *built into* the compiler and can be listed
86+
by running the following command:
8587

8688
``` console
8789
$ rustc --print target-list | column
88-
aarch64-fuchsia mips64el-unknown-linux-gnuabi64
89-
aarch64-linux-android mipsel-unknown-linux-gnu
90-
aarch64-unknown-cloudabi mipsel-unknown-linux-musl
91-
aarch64-unknown-freebsd mipsel-unknown-linux-uclibc
92-
aarch64-unknown-linux-gnu msp430-none-elf
93-
aarch64-unknown-linux-musl powerpc-unknown-linux-gnu
94-
aarch64-unknown-openbsd powerpc-unknown-linux-gnuspe
95-
arm-linux-androideabi powerpc-unknown-netbsd
96-
arm-unknown-linux-gnueabi powerpc64-unknown-linux-gnu
97-
arm-unknown-linux-gnueabihf powerpc64le-unknown-linux-gnu
98-
arm-unknown-linux-musleabi powerpc64le-unknown-linux-musl
99-
arm-unknown-linux-musleabihf s390x-unknown-linux-gnu
100-
armebv7r-none-eabihf sparc-unknown-linux-gnu
101-
armv4t-unknown-linux-gnueabi sparc64-unknown-linux-gnu
102-
armv5te-unknown-linux-gnueabi sparc64-unknown-netbsd
103-
armv5te-unknown-linux-musleabi sparcv9-sun-solaris
104-
armv6-unknown-netbsd-eabihf thumbv6m-none-eabi
105-
armv7-linux-androideabi thumbv7em-none-eabi
106-
armv7-unknown-cloudabi-eabihf thumbv7em-none-eabihf
107-
armv7-unknown-linux-gnueabihf thumbv7m-none-eabi
108-
armv7-unknown-linux-musleabihf wasm32-experimental-emscripten
109-
armv7-unknown-netbsd-eabihf wasm32-unknown-emscripten
110-
asmjs-unknown-emscripten wasm32-unknown-unknown
111-
i586-pc-windows-msvc x86_64-apple-darwin
112-
i586-unknown-linux-gnu x86_64-fuchsia
113-
i586-unknown-linux-musl x86_64-linux-android
114-
i686-apple-darwin x86_64-pc-windows-gnu
115-
i686-linux-android x86_64-pc-windows-msvc
116-
i686-pc-windows-gnu x86_64-rumprun-netbsd
117-
i686-pc-windows-msvc x86_64-sun-solaris
118-
i686-unknown-cloudabi x86_64-unknown-bitrig
119-
i686-unknown-dragonfly x86_64-unknown-cloudabi
120-
i686-unknown-freebsd x86_64-unknown-dragonfly
121-
i686-unknown-haiku x86_64-unknown-freebsd
122-
i686-unknown-linux-gnu x86_64-unknown-haiku
123-
i686-unknown-linux-musl x86_64-unknown-l4re-uclibc
124-
i686-unknown-netbsd x86_64-unknown-linux-gnu
125-
i686-unknown-openbsd x86_64-unknown-linux-gnux32
126-
mips-unknown-linux-gnu x86_64-unknown-linux-musl
127-
mips-unknown-linux-musl x86_64-unknown-netbsd
128-
mips-unknown-linux-uclibc x86_64-unknown-openbsd
129-
mips64-unknown-linux-gnuabi64 x86_64-unknown-redox
90+
aarch64-fuchsia mipsisa32r6el-unknown-linux-gnu
91+
aarch64-linux-android mipsisa64r6-unknown-linux-gnuabi64
92+
aarch64-pc-windows-msvc mipsisa64r6el-unknown-linux-gnuabi64
93+
aarch64-unknown-cloudabi msp430-none-elf
94+
aarch64-unknown-freebsd nvptx64-nvidia-cuda
95+
aarch64-unknown-hermit powerpc-unknown-linux-gnu
96+
aarch64-unknown-linux-gnu powerpc-unknown-linux-gnuspe
97+
aarch64-unknown-linux-musl powerpc-unknown-linux-musl
98+
aarch64-unknown-netbsd powerpc-unknown-netbsd
99+
aarch64-unknown-none powerpc-wrs-vxworks
100+
aarch64-unknown-none-softfloat powerpc-wrs-vxworks-spe
101+
aarch64-unknown-openbsd powerpc64-unknown-freebsd
102+
aarch64-unknown-redox powerpc64-unknown-linux-gnu
103+
aarch64-uwp-windows-msvc powerpc64-unknown-linux-musl
104+
aarch64-wrs-vxworks powerpc64-wrs-vxworks
105+
arm-linux-androideabi powerpc64le-unknown-linux-gnu
106+
arm-unknown-linux-gnueabi powerpc64le-unknown-linux-musl
107+
arm-unknown-linux-gnueabihf riscv32i-unknown-none-elf
108+
arm-unknown-linux-musleabi riscv32imac-unknown-none-elf
109+
arm-unknown-linux-musleabihf riscv32imc-unknown-none-elf
110+
armebv7r-none-eabi riscv64gc-unknown-linux-gnu
111+
armebv7r-none-eabihf riscv64gc-unknown-none-elf
112+
armv4t-unknown-linux-gnueabi riscv64imac-unknown-none-elf
113+
armv5te-unknown-linux-gnueabi s390x-unknown-linux-gnu
114+
armv5te-unknown-linux-musleabi sparc-unknown-linux-gnu
115+
armv6-unknown-freebsd sparc64-unknown-linux-gnu
116+
armv6-unknown-netbsd-eabihf sparc64-unknown-netbsd
117+
armv7-linux-androideabi sparc64-unknown-openbsd
118+
armv7-unknown-cloudabi-eabihf sparcv9-sun-solaris
119+
armv7-unknown-freebsd thumbv6m-none-eabi
120+
armv7-unknown-linux-gnueabi thumbv7a-pc-windows-msvc
121+
armv7-unknown-linux-gnueabihf thumbv7em-none-eabi
122+
armv7-unknown-linux-musleabi thumbv7em-none-eabihf
123+
armv7-unknown-linux-musleabihf thumbv7m-none-eabi
124+
armv7-unknown-netbsd-eabihf thumbv7neon-linux-androideabi
125+
armv7-wrs-vxworks-eabihf thumbv7neon-unknown-linux-gnueabihf
126+
armv7a-none-eabi thumbv7neon-unknown-linux-musleabihf
127+
armv7a-none-eabihf thumbv8m.base-none-eabi
128+
armv7r-none-eabi thumbv8m.main-none-eabi
129+
armv7r-none-eabihf thumbv8m.main-none-eabihf
130+
asmjs-unknown-emscripten wasm32-unknown-emscripten
131+
hexagon-unknown-linux-musl wasm32-unknown-unknown
132+
i586-pc-windows-msvc wasm32-wasi
133+
i586-unknown-linux-gnu x86_64-apple-darwin
134+
i586-unknown-linux-musl x86_64-fortanix-unknown-sgx
135+
i686-apple-darwin x86_64-fuchsia
136+
i686-linux-android x86_64-linux-android
137+
i686-pc-windows-gnu x86_64-linux-kernel
138+
i686-pc-windows-msvc x86_64-pc-solaris
139+
i686-unknown-cloudabi x86_64-pc-windows-gnu
140+
i686-unknown-freebsd x86_64-pc-windows-msvc
141+
i686-unknown-haiku x86_64-rumprun-netbsd
142+
i686-unknown-linux-gnu x86_64-sun-solaris
143+
i686-unknown-linux-musl x86_64-unknown-cloudabi
144+
i686-unknown-netbsd x86_64-unknown-dragonfly
145+
i686-unknown-openbsd x86_64-unknown-freebsd
146+
i686-unknown-uefi x86_64-unknown-haiku
147+
i686-uwp-windows-gnu x86_64-unknown-hermit
148+
i686-uwp-windows-msvc x86_64-unknown-hermit-kernel
149+
i686-wrs-vxworks x86_64-unknown-illumos
150+
mips-unknown-linux-gnu x86_64-unknown-l4re-uclibc
151+
mips-unknown-linux-musl x86_64-unknown-linux-gnu
152+
mips-unknown-linux-uclibc x86_64-unknown-linux-gnux32
153+
mips64-unknown-linux-gnuabi64 x86_64-unknown-linux-musl
154+
mips64-unknown-linux-muslabi64 x86_64-unknown-netbsd
155+
mips64el-unknown-linux-gnuabi64 x86_64-unknown-openbsd
156+
mips64el-unknown-linux-muslabi64 x86_64-unknown-redox
157+
mipsel-unknown-linux-gnu x86_64-unknown-uefi
158+
mipsel-unknown-linux-musl x86_64-uwp-windows-gnu
159+
mipsel-unknown-linux-uclibc x86_64-uwp-windows-msvc
160+
mipsisa32r6-unknown-linux-gnu x86_64-wrs-vxworks
130161
```
131162

132-
You can print the specification of any of these targets using the following command:
163+
You can print the specification of one of these targets using the following command:
133164

134165
``` console
135166
$ rustc +nightly -Z unstable-options --print target-spec-json --target thumbv7m-none-eabi
@@ -163,86 +194,69 @@ $ rustc +nightly -Z unstable-options --print target-spec-json --target thumbv7m-
163194
```
164195

165196
If none of these built-in targets seems appropriate for your target system, you'll have to create a
166-
custom target by writing your own target specification file in JSON format. The recommended way is to
167-
dump the specification of a built-in target that's similar to your target system into a file and then
168-
tweak it to match the properties of your target system. To do so, use the previously shown command,
169-
`rustc --print target-spec-json`. As of Rust 1.28, there's no up to date documentation on what each of
170-
the fields of a target specification mean, other than [the compiler source code].
197+
custom target by writing your own target specification file in JSON format which is described in the
198+
[next section][custom-target].
171199

172-
[the compiler source code]: https://github.com/rust-lang/rust/blob/1.27.2/src/librustc_target/spec/mod.rs#L376-L400
173-
174-
Once you have a target specification file you can refer to it by its path or by its name if its in
175-
the current directory or in `$RUST_TARGET_PATH`.
176-
177-
``` console
178-
$ rustc +nightly -Z unstable-options --print target-spec-json \
179-
--target thumbv7m-none-eabi \
180-
> foo.json
181-
182-
$ rustc --print cfg --target foo.json # or just --target foo
183-
debug_assertions
184-
target_arch="arm"
185-
target_endian="little"
186-
target_env=""
187-
target_feature="mclass"
188-
target_feature="v7"
189-
target_has_atomic="16"
190-
target_has_atomic="32"
191-
target_has_atomic="8"
192-
target_has_atomic="cas"
193-
target_has_atomic="ptr"
194-
target_os="none"
195-
target_pointer_width="32"
196-
target_vendor=""
197-
```
200+
[custom-target]: ./custom-target.md
198201

199202
## `rust-std` component
200203

201204
For some of the built-in target the Rust team distributes `rust-std` components via `rustup`. This
202-
component is a collection of pre-compiled crates like `core` and `std`, and it's required for
203-
cross compilation.
205+
component is a collection of pre-compiled crates like `core` and `std`, and it's required for cross
206+
compilation.
204207

205208
You can find the list of targets that have a `rust-std` component available via `rustup` by running
206209
the following command:
207210

208211
``` console
209212
$ rustup target list | column
210-
aarch64-apple-ios mips64-unknown-linux-gnuabi64
211-
aarch64-linux-android mips64el-unknown-linux-gnuabi64
212-
aarch64-unknown-fuchsia mipsel-unknown-linux-gnu
213-
aarch64-unknown-linux-gnu mipsel-unknown-linux-musl
214-
aarch64-unknown-linux-musl powerpc-unknown-linux-gnu
215-
arm-linux-androideabi powerpc64-unknown-linux-gnu
216-
arm-unknown-linux-gnueabi powerpc64le-unknown-linux-gnu
217-
arm-unknown-linux-gnueabihf s390x-unknown-linux-gnu
218-
arm-unknown-linux-musleabi sparc64-unknown-linux-gnu
219-
arm-unknown-linux-musleabihf sparcv9-sun-solaris
220-
armv5te-unknown-linux-gnueabi thumbv6m-none-eabi
221-
armv5te-unknown-linux-musleabi thumbv7em-none-eabi
222-
armv7-apple-ios thumbv7em-none-eabihf
213+
aarch64-apple-ios mipsel-unknown-linux-musl
214+
aarch64-fuchsia nvptx64-nvidia-cuda
215+
aarch64-linux-android powerpc-unknown-linux-gnu
216+
aarch64-pc-windows-msvc powerpc64-unknown-linux-gnu
217+
aarch64-unknown-linux-gnu powerpc64le-unknown-linux-gnu
218+
aarch64-unknown-linux-musl riscv32i-unknown-none-elf
219+
aarch64-unknown-none riscv32imac-unknown-none-elf
220+
aarch64-unknown-none-softfloat riscv32imc-unknown-none-elf
221+
arm-linux-androideabi riscv64gc-unknown-linux-gnu
222+
arm-unknown-linux-gnueabi riscv64gc-unknown-none-elf
223+
arm-unknown-linux-gnueabihf riscv64imac-unknown-none-elf
224+
arm-unknown-linux-musleabi s390x-unknown-linux-gnu
225+
arm-unknown-linux-musleabihf sparc64-unknown-linux-gnu
226+
armebv7r-none-eabi sparcv9-sun-solaris
227+
armebv7r-none-eabihf thumbv6m-none-eabi
228+
armv5te-unknown-linux-gnueabi thumbv7em-none-eabi
229+
armv5te-unknown-linux-musleabi thumbv7em-none-eabihf
223230
armv7-linux-androideabi thumbv7m-none-eabi
224-
armv7-unknown-linux-gnueabihf wasm32-unknown-emscripten
225-
armv7-unknown-linux-musleabihf wasm32-unknown-unknown
226-
armv7s-apple-ios x86_64-apple-darwin
227-
asmjs-unknown-emscripten x86_64-apple-ios
228-
i386-apple-ios x86_64-linux-android
229-
i586-pc-windows-msvc x86_64-pc-windows-gnu
230-
i586-unknown-linux-gnu x86_64-pc-windows-msvc
231-
i586-unknown-linux-musl x86_64-rumprun-netbsd
232-
i686-apple-darwin x86_64-sun-solaris
233-
i686-linux-android x86_64-unknown-cloudabi
234-
i686-pc-windows-gnu x86_64-unknown-freebsd
235-
i686-pc-windows-msvc x86_64-unknown-fuchsia
236-
i686-unknown-freebsd x86_64-unknown-linux-gnu (default)
237-
i686-unknown-linux-gnu x86_64-unknown-linux-gnux32
238-
i686-unknown-linux-musl x86_64-unknown-linux-musl
239-
mips-unknown-linux-gnu x86_64-unknown-netbsd
240-
mips-unknown-linux-musl x86_64-unknown-redox
231+
armv7-unknown-linux-gnueabi thumbv7neon-linux-androideabi
232+
armv7-unknown-linux-gnueabihf thumbv7neon-unknown-linux-gnueabihf
233+
armv7-unknown-linux-musleabi thumbv8m.base-none-eabi
234+
armv7-unknown-linux-musleabihf thumbv8m.main-none-eabi
235+
armv7a-none-eabi thumbv8m.main-none-eabihf
236+
armv7r-none-eabi wasm32-unknown-emscripten
237+
armv7r-none-eabihf wasm32-unknown-unknown
238+
asmjs-unknown-emscripten wasm32-wasi
239+
i586-pc-windows-msvc x86_64-apple-darwin
240+
i586-unknown-linux-gnu x86_64-apple-ios
241+
i586-unknown-linux-musl x86_64-fortanix-unknown-sgx
242+
i686-linux-android x86_64-fuchsia
243+
i686-pc-windows-gnu x86_64-linux-android
244+
i686-pc-windows-msvc x86_64-pc-windows-gnu
245+
i686-unknown-freebsd x86_64-pc-windows-msvc
246+
i686-unknown-linux-gnu x86_64-rumprun-netbsd
247+
i686-unknown-linux-musl x86_64-sun-solaris
248+
mips-unknown-linux-gnu x86_64-unknown-cloudabi
249+
mips-unknown-linux-musl x86_64-unknown-freebsd
250+
mips64-unknown-linux-gnuabi64 x86_64-unknown-linux-gnu (default)
251+
mips64-unknown-linux-muslabi64 x86_64-unknown-linux-gnux32
252+
mips64el-unknown-linux-gnuabi64 x86_64-unknown-linux-musl
253+
mips64el-unknown-linux-muslabi64 x86_64-unknown-netbsd
254+
mipsel-unknown-linux-gnu x86_64-unknown-redox
241255
```
242256

243-
If there's no `rust-std` component for your target or you are using a custom target, then you'll have
244-
to use a tool like [Xargo] to have Cargo compile the `core` crate on the fly. Note that Xargo
245-
requires a nightly toolchain; the long term plan is to upstream Xargo's functionality into Cargo
246-
and eventually have that functionality available on stable.
257+
If there's no `rust-std` component for your target, or you are using a custom target, then you'll
258+
have to use a nightly toolchain to build the standard library. See the next page about [building for
259+
custom targets][use-target-file].
247260

248-
[Xargo]: https://github.com/japaric/xargo
261+
[use-target-file]: ./custom-target.md#use-the-target-file
262+
[xargo]: https://github.com/japaric/xargo

0 commit comments

Comments
 (0)