Skip to content

Commit

Permalink
cmd/go/internal/work: make formatOutput return an error that includes…
Browse files Browse the repository at this point in the history
… 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]>
  • Loading branch information
Bryan C. Mills authored and gopherbot committed Dec 1, 2022
1 parent e24380b commit af1a5d9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 36 deletions.
73 changes: 44 additions & 29 deletions src/cmd/go/internal/work/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,15 @@ func (b *Builder) Do(ctx context.Context, root *Action) {
defer b.exec.Unlock()

if err != nil {
if b.AllowErrors {
if b.AllowErrors && a.Package != nil {
if a.Package.Error == nil {
a.Package.Error = &load.PackageError{Err: err}
}
} else {
var ipe load.ImportPathError
if a.Package != nil && (!errors.As(err, &ipe) || ipe.ImportPath() != a.Package.ImportPath) {
err = fmt.Errorf("%s: %v", a.Package.ImportPath, err)
}
base.Errorf("%s", err)
}
a.Failed = true
Expand Down Expand Up @@ -495,9 +499,6 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) {
}

defer func() {
if err != nil {
err = fmt.Errorf("go build %s: %v", p.ImportPath, err)
}
if err != nil && b.IsCmdList && b.NeedError && p.Error == nil {
p.Error = &load.PackageError{Err: err}
}
Expand Down Expand Up @@ -846,8 +847,7 @@ OverlayLoop:
}

if err != nil {
prefix, suffix := formatOutput(b.WorkDir, p.Dir, p.Desc(), output)
return errors.New(prefix + suffix)
return formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), output)
} else {
b.showOutput(a, p.Dir, p.Desc(), output)
}
Expand Down Expand Up @@ -1530,8 +1530,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
var out []byte
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
if err != nil {
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)+err.Error())
return nil, nil, err
}
if len(out) > 0 {
cflags, err = splitPkgConfigOutput(out)
Expand All @@ -1544,8 +1544,8 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
}
out, err = b.runOut(nil, p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
if err != nil {
prefix, suffix := formatOutput(b.WorkDir, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out))
return nil, nil, errors.New(fmt.Sprint(prefix, suffix+err.Error()))
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)+err.Error())
return nil, nil, err
}
if len(out) > 0 {
// NOTE: we don't attempt to parse quotes and unescapes here. pkg-config
Expand Down Expand Up @@ -2093,16 +2093,37 @@ func (b *Builder) Showcmd(dir string, format string, args ...any) {
// If a is not nil and a.output is not nil, showOutput appends to that slice instead of
// printing to b.Print.
func (b *Builder) showOutput(a *Action, dir, desc, out string) {
prefix, suffix := formatOutput(b.WorkDir, dir, desc, out)
importPath := ""
if a != nil && a.Package != nil {
importPath = a.Package.ImportPath
}
psErr := formatOutput(b.WorkDir, dir, importPath, desc, out)
if a != nil && a.output != nil {
a.output = append(a.output, prefix...)
a.output = append(a.output, suffix...)
a.output = append(a.output, psErr.prefix...)
a.output = append(a.output, psErr.suffix...)
return
}

b.output.Lock()
defer b.output.Unlock()
b.Print(prefix, suffix)
b.Print(psErr.prefix, psErr.suffix)
}

// A prefixSuffixError is an error formatted by formatOutput.
type prefixSuffixError struct {
importPath string
prefix, suffix string
}

func (e *prefixSuffixError) Error() string {
if e.importPath != "" && !strings.HasPrefix(strings.TrimPrefix(e.prefix, "# "), e.importPath) {
return fmt.Sprintf("go build %s:\n%s%s", e.importPath, e.prefix, e.suffix)
}
return e.prefix + e.suffix
}

func (e *prefixSuffixError) ImportPath() string {
return e.importPath
}

// formatOutput prints "# desc" followed by the given output.
Expand All @@ -2128,17 +2149,17 @@ func (b *Builder) showOutput(a *Action, dir, desc, out string) {
// formatOutput also replaces references to the work directory with $WORK.
// formatOutput returns the output in a prefix with the description and a
// suffix with the actual output.
func formatOutput(workDir, dir, desc, out string) (prefix, suffix string) {
prefix = "# " + desc
suffix = "\n" + out
func formatOutput(workDir, dir, importPath, desc, out string) *prefixSuffixError {
prefix := "# " + desc
suffix := "\n" + out
if reldir := base.ShortPath(dir); reldir != dir {
suffix = strings.ReplaceAll(suffix, " "+dir, " "+reldir)
suffix = strings.ReplaceAll(suffix, "\n"+dir, "\n"+reldir)
suffix = strings.ReplaceAll(suffix, "\n\t"+dir, "\n\t"+reldir)
}
suffix = strings.ReplaceAll(suffix, " "+workDir, " $WORK")

return prefix, suffix
return &prefixSuffixError{importPath: importPath, prefix: prefix, suffix: suffix}
}

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

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

if err != nil || os.Getenv("GO_BUILDER_NAME") != "" {
prefix, suffix := formatOutput(b.WorkDir, p.Dir, desc, b.processOutput(output))
err = errors.New(prefix + suffix)
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), b.processOutput(output))
} else {
b.showOutput(a, p.Dir, desc, b.processOutput(output))
b.showOutput(a, p.Dir, p.Desc(), b.processOutput(output))
}
}
return err
Expand Down Expand Up @@ -3079,8 +3097,6 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h")
}

execdir := p.Dir

// Rewrite overlaid paths in cgo files.
// cgo adds //line and #line pragmas in generated files with these paths.
var trimpath []string
Expand All @@ -3095,7 +3111,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
cgoflags = append(cgoflags, "-trimpath", strings.Join(trimpath, ";"))
}

if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
return nil, nil, err
}
outGo = append(outGo, gofiles...)
Expand Down Expand Up @@ -3553,8 +3569,7 @@ func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFL
return "", "", errors.New("must have SWIG version >= 3.0.6")
}
// swig error
prefix, suffix := formatOutput(b.WorkDir, p.Dir, p.Desc(), b.processOutput(out))
return "", "", errors.New(prefix + suffix)
err = formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), b.processOutput(out))
}
return "", "", err
}
Expand Down
4 changes: 1 addition & 3 deletions src/cmd/go/internal/work/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package work
import (
"bufio"
"bytes"
"errors"
"fmt"
"internal/platform"
"io"
Expand Down Expand Up @@ -511,8 +510,7 @@ func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) er
return nil
}
if err := packInternal(absAfile, absOfiles); err != nil {
prefix, suffix := formatOutput(b.WorkDir, p.Dir, p.Desc(), err.Error()+"\n")
return errors.New(prefix + suffix)
return formatOutput(b.WorkDir, p.Dir, p.ImportPath, p.Desc(), err.Error()+"\n")
}
return nil
}
Expand Down
15 changes: 11 additions & 4 deletions src/cmd/go/testdata/script/list_export_e.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
go list -e -export ./...
! go list -export ./...
stderr '^# example.com/p2\np2'${/}'main\.go:7:.*'
! stderr '^go build '

go list -f '{{with .Error}}{{.}}{{end}}' -e -export ./...
! stderr '.'
go list -e -export -json ...
stdout '^# example.com/p2\np2'${/}'main\.go:7:.*'

go list -e -export -json=Error ./...
stdout '"Err": "# example.com/p2'

-- go.mod --
module example.com
Expand All @@ -15,5 +22,5 @@ import "fmt"
import "example.com/p1"

func main() {
fmt.Println(p1.Name == 5)
}
fmt.Println(p1.Name == 5)
}
16 changes: 16 additions & 0 deletions src/cmd/go/testdata/script/list_pkgconfig_error.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[!cgo] skip 'test verifies cgo pkg-config errors'
[!exec:pkg-config] skip 'test requires pkg-config tool'

! go list -export .
stderr '^go build example:\n# pkg-config (.*\n)+pkg-config: exit status \d+$'

-- go.mod --
module example
go 1.20
-- example.go --
package example

// #cgo pkg-config: libnot-a-valid-cgo-library
import "C"

package main() {}

0 comments on commit af1a5d9

Please sign in to comment.