Make ninja file deterministic even with dup module names
Bug: 65683273 Test: ./build/soong/scripts/diff_build_graphs.sh \ --products=aosp_arm '' '' Change-Id: I5e45b2309ba4993ba2180b5f9a4785f31e28d503
This commit is contained in:
parent
f23e36690e
commit
0e90759bfe
4 changed files with 40 additions and 27 deletions
50
context.go
50
context.go
|
@ -25,7 +25,6 @@ import (
|
|||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
@ -78,7 +77,6 @@ type Context struct {
|
|||
mutatorInfo []*mutatorInfo
|
||||
earlyMutatorInfo []*mutatorInfo
|
||||
variantMutatorNames []string
|
||||
moduleNinjaNames map[string]*moduleGroup
|
||||
|
||||
depsModified uint32 // positive if a mutator modified the dependencies
|
||||
|
||||
|
@ -278,7 +276,6 @@ func newContext() *Context {
|
|||
moduleFactories: make(map[string]ModuleFactory),
|
||||
nameInterface: NewSimpleNameInterface(),
|
||||
moduleInfo: make(map[Module]*moduleInfo),
|
||||
moduleNinjaNames: make(map[string]*moduleGroup),
|
||||
globs: make(map[string]GlobPath),
|
||||
fs: pathtools.OsFs,
|
||||
ninjaBuildDir: nil,
|
||||
|
@ -1278,21 +1275,13 @@ func (c *Context) addModule(module *moduleInfo) []error {
|
|||
name := module.logicModule.Name()
|
||||
c.moduleInfo[module.logicModule] = module
|
||||
|
||||
ninjaName := toNinjaName(name)
|
||||
// The sanitizing in toNinjaName can result in collisions, uniquify the name if it
|
||||
// already exists
|
||||
for i := 0; c.moduleNinjaNames[ninjaName] != nil; i++ {
|
||||
ninjaName = toNinjaName(name) + strconv.Itoa(i)
|
||||
}
|
||||
|
||||
group := &moduleGroup{
|
||||
name: name,
|
||||
ninjaName: ninjaName,
|
||||
modules: []*moduleInfo{module},
|
||||
name: name,
|
||||
modules: []*moduleInfo{module},
|
||||
}
|
||||
module.group = group
|
||||
namespace, errs := c.nameInterface.NewModule(
|
||||
&namespaceContextImpl{c.ModulePath(module.logicModule)},
|
||||
newNamespaceContext(module),
|
||||
ModuleGroup{moduleGroup: group},
|
||||
module.logicModule)
|
||||
if len(errs) > 0 {
|
||||
|
@ -1303,7 +1292,6 @@ func (c *Context) addModule(module *moduleInfo) []error {
|
|||
}
|
||||
group.namespace = namespace
|
||||
|
||||
c.moduleNinjaNames[ninjaName] = group
|
||||
c.moduleGroups = append(c.moduleGroups, group)
|
||||
|
||||
return nil
|
||||
|
@ -2179,10 +2167,15 @@ func (c *Context) generateModuleBuildActions(config interface{},
|
|||
}()
|
||||
|
||||
c.parallelVisit(bottomUpVisitor, func(module *moduleInfo) bool {
|
||||
|
||||
uniqueName := c.nameInterface.UniqueName(newNamespaceContext(module), module.group.name)
|
||||
sanitizedName := toNinjaName(uniqueName)
|
||||
|
||||
prefix := moduleNamespacePrefix(sanitizedName + "_" + module.variantName)
|
||||
|
||||
// The parent scope of the moduleContext's local scope gets overridden to be that of the
|
||||
// calling Go package on a per-call basis. Since the initial parent scope doesn't matter we
|
||||
// just set it to nil.
|
||||
prefix := moduleNamespacePrefix(module.group.ninjaName + "_" + module.variantName)
|
||||
scope := newLocalScope(nil, prefix)
|
||||
|
||||
mctx := &moduleContext{
|
||||
|
@ -3166,24 +3159,33 @@ func (s depSorter) Swap(i, j int) {
|
|||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
type moduleSorter []*moduleInfo
|
||||
type moduleSorter struct {
|
||||
modules []*moduleInfo
|
||||
nameInterface NameInterface
|
||||
}
|
||||
|
||||
func (s moduleSorter) Len() int {
|
||||
return len(s)
|
||||
return len(s.modules)
|
||||
}
|
||||
|
||||
func (s moduleSorter) Less(i, j int) bool {
|
||||
iName := s[i].Name()
|
||||
jName := s[j].Name()
|
||||
iMod := s.modules[i]
|
||||
jMod := s.modules[j]
|
||||
iName := s.nameInterface.UniqueName(newNamespaceContext(iMod), iMod.group.name)
|
||||
jName := s.nameInterface.UniqueName(newNamespaceContext(jMod), jMod.group.name)
|
||||
if iName == jName {
|
||||
iName = s[i].variantName
|
||||
jName = s[j].variantName
|
||||
iName = s.modules[i].variantName
|
||||
jName = s.modules[j].variantName
|
||||
}
|
||||
|
||||
if iName == jName {
|
||||
panic(fmt.Sprintf("duplicate module name: %s: %#v and %#v\n", iName, iMod, jMod))
|
||||
}
|
||||
return iName < jName
|
||||
}
|
||||
|
||||
func (s moduleSorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
s.modules[i], s.modules[j] = s.modules[j], s.modules[i]
|
||||
}
|
||||
|
||||
func (c *Context) writeAllModuleActions(nw *ninjaWriter) error {
|
||||
|
@ -3198,7 +3200,7 @@ func (c *Context) writeAllModuleActions(nw *ninjaWriter) error {
|
|||
for _, module := range c.moduleInfo {
|
||||
modules = append(modules, module)
|
||||
}
|
||||
sort.Sort(moduleSorter(modules))
|
||||
sort.Sort(moduleSorter{modules, c.nameInterface})
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
|
|
|
@ -272,9 +272,7 @@ func (d *baseModuleContext) Fs() pathtools.FileSystem {
|
|||
}
|
||||
|
||||
func (d *baseModuleContext) Namespace() Namespace {
|
||||
nsctx := &namespaceContextImpl{d.context.ModulePath(d.module.logicModule)}
|
||||
|
||||
return d.context.nameInterface.GetNamespace(nsctx)
|
||||
return d.context.nameInterface.GetNamespace(newNamespaceContext(d.module))
|
||||
}
|
||||
|
||||
var _ ModuleContext = (*moduleContext)(nil)
|
||||
|
|
|
@ -69,6 +69,9 @@ type NameInterface interface {
|
|||
|
||||
// gets the namespace for a given path
|
||||
GetNamespace(ctx NamespaceContext) (namespace Namespace)
|
||||
|
||||
// returns a deterministic, unique, arbitrary string for the given name in the given namespace
|
||||
UniqueName(ctx NamespaceContext, name string) (unique string)
|
||||
}
|
||||
|
||||
// A NamespaceContext stores the information given to a NameInterface to enable the NameInterface
|
||||
|
@ -81,6 +84,10 @@ type namespaceContextImpl struct {
|
|||
modulePath string
|
||||
}
|
||||
|
||||
func newNamespaceContext(moduleInfo *moduleInfo) (ctx NamespaceContext) {
|
||||
return &namespaceContextImpl{moduleInfo.pos.Filename}
|
||||
}
|
||||
|
||||
func (ctx *namespaceContextImpl) ModulePath() string {
|
||||
return ctx.modulePath
|
||||
}
|
||||
|
@ -165,3 +172,7 @@ func (s *SimpleNameInterface) MissingDependencyError(depender string, dependerNa
|
|||
func (s *SimpleNameInterface) GetNamespace(ctx NamespaceContext) Namespace {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SimpleNameInterface) UniqueName(ctx NamespaceContext, name string) (unique string) {
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -331,6 +331,8 @@ func toNinjaName(name string) string {
|
|||
if valid {
|
||||
ret.WriteRune(r)
|
||||
} else {
|
||||
// TODO(jeffrygaston): do escaping so that toNinjaName won't ever output duplicate
|
||||
// names for two different input names
|
||||
ret.WriteRune('_')
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue