Skip to content

Commit 0174858

Browse files
committed
cmd/go: add undocumented -debug-actiongraph flag to dump action graph
This will be useful for debugging but is intentionally undocumented and not guaranteed to persist in any particular form. Change-Id: I60710a1e94cfc2ce31fe91fc268c51985060f8df Reviewed-on: https://go-review.googlesource.com/69330 Run-TryBot: Russ Cox <[email protected]> Reviewed-by: David Crawshaw <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 966c459 commit 0174858

File tree

4 files changed

+102
-13
lines changed

4 files changed

+102
-13
lines changed

src/cmd/go/internal/cfg/cfg.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ var (
3737
BuildV bool // -v flag
3838
BuildWork bool // -work flag
3939
BuildX bool // -x flag
40+
41+
DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable)
4042
)
4143

4244
func init() {

src/cmd/go/internal/run/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func runRun(cmd *base.Command, args []string) {
111111
}
112112
p.Internal.ExeName = src[:len(src)-len(".go")] // name temporary executable for first go file
113113
a1 := b.Action(work.ModeBuild, work.ModeBuild, p)
114-
a := &work.Action{Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}}
114+
a := &work.Action{Mode: "go run", Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}}
115115
b.Do(a)
116116
}
117117

src/cmd/go/internal/test/test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ func runTest(cmd *base.Command, args []string) {
522522
}
523523
sort.Strings(all)
524524

525-
a := &work.Action{}
525+
a := &work.Action{Mode: "go test -i"}
526526
for _, p := range load.PackagesForBuild(all) {
527527
a.Deps = append(a.Deps, b.Action(work.ModeInstall, work.ModeInstall, p))
528528
}
@@ -599,7 +599,7 @@ func runTest(cmd *base.Command, args []string) {
599599
}
600600

601601
// Ultimately the goal is to print the output.
602-
root := &work.Action{Deps: prints}
602+
root := &work.Action{Mode: "go test", Deps: prints}
603603

604604
// Force the printing of results to happen in order,
605605
// one at a time.
@@ -652,8 +652,8 @@ var windowsBadWords = []string{
652652
func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) {
653653
if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
654654
build := b.Action(work.ModeBuild, work.ModeBuild, p)
655-
run := &work.Action{Package: p, Deps: []*work.Action{build}}
656-
print := &work.Action{Func: builderNoTest, Package: p, Deps: []*work.Action{run}}
655+
run := &work.Action{Mode: "test run", Package: p, Deps: []*work.Action{build}}
656+
print := &work.Action{Mode: "test print", Func: builderNoTest, Package: p, Deps: []*work.Action{run}}
657657
return build, run, print, nil
658658
}
659659

@@ -945,6 +945,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
945945
}
946946
}
947947
buildAction = &work.Action{
948+
Mode: "test build",
948949
Func: work.BuildInstallFunc,
949950
Deps: []*work.Action{buildAction},
950951
Package: pmain,
@@ -953,22 +954,25 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
953954
runAction = buildAction // make sure runAction != nil even if not running test
954955
}
955956
if testC {
956-
printAction = &work.Action{Package: p, Deps: []*work.Action{runAction}} // nop
957+
printAction = &work.Action{Mode: "test print (nop)", Package: p, Deps: []*work.Action{runAction}} // nop
957958
} else {
958959
// run test
959960
runAction = &work.Action{
961+
Mode: "test run",
960962
Func: builderRunTest,
961963
Deps: []*work.Action{buildAction},
962964
Package: p,
963965
IgnoreFail: true,
964966
}
965967
cleanAction := &work.Action{
968+
Mode: "test clean",
966969
Func: builderCleanTest,
967970
Deps: []*work.Action{runAction},
968971
Package: p,
969972
Objdir: testDir,
970973
}
971974
printAction = &work.Action{
975+
Mode: "test print",
972976
Func: builderPrintTest,
973977
Deps: []*work.Action{cleanAction},
974978
Package: p,

src/cmd/go/internal/work/build.go

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"bytes"
1010
"container/heap"
1111
"debug/elf"
12+
"encoding/json"
1213
"errors"
1314
"flag"
1415
"fmt"
@@ -223,6 +224,9 @@ func AddBuildFlags(cmd *base.Command) {
223224
cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
224225
cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
225226
cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
227+
228+
// Undocumented, unstable debugging flags.
229+
cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
226230
}
227231

228232
// fileExtSplit expects a filename and returns the name
@@ -471,7 +475,7 @@ func runBuild(cmd *base.Command, args []string) {
471475
a = b.libaction(libName, pkgs, ModeBuild, depMode)
472476
}
473477
} else {
474-
a = &Action{}
478+
a = &Action{Mode: "go build"}
475479
for _, p := range pkgs {
476480
a.Deps = append(a.Deps, b.Action(ModeBuild, depMode, p))
477481
}
@@ -589,7 +593,7 @@ func InstallPackages(args []string, forGet bool) {
589593
a = b.libaction(libName, pkgs, ModeInstall, ModeInstall)
590594
}
591595
} else {
592-
a = &Action{}
596+
a = &Action{Mode: "go install"}
593597
var tools []*Action
594598
for _, p := range pkgs {
595599
// During 'go get', don't attempt (and fail) to install packages with only tests.
@@ -611,6 +615,7 @@ func InstallPackages(args []string, forGet bool) {
611615
}
612616
if len(tools) > 0 {
613617
a = &Action{
618+
Mode: "go install (tools)",
614619
Deps: tools,
615620
}
616621
}
@@ -672,6 +677,7 @@ type Builder struct {
672677

673678
// An Action represents a single action in the action graph.
674679
type Action struct {
680+
Mode string // description of action operation
675681
Package *load.Package // the package this action works on
676682
Deps []*Action // actions that must happen before this one
677683
Func func(*Builder, *Action) error // the action itself (nil = no-op)
@@ -692,13 +698,79 @@ type Action struct {
692698
Failed bool // whether the action failed
693699
}
694700

701+
type actionJSON struct {
702+
ID int
703+
Mode string
704+
Package string
705+
Deps []int `json:",omitempty"`
706+
IgnoreFail bool `json:",omitempty"`
707+
Args []string `json:",omitempty"`
708+
Link bool `json:",omitempty"`
709+
Objdir string `json:",omitempty"`
710+
Target string `json:",omitempty"`
711+
Priority int `json:",omitempty"`
712+
Failed bool `json:",omitempty"`
713+
Pkgfile string `json:",omitempty"`
714+
}
715+
695716
// cacheKey is the key for the action cache.
696717
type cacheKey struct {
697718
mode BuildMode
698719
p *load.Package
699720
shlib string
700721
}
701722

723+
func actionGraphJSON(a *Action) string {
724+
var workq []*Action
725+
var inWorkq = make(map[*Action]int)
726+
727+
add := func(a *Action) {
728+
if _, ok := inWorkq[a]; ok {
729+
return
730+
}
731+
inWorkq[a] = len(workq)
732+
workq = append(workq, a)
733+
}
734+
add(a)
735+
736+
for i := 0; i < len(workq); i++ {
737+
for _, dep := range workq[i].Deps {
738+
add(dep)
739+
}
740+
}
741+
742+
var list []*actionJSON
743+
for id, a := range workq {
744+
aj := &actionJSON{
745+
Mode: a.Mode,
746+
ID: id,
747+
IgnoreFail: a.IgnoreFail,
748+
Args: a.Args,
749+
Link: a.Link,
750+
Objdir: a.Objdir,
751+
Target: a.Target,
752+
Failed: a.Failed,
753+
Priority: a.priority,
754+
}
755+
if a.Package != nil {
756+
// TODO(rsc): Make this a unique key for a.Package somehow.
757+
aj.Package = a.Package.ImportPath
758+
aj.Pkgfile = a.Package.Internal.Pkgfile
759+
}
760+
for _, a1 := range a.Deps {
761+
aj.Deps = append(aj.Deps, inWorkq[a1])
762+
}
763+
list = append(list, aj)
764+
}
765+
766+
js, err := json.MarshalIndent(list, "", "\t")
767+
if err != nil {
768+
fmt.Fprintf(os.Stderr, "go: writing debug action graph: %v\n", err)
769+
return ""
770+
}
771+
return string(js)
772+
}
773+
702774
// BuildMode specifies the build mode:
703775
// are we just building things or also installing the results?
704776
type BuildMode int
@@ -827,7 +899,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
827899
return a
828900
}
829901

830-
a = &Action{Package: p}
902+
a = &Action{Mode: "???", Package: p}
831903
b.actionCache[key] = a
832904

833905
for _, p1 := range p.Internal.Imports {
@@ -854,11 +926,13 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
854926
switch p.ImportPath {
855927
case "builtin", "unsafe":
856928
// Fake packages - nothing to build.
929+
a.Mode = "built-in package"
857930
return a
858931
}
859932
// gccgo standard library is "fake" too.
860933
if cfg.BuildToolchainName == "gccgo" {
861934
// the target name is needed for cgo.
935+
a.Mode = "gccgo stdlib"
862936
a.Target = p.Internal.Target
863937
return a
864938
}
@@ -867,6 +941,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
867941
if !p.Stale && p.Internal.Target != "" {
868942
// p.Stale==false implies that p.Internal.Target is up-to-date.
869943
// Record target name for use by actions depending on this one.
944+
a.Mode = "use installed"
870945
a.Target = p.Internal.Target
871946
p.Internal.Pkgfile = a.Target
872947
return a
@@ -938,7 +1013,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
9381013
}
9391014

9401015
func (b *Builder) libaction(libname string, pkgs []*load.Package, mode, depMode BuildMode) *Action {
941-
a := &Action{}
1016+
a := &Action{Mode: "libaction???"}
9421017
switch mode {
9431018
default:
9441019
base.Fatalf("unrecognized mode %v", mode)
@@ -1046,7 +1121,7 @@ func (b *Builder) libaction(libname string, pkgs []*load.Package, mode, depMode
10461121
if p.Internal.Target == "" {
10471122
continue
10481123
}
1049-
shlibnameaction := &Action{}
1124+
shlibnameaction := &Action{Mode: "shlibname"}
10501125
shlibnameaction.Func = (*Builder).installShlibname
10511126
shlibnameaction.Target = p.Internal.Target[:len(p.Internal.Target)-2] + ".shlibname"
10521127
a.Deps = append(a.Deps, shlibnameaction)
@@ -1095,6 +1170,14 @@ func (b *Builder) Do(root *Action) {
10951170
a.priority = i
10961171
}
10971172

1173+
if cfg.DebugActiongraph != "" {
1174+
js := actionGraphJSON(root)
1175+
if err := ioutil.WriteFile(cfg.DebugActiongraph, []byte(js), 0666); err != nil {
1176+
fmt.Fprintf(os.Stderr, "go: writing action graph: %v\n", err)
1177+
base.SetExitStatus(1)
1178+
}
1179+
}
1180+
10981181
b.readySema = make(chan bool, len(all))
10991182

11001183
// Initialize per-action execution state.
@@ -3040,7 +3123,7 @@ func (tools gccgoToolchain) ld(b *Builder, root *Action, out, importcfg string,
30403123
}
30413124

30423125
func (tools gccgoToolchain) ldShared(b *Builder, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
3043-
fakeRoot := &Action{}
3126+
fakeRoot := &Action{Mode: "gccgo ldshared"}
30443127
fakeRoot.Deps = toplevelactions
30453128
return tools.link(b, fakeRoot, out, importcfg, allactions, "", nil, "shared", out)
30463129
}
@@ -3673,7 +3756,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
36733756

36743757
p := load.GoFilesPackage(srcs)
36753758

3676-
if _, _, e := BuildToolchain.gc(b, &Action{Package: p, Objdir: objdir}, "", nil, false, srcs); e != nil {
3759+
if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, false, srcs); e != nil {
36773760
return "32", nil
36783761
}
36793762
return "64", nil

0 commit comments

Comments
 (0)