]> Cypherpunks repositories - gostls13.git/commitdiff
internal/testenv: use 'go env CGO_ENABLED' instead of a build constraint
authorBryan C. Mills <bcmills@google.com>
Tue, 28 Feb 2023 19:16:54 +0000 (19:16 +0000)
committerGopher Robot <gobot@golang.org>
Wed, 1 Mar 2023 17:28:28 +0000 (17:28 +0000)
A build constraint reports whether the test binary was compiled with
cgo enabled, but that doesn't necessarily imply that cgo can be used
in the environment in which the test binary is run.

In particular, cross-compiled builders (such as Android) may compile
the test binaries on the host with CGO enabled but not provide a C
toolchain on the device that runs the test.

For #58775.

Change-Id: Ibf2f44c9e956cd3fa898c3de67af4449e8ef2dd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/472215
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>

src/internal/testenv/testenv.go
src/internal/testenv/testenv_cgo.go [deleted file]

index 82fdfb6ff6e6b3cd328c82783141577426163969..65a82fd5f767d05901083e0528e2c0743692a9c2 100644 (file)
@@ -193,28 +193,40 @@ func GOROOT(t testing.TB) string {
 
 // GoTool reports the path to the Go tool.
 func GoTool() (string, error) {
-       if !HasGoBuild() {
-               return "", errors.New("platform cannot run go tool")
-       }
-       var exeSuffix string
-       if runtime.GOOS == "windows" {
-               exeSuffix = ".exe"
-       }
-       goroot, err := findGOROOT()
-       if err != nil {
-               return "", fmt.Errorf("cannot find go tool: %w", err)
-       }
-       path := filepath.Join(goroot, "bin", "go"+exeSuffix)
-       if _, err := os.Stat(path); err == nil {
-               return path, nil
-       }
-       goBin, err := exec.LookPath("go" + exeSuffix)
-       if err != nil {
-               return "", errors.New("cannot find go tool: " + err.Error())
-       }
-       return goBin, nil
+       goToolOnce.Do(func() {
+               goToolPath, goToolErr = func() (string, error) {
+                       if !HasGoBuild() {
+                               return "", errors.New("platform cannot run go tool")
+                       }
+                       var exeSuffix string
+                       if runtime.GOOS == "windows" {
+                               exeSuffix = ".exe"
+                       }
+                       goroot, err := findGOROOT()
+                       if err != nil {
+                               return "", fmt.Errorf("cannot find go tool: %w", err)
+                       }
+                       path := filepath.Join(goroot, "bin", "go"+exeSuffix)
+                       if _, err := os.Stat(path); err == nil {
+                               return path, nil
+                       }
+                       goBin, err := exec.LookPath("go" + exeSuffix)
+                       if err != nil {
+                               return "", errors.New("cannot find go tool: " + err.Error())
+                       }
+                       return goBin, nil
+               }()
+       })
+
+       return goToolPath, goToolErr
 }
 
+var (
+       goToolOnce sync.Once
+       goToolPath string
+       goToolErr  error
+)
+
 // HasSrc reports whether the entire source tree is available under GOROOT.
 func HasSrc() bool {
        switch runtime.GOOS {
@@ -242,16 +254,34 @@ func MustHaveExternalNetwork(t testing.TB) {
        }
 }
 
-var haveCGO bool
-
 // HasCGO reports whether the current system can use cgo.
 func HasCGO() bool {
-       return haveCGO
+       hasCgoOnce.Do(func() {
+               goTool, err := GoTool()
+               if err != nil {
+                       return
+               }
+               cmd := exec.Command(goTool, "env", "CGO_ENABLED")
+               out, err := cmd.Output()
+               if err != nil {
+                       panic(fmt.Sprintf("%v: %v", cmd, out))
+               }
+               hasCgo, err = strconv.ParseBool(string(bytes.TrimSpace(out)))
+               if err != nil {
+                       panic(fmt.Sprintf("%v: non-boolean output %q", cmd, out))
+               }
+       })
+       return hasCgo
 }
 
+var (
+       hasCgoOnce sync.Once
+       hasCgo     bool
+)
+
 // MustHaveCGO calls t.Skip if cgo is not available.
 func MustHaveCGO(t testing.TB) {
-       if !haveCGO {
+       if !HasCGO() {
                t.Skipf("skipping test: no cgo")
        }
 }
diff --git a/src/internal/testenv/testenv_cgo.go b/src/internal/testenv/testenv_cgo.go
deleted file mode 100644 (file)
index 7426a29..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-//go:build cgo
-
-package testenv
-
-func init() {
-       haveCGO = true
-}