From 9d3dfd88686ff3889b3daf2e5fcd1df6e4dd5f17 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 22 Apr 2018 19:06:44 +0200 Subject: [PATCH] Make package process order deterministic: based on import order --- tgo.go | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/tgo.go b/tgo.go index 4f6793ac..9f6958a8 100644 --- a/tgo.go +++ b/tgo.go @@ -132,7 +132,7 @@ func NewCompiler(pkgName, triple string) (*Compiler, error) { return c, nil } -func (c *Compiler) Parse(pkgName string) error { +func (c *Compiler) Parse(mainPath string) error { tripleSplit := strings.Split(c.triple, "-") config := loader.Config { @@ -149,7 +149,7 @@ func (c *Compiler) Parse(pkgName string) error { AllowErrors: true, } config.Import("runtime") - config.Import(pkgName) + config.Import(mainPath) lprogram, err := config.Load() if err != nil { return err @@ -165,8 +165,42 @@ func (c *Compiler) Parse(pkgName string) error { program := ssautil.CreateProgram(lprogram, ssa.SanityCheckFunctions | ssa.BareInits) program.Build() - // TODO: order of packages is random - for _, pkg := range program.AllPackages() { + + // Make a list of packages in import order. + packageList := []*ssa.Package{} + packageSet := map[string]struct{}{} + worklist := [][]string{{"runtime", mainPath}} + for len(worklist) != 0 { + for _, pkgPath := range worklist[0] { + pkg := program.ImportedPackage(pkgPath) + if pkg == nil { + packageSet[pkgPath] = struct{}{} + continue // non-SSA package (e.g. cgo) + } + if _, ok := packageSet[pkgPath]; ok { + continue + } + + unsatisfiedImports := make([]string, 0) + for _, pkg := range pkg.Pkg.Imports() { + if _, ok := packageSet[pkg.Path()]; ok { + continue + } + unsatisfiedImports = append(unsatisfiedImports, pkg.Path()) + } + if len(unsatisfiedImports) == 0 { + // all dependencies are in packageList inserted + packageList = append(packageList, pkg) + packageSet[pkgPath] = struct{}{} + } else { + unsatisfiedImports = append(unsatisfiedImports, pkgPath) // reconsider + worklist = append(worklist, unsatisfiedImports) + } + } + worklist = worklist[1:] + } + + for _, pkg := range packageList { fmt.Println("package:", pkg.Pkg.Path()) // Make sure we're walking through all members in a constant order every