Skip to content

Commit 7d6517c

Browse files
Bryan C. Millsprattmic
Bryan C. Mills
authored andcommitted
[release-branch.go1.19] cmd/go/internal/work: make formatOutput return an error that includes the import path
This refines the error output that was previously adjusted in CL 437298. Longer term, we should consider unraveling the call chains involving formatOutput to avoid passing so many parameters through so many different formatting functions. Updates #60710. Updates #60650. Updates #25842. Change-Id: I3b9d03bf5968902d8ccc4841ab4dbe114a2239e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/451218 Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Russ Cox <[email protected]> Reviewed-by: Russ Cox <[email protected]> Run-TryBot: Russ Cox <[email protected]> Reviewed-by: Than McIntosh <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/502196 Reviewed-by: Dmitri Shuralyov <[email protected]> TryBot-Bypass: Bryan Mills <[email protected]> Run-TryBot: Bryan Mills <[email protected]> Reviewed-by: Michael Matloob <[email protected]>
1 parent c045822 commit 7d6517c

File tree

4 files changed

+72
-31
lines changed

4 files changed

+72
-31
lines changed

src/cmd/go/internal/work/exec.go

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,15 @@ func (b *Builder) Do(ctx context.Context, root *Action) {
149149
defer b.exec.Unlock()
150150

151151
if err != nil {
152-
if b.AllowErrors {
152+
if b.AllowErrors && a.Package != nil {
153153
if a.Package.Error == nil {
154154
a.Package.Error = &load.PackageError{Err: err}
155155
}
156156
} else {
157+
var ipe load.ImportPathError
158+
if a.Package != nil && (!errors.As(err, &ipe) || ipe.ImportPath() != a.Package.ImportPath) {
159+
err = fmt.Errorf("%s: %v", a.Package.ImportPath, err)
160+
}
157161
base.Errorf("%s", err)
158162
}
159163
a.Failed = true
@@ -510,9 +514,6 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) {
510514
}
511515

512516
defer func() {
513-
if err != nil {
514-
err = fmt.Errorf("go build %s: %v", p.ImportPath, err)
515-
}
516517
if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
517518
p.Error = &load.PackageError{Err: err}
518519
}
@@ -825,7 +826,7 @@ OverlayLoop:
825826
}
826827

827828
if err != nil {
828-
return errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), output)))
829+
return formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), output)
829830
} else {
830831
b.showOutput(a, p.Dir, p.Desc(), output)
831832
}
@@ -1506,8 +1507,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
15061507
var out []byte
15071508
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
15081509
if err != nil {
1509-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1510-
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
1510+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)+err.Error())
1511+
return nil, nil, err
15111512
}
15121513
if len(out) > 0 {
15131514
cflags, err = splitPkgConfigOutput(out)
@@ -1520,8 +1521,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
15201521
}
15211522
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
15221523
if err != nil {
1523-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1524-
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
1524+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)+err.Error())
1525+
return nil, nil, err
15251526
}
15261527
if len(out) > 0 {
15271528
// NOTE: we don't attempt to parse quotes and unescapes here. pkg-config
@@ -2017,16 +2018,37 @@ func (b *Builder) Showcmd(dir string, format string, args ...any) {
20172018
// If a is not nil and a.output is not nil, showOutput appends to that slice instead of
20182019
// printing to b.Print.
20192020
func (b *Builder) showOutput(a *Action, dir, desc, out string) {
2020-
prefix, suffix := formatOutput(b.WorkDir, dir, desc, out)
2021+
importPath := ""
2022+
if a != nil && a.Package != nil {
2023+
importPath = a.Package.ImportPath
2024+
}
2025+
psErr := formatOutput(b.WorkDir, dir, importPath, desc, out)
20212026
if a != nil && a.output != nil {
2022-
a.output = append(a.output, prefix...)
2023-
a.output = append(a.output, suffix...)
2027+
a.output = append(a.output, psErr.prefix...)
2028+
a.output = append(a.output, psErr.suffix...)
20242029
return
20252030
}
20262031

20272032
b.output.Lock()
20282033
defer b.output.Unlock()
2029-
b.Print(prefix, suffix)
2034+
b.Print(psErr.prefix, psErr.suffix)
2035+
}
2036+
2037+
// A prefixSuffixError is an error formatted by formatOutput.
2038+
type prefixSuffixError struct {
2039+
importPath string
2040+
prefix, suffix string
2041+
}
2042+
2043+
func (e *prefixSuffixError) Error() string {
2044+
if e.importPath != "" && !strings.HasPrefix(strings.TrimPrefix(e.prefix, "# "), e.importPath) {
2045+
return fmt.Sprintf("go build %s:\n%s%s", e.importPath, e.prefix, e.suffix)
2046+
}
2047+
return e.prefix + e.suffix
2048+
}
2049+
2050+
func (e *prefixSuffixError) ImportPath() string {
2051+
return e.importPath
20302052
}
20312053

20322054
// formatOutput prints "# desc" followed by the given output.
@@ -2052,17 +2074,17 @@ func (b *Builder) showOutput(a *Action, dir, desc, out string) {
20522074
// formatOutput also replaces references to the work directory with $WORK.
20532075
// formatOutput returns the output in a prefix with the description and a
20542076
// suffix with the actual output.
2055-
func formatOutput(workDir, dir, desc, out string) (prefix, suffix string) {
2056-
prefix = "# " + desc
2057-
suffix = "\n" + out
2077+
func formatOutput(workDir, dir, importPath, desc, out string) *prefixSuffixError {
2078+
prefix := "# " + desc
2079+
suffix := "\n" + out
20582080
if reldir := base.ShortPath(dir); reldir != dir {
20592081
suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
20602082
suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
20612083
suffix = strings.ReplaceAll(suffix, "\n\t"+dir, "\n\t"+reldir)
20622084
}
20632085
suffix = strings.ReplaceAll(suffix, " "+workDir, " $WORK")
20642086

2065-
return prefix, suffix
2087+
return &prefixSuffixError{importPath: importPath, prefix: prefix, suffix: suffix}
20662088
}
20672089

20682090
var cgoLine = lazyregexp.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
@@ -2078,7 +2100,7 @@ func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs
20782100
desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
20792101
}
20802102
if err != nil {
2081-
err = errors.New(fmt.Sprint(formatOutput(b.WorkDir, dir, desc, b.processOutput(out))))
2103+
err = formatOutput(b.WorkDir, dir, a.Package.ImportPath, desc, b.processOutput(out))
20822104
} else {
20832105
b.showOutput(a, dir, desc, b.processOutput(out))
20842106
}
@@ -2364,7 +2386,6 @@ func (b *Builder) gfortran(a *Action, p *load.Package, workdir, out string, flag
23642386
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
23652387
func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []string, file string, compiler []string) error {
23662388
file = mkAbs(p.Dir, file)
2367-
desc := p.ImportPath
23682389
outfile = mkAbs(p.Dir, outfile)
23692390

23702391
// Elide source directory paths if -trimpath or GOROOT_FINAL is set.
@@ -2425,9 +2446,9 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
24252446
}
24262447

24272448
if err != nil || os.Getenv("GO_BUILDER_NAME") != "" {
2428-
err = errors.New(fmt.Sprintf(formatOutput(b.WorkDir, p.Dir, desc, b.processOutput(output))))
2449+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), b.processOutput(output))
24292450
} else {
2430-
b.showOutput(a, p.Dir, desc, b.processOutput(output))
2451+
b.showOutput(a, p.Dir, p.Desc(), b.processOutput(output))
24312452
}
24322453
}
24332454
return err
@@ -2890,8 +2911,6 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
28902911
cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h")
28912912
}
28922913

2893-
execdir := p.Dir
2894-
28952914
// Rewrite overlaid paths in cgo files.
28962915
// cgo adds //line and #line pragmas in generated files with these paths.
28972916
var trimpath []string
@@ -2906,7 +2925,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
29062925
cgoflags = append(cgoflags, "-trimpath", strings.Join(trimpath, ";"))
29072926
}
29082927

2909-
if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
2928+
if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
29102929
return nil, nil, err
29112930
}
29122931
outGo = append(outGo, gofiles...)
@@ -3382,7 +3401,7 @@ func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFL
33823401
return "", "", errors.New("must have SWIG version >= 3.0.6")
33833402
}
33843403
// swig error
3385-
return "", "", errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), b.processOutput(out))))
3404+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), b.processOutput(out))
33863405
}
33873406
return "", "", err
33883407
}

src/cmd/go/internal/work/gc.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package work
77
import (
88
"bufio"
99
"bytes"
10-
"errors"
1110
"fmt"
1211
"io"
1312
"log"
@@ -503,7 +502,7 @@ func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) er
503502
return nil
504503
}
505504
if err := packInternal(absAfile, absOfiles); err != nil {
506-
return errors.New(fmt.Sprint(formatOutput(b.WorkDir, p.Dir, p.Desc(), err.Error()+"\n")))
505+
return formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), err.Error()+"\n")
507506
}
508507
return nil
509508
}

src/cmd/go/testdata/script/list_export_e.txt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1-
go list -e -export ./...
1+
! go list -export ./...
2+
stderr '^# example.com/p2\np2'${/}'main\.go:7:.*'
3+
! stderr '^go build '
4+
5+
go list -f '{{with .Error}}{{.}}{{end}}' -e -export ./...
26
! stderr '.'
3-
go list -e -export -json ...
7+
stdout '^# example.com/p2\np2'${/}'main\.go:7:.*'
8+
9+
go list -e -export -json=Error ./...
10+
stdout '"Err": "# example.com/p2'
411

512
-- go.mod --
613
module example.com
@@ -15,5 +22,5 @@ import "fmt"
1522
import "example.com/p1"
1623

1724
func main() {
18-
fmt.Println(p1.Name == 5)
19-
}
25+
fmt.Println(p1.Name == 5)
26+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[!cgo] skip 'test verifies cgo pkg-config errors'
2+
[!exec:pkg-config] skip 'test requires pkg-config tool'
3+
4+
! go list -export .
5+
stderr '^go build example:\n# pkg-config (.*\n)+pkg-config: exit status \d+$'
6+
7+
-- go.mod --
8+
module example
9+
go 1.20
10+
-- example.go --
11+
package example
12+
13+
// #cgo pkg-config: libnot-a-valid-cgo-library
14+
import "C"
15+
16+
package main() {}

0 commit comments

Comments
 (0)