targets: let specific targets inherit more general targets

This avoids a ton of duplication and makes it easier to change a generic
target (for example, the "cortex-m" target) for all boards that use it.

Also, by making it possible to inherit properties from a parent target
specification, it is easier to support out-of-tree boards that don't
have to be updated so often. A target specification for a
special-purpose board can simply inherit the specification of a
supported chip and override the properites it needs to override (like
the programming interface).
Этот коммит содержится в:
Ayke van Laethem 2018-11-19 21:08:12 +01:00
родитель f02766265c
коммит 760bc5d0a4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
10 изменённых файлов: 198 добавлений и 91 удалений

129
target.go
Просмотреть файл

@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"io"
"os"
"os/user"
"path/filepath"
@ -17,6 +18,7 @@ import (
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.TargetOptions.html
// https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json
type TargetSpec struct {
Inherits []string `json:"inherits"`
Triple string `json:"llvm-target"`
BuildTags []string `json:"build-tags"`
Linker string `json:"linker"`
@ -30,13 +32,117 @@ type TargetSpec struct {
GDBCmds []string `json:"gdb-initial-cmds"`
}
// Load a target specification
// copyProperties copies all properties that are set in spec2 into itself.
func (spec *TargetSpec) copyProperties(spec2 *TargetSpec) {
// TODO: simplify this using reflection? Inherits and BuildTags are special
// cases, but the rest can simply be copied if set.
spec.Inherits = append(spec.Inherits, spec2.Inherits...)
if spec2.Triple != "" {
spec.Triple = spec2.Triple
}
spec.BuildTags = append(spec.BuildTags, spec2.BuildTags...)
if spec2.Linker != "" {
spec.Linker = spec2.Linker
}
if spec2.RTLib != "" {
spec.RTLib = spec2.RTLib
}
if len(spec2.PreLinkArgs) != 0 {
spec.PreLinkArgs = spec2.PreLinkArgs
}
if spec2.Objcopy != "" {
spec.Objcopy = spec2.Objcopy
}
if len(spec2.Emulator) != 0 {
spec.Emulator = spec2.Emulator
}
if spec2.Flasher != "" {
spec.Flasher = spec2.Flasher
}
if len(spec2.OCDDaemon) != 0 {
spec.OCDDaemon = spec2.OCDDaemon
}
if spec2.GDB != "" {
spec.GDB = spec2.GDB
}
if len(spec2.GDBCmds) != 0 {
spec.GDBCmds = spec2.GDBCmds
}
}
// load reads a target specification from the JSON in the given io.Reader. It
// may load more targets specified using the "inherits" property.
func (spec *TargetSpec) load(r io.Reader) error {
err := json.NewDecoder(r).Decode(spec)
if err != nil {
return err
}
return nil
}
// loadFromName loads the given target from the targets/ directory inside the
// compiler sources.
func (spec *TargetSpec) loadFromName(name string) error {
path := filepath.Join(sourceDir(), "targets", strings.ToLower(name)+".json")
fp, err := os.Open(path)
if err != nil {
return err
}
defer fp.Close()
return spec.load(fp)
}
// resolveInherits loads inherited targets, recursively.
func (spec *TargetSpec) resolveInherits() error {
// First create a new spec with all the inherited properties.
newSpec := &TargetSpec{}
for _, name := range spec.Inherits {
subtarget := &TargetSpec{}
err := subtarget.loadFromName(name)
if err != nil {
return err
}
err = subtarget.resolveInherits()
if err != nil {
return err
}
newSpec.copyProperties(subtarget)
}
// When all properties are loaded, make sure they are properly inherited.
newSpec.copyProperties(spec)
*spec = *newSpec
return nil
}
// Load a target specification.
func LoadTarget(target string) (*TargetSpec, error) {
if target == "" {
target = llvm.DefaultTargetTriple()
}
spec := &TargetSpec{
// See whether there is a target specification for this target (e.g.
// Arduino).
spec := &TargetSpec{}
err := spec.loadFromName(target)
if err == nil {
// Successfully loaded this target from a built-in .json file. Make sure
// it includes all parents as specified in the "inherits" key.
err = spec.resolveInherits()
if err != nil {
return nil, err
}
return spec, nil
} else if !os.IsNotExist(err) {
// Expected a 'file not found' error, got something else. Report it as
// an error.
return nil, err
} else {
// No target spec available. Use the default one, useful on most systems
// with a regular OS.
*spec = TargetSpec{
Triple: target,
BuildTags: []string{runtime.GOOS, runtime.GOARCH},
Linker: "cc",
@ -45,26 +151,9 @@ func LoadTarget(target string) (*TargetSpec, error) {
GDB: "gdb",
GDBCmds: []string{"run"},
}
// See whether there is a target specification for this target (e.g.
// Arduino).
path := filepath.Join(sourceDir(), "targets", strings.ToLower(target)+".json")
if fp, err := os.Open(path); err == nil {
defer fp.Close()
*spec = TargetSpec{} // reset all fields
err := json.NewDecoder(fp).Decode(spec)
if err != nil {
return nil, err
}
} else if !os.IsNotExist(err) {
// Expected a 'file not found' error, got something else.
return nil, err
} else {
// No target spec available. Use the default one.
}
return spec, nil
}
}
// Return the source directory of this package, or "." when it cannot be
// recovered.

Просмотреть файл

@ -1,9 +1,18 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7m-none-eabi",
"build-tags": ["bluepill", "stm32f103xx", "stm32", "tinygo.arm", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"rtlib": "compiler-rt",
"pre-link-args": ["-nostdlib", "-nostartfiles", "-mcpu=cortex-m3", "-mthumb", "-T", "targets/stm32.ld", "-Wl,--gc-sections", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections", "-Os", "src/device/stm32/stm32f103xx.s"],
"objcopy": "arm-none-eabi-objcopy",
"build-tags": ["bluepill", "stm32f103xx", "stm32"],
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m3",
"-mthumb",
"-T", "targets/stm32.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"src/device/stm32/stm32f103xx.s"
],
"flash": "openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c 'program {hex} reset exit'"
}

7
targets/cortex-m.json Обычный файл
Просмотреть файл

@ -0,0 +1,7 @@
{
"build-tags": ["tinygo.arm", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"rtlib": "compiler-rt",
"objcopy": "arm-none-eabi-objcopy",
"gdb": "arm-none-eabi-gdb"
}

Просмотреть файл

@ -1,26 +1,7 @@
{
"llvm-target": "armv6m-none-eabi",
"build-tags": ["microbit", "nrf51822", "nrf51", "nrf", "tinygo.arm", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"rtlib": "compiler-rt",
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m0",
"-mthumb",
"-T", "targets/nrf51.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"-DNRF51",
"-Ilib/CMSIS/CMSIS/Include",
"lib/nrfx/mdk/system_nrf51.c",
"src/device/nrf/nrf51.s"
],
"objcopy": "arm-none-eabi-objcopy",
"inherits": ["nrf51"],
"build-tags": ["microbit"],
"flash": "openocd -f interface/cmsis-dap.cfg -f target/nrf51.cfg -c 'program {hex} reset exit'",
"ocd-daemon": ["openocd", "-f", "interface/cmsis-dap.cfg", "-f", "target/nrf51.cfg"],
"gdb": "arm-none-eabi-gdb",
"gdb-initial-cmds": ["target remote :3333", "monitor halt", "load", "monitor reset", "c"]
}

20
targets/nrf51.json Обычный файл
Просмотреть файл

@ -0,0 +1,20 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv6m-none-eabi",
"build-tags": ["nrf51822", "nrf51", "nrf"],
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m0",
"-mthumb",
"-T", "targets/nrf51.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"-DNRF51",
"-Ilib/CMSIS/CMSIS/Include",
"lib/nrfx/mdk/system_nrf51.c",
"src/device/nrf/nrf51.s"
]
}

20
targets/nrf52.json Обычный файл
Просмотреть файл

@ -0,0 +1,20 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7em-none-eabi",
"build-tags": ["nrf52", "nrf"],
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m4",
"-mthumb",
"-T", "targets/nrf52.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"-DNRF52832_XXAA",
"-Ilib/CMSIS/CMSIS/Include",
"lib/nrfx/mdk/system_nrf52.c",
"src/device/nrf/nrf52.s"
]
}

Просмотреть файл

@ -1,25 +1,7 @@
{
"llvm-target": "armv7em-none-eabi",
"build-tags": ["nrf52840_mdk", "nrf52840", "nrf", "tinygo.arm", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m4",
"-mthumb",
"-T", "targets/nrf52840.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"-DNRF52840_XXAA",
"-Ilib/CMSIS/CMSIS/Include",
"lib/nrfx/mdk/system_nrf52840.c",
"src/device/nrf/nrf52840.s"
],
"objcopy": "arm-none-eabi-objcopy",
"inherits": ["nrf52840"],
"build-tags": ["nrf52840_mdk"],
"flash": "openocd -f interface/cmsis-dap.cfg -f target/nrf51.cfg -c 'program {hex} reset exit'",
"ocd-daemon": ["openocd", "-f", "interface/cmsis-dap.cfg", "-f", "target/nrf51.cfg"],
"gdb": "arm-none-eabi-gdb",
"gdb-initial-cmds": ["target remote :3333", "monitor halt", "load", "monitor reset", "c"]
}

20
targets/nrf52840.json Обычный файл
Просмотреть файл

@ -0,0 +1,20 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7em-none-eabi",
"build-tags": ["nrf52840", "nrf"],
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m4",
"-mthumb",
"-T", "targets/nrf52840.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"-DNRF52840_XXAA",
"-Ilib/CMSIS/CMSIS/Include",
"lib/nrfx/mdk/system_nrf52840.c",
"src/device/nrf/nrf52840.s"
]
}

Просмотреть файл

@ -1,26 +1,7 @@
{
"llvm-target": "armv7em-none-eabi",
"build-tags": ["pca10040", "nrf52832", "nrf52", "nrf", "tinygo.arm", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"rtlib": "compiler-rt",
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
"-mcpu=cortex-m4",
"-mthumb",
"-T", "targets/nrf52.ld",
"-Wl,--gc-sections",
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections",
"-Os",
"-DNRF52832_XXAA",
"-Ilib/CMSIS/CMSIS/Include",
"lib/nrfx/mdk/system_nrf52.c",
"src/device/nrf/nrf52.s"
],
"objcopy": "arm-none-eabi-objcopy",
"inherits": ["nrf52"],
"build-tags": ["pca10040"],
"flash": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset",
"ocd-daemon": ["openocd", "-f", "interface/jlink.cfg", "-c", "transport select swd", "-f", "target/nrf51.cfg"],
"gdb": "arm-none-eabi-gdb",
"gdb-initial-cmds": ["target remote :3333", "monitor halt", "load", "monitor reset", "c"]
}

Просмотреть файл

@ -1,8 +1,7 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7m-none-eabi",
"build-tags": ["qemu", "lm3s6965", "tinygo.arm", "js", "wasm"],
"linker": "arm-none-eabi-gcc",
"rtlib": "compiler-rt",
"build-tags": ["qemu", "lm3s6965"],
"pre-link-args": [
"-nostdlib",
"-nostartfiles",
@ -15,6 +14,5 @@
"-Os",
"targets/cortex-m.s"
],
"objcopy": "arm-none-eabi-objcopy",
"emulator": ["qemu-system-arm", "-machine", "lm3s6965evb", "-semihosting", "-nographic", "-kernel"]
}