From 121292911ada0a830f2ad6d83e2f393997939149 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 29 Oct 2020 18:23:58 -0700 Subject: [PATCH] Store ninja file deps from PackageVarContext in the config Store ninja file deps from ExistentPathForSource on a PackageVarContext in the config instead of the PackageContext, as the PackageContext may be shared between multiple tests running in parallel. Test: all soong tests Change-Id: Ib1809a4dd4a82696e0fe48a87eac21a44684ecb5 --- android/Android.bp | 2 + android/config.go | 2 + android/ninja_deps.go | 43 ++++++++++++++++++++++ android/ninja_deps_test.go | 75 ++++++++++++++++++++++++++++++++++++++ android/package_ctx.go | 2 +- android/register.go | 4 +- 6 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 android/ninja_deps.go create mode 100644 android/ninja_deps_test.go diff --git a/android/Android.bp b/android/Android.bp index 7bd145080..8673ab242 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -32,6 +32,7 @@ bootstrap_go_package { "mutator.go", "namespace.go", "neverallow.go", + "ninja_deps.go", "notices.go", "onceper.go", "override_module.go", @@ -73,6 +74,7 @@ bootstrap_go_package { "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 e87a4ac2a..d833c5c4d 100644 --- a/android/config.go +++ b/android/config.go @@ -126,6 +126,8 @@ type config struct { // in tests when a path doesn't exist. testAllowNonExistentPaths bool + ninjaFileDepsSet sync.Map + OncePer } diff --git a/android/ninja_deps.go b/android/ninja_deps.go new file mode 100644 index 000000000..2f442d5f0 --- /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 000000000..d3775edd9 --- /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 0de356e1c..6d0fcb33f 100644 --- a/android/package_ctx.go +++ b/android/package_ctx.go @@ -56,7 +56,7 @@ func (e *configErrorWrapper) Errorf(format string, args ...interface{}) { 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 b33ad40b1..08e47b330 100644 --- a/android/register.go +++ b/android/register.go @@ -113,8 +113,10 @@ func (ctx *Context) Register() { // Register makevars after other singletons so they can export values through makevars ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc)) - // Register env last so that it can track all used environment variables + // 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 {