Skip to content

Commit af1a5d9

Browse files
Bryan C. Millsgopherbot
Bryan C. Mills
authored andcommitted
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 #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]>
1 parent e24380b commit af1a5d9

File tree

4 files changed

+72
-36
lines changed

4 files changed

+72
-36
lines changed

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

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

155155
if err != nil {
156-
if b.AllowErrors {
156+
if b.AllowErrors && a.Package != nil {
157157
if a.Package.Error == nil {
158158
a.Package.Error = &load.PackageError{Err: err}
159159
}
160160
} else {
161+
var ipe load.ImportPathError
162+
if a.Package != nil && (!errors.As(err, &ipe) || ipe.ImportPath() != a.Package.ImportPath) {
163+
err = fmt.Errorf("%s: %v", a.Package.ImportPath, err)
164+
}
161165
base.Errorf("%s", err)
162166
}
163167
a.Failed = true
@@ -495,9 +499,6 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) {
495499
}
496500

497501
defer func() {
498-
if err != nil {
499-
err = fmt.Errorf("go build %s: %v", p.ImportPath, err)
500-
}
501502
if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
502503
p.Error = &load.PackageError{Err: err}
503504
}
@@ -846,8 +847,7 @@ OverlayLoop:
846847
}
847848

848849
if err != nil {
849-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, p.Desc(), output)
850-
return errors.New(prefix + suffix)
850+
return formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), output)
851851
} else {
852852
b.showOutput(a, p.Dir, p.Desc(), output)
853853
}
@@ -1530,8 +1530,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
15301530
var out []byte
15311531
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
15321532
if err != nil {
1533-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1534-
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
1533+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)+err.Error())
1534+
return nil, nil, err
15351535
}
15361536
if len(out) > 0 {
15371537
cflags, err = splitPkgConfigOutput(out)
@@ -1544,8 +1544,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
15441544
}
15451545
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
15461546
if err != nil {
1547-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
1548-
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
1547+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)+err.Error())
1548+
return nil, nil, err
15491549
}
15501550
if len(out) > 0 {
15511551
// NOTE: we don't attempt to parse quotes and unescapes here. pkg-config
@@ -2093,16 +2093,37 @@ func (b *Builder) Showcmd(dir string, format string, args ...any) {
20932093
// If a is not nil and a.output is not nil, showOutput appends to that slice instead of
20942094
// printing to b.Print.
20952095
func (b *Builder) showOutput(a *Action, dir, desc, out string) {
2096-
prefix, suffix := formatOutput(b.WorkDir, dir, desc, out)
2096+
importPath := ""
2097+
if a != nil && a.Package != nil {
2098+
importPath = a.Package.ImportPath
2099+
}
2100+
psErr := formatOutput(b.WorkDir, dir, importPath, desc, out)
20972101
if a != nil && a.output != nil {
2098-
a.output = append(a.output, prefix...)
2099-
a.output = append(a.output, suffix...)
2102+
a.output = append(a.output, psErr.prefix...)
2103+
a.output = append(a.output, psErr.suffix...)
21002104
return
21012105
}
21022106

21032107
b.output.Lock()
21042108
defer b.output.Unlock()
2105-
b.Print(prefix, suffix)
2109+
b.Print(psErr.prefix, psErr.suffix)
2110+
}
2111+
2112+
// A prefixSuffixError is an error formatted by formatOutput.
2113+
type prefixSuffixError struct {
2114+
importPath string
2115+
prefix, suffix string
2116+
}
2117+
2118+
func (e *prefixSuffixError) Error() string {
2119+
if e.importPath != "" && !strings.HasPrefix(strings.TrimPrefix(e.prefix, "# "), e.importPath) {
2120+
return fmt.Sprintf("go build %s:\n%s%s", e.importPath, e.prefix, e.suffix)
2121+
}
2122+
return e.prefix + e.suffix
2123+
}
2124+
2125+
func (e *prefixSuffixError) ImportPath() string {
2126+
return e.importPath
21062127
}
21072128

21082129
// formatOutput prints "# desc" followed by the given output.
@@ -2128,17 +2149,17 @@ func (b *Builder) showOutput(a *Action, dir, desc, out string) {
21282149
// formatOutput also replaces references to the work directory with $WORK.
21292150
// formatOutput returns the output in a prefix with the description and a
21302151
// suffix with the actual output.
2131-
func formatOutput(workDir, dir, desc, out string) (prefix, suffix string) {
2132-
prefix = "# " + desc
2133-
suffix = "\n" + out
2152+
func formatOutput(workDir, dir, importPath, desc, out string) *prefixSuffixError {
2153+
prefix := "# " + desc
2154+
suffix := "\n" + out
21342155
if reldir := base.ShortPath(dir); reldir != dir {
21352156
suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
21362157
suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
21372158
suffix = strings.ReplaceAll(suffix, "\n\t"+dir, "\n\t"+reldir)
21382159
}
21392160
suffix = strings.ReplaceAll(suffix, " "+workDir, " $WORK")
21402161

2141-
return prefix, suffix
2162+
return &prefixSuffixError{importPath: importPath, prefix: prefix, suffix: suffix}
21422163
}
21432164

21442165
var cgoLine = lazyregexp.New(`\[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]`)
@@ -2154,8 +2175,7 @@ func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs
21542175
desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
21552176
}
21562177
if err != nil {
2157-
prefix, suffix := formatOutput(b.WorkDir, dir, desc, b.processOutput(out))
2158-
err = errors.New(prefix + suffix)
2178+
err = formatOutput(b.WorkDir, dir, a.Package.ImportPath, desc, b.processOutput(out))
21592179
} else {
21602180
b.showOutput(a, dir, desc, b.processOutput(out))
21612181
}
@@ -2441,7 +2461,6 @@ func (b *Builder) gfortran(a *Action, p *load.Package, workdir, out string, flag
24412461
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
24422462
func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []string, file string, compiler []string) error {
24432463
file = mkAbs(p.Dir, file)
2444-
desc := p.ImportPath
24452464
outfile = mkAbs(p.Dir, outfile)
24462465

24472466
// Elide source directory paths if -trimpath or GOROOT_FINAL is set.
@@ -2502,10 +2521,9 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
25022521
}
25032522

25042523
if err != nil || os.Getenv("GO_BUILDER_NAME") != "" {
2505-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, desc, b.processOutput(output))
2506-
err = errors.New(prefix + suffix)
2524+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), b.processOutput(output))
25072525
} else {
2508-
b.showOutput(a, p.Dir, desc, b.processOutput(output))
2526+
b.showOutput(a, p.Dir, p.Desc(), b.processOutput(output))
25092527
}
25102528
}
25112529
return err
@@ -3079,8 +3097,6 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
30793097
cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h")
30803098
}
30813099

3082-
execdir := p.Dir
3083-
30843100
// Rewrite overlaid paths in cgo files.
30853101
// cgo adds //line and #line pragmas in generated files with these paths.
30863102
var trimpath []string
@@ -3095,7 +3111,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
30953111
cgoflags = append(cgoflags, "-trimpath", strings.Join(trimpath, ";"))
30963112
}
30973113

3098-
if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
3114+
if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
30993115
return nil, nil, err
31003116
}
31013117
outGo = append(outGo, gofiles...)
@@ -3553,8 +3569,7 @@ func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFL
35533569
return "", "", errors.New("must have SWIG version >= 3.0.6")
35543570
}
35553571
// swig error
3556-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, p.Desc(), b.processOutput(out))
3557-
return "", "", errors.New(prefix + suffix)
3572+
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), b.processOutput(out))
35583573
}
35593574
return "", "", err
35603575
}

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

Lines changed: 1 addition & 3 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
"internal/platform"
1312
"io"
@@ -511,8 +510,7 @@ func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) er
511510
return nil
512511
}
513512
if err := packInternal(absAfile, absOfiles); err != nil {
514-
prefix, suffix := formatOutput(b.WorkDir, p.Dir, p.Desc(), err.Error()+"\n")
515-
return errors.New(prefix + suffix)
513+
return formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), err.Error()+"\n")
516514
}
517515
return nil
518516
}

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)