From eae7b36699477c9c781669f553a7c085e415ac1e Mon Sep 17 00:00:00 2001 From: Yu Liu Date: Thu, 16 Nov 2023 17:05:47 -0800 Subject: [PATCH] Add container property to aconfig_declarations. Bug: 311155208 Test: Unit test Change-Id: I7b187138856d0144203961e82b6dad5e2f8eed9d --- aconfig/Android.bp | 9 - aconfig/aconfig_declarations.go | 56 ++- aconfig/aconfig_declarations_test.go | 4 +- aconfig/all_aconfig_declarations.go | 6 +- aconfig/codegen/Android.bp | 32 ++ aconfig/{ => codegen}/cc_aconfig_library.go | 7 +- .../{ => codegen}/cc_aconfig_library_test.go | 2 +- aconfig/codegen/init.go | 83 ++++ aconfig/{ => codegen}/java_aconfig_library.go | 9 +- .../java_aconfig_library_test.go | 42 +- aconfig/{ => codegen}/rust_aconfig_library.go | 5 +- .../rust_aconfig_library_test.go | 2 +- aconfig/codegen/testing.go | 25 + aconfig/init.go | 51 +- android/testing.go | 7 + apex/Android.bp | 2 + apex/apex.go | 18 + apex/apex_test.go | 436 ++++++++++++++++++ apex/builder.go | 28 +- cc/Android.bp | 1 + cc/cc.go | 6 + java/Android.bp | 1 + java/androidmk.go | 13 +- java/base.go | 41 +- java/generated_java_library_test.go | 1 - java/java.go | 9 - 26 files changed, 750 insertions(+), 146 deletions(-) create mode 100644 aconfig/codegen/Android.bp rename aconfig/{ => codegen}/cc_aconfig_library.go (97%) rename aconfig/{ => codegen}/cc_aconfig_library_test.go (99%) create mode 100644 aconfig/codegen/init.go rename aconfig/{ => codegen}/java_aconfig_library.go (94%) rename aconfig/{ => codegen}/java_aconfig_library_test.go (82%) rename aconfig/{ => codegen}/rust_aconfig_library.go (96%) rename aconfig/{ => codegen}/rust_aconfig_library_test.go (99%) create mode 100644 aconfig/codegen/testing.go diff --git a/aconfig/Android.bp b/aconfig/Android.bp index faa4ddbb6..04de9198a 100644 --- a/aconfig/Android.bp +++ b/aconfig/Android.bp @@ -12,28 +12,19 @@ bootstrap_go_package { "soong", "soong-android", "soong-bazel", - "soong-android", - "soong-java", - "soong-rust", ], srcs: [ "aconfig_declarations.go", "aconfig_values.go", "aconfig_value_set.go", "all_aconfig_declarations.go", - "cc_aconfig_library.go", "init.go", - "java_aconfig_library.go", "testing.go", - "rust_aconfig_library.go", ], testSrcs: [ "aconfig_declarations_test.go", "aconfig_values_test.go", "aconfig_value_set_test.go", - "java_aconfig_library_test.go", - "cc_aconfig_library_test.go", - "rust_aconfig_library_test.go", ], pluginFor: ["soong_build"], } diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go index 897f8925a..e662f1da4 100644 --- a/aconfig/aconfig_declarations.go +++ b/aconfig/aconfig_declarations.go @@ -38,6 +38,9 @@ type DeclarationsModule struct { // Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS Values []string `blueprint:"mutated"` + + // Container(system/vendor/apex) that this module belongs to + Container string } intermediatePath android.WritablePath @@ -69,6 +72,8 @@ func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext if len(module.properties.Package) == 0 { ctx.PropertyErrorf("package", "missing package property") } + // TODO(b/311155208): Add mandatory check for container after all pre-existing + // ones are changed. // Add a dependency on the aconfig_value_sets defined in // RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that @@ -110,12 +115,21 @@ func optionalVariable(prefix string, value string) string { } // Provider published by aconfig_value_set -type declarationsProviderData struct { +type DeclarationsProviderData struct { Package string + Container string IntermediatePath android.WritablePath } -var declarationsProviderKey = blueprint.NewProvider(declarationsProviderData{}) +var DeclarationsProviderKey = blueprint.NewProvider(DeclarationsProviderData{}) + +// This is used to collect the aconfig declarations info on the transitive closure, +// the data is keyed on the container. +type TransitiveDeclarationsInfo struct { + AconfigFiles map[string]*android.DepSet[android.Path] +} + +var TransitiveDeclarationsInfoProvider = blueprint.NewProvider(TransitiveDeclarationsInfo{}) func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag @@ -156,13 +170,49 @@ func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.Module }, }) - ctx.SetProvider(declarationsProviderKey, declarationsProviderData{ + ctx.SetProvider(DeclarationsProviderKey, DeclarationsProviderData{ Package: module.properties.Package, + Container: module.properties.Container, IntermediatePath: intermediatePath, }) } +func CollectTransitiveAconfigFiles(ctx android.ModuleContext, transitiveAconfigFiles *map[string]*android.DepSet[android.Path]) { + if *transitiveAconfigFiles == nil { + *transitiveAconfigFiles = make(map[string]*android.DepSet[android.Path]) + } + ctx.VisitDirectDeps(func(module android.Module) { + if dep := ctx.OtherModuleProvider(module, DeclarationsProviderKey).(DeclarationsProviderData); dep.IntermediatePath != nil { + aconfigMap := make(map[string]*android.DepSet[android.Path]) + aconfigMap[dep.Container] = android.NewDepSet(android.POSTORDER, []android.Path{dep.IntermediatePath}, nil) + mergeTransitiveAconfigFiles(aconfigMap, *transitiveAconfigFiles) + return + } + if dep := ctx.OtherModuleProvider(module, TransitiveDeclarationsInfoProvider).(TransitiveDeclarationsInfo); len(dep.AconfigFiles) > 0 { + mergeTransitiveAconfigFiles(dep.AconfigFiles, *transitiveAconfigFiles) + } + }) + + ctx.SetProvider(TransitiveDeclarationsInfoProvider, TransitiveDeclarationsInfo{ + AconfigFiles: *transitiveAconfigFiles, + }) +} + +func mergeTransitiveAconfigFiles(from, to map[string]*android.DepSet[android.Path]) { + for fromKey, fromValue := range from { + if fromValue == nil { + continue + } + toValue, ok := to[fromKey] + if !ok { + to[fromKey] = fromValue + } else { + to[fromKey] = android.NewDepSet(android.POSTORDER, toValue.ToList(), []*android.DepSet[android.Path]{fromValue}) + } + } +} + type bazelAconfigDeclarationsAttributes struct { Srcs bazel.LabelListAttribute Package string diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go index e0d8f7d5a..e6bd87cd5 100644 --- a/aconfig/aconfig_declarations_test.go +++ b/aconfig/aconfig_declarations_test.go @@ -26,6 +26,7 @@ func TestAconfigDeclarations(t *testing.T) { aconfig_declarations { name: "module_name", package: "com.example.package", + container: "com.android.foo", srcs: [ "foo.aconfig", "bar.aconfig", @@ -37,8 +38,9 @@ func TestAconfigDeclarations(t *testing.T) { module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule) // Check that the provider has the right contents - depData := result.ModuleProvider(module, declarationsProviderKey).(declarationsProviderData) + depData := result.ModuleProvider(module, DeclarationsProviderKey).(DeclarationsProviderData) android.AssertStringEquals(t, "package", depData.Package, "com.example.package") + android.AssertStringEquals(t, "container", depData.Container, "com.android.foo") if !strings.HasSuffix(depData.IntermediatePath.String(), "/intermediate.pb") { t.Errorf("Missing intermediates path in provider: %s", depData.IntermediatePath.String()) } diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go index 6096c6c0b..7ccb81a37 100644 --- a/aconfig/all_aconfig_declarations.go +++ b/aconfig/all_aconfig_declarations.go @@ -37,17 +37,17 @@ func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.Si // Find all of the aconfig_declarations modules var cacheFiles android.Paths ctx.VisitAllModules(func(module android.Module) { - if !ctx.ModuleHasProvider(module, declarationsProviderKey) { + if !ctx.ModuleHasProvider(module, DeclarationsProviderKey) { return } - decl := ctx.ModuleProvider(module, declarationsProviderKey).(declarationsProviderData) + decl := ctx.ModuleProvider(module, DeclarationsProviderKey).(DeclarationsProviderData) cacheFiles = append(cacheFiles, decl.IntermediatePath) }) // Generate build action for aconfig this.intermediatePath = android.PathForIntermediates(ctx, "all_aconfig_declarations.pb") ctx.Build(pctx, android.BuildParams{ - Rule: allDeclarationsRule, + Rule: AllDeclarationsRule, Inputs: cacheFiles, Output: this.intermediatePath, Description: "all_aconfig_declarations", diff --git a/aconfig/codegen/Android.bp b/aconfig/codegen/Android.bp new file mode 100644 index 000000000..494f7e693 --- /dev/null +++ b/aconfig/codegen/Android.bp @@ -0,0 +1,32 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-aconfig-codegen", + pkgPath: "android/soong/aconfig/codegen", + deps: [ + "blueprint", + "blueprint-pathtools", + "sbox_proto", + "soong", + "soong-aconfig", + "soong-android", + "soong-bazel", + "soong-java", + "soong-rust", + ], + srcs: [ + "cc_aconfig_library.go", + "init.go", + "java_aconfig_library.go", + "rust_aconfig_library.go", + "testing.go", + ], + testSrcs: [ + "java_aconfig_library_test.go", + "cc_aconfig_library_test.go", + "rust_aconfig_library_test.go", + ], + pluginFor: ["soong_build"], +} diff --git a/aconfig/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go similarity index 97% rename from aconfig/cc_aconfig_library.go rename to aconfig/codegen/cc_aconfig_library.go index 210a58105..7b68844e9 100644 --- a/aconfig/cc_aconfig_library.go +++ b/aconfig/codegen/cc_aconfig_library.go @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package aconfig +package codegen import ( + "android/soong/aconfig" "android/soong/android" "android/soong/bazel" "android/soong/cc" @@ -92,7 +93,7 @@ func (this *CcAconfigLibraryCallbacks) GeneratorSources(ctx cc.ModuleContext) cc if len(declarationsModules) != 1 { panic(fmt.Errorf("Exactly one aconfig_declarations property required")) } - declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) + declarations := ctx.OtherModuleProvider(declarationsModules[0], aconfig.DeclarationsProviderKey).(aconfig.DeclarationsProviderData) // Figure out the generated file paths. This has to match aconfig's codegen_cpp.rs. this.generatedDir = android.PathForModuleGen(ctx) @@ -122,7 +123,7 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex if len(declarationsModules) != 1 { panic(fmt.Errorf("Exactly one aconfig_declarations property required")) } - declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) + declarations := ctx.OtherModuleProvider(declarationsModules[0], aconfig.DeclarationsProviderKey).(aconfig.DeclarationsProviderData) mode := proptools.StringDefault(this.properties.Mode, "production") if !isModeSupported(mode) { diff --git a/aconfig/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go similarity index 99% rename from aconfig/cc_aconfig_library_test.go rename to aconfig/codegen/cc_aconfig_library_test.go index ba2725059..0c8a96936 100644 --- a/aconfig/cc_aconfig_library_test.go +++ b/aconfig/codegen/cc_aconfig_library_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package aconfig +package codegen import ( "fmt" diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go new file mode 100644 index 000000000..0bff9d2af --- /dev/null +++ b/aconfig/codegen/init.go @@ -0,0 +1,83 @@ +// Copyright 2023 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 codegen + +import ( + "android/soong/android" + + "github.com/google/blueprint" +) + +var ( + pctx = android.NewPackageContext("android/soong/aconfig/codegen") + + // For java_aconfig_library: Generate java library + javaRule = pctx.AndroidStaticRule("java_aconfig_library", + blueprint.RuleParams{ + Command: `rm -rf ${out}.tmp` + + ` && mkdir -p ${out}.tmp` + + ` && ${aconfig} create-java-lib` + + ` --mode ${mode}` + + ` --cache ${in}` + + ` --out ${out}.tmp` + + ` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` + + ` && rm -rf ${out}.tmp`, + CommandDeps: []string{ + "$aconfig", + "$soong_zip", + }, + Restat: true, + }, "mode") + + // For cc_aconfig_library: Generate C++ library + cppRule = pctx.AndroidStaticRule("cc_aconfig_library", + blueprint.RuleParams{ + Command: `rm -rf ${gendir}` + + ` && mkdir -p ${gendir}` + + ` && ${aconfig} create-cpp-lib` + + ` --mode ${mode}` + + ` --cache ${in}` + + ` --out ${gendir}`, + CommandDeps: []string{ + "$aconfig", + }, + }, "gendir", "mode") + + // For rust_aconfig_library: Generate Rust library + rustRule = pctx.AndroidStaticRule("rust_aconfig_library", + blueprint.RuleParams{ + Command: `rm -rf ${gendir}` + + ` && mkdir -p ${gendir}` + + ` && ${aconfig} create-rust-lib` + + ` --mode ${mode}` + + ` --cache ${in}` + + ` --out ${gendir}`, + CommandDeps: []string{ + "$aconfig", + }, + }, "gendir", "mode") +) + +func init() { + RegisterBuildComponents(android.InitRegistrationContext) + pctx.HostBinToolVariable("aconfig", "aconfig") + pctx.HostBinToolVariable("soong_zip", "soong_zip") +} + +func RegisterBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory) + ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory) + ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory) +} diff --git a/aconfig/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go similarity index 94% rename from aconfig/java_aconfig_library.go rename to aconfig/codegen/java_aconfig_library.go index eedb3c358..e2fb15bc7 100644 --- a/aconfig/java_aconfig_library.go +++ b/aconfig/codegen/java_aconfig_library.go @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package aconfig +package codegen import ( "fmt" + "android/soong/aconfig" "android/soong/android" "android/soong/bazel" "android/soong/java" @@ -73,7 +74,7 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild if len(declarationsModules) != 1 { panic(fmt.Errorf("Exactly one aconfig_declarations property required")) } - declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) + declarations := ctx.OtherModuleProvider(declarationsModules[0], aconfig.DeclarationsProviderKey).(aconfig.DeclarationsProviderData) // Generate the action to build the srcjar srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar") @@ -93,10 +94,6 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild }, }) - // Tell the java module about the .aconfig files, so they can be propagated up the dependency chain. - // TODO: It would be nice to have that propagation code here instead of on java.Module and java.JavaInfo. - module.AddAconfigIntermediate(declarations.IntermediatePath) - return srcJarPath } diff --git a/aconfig/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go similarity index 82% rename from aconfig/java_aconfig_library_test.go rename to aconfig/codegen/java_aconfig_library_test.go index a803672db..cbfdc2179 100644 --- a/aconfig/java_aconfig_library_test.go +++ b/aconfig/codegen/java_aconfig_library_test.go @@ -12,11 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package aconfig +package codegen import ( "fmt" - "strings" "testing" "android/soong/android" @@ -34,14 +33,25 @@ func runJavaAndroidMkTest(t *testing.T, bp string) { ExtendWithErrorHandler(android.FixtureExpectsNoErrors). RunTestWithBp(t, bp+` aconfig_declarations { - name: "my_aconfig_declarations", + name: "my_aconfig_declarations_foo", package: "com.example.package", srcs: ["foo.aconfig"], } java_aconfig_library { - name: "my_java_aconfig_library", - aconfig_declarations: "my_aconfig_declarations", + name: "my_java_aconfig_library_foo", + aconfig_declarations: "my_aconfig_declarations_foo", + } + + aconfig_declarations { + name: "my_aconfig_declarations_bar", + package: "com.example.package", + srcs: ["bar.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library_bar", + aconfig_declarations: "my_aconfig_declarations_bar", } `) @@ -50,10 +60,9 @@ func runJavaAndroidMkTest(t *testing.T, bp string) { entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0] makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"] - android.AssertIntEquals(t, "len(LOCAL_ACONFIG_FILES)", 1, len(makeVar)) - if !strings.HasSuffix(makeVar[0], "intermediate.pb") { - t.Errorf("LOCAL_ACONFIG_FILES should end with /intermediates.pb, instead it is: %s", makeVar[0]) - } + android.AssertIntEquals(t, "len(LOCAL_ACONFIG_FILES)", 2, len(makeVar)) + android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/intermediate.pb") + android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_bar/intermediate.pb") } func TestAndroidMkJavaLibrary(t *testing.T) { @@ -64,7 +73,8 @@ func TestAndroidMkJavaLibrary(t *testing.T) { "src/foo.java", ], static_libs: [ - "my_java_aconfig_library", + "my_java_aconfig_library_foo", + "my_java_aconfig_library_bar", ], platform_apis: true, } @@ -81,7 +91,8 @@ func TestAndroidMkAndroidApp(t *testing.T) { "src/foo.java", ], static_libs: [ - "my_java_aconfig_library", + "my_java_aconfig_library_foo", + "my_java_aconfig_library_bar", ], platform_apis: true, } @@ -98,7 +109,8 @@ func TestAndroidMkBinary(t *testing.T) { "src/foo.java", ], static_libs: [ - "my_java_aconfig_library", + "my_java_aconfig_library_foo", + "my_java_aconfig_library_bar", ], platform_apis: true, main_class: "foo", @@ -116,7 +128,8 @@ func TestAndroidMkAndroidLibrary(t *testing.T) { "src/foo.java", ], static_libs: [ - "my_java_aconfig_library", + "my_java_aconfig_library_foo", + "my_java_aconfig_library_bar", ], platform_apis: true, } @@ -134,7 +147,8 @@ func TestAndroidMkBinaryThatLinksAgainstAar(t *testing.T) { "src/foo.java", ], static_libs: [ - "my_java_aconfig_library", + "my_java_aconfig_library_foo", + "my_java_aconfig_library_bar", ], platform_apis: true, } diff --git a/aconfig/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go similarity index 96% rename from aconfig/rust_aconfig_library.go rename to aconfig/codegen/rust_aconfig_library.go index 265685e6f..3525de19a 100644 --- a/aconfig/rust_aconfig_library.go +++ b/aconfig/codegen/rust_aconfig_library.go @@ -1,8 +1,9 @@ -package aconfig +package codegen import ( "fmt" + "android/soong/aconfig" "android/soong/android" "android/soong/rust" @@ -64,7 +65,7 @@ func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.Path if len(declarationsModules) != 1 { panic(fmt.Errorf("Exactly one aconfig_declarations property required")) } - declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) + declarations := ctx.OtherModuleProvider(declarationsModules[0], aconfig.DeclarationsProviderKey).(aconfig.DeclarationsProviderData) mode := proptools.StringDefault(a.Properties.Mode, "production") if !isModeSupported(mode) { diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go similarity index 99% rename from aconfig/rust_aconfig_library_test.go rename to aconfig/codegen/rust_aconfig_library_test.go index 3aeab7622..c09f70149 100644 --- a/aconfig/rust_aconfig_library_test.go +++ b/aconfig/codegen/rust_aconfig_library_test.go @@ -1,4 +1,4 @@ -package aconfig +package codegen import ( "fmt" diff --git a/aconfig/codegen/testing.go b/aconfig/codegen/testing.go new file mode 100644 index 000000000..3e1c22eb9 --- /dev/null +++ b/aconfig/codegen/testing.go @@ -0,0 +1,25 @@ +// Copyright (C) 2021 The Android Open Source Project +// +// 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 codegen + +import ( + "android/soong/aconfig" + "android/soong/android" +) + +var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("aconfig_declarations", aconfig.DeclarationsFactory) + RegisterBuildComponents(ctx) +}) diff --git a/aconfig/init.go b/aconfig/init.go index 626e66d0f..79bf0027b 100644 --- a/aconfig/init.go +++ b/aconfig/init.go @@ -40,54 +40,8 @@ var ( Restat: true, }, "release_version", "package", "declarations", "values", "default-permission") - // For java_aconfig_library: Generate java library - javaRule = pctx.AndroidStaticRule("java_aconfig_library", - blueprint.RuleParams{ - Command: `rm -rf ${out}.tmp` + - ` && mkdir -p ${out}.tmp` + - ` && ${aconfig} create-java-lib` + - ` --mode ${mode}` + - ` --cache ${in}` + - ` --out ${out}.tmp` + - ` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` + - ` && rm -rf ${out}.tmp`, - CommandDeps: []string{ - "$aconfig", - "$soong_zip", - }, - Restat: true, - }, "mode") - - // For cc_aconfig_library: Generate C++ library - cppRule = pctx.AndroidStaticRule("cc_aconfig_library", - blueprint.RuleParams{ - Command: `rm -rf ${gendir}` + - ` && mkdir -p ${gendir}` + - ` && ${aconfig} create-cpp-lib` + - ` --mode ${mode}` + - ` --cache ${in}` + - ` --out ${gendir}`, - CommandDeps: []string{ - "$aconfig", - }, - }, "gendir", "mode") - - // For rust_aconfig_library: Generate Rust library - rustRule = pctx.AndroidStaticRule("rust_aconfig_library", - blueprint.RuleParams{ - Command: `rm -rf ${gendir}` + - ` && mkdir -p ${gendir}` + - ` && ${aconfig} create-rust-lib` + - ` --mode ${mode}` + - ` --cache ${in}` + - ` --out ${gendir}`, - CommandDeps: []string{ - "$aconfig", - }, - }, "gendir", "mode") - // For all_aconfig_declarations: Combine all parsed_flags proto files - allDeclarationsRule = pctx.AndroidStaticRule("all_aconfig_declarations_dump", + AllDeclarationsRule = pctx.AndroidStaticRule("All_aconfig_declarations_dump", blueprint.RuleParams{ Command: `${aconfig} dump --format protobuf --out ${out} ${cache_files}`, CommandDeps: []string{ @@ -106,8 +60,5 @@ func RegisterBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory) ctx.RegisterModuleType("aconfig_values", ValuesFactory) ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory) - ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory) - ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory) - ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory) ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory) } diff --git a/android/testing.go b/android/testing.go index da3b75aa2..c596468c3 100644 --- a/android/testing.go +++ b/android/testing.go @@ -1293,3 +1293,10 @@ func StringRelativeToTop(config Config, command string) string { func StringsRelativeToTop(config Config, command []string) []string { return normalizeStringArrayRelativeToTop(config, command) } + +func EnsureListContainsSuffix(t *testing.T, result []string, expected string) { + t.Helper() + if !SuffixInList(result, expected) { + t.Errorf("%q is not found in %v", expected, result) + } +} diff --git a/apex/Android.bp b/apex/Android.bp index 079149737..0a5063ff7 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -8,6 +8,8 @@ bootstrap_go_package { deps: [ "blueprint", "soong", + "soong-aconfig", + "soong-aconfig-codegen", "soong-android", "soong-bazel", "soong-bpf", diff --git a/apex/apex.go b/apex/apex.go index ecc794b5b..56f33676f 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -24,6 +24,7 @@ import ( "sort" "strings" + "android/soong/aconfig" "android/soong/bazel/cquery" "github.com/google/blueprint" @@ -482,6 +483,8 @@ type apexBundle struct { nativeApisUsedByModuleFile android.ModuleOutPath nativeApisBackedByModuleFile android.ModuleOutPath javaApisUsedByModuleFile android.ModuleOutPath + + aconfigFiles []android.Path } // apexFileClass represents a type of file that can be included in APEX. @@ -2008,6 +2011,8 @@ type visitorContext struct { // visitor skips these from this list of module names unwantedTransitiveDeps []string + + aconfigFiles []android.Path } func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) { @@ -2067,6 +2072,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs) fi.isJniLib = isJniLib vctx.filesInfo = append(vctx.filesInfo, fi) + addAconfigFiles(vctx, ctx, child) // Collect the list of stub-providing libs except: // - VNDK libs are only for vendors // - bootstrap bionic libs are treated as provided by system @@ -2090,6 +2096,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, switch ch := child.(type) { case *cc.Module: vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch)) + addAconfigFiles(vctx, ctx, child) return true // track transitive dependencies case *rust.Module: vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch)) @@ -2132,6 +2139,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, return false } vctx.filesInfo = append(vctx.filesInfo, af) + addAconfigFiles(vctx, ctx, child) return true // track transitive dependencies default: ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child)) @@ -2140,6 +2148,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, switch ap := child.(type) { case *java.AndroidApp: vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...) + addAconfigFiles(vctx, ctx, child) return true // track transitive dependencies case *java.AndroidAppImport: vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...) @@ -2298,6 +2307,7 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, } vctx.filesInfo = append(vctx.filesInfo, af) + addAconfigFiles(vctx, ctx, child) return true // track transitive dependencies } else if rm, ok := child.(*rust.Module); ok { af := apexFileForRustLibrary(ctx, rm) @@ -2378,6 +2388,13 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, return false } +func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) { + dep := ctx.OtherModuleProvider(module, aconfig.TransitiveDeclarationsInfoProvider).(aconfig.TransitiveDeclarationsInfo) + if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil { + vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()].ToList()...) + } +} + func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool { // TODO(b/263308293) remove this if a.properties.IsCoverageVariant { @@ -2459,6 +2476,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { // 3) some fields in apexBundle struct are configured a.installDir = android.PathForModuleInstall(ctx, "apex") a.filesInfo = vctx.filesInfo + a.aconfigFiles = android.FirstUniquePaths(vctx.aconfigFiles) a.setPayloadFsType(ctx) a.setSystemLibLink(ctx) diff --git a/apex/apex_test.go b/apex/apex_test.go index ddb9a4051..af643a0a0 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -25,6 +25,7 @@ import ( "strings" "testing" + "android/soong/aconfig/codegen" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -151,6 +152,7 @@ var prepareForApexTest = android.GroupFixturePreparers( prebuilt_etc.PrepareForTestWithPrebuiltEtc, rust.PrepareForTestWithRustDefaultModules, sh.PrepareForTestWithShBuildComponents, + codegen.PrepareForTestWithAconfigBuildComponents, PrepareForTestWithApexBuildComponents, @@ -10756,3 +10758,437 @@ func TestFileSystemShouldSkipApexLibraries(t *testing.T) { inputs.Strings(), "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so") } + +var apex_default_bp = ` + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + filegroup { + name: "myapex.manifest", + srcs: ["apex_manifest.json"], + } + + filegroup { + name: "myapex.androidmanifest", + srcs: ["AndroidManifest.xml"], + } +` + +func TestAconfigFilesJavaDeps(t *testing.T) { + ctx := testApex(t, apex_default_bp+` + apex { + name: "myapex", + manifest: ":myapex.manifest", + androidManifest: ":myapex.androidmanifest", + key: "myapex.key", + java_libs: [ + "my_java_library_foo", + "my_java_library_bar", + ], + updatable: false, + } + + java_library { + name: "my_java_library_foo", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["my_java_aconfig_library_foo"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + java_library { + name: "my_java_library_bar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["my_java_aconfig_library_bar"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_foo", + package: "com.example.package", + container: "myapex", + srcs: ["foo.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library_foo", + aconfig_declarations: "my_aconfig_declarations_foo", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_bar", + package: "com.example.package", + container: "myapex", + srcs: ["bar.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library_bar", + aconfig_declarations: "my_aconfig_declarations_bar", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + `) + + mod := ctx.ModuleForTests("myapex", "android_common_myapex") + s := mod.Rule("apexRule").Args["copy_commands"] + copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) + if len(copyCmds) != 5 { + t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s) + } + + ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex$") + + combineAconfigRule := mod.Rule("All_aconfig_declarations_dump") + s = " " + combineAconfigRule.Args["cache_files"] + aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:] + if len(aconfigArgs) != 2 { + t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s) + } + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb") + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb") + + buildParams := combineAconfigRule.BuildParams + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb") + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb") + ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb") +} + +func TestAconfigFilesJavaAndCcDeps(t *testing.T) { + ctx := testApex(t, apex_default_bp+` + apex { + name: "myapex", + manifest: ":myapex.manifest", + androidManifest: ":myapex.androidmanifest", + key: "myapex.key", + java_libs: [ + "my_java_library_foo", + ], + native_shared_libs: [ + "my_cc_library_bar", + ], + binaries: [ + "my_cc_binary_baz", + ], + updatable: false, + } + + java_library { + name: "my_java_library_foo", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["my_java_aconfig_library_foo"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + cc_library { + name: "my_cc_library_bar", + srcs: ["foo/bar/MyClass.cc"], + static_libs: ["my_cc_aconfig_library_bar"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + cc_binary { + name: "my_cc_binary_baz", + srcs: ["foo/bar/MyClass.cc"], + static_libs: ["my_cc_aconfig_library_baz"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_foo", + package: "com.example.package", + container: "myapex", + srcs: ["foo.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library_foo", + aconfig_declarations: "my_aconfig_declarations_foo", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_bar", + package: "com.example.package", + container: "myapex", + srcs: ["bar.aconfig"], + } + + cc_aconfig_library { + name: "my_cc_aconfig_library_bar", + aconfig_declarations: "my_aconfig_declarations_bar", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_baz", + package: "com.example.package", + container: "myapex", + srcs: ["baz.aconfig"], + } + + cc_aconfig_library { + name: "my_cc_aconfig_library_baz", + aconfig_declarations: "my_aconfig_declarations_baz", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + cc_library { + name: "server_configurable_flags", + srcs: ["server_configurable_flags.cc"], + } + `) + + mod := ctx.ModuleForTests("myapex", "android_common_myapex") + s := mod.Rule("apexRule").Args["copy_commands"] + copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) + if len(copyCmds) != 9 { + t.Fatalf("Expected 9 commands, got %d in:\n%s", len(copyCmds), s) + } + + ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex$") + + combineAconfigRule := mod.Rule("All_aconfig_declarations_dump") + s = " " + combineAconfigRule.Args["cache_files"] + aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:] + if len(aconfigArgs) != 3 { + t.Fatalf("Expected 3 commands, got %d in:\n%s", len(aconfigArgs), s) + } + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb") + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb") + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_baz/intermediate.pb") + + buildParams := combineAconfigRule.BuildParams + if len(buildParams.Inputs) != 3 { + t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs)) + } + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb") + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb") + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_baz/intermediate.pb") + ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb") +} + +func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) { + ctx := testApex(t, apex_default_bp+` + apex { + name: "myapex", + manifest: ":myapex.manifest", + androidManifest: ":myapex.androidmanifest", + key: "myapex.key", + java_libs: [ + "my_java_library_foo", + "other_java_library_bar", + ], + updatable: false, + } + + java_library { + name: "my_java_library_foo", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["my_java_aconfig_library_foo"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + java_library { + name: "other_java_library_bar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["other_java_aconfig_library_bar"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_foo", + package: "com.example.package", + container: "myapex", + srcs: ["foo.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library_foo", + aconfig_declarations: "my_aconfig_declarations_foo", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "other_aconfig_declarations_bar", + package: "com.example.package", + container: "otherapex", + srcs: ["bar.aconfig"], + } + + java_aconfig_library { + name: "other_java_aconfig_library_bar", + aconfig_declarations: "other_aconfig_declarations_bar", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + `) + + mod := ctx.ModuleForTests("myapex", "android_common_myapex") + combineAconfigRule := mod.Rule("All_aconfig_declarations_dump") + s := " " + combineAconfigRule.Args["cache_files"] + aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:] + if len(aconfigArgs) != 1 { + t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s) + } + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb") + + buildParams := combineAconfigRule.BuildParams + if len(buildParams.Inputs) != 1 { + t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs)) + } + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb") + ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb") +} + +func TestAconfigFilesRemoveDuplicates(t *testing.T) { + ctx := testApex(t, apex_default_bp+` + apex { + name: "myapex", + manifest: ":myapex.manifest", + androidManifest: ":myapex.androidmanifest", + key: "myapex.key", + java_libs: [ + "my_java_library_foo", + "my_java_library_bar", + ], + updatable: false, + } + + java_library { + name: "my_java_library_foo", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["my_java_aconfig_library_foo"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + java_library { + name: "my_java_library_bar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "none", + system_modules: "none", + static_libs: ["my_java_aconfig_library_bar"], + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + aconfig_declarations { + name: "my_aconfig_declarations_foo", + package: "com.example.package", + container: "myapex", + srcs: ["foo.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library_foo", + aconfig_declarations: "my_aconfig_declarations_foo", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + java_aconfig_library { + name: "my_java_aconfig_library_bar", + aconfig_declarations: "my_aconfig_declarations_foo", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + `) + + mod := ctx.ModuleForTests("myapex", "android_common_myapex") + combineAconfigRule := mod.Rule("All_aconfig_declarations_dump") + s := " " + combineAconfigRule.Args["cache_files"] + aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:] + if len(aconfigArgs) != 1 { + t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s) + } + android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb") + + buildParams := combineAconfigRule.BuildParams + if len(buildParams.Inputs) != 1 { + t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs)) + } + android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb") + ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb") +} diff --git a/apex/builder.go b/apex/builder.go index 3f358acd4..30788630b 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -24,6 +24,7 @@ import ( "strconv" "strings" + "android/soong/aconfig" "android/soong/android" "android/soong/java" @@ -36,6 +37,7 @@ var ( ) func init() { + pctx.Import("android/soong/aconfig") pctx.Import("android/soong/android") pctx.Import("android/soong/cc/config") pctx.Import("android/soong/java") @@ -80,6 +82,7 @@ func init() { pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config") pctx.HostBinToolVariable("assemble_vintf", "assemble_vintf") pctx.HostBinToolVariable("apex_elf_checker", "apex_elf_checker") + pctx.HostBinToolVariable("aconfig", "aconfig") } var ( @@ -574,6 +577,7 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) { installMapSet[installMapPath.String()+":"+fi.installDir+"/"+fi.builtFile.Base()] = true } + implicitInputs = append(implicitInputs, a.manifestPbOut) if len(installMapSet) > 0 { @@ -628,10 +632,28 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) { outHostBinDir := ctx.Config().HostToolPath(ctx, "").String() prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin") + defaultReadOnlyFiles := []string{"apex_manifest.json", "apex_manifest.pb"} + if len(a.aconfigFiles) > 0 { + apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb") + ctx.Build(pctx, android.BuildParams{ + Rule: aconfig.AllDeclarationsRule, + Inputs: a.aconfigFiles, + Output: apexAconfigFile, + Description: "combine_aconfig_declarations", + Args: map[string]string{ + "cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "), + }, + }) + + copyCommands = append(copyCommands, "cp -f "+apexAconfigFile.String()+" "+imageDir.String()) + implicitInputs = append(implicitInputs, apexAconfigFile) + defaultReadOnlyFiles = append(defaultReadOnlyFiles, apexAconfigFile.Base()) + } + //////////////////////////////////////////////////////////////////////////////////// // Step 2: create canned_fs_config which encodes filemode,uid,gid of each files // in this APEX. The file will be used by apexer in later steps. - cannedFsConfig := a.buildCannedFsConfig(ctx) + cannedFsConfig := a.buildCannedFsConfig(ctx, defaultReadOnlyFiles) implicitInputs = append(implicitInputs, cannedFsConfig) //////////////////////////////////////////////////////////////////////////////////// @@ -1082,8 +1104,8 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) { a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build()) } -func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath { - var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"} +func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext, defaultReadOnlyFiles []string) android.OutputPath { + var readOnlyPaths = defaultReadOnlyFiles var executablePaths []string // this also includes dirs var appSetDirs []string appSetFiles := make(map[string]android.Path) diff --git a/cc/Android.bp b/cc/Android.bp index 77e96db35..06e0e5efc 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -9,6 +9,7 @@ bootstrap_go_package { "blueprint", "blueprint-pathtools", "soong", + "soong-aconfig", "soong-aidl-library", "soong-android", "soong-bazel", diff --git a/cc/cc.go b/cc/cc.go index e215438f2..d2518a135 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -30,6 +30,7 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/proptools" + "android/soong/aconfig" "android/soong/aidl_library" "android/soong/android" "android/soong/bazel/cquery" @@ -923,6 +924,9 @@ type Module struct { apexSdkVersion android.ApiLevel hideApexVariantFromMake bool + + // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo + transitiveAconfigFiles map[string]*android.DepSet[android.Path] } func (c *Module) AddJSONData(d *map[string]interface{}) { @@ -2335,6 +2339,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } + aconfig.CollectTransitiveAconfigFiles(ctx, &c.transitiveAconfigFiles) + c.maybeInstall(ctx, apexInfo) } diff --git a/java/Android.bp b/java/Android.bp index cf968713c..6020d0048 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -9,6 +9,7 @@ bootstrap_go_package { "blueprint", "blueprint-pathtools", "soong", + "soong-aconfig", "soong-android", "soong-bazel", "soong-cc", diff --git a/java/androidmk.go b/java/androidmk.go index 84f78c89b..fb3fefa5a 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -128,8 +128,8 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if library.dexpreopter.configPath != nil { entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath) } - - entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", library.getTransitiveAconfigFiles().ToList()) + // TODO(b/311155208): The container here should be system. + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", library.getTransitiveAconfigFiles("")) }, }, }) @@ -306,7 +306,8 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { if len(binary.dexpreopter.builtInstalled) > 0 { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled) } - entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", binary.getTransitiveAconfigFiles().ToList()) + // TODO(b/311155208): The container here should be system. + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", binary.getTransitiveAconfigFiles("")) }, }, ExtraFooters: []android.AndroidMkExtraFootersFunc{ @@ -459,7 +460,8 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports) if app.Name() != "framework-res" { - entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", app.getTransitiveAconfigFiles().ToList()) + // TODO(b/311155208): The container here should be system. + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", app.getTransitiveAconfigFiles("")) } }, }, @@ -537,7 +539,8 @@ func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries { entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile) entries.AddStrings("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.exportedProguardFlagFiles.Strings()...) entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true) - entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", a.getTransitiveAconfigFiles().ToList()) + // TODO(b/311155208): The container here should be system. + entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", a.getTransitiveAconfigFiles("")) }) return entriesList diff --git a/java/base.go b/java/base.go index fdc164e11..3bbae2eed 100644 --- a/java/base.go +++ b/java/base.go @@ -25,6 +25,7 @@ import ( "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" + "android/soong/aconfig" "android/soong/android" "android/soong/dexpreopt" "android/soong/java/config" @@ -512,13 +513,8 @@ type Module struct { // or the module should override Stem(). stem string - // Aconfig "cache files" that went directly into this module. Transitive ones are - // tracked via JavaInfo.TransitiveAconfigFiles - // TODO: Extract to something standalone to propagate tags via GeneratedJavaLibraryModule - aconfigIntermediates android.Paths - - // Aconfig files for all transitive deps. Also exposed via JavaInfo - transitiveAconfigFiles *android.DepSet[android.Path] + // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo + transitiveAconfigFiles map[string]*android.DepSet[android.Path] } func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error { @@ -1723,7 +1719,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath ctx.CheckbuildFile(outputFile) - j.collectTransitiveAconfigFiles(ctx) + aconfig.CollectTransitiveAconfigFiles(ctx, &j.transitiveAconfigFiles) ctx.SetProvider(JavaInfoProvider, JavaInfo{ HeaderJars: android.PathsIfNonNil(j.headerJarFile), @@ -1740,7 +1736,6 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath ExportedPluginClasses: j.exportedPluginClasses, ExportedPluginDisableTurbine: j.exportedDisableTurbine, JacocoReportClassesFile: j.jacocoReportClassesFile, - TransitiveAconfigFiles: j.transitiveAconfigFiles, }) // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource @@ -2081,32 +2076,8 @@ func (j *Module) IsInstallable() bool { return Bool(j.properties.Installable) } -func (j *Module) collectTransitiveAconfigFiles(ctx android.ModuleContext) { - // Aconfig files from this module - mine := j.aconfigIntermediates - - // Aconfig files from transitive dependencies - fromDeps := []*android.DepSet[android.Path]{} - ctx.VisitDirectDeps(func(module android.Module) { - dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) - if dep.TransitiveAconfigFiles != nil { - fromDeps = append(fromDeps, dep.TransitiveAconfigFiles) - } - }) - - // DepSet containing aconfig files myself and from dependencies - j.transitiveAconfigFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps) -} - -func (j *Module) AddAconfigIntermediate(path android.Path) { - j.aconfigIntermediates = append(j.aconfigIntermediates, path) -} - -func (j *Module) getTransitiveAconfigFiles() *android.DepSet[android.Path] { - if j.transitiveAconfigFiles == nil { - panic(fmt.Errorf("java.Moduile: getTransitiveAconfigFiles called before collectTransitiveAconfigFiles module=%s", j.Name())) - } - return j.transitiveAconfigFiles +func (j *Module) getTransitiveAconfigFiles(container string) []android.Path { + return j.transitiveAconfigFiles[container].ToList() } type sdkLinkType int diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go index 7fbbfee22..ac9524e07 100644 --- a/java/generated_java_library_test.go +++ b/java/generated_java_library_test.go @@ -37,7 +37,6 @@ func (callbacks *JavaGenLibTestCallbacks) DepsMutator(module *GeneratedJavaLibra } func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path { - module.AddAconfigIntermediate(android.PathForOutput(ctx, "aconfig_cache_file")) return android.PathForOutput(ctx, "blah.srcjar") } diff --git a/java/java.go b/java/java.go index bb9357cc7..4962698de 100644 --- a/java/java.go +++ b/java/java.go @@ -297,15 +297,6 @@ type JavaInfo struct { // JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be // instrumented by jacoco. JacocoReportClassesFile android.Path - - // set of aconfig flags for all transitive libs deps - // TODO(joeo): It would be nice if this were over in the aconfig package instead of here. - // In order to do that, generated_java_library would need a way doing - // collectTransitiveAconfigFiles with one of the callbacks, and having that automatically - // propagated. If we were to clean up more of the stuff on JavaInfo that's not part of - // core java rules (e.g. AidlIncludeDirs), then maybe adding more framework to do that would be - // worth it. - TransitiveAconfigFiles *android.DepSet[android.Path] } var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})