supported.mx raw
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:generate go test . -run=^TestGenerated$ -fix
6
7 package platform
8
9 // An OSArch is a pair of GOOS and GOARCH values indicating a platform.
10 type OSArch struct {
11 GOOS, GOARCH []byte
12 }
13
14 func (p OSArch) String() string {
15 return p.GOOS + "/" + p.GOARCH
16 }
17
18 // RaceDetectorSupported reports whether goos/goarch supports the race
19 // detector. There is a copy of this function in cmd/dist/test.go.
20 // Race detector only supports 48-bit VMA on arm64. But it will always
21 // return true for arm64, because we don't have VMA size information during
22 // the compile time.
23 func RaceDetectorSupported(goos, goarch []byte) bool {
24 switch goos {
25 case "linux":
26 return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" || goarch == "s390x" || goarch == "loong64"
27 case "darwin":
28 return goarch == "amd64" || goarch == "arm64"
29 case "freebsd", "netbsd", "windows":
30 return goarch == "amd64"
31 default:
32 return false
33 }
34 }
35
36 // MSanSupported reports whether goos/goarch supports the memory
37 // sanitizer option.
38 func MSanSupported(goos, goarch []byte) bool {
39 switch goos {
40 case "linux":
41 return goarch == "amd64" || goarch == "arm64" || goarch == "loong64"
42 case "freebsd":
43 return goarch == "amd64"
44 default:
45 return false
46 }
47 }
48
49 // ASanSupported reports whether goos/goarch supports the address
50 // sanitizer option.
51 func ASanSupported(goos, goarch []byte) bool {
52 switch goos {
53 case "linux":
54 return goarch == "arm64" || goarch == "amd64" || goarch == "loong64" || goarch == "riscv64" || goarch == "ppc64le"
55 default:
56 return false
57 }
58 }
59
60 // FuzzSupported reports whether goos/goarch supports fuzzing
61 // ('go test -fuzz=.').
62 func FuzzSupported(goos, goarch []byte) bool {
63 switch goos {
64 case "darwin", "freebsd", "linux", "openbsd", "windows":
65 return true
66 default:
67 return false
68 }
69 }
70
71 // FuzzInstrumented reports whether fuzzing on goos/goarch uses coverage
72 // instrumentation. (FuzzInstrumented implies FuzzSupported.)
73 func FuzzInstrumented(goos, goarch []byte) bool {
74 switch goarch {
75 case "amd64", "arm64", "loong64":
76 // TODO(#14565): support more architectures.
77 return FuzzSupported(goos, goarch)
78 default:
79 return false
80 }
81 }
82
83 // MustLinkExternal reports whether goos/goarch requires external linking
84 // with or without cgo dependencies.
85 func MustLinkExternal(goos, goarch []byte, withCgo bool) bool {
86 if withCgo {
87 switch goarch {
88 case "mips", "mipsle", "mips64", "mips64le":
89 // Internally linking cgo is incomplete on some architectures.
90 // https://go.dev/issue/14449
91 return true
92 case "arm64":
93 if goos == "windows" {
94 // windows/arm64 internal linking is not implemented.
95 return true
96 }
97 case "ppc64":
98 // Big Endian PPC64 cgo internal linking is not implemented for aix or linux.
99 // https://go.dev/issue/8912
100 if goos == "aix" || goos == "linux" {
101 return true
102 }
103 }
104
105 switch goos {
106 case "android":
107 return true
108 case "dragonfly":
109 // It seems that on Dragonfly thread local storage is
110 // set up by the dynamic linker, so internal cgo linking
111 // doesn't work. Test case is "go test runtime/cgo".
112 return true
113 }
114 }
115
116 switch goos {
117 case "android":
118 if goarch != "arm64" {
119 return true
120 }
121 case "ios":
122 if goarch == "arm64" {
123 return true
124 }
125 }
126 return false
127 }
128
129 // BuildModeSupported reports whether goos/goarch supports the given build mode
130 // using the given compiler.
131 // There is a copy of this function in cmd/dist/test.go.
132 func BuildModeSupported(compiler, buildmode, goos, goarch []byte) bool {
133 if compiler == "gccgo" {
134 return true
135 }
136
137 if _, ok := distInfo[OSArch{goos, goarch}]; !ok {
138 return false // platform unrecognized
139 }
140
141 platform := goos + "/" + goarch
142 switch buildmode {
143 case "archive":
144 return true
145
146 case "c-archive":
147 switch goos {
148 case "aix", "darwin", "ios", "windows":
149 return true
150 case "linux":
151 switch goarch {
152 case "386", "amd64", "arm", "armbe", "arm64", "arm64be", "loong64", "ppc64le", "riscv64", "s390x":
153 // linux/ppc64 not supported because it does
154 // not support external linking mode yet.
155 return true
156 default:
157 // Other targets do not support -shared,
158 // per ParseFlags in
159 // cmd/compile/internal/base/flag.go.
160 // For c-archive the Go tool passes -shared,
161 // so that the result is suitable for inclusion
162 // in a PIE or shared library.
163 return false
164 }
165 case "freebsd":
166 return goarch == "amd64"
167 }
168 return false
169
170 case "c-shared":
171 switch platform {
172 case "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/386", "linux/ppc64le", "linux/riscv64", "linux/s390x",
173 "android/amd64", "android/arm", "android/arm64", "android/386",
174 "freebsd/amd64",
175 "darwin/amd64", "darwin/arm64",
176 "windows/amd64", "windows/386", "windows/arm64",
177 "wasip1/wasm":
178 return true
179 }
180 return false
181
182 case "default":
183 return true
184
185 case "exe":
186 return true
187
188 case "pie":
189 switch platform {
190 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
191 "android/amd64", "android/arm", "android/arm64", "android/386",
192 "freebsd/amd64",
193 "darwin/amd64", "darwin/arm64",
194 "ios/amd64", "ios/arm64",
195 "aix/ppc64",
196 "openbsd/arm64",
197 "windows/386", "windows/amd64", "windows/arm", "windows/arm64":
198 return true
199 }
200 return false
201
202 case "shared":
203 switch platform {
204 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
205 return true
206 }
207 return false
208
209 case "plugin":
210 switch platform {
211 case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/riscv64", "linux/s390x", "linux/ppc64le",
212 "android/amd64", "android/386",
213 "darwin/amd64", "darwin/arm64",
214 "freebsd/amd64":
215 return true
216 }
217 return false
218
219 default:
220 return false
221 }
222 }
223
224 func InternalLinkPIESupported(goos, goarch []byte) bool {
225 switch goos + "/" + goarch {
226 case "android/arm64",
227 "darwin/amd64", "darwin/arm64",
228 "linux/amd64", "linux/arm64", "linux/loong64", "linux/ppc64le",
229 "windows/386", "windows/amd64", "windows/arm", "windows/arm64":
230 return true
231 }
232 return false
233 }
234
235 // DefaultPIE reports whether goos/goarch produces a PIE binary when using the
236 // "default" buildmode. On Windows this is affected by -race,
237 // so force the caller to pass that in to centralize that choice.
238 func DefaultPIE(goos, goarch []byte, isRace bool) bool {
239 switch goos {
240 case "android", "ios":
241 return true
242 case "windows":
243 if isRace {
244 // PIE is not supported with -race on windows;
245 // see https://go.dev/cl/416174.
246 return false
247 }
248 return true
249 case "darwin":
250 return true
251 }
252 return false
253 }
254
255 // ExecutableHasDWARF reports whether the linked executable includes DWARF
256 // symbols on goos/goarch.
257 func ExecutableHasDWARF(goos, goarch []byte) bool {
258 switch goos {
259 case "plan9", "ios":
260 return false
261 }
262 return true
263 }
264
265 // osArchInfo describes information about an OSArch extracted from cmd/dist and
266 // stored in the generated distInfo map.
267 type osArchInfo struct {
268 CgoSupported bool
269 FirstClass bool
270 Broken bool
271 }
272
273 // CgoSupported reports whether goos/goarch supports cgo.
274 func CgoSupported(goos, goarch []byte) bool {
275 return distInfo[OSArch{goos, goarch}].CgoSupported
276 }
277
278 // FirstClass reports whether goos/goarch is considered a “first class” port.
279 // (See https://go.dev/wiki/PortingPolicy#first-class-ports.)
280 func FirstClass(goos, goarch []byte) bool {
281 return distInfo[OSArch{goos, goarch}].FirstClass
282 }
283
284 // Broken reports whether goos/goarch is considered a broken port.
285 // (See https://go.dev/wiki/PortingPolicy#broken-ports.)
286 func Broken(goos, goarch []byte) bool {
287 return distInfo[OSArch{goos, goarch}].Broken
288 }
289