Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/internal/platform/supported.go

     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 string
    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 string) bool {
    24  	switch goos {
    25  	case "linux":
    26  		return goarch == "amd64" || goarch == "arm64" || goarch == "loong64" || goarch == "ppc64le" || goarch == "riscv64" || goarch == "s390x"
    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 string) 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 string) 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  // FIPS140Supported reports whether goos/goarch supports FIPS 140-3 mode.
    61  // It does not consider non-platform constraints such as the purego build tag,
    62  // -asan, or GOEXPERIMENT=boringcrypto.
    63  // There is a copy of this function in cmd/dist/test.go.
    64  func FIPS140Supported(goos, goarch string) bool {
    65  	// Keep this in sync with crypto/internal/fips140.Supported.
    66  	switch {
    67  	case goarch == "wasm",
    68  		goos == "windows" && goarch == "386",
    69  		goos == "openbsd",
    70  		goos == "aix":
    71  		return false
    72  	}
    73  	return true
    74  }
    75  
    76  // FuzzSupported reports whether goos/goarch supports fuzzing
    77  // ('go test -fuzz=.').
    78  func FuzzSupported(goos, goarch string) bool {
    79  	switch goos {
    80  	case "darwin", "freebsd", "linux", "openbsd", "windows":
    81  		return true
    82  	default:
    83  		return false
    84  	}
    85  }
    86  
    87  // FuzzInstrumented reports whether fuzzing on goos/goarch uses coverage
    88  // instrumentation. (FuzzInstrumented implies FuzzSupported.)
    89  func FuzzInstrumented(goos, goarch string) bool {
    90  	switch goarch {
    91  	case "amd64", "arm64", "loong64":
    92  		// TODO(#14565): support more architectures.
    93  		return FuzzSupported(goos, goarch)
    94  	default:
    95  		return false
    96  	}
    97  }
    98  
    99  // MustLinkExternal reports whether goos/goarch requires external linking
   100  // with or without cgo dependencies.
   101  func MustLinkExternal(goos, goarch string, withCgo bool) bool {
   102  	if withCgo {
   103  		switch goarch {
   104  		case "mips", "mipsle", "mips64", "mips64le":
   105  			// Internally linking cgo is incomplete on some architectures.
   106  			// https://go.dev/issue/14449
   107  			return true
   108  		case "ppc64":
   109  			// Big Endian PPC64 cgo internal linking is not implemented for aix.
   110  			// https://go.dev/issue/8912
   111  			if goos == "aix" {
   112  				return true
   113  			}
   114  		}
   115  
   116  		switch goos {
   117  		case "android":
   118  			return true
   119  		case "dragonfly":
   120  			// It seems that on Dragonfly thread local storage is
   121  			// set up by the dynamic linker, so internal cgo linking
   122  			// doesn't work. Test case is "go test runtime/cgo".
   123  			return true
   124  		}
   125  	}
   126  
   127  	switch goos {
   128  	case "android":
   129  		if goarch != "arm64" {
   130  			return true
   131  		}
   132  	case "ios":
   133  		if goarch == "arm64" {
   134  			return true
   135  		}
   136  	}
   137  	return false
   138  }
   139  
   140  // BuildModeSupported reports whether goos/goarch supports the given build mode
   141  // using the given compiler.
   142  // There is a copy of this function in cmd/dist/test.go.
   143  func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
   144  	if compiler == "gccgo" {
   145  		return true
   146  	}
   147  
   148  	if _, ok := distInfo[OSArch{goos, goarch}]; !ok {
   149  		return false // platform unrecognized
   150  	}
   151  
   152  	platform := goos + "/" + goarch
   153  	switch buildmode {
   154  	case "archive":
   155  		return true
   156  
   157  	case "c-archive":
   158  		switch goos {
   159  		case "aix", "darwin", "ios", "windows":
   160  			return true
   161  		case "linux":
   162  			switch goarch {
   163  			case "386", "amd64", "arm", "armbe", "arm64", "arm64be", "loong64", "ppc64", "ppc64le", "riscv64", "s390x":
   164  				return true
   165  			default:
   166  				// Other targets do not support -shared,
   167  				// per ParseFlags in
   168  				// cmd/compile/internal/base/flag.go.
   169  				// For c-archive the Go tool passes -shared,
   170  				// so that the result is suitable for inclusion
   171  				// in a PIE or shared library.
   172  				return false
   173  			}
   174  		case "freebsd":
   175  			return goarch == "amd64"
   176  		}
   177  		return false
   178  
   179  	case "c-shared":
   180  		switch platform {
   181  		case "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/386", "linux/ppc64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
   182  			"android/amd64", "android/arm", "android/arm64", "android/386",
   183  			"freebsd/amd64",
   184  			"darwin/amd64", "darwin/arm64",
   185  			"windows/amd64", "windows/386", "windows/arm64",
   186  			"wasip1/wasm":
   187  			return true
   188  		}
   189  		return false
   190  
   191  	case "default":
   192  		return true
   193  
   194  	case "exe":
   195  		return true
   196  
   197  	case "pie":
   198  		switch platform {
   199  		case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/ppc64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
   200  			"android/amd64", "android/arm", "android/arm64", "android/386",
   201  			"freebsd/amd64",
   202  			"darwin/amd64", "darwin/arm64",
   203  			"ios/amd64", "ios/arm64",
   204  			"aix/ppc64",
   205  			"openbsd/arm64",
   206  			"windows/386", "windows/amd64", "windows/arm64":
   207  			return true
   208  		}
   209  		return false
   210  
   211  	case "shared":
   212  		switch platform {
   213  		case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64", "linux/ppc64le", "linux/s390x":
   214  			return true
   215  		}
   216  		return false
   217  
   218  	case "plugin":
   219  		switch platform {
   220  		case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/riscv64", "linux/s390x", "linux/ppc64", "linux/ppc64le",
   221  			"android/amd64", "android/386",
   222  			"darwin/amd64", "darwin/arm64",
   223  			"freebsd/amd64":
   224  			return true
   225  		}
   226  		return false
   227  
   228  	default:
   229  		return false
   230  	}
   231  }
   232  
   233  func InternalLinkPIESupported(goos, goarch string) bool {
   234  	switch goos + "/" + goarch {
   235  	case "android/arm64",
   236  		"darwin/amd64", "darwin/arm64",
   237  		"linux/amd64", "linux/arm64", "linux/loong64", "linux/ppc64", "linux/ppc64le", "linux/s390x",
   238  		"windows/386", "windows/amd64", "windows/arm64":
   239  		return true
   240  	}
   241  	return false
   242  }
   243  
   244  // DefaultPIE reports whether goos/goarch produces a PIE binary when using the
   245  // "default" buildmode. On Windows this is affected by -race,
   246  // so force the caller to pass that in to centralize that choice.
   247  func DefaultPIE(goos, goarch string, isRace bool) bool {
   248  	switch goos {
   249  	case "android", "ios":
   250  		return true
   251  	case "windows":
   252  		if isRace {
   253  			// PIE is not supported with -race on windows;
   254  			// see https://go.dev/cl/416174.
   255  			return false
   256  		}
   257  		return true
   258  	case "darwin":
   259  		return true
   260  	}
   261  	return false
   262  }
   263  
   264  // ExecutableHasDWARF reports whether the linked executable includes DWARF
   265  // symbols on goos/goarch.
   266  func ExecutableHasDWARF(goos, goarch string) bool {
   267  	switch goos {
   268  	case "plan9", "ios":
   269  		return false
   270  	}
   271  	return true
   272  }
   273  
   274  // osArchInfo describes information about an OSArch extracted from cmd/dist and
   275  // stored in the generated distInfo map.
   276  type osArchInfo struct {
   277  	CgoSupported bool
   278  	FirstClass   bool
   279  	Broken       bool
   280  }
   281  
   282  // CgoSupported reports whether goos/goarch supports cgo.
   283  func CgoSupported(goos, goarch string) bool {
   284  	return distInfo[OSArch{goos, goarch}].CgoSupported
   285  }
   286  
   287  // FirstClass reports whether goos/goarch is considered a “first class” port.
   288  // (See https://go.dev/wiki/PortingPolicy#first-class-ports.)
   289  func FirstClass(goos, goarch string) bool {
   290  	return distInfo[OSArch{goos, goarch}].FirstClass
   291  }
   292  
   293  // Broken reports whether goos/goarch is considered a broken port.
   294  // (See https://go.dev/wiki/PortingPolicy#broken-ports.)
   295  func Broken(goos, goarch string) bool {
   296  	return distInfo[OSArch{goos, goarch}].Broken
   297  }
   298  

View as plain text