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 == "ppc64le" || goarch == "arm64" || 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", "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":
    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 "loong64", "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 string) 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  			return true
   178  		}
   179  		return false
   180  
   181  	case "default":
   182  		return true
   183  
   184  	case "exe":
   185  		return true
   186  
   187  	case "pie":
   188  		switch platform {
   189  		case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/loong64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
   190  			"android/amd64", "android/arm", "android/arm64", "android/386",
   191  			"freebsd/amd64",
   192  			"darwin/amd64", "darwin/arm64",
   193  			"ios/amd64", "ios/arm64",
   194  			"aix/ppc64",
   195  			"openbsd/arm64",
   196  			"windows/386", "windows/amd64", "windows/arm", "windows/arm64":
   197  			return true
   198  		}
   199  		return false
   200  
   201  	case "shared":
   202  		switch platform {
   203  		case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
   204  			return true
   205  		}
   206  		return false
   207  
   208  	case "plugin":
   209  		switch platform {
   210  		case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/loong64", "linux/s390x", "linux/ppc64le",
   211  			"android/amd64", "android/386",
   212  			"darwin/amd64", "darwin/arm64",
   213  			"freebsd/amd64":
   214  			return true
   215  		}
   216  		return false
   217  
   218  	default:
   219  		return false
   220  	}
   221  }
   222  
   223  func InternalLinkPIESupported(goos, goarch string) bool {
   224  	switch goos + "/" + goarch {
   225  	case "android/arm64",
   226  		"darwin/amd64", "darwin/arm64",
   227  		"linux/amd64", "linux/arm64", "linux/ppc64le",
   228  		"windows/386", "windows/amd64", "windows/arm", "windows/arm64":
   229  		return true
   230  	}
   231  	return false
   232  }
   233  
   234  // DefaultPIE reports whether goos/goarch produces a PIE binary when using the
   235  // "default" buildmode. On Windows this is affected by -race,
   236  // so force the caller to pass that in to centralize that choice.
   237  func DefaultPIE(goos, goarch string, isRace bool) bool {
   238  	switch goos {
   239  	case "android", "ios":
   240  		return true
   241  	case "windows":
   242  		if isRace {
   243  			// PIE is not supported with -race on windows;
   244  			// see https://go.dev/cl/416174.
   245  			return false
   246  		}
   247  		return true
   248  	case "darwin":
   249  		return true
   250  	}
   251  	return false
   252  }
   253  
   254  // ExecutableHasDWARF reports whether the linked executable includes DWARF
   255  // symbols on goos/goarch.
   256  func ExecutableHasDWARF(goos, goarch string) bool {
   257  	switch goos {
   258  	case "plan9", "ios":
   259  		return false
   260  	}
   261  	return true
   262  }
   263  
   264  // osArchInfo describes information about an OSArch extracted from cmd/dist and
   265  // stored in the generated distInfo map.
   266  type osArchInfo struct {
   267  	CgoSupported bool
   268  	FirstClass   bool
   269  	Broken       bool
   270  }
   271  
   272  // CgoSupported reports whether goos/goarch supports cgo.
   273  func CgoSupported(goos, goarch string) bool {
   274  	return distInfo[OSArch{goos, goarch}].CgoSupported
   275  }
   276  
   277  // FirstClass reports whether goos/goarch is considered a “first class” port.
   278  // (See https://go.dev/wiki/PortingPolicy#first-class-ports.)
   279  func FirstClass(goos, goarch string) bool {
   280  	return distInfo[OSArch{goos, goarch}].FirstClass
   281  }
   282  
   283  // Broken reportsr whether goos/goarch is considered a broken port.
   284  // (See https://go.dev/wiki/PortingPolicy#broken-ports.)
   285  func Broken(goos, goarch string) bool {
   286  	return distInfo[OSArch{goos, goarch}].Broken
   287  }
   288  

View as plain text