p.Internal.Imports = append(p.Internal.Imports, p1)
}
-// PrepareForCoverageBuild is a helper invoked for "go install -cover"
-// and "go build -cover"; it walks through the packages being built
-// (and dependencies) and marks them for coverage instrumentation
-// when appropriate, and adding dependencies where needed.
+// PrepareForCoverageBuild is a helper invoked for "go install
+// -cover", "go run -cover", and "go build -cover" (but not used by
+// "go test -cover"). It walks through the packages being built (and
+// dependencies) and marks them for coverage instrumentation when
+// appropriate, and possibly adding additional deps where needed.
func PrepareForCoverageBuild(pkgs []*Package) {
var match []func(*Package) bool
- matchMainMod := func(p *Package) bool {
- return !p.Standard && p.Module != nil && p.Module.Main
- }
-
- // The set of packages instrumented by default varies depending on
- // options and the nature of the build. If "-coverpkg" has been
- // set, then match packages below using that value; if we're
- // building with a module in effect, then default to packages in
- // the main module. If no module is in effect and we're building
- // in GOPATH mode, instrument the named packages and their
- // dependencies in GOPATH. Otherwise, for "go run ..." and for the
- // "go build ..." case, instrument just the packages named on the
- // command line.
- if len(cfg.BuildCoverPkg) == 0 {
- if modload.Enabled() {
- // Default is main module.
- match = []func(*Package) bool{matchMainMod}
- } else {
- // These matchers below are intended to handle the cases of:
- //
- // 1. "go run ..." and "go build ..."
- // 2. building in gopath mode with GO111MODULE=off
- //
- // In case 2 above, the assumption here is that (in the
- // absence of a -coverpkg flag) we will be instrumenting
- // the named packages only.
- matchMain := func(p *Package) bool { return p.Internal.CmdlineFiles || p.Internal.CmdlinePkg }
- match = []func(*Package) bool{matchMain}
- }
- } else {
+ matchMainModAndCommandLine := func(p *Package) bool {
+ // note that p.Standard implies p.Module == nil below.
+ return p.Internal.CmdlineFiles || p.Internal.CmdlinePkg || (p.Module != nil && p.Module.Main)
+ }
+
+ if len(cfg.BuildCoverPkg) != 0 {
+ // If -coverpkg has been specified, then we instrument only
+ // the specific packages selected by the user-specified pattern(s).
match = make([]func(*Package) bool, len(cfg.BuildCoverPkg))
for i := range cfg.BuildCoverPkg {
match[i] = MatchPackage(cfg.BuildCoverPkg[i], base.Cwd())
}
+ } else {
+ // Without -coverpkg, instrument only packages in the main module
+ // (if any), as well as packages/files specifically named on the
+ // command line.
+ match = []func(*Package) bool{matchMainModAndCommandLine}
}
- // Visit the packages being built or installed, along with all
- // of their dependencies, and mark them to be instrumented,
- // taking into account the value of -coverpkg.
+ // Visit the packages being built or installed, along with all of
+ // their dependencies, and mark them to be instrumented, taking
+ // into account the matchers we've set up in the sequence above.
SelectCoverPackages(PackageList(pkgs), match, "build")
}
--- /dev/null
+
+# This test is intended to verify that when a user does "go run -cover ..."
+# or "go build -cover ...", packages named on the command line are
+# always instrumented (but not their dependencies). This rule applies
+# inside and outside the standard library.
+
+[short] skip
+
+# Compile an object.
+go tool compile -p tiny tiny/tiny.go tiny/tiny2.go
+
+# Build a stdlib command with coverage.
+go build -o $WORK/nm.exe -cover cmd/nm
+
+# Save off old GOCOVERDIR setting
+env SAVEGOCOVERDIR=$GOCOVERDIR
+
+# Collect a coverage profile from running 'cmd/nm' on the object.
+mkdir $WORK/covdata
+env GOCOVERDIR=$WORK/covdata
+exec $WORK/nm.exe tiny.o
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Check to make sure we instrumented just the main package, not
+# any dependencies.
+go tool covdata pkglist -i=$WORK/covdata
+stdout main
+! stdout cmd/internal/goobj pkglist.txt
+
+# ... now collect a coverage profile from a Go file
+# listed on the command line.
+go build -cover -o $WORK/another.exe testdata/another.go
+mkdir $WORK/covdata2
+env GOCOVERDIR=$WORK/covdata2
+exec $WORK/another.exe
+
+# Restore previous GOCOVERDIR setting
+env GOCOVERDIR=$SAVEGOCOVERDIR
+
+# Check to make sure we instrumented just the main package.
+go tool covdata pkglist -i=$WORK/covdata2
+stdout main
+! stdout fmt
+
+-- go.mod --
+
+module example.prog
+
+-- testdata/another.go --
+
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hi dad")
+}
+
+-- tiny/tiny.go --
+
+package tiny
+
+var Tvar int
+
+-- tiny/tiny2.go --
+
+package tiny
+
+var Tvar2 bool
+