mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/go: print toolchain switching with GODEBUG=toolchaintrace
This CL introduces the ability to print information about the toolchain switch used in the go command, controlled by the `toolchaintrace` setting. This setting defaults to `toolchaintrace=0`, meaning no information is printed. Setting it to `toolchaintrace=1` will cause the go command to print a message indicating the toolchain used and where it was found. Fixes: #63939 Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest Change-Id: Idc58e3d5bc76573aa48e1f7df352caa13004c25e Reviewed-on: https://go-review.googlesource.com/c/go/+/610235 Reviewed-by: Michael Matloob <matloob@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
e190638f20
commit
c71b5ff76a
@ -8,6 +8,7 @@ package toolchain
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
|
"fmt"
|
||||||
"internal/godebug"
|
"internal/godebug"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -26,6 +27,13 @@ func execGoToolchain(gotoolchain, dir, exe string) {
|
|||||||
} else {
|
} else {
|
||||||
os.Setenv("GOROOT", dir)
|
os.Setenv("GOROOT", dir)
|
||||||
}
|
}
|
||||||
|
if toolchainTrace {
|
||||||
|
if dir == "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "go: using %s toolchain located in system PATH (%s)\n", gotoolchain, exe)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "go: using %s toolchain from cache located at %s\n", gotoolchain, exe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// On Windows, there is no syscall.Exec, so the best we can do
|
// On Windows, there is no syscall.Exec, so the best we can do
|
||||||
// is run a subprocess and exit with the same status.
|
// is run a subprocess and exit with the same status.
|
||||||
|
@ -6,11 +6,14 @@
|
|||||||
package toolchain
|
package toolchain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
"internal/godebug"
|
||||||
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -84,6 +87,7 @@ func FilterEnv(env []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var counterErrorsInvalidToolchainInFile = counter.New("go/errors:invalid-toolchain-in-file")
|
var counterErrorsInvalidToolchainInFile = counter.New("go/errors:invalid-toolchain-in-file")
|
||||||
|
var toolchainTrace = godebug.New("#toolchaintrace").Value() == "1"
|
||||||
|
|
||||||
// Select invokes a different Go toolchain if directed by
|
// Select invokes a different Go toolchain if directed by
|
||||||
// the GOTOOLCHAIN environment variable or the user's configuration
|
// the GOTOOLCHAIN environment variable or the user's configuration
|
||||||
@ -137,6 +141,7 @@ func Select() {
|
|||||||
minToolchain := gover.LocalToolchain()
|
minToolchain := gover.LocalToolchain()
|
||||||
minVers := gover.Local()
|
minVers := gover.Local()
|
||||||
var mode string
|
var mode string
|
||||||
|
var toolchainTraceBuffer bytes.Buffer
|
||||||
if gotoolchain == "auto" {
|
if gotoolchain == "auto" {
|
||||||
mode = "auto"
|
mode = "auto"
|
||||||
} else if gotoolchain == "path" {
|
} else if gotoolchain == "path" {
|
||||||
@ -158,6 +163,9 @@ func Select() {
|
|||||||
base.Fatalf("invalid GOTOOLCHAIN %q: only version suffixes are +auto and +path", gotoolchain)
|
base.Fatalf("invalid GOTOOLCHAIN %q: only version suffixes are +auto and +path", gotoolchain)
|
||||||
}
|
}
|
||||||
mode = suffix
|
mode = suffix
|
||||||
|
if toolchainTrace {
|
||||||
|
fmt.Fprintf(&toolchainTraceBuffer, "go: default toolchain set to %s from GOTOOLCHAIN=%s\n", minToolchain, gotoolchain)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gotoolchain = minToolchain
|
gotoolchain = minToolchain
|
||||||
@ -190,6 +198,13 @@ func Select() {
|
|||||||
base.Fatalf("invalid toolchain %q in %s", toolchain, base.ShortPath(file))
|
base.Fatalf("invalid toolchain %q in %s", toolchain, base.ShortPath(file))
|
||||||
}
|
}
|
||||||
if gover.Compare(toolVers, minVers) > 0 {
|
if gover.Compare(toolVers, minVers) > 0 {
|
||||||
|
if toolchainTrace {
|
||||||
|
modeFormat := mode
|
||||||
|
if strings.Contains(cfg.Getenv("GOTOOLCHAIN"), "+") { // go1.2.3+auto
|
||||||
|
modeFormat = fmt.Sprintf("<name>+%s", mode)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&toolchainTraceBuffer, "go: upgrading toolchain to %s (required by toolchain line in %s; upgrade allowed by GOTOOLCHAIN=%s)\n", toolchain, base.ShortPath(file), modeFormat)
|
||||||
|
}
|
||||||
gotoolchain = toolchain
|
gotoolchain = toolchain
|
||||||
minVers = toolVers
|
minVers = toolVers
|
||||||
gover.Startup.AutoToolchain = toolchain
|
gover.Startup.AutoToolchain = toolchain
|
||||||
@ -206,6 +221,13 @@ func Select() {
|
|||||||
}
|
}
|
||||||
gover.Startup.AutoGoVersion = goVers
|
gover.Startup.AutoGoVersion = goVers
|
||||||
gover.Startup.AutoToolchain = "" // in case we are overriding it for being too old
|
gover.Startup.AutoToolchain = "" // in case we are overriding it for being too old
|
||||||
|
if toolchainTrace {
|
||||||
|
modeFormat := mode
|
||||||
|
if strings.Contains(cfg.Getenv("GOTOOLCHAIN"), "+") { // go1.2.3+auto
|
||||||
|
modeFormat = fmt.Sprintf("<name>+%s", mode)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&toolchainTraceBuffer, "go: upgrading toolchain to %s (required by go line in %s; upgrade allowed by GOTOOLCHAIN=%s)\n", gotoolchain, base.ShortPath(file), modeFormat)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,8 +259,16 @@ func Select() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if toolchainTrace {
|
||||||
|
// Flush toolchain tracing buffer only in the parent process (targetEnv is unset).
|
||||||
|
io.Copy(os.Stderr, &toolchainTraceBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
if gotoolchain == "local" || gotoolchain == gover.LocalToolchain() {
|
if gotoolchain == "local" || gotoolchain == gover.LocalToolchain() {
|
||||||
// Let the current binary handle the command.
|
// Let the current binary handle the command.
|
||||||
|
if toolchainTrace {
|
||||||
|
fmt.Fprintf(os.Stderr, "go: using local toolchain %s\n", gover.LocalToolchain())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
122
src/cmd/go/testdata/script/gotoolchain_godebug_trace.txt
vendored
Normal file
122
src/cmd/go/testdata/script/gotoolchain_godebug_trace.txt
vendored
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
# Test the GODEBUG=toolchaintrace behavior
|
||||||
|
# See https://go.dev/issue/63939
|
||||||
|
env GODEBUG=toolchaintrace=1
|
||||||
|
env TESTGO_VERSION=go1.21.0
|
||||||
|
env TESTGO_VERSION_SWITCH=switch
|
||||||
|
env GOTOOLCHAIN=auto
|
||||||
|
|
||||||
|
# Go line is newer than local go version.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.21.1
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.21.1 \(required by go line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
|
||||||
|
stderr -count=1 'go: using go1.21.1 toolchain from cache located at .*'
|
||||||
|
stdout 'go version go1.21.1'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
# Toolchain line is newer than go line.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.21.1 -toolchain=go1.21.2
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.21.2 \(required by toolchain line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
|
||||||
|
stderr -count=1 'go: using go1.21.2 toolchain from cache located at .*'
|
||||||
|
stdout 'go version go1.21.2'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
# Go line is newer than local go version and toolchain line.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.22 -toolchain=go1.21.2
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.21.2 \(required by toolchain line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.22.0 \(required by go line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
|
||||||
|
stderr -count=1 'go: using go1.22.0 toolchain from cache located at .*'
|
||||||
|
stdout 'go version go1.22.0'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
# No switch.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.21.0 -toolchain=go1.21.0
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: using local toolchain go1.21.0'
|
||||||
|
! stderr 'go: upgrading toolchain'
|
||||||
|
stdout 'go version go1.21.0'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
# GOTOOLCHAIN+auto is older than go line and toolchain line.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.22 -toolchain=go1.21.2
|
||||||
|
env GOTOOLCHAIN=go1.21.0+auto
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: default toolchain set to go1.21.0 from GOTOOLCHAIN=go1.21.0\+auto'
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.21.2 \(required by toolchain line in go.mod; upgrade allowed by GOTOOLCHAIN=<name>\+auto\)'
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.22.0 \(required by go line in go.mod; upgrade allowed by GOTOOLCHAIN=<name>\+auto\)'
|
||||||
|
stderr -count=1 'go: using go1.22.0 toolchain from cache located at .*'
|
||||||
|
stdout 'go version go1.22.0'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
# GOTOOLCHAIN is older than go line and toolchain line.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.22 -toolchain=go1.21.2
|
||||||
|
env GOTOOLCHAIN=go1.21.1
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: default toolchain set to go1.21.1 from GOTOOLCHAIN=go1.21.1'
|
||||||
|
stderr -count=1 'go: using go1.21.1 toolchain from cache located at .*'
|
||||||
|
! stderr 'go: upgrading toolchain'
|
||||||
|
stdout 'go version go1.21.1'
|
||||||
|
rm go.mod
|
||||||
|
env GOTOOLCHAIN=auto
|
||||||
|
|
||||||
|
# GOTOOLCHAIN+auto is newer than go line and toolchain line.
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.21.1 -toolchain=go1.21.2
|
||||||
|
env GOTOOLCHAIN=go1.22.0+auto
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: default toolchain set to go1.22.0 from GOTOOLCHAIN=go1.22.0\+auto'
|
||||||
|
stderr -count=1 'go: using go1.22.0 toolchain from cache located at .*'
|
||||||
|
stdout 'go version go1.22.0'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
# GOTOOLCHAIN=local
|
||||||
|
env GOTOOLCHAIN=local
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.21.1 -toolchain=go1.21.2
|
||||||
|
go version
|
||||||
|
stderr -count=1 'go: default toolchain set to go1.21.0 from GOTOOLCHAIN=local'
|
||||||
|
stderr -count=1 'go: using local toolchain go1.21.0'
|
||||||
|
stdout 'go version go1.21.0'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
[short] stop 'requires build'
|
||||||
|
# If toolchain found in PATH, ensure we print that.
|
||||||
|
env GOTOOLCHAIN=auto
|
||||||
|
env TESTGO_VERSION_SWITCH=
|
||||||
|
mkdir $WORK/bin
|
||||||
|
go build -o $WORK/bin/go1.22.0$GOEXE ./fake/fakego.go # adds .exe extension implicitly on Windows
|
||||||
|
[!GOOS:plan9] env PATH=$WORK/bin
|
||||||
|
[GOOS:plan9] env path=$WORK/bin
|
||||||
|
go mod init m
|
||||||
|
go mod edit -go=1.22.0
|
||||||
|
! go version
|
||||||
|
stderr -count=1 'go: upgrading toolchain to go1.22.0 \(required by go line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
|
||||||
|
stderr -count=1 'go: using go1.22.0 toolchain located in system PATH \('$WORK'[/\\]bin[/\\]go1.22.0'$GOEXE'\)'
|
||||||
|
stderr 'running go1.22.0 from PATH'
|
||||||
|
rm go.mod
|
||||||
|
|
||||||
|
|
||||||
|
-- fake/fakego.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
exe, _ := os.Executable()
|
||||||
|
name := filepath.Base(exe)
|
||||||
|
name = strings.TrimSuffix(name, ".exe")
|
||||||
|
fmt.Fprintf(os.Stderr, "running %s from PATH\n", name)
|
||||||
|
os.Exit(1) // fail in case we are running this accidentally (like in "go mod edit")
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user