summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
author Jeff Gaston <jeffrygaston@google.com> 2017-12-01 17:10:33 -0800
committer Jeff Gaston <jeffrygaston@google.com> 2017-12-04 17:44:32 -0800
commitb274ed3252dfadfd5a7edf70e470b61cf074c0de (patch)
treed9b6240f71a17911de306631868ca851d7163887 /android
parent5c3886de5a1eabb81e7d166a86c29ca324dabf49 (diff)
Make ninja file deterministic even with dup module names
Bug: 65683273 Test: ./build/soong/scripts/diff_build_graphs.sh \ --products=aosp_arm '' '' Change-Id: Ie01ff579d69e94b12363f53aec5d25810211c451
Diffstat (limited to 'android')
-rw-r--r--android/namespace.go42
-rw-r--r--android/namespace_test.go20
-rw-r--r--android/testing.go14
3 files changed, 59 insertions, 17 deletions
diff --git a/android/namespace.go b/android/namespace.go
index b3e718af3..1f8ef5a66 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -22,7 +22,6 @@ import (
"strconv"
"strings"
"sync"
- "sync/atomic"
"github.com/google/blueprint"
)
@@ -66,6 +65,15 @@ func (s *sortedNamespaces) sortedItems() []*Namespace {
return s.items
}
+func (s *sortedNamespaces) index(namespace *Namespace) int {
+ for i, candidate := range s.sortedItems() {
+ if namespace == candidate {
+ return i
+ }
+ }
+ return -1
+}
+
// A NameResolver implements blueprint.NameInterface, and implements the logic to
// find a module from namespaces based on a query string.
// A query string can be a module name or can be be "//namespace_path:module_path"
@@ -73,7 +81,7 @@ type NameResolver struct {
rootNamespace *Namespace
// id counter for atomic.AddInt32
- numNamespaces int32
+ nextNamespaceId int32
// All namespaces, without duplicates.
sortedNamespaces sortedNamespaces
@@ -104,14 +112,6 @@ func (r *NameResolver) newNamespace(path string) *Namespace {
namespace.exportToKati = r.namespaceExportFilter(namespace)
- nextId := atomic.AddInt32(&r.numNamespaces, 1)
- id := nextId - 1
- stringId := ""
- if id > 0 {
- stringId = strconv.Itoa(int(id))
- }
- namespace.id = stringId
-
return namespace
}
@@ -291,6 +291,14 @@ func (r *NameResolver) FindNamespaceImports(namespace *Namespace) (err error) {
return nil
}
+func (r *NameResolver) chooseId(namespace *Namespace) {
+ id := r.sortedNamespaces.index(namespace)
+ if id < 0 {
+ panic(fmt.Sprintf("Namespace not found: %v\n", namespace.id))
+ }
+ namespace.id = strconv.Itoa(id)
+}
+
func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string) (err error) {
text := fmt.Sprintf("%q depends on undefined module %q", depender, depName)
@@ -332,6 +340,14 @@ func (r *NameResolver) findNamespaceFromCtx(ctx blueprint.NamespaceContext) *Nam
return r.findNamespace(filepath.Dir(ctx.ModulePath()))
}
+func (r *NameResolver) UniqueName(ctx blueprint.NamespaceContext, name string) (unique string) {
+ prefix := r.findNamespaceFromCtx(ctx).id
+ if prefix != "" {
+ prefix = prefix + "-"
+ }
+ return prefix + name
+}
+
var _ blueprint.NameInterface = (*NameResolver)(nil)
type Namespace struct {
@@ -391,15 +407,17 @@ func NamespaceFactory() Module {
}
func RegisterNamespaceMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("namespace_deps", namespaceDeps)
+ ctx.BottomUp("namespace_deps", namespaceMutator).Parallel()
}
-func namespaceDeps(ctx BottomUpMutatorContext) {
+func namespaceMutator(ctx BottomUpMutatorContext) {
module, ok := ctx.Module().(*NamespaceModule)
if ok {
err := module.resolver.FindNamespaceImports(module.namespace)
if err != nil {
ctx.ModuleErrorf(err.Error())
}
+
+ module.resolver.chooseId(module.namespace)
}
}
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 13da88b42..9ab186b00 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -19,6 +19,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "reflect"
"testing"
"github.com/google/blueprint"
@@ -562,6 +563,25 @@ func TestDeclaringNamespaceInNonAndroidBpFile(t *testing.T) {
}
}
+// so that the generated .ninja file will have consistent names
+func TestConsistentNamespaceNames(t *testing.T) {
+ ctx := setupTest(t,
+ map[string]string{
+ "dir1": "soong_namespace{}",
+ "dir2": "soong_namespace{}",
+ "dir3": "soong_namespace{}",
+ })
+
+ ns1, _ := ctx.NameResolver.namespaceAt("dir1")
+ ns2, _ := ctx.NameResolver.namespaceAt("dir2")
+ ns3, _ := ctx.NameResolver.namespaceAt("dir3")
+ actualIds := []string{ns1.id, ns2.id, ns3.id}
+ expectedIds := []string{"1", "2", "3"}
+ if !reflect.DeepEqual(actualIds, expectedIds) {
+ t.Errorf("Incorrect namespace ids.\nactual: %s\nexpected: %s\n", actualIds, expectedIds)
+ }
+}
+
// some utils to support the tests
func mockFiles(bps map[string]string) (files map[string][]byte) {
diff --git a/android/testing.go b/android/testing.go
index 4f2a2da4f..1c0fac10d 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -23,14 +23,17 @@ import (
)
func NewTestContext() *TestContext {
- ctx := &TestContext{
- Context: blueprint.NewContext(),
- }
-
namespaceExportFilter := func(namespace *Namespace) bool {
return true
}
- ctx.SetNameInterface(NewNameResolver(namespaceExportFilter))
+
+ nameResolver := NewNameResolver(namespaceExportFilter)
+ ctx := &TestContext{
+ Context: blueprint.NewContext(),
+ NameResolver: nameResolver,
+ }
+
+ ctx.SetNameInterface(nameResolver)
return ctx
}
@@ -44,6 +47,7 @@ func NewTestArchContext() *TestContext {
type TestContext struct {
*blueprint.Context
preArch, preDeps, postDeps []RegisterMutatorFunc
+ NameResolver *NameResolver
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {