Skip to content

Add notes about creating a custom target #67

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

Merged
merged 11 commits into from
Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ci/asm/app/release.objdump
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ main:
trap

Reset:
bl #-0x6
push {r7, lr}
mov r7, sp
bl #-0xa
trap

DefaultExceptionHandler:
Expand All @@ -22,4 +24,4 @@ UsageFault:

HardFaultTrampoline:
mrs r0, msp
b #-0x14 <HardFault>
b #-0x18 <HardFault>
8 changes: 4 additions & 4 deletions ci/asm/app/release.vector_table
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
app: file format ELF32-arm-little

Contents of section .vector_table:
0000 00000120 45000000 4b000000 4d000000 ... E...K...M...
0010 4b000000 4b000000 4b000000 00000000 K...K...K.......
0020 00000000 00000000 00000000 4b000000 ............K...
0030 00000000 00000000 4b000000 4b000000 ........K...K...
0000 00000120 45000000 4f000000 51000000 ... E...O...Q...
0010 4f000000 4f000000 4f000000 00000000 O...O...O.......
0020 00000000 00000000 00000000 4f000000 ............O...
0030 00000000 00000000 4f000000 4f000000 ........O...O...
4 changes: 3 additions & 1 deletion ci/main/app/app.objdump
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ main:
b #-4 <main+0x8>

Reset:
bl #-14
push {r7, lr}
mov r7, sp
bl #-18
trap
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
- [DMA](./dma.md)
---
[A note on compiler support](./compiler-support.md)
[Creating a custom target](./custom-target.md)
252 changes: 133 additions & 119 deletions src/compiler-support.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# A note on compiler support

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

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

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

## LLVM support
Expand Down Expand Up @@ -64,7 +65,8 @@ changes.

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

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

A compilation target is more than just its architecture. Each target has a [specification]
associated to it that describes, among other things, its architecture, its operating system
and the default linker.
associated to it that describes, among other things, its architecture, its operating system and the
default linker.

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

The Rust compiler knows about several targets. These are said to be *built into* the compiler and
can be listed by running the following command:
The Rust compiler knows about several targets. These are *built into* the compiler and can be listed
by running the following command:

``` console
$ rustc --print target-list | column
aarch64-fuchsia mips64el-unknown-linux-gnuabi64
aarch64-linux-android mipsel-unknown-linux-gnu
aarch64-unknown-cloudabi mipsel-unknown-linux-musl
aarch64-unknown-freebsd mipsel-unknown-linux-uclibc
aarch64-unknown-linux-gnu msp430-none-elf
aarch64-unknown-linux-musl powerpc-unknown-linux-gnu
aarch64-unknown-openbsd powerpc-unknown-linux-gnuspe
arm-linux-androideabi powerpc-unknown-netbsd
arm-unknown-linux-gnueabi powerpc64-unknown-linux-gnu
arm-unknown-linux-gnueabihf powerpc64le-unknown-linux-gnu
arm-unknown-linux-musleabi powerpc64le-unknown-linux-musl
arm-unknown-linux-musleabihf s390x-unknown-linux-gnu
armebv7r-none-eabihf sparc-unknown-linux-gnu
armv4t-unknown-linux-gnueabi sparc64-unknown-linux-gnu
armv5te-unknown-linux-gnueabi sparc64-unknown-netbsd
armv5te-unknown-linux-musleabi sparcv9-sun-solaris
armv6-unknown-netbsd-eabihf thumbv6m-none-eabi
armv7-linux-androideabi thumbv7em-none-eabi
armv7-unknown-cloudabi-eabihf thumbv7em-none-eabihf
armv7-unknown-linux-gnueabihf thumbv7m-none-eabi
armv7-unknown-linux-musleabihf wasm32-experimental-emscripten
armv7-unknown-netbsd-eabihf wasm32-unknown-emscripten
asmjs-unknown-emscripten wasm32-unknown-unknown
i586-pc-windows-msvc x86_64-apple-darwin
i586-unknown-linux-gnu x86_64-fuchsia
i586-unknown-linux-musl x86_64-linux-android
i686-apple-darwin x86_64-pc-windows-gnu
i686-linux-android x86_64-pc-windows-msvc
i686-pc-windows-gnu x86_64-rumprun-netbsd
i686-pc-windows-msvc x86_64-sun-solaris
i686-unknown-cloudabi x86_64-unknown-bitrig
i686-unknown-dragonfly x86_64-unknown-cloudabi
i686-unknown-freebsd x86_64-unknown-dragonfly
i686-unknown-haiku x86_64-unknown-freebsd
i686-unknown-linux-gnu x86_64-unknown-haiku
i686-unknown-linux-musl x86_64-unknown-l4re-uclibc
i686-unknown-netbsd x86_64-unknown-linux-gnu
i686-unknown-openbsd x86_64-unknown-linux-gnux32
mips-unknown-linux-gnu x86_64-unknown-linux-musl
mips-unknown-linux-musl x86_64-unknown-netbsd
mips-unknown-linux-uclibc x86_64-unknown-openbsd
mips64-unknown-linux-gnuabi64 x86_64-unknown-redox
aarch64-fuchsia mipsisa32r6el-unknown-linux-gnu
aarch64-linux-android mipsisa64r6-unknown-linux-gnuabi64
aarch64-pc-windows-msvc mipsisa64r6el-unknown-linux-gnuabi64
aarch64-unknown-cloudabi msp430-none-elf
aarch64-unknown-freebsd nvptx64-nvidia-cuda
aarch64-unknown-hermit powerpc-unknown-linux-gnu
aarch64-unknown-linux-gnu powerpc-unknown-linux-gnuspe
aarch64-unknown-linux-musl powerpc-unknown-linux-musl
aarch64-unknown-netbsd powerpc-unknown-netbsd
aarch64-unknown-none powerpc-wrs-vxworks
aarch64-unknown-none-softfloat powerpc-wrs-vxworks-spe
aarch64-unknown-openbsd powerpc64-unknown-freebsd
aarch64-unknown-redox powerpc64-unknown-linux-gnu
aarch64-uwp-windows-msvc powerpc64-unknown-linux-musl
aarch64-wrs-vxworks powerpc64-wrs-vxworks
arm-linux-androideabi powerpc64le-unknown-linux-gnu
arm-unknown-linux-gnueabi powerpc64le-unknown-linux-musl
arm-unknown-linux-gnueabihf riscv32i-unknown-none-elf
arm-unknown-linux-musleabi riscv32imac-unknown-none-elf
arm-unknown-linux-musleabihf riscv32imc-unknown-none-elf
armebv7r-none-eabi riscv64gc-unknown-linux-gnu
armebv7r-none-eabihf riscv64gc-unknown-none-elf
armv4t-unknown-linux-gnueabi riscv64imac-unknown-none-elf
armv5te-unknown-linux-gnueabi s390x-unknown-linux-gnu
armv5te-unknown-linux-musleabi sparc-unknown-linux-gnu
armv6-unknown-freebsd sparc64-unknown-linux-gnu
armv6-unknown-netbsd-eabihf sparc64-unknown-netbsd
armv7-linux-androideabi sparc64-unknown-openbsd
armv7-unknown-cloudabi-eabihf sparcv9-sun-solaris
armv7-unknown-freebsd thumbv6m-none-eabi
armv7-unknown-linux-gnueabi thumbv7a-pc-windows-msvc
armv7-unknown-linux-gnueabihf thumbv7em-none-eabi
armv7-unknown-linux-musleabi thumbv7em-none-eabihf
armv7-unknown-linux-musleabihf thumbv7m-none-eabi
armv7-unknown-netbsd-eabihf thumbv7neon-linux-androideabi
armv7-wrs-vxworks-eabihf thumbv7neon-unknown-linux-gnueabihf
armv7a-none-eabi thumbv7neon-unknown-linux-musleabihf
armv7a-none-eabihf thumbv8m.base-none-eabi
armv7r-none-eabi thumbv8m.main-none-eabi
armv7r-none-eabihf thumbv8m.main-none-eabihf
asmjs-unknown-emscripten wasm32-unknown-emscripten
hexagon-unknown-linux-musl wasm32-unknown-unknown
i586-pc-windows-msvc wasm32-wasi
i586-unknown-linux-gnu x86_64-apple-darwin
i586-unknown-linux-musl x86_64-fortanix-unknown-sgx
i686-apple-darwin x86_64-fuchsia
i686-linux-android x86_64-linux-android
i686-pc-windows-gnu x86_64-linux-kernel
i686-pc-windows-msvc x86_64-pc-solaris
i686-unknown-cloudabi x86_64-pc-windows-gnu
i686-unknown-freebsd x86_64-pc-windows-msvc
i686-unknown-haiku x86_64-rumprun-netbsd
i686-unknown-linux-gnu x86_64-sun-solaris
i686-unknown-linux-musl x86_64-unknown-cloudabi
i686-unknown-netbsd x86_64-unknown-dragonfly
i686-unknown-openbsd x86_64-unknown-freebsd
i686-unknown-uefi x86_64-unknown-haiku
i686-uwp-windows-gnu x86_64-unknown-hermit
i686-uwp-windows-msvc x86_64-unknown-hermit-kernel
i686-wrs-vxworks x86_64-unknown-illumos
mips-unknown-linux-gnu x86_64-unknown-l4re-uclibc
mips-unknown-linux-musl x86_64-unknown-linux-gnu
mips-unknown-linux-uclibc x86_64-unknown-linux-gnux32
mips64-unknown-linux-gnuabi64 x86_64-unknown-linux-musl
mips64-unknown-linux-muslabi64 x86_64-unknown-netbsd
mips64el-unknown-linux-gnuabi64 x86_64-unknown-openbsd
mips64el-unknown-linux-muslabi64 x86_64-unknown-redox
mipsel-unknown-linux-gnu x86_64-unknown-uefi
mipsel-unknown-linux-musl x86_64-uwp-windows-gnu
mipsel-unknown-linux-uclibc x86_64-uwp-windows-msvc
mipsisa32r6-unknown-linux-gnu x86_64-wrs-vxworks
```

You can print the specification of any of these targets using the following command:
You can print the specification of one of these targets using the following command:

``` console
$ rustc +nightly -Z unstable-options --print target-spec-json --target thumbv7m-none-eabi
Expand Down Expand Up @@ -163,86 +194,69 @@ $ rustc +nightly -Z unstable-options --print target-spec-json --target thumbv7m-
```

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

[the compiler source code]: https://github.com/rust-lang/rust/blob/1.27.2/src/librustc_target/spec/mod.rs#L376-L400

Once you have a target specification file you can refer to it by its path or by its name if its in
the current directory or in `$RUST_TARGET_PATH`.

``` console
$ rustc +nightly -Z unstable-options --print target-spec-json \
--target thumbv7m-none-eabi \
> foo.json

$ rustc --print cfg --target foo.json # or just --target foo
debug_assertions
target_arch="arm"
target_endian="little"
target_env=""
target_feature="mclass"
target_feature="v7"
target_has_atomic="16"
target_has_atomic="32"
target_has_atomic="8"
target_has_atomic="cas"
target_has_atomic="ptr"
target_os="none"
target_pointer_width="32"
target_vendor=""
```
[custom-target]: ./custom-target.md

## `rust-std` component

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

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

``` console
$ rustup target list | column
aarch64-apple-ios mips64-unknown-linux-gnuabi64
aarch64-linux-android mips64el-unknown-linux-gnuabi64
aarch64-unknown-fuchsia mipsel-unknown-linux-gnu
aarch64-unknown-linux-gnu mipsel-unknown-linux-musl
aarch64-unknown-linux-musl powerpc-unknown-linux-gnu
arm-linux-androideabi powerpc64-unknown-linux-gnu
arm-unknown-linux-gnueabi powerpc64le-unknown-linux-gnu
arm-unknown-linux-gnueabihf s390x-unknown-linux-gnu
arm-unknown-linux-musleabi sparc64-unknown-linux-gnu
arm-unknown-linux-musleabihf sparcv9-sun-solaris
armv5te-unknown-linux-gnueabi thumbv6m-none-eabi
armv5te-unknown-linux-musleabi thumbv7em-none-eabi
armv7-apple-ios thumbv7em-none-eabihf
aarch64-apple-ios mipsel-unknown-linux-musl
aarch64-fuchsia nvptx64-nvidia-cuda
aarch64-linux-android powerpc-unknown-linux-gnu
aarch64-pc-windows-msvc powerpc64-unknown-linux-gnu
aarch64-unknown-linux-gnu powerpc64le-unknown-linux-gnu
aarch64-unknown-linux-musl riscv32i-unknown-none-elf
aarch64-unknown-none riscv32imac-unknown-none-elf
aarch64-unknown-none-softfloat riscv32imc-unknown-none-elf
arm-linux-androideabi riscv64gc-unknown-linux-gnu
arm-unknown-linux-gnueabi riscv64gc-unknown-none-elf
arm-unknown-linux-gnueabihf riscv64imac-unknown-none-elf
arm-unknown-linux-musleabi s390x-unknown-linux-gnu
arm-unknown-linux-musleabihf sparc64-unknown-linux-gnu
armebv7r-none-eabi sparcv9-sun-solaris
armebv7r-none-eabihf thumbv6m-none-eabi
armv5te-unknown-linux-gnueabi thumbv7em-none-eabi
armv5te-unknown-linux-musleabi thumbv7em-none-eabihf
armv7-linux-androideabi thumbv7m-none-eabi
armv7-unknown-linux-gnueabihf wasm32-unknown-emscripten
armv7-unknown-linux-musleabihf wasm32-unknown-unknown
armv7s-apple-ios x86_64-apple-darwin
asmjs-unknown-emscripten x86_64-apple-ios
i386-apple-ios x86_64-linux-android
i586-pc-windows-msvc x86_64-pc-windows-gnu
i586-unknown-linux-gnu x86_64-pc-windows-msvc
i586-unknown-linux-musl x86_64-rumprun-netbsd
i686-apple-darwin x86_64-sun-solaris
i686-linux-android x86_64-unknown-cloudabi
i686-pc-windows-gnu x86_64-unknown-freebsd
i686-pc-windows-msvc x86_64-unknown-fuchsia
i686-unknown-freebsd x86_64-unknown-linux-gnu (default)
i686-unknown-linux-gnu x86_64-unknown-linux-gnux32
i686-unknown-linux-musl x86_64-unknown-linux-musl
mips-unknown-linux-gnu x86_64-unknown-netbsd
mips-unknown-linux-musl x86_64-unknown-redox
armv7-unknown-linux-gnueabi thumbv7neon-linux-androideabi
armv7-unknown-linux-gnueabihf thumbv7neon-unknown-linux-gnueabihf
armv7-unknown-linux-musleabi thumbv8m.base-none-eabi
armv7-unknown-linux-musleabihf thumbv8m.main-none-eabi
armv7a-none-eabi thumbv8m.main-none-eabihf
armv7r-none-eabi wasm32-unknown-emscripten
armv7r-none-eabihf wasm32-unknown-unknown
asmjs-unknown-emscripten wasm32-wasi
i586-pc-windows-msvc x86_64-apple-darwin
i586-unknown-linux-gnu x86_64-apple-ios
i586-unknown-linux-musl x86_64-fortanix-unknown-sgx
i686-linux-android x86_64-fuchsia
i686-pc-windows-gnu x86_64-linux-android
i686-pc-windows-msvc x86_64-pc-windows-gnu
i686-unknown-freebsd x86_64-pc-windows-msvc
i686-unknown-linux-gnu x86_64-rumprun-netbsd
i686-unknown-linux-musl x86_64-sun-solaris
mips-unknown-linux-gnu x86_64-unknown-cloudabi
mips-unknown-linux-musl x86_64-unknown-freebsd
mips64-unknown-linux-gnuabi64 x86_64-unknown-linux-gnu (default)
mips64-unknown-linux-muslabi64 x86_64-unknown-linux-gnux32
mips64el-unknown-linux-gnuabi64 x86_64-unknown-linux-musl
mips64el-unknown-linux-muslabi64 x86_64-unknown-netbsd
mipsel-unknown-linux-gnu x86_64-unknown-redox
```

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

[Xargo]: https://github.com/japaric/xargo
[use-target-file]: ./custom-target.md#use-the-target-file
[xargo]: https://github.com/japaric/xargo
Loading