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