5.2. The target specification JSON file

External resources:

Rust provides a built-in list of target specifications that are viewable via rustc --print target-list. A custom target specification JSON file may be written to override and tweak various target-specific options, such as linker scripts, flags, and LLVM options.

When compiling for AVR, a specific microcontroller variant/model must be targeted. This allows LLVM to generate instructions that confirm to each particular microcontroller's ABI and supported instruction set.

The target specification JSON file:

  • May live in any directory - most often, committed to version control.
  • Any file name you like, so long as it's JSON
  • Is given to Rust via the --target my-target-spec.json. For example, cargo build --target ./targets/my-target-spec.json.

An example - using the GNU toolchain for linking and compiler support libraries

Here is an example target specification JSON file for the AVR atmega328p.

This target specification:

  • Enables the GNU AVR linker through the avr-gcc compiler frontend
  • Tells the linker to include libgcc (as compiler-rt for AVR is not yet fully supported)
  • Tells Rust not to pass the --eh-frame-hdr argument to the linker, which isn't supported by AVR-GCC and will cause and error if omitted.
  • Instructs LLVM to use the avr-unknown-unknown target specifically for the atmega328p microcontroller
  • Explicitly passes an -mmcu argument to the linker to ensure runtime libraries are not skipped by the linker
{
  "arch": "avr",
  "cpu": "atmega328p",
  "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
  "env": "",
  "executables": true,
  "linker": "avr-gcc",
  "linker-flavor": "gcc",
  "linker-is-gnu": true,
  "llvm-target": "avr-unknown-unknown",
  "no-compiler-rt": true,
  "os": "unknown",
  "position-independent-executables": false,
  "exe-suffix": ".elf",
  "eh-frame-header": false,
  "pre-link-args": {
    "gcc": ["-mmcu=atmega328p"]
  },
  "late-link-args": {
    "gcc": ["-lgcc"]
  },
  "target-c-int-width": "16",
  "target-endian": "little",
  "target-pointer-width": "16",
  "vendor": "unknown"
}

Adapting to another microcontroller variant

Adapting a target specification JSON to another AVR variant is trivial.

Options that must be updated to target individual microcontroller variants:

  • cpu - set to the lower-case model name of the desired AVR variant
  • pre-link-args - the correct -mmcu option, always equal to the cpu, must be updated