@ -23,11 +23,11 @@ import (
"os"
"os"
"os/exec"
"os/exec"
"path/filepath"
"path/filepath"
"regexp"
"runtime"
"runtime"
"runtime/debug"
"runtime/debug"
"strconv"
"strconv"
"strings"
"strings"
"time"
"unicode"
"unicode"
"unicode/utf8"
"unicode/utf8"
@ -248,15 +248,12 @@ func (e errJustExit) Error() string { return fmt.Sprintf("exit: %d", e) }
func goVersionOK ( ) bool {
func goVersionOK ( ) bool {
const (
const (
minGoVersionSemver = "v1.16.0"
minGoVersionSemver = "v1.17.0"
suggestedGoVersion = "1.16.x"
suggestedGoVersion = "1.17.x"
gitTimeFormat = "Mon Jan 2 15:04:05 2006 -0700"
)
)
// Go 1.16 was released on Febuary 16th, 2021.
minGoVersionDate := time . Date ( 2021 , 2 , 16 , 0 , 0 , 0 , 0 , time . UTC )
version := cache . GoEnv . GOVERSION
rxVersion := regexp . MustCompile ( ` go\d+\.\d+(\.\d)? ` )
version := rxVersion . FindString ( cache . GoEnv . GOVERSION )
if version == "" {
if version == "" {
// Go 1.15.x and older do not have GOVERSION yet.
// Go 1.15.x and older do not have GOVERSION yet.
// We could go the extra mile and fetch it via 'go version',
// We could go the extra mile and fetch it via 'go version',
@ -265,37 +262,6 @@ func goVersionOK() bool {
return false
return false
}
}
if strings . HasPrefix ( version , "devel " ) {
commitAndDate := strings . TrimPrefix ( version , "devel " )
// Remove commit hash and architecture from version
startDateIdx := strings . IndexByte ( commitAndDate , ' ' ) + 1
if startDateIdx < 0 {
// Custom version; assume the user knows what they're doing.
// TODO: cover this in a test
return true
}
// TODO: once we support Go 1.17 and later, use the major Go
// version included in its devel versions:
//
// go version devel go1.17-8518aac314 ...
date := commitAndDate [ startDateIdx : ]
versionDate , err := time . Parse ( gitTimeFormat , date )
if err != nil {
// Custom version; assume the user knows what they're doing.
return true
}
if versionDate . After ( minGoVersionDate ) {
return true
}
fmt . Fprintf ( os . Stderr , "Go version %q is too old; please upgrade to Go %s or a newer devel version\n" , version , suggestedGoVersion )
return false
}
versionSemver := "v" + strings . TrimPrefix ( version , "go" )
versionSemver := "v" + strings . TrimPrefix ( version , "go" )
if semver . Compare ( versionSemver , minGoVersionSemver ) < 0 {
if semver . Compare ( versionSemver , minGoVersionSemver ) < 0 {
fmt . Fprintf ( os . Stderr , "Go version %q is too old; please upgrade to Go %s\n" , version , suggestedGoVersion )
fmt . Fprintf ( os . Stderr , "Go version %q is too old; please upgrade to Go %s\n" , version , suggestedGoVersion )
@ -369,23 +335,6 @@ func mainErr(args []string) error {
toolexecImportPath := os . Getenv ( "TOOLEXEC_IMPORTPATH" )
toolexecImportPath := os . Getenv ( "TOOLEXEC_IMPORTPATH" )
// Workaround for https://github.com/golang/go/issues/44963.
// TODO(mvdan): remove once we only support Go 1.17 and later.
if tool == "compile" && ! strings . Contains ( toolexecImportPath , ".test]" ) {
isTestPkg := false
_ , paths := splitFlagsFromFiles ( args , ".go" )
for _ , path := range paths {
if strings . HasSuffix ( path , "_test.go" ) {
isTestPkg = true
break
}
}
if isTestPkg {
forPkg := strings . TrimSuffix ( toolexecImportPath , "_test" )
toolexecImportPath = fmt . Sprintf ( "%s [%s.test]" , toolexecImportPath , forPkg )
}
}
curPkg = cache . ListedPackages [ toolexecImportPath ]
curPkg = cache . ListedPackages [ toolexecImportPath ]
if curPkg == nil {
if curPkg == nil {
return fmt . Errorf ( "TOOLEXEC_IMPORTPATH not found in listed packages: %s" , toolexecImportPath )
return fmt . Errorf ( "TOOLEXEC_IMPORTPATH not found in listed packages: %s" , toolexecImportPath )
@ -673,10 +622,9 @@ func transformCompile(args []string) ([]string, error) {
return nil , err
return nil , err
}
}
if ( curPkg . ImportPath == "runtime" && opts . Tiny ) || curPkg . ImportPath == "runtime/internal/sys" {
if curPkg . ImportPath == "runtime" && opts . Tiny {
// Even though these packages aren't private, we will still process
// When using -tiny, we call stripRuntime below.
// them later to remove build information and strip code from the
// We don't want -literals and -debugdir to apply, though.
// runtime. However, we only want flags to work on private packages.
opts . GarbleLiterals = false
opts . GarbleLiterals = false
opts . DebugDir = ""
opts . DebugDir = ""
} else if ! curPkg . Private {
} else if ! curPkg . Private {
@ -706,29 +654,9 @@ func transformCompile(args []string) ([]string, error) {
for i , file := range files {
for i , file := range files {
name := filepath . Base ( paths [ i ] )
name := filepath . Base ( paths [ i ] )
switch curPkg . ImportPath {
if curPkg . ImportPath == "runtime" && opts . Tiny {
case "runtime" :
// strip unneeded runtime code
// strip unneeded runtime code
stripRuntime ( name , file )
stripRuntime ( name , file )
case "runtime/internal/sys" :
// The first declaration in zversion.go contains the Go
// version as follows. Replace it here, since the
// linker's -X does not work with constants.
//
// const TheVersion = `devel ...`
//
// Don't touch the source in any other way.
// TODO: remove once we only support Go 1.17 and later,
// as from that point we can just rely on linking -X flags.
if name != "zversion.go" {
break
}
spec := file . Decls [ 0 ] . ( * ast . GenDecl ) . Specs [ 0 ] . ( * ast . ValueSpec )
if len ( spec . Names ) != 1 || spec . Names [ 0 ] . Name != "TheVersion" {
break
}
lit := spec . Values [ 0 ] . ( * ast . BasicLit )
lit . Value = "`unknown`"
}
}
if strings . HasPrefix ( name , "_cgo_" ) {
if strings . HasPrefix ( name , "_cgo_" ) {
// Don't obfuscate cgo code, since it's generated and it gets messy.
// Don't obfuscate cgo code, since it's generated and it gets messy.
@ -848,7 +776,7 @@ func (tf *transformer) handleDirectives(comments []*ast.CommentGroup) {
// Once we support go:linkname well and once we can obfuscate the runtime
// Once we support go:linkname well and once we can obfuscate the runtime
// package, this entire map can likely go away.
// package, this entire map can likely go away.
//
//
// The list was obtained via scripts/runtime-related.sh on Go 1.1 6 .
// The list was obtained via scripts/runtime-related.sh on Go 1.1 7 .
var runtimeRelated = map [ string ] bool {
var runtimeRelated = map [ string ] bool {
"bufio" : true ,
"bufio" : true ,
"bytes" : true ,
"bytes" : true ,
@ -861,9 +789,12 @@ var runtimeRelated = map[string]bool{
"fmt" : true ,
"fmt" : true ,
"hash" : true ,
"hash" : true ,
"hash/crc32" : true ,
"hash/crc32" : true ,
"internal/abi" : true ,
"internal/bytealg" : true ,
"internal/bytealg" : true ,
"internal/cpu" : true ,
"internal/cpu" : true ,
"internal/fmtsort" : true ,
"internal/fmtsort" : true ,
"internal/goexperiment" : true ,
"internal/itoa" : true ,
"internal/nettrace" : true ,
"internal/nettrace" : true ,
"internal/oserror" : true ,
"internal/oserror" : true ,
"internal/poll" : true ,
"internal/poll" : true ,
@ -910,11 +841,6 @@ var runtimeRelated = map[string]bool{
"unsafe" : true ,
"unsafe" : true ,
"vendor/golang.org/x/net/dns/dnsmessage" : true ,
"vendor/golang.org/x/net/dns/dnsmessage" : true ,
"vendor/golang.org/x/net/route" : true ,
"vendor/golang.org/x/net/route" : true ,
// Manual additions for Go 1.17 as of June 2021.
"internal/abi" : true ,
"internal/itoa" : true ,
"internal/goexperiment" : true ,
}
}
// isPrivate checks if a package import path should be considered private,
// isPrivate checks if a package import path should be considered private,
@ -1791,7 +1717,7 @@ func alterTrimpath(flags []string) []string {
return flagSetValue ( flags , "-trimpath" , sharedTempDir + "=>;" + trimpath )
return flagSetValue ( flags , "-trimpath" , sharedTempDir + "=>;" + trimpath )
}
}
// buildFlags is obtained from 'go help build' as of Go 1.1 6 .
// buildFlags is obtained from 'go help build' as of Go 1.1 7 .
var buildFlags = map [ string ] bool {
var buildFlags = map [ string ] bool {
"-a" : true ,
"-a" : true ,
"-n" : true ,
"-n" : true ,
@ -1819,7 +1745,7 @@ var buildFlags = map[string]bool{
"-overlay" : true ,
"-overlay" : true ,
}
}
// booleanFlags is obtained from 'go help build' and 'go help testflag' as of Go 1.1 6 .
// booleanFlags is obtained from 'go help build' and 'go help testflag' as of Go 1.1 7 .
var booleanFlags = map [ string ] bool {
var booleanFlags = map [ string ] bool {
// Shared build flags.
// Shared build flags.
"-a" : true ,
"-a" : true ,