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

View as plain text