// a space-separated list of build tags to consider satisfied during the
// build. For more information about build tags, see the description of
// build constraints in the documentation for the go/build package.
+// -trimpath
+// remove all file system paths from the resulting executable.
+// Instead of absolute file system paths, the recorded file names
+// will begin with either "go" (for the standard library),
+// or a module path@version (when using modules),
+// or a plain import path (when using GOPATH).
// -toolexec 'cmd args'
// a program to use to invoke toolchain programs like vet and asm.
// For example, instead of running asm, the go command will run
BuildToolchainName string
BuildToolchainCompiler func() string
BuildToolchainLinker func() string
+ BuildTrimpath bool // -trimpath flag
BuildV bool // -v flag
BuildWork bool // -work flag
BuildX bool // -x flag
a space-separated list of build tags to consider satisfied during the
build. For more information about build tags, see the description of
build constraints in the documentation for the go/build package.
+ -trimpath
+ remove all file system paths from the resulting executable.
+ Instead of absolute file system paths, the recorded file names
+ will begin with either "go" (for the standard library),
+ or a module path@version (when using modules),
+ or a plain import path (when using GOPATH).
-toolexec 'cmd args'
a program to use to invoke toolchain programs like vet and asm.
For example, instead of running asm, the go command will run
cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
+ cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "")
cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
// Undocumented, unstable debugging flags.
q := strconv.Quote(s)
// A gccgo command line can contain -( and -).
// Make sure we quote them since they are special to the shell.
- if s == "" || strings.ContainsAny(s, " ()") || len(q) > len(s)+2 {
+ // The trimpath argument can also contain > (part of =>) and ;. Quote those too.
+ if s == "" || strings.ContainsAny(s, " ()>;") || len(q) > len(s)+2 {
buf.WriteString(q)
} else {
buf.WriteString(s)
}
}
- args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", trimDir(a.Objdir), gcflags, gcargs, "-D", p.Internal.LocalPrefix}
+ args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs, "-D", p.Internal.LocalPrefix}
if importcfg != nil {
if err := b.writeFile(objdir+"importcfg", importcfg); err != nil {
return "", nil, err
return c
}
-func trimDir(dir string) string {
- if len(dir) > 1 && dir[len(dir)-1] == filepath.Separator {
- dir = dir[:len(dir)-1]
+// trimpath returns the -trimpath argument to use
+// when compiling the action.
+func (a *Action) trimpath() string {
+ // Strip the object directory entirely.
+ objdir := a.Objdir
+ if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator {
+ objdir = objdir[:len(objdir)-1]
}
- return dir
+ rewrite := objdir + "=>"
+
+ // For "go build -trimpath", rewrite package source directory
+ // to a file system-independent path (just the import path).
+ if cfg.BuildTrimpath {
+ if m := a.Package.Module; m != nil {
+ rewrite += ";" + m.Dir + "=>" + m.Path + "@" + m.Version
+ } else {
+ rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
+ }
+ }
+
+ return rewrite
}
func asmArgs(a *Action, p *load.Package) []interface{} {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(cfg.GOROOT, "pkg", "include")
- args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", trimDir(a.Objdir), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags}
+ args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", a.trimpath(), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags}
if p.ImportPath == "runtime" && cfg.Goarch == "386" {
for _, arg := range forcedAsmflags {
if arg == "-dynlink" {
dir, out = filepath.Split(out)
}
- return b.run(root, dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags, mainpkg)
+ env := []string{}
+ if cfg.BuildTrimpath {
+ env = append(env, "GOROOT_FINAL=go")
+ }
+ return b.run(root, dir, root.Package.ImportPath, env, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags, mainpkg)
}
func (gcToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
if neg {
ts.fatalf("unsupported: ! env")
}
+
+ conv := func(s string) string { return s }
+ if len(args) > 0 && args[0] == "-r" {
+ conv = regexp.QuoteMeta
+ args = args[1:]
+ }
+
if len(args) == 0 {
printed := make(map[string]bool) // env list can have duplicates; only print effective value (from envMap) once
for _, kv := range ts.env {
fmt.Fprintf(&ts.log, "%s=%s\n", env, ts.envMap[env])
continue
}
- ts.env = append(ts.env, env)
- ts.envMap[env[:i]] = env[i+1:]
+ key, val := env[:i], conv(env[i+1:])
+ ts.env = append(ts.env, key+"="+val)
+ ts.envMap[key] = val
}
}
}
args = args[1:]
}
+ quiet := false
+ if len(args) >= 1 && args[0] == "-q" {
+ quiet = true
+ args = args[1:]
+ }
extraUsage := ""
want := 1
if neg {
if re.MatchString(text) {
- if isGrep {
+ if isGrep && !quiet {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("unexpected match for %#q found in %s: %s", pattern, name, re.FindString(text))
}
} else {
if !re.MatchString(text) {
- if isGrep {
+ if isGrep && !quiet {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("no match for %#q found in %s", pattern, name)
if n > 0 {
count := len(re.FindAllString(text, -1))
if count != n {
- if isGrep {
+ if isGrep && !quiet {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("have %d matches for %#q, want %d", count, pattern, n)
src can include "stdout" or "stderr" to use the standard output or standard error
from the most recent exec or go command.
-- env [key=value...]
+- env [-r] [key=value...]
With no arguments, print the environment (useful for debugging).
Otherwise add the listed key=value pairs to the environment.
+ The -r flag causes the values to be escaped using regexp.QuoteMeta
+ before being recorded.
- [!] exec program [args...] [&]
Run the given executable program with the arguments.
Run the (test copy of the) go command with the given arguments.
It must (or must not) succeed.
-- [!] grep [-count=N] pattern file
+- [!] grep [-count=N] [-q] pattern file
The file's content must (or must not) match the regular expression pattern.
For positive matches, -count=N specifies an exact number of matches to require.
+ The -q flag disables printing the file content on a mismatch.
- mkdir path...
Create the listed directories, if they do not already exists.
--- /dev/null
+env -r GOROOT_REGEXP=$GOROOT
+env -r WORK_REGEXP=$WORK
+env GOROOT GOROOT_REGEXP WORK WORK_REGEXP
+
+go build -trimpath -o hello.exe hello.go
+! grep -q $GOROOT_REGEXP hello.exe
+! grep -q $WORK_REGEXP hello.exe
+
+env GO111MODULE=on
+go build -trimpath -o fortune.exe rsc.io/fortune
+! grep -q $GOROOT_REGEXP fortune.exe
+! grep -q $WORK_REGEXP fortune.exe
+
+-- hello.go --
+package main
+func main() { println("hello") }
+
+-- go.mod --
+module m