Add container property to aconfig_declarations.
Bug: 311155208 Test: Unit test Change-Id: I7b187138856d0144203961e82b6dad5e2f8eed9d
This commit is contained in:
parent
62093cf7fc
commit
eae7b36699
26 changed files with 750 additions and 146 deletions
|
@ -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"],
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
32
aconfig/codegen/Android.bp
Normal file
32
aconfig/codegen/Android.bp
Normal file
|
@ -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"],
|
||||
}
|
|
@ -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) {
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aconfig
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
83
aconfig/codegen/init.go
Normal file
83
aconfig/codegen/init.go
Normal file
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
|
@ -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) {
|
|
@ -1,4 +1,4 @@
|
|||
package aconfig
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
25
aconfig/codegen/testing.go
Normal file
25
aconfig/codegen/testing.go
Normal file
|
@ -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)
|
||||
})
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ bootstrap_go_package {
|
|||
deps: [
|
||||
"blueprint",
|
||||
"soong",
|
||||
"soong-aconfig",
|
||||
"soong-aconfig-codegen",
|
||||
"soong-android",
|
||||
"soong-bazel",
|
||||
"soong-bpf",
|
||||
|
|
18
apex/apex.go
18
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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -9,6 +9,7 @@ bootstrap_go_package {
|
|||
"blueprint",
|
||||
"blueprint-pathtools",
|
||||
"soong",
|
||||
"soong-aconfig",
|
||||
"soong-aidl-library",
|
||||
"soong-android",
|
||||
"soong-bazel",
|
||||
|
|
6
cc/cc.go
6
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ bootstrap_go_package {
|
|||
"blueprint",
|
||||
"blueprint-pathtools",
|
||||
"soong",
|
||||
"soong-aconfig",
|
||||
"soong-android",
|
||||
"soong-bazel",
|
||||
"soong-cc",
|
||||
|
|
|
@ -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
|
||||
|
|
41
java/base.go
41
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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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{})
|
||||
|
|
Loading…
Reference in a new issue