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.

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

As of Rust 1.28, the official Rust compiler, rustc, uses LLVM for (machine) code generation. The minimal level of support Rust provides for an architecture is having its LLVM backend enabled in rustc. You can see all the architectures that rustc supports, through LLVM, by running the following command:

$ # you need to have `cargo-binutils` installed to run this command $ cargo objdump -- -version LLVM (http://llvm.org/): LLVM version 7.0.0svn Optimized build. Default target: x86_64-unknown-linux-gnu Host CPU: skylake Registered Targets: aarch64 - AArch64 (little endian) aarch64_be - AArch64 (big endian) arm - ARM arm64 - ARM64 (little endian) armeb - ARM (big endian) hexagon - Hexagon mips - Mips mips64 - Mips64 [experimental] mips64el - Mips64el [experimental] mipsel - Mipsel msp430 - MSP430 [experimental] nvptx - NVIDIA PTX 32-bit nvptx64 - NVIDIA PTX 64-bit ppc32 - PowerPC 32 ppc64 - PowerPC 64 ppc64le - PowerPC 64 LE sparc - Sparc sparcel - Sparc LE sparcv9 - Sparc V9 systemz - SystemZ thumb - Thumb thumbeb - Thumb (big endian) wasm32 - WebAssembly 32-bit wasm64 - WebAssembly 64-bit x86 - 32-bit X86: Pentium-Pro and above x86-64 - 64-bit X86: EM64T and AMD64

If LLVM supports the architecture you are interested in, but rustc is built with the backend disabled (which is the case of AVR as of Rust 1.28), then you will need to modify the Rust source enabling it. The first two commits of PR rust-lang/rust#52787 give you an idea of the required 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.

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 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.

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

$ rustc --print target-list | column 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 one of these targets using the following command:

$ rustc +nightly -Z unstable-options --print target-spec-json --target thumbv7m-none-eabi { "abi-blacklist": [ "stdcall", "fastcall", "vectorcall", "thiscall", "win64", "sysv64" ], "arch": "arm", "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", "emit-debug-gdb-scripts": false, "env": "", "executables": true, "is-builtin": true, "linker": "arm-none-eabi-gcc", "linker-flavor": "gcc", "llvm-target": "thumbv7m-none-eabi", "max-atomic-width": 32, "os": "none", "panic-strategy": "abort", "relocation-model": "static", "target-c-int-width": "32", "target-endian": "little", "target-pointer-width": "32", "vendor": "" }

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 which is described in the next section.

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.

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

$ rustup target list | column 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-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 nightly toolchain to build the standard library. See the next page about building for custom targets.