Validate aconfig libs are built with the correct modes.
Bug: 323071835 Test: Unit tests and manual tests. Change-Id: I32de90826c7c8bb4d8495608e959d554820ab9a2
This commit is contained in:
parent
eefca7373c
commit
67a28425a7
16 changed files with 696 additions and 32 deletions
|
@ -15,9 +15,10 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"android/soong/aconfig"
|
||||
"android/soong/android"
|
||||
"fmt"
|
||||
"maps"
|
||||
|
||||
"android/soong/android"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
@ -43,6 +44,7 @@ type AconfigDeclarationsGroup struct {
|
|||
aconfigDeclarationNames []string
|
||||
intermediateCacheOutputPaths android.Paths
|
||||
javaSrcjars android.Paths
|
||||
modeInfos map[string]android.ModeInfo
|
||||
}
|
||||
|
||||
type AconfigDeclarationsGroupProperties struct {
|
||||
|
@ -76,9 +78,10 @@ func (adg *AconfigDeclarationsGroup) DepsMutator(ctx android.BottomUpMutatorCont
|
|||
}
|
||||
|
||||
func (adg *AconfigDeclarationsGroup) VisitDeps(ctx android.ModuleContext) {
|
||||
adg.modeInfos = make(map[string]android.ModeInfo)
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
tag := ctx.OtherModuleDependencyTag(dep)
|
||||
if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok {
|
||||
if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
|
||||
|
||||
// aconfig declaration names and cache files are collected for all aconfig library dependencies
|
||||
adg.aconfigDeclarationNames = append(adg.aconfigDeclarationNames, provider.AconfigDeclarations...)
|
||||
|
@ -88,8 +91,14 @@ func (adg *AconfigDeclarationsGroup) VisitDeps(ctx android.ModuleContext) {
|
|||
case aconfigDeclarationsGroupTag:
|
||||
// Will retrieve outputs from another language codegen modules when support is added
|
||||
adg.javaSrcjars = append(adg.javaSrcjars, provider.Srcjars...)
|
||||
maps.Copy(adg.modeInfos, provider.ModeInfos)
|
||||
case javaAconfigLibraryTag:
|
||||
adg.javaSrcjars = append(adg.javaSrcjars, provider.Srcjars...)
|
||||
maps.Copy(adg.modeInfos, provider.ModeInfos)
|
||||
case ccAconfigLibraryTag:
|
||||
maps.Copy(adg.modeInfos, provider.ModeInfos)
|
||||
case rustAconfigLibraryTag:
|
||||
maps.Copy(adg.modeInfos, provider.ModeInfos)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -100,10 +109,11 @@ func (adg *AconfigDeclarationsGroup) GenerateAndroidBuildActions(ctx android.Mod
|
|||
adg.aconfigDeclarationNames = android.FirstUniqueStrings(adg.aconfigDeclarationNames)
|
||||
adg.intermediateCacheOutputPaths = android.FirstUniquePaths(adg.intermediateCacheOutputPaths)
|
||||
|
||||
android.SetProvider(ctx, aconfig.CodegenInfoProvider, aconfig.CodegenInfo{
|
||||
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
|
||||
AconfigDeclarations: adg.aconfigDeclarationNames,
|
||||
IntermediateCacheOutputPaths: adg.intermediateCacheOutputPaths,
|
||||
Srcjars: adg.javaSrcjars,
|
||||
ModeInfos: adg.modeInfos,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -146,4 +146,12 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex
|
|||
"mode": mode,
|
||||
},
|
||||
})
|
||||
|
||||
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
|
||||
ModeInfos: map[string]android.ModeInfo{
|
||||
ctx.ModuleName(): {
|
||||
Container: declarations.Container,
|
||||
Mode: mode,
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ package codegen
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"android/soong/aconfig"
|
||||
"android/soong/android"
|
||||
"android/soong/java"
|
||||
|
||||
|
@ -119,10 +118,15 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild
|
|||
module.AddJarJarRenameRule(declarations.Package+".FakeFeatureFlagsImpl", "")
|
||||
}
|
||||
|
||||
android.SetProvider(ctx, aconfig.CodegenInfoProvider, aconfig.CodegenInfo{
|
||||
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
|
||||
AconfigDeclarations: []string{declarationsModules[0].Name()},
|
||||
IntermediateCacheOutputPaths: android.Paths{declarations.IntermediateCacheOutputPath},
|
||||
Srcjars: android.Paths{srcJarPath},
|
||||
ModeInfos: map[string]android.ModeInfo{
|
||||
ctx.ModuleName(): {
|
||||
Container: declarations.Container,
|
||||
Mode: mode,
|
||||
}},
|
||||
})
|
||||
|
||||
return srcJarPath
|
||||
|
|
|
@ -85,6 +85,15 @@ func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.Path
|
|||
},
|
||||
})
|
||||
a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
|
||||
|
||||
android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
|
||||
ModeInfos: map[string]android.ModeInfo{
|
||||
ctx.ModuleName(): {
|
||||
Container: declarations.Container,
|
||||
Mode: mode,
|
||||
}},
|
||||
})
|
||||
|
||||
return generatedSource
|
||||
}
|
||||
|
||||
|
|
|
@ -20,20 +20,6 @@ import (
|
|||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
type CodegenInfo struct {
|
||||
// AconfigDeclarations is the name of the aconfig_declarations modules that
|
||||
// the codegen module is associated with
|
||||
AconfigDeclarations []string
|
||||
|
||||
// Paths to the cache files of the associated aconfig_declaration modules
|
||||
IntermediateCacheOutputPaths android.Paths
|
||||
|
||||
// Paths to the srcjar files generated from the java_aconfig_library modules
|
||||
Srcjars android.Paths
|
||||
}
|
||||
|
||||
var CodegenInfoProvider = blueprint.NewProvider[CodegenInfo]()
|
||||
|
||||
var (
|
||||
pctx = android.NewPackageContext("android/soong/aconfig")
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package android
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
|
@ -50,6 +51,35 @@ type AconfigTransitiveDeclarationsInfo struct {
|
|||
|
||||
var AconfigTransitiveDeclarationsInfoProvider = blueprint.NewProvider[AconfigTransitiveDeclarationsInfo]()
|
||||
|
||||
type ModeInfo struct {
|
||||
Container string
|
||||
Mode string
|
||||
}
|
||||
type CodegenInfo struct {
|
||||
// AconfigDeclarations is the name of the aconfig_declarations modules that
|
||||
// the codegen module is associated with
|
||||
AconfigDeclarations []string
|
||||
|
||||
// Paths to the cache files of the associated aconfig_declaration modules
|
||||
IntermediateCacheOutputPaths Paths
|
||||
|
||||
// Paths to the srcjar files generated from the java_aconfig_library modules
|
||||
Srcjars Paths
|
||||
|
||||
ModeInfos map[string]ModeInfo
|
||||
}
|
||||
|
||||
var CodegenInfoProvider = blueprint.NewProvider[CodegenInfo]()
|
||||
|
||||
func propagateModeInfos(ctx ModuleContext, module Module, to, from map[string]ModeInfo) {
|
||||
if len(from) > 0 {
|
||||
depTag := ctx.OtherModuleDependencyTag(module)
|
||||
if tag, ok := depTag.(PropagateAconfigValidationDependencyTag); ok && tag.PropagateAconfigValidation() {
|
||||
maps.Copy(to, from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CollectDependencyAconfigFiles is used by some module types to provide finer dependency graphing than
|
||||
// we can do in ModuleBase.
|
||||
func CollectDependencyAconfigFiles(ctx ModuleContext, mergedAconfigFiles *map[string]Paths) {
|
||||
|
@ -90,13 +120,40 @@ func SetAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFi
|
|||
|
||||
type aconfigPropagatingDeclarationsInfo struct {
|
||||
AconfigFiles map[string]Paths
|
||||
ModeInfos map[string]ModeInfo
|
||||
}
|
||||
|
||||
var aconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]()
|
||||
|
||||
func VerifyAconfigBuildMode(ctx ModuleContext, container string, module blueprint.Module, asError bool) {
|
||||
if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
|
||||
for k, v := range dep.ModeInfos {
|
||||
msg := fmt.Sprintf("%s/%s depends on %s/%s/%s across containers\n",
|
||||
module.Name(), container, k, v.Container, v.Mode)
|
||||
if v.Container != container && v.Mode != "exported" && v.Mode != "force-read-only" {
|
||||
if asError {
|
||||
ctx.ModuleErrorf(msg)
|
||||
} else {
|
||||
fmt.Printf("WARNING: " + msg)
|
||||
}
|
||||
} else {
|
||||
if !asError {
|
||||
fmt.Printf("PASSED: " + msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
|
||||
mergedAconfigFiles := make(map[string]Paths)
|
||||
mergedModeInfos := make(map[string]ModeInfo)
|
||||
|
||||
ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
|
||||
if aconfig_dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok && len(aconfig_dep.ModeInfos) > 0 {
|
||||
maps.Copy(mergedModeInfos, aconfig_dep.ModeInfos)
|
||||
}
|
||||
|
||||
// If any of our dependencies have aconfig declarations (directly or propagated), then merge those and provide them.
|
||||
if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
|
||||
mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath)
|
||||
|
@ -105,6 +162,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
|
|||
for container, v := range dep.AconfigFiles {
|
||||
mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
|
||||
}
|
||||
propagateModeInfos(ctx, module, mergedModeInfos, dep.ModeInfos)
|
||||
}
|
||||
if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok {
|
||||
for container, v := range dep.AconfigFiles {
|
||||
|
@ -120,6 +178,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
|
|||
|
||||
SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{
|
||||
AconfigFiles: mergedAconfigFiles,
|
||||
ModeInfos: mergedModeInfos,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package android
|
|||
// product variables necessary for soong_build's operation.
|
||||
|
||||
import (
|
||||
"android/soong/shared"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -30,6 +29,8 @@ import (
|
|||
"sync"
|
||||
"unicode"
|
||||
|
||||
"android/soong/shared"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/bootstrap"
|
||||
"github.com/google/blueprint/pathtools"
|
||||
|
@ -1932,6 +1933,10 @@ func (c *deviceConfig) GenerateAidlNdkPlatformBackend() bool {
|
|||
return c.config.productVariables.GenerateAidlNdkPlatformBackend
|
||||
}
|
||||
|
||||
func (c *deviceConfig) AconfigContainerValidation() string {
|
||||
return c.config.productVariables.AconfigContainerValidation
|
||||
}
|
||||
|
||||
func (c *config) IgnorePrefer32OnDevice() bool {
|
||||
return c.productVariables.IgnorePrefer32OnDevice
|
||||
}
|
||||
|
|
|
@ -43,3 +43,15 @@ func IsInstallDepNeededTag(tag blueprint.DependencyTag) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type PropagateAconfigValidationDependencyTag interface {
|
||||
PropagateAconfigValidation() bool
|
||||
}
|
||||
|
||||
type AlwaysPropagateAconfigValidationDependencyTag struct{}
|
||||
|
||||
func (p AlwaysPropagateAconfigValidationDependencyTag) PropagateAconfigValidation() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var _ PropagateAconfigValidationDependencyTag = AlwaysPropagateAconfigValidationDependencyTag{}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
package android
|
||||
|
||||
import (
|
||||
"android/soong/bazel"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
@ -27,6 +26,8 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"android/soong/bazel"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
@ -2087,6 +2088,7 @@ func isUnqualifiedModuleName(module string) bool {
|
|||
// caused by prebuilt_ prefix, or fully qualified module names.
|
||||
type sourceOrOutputDependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
AlwaysPropagateAconfigValidationDependencyTag
|
||||
|
||||
// The name of the module.
|
||||
moduleName string
|
||||
|
|
|
@ -500,6 +500,8 @@ type ProductVariables struct {
|
|||
HiddenapiExportableStubs *bool `json:",omitempty"`
|
||||
|
||||
ExportRuntimeApis *bool `json:",omitempty"`
|
||||
|
||||
AconfigContainerValidation string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type PartitionQualifiedVariablesType struct {
|
||||
|
|
550
apex/aconfig_test.go
Normal file
550
apex/aconfig_test.go
Normal file
|
@ -0,0 +1,550 @@
|
|||
// Copyright 2024 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 apex
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"android/soong/aconfig/codegen"
|
||||
"android/soong/android"
|
||||
"android/soong/cc"
|
||||
"android/soong/genrule"
|
||||
"android/soong/java"
|
||||
"android/soong/rust"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
var withAconfigValidationError = android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||
variables.AconfigContainerValidation = "error"
|
||||
variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
|
||||
})
|
||||
|
||||
func TestValidationAcrossContainersExportedPass(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
bp string
|
||||
}{
|
||||
{
|
||||
name: "Java lib passes for exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
java_libs: [
|
||||
"my_java_library_foo",
|
||||
],
|
||||
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"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["foo.aconfig"],
|
||||
exportable: true,
|
||||
}
|
||||
java_aconfig_library {
|
||||
name: "my_java_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
mode: "exported",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "Android app passes for exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
apps: [
|
||||
"my_android_app_foo",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
android_app {
|
||||
name: "my_android_app_foo",
|
||||
srcs: ["foo/MyClass.java"],
|
||||
sdk_version: "none",
|
||||
system_modules: "none",
|
||||
stl: "none",
|
||||
static_libs: ["my_java_library_bar"],
|
||||
apex_available: [ "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"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_bar",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["bar.aconfig"],
|
||||
exportable: true,
|
||||
}
|
||||
java_aconfig_library {
|
||||
name: "my_java_aconfig_library_bar",
|
||||
aconfig_declarations: "my_aconfig_declarations_bar",
|
||||
mode: "exported",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
},
|
||||
{
|
||||
name: "Cc lib passes for exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: [
|
||||
"my_cc_library_bar",
|
||||
],
|
||||
binaries: [
|
||||
"my_cc_binary_baz",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
cc_library {
|
||||
name: "my_cc_library_bar",
|
||||
srcs: ["foo/bar/MyClass.cc"],
|
||||
static_libs: [
|
||||
"my_cc_aconfig_library_bar",
|
||||
"my_cc_aconfig_library_baz",
|
||||
],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
cc_binary {
|
||||
name: "my_cc_binary_baz",
|
||||
srcs: ["foo/bar/MyClass.cc"],
|
||||
static_libs: ["my_cc_aconfig_library_baz"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
cc_library {
|
||||
name: "server_configurable_flags",
|
||||
srcs: ["server_configurable_flags.cc"],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_bar",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["bar.aconfig"],
|
||||
exportable: true,
|
||||
}
|
||||
cc_aconfig_library {
|
||||
name: "my_cc_aconfig_library_bar",
|
||||
aconfig_declarations: "my_aconfig_declarations_bar",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
mode: "exported",
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_baz",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["baz.aconfig"],
|
||||
exportable: true,
|
||||
}
|
||||
cc_aconfig_library {
|
||||
name: "my_cc_aconfig_library_baz",
|
||||
aconfig_declarations: "my_aconfig_declarations_baz",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
mode: "exported",
|
||||
}`,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
android.GroupFixturePreparers(
|
||||
java.PrepareForTestWithJavaDefaultModules,
|
||||
cc.PrepareForTestWithCcBuildComponents,
|
||||
rust.PrepareForTestWithRustDefaultModules,
|
||||
codegen.PrepareForTestWithAconfigBuildComponents,
|
||||
PrepareForTestWithApexBuildComponents,
|
||||
prepareForTestWithMyapex,
|
||||
withAconfigValidationError,
|
||||
).
|
||||
RunTestWithBp(t, test.bp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidationAcrossContainersNotExportedFail(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
expectedError string
|
||||
bp string
|
||||
}{
|
||||
{
|
||||
name: "Java lib fails for non-exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
java_libs: [
|
||||
"my_java_library_foo",
|
||||
],
|
||||
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"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["foo.aconfig"],
|
||||
}
|
||||
java_aconfig_library {
|
||||
name: "my_java_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
expectedError: `.*my_java_library_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
|
||||
},
|
||||
{
|
||||
name: "Android app fails for non-exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
apps: [
|
||||
"my_android_app_foo",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
android_app {
|
||||
name: "my_android_app_foo",
|
||||
srcs: ["foo/MyClass.java"],
|
||||
sdk_version: "none",
|
||||
system_modules: "none",
|
||||
stl: "none",
|
||||
static_libs: ["my_java_library_foo"],
|
||||
apex_available: [ "myapex" ],
|
||||
}
|
||||
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"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["bar.aconfig"],
|
||||
}
|
||||
java_aconfig_library {
|
||||
name: "my_java_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
|
||||
},
|
||||
{
|
||||
name: "Cc lib fails for non-exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: [
|
||||
"my_cc_library_foo",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
cc_library {
|
||||
name: "my_cc_library_foo",
|
||||
srcs: ["foo/bar/MyClass.cc"],
|
||||
shared_libs: [
|
||||
"my_cc_aconfig_library_foo",
|
||||
],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
cc_library {
|
||||
name: "server_configurable_flags",
|
||||
srcs: ["server_configurable_flags.cc"],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["foo.aconfig"],
|
||||
}
|
||||
cc_aconfig_library {
|
||||
name: "my_cc_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
expectedError: `.*my_cc_library_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
|
||||
},
|
||||
{
|
||||
name: "Cc binary fails for non-exported containers cross",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
binaries: [
|
||||
"my_cc_binary_foo",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
cc_library {
|
||||
name: "my_cc_library_foo",
|
||||
srcs: ["foo/bar/MyClass.cc"],
|
||||
static_libs: [
|
||||
"my_cc_aconfig_library_foo",
|
||||
],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
cc_binary {
|
||||
name: "my_cc_binary_foo",
|
||||
srcs: ["foo/bar/MyClass.cc"],
|
||||
static_libs: ["my_cc_library_foo"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
cc_library {
|
||||
name: "server_configurable_flags",
|
||||
srcs: ["server_configurable_flags.cc"],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["foo.aconfig"],
|
||||
}
|
||||
cc_aconfig_library {
|
||||
name: "my_cc_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
expectedError: `.*my_cc_binary_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
|
||||
},
|
||||
{
|
||||
name: "Aconfig validation propagate along sourceOrOutputDependencyTag",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
apps: [
|
||||
"my_android_app_foo",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
android_app {
|
||||
name: "my_android_app_foo",
|
||||
srcs: ["foo/MyClass.java"],
|
||||
sdk_version: "none",
|
||||
system_modules: "none",
|
||||
stl: "none",
|
||||
static_libs: ["my_java_library_foo"],
|
||||
apex_available: [ "myapex" ],
|
||||
}
|
||||
java_library {
|
||||
name: "my_java_library_foo",
|
||||
srcs: [":my_genrule_foo"],
|
||||
sdk_version: "none",
|
||||
system_modules: "none",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
aconfig_declarations_group {
|
||||
name: "my_aconfig_declarations_group_foo",
|
||||
java_aconfig_libraries: [
|
||||
"my_java_aconfig_library_foo",
|
||||
],
|
||||
}
|
||||
filegroup {
|
||||
name: "my_filegroup_foo_srcjars",
|
||||
srcs: [
|
||||
":my_aconfig_declarations_group_foo{.srcjars}",
|
||||
],
|
||||
}
|
||||
genrule {
|
||||
name: "my_genrule_foo",
|
||||
srcs: [":my_filegroup_foo_srcjars"],
|
||||
cmd: "cp $(in) $(out)",
|
||||
out: ["my_genrule_foo.srcjar"],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["bar.aconfig"],
|
||||
}
|
||||
java_aconfig_library {
|
||||
name: "my_java_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
errorHandler := android.FixtureExpectsNoErrors
|
||||
if test.expectedError != "" {
|
||||
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
|
||||
}
|
||||
android.GroupFixturePreparers(
|
||||
java.PrepareForTestWithJavaDefaultModules,
|
||||
cc.PrepareForTestWithCcBuildComponents,
|
||||
rust.PrepareForTestWithRustDefaultModules,
|
||||
codegen.PrepareForTestWithAconfigBuildComponents,
|
||||
genrule.PrepareForIntegrationTestWithGenrule,
|
||||
PrepareForTestWithApexBuildComponents,
|
||||
prepareForTestWithMyapex,
|
||||
withAconfigValidationError,
|
||||
).
|
||||
ExtendWithErrorHandler(errorHandler).
|
||||
RunTestWithBp(t, test.bp)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidationNotPropagateAcrossShared(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
bp string
|
||||
}{
|
||||
{
|
||||
name: "Java shared lib not propagate aconfig validation",
|
||||
bp: apex_default_bp + `
|
||||
apex {
|
||||
name: "myapex",
|
||||
manifest: ":myapex.manifest",
|
||||
androidManifest: ":myapex.androidmanifest",
|
||||
key: "myapex.key",
|
||||
java_libs: [
|
||||
"my_java_library_bar",
|
||||
],
|
||||
updatable: false,
|
||||
}
|
||||
java_library {
|
||||
name: "my_java_library_bar",
|
||||
srcs: ["foo/bar/MyClass.java"],
|
||||
sdk_version: "none",
|
||||
system_modules: "none",
|
||||
libs: ["my_java_library_foo"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
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"],
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}
|
||||
aconfig_declarations {
|
||||
name: "my_aconfig_declarations_foo",
|
||||
package: "com.example.package",
|
||||
container: "otherapex",
|
||||
srcs: ["foo.aconfig"],
|
||||
}
|
||||
java_aconfig_library {
|
||||
name: "my_java_aconfig_library_foo",
|
||||
aconfig_declarations: "my_aconfig_declarations_foo",
|
||||
apex_available: [
|
||||
"myapex",
|
||||
],
|
||||
}`,
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
android.GroupFixturePreparers(
|
||||
java.PrepareForTestWithJavaDefaultModules,
|
||||
cc.PrepareForTestWithCcBuildComponents,
|
||||
rust.PrepareForTestWithRustDefaultModules,
|
||||
codegen.PrepareForTestWithAconfigBuildComponents,
|
||||
PrepareForTestWithApexBuildComponents,
|
||||
prepareForTestWithMyapex,
|
||||
withAconfigValidationError,
|
||||
).
|
||||
RunTestWithBp(t, test.bp)
|
||||
})
|
||||
}
|
||||
}
|
12
apex/apex.go
12
apex/apex.go
|
@ -2321,9 +2321,15 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
|
|||
}
|
||||
|
||||
func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) {
|
||||
dep, _ := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider)
|
||||
if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
|
||||
vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
|
||||
if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider); ok {
|
||||
if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
|
||||
vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
|
||||
}
|
||||
}
|
||||
|
||||
validationFlag := ctx.DeviceConfig().AconfigContainerValidation()
|
||||
if validationFlag == "error" || validationFlag == "warning" {
|
||||
android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), module, validationFlag == "error")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
6
cc/cc.go
6
cc/cc.go
|
@ -766,6 +766,12 @@ func (d libraryDependencyTag) InstallDepNeeded() bool {
|
|||
|
||||
var _ android.InstallNeededDependencyTag = libraryDependencyTag{}
|
||||
|
||||
func (d libraryDependencyTag) PropagateAconfigValidation() bool {
|
||||
return d.static()
|
||||
}
|
||||
|
||||
var _ android.PropagateAconfigValidationDependencyTag = libraryDependencyTag{}
|
||||
|
||||
// dependencyTag is used for tagging miscellaneous dependency types that don't fit into
|
||||
// libraryDependencyTag. Each tag object is created globally and reused for multiple
|
||||
// dependencies (although since the object contains no references, assigning a tag to a
|
||||
|
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/google/blueprint/pathtools"
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/aconfig"
|
||||
"android/soong/android"
|
||||
"android/soong/dexpreopt"
|
||||
"android/soong/java/config"
|
||||
|
@ -2546,7 +2545,7 @@ func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProvid
|
|||
default:
|
||||
return RenameUseExclude, "srcfile"
|
||||
}
|
||||
} else if _, ok := android.OtherModuleProvider(ctx, m, aconfig.CodegenInfoProvider); ok {
|
||||
} else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
|
||||
return RenameUseInclude, "aconfig_declarations_group"
|
||||
} else {
|
||||
switch tag {
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/aconfig"
|
||||
"android/soong/android"
|
||||
"android/soong/java/config"
|
||||
)
|
||||
|
@ -414,7 +413,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
|
|||
case aconfigDeclarationTag:
|
||||
if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
|
||||
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
|
||||
} else if dep, ok := android.OtherModuleProvider(ctx, module, aconfig.CodegenInfoProvider); ok {
|
||||
} else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
|
||||
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
|
||||
} else {
|
||||
ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
|
||||
|
|
13
java/java.go
13
java/java.go
|
@ -24,7 +24,6 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"android/soong/aconfig"
|
||||
"android/soong/remoteexec"
|
||||
"android/soong/testing"
|
||||
|
||||
|
@ -346,6 +345,12 @@ func (j *Module) XrefJavaFiles() android.Paths {
|
|||
return j.kytheFiles
|
||||
}
|
||||
|
||||
func (d dependencyTag) PropagateAconfigValidation() bool {
|
||||
return d.static
|
||||
}
|
||||
|
||||
var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
|
||||
|
||||
type dependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
name string
|
||||
|
@ -355,6 +360,8 @@ type dependencyTag struct {
|
|||
|
||||
// True if the dependency is a toolchain, for example an annotation processor.
|
||||
toolchain bool
|
||||
|
||||
static bool
|
||||
}
|
||||
|
||||
// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
|
||||
|
@ -400,7 +407,7 @@ func IsJniDepTag(depTag blueprint.DependencyTag) bool {
|
|||
var (
|
||||
dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
|
||||
dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
|
||||
staticLibTag = dependencyTag{name: "staticlib"}
|
||||
staticLibTag = dependencyTag{name: "staticlib", static: true}
|
||||
libTag = dependencyTag{name: "javalib", runtimeLinked: true}
|
||||
sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true}
|
||||
java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
|
||||
|
@ -2172,7 +2179,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
case aconfigDeclarationTag:
|
||||
if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
|
||||
al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPath)
|
||||
} else if provider, ok := android.OtherModuleProvider(ctx, dep, aconfig.CodegenInfoProvider); ok {
|
||||
} else if provider, ok := android.OtherModuleProvider(ctx, dep, android.CodegenInfoProvider); ok {
|
||||
al.aconfigProtoFiles = append(al.aconfigProtoFiles, provider.IntermediateCacheOutputPaths...)
|
||||
} else {
|
||||
ctx.ModuleErrorf("Only aconfig_declarations and aconfig_declarations_group "+
|
||||
|
|
Loading…
Reference in a new issue