-
Notifications
You must be signed in to change notification settings - Fork 735
/
Copy pathtarget.go
160 lines (139 loc) · 4.02 KB
/
target.go
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//go:build !windows
package gen
import (
"errors"
"fmt"
"go/build/constraint"
"maps"
"runtime"
"slices"
)
var ErrInvalidTarget = errors.New("unsupported target")
var targetsByGoArch = map[GoArch]Target{
"386": {"bpfel", "x86", ""},
"amd64": {"bpfel", "x86", ""},
"arm": {"bpfel", "arm", ""},
"arm64": {"bpfel", "arm64", ""},
"loong64": {"bpfel", "loongarch", ""},
"mips": {"bpfeb", "mips", ""},
"mipsle": {"bpfel", "", ""},
"mips64": {"bpfeb", "", ""},
"mips64le": {"bpfel", "", ""},
"ppc64": {"bpfeb", "powerpc", ""},
"ppc64le": {"bpfel", "powerpc", ""},
"riscv64": {"bpfel", "riscv", ""},
"s390x": {"bpfeb", "s390", ""},
"wasm": {"bpfel", "", "js"},
}
type Target struct {
// Clang arch string, used to define the clang -target flag, as per
// "clang -print-targets".
clang string
// Linux arch string, used to define __TARGET_ARCH_xzy macros used by
// https://github.com/libbpf/libbpf/blob/master/src/bpf_tracing.h
linux string
// GOOS override for use during tests.
goos string
}
// TargetsByGoArch returns all supported targets.
func TargetsByGoArch() map[GoArch]Target {
return maps.Clone(targetsByGoArch)
}
// IsGeneric returns true if the target will compile to generic BPF.
func (tgt *Target) IsGeneric() bool {
return tgt.linux == ""
}
// Suffix returns a a string suitable for appending to a file name to
// identify the target.
func (tgt *Target) Suffix() string {
// The output filename must not match any of the following patterns:
//
// *_GOOS
// *_GOARCH
// *_GOOS_GOARCH
//
// Otherwise it is interpreted as a build constraint by the Go toolchain.
stem := tgt.clang
if tgt.linux != "" {
stem = fmt.Sprintf("%s_%s", tgt.linux, tgt.clang)
}
return stem
}
// ObsoleteSuffix returns an obsolete suffix for a subset of targets.
//
// It's used to work around an old bug and should not be used in new code.
func (tgt *Target) ObsoleteSuffix() string {
if tgt.linux == "" {
return ""
}
return fmt.Sprintf("%s_%s", tgt.clang, tgt.linux)
}
// GoArch is a Go arch string.
//
// See https://go.dev/doc/install/source#environment for valid GOARCHes when
// GOOS=linux.
type GoArch string
type GoArches []GoArch
// Constraints is satisfied when GOARCH is any of the arches.
func (arches GoArches) Constraint() constraint.Expr {
var archConstraint constraint.Expr
for _, goarch := range arches {
tag := &constraint.TagExpr{Tag: string(goarch)}
archConstraint = orConstraints(archConstraint, tag)
}
return archConstraint
}
// FindTarget turns a list of identifiers into targets and their respective
// GoArches.
//
// The following are valid identifiers:
//
// - bpf: compile generic BPF for host endianness
// - bpfel: compile generic BPF for little endian
// - bpfeb: compile generic BPF for big endian
// - native: compile BPF for host target
// - $GOARCH: compile BPF for $GOARCH target
//
// Generic BPF can run on any target goarch with the correct endianness,
// but doesn't have access to some arch specific tracing functionality.
func FindTarget(id string) (Target, GoArches, error) {
switch id {
case "bpf", "bpfel", "bpfeb":
var goarches []GoArch
for arch, archTarget := range targetsByGoArch {
if archTarget.clang == id {
// Include tags for all goarches that have the same endianness.
goarches = append(goarches, arch)
}
}
slices.Sort(goarches)
return Target{id, "", ""}, goarches, nil
case "native":
id = runtime.GOARCH
fallthrough
default:
archTarget, ok := targetsByGoArch[GoArch(id)]
if !ok || archTarget.linux == "" {
return Target{}, nil, fmt.Errorf("%q: %w", id, ErrInvalidTarget)
}
var goarches []GoArch
for goarch, lt := range targetsByGoArch {
if lt == archTarget {
// Include tags for all goarches that have the same
// target.
goarches = append(goarches, goarch)
}
}
slices.Sort(goarches)
return archTarget, goarches, nil
}
}
func orConstraints(x, y constraint.Expr) constraint.Expr {
if x == nil {
return y
}
if y == nil {
return x
}
return &constraint.OrExpr{X: x, Y: y}
}