9
9
"bytes"
10
10
"container/heap"
11
11
"debug/elf"
12
+ "encoding/json"
12
13
"errors"
13
14
"flag"
14
15
"fmt"
@@ -223,6 +224,9 @@ func AddBuildFlags(cmd *base.Command) {
223
224
cmd .Flag .Var ((* base .StringsFlag )(& cfg .BuildContext .BuildTags ), "tags" , "" )
224
225
cmd .Flag .Var ((* base .StringsFlag )(& cfg .BuildToolexec ), "toolexec" , "" )
225
226
cmd .Flag .BoolVar (& cfg .BuildWork , "work" , false , "" )
227
+
228
+ // Undocumented, unstable debugging flags.
229
+ cmd .Flag .StringVar (& cfg .DebugActiongraph , "debug-actiongraph" , "" , "" )
226
230
}
227
231
228
232
// fileExtSplit expects a filename and returns the name
@@ -471,7 +475,7 @@ func runBuild(cmd *base.Command, args []string) {
471
475
a = b .libaction (libName , pkgs , ModeBuild , depMode )
472
476
}
473
477
} else {
474
- a = & Action {}
478
+ a = & Action {Mode : "go build" }
475
479
for _ , p := range pkgs {
476
480
a .Deps = append (a .Deps , b .Action (ModeBuild , depMode , p ))
477
481
}
@@ -589,7 +593,7 @@ func InstallPackages(args []string, forGet bool) {
589
593
a = b .libaction (libName , pkgs , ModeInstall , ModeInstall )
590
594
}
591
595
} else {
592
- a = & Action {}
596
+ a = & Action {Mode : "go install" }
593
597
var tools []* Action
594
598
for _ , p := range pkgs {
595
599
// During 'go get', don't attempt (and fail) to install packages with only tests.
@@ -611,6 +615,7 @@ func InstallPackages(args []string, forGet bool) {
611
615
}
612
616
if len (tools ) > 0 {
613
617
a = & Action {
618
+ Mode : "go install (tools)" ,
614
619
Deps : tools ,
615
620
}
616
621
}
@@ -672,6 +677,7 @@ type Builder struct {
672
677
673
678
// An Action represents a single action in the action graph.
674
679
type Action struct {
680
+ Mode string // description of action operation
675
681
Package * load.Package // the package this action works on
676
682
Deps []* Action // actions that must happen before this one
677
683
Func func (* Builder , * Action ) error // the action itself (nil = no-op)
@@ -692,13 +698,79 @@ type Action struct {
692
698
Failed bool // whether the action failed
693
699
}
694
700
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
+
695
716
// cacheKey is the key for the action cache.
696
717
type cacheKey struct {
697
718
mode BuildMode
698
719
p * load.Package
699
720
shlib string
700
721
}
701
722
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
+
702
774
// BuildMode specifies the build mode:
703
775
// are we just building things or also installing the results?
704
776
type BuildMode int
@@ -827,7 +899,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
827
899
return a
828
900
}
829
901
830
- a = & Action {Package : p }
902
+ a = & Action {Mode : "???" , Package : p }
831
903
b .actionCache [key ] = a
832
904
833
905
for _ , p1 := range p .Internal .Imports {
@@ -854,11 +926,13 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
854
926
switch p .ImportPath {
855
927
case "builtin" , "unsafe" :
856
928
// Fake packages - nothing to build.
929
+ a .Mode = "built-in package"
857
930
return a
858
931
}
859
932
// gccgo standard library is "fake" too.
860
933
if cfg .BuildToolchainName == "gccgo" {
861
934
// the target name is needed for cgo.
935
+ a .Mode = "gccgo stdlib"
862
936
a .Target = p .Internal .Target
863
937
return a
864
938
}
@@ -867,6 +941,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
867
941
if ! p .Stale && p .Internal .Target != "" {
868
942
// p.Stale==false implies that p.Internal.Target is up-to-date.
869
943
// Record target name for use by actions depending on this one.
944
+ a .Mode = "use installed"
870
945
a .Target = p .Internal .Target
871
946
p .Internal .Pkgfile = a .Target
872
947
return a
@@ -938,7 +1013,7 @@ func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lo
938
1013
}
939
1014
940
1015
func (b * Builder ) libaction (libname string , pkgs []* load.Package , mode , depMode BuildMode ) * Action {
941
- a := & Action {}
1016
+ a := & Action {Mode : "libaction???" }
942
1017
switch mode {
943
1018
default :
944
1019
base .Fatalf ("unrecognized mode %v" , mode )
@@ -1046,7 +1121,7 @@ func (b *Builder) libaction(libname string, pkgs []*load.Package, mode, depMode
1046
1121
if p .Internal .Target == "" {
1047
1122
continue
1048
1123
}
1049
- shlibnameaction := & Action {}
1124
+ shlibnameaction := & Action {Mode : "shlibname" }
1050
1125
shlibnameaction .Func = (* Builder ).installShlibname
1051
1126
shlibnameaction .Target = p .Internal .Target [:len (p .Internal .Target )- 2 ] + ".shlibname"
1052
1127
a .Deps = append (a .Deps , shlibnameaction )
@@ -1095,6 +1170,14 @@ func (b *Builder) Do(root *Action) {
1095
1170
a .priority = i
1096
1171
}
1097
1172
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
+
1098
1181
b .readySema = make (chan bool , len (all ))
1099
1182
1100
1183
// Initialize per-action execution state.
@@ -3040,7 +3123,7 @@ func (tools gccgoToolchain) ld(b *Builder, root *Action, out, importcfg string,
3040
3123
}
3041
3124
3042
3125
func (tools gccgoToolchain ) ldShared (b * Builder , toplevelactions []* Action , out , importcfg string , allactions []* Action ) error {
3043
- fakeRoot := & Action {}
3126
+ fakeRoot := & Action {Mode : "gccgo ldshared" }
3044
3127
fakeRoot .Deps = toplevelactions
3045
3128
return tools .link (b , fakeRoot , out , importcfg , allactions , "" , nil , "shared" , out )
3046
3129
}
@@ -3673,7 +3756,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
3673
3756
3674
3757
p := load .GoFilesPackage (srcs )
3675
3758
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 {
3677
3760
return "32" , nil
3678
3761
}
3679
3762
return "64" , nil
0 commit comments