func writeOutFileList(t *testing.T, infiles []string, outdir, tag string) ([]string, string) {
outfilelist := filepath.Join(outdir, tag+"outfilelist.txt")
var sb strings.Builder
- outfs := []string{}
+ cv := filepath.Join(outdir, "covervars.go")
+ outfs := []string{cv}
+ fmt.Fprintf(&sb, "%s\n", cv)
for _, inf := range infiles {
base := filepath.Base(inf)
of := filepath.Join(outdir, tag+".cov."+base)
var pkgconfig coverage.CoverPkgConfig
-var outputfiles []string // set when -pkgcfg is in use
+// outputfiles is the list of *.cover.go instrumented outputs to write,
+// one per input (set when -pkgcfg is in use)
+var outputfiles []string
+
+// covervarsoutfile is an additional Go source file into which we'll
+// write definitions of coverage counter variables + meta data variables
+// (set when -pkgcfg is in use).
+var covervarsoutfile string
var profile string // The profile to read; the value of -html or -func
if outputfiles, err = readOutFileList(*outfilelist); err != nil {
return err
}
+ covervarsoutfile = outputfiles[0]
+ outputfiles = outputfiles[1:]
numInputs := len(flag.Args())
numOutputs := len(outputfiles)
if numOutputs != numInputs {
}
// TODO: process files in parallel here if it matters.
for k, name := range names {
- last := false
- if k == len(names)-1 {
- last = true
- }
-
fd := os.Stdout
isStdout := true
if *pkgcfg != "" {
}
isStdout = false
}
- p.annotateFile(name, fd, last)
+ p.annotateFile(name, fd)
if !isStdout {
if err := fd.Close(); err != nil {
log.Fatalf("cover: %s", err)
}
}
}
+
+ if *pkgcfg != "" {
+ fd, err := os.Create(covervarsoutfile)
+ if err != nil {
+ log.Fatalf("cover: %s", err)
+ }
+ p.emitMetaData(fd)
+ if err := fd.Close(); err != nil {
+ log.Fatalf("cover: %s", err)
+ }
+ }
}
-func (p *Package) annotateFile(name string, fd io.Writer, last bool) {
+func (p *Package) annotateFile(name string, fd io.Writer) {
fset := token.NewFileSet()
content, err := os.ReadFile(name)
if err != nil {
if *mode == "atomic" {
fmt.Fprintf(fd, "\nvar _ = %sLoadUint32\n", atomicPackagePrefix())
}
-
- // Last file? Emit meta-data and converage config.
- if last {
- p.emitMetaData(fd)
- }
}
// setCounterStmt returns the expression: __count[23] = 1.
panic("internal error: seen functions with regonly/testmain")
}
+ // Emit package name.
+ fmt.Fprintf(w, "\npackage %s\n\n", pkgconfig.PkgName)
+
// Emit package ID var.
fmt.Fprintf(w, "\nvar %sP uint32\n", *varVar)
if mode == "" {
panic("covermode should be set at this point")
}
- pkgcfg := a.Objdir + "pkgcfg.txt"
- covoutfiles := a.Objdir + "coveroutfiles.txt"
- if err := b.cover2(a, pkgcfg, covoutfiles, infiles, outfiles, coverVar, mode); err != nil {
+ if newoutfiles, err := b.cover2(a, infiles, outfiles, coverVar, mode); err != nil {
return err
+ } else {
+ outfiles = newoutfiles
+ gofiles = append([]string{newoutfiles[0]}, gofiles...)
}
} else {
// If there are no input files passed to cmd/cover,
// cover2 runs, in effect,
//
// go tool cover -pkgcfg=<config file> -mode=b.coverMode -var="varName" -o <outfiles> <infiles>
-func (b *Builder) cover2(a *Action, pkgcfg, covoutputs string, infiles, outfiles []string, varName string, mode string) error {
+//
+// Return value is an updated output files list; in addition to the
+// regular outputs (instrumented source files) the cover tool also
+// writes a separate file (appearing first in the list of outputs)
+// that will contain coverage counters and meta-data.
+func (b *Builder) cover2(a *Action, infiles, outfiles []string, varName string, mode string) ([]string, error) {
+ pkgcfg := a.Objdir + "pkgcfg.txt"
+ covoutputs := a.Objdir + "coveroutfiles.txt"
+ odir := filepath.Dir(outfiles[0])
+ cv := filepath.Join(odir, "covervars.go")
+ outfiles = append([]string{cv}, outfiles...)
if err := b.writeCoverPkgInputs(a, pkgcfg, covoutputs, outfiles); err != nil {
- return err
+ return nil, err
}
args := []string{base.Tool("cover"),
"-pkgcfg", pkgcfg,
"-outfilelist", covoutputs,
}
args = append(args, infiles...)
- return b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil,
- cfg.BuildToolexec, args)
+ if err := b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil,
+ cfg.BuildToolexec, args); err != nil {
+ return nil, err
+ }
+ return outfiles, nil
}
func (b *Builder) writeCoverPkgInputs(a *Action, pconfigfile string, covoutputsfile string, outfiles []string) error {