1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
package main
import (
"encoding/json"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
)
// Target specification for a given target. Used for bare metal targets.
//
// The target specification is mostly inspired by Rust:
// 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 {
Triple string `json:"llvm-target"`
BuildTags []string `json:"build-tags"`
Linker string `json:"linker"`
CompilerRT bool `json:"compiler-rt"`
PreLinkArgs []string `json:"pre-link-args"`
Objcopy string `json:"objcopy"`
Emulator []string `json:"emulator"`
Flasher string `json:"flash"`
OCDDaemon []string `json:"ocd-daemon"`
GDB string `json:"gdb"`
GDBCmds []string `json:"gdb-initial-cmds"`
}
// Load a target specification
func LoadTarget(target string) (*TargetSpec, error) {
spec := &TargetSpec{
Triple: target,
BuildTags: []string{runtime.GOOS, runtime.GOARCH},
Linker: "cc",
PreLinkArgs: []string{"-no-pie"}, // WARNING: clang < 5.0 requires -nopie
Objcopy: "objcopy",
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. This is fine.
}
return spec, nil
}
// Return the source directory of this package, or "." when it cannot be
// recovered.
func sourceDir() string {
// https://stackoverflow.com/a/32163888/559350
_, path, _, _ := runtime.Caller(0)
return filepath.Dir(path)
}
func getGopath() string {
gopath := os.Getenv("GOPATH")
if gopath != "" {
return gopath
}
// fallback
home := getHomeDir()
return filepath.Join(home, "go")
}
func getHomeDir() string {
u, err := user.Current()
if err != nil {
panic("cannot get current user: " + err.Error())
}
if u.HomeDir == "" {
// This is very unlikely, so panic here.
// Not the nicest solution, however.
panic("could not find home directory")
}
return u.HomeDir
}
|