Merge changes Iba57c949,Ief43ff51,Ib1809a4d,I2ab64f36 am: b08a091502 am: 3f57de54b2 am: a088bff723 am: 6c4cdb0bb2

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1480605

Change-Id: Ie0876cdaf142dbd75c094f9e680849efb4105b28
diff --git a/android/Android.bp b/android/Android.bp
index c6f01fe..503462e 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -32,6 +32,7 @@
         "mutator.go",
         "namespace.go",
         "neverallow.go",
+        "ninja_deps.go",
         "notices.go",
         "onceper.go",
         "override_module.go",
@@ -74,6 +75,7 @@
         "mutator_test.go",
         "namespace_test.go",
         "neverallow_test.go",
+        "ninja_deps_test.go",
         "onceper_test.go",
         "package_test.go",
         "path_properties_test.go",
diff --git a/android/config.go b/android/config.go
index e87a4ac..d833c5c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -126,6 +126,8 @@
 	// in tests when a path doesn't exist.
 	testAllowNonExistentPaths bool
 
+	ninjaFileDepsSet sync.Map
+
 	OncePer
 }
 
diff --git a/android/makevars.go b/android/makevars.go
index 3ca7792..f784395 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -139,15 +139,24 @@
 	MakeVars(ctx MakeVarsContext)
 }
 
-// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to the list of
-// MakeVarsProviders to run.
-func registerSingletonMakeVarsProvider(singleton SingletonMakeVarsProvider) {
-	singletonMakeVarsProviders = append(singletonMakeVarsProviders,
-		makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
+var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
+
+// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
+// the list of MakeVarsProviders to run.
+func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
+	// Singletons are registered on the Context and may be different between different Contexts,
+	// for example when running multiple tests.  Store the SingletonMakeVarsProviders in the
+	// Config so they are attached to the Context.
+	singletonMakeVarsProviders := config.Once(singletonMakeVarsProvidersKey, func() interface{} {
+		return &[]makeVarsProvider{}
+	}).(*[]makeVarsProvider)
+
+	*singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
+		makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
 }
 
-// SingletonmakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
-func SingletonmakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
+// singletonMakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
+func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
 	return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
 }
 
@@ -175,9 +184,6 @@
 // Collection of makevars providers that are registered in init() methods.
 var makeVarsInitProviders []makeVarsProvider
 
-// Collection of singleton makevars providers that are not registered as part of init() methods.
-var singletonMakeVarsProviders []makeVarsProvider
-
 type makeVarsContext struct {
 	SingletonContext
 	config  Config
@@ -224,7 +230,11 @@
 	var vars []makeVarsVariable
 	var dists []dist
 	var phonies []phony
-	for _, provider := range append(makeVarsInitProviders) {
+
+	providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
+	providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...)
+
+	for _, provider := range providers {
 		mctx := &makeVarsContext{
 			SingletonContext: ctx,
 			pctx:             provider.pctx,
@@ -237,25 +247,6 @@
 		dists = append(dists, mctx.dists...)
 	}
 
-	for _, provider := range append(singletonMakeVarsProviders) {
-		mctx := &makeVarsContext{
-			SingletonContext: ctx,
-			pctx:             provider.pctx,
-		}
-
-		provider.call(mctx)
-
-		vars = append(vars, mctx.vars...)
-		phonies = append(phonies, mctx.phonies...)
-		dists = append(dists, mctx.dists...)
-	}
-
-	// Clear singleton makevars providers after use. Since these are in-memory
-	// singletons, this ensures state is reset if the build tree is processed
-	// multiple times.
-	// TODO(cparsons): Clean up makeVarsProviders to be part of the context.
-	singletonMakeVarsProviders = nil
-
 	ctx.VisitAllModules(func(m Module) {
 		if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
 			mctx := &makeVarsContext{
diff --git a/android/ninja_deps.go b/android/ninja_deps.go
new file mode 100644
index 0000000..2f442d5
--- /dev/null
+++ b/android/ninja_deps.go
@@ -0,0 +1,43 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import "sort"
+
+func (c *config) addNinjaFileDeps(deps ...string) {
+	for _, dep := range deps {
+		c.ninjaFileDepsSet.Store(dep, true)
+	}
+}
+
+func (c *config) ninjaFileDeps() []string {
+	var deps []string
+	c.ninjaFileDepsSet.Range(func(key, value interface{}) bool {
+		deps = append(deps, key.(string))
+		return true
+	})
+	sort.Strings(deps)
+	return deps
+}
+
+func ninjaDepsSingletonFactory() Singleton {
+	return &ninjaDepsSingleton{}
+}
+
+type ninjaDepsSingleton struct{}
+
+func (ninjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
+	ctx.AddNinjaFileDeps(ctx.Config().ninjaFileDeps()...)
+}
diff --git a/android/ninja_deps_test.go b/android/ninja_deps_test.go
new file mode 100644
index 0000000..d3775ed
--- /dev/null
+++ b/android/ninja_deps_test.go
@@ -0,0 +1,75 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"testing"
+)
+
+func init() {
+	// This variable uses ExistentPathForSource on a PackageVarContext, which is a PathContext
+	// that is not a PathGlobContext.  That requires the deps to be stored in the Config.
+	pctx.VariableFunc("test_ninja_deps_variable", func(ctx PackageVarContext) string {
+		// Using ExistentPathForSource to look for a file that does not exist in a directory that
+		// does exist (test_ninja_deps) from a PackageVarContext adds a dependency from build.ninja
+		// to the directory.
+		if ExistentPathForSource(ctx, "test_ninja_deps/does_not_exist").Valid() {
+			return "true"
+		} else {
+			return "false"
+		}
+	})
+}
+
+func testNinjaDepsSingletonFactory() Singleton {
+	return testNinjaDepsSingleton{}
+}
+
+type testNinjaDepsSingleton struct{}
+
+func (testNinjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
+	// Reference the test_ninja_deps_variable in a build statement so Blueprint is forced to
+	// evaluate it.
+	ctx.Build(pctx, BuildParams{
+		Rule:   Cp,
+		Input:  PathForTesting("foo"),
+		Output: PathForOutput(ctx, "test_ninja_deps_out"),
+		Args: map[string]string{
+			"cpFlags": "${test_ninja_deps_variable}",
+		},
+	})
+}
+
+func TestNinjaDeps(t *testing.T) {
+	fs := map[string][]byte{
+		"test_ninja_deps/exists": nil,
+	}
+	config := TestConfig(buildDir, nil, "", fs)
+
+	ctx := NewTestContext(config)
+	ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
+	ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
+	ctx.Register()
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	ninjaDeps, errs := ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	// Verify that the ninja file has a dependency on the test_ninja_deps directory.
+	if g, w := ninjaDeps, "test_ninja_deps"; !InList(w, g) {
+		t.Errorf("expected %q in %q", w, g)
+	}
+}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index 0de356e..6d0fcb3 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -56,7 +56,7 @@
 	e.errors = append(e.errors, fmt.Errorf(format, args...))
 }
 func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
-	e.pctx.AddNinjaFileDeps(deps...)
+	e.config.addNinjaFileDeps(deps...)
 }
 
 type PackageVarContext interface {
diff --git a/android/register.go b/android/register.go
index bd824c9..08e47b3 100644
--- a/android/register.go
+++ b/android/register.go
@@ -29,7 +29,7 @@
 
 type singleton struct {
 	name    string
-	factory blueprint.SingletonFactory
+	factory SingletonFactory
 }
 
 var singletons []singleton
@@ -57,11 +57,11 @@
 
 // SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting
 // a Singleton into a blueprint.Singleton
-func SingletonFactoryAdaptor(factory SingletonFactory) blueprint.SingletonFactory {
+func SingletonFactoryAdaptor(ctx *Context, factory SingletonFactory) blueprint.SingletonFactory {
 	return func() blueprint.Singleton {
 		singleton := factory()
 		if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
-			registerSingletonMakeVarsProvider(makevars)
+			registerSingletonMakeVarsProvider(ctx.config, makevars)
 		}
 		return &singletonAdaptor{Singleton: singleton}
 	}
@@ -72,11 +72,11 @@
 }
 
 func RegisterSingletonType(name string, factory SingletonFactory) {
-	singletons = append(singletons, singleton{name, SingletonFactoryAdaptor(factory)})
+	singletons = append(singletons, singleton{name, factory})
 }
 
 func RegisterPreSingletonType(name string, factory SingletonFactory) {
-	preSingletons = append(preSingletons, singleton{name, SingletonFactoryAdaptor(factory)})
+	preSingletons = append(preSingletons, singleton{name, factory})
 }
 
 type Context struct {
@@ -92,7 +92,7 @@
 
 func (ctx *Context) Register() {
 	for _, t := range preSingletons {
-		ctx.RegisterPreSingletonType(t.name, t.factory)
+		ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
 	}
 
 	for _, t := range moduleTypes {
@@ -100,21 +100,23 @@
 	}
 
 	for _, t := range singletons {
-		ctx.RegisterSingletonType(t.name, t.factory)
+		ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
 	}
 
 	registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
 
-	ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(BazelSingleton))
+	ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
 
 	// Register phony just before makevars so it can write out its phony rules as Make rules
-	ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
+	ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(ctx, phonySingletonFactory))
 
 	// Register makevars after other singletons so they can export values through makevars
-	ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
+	ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc))
 
-	// Register env last so that it can track all used environment variables
-	ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(EnvSingleton))
+	// Register env and ninjadeps last so that they can track all used environment variables and
+	// Ninja file dependencies stored in the config.
+	ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(ctx, EnvSingleton))
+	ctx.RegisterSingletonType("ninjadeps", SingletonFactoryAdaptor(ctx, ninjaDepsSingletonFactory))
 }
 
 func ModuleTypeFactories() map[string]ModuleFactory {
diff --git a/android/testing.go b/android/testing.go
index d83cecc..1e2ae13 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -104,7 +104,7 @@
 }
 
 func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
-	ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(factory))
+	ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
 }
 
 func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
diff --git a/cc/cc.go b/cc/cc.go
index a2d6cd9..bd6e5d5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -88,7 +88,7 @@
 		ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
 	})
 
-	android.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory)
+	ctx.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory)
 }
 
 type Deps struct {
@@ -369,7 +369,7 @@
 	useSdk() bool
 	sdkVersion() string
 	useVndk() bool
-	isNdk() bool
+	isNdk(config android.Config) bool
 	isLlndk(config android.Config) bool
 	isLlndkPublic(config android.Config) bool
 	isVndkPrivate(config android.Config) bool
@@ -939,8 +939,8 @@
 	return c.coverage.Properties.IsCoverageVariant
 }
 
-func (c *Module) IsNdk() bool {
-	return inList(c.BaseModuleName(), ndkKnownLibs)
+func (c *Module) IsNdk(config android.Config) bool {
+	return inList(c.BaseModuleName(), *getNDKKnownLibs(config))
 }
 
 func (c *Module) isLlndk(config android.Config) bool {
@@ -1145,8 +1145,8 @@
 	return ctx.mod.UseVndk()
 }
 
-func (ctx *moduleContextImpl) isNdk() bool {
-	return ctx.mod.IsNdk()
+func (ctx *moduleContextImpl) isNdk(config android.Config) bool {
+	return ctx.mod.IsNdk(config)
 }
 
 func (ctx *moduleContextImpl) isLlndk(config android.Config) bool {
@@ -1766,7 +1766,7 @@
 			for _, entry := range list {
 				// strip #version suffix out
 				name, _ := StubsLibNameAndVersion(entry)
-				if ctx.useSdk() && inList(name, ndkKnownLibs) {
+				if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
 					variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 				} else if ctx.useVndk() {
 					nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
diff --git a/cc/library.go b/cc/library.go
index eeddd90..2127c08 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -567,7 +567,7 @@
 		return ""
 	}
 	// Return NDK if the library is both NDK and LLNDK.
-	if ctx.isNdk() {
+	if ctx.isNdk(ctx.Config()) {
 		return "NDK"
 	}
 	if ctx.isLlndkPublic(ctx.Config()) {
@@ -1099,7 +1099,7 @@
 
 func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path {
 	// The logic must be consistent with classifySourceAbiDump.
-	isNdk := ctx.isNdk()
+	isNdk := ctx.isNdk(ctx.Config())
 	isLlndkOrVndk := ctx.isLlndkPublic(ctx.Config()) || (ctx.useVndk() && ctx.isVndk())
 
 	refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isLlndkOrVndk, false)
@@ -1153,7 +1153,7 @@
 			library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
 				refAbiDumpFile, fileName, exportedHeaderFlags,
 				Bool(library.Properties.Header_abi_checker.Check_all_apis),
-				ctx.isLlndk(ctx.Config()), ctx.isNdk(), ctx.isVndkExt())
+				ctx.isLlndk(ctx.Config()), ctx.isNdk(ctx.Config()), ctx.isVndkExt())
 		}
 	}
 }
diff --git a/cc/makevars.go b/cc/makevars.go
index dcfd6d8..bd8aab5 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -171,6 +171,7 @@
 	ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " "))
 	ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " "))
 
+	ndkKnownLibs := *getNDKKnownLibs(ctx.Config())
 	sort.Strings(ndkKnownLibs)
 	ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " "))
 
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 9097e7b..a5c43fe 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -45,8 +45,7 @@
 
 	ndkLibrarySuffix = ".ndk"
 
-	// Added as a variation dependency via depsMutator.
-	ndkKnownLibs = []string{}
+	ndkKnownLibsKey = android.NewOnceKey("ndkKnownLibsKey")
 	// protects ndkKnownLibs writes during parallel BeginMutator.
 	ndkKnownLibsLock sync.Mutex
 )
@@ -158,6 +157,12 @@
 	return true
 }
 
+func getNDKKnownLibs(config android.Config) *[]string {
+	return config.Once(ndkKnownLibsKey, func() interface{} {
+		return &[]string{}
+	}).(*[]string)
+}
+
 func (c *stubDecorator) compilerInit(ctx BaseModuleContext) {
 	c.baseCompiler.compilerInit(ctx)
 
@@ -168,12 +173,13 @@
 
 	ndkKnownLibsLock.Lock()
 	defer ndkKnownLibsLock.Unlock()
-	for _, lib := range ndkKnownLibs {
+	ndkKnownLibs := getNDKKnownLibs(ctx.Config())
+	for _, lib := range *ndkKnownLibs {
 		if lib == name {
 			return
 		}
 	}
-	ndkKnownLibs = append(ndkKnownLibs, name)
+	*ndkKnownLibs = append(*ndkKnownLibs, name)
 }
 
 func addStubLibraryCompilerFlags(flags Flags) Flags {
diff --git a/java/app.go b/java/app.go
index 17de8b9..3446739 100755
--- a/java/app.go
+++ b/java/app.go
@@ -890,7 +890,7 @@
 
 		if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
 			if dep, ok := module.(*cc.Module); ok {
-				if dep.IsNdk() || dep.IsStubs() {
+				if dep.IsNdk(ctx.Config()) || dep.IsStubs() {
 					return false
 				}
 
diff --git a/java/java_test.go b/java/java_test.go
index efca039..845a03a 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -92,8 +92,8 @@
 
 	ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
 	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
-	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
-	ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory))
+	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(ctx.Context, OverlaySingletonFactory))
+	ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(ctx.Context, sdkPreSingletonFactory))
 
 	android.RegisterPrebuiltMutators(ctx)