From 71ad46cd2a4eb34befbb21c0a37b5a8092c2b7f5 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 10 Mar 2023 14:25:41 -0500 Subject: [PATCH] internal/testenv: allow 'go build' on android when supported As of CL 472096, it should work on android/arm64 always (because internal linking is supported on that platform), and on other android platforms when a C toolchain is present in the test environment. Updates #58775. Change-Id: Ifa38dc69b258b38dcc341979dcbf8cd61265c787 Reviewed-on: https://go-review.googlesource.com/c/go/+/475456 Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Auto-Submit: Bryan Mills Reviewed-by: Cherry Mui Reviewed-by: Changkun Ou --- src/internal/testenv/testenv.go | 63 ++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go index 9a649e037c..aeda1f964f 100644 --- a/src/internal/testenv/testenv.go +++ b/src/internal/testenv/testenv.go @@ -45,13 +45,62 @@ func HasGoBuild() bool { // run go build. return false } - switch runtime.GOOS { - case "android", "js", "ios", "wasip1": + + if !HasExec() { + // If we can't exec anything at all, we certainly can't exec 'go build'. return false } + + if platform.MustLinkExternal(runtime.GOOS, runtime.GOARCH, false) { + // We can assume that we always have a complete Go toolchain available. + // However, this platform requires a C linker to build even pure Go + // programs, including tests. Do we have one in the test environment? + // (On Android, for example, the device running the test might not have a + // C toolchain installed.) + // + // If CC is set explicitly, assume that we do. Otherwise, use 'go env CC' + // to determine which toolchain it would use by default. + if os.Getenv("CC") == "" { + if _, err := findCC(); err != nil { + return false + } + } + } + return true } +func findCC() (string, error) { + ccOnce.Do(func() { + goTool, err := findGoTool() + if err != nil { + ccErr = err + return + } + + cmd := exec.Command(goTool, "env", "CC") + out, err := cmd.Output() + out = bytes.TrimSpace(out) + if err != nil { + ccErr = fmt.Errorf("%v: %w", cmd, err) + return + } else if len(out) == 0 { + ccErr = fmt.Errorf("%v: no CC reported", cmd) + return + } + + cc := string(out) + ccPath, ccErr = exec.LookPath(cc) + }) + return ccPath, ccErr +} + +var ( + ccOnce sync.Once + ccPath string + ccErr error +) + // MustHaveGoBuild checks that the current system can build programs with “go build” // and then run them with os.StartProcess or exec.Command. // If not, MustHaveGoBuild calls t.Skip with an explanation. @@ -212,11 +261,15 @@ 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") + } + return findGoTool() +} + +func findGoTool() (string, error) { 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" -- 2.50.0