[automerger skipped] Add global C flags to compile_commands am: b763553ed3 -s ours
am skip reason: Merged-In Id583da6eb5151a9baa9a47771f5f937c88bc43f7 with SHA-1 342fa6b927 is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/soong/+/26769180
Change-Id: I2a557710a811c535ca5ffa461dded64b7946613a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 392e819..d29e312 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -137,18 +137,22 @@
inputFiles := make([]android.Path, len(declarationFiles))
copy(inputFiles, declarationFiles)
inputFiles = append(inputFiles, valuesFiles...)
+ args := map[string]string{
+ "release_version": ctx.Config().ReleaseVersion(),
+ "package": module.properties.Package,
+ "declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
+ "values": joinAndPrefix(" --values ", module.properties.Values),
+ "default-permission": optionalVariable(" --default-permission ", defaultPermission),
+ }
+ if len(module.properties.Container) > 0 {
+ args["container"] = "--container " + module.properties.Container
+ }
ctx.Build(pctx, android.BuildParams{
Rule: aconfigRule,
Output: intermediateCacheFilePath,
Inputs: inputFiles,
Description: "aconfig_declarations",
- Args: map[string]string{
- "release_version": ctx.Config().ReleaseVersion(),
- "package": module.properties.Package,
- "declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
- "values": joinAndPrefix(" --values ", module.properties.Values),
- "default-permission": optionalVariable(" --default-permission ", defaultPermission),
- },
+ Args: args,
})
intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt")
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index 1fe3c86..5201fed 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -69,3 +69,38 @@
depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
android.AssertBoolEquals(t, "exportable", depData.Exportable, false)
}
+
+func TestAconfigDeclarationsWithContainer(t *testing.T) {
+ bp := `
+ aconfig_declarations {
+ name: "module_name",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "foo.aconfig",
+ ],
+ }
+ `
+ result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module_name", "")
+ rule := module.Rule("aconfig")
+ android.AssertStringEquals(t, "rule must contain container", rule.Args["container"], "--container com.android.foo")
+}
+
+func TestAconfigDeclarationsWithoutContainer(t *testing.T) {
+ bp := `
+ aconfig_declarations {
+ name: "module_name",
+ package: "com.example.package",
+ srcs: [
+ "foo.aconfig",
+ ],
+ }
+ `
+ result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module_name", "")
+ rule := module.Rule("aconfig")
+ android.AssertIntEquals(t, "rule must not contain container", len(rule.Args["container"]), 0)
+}
diff --git a/aconfig/codegen/aconfig_declarations_group.go b/aconfig/codegen/aconfig_declarations_group.go
index 203b6be..1c91bee 100644
--- a/aconfig/codegen/aconfig_declarations_group.go
+++ b/aconfig/codegen/aconfig_declarations_group.go
@@ -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 @@
aconfigDeclarationNames []string
intermediateCacheOutputPaths android.Paths
javaSrcjars android.Paths
+ modeInfos map[string]android.ModeInfo
}
type AconfigDeclarationsGroupProperties struct {
@@ -76,9 +78,10 @@
}
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 @@
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 @@
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,
})
}
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index 50cd4de..80e4926 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -146,4 +146,12 @@
"mode": mode,
},
})
+
+ android.SetProvider(ctx, android.CodegenInfoProvider, android.CodegenInfo{
+ ModeInfos: map[string]android.ModeInfo{
+ ctx.ModuleName(): {
+ Container: declarations.Container,
+ Mode: mode,
+ }},
+ })
}
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index 7d7296e..1378dfe 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -17,7 +17,6 @@
import (
"fmt"
- "android/soong/aconfig"
"android/soong/android"
"android/soong/java"
@@ -92,12 +91,12 @@
if !isModeSupported(mode) {
ctx.PropertyErrorf("mode", "%q is not a supported mode", mode)
}
- // TODO: uncomment this part after internal clean up
- //if mode == "exported" && !declarations.Exportable {
- // // if mode is exported, the corresponding aconfig_declaration must mark its
- // // exportable property true
- // ctx.PropertyErrorf("mode", "exported mode requires its aconfig_declaration has exportable prop true")
- //}
+
+ if mode == "exported" && !declarations.Exportable {
+ // if mode is exported, the corresponding aconfig_declaration must mark its
+ // exportable property true
+ ctx.PropertyErrorf("mode", "exported mode requires its aconfig_declaration has exportable prop true")
+ }
ctx.Build(pctx, android.BuildParams{
Rule: javaRule,
@@ -119,10 +118,15 @@
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
diff --git a/aconfig/codegen/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
index 2ab54b6..ad8d632 100644
--- a/aconfig/codegen/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -85,13 +85,25 @@
},
})
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
}
func (a *aconfigDecorator) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps {
deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps)
+ deps.Rustlibs = append(deps.Rustlibs, "libaconfig_storage_read_api")
deps.Rustlibs = append(deps.Rustlibs, "libflags_rust")
deps.Rustlibs = append(deps.Rustlibs, "liblazy_static")
+ deps.Rustlibs = append(deps.Rustlibs, "liblogger")
+ deps.Rustlibs = append(deps.Rustlibs, "liblog_rust")
ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations)
return deps
}
diff --git a/aconfig/codegen/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go
index 60bc9f7..fe28f94 100644
--- a/aconfig/codegen/rust_aconfig_library_test.go
+++ b/aconfig/codegen/rust_aconfig_library_test.go
@@ -11,7 +11,7 @@
func TestRustAconfigLibrary(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithAconfigBuildComponents,
- rust.PrepareForTestWithRustIncludeVndk,
+ rust.PrepareForIntegrationTestWithRust,
android.PrepareForTestWithArchMutator,
android.PrepareForTestWithDefaults,
android.PrepareForTestWithPrebuilts,
@@ -28,6 +28,21 @@
crate_name: "lazy_static",
srcs: ["src/lib.rs"],
}
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["lib.rs"],
+ }
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
@@ -85,7 +100,7 @@
t.Helper()
result := android.GroupFixturePreparers(
PrepareForTestWithAconfigBuildComponents,
- rust.PrepareForTestWithRustIncludeVndk).
+ rust.PrepareForIntegrationTestWithRust).
ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
RunTestWithBp(t, fmt.Sprintf(`
rust_library {
@@ -98,6 +113,21 @@
crate_name: "lazy_static",
srcs: ["src/lib.rs"],
}
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["lib.rs"],
+ }
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
@@ -132,7 +162,7 @@
t.Helper()
android.GroupFixturePreparers(
PrepareForTestWithAconfigBuildComponents,
- rust.PrepareForTestWithRustIncludeVndk).
+ rust.PrepareForIntegrationTestWithRust).
ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)).
RunTestWithBp(t, fmt.Sprintf(`
rust_library {
@@ -145,6 +175,21 @@
crate_name: "lazy_static",
srcs: ["src/lib.rs"],
}
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["lib.rs"],
+ }
aconfig_declarations {
name: "my_aconfig_declarations",
package: "com.example.package",
diff --git a/aconfig/init.go b/aconfig/init.go
index e64429f..4655467 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -20,20 +20,6 @@
"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")
@@ -42,6 +28,7 @@
blueprint.RuleParams{
Command: `${aconfig} create-cache` +
` --package ${package}` +
+ ` ${container}` +
` ${declarations}` +
` ${values}` +
` ${default-permission}` +
@@ -52,7 +39,7 @@
"${aconfig}",
},
Restat: true,
- }, "release_version", "package", "declarations", "values", "default-permission")
+ }, "release_version", "package", "container", "declarations", "values", "default-permission")
// For create-device-config-sysprops: Generate aconfig flag value map text file
aconfigTextRule = pctx.AndroidStaticRule("aconfig_text",
diff --git a/android/Android.bp b/android/Android.bp
index e73f355..03619f4 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -16,7 +16,6 @@
"soong-remoteexec",
"soong-response",
"soong-shared",
- "soong-starlark",
"soong-starlark-format",
"soong-ui-metrics_proto",
"soong-android-allowlists",
@@ -135,6 +134,7 @@
"rule_builder_test.go",
"sdk_version_test.go",
"sdk_test.go",
+ "selects_test.go",
"singleton_module_test.go",
"soong_config_modules_test.go",
"util_test.go",
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index 74c1a5e..4c1782b 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -17,6 +17,7 @@
import (
"fmt"
"io"
+ "maps"
"reflect"
"github.com/google/blueprint"
@@ -50,6 +51,35 @@
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) {
@@ -75,7 +105,8 @@
}
})
- for container, aconfigFiles := range *mergedAconfigFiles {
+ for _, container := range SortedKeys(*mergedAconfigFiles) {
+ aconfigFiles := (*mergedAconfigFiles)[container]
(*mergedAconfigFiles)[container] = mergeAconfigFiles(ctx, container, aconfigFiles, false)
}
@@ -90,13 +121,40 @@
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 +163,7 @@
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 {
@@ -114,12 +173,14 @@
})
// We only need to set the provider if we have aconfig files.
if len(mergedAconfigFiles) > 0 {
- for container, aconfigFiles := range mergedAconfigFiles {
+ for _, container := range SortedKeys(mergedAconfigFiles) {
+ aconfigFiles := mergedAconfigFiles[container]
mergedAconfigFiles[container] = mergeAconfigFiles(ctx, container, aconfigFiles, true)
}
SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{
AconfigFiles: mergedAconfigFiles,
+ ModeInfos: mergedModeInfos,
})
}
}
diff --git a/android/apex.go b/android/apex.go
index 4d36a93..8759905 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -976,3 +976,18 @@
// Map from the apex library name (without prebuilt_ prefix) to the dex file path on host
LibraryNameToDexJarPathOnHost map[string]Path
}
+
+var PrebuiltInfoProvider = blueprint.NewProvider[PrebuiltInfo]()
+
+// contents of prebuilt_info.json
+type PrebuiltInfo struct {
+ // Name of the apex, without the prebuilt_ prefix
+ Name string
+
+ Is_prebuilt bool
+
+ // This is relative to root of the workspace.
+ // In case of mainline modules, this file contains the build_id that was used
+ // to generate the mainline module prebuilt.
+ Prebuilt_info_file_path string `json:",omitempty"`
+}
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index c388aff..dd09fbf 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -27,11 +27,13 @@
func RegisterApexContributionsBuildComponents(ctx RegistrationContext) {
ctx.RegisterModuleType("apex_contributions", apexContributionsFactory)
+ ctx.RegisterModuleType("apex_contributions_defaults", apexContributionsDefaultsFactory)
ctx.RegisterSingletonModuleType("all_apex_contributions", allApexContributionsFactory)
}
type apexContributions struct {
ModuleBase
+ DefaultableModuleBase
properties contributionProps
}
@@ -61,6 +63,7 @@
module := &apexContributions{}
module.AddProperties(&module.properties)
InitAndroidModule(module)
+ InitDefaultableModule(module)
return module
}
@@ -70,6 +73,18 @@
func (m *apexContributions) GenerateAndroidBuildActions(ctx ModuleContext) {
}
+type apexContributionsDefaults struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func apexContributionsDefaultsFactory() Module {
+ module := &apexContributionsDefaults{}
+ module.AddProperties(&contributionProps{})
+ InitDefaultsModule(module)
+ return module
+}
+
// A container for apex_contributions.
// Based on product_config, it will create a dependency on the selected
// apex_contributions per mainline module
@@ -100,10 +115,6 @@
func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
for _, content := range m.Contents() {
- // Skip any apexes that have been added to the product specific ignore list
- if InList(content, ctx.Config().BuildIgnoreApexContributionContents()) {
- continue
- }
// Coverage builds for TARGET_RELEASE=foo should always build from source,
// even if TARGET_RELEASE=foo uses prebuilt mainline modules.
// This is necessary because the checked-in prebuilts were generated with
@@ -126,13 +137,19 @@
}
p := PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
- if m, ok := child.(*apexContributions); ok {
- addContentsToProvider(&p, m)
- } else {
- ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
- }
- })
+ // Skip apex_contributions if BuildApexContributionContents is true
+ // This product config var allows some products in the same family to use mainline modules from source
+ // (e.g. shiba and shiba_fullmte)
+ // Eventually these product variants will have their own release config maps.
+ if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) {
+ ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
+ if m, ok := child.(*apexContributions); ok {
+ addContentsToProvider(&p, m)
+ } else {
+ ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
+ }
+ })
+ }
SetProvider(ctx, PrebuiltSelectionInfoProvider, p)
}
diff --git a/android/api_levels.go b/android/api_levels.go
index 6fa4a0e..fab5fc7 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -15,7 +15,6 @@
package android
import (
- "android/soong/starlark_import"
"encoding/json"
"fmt"
"strconv"
@@ -290,6 +289,8 @@
var ApiLevelR = uncheckedFinalApiLevel(30)
+var ApiLevelUpsideDownCake = uncheckedFinalApiLevel(34)
+
// ReplaceFinalizedCodenames returns the API level number associated with that API level
// if the `raw` input is the codename of an API level has been finalized.
// If the input is *not* a finalized codename, the input is returned unmodified.
@@ -440,7 +441,28 @@
}
func getApiLevelsMapReleasedVersions() (map[string]int, error) {
- return starlark_import.GetStarlarkValue[map[string]int]("api_levels_released_versions")
+ return map[string]int{
+ "G": 9,
+ "I": 14,
+ "J": 16,
+ "J-MR1": 17,
+ "J-MR2": 18,
+ "K": 19,
+ "L": 21,
+ "L-MR1": 22,
+ "M": 23,
+ "N": 24,
+ "N-MR1": 25,
+ "O": 26,
+ "O-MR1": 27,
+ "P": 28,
+ "Q": 29,
+ "R": 30,
+ "S": 31,
+ "S-V2": 32,
+ "Tiramisu": 33,
+ "UpsideDownCake": 34,
+ }, nil
}
var finalCodenamesMapKey = NewOnceKey("FinalCodenamesMap")
diff --git a/android/arch.go b/android/arch.go
index 4fe4345..9e79e31 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -693,6 +693,7 @@
m.base().commonProperties.CompileTarget = target
m.base().commonProperties.CompileMultiTargets = multiTargets
m.base().commonProperties.CompilePrimary = primaryTarget
+ m.base().commonProperties.ArchReady = true
}
// decodeMultilib returns the appropriate compile_multilib property for the module, or the default
diff --git a/android/arch_module_context.go b/android/arch_module_context.go
index 3cf4b41..a3a03af 100644
--- a/android/arch_module_context.go
+++ b/android/arch_module_context.go
@@ -35,6 +35,7 @@
type archModuleContext struct {
// TODO: these should eventually go through a (possibly cached) provider like any other configuration instead
// of being special cased.
+ ready bool
os OsType
target Target
targetPrimary bool
@@ -42,6 +43,13 @@
primaryArch bool
}
+// ArchReady returns true if the arch mutator has run on the module. Before this returns
+// true, the module essentially doesn't have an arch and cannot make decisions based on
+// architecture.
+func (a *archModuleContext) ArchReady() bool {
+ return a.ready
+}
+
func (a *archModuleContext) Target() Target {
return a.target
}
diff --git a/android/base_module_context.go b/android/base_module_context.go
index b9c1153..c4922f4 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -16,9 +16,11 @@
import (
"fmt"
- "github.com/google/blueprint"
"regexp"
"strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/parser"
)
// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
@@ -214,6 +216,10 @@
// getMissingDependencies returns the list of missing dependencies.
// Calling this function prevents adding new dependencies.
getMissingDependencies() []string
+
+ // EvaluateConfiguration makes ModuleContext a valid proptools.ConfigurableEvaluator, so this context
+ // can be used to evaluate the final value of Configurable properties.
+ EvaluateConfiguration(parser.SelectType, string, string) (string, bool)
}
type baseModuleContext struct {
@@ -299,6 +305,12 @@
AllowDisabledModuleDependency(target Module) bool
}
+type AlwaysAllowDisabledModuleDependencyTag struct{}
+
+func (t AlwaysAllowDisabledModuleDependencyTag) AllowDisabledModuleDependency(Module) bool {
+ return true
+}
+
func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
aModule, _ := module.(Module)
@@ -564,3 +576,7 @@
}
return sb.String()
}
+
+func (m *baseModuleContext) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) {
+ return m.Module().ConfigurableEvaluator(m).EvaluateConfiguration(ty, property, condition)
+}
diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go
index 8e19ad5..8288fc5 100644
--- a/android/buildinfo_prop.go
+++ b/android/buildinfo_prop.go
@@ -54,6 +54,39 @@
return Paths{p.outputFilePath}, nil
}
+func getBuildVariant(config Config) string {
+ if config.Eng() {
+ return "eng"
+ } else if config.Debuggable() {
+ return "userdebug"
+ } else {
+ return "user"
+ }
+}
+
+func getBuildFlavor(config Config) string {
+ buildFlavor := config.DeviceProduct() + "-" + getBuildVariant(config)
+ if InList("address", config.SanitizeDevice()) && !strings.Contains(buildFlavor, "_asan") {
+ buildFlavor += "_asan"
+ }
+ return buildFlavor
+}
+
+func shouldAddBuildThumbprint(config Config) bool {
+ knownOemProperties := []string{
+ "ro.product.brand",
+ "ro.product.name",
+ "ro.product.device",
+ }
+
+ for _, knownProp := range knownOemProperties {
+ if InList(knownProp, config.OemProperties()) {
+ return true
+ }
+ }
+ return false
+}
+
func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath
if !ctx.Config().KatiEnabled() {
@@ -61,87 +94,66 @@
return
}
- lines := make([]string, 0)
-
- writeString := func(str string) {
- lines = append(lines, str)
- }
-
- writeString("# begin build properties")
- writeString("# autogenerated by build/soong/android/buildinfo_prop.go")
-
- writeProp := func(key, value string) {
- if strings.Contains(key, "=") {
- panic(fmt.Errorf("wrong property key %q: key must not contain '='", key))
- }
- writeString(key + "=" + value)
- }
+ rule := NewRuleBuilder(pctx, ctx)
config := ctx.Config()
+ buildVariant := getBuildVariant(config)
+ buildFlavor := getBuildFlavor(config)
- writeProp("ro.build.version.sdk", config.PlatformSdkVersion().String())
- writeProp("ro.build.version.preview_sdk", config.PlatformPreviewSdkVersion())
- writeProp("ro.build.version.codename", config.PlatformSdkCodename())
- writeProp("ro.build.version.all_codenames", strings.Join(config.PlatformVersionActiveCodenames(), ","))
- writeProp("ro.build.version.release", config.PlatformVersionLastStable())
- writeProp("ro.build.version.release_or_codename", config.PlatformVersionName())
- writeProp("ro.build.version.security_patch", config.PlatformSecurityPatch())
- writeProp("ro.build.version.base_os", config.PlatformBaseOS())
- writeProp("ro.build.version.min_supported_target_sdk", config.PlatformMinSupportedTargetSdkVersion())
- writeProp("ro.build.version.known_codenames", config.PlatformVersionKnownCodenames())
+ cmd := rule.Command().BuiltTool("buildinfo")
- if config.Eng() {
- writeProp("ro.build.type", "eng")
- } else if config.Debuggable() {
- writeProp("ro.build.type", "userdebug")
- } else {
- writeProp("ro.build.type", "user")
+ if config.BoardUseVbmetaDigestInFingerprint() {
+ cmd.Flag("--use-vbmeta-digest-in-fingerprint")
}
- // Currently, only a few properties are implemented to unblock microdroid use case.
- // TODO(b/189164487): support below properties as well and replace build/make/tools/buildinfo.sh
- /*
- if $BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT {
- writeProp("ro.build.legacy.id", config.BuildID())
- } else {
- writeProp("ro.build.id", config.BuildId())
- }
- writeProp("ro.build.display.id", $BUILD_DISPLAY_ID)
- writeProp("ro.build.version.incremental", $BUILD_NUMBER)
- writeProp("ro.build.version.preview_sdk_fingerprint", $PLATFORM_PREVIEW_SDK_FINGERPRINT)
- writeProp("ro.build.version.release_or_preview_display", $PLATFORM_DISPLAY_VERSION)
- writeProp("ro.build.date", `$DATE`)
- writeProp("ro.build.date.utc", `$DATE +%s`)
- writeProp("ro.build.user", $BUILD_USERNAME)
- writeProp("ro.build.host", $BUILD_HOSTNAME)
- writeProp("ro.build.tags", $BUILD_VERSION_TAGS)
- writeProp("ro.build.flavor", $TARGET_BUILD_FLAVOR)
- // These values are deprecated, use "ro.product.cpu.abilist"
- // instead (see below).
- writeString("# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
- writeString("# use ro.product.cpu.abilist instead.")
- writeProp("ro.product.cpu.abi", $TARGET_CPU_ABI)
- if [ -n "$TARGET_CPU_ABI2" ] {
- writeProp("ro.product.cpu.abi2", $TARGET_CPU_ABI2)
- }
+ cmd.FlagWithArg("--build-flavor=", buildFlavor)
+ cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx))
+ cmd.FlagWithArg("--build-id=", config.BuildId())
+ cmd.FlagWithArg("--build-keys=", config.BuildKeys())
- if [ -n "$PRODUCT_DEFAULT_LOCALE" ] {
- writeProp("ro.product.locale", $PRODUCT_DEFAULT_LOCALE)
- }
- writeProp("ro.wifi.channels", $PRODUCT_DEFAULT_WIFI_CHANNELS)
- writeString("# ro.build.product is obsolete; use ro.product.device")
- writeProp("ro.build.product", $TARGET_DEVICE)
+ // shouldn't depend on BuildNumberFile and BuildThumbprintFile to prevent from rebuilding
+ // on every incremental build.
+ cmd.FlagWithArg("--build-number-file=", config.BuildNumberFile(ctx).String())
+ if shouldAddBuildThumbprint(config) {
+ cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String())
+ }
- writeString("# Do not try to parse description or thumbprint")
- writeProp("ro.build.description", $PRIVATE_BUILD_DESC)
- if [ -n "$BUILD_THUMBPRINT" ] {
- writeProp("ro.build.thumbprint", $BUILD_THUMBPRINT)
- }
- */
+ cmd.FlagWithArg("--build-type=", config.BuildType())
+ cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME"))
+ cmd.FlagWithArg("--build-variant=", buildVariant)
+ cmd.FlagForEachArg("--cpu-abis=", config.DeviceAbi())
- writeString("# end build properties")
+ // shouldn't depend on BUILD_DATETIME_FILE to prevent from rebuilding on every incremental
+ // build.
+ cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE"))
- WriteFileRule(ctx, p.outputFilePath, strings.Join(lines, "\n"))
+ if len(config.ProductLocales()) > 0 {
+ cmd.FlagWithArg("--default-locale=", config.ProductLocales()[0])
+ }
+
+ cmd.FlagForEachArg("--default-wifi-channels=", config.ProductDefaultWifiChannels())
+ cmd.FlagWithArg("--device=", config.DeviceName())
+ if config.DisplayBuildNumber() {
+ cmd.Flag("--display-build-number")
+ }
+
+ cmd.FlagWithArg("--platform-base-os=", config.PlatformBaseOS())
+ cmd.FlagWithArg("--platform-display-version=", config.PlatformDisplayVersionName())
+ cmd.FlagWithArg("--platform-min-supported-target-sdk-version=", config.PlatformMinSupportedTargetSdkVersion())
+ cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx))
+ cmd.FlagWithArg("--platform-preview-sdk-version=", config.PlatformPreviewSdkVersion())
+ cmd.FlagWithArg("--platform-sdk-version=", config.PlatformSdkVersion().String())
+ cmd.FlagWithArg("--platform-security-patch=", config.PlatformSecurityPatch())
+ cmd.FlagWithArg("--platform-version=", config.PlatformVersionName())
+ cmd.FlagWithArg("--platform-version-codename=", config.PlatformSdkCodename())
+ cmd.FlagForEachArg("--platform-version-all-codenames=", config.PlatformVersionActiveCodenames())
+ cmd.FlagWithArg("--platform-version-known-codenames=", config.PlatformVersionKnownCodenames())
+ cmd.FlagWithArg("--platform-version-last-stable=", config.PlatformVersionLastStable())
+ cmd.FlagWithArg("--product=", config.DeviceProduct())
+
+ cmd.FlagWithOutput("--out=", p.outputFilePath)
+
+ rule.Build(ctx.ModuleName(), "generating buildinfo props")
if !p.installable() {
p.SkipInstall()
diff --git a/android/config.go b/android/config.go
index 396b685..f2f7d7d 100644
--- a/android/config.go
+++ b/android/config.go
@@ -18,7 +18,6 @@
// product variables necessary for soong_build's operation.
import (
- "android/soong/shared"
"encoding/json"
"fmt"
"os"
@@ -30,6 +29,8 @@
"sync"
"unicode"
+ "android/soong/shared"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/pathtools"
@@ -113,6 +114,8 @@
GenerateDocFile
)
+const testKeyDir = "build/make/target/product/security"
+
// SoongOutDir returns the build output directory for the configuration.
func (c Config) SoongOutDir() string {
return c.soongOutDir
@@ -167,7 +170,10 @@
// Thus, verify_overlaps is disabled when RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE is set to false.
// TODO(b/308174018): Re-enable verify_overlaps for both builr from source/mainline prebuilts.
func (c Config) DisableVerifyOverlaps() bool {
- return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || !c.ReleaseDefaultModuleBuildFromSource()
+ if c.IsEnvFalse("DISABLE_VERIFY_OVERLAPS") && c.ReleaseDisableVerifyOverlaps() {
+ panic("The current release configuration does not support verify_overlaps. DISABLE_VERIFY_OVERLAPS cannot be set to false")
+ }
+ return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || c.ReleaseDisableVerifyOverlaps() || !c.ReleaseDefaultModuleBuildFromSource()
}
// MaxPageSizeSupported returns the max page size supported by the device. This
@@ -208,6 +214,10 @@
Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
}
+func (c Config) ReleaseDisableVerifyOverlaps() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_DISABLE_VERIFY_OVERLAPS_CHECK")
+}
+
// Enables flagged apis annotated with READ_WRITE aconfig flags to be included in the stubs
// and hiddenapi flags so that they are accessible at runtime
func (c Config) ReleaseExportRuntimeApis() bool {
@@ -833,6 +843,10 @@
return String(c.productVariables.BuildId)
}
+func (c *config) DisplayBuildNumber() bool {
+ return Bool(c.productVariables.DisplayBuildNumber)
+}
+
// BuildNumberFile returns the path to a text file containing metadata
// representing the current build's number.
//
@@ -844,6 +858,23 @@
return PathForOutput(ctx, String(c.productVariables.BuildNumberFile))
}
+// BuildHostnameFile returns the path to a text file containing metadata
+// representing the current build's host name.
+func (c *config) BuildHostnameFile(ctx PathContext) Path {
+ return PathForOutput(ctx, String(c.productVariables.BuildHostnameFile))
+}
+
+// BuildThumbprintFile returns the path to a text file containing metadata
+// representing the current build's thumbprint.
+//
+// Rules that want to reference the build thumbprint should read from this file
+// without depending on it. They will run whenever their other dependencies
+// require them to run and get the current build thumbprint. This ensures they
+// don't rebuild on every incremental build when the build thumbprint changes.
+func (c *config) BuildThumbprintFile(ctx PathContext) Path {
+ return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildThumbprintFile))
+}
+
// DeviceName returns the name of the current device target.
// TODO: take an AndroidModuleContext to select the device name for multi-device builds
func (c *config) DeviceName() string {
@@ -865,6 +896,10 @@
return c.productVariables.DeviceProduct != nil
}
+func (c *config) DeviceAbi() []string {
+ return c.productVariables.DeviceAbi
+}
+
func (c *config) DeviceResourceOverlays() []string {
return c.productVariables.DeviceResourceOverlays
}
@@ -873,6 +908,10 @@
return c.productVariables.ProductResourceOverlays
}
+func (c *config) PlatformDisplayVersionName() string {
+ return String(c.productVariables.Platform_display_version_name)
+}
+
func (c *config) PlatformVersionName() string {
return String(c.productVariables.Platform_version_name)
}
@@ -1030,7 +1069,7 @@
if defaultCert != "" {
return PathForSource(ctx, filepath.Dir(defaultCert))
}
- return PathForSource(ctx, "build/make/target/product/security")
+ return PathForSource(ctx, testKeyDir)
}
func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) {
@@ -1042,10 +1081,18 @@
return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8")
}
+func (c *config) BuildKeys() string {
+ defaultCert := String(c.productVariables.DefaultAppCertificate)
+ if defaultCert == "" || defaultCert == filepath.Join(testKeyDir, "testkey") {
+ return "test-keys"
+ }
+ return "dev-keys"
+}
+
func (c *config) ApexKeyDir(ctx ModuleContext) SourcePath {
// TODO(b/121224311): define another variable such as TARGET_APEX_KEY_OVERRIDE
defaultCert := String(c.productVariables.DefaultAppCertificate)
- if defaultCert == "" || filepath.Dir(defaultCert) == "build/make/target/product/security" {
+ if defaultCert == "" || filepath.Dir(defaultCert) == testKeyDir {
// When defaultCert is unset or is set to the testkeys path, use the APEX keys
// that is under the module dir
return pathForModuleSrc(ctx)
@@ -1104,6 +1151,10 @@
return Bool(c.productVariables.Eng)
}
+func (c *config) BuildType() string {
+ return String(c.productVariables.BuildType)
+}
+
// DevicePrimaryArchType returns the ArchType for the first configured device architecture, or
// Common if there are no device architectures.
func (c *config) DevicePrimaryArchType() ArchType {
@@ -1345,13 +1396,16 @@
panic(fmt.Errorf("Cannot parse vendor API level %s to an integer: %s",
c.VendorApiLevel(), err))
}
- if vendorApiLevel < 202404 || vendorApiLevel%100 != 4 {
- panic("Unknown vendor API level " + c.VendorApiLevel())
- }
// The version before trunk stable is 34.
if vendorApiLevel == 202404 {
return "34"
}
+ if vendorApiLevel >= 1 && vendorApiLevel <= 34 {
+ return strconv.Itoa(vendorApiLevel - 1)
+ }
+ if vendorApiLevel < 202404 || vendorApiLevel%100 != 4 {
+ panic("Unknown vendor API level " + c.VendorApiLevel())
+ }
return strconv.Itoa(vendorApiLevel - 100)
}
@@ -1394,10 +1448,6 @@
return StringDefault(c.config.productVariables.DeviceCurrentApiLevelForVendorModules, "current")
}
-func (c *deviceConfig) PlatformVndkVersion() string {
- return String(c.config.productVariables.Platform_vndk_version)
-}
-
func (c *deviceConfig) ExtraVndkVersions() []string {
return c.config.productVariables.ExtraVndkVersions
}
@@ -1935,6 +1985,10 @@
return c.config.productVariables.GenerateAidlNdkPlatformBackend
}
+func (c *deviceConfig) AconfigContainerValidation() string {
+ return c.config.productVariables.AconfigContainerValidation
+}
+
func (c *config) IgnorePrefer32OnDevice() bool {
return c.productVariables.IgnorePrefer32OnDevice
}
@@ -2068,6 +2122,22 @@
return ret
}
-func (c *config) BuildIgnoreApexContributionContents() []string {
+func (c *config) BuildIgnoreApexContributionContents() *bool {
return c.productVariables.BuildIgnoreApexContributionContents
}
+
+func (c *config) ProductLocales() []string {
+ return c.productVariables.ProductLocales
+}
+
+func (c *config) ProductDefaultWifiChannels() []string {
+ return c.productVariables.ProductDefaultWifiChannels
+}
+
+func (c *config) BoardUseVbmetaDigestInFingerprint() bool {
+ return Bool(c.productVariables.BoardUseVbmetaDigestInFingerprint)
+}
+
+func (c *config) OemProperties() []string {
+ return c.productVariables.OemProperties
+}
diff --git a/android/deptag.go b/android/deptag.go
index a15443b..c7ba4d3 100644
--- a/android/deptag.go
+++ b/android/deptag.go
@@ -43,3 +43,15 @@
}
return false
}
+
+type PropagateAconfigValidationDependencyTag interface {
+ PropagateAconfigValidation() bool
+}
+
+type AlwaysPropagateAconfigValidationDependencyTag struct{}
+
+func (p AlwaysPropagateAconfigValidationDependencyTag) PropagateAconfigValidation() bool {
+ return true
+}
+
+var _ PropagateAconfigValidationDependencyTag = AlwaysPropagateAconfigValidationDependencyTag{}
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 8f75773..cf1b5fc 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -15,9 +15,10 @@
package android
import (
- "github.com/google/blueprint"
"os"
"text/scanner"
+
+ "github.com/google/blueprint"
)
// EarlyModuleContext provides methods that can be called early, as soon as the properties have
@@ -54,6 +55,9 @@
// PropertyErrorf reports an error at the line number of a property in the module definition.
PropertyErrorf(property, fmt string, args ...interface{})
+ // OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition.
+ OtherModulePropertyErrorf(module Module, property, fmt string, args ...interface{})
+
// Failed returns true if any errors have been reported. In most cases the module can continue with generating
// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
// has prevented the module from creating necessary data it can return early when Failed returns true.
@@ -167,3 +171,7 @@
func (e *earlyModuleContext) Namespace() *Namespace {
return e.EarlyModuleContext.Namespace().(*Namespace)
}
+
+func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
+ e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args)
+}
diff --git a/android/filegroup.go b/android/filegroup.go
index bc881ed..86d7b4b 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -15,6 +15,7 @@
package android
import (
+ "maps"
"strings"
"github.com/google/blueprint"
@@ -97,6 +98,25 @@
}
SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()})
CollectDependencyAconfigFiles(ctx, &fg.mergedAconfigFiles)
+
+ var aconfigDeclarations []string
+ var intermediateCacheOutputPaths Paths
+ var srcjars Paths
+ modeInfos := make(map[string]ModeInfo)
+ ctx.VisitDirectDeps(func(module Module) {
+ if dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok {
+ aconfigDeclarations = append(aconfigDeclarations, dep.AconfigDeclarations...)
+ intermediateCacheOutputPaths = append(intermediateCacheOutputPaths, dep.IntermediateCacheOutputPaths...)
+ srcjars = append(srcjars, dep.Srcjars...)
+ maps.Copy(modeInfos, dep.ModeInfos)
+ }
+ })
+ SetProvider(ctx, CodegenInfoProvider, CodegenInfo{
+ AconfigDeclarations: aconfigDeclarations,
+ IntermediateCacheOutputPaths: intermediateCacheOutputPaths,
+ Srcjars: srcjars,
+ ModeInfos: modeInfos,
+ })
}
func (fg *fileGroup) Srcs() Paths {
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 463fd07..eabb1b1 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -77,6 +77,11 @@
if ctx.OtherModuleDependencyTag(dep) == DefaultsDepTag {
return
}
+ // The required dependencies just say modules A and B should be installed together.
+ // It doesn't mean that one is built using the other.
+ if ctx.OtherModuleDependencyTag(dep) == RequiredDepTag {
+ return
+ }
if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
diff --git a/android/module.go b/android/module.go
index b615ff5..f908451 100644
--- a/android/module.go
+++ b/android/module.go
@@ -15,7 +15,6 @@
package android
import (
- "android/soong/bazel"
"crypto/md5"
"encoding/hex"
"encoding/json"
@@ -27,7 +26,10 @@
"sort"
"strings"
+ "android/soong/bazel"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/parser"
"github.com/google/blueprint/proptools"
)
@@ -122,6 +124,8 @@
// TransitivePackagingSpecs returns the PackagingSpecs for this module and any transitive
// dependencies with dependency tags for which IsInstallDepNeeded() returns true.
TransitivePackagingSpecs() []PackagingSpec
+
+ ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator
}
// Qualified id for a module
@@ -432,6 +436,10 @@
// Set by osMutator
CompileOS OsType `blueprint:"mutated"`
+ // Set to true after the arch mutator has run on this module and set CompileTarget,
+ // CompileMultiTargets, and CompilePrimary
+ ArchReady bool `blueprint:"mutated"`
+
// The Target of artifacts that this module variant is responsible for creating.
//
// Set by archMutator
@@ -541,6 +549,15 @@
var teamDepTag = TeamDepTagType{}
+// Dependency tag for required, host_required, and target_required modules.
+var RequiredDepTag = struct {
+ blueprint.BaseDependencyTag
+ InstallAlwaysNeededDependencyTag
+ // Requiring disabled module has been supported (as a side effect of this being implemented
+ // in Make). We may want to make it an error, but for now, let's keep the existing behavior.
+ AlwaysAllowDisabledModuleDependencyTag
+}{}
+
// CommonTestOptions represents the common `test_options` properties in
// Android.bp.
type CommonTestOptions struct {
@@ -1006,6 +1023,87 @@
if m.Team() != "" {
ctx.AddDependency(ctx.Module(), teamDepTag, m.Team())
}
+
+ // TODO(jiyong): remove below case. This is to work around build errors happening
+ // on branches with reduced manifest like aosp_kernel-build-tools.
+ // In the branch, a build error occurs as follows.
+ // 1. aosp_kernel-build-tools is a reduced manifest branch. It doesn't have some git
+ // projects like external/bouncycastle
+ // 2. `boot_signer` is `required` by modules like `build_image` which is explicitly list as
+ // the top-level build goal (in the shell file that invokes Soong).
+ // 3. `boot_signer` depends on `bouncycastle-unbundled` which is in the missing git project.
+ // 4. aosp_kernel-build-tools invokes soong with `--skip-make`. Therefore, the absence of
+ // ALLOW_MISSING_DEPENDENCIES didn't cause a problem.
+ // 5. Now, since Soong understands `required` deps, it tries to build `boot_signer` and the
+ // absence of external/bouncycastle fails the build.
+ //
+ // Unfortunately, there's no way for Soong to correctly determine if it's running in a
+ // reduced manifest branch. Instead, here, we use the absence of DeviceArch or DeviceName as
+ // a strong signal, because that's very common across reduced manifest branches.
+ pv := ctx.Config().productVariables
+ fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil
+ if fullManifest {
+ m.addRequiredDeps(ctx)
+ }
+}
+
+// addRequiredDeps adds required, target_required, and host_required as dependencies.
+func (m *ModuleBase) addRequiredDeps(ctx BottomUpMutatorContext) {
+ addDep := func(target Target, depName string) {
+ if !ctx.OtherModuleExists(depName) {
+ if ctx.Config().AllowMissingDependencies() {
+ return
+ }
+ }
+
+ // If Android native module requires another Android native module, ensure that
+ // they have the same bitness. This mimics the policy in select-bitness-of-required-modules
+ // in build/make/core/main.mk.
+ // TODO(jiyong): the Make-side does this only when the required module is a shared
+ // library or a native test.
+ bothInAndroid := m.Device() && target.Os.Class == Device
+ nativeArch := InList(m.Arch().ArchType.Multilib, []string{"lib32", "lib64"})
+ sameBitness := m.Arch().ArchType.Multilib == target.Arch.ArchType.Multilib
+ if bothInAndroid && nativeArch && !sameBitness {
+ return
+ }
+
+ variation := target.Variations()
+ if ctx.OtherModuleFarDependencyVariantExists(variation, depName) {
+ ctx.AddFarVariationDependencies(variation, RequiredDepTag, depName)
+ }
+ }
+
+ if m.Device() {
+ for _, depName := range m.RequiredModuleNames() {
+ for _, target := range ctx.Config().Targets[Android] {
+ addDep(target, depName)
+ }
+ }
+ for _, depName := range m.HostRequiredModuleNames() {
+ for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
+ addDep(target, depName)
+ }
+ }
+ }
+
+ if m.Host() {
+ for _, depName := range m.RequiredModuleNames() {
+ for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
+ // When a host module requires another host module, don't make a
+ // dependency if they have different OSes (i.e. hostcross).
+ if m.Target().HostCross != target.HostCross {
+ continue
+ }
+ addDep(target, depName)
+ }
+ }
+ for _, depName := range m.TargetRequiredModuleNames() {
+ for _, target := range ctx.Config().Targets[Android] {
+ addDep(target, depName)
+ }
+ }
+ }
}
// AddProperties "registers" the provided props
@@ -1135,6 +1233,10 @@
return distFiles
}
+func (m *ModuleBase) ArchReady() bool {
+ return m.commonProperties.ArchReady
+}
+
func (m *ModuleBase) Target() Target {
return m.commonProperties.CompileTarget
}
@@ -1658,6 +1760,7 @@
}
return archModuleContext{
+ ready: m.commonProperties.ArchReady,
os: m.commonProperties.CompileOS,
target: m.commonProperties.CompileTarget,
targetPrimary: m.commonProperties.CompilePrimary,
@@ -2008,6 +2111,65 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
+type ConfigAndErrorContext interface {
+ Config() Config
+ OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+}
+
+type configurationEvalutor struct {
+ ctx ConfigAndErrorContext
+ m Module
+}
+
+func (m *ModuleBase) ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator {
+ return configurationEvalutor{
+ ctx: ctx,
+ m: m.module,
+ }
+}
+
+func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args ...interface{}) {
+ e.ctx.OtherModulePropertyErrorf(e.m, property, fmt, args)
+}
+
+func (e configurationEvalutor) EvaluateConfiguration(ty parser.SelectType, property, condition string) (string, bool) {
+ ctx := e.ctx
+ m := e.m
+ switch ty {
+ case parser.SelectTypeReleaseVariable:
+ if v, ok := ctx.Config().productVariables.BuildFlags[condition]; ok {
+ return v, true
+ }
+ return "", false
+ case parser.SelectTypeProductVariable:
+ // TODO(b/323382414): Might add these on a case-by-case basis
+ ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects")
+ return "", false
+ case parser.SelectTypeSoongConfigVariable:
+ parts := strings.Split(condition, ":")
+ namespace := parts[0]
+ variable := parts[1]
+ if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok {
+ if v, ok := n[variable]; ok {
+ return v, true
+ }
+ }
+ return "", false
+ case parser.SelectTypeVariant:
+ if condition == "arch" {
+ if !m.base().ArchReady() {
+ ctx.OtherModulePropertyErrorf(m, property, "A select on arch was attempted before the arch mutator ran")
+ return "", false
+ }
+ return m.base().Arch().ArchType.Name, true
+ }
+ ctx.OtherModulePropertyErrorf(m, property, "Unknown variant %s", condition)
+ return "", false
+ default:
+ panic("Should be unreachable")
+ }
+}
+
// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
// or if this variant is not overridden.
@@ -2087,6 +2249,7 @@
// caused by prebuilt_ prefix, or fully qualified module names.
type sourceOrOutputDependencyTag struct {
blueprint.BaseDependencyTag
+ AlwaysPropagateAconfigValidationDependencyTag
// The name of the module.
moduleName string
diff --git a/android/module_context.go b/android/module_context.go
index 1cab630..d3e2770 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -234,6 +234,8 @@
variables map[string]string
}
+var _ ModuleContext = &moduleContext{}
+
func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
return pctx, BuildParams{
Rule: ErrorRule,
diff --git a/android/ninja_deps.go b/android/ninja_deps.go
index 1d50a47..bdf465e 100644
--- a/android/ninja_deps.go
+++ b/android/ninja_deps.go
@@ -15,7 +15,6 @@
package android
import (
- "android/soong/starlark_import"
"sort"
)
@@ -43,11 +42,4 @@
func (ninjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
ctx.AddNinjaFileDeps(ctx.Config().ninjaFileDeps()...)
-
- deps, err := starlark_import.GetNinjaDeps()
- if err != nil {
- ctx.Errorf("Error running starlark code: %s", err)
- } else {
- ctx.AddNinjaFileDeps(deps...)
- }
}
diff --git a/android/path_properties.go b/android/path_properties.go
index bbfaa8c..ea92565 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -47,7 +47,7 @@
// tagged with `android:"path"`.
var pathProperties []string
for _, ps := range props {
- pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ps)...)
+ pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...)
}
// Remove duplicates to avoid multiple dependencies.
@@ -64,7 +64,7 @@
// pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with
// android:"path" to extract all their values from a property struct, returning them as a single
// slice of strings.
-func pathPropertiesForPropertyStruct(ps interface{}) []string {
+func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string {
v := reflect.ValueOf(ps)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type()))
@@ -106,6 +106,16 @@
ret = append(ret, sv.String())
case reflect.Slice:
ret = append(ret, sv.Interface().([]string)...)
+ case reflect.Struct:
+ intf := sv.Interface()
+ if configurable, ok := intf.(proptools.Configurable[string]); ok {
+ ret = append(ret, proptools.String(configurable.Evaluate(ctx)))
+ } else if configurable, ok := intf.(proptools.Configurable[[]string]); ok {
+ ret = append(ret, proptools.Slice(configurable.Evaluate(ctx))...)
+ } else {
+ panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
+ v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
+ }
default:
panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 5a94a0f..91ba05b 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -71,6 +71,9 @@
//
// If specified then the prefer property is ignored in favor of the value of the Soong config
// variable.
+ //
+ // DEPRECATED: This property is being deprecated b/308188211.
+ // Use RELEASE_APEX_CONTRIBUTIONS build flags to select prebuilts of mainline modules.
Use_source_config_var *ConfigVarProperties
}
diff --git a/android/sdk.go b/android/sdk.go
index 6d5293e..121470d 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -868,3 +868,11 @@
}
var AdditionalSdkInfoProvider = blueprint.NewProvider[AdditionalSdkInfo]()
+
+var apiFingerprintPathKey = NewOnceKey("apiFingerprintPathKey")
+
+func ApiFingerprintPath(ctx PathContext) OutputPath {
+ return ctx.Config().Once(apiFingerprintPathKey, func() interface{} {
+ return PathForOutput(ctx, "api_fingerprint.txt")
+ }).(OutputPath)
+}
diff --git a/android/selects_test.go b/android/selects_test.go
new file mode 100644
index 0000000..adbe59a
--- /dev/null
+++ b/android/selects_test.go
@@ -0,0 +1,358 @@
+// 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 android
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func TestSelects(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ provider selectsTestProvider
+ vendorVars map[string]map[string]string
+ expectedError string
+ }{
+ {
+ name: "basic string list",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": ["a.cpp"],
+ "b": ["b.cpp"],
+ _: ["c.cpp"],
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string_list: &[]string{"c.cpp"},
+ },
+ },
+ {
+ name: "basic string",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": "a.cpp",
+ "b": "b.cpp",
+ _: "c.cpp",
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string: proptools.StringPtr("c.cpp"),
+ },
+ },
+ {
+ name: "basic bool",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": true,
+ "b": false,
+ _: true,
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_bool: proptools.BoolPtr(true),
+ },
+ },
+ {
+ name: "basic paths",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": ["foo.txt"],
+ "b": ["bar.txt"],
+ _: ["baz.txt"],
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_paths: &[]string{"baz.txt"},
+ },
+ },
+ {
+ name: "paths with module references",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_paths: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": [":a"],
+ "b": [":b"],
+ _: [":c"],
+ }),
+ }
+ `,
+ expectedError: `"foo" depends on undefined module "c"`,
+ },
+ {
+ name: "Differing types",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": "a.cpp",
+ "b": true,
+ _: "c.cpp",
+ }),
+ }
+ `,
+ expectedError: `can't assign bool value to string property "my_string\[1\]"`,
+ },
+ {
+ name: "String list non-default",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": ["a.cpp"],
+ "b": ["b.cpp"],
+ _: ["c.cpp"],
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string_list: &[]string{"a.cpp"},
+ },
+ vendorVars: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "a",
+ },
+ },
+ },
+ {
+ name: "String list append",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": ["a.cpp"],
+ "b": ["b.cpp"],
+ _: ["c.cpp"],
+ }) + select(soong_config_variable("my_namespace", "my_variable_2"), {
+ "a2": ["a2.cpp"],
+ "b2": ["b2.cpp"],
+ _: ["c2.cpp"],
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string_list: &[]string{"a.cpp", "c2.cpp"},
+ },
+ vendorVars: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "a",
+ },
+ },
+ },
+ {
+ name: "String list prepend literal",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string_list: ["literal.cpp"] + select(soong_config_variable("my_namespace", "my_variable"), {
+ "a2": ["a2.cpp"],
+ "b2": ["b2.cpp"],
+ _: ["c2.cpp"],
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string_list: &[]string{"literal.cpp", "c2.cpp"},
+ },
+ },
+ {
+ name: "String list append literal",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string_list: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a2": ["a2.cpp"],
+ "b2": ["b2.cpp"],
+ _: ["c2.cpp"],
+ }) + ["literal.cpp"],
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string_list: &[]string{"c2.cpp", "literal.cpp"},
+ },
+ },
+ {
+ name: "true + false = true",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": true,
+ "b": false,
+ _: true,
+ }) + false,
+ }
+ `,
+ provider: selectsTestProvider{
+ my_bool: proptools.BoolPtr(true),
+ },
+ },
+ {
+ name: "false + false = false",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_bool: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": true,
+ "b": false,
+ _: true,
+ }) + false,
+ }
+ `,
+ vendorVars: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "b",
+ },
+ },
+ provider: selectsTestProvider{
+ my_bool: proptools.BoolPtr(false),
+ },
+ },
+ {
+ name: "Append string",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+ "a": "a",
+ "b": "b",
+ _: "c",
+ }) + ".cpp",
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string: proptools.StringPtr("c.cpp"),
+ },
+ },
+ {
+ name: "Select on variant",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string: select(variant("arch"), {
+ "x86": "my_x86",
+ "x86_64": "my_x86_64",
+ "arm": "my_arm",
+ "arm64": "my_arm64",
+ _: "my_default",
+ }),
+ }
+ `,
+ provider: selectsTestProvider{
+ my_string: proptools.StringPtr("my_arm64"),
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ fixtures := GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("my_module_type", newSelectsMockModule)
+ }),
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.VendorVars = tc.vendorVars
+ }),
+ )
+ if tc.expectedError != "" {
+ fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
+ }
+ result := fixtures.RunTestWithBp(t, tc.bp)
+
+ if tc.expectedError == "" {
+ m := result.ModuleForTests("foo", "android_arm64_armv8-a")
+ p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
+ if !reflect.DeepEqual(p, tc.provider) {
+ t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String())
+ }
+ }
+ })
+ }
+}
+
+type selectsTestProvider struct {
+ my_bool *bool
+ my_string *string
+ my_string_list *[]string
+ my_paths *[]string
+}
+
+func (p *selectsTestProvider) String() string {
+ myBoolStr := "nil"
+ if p.my_bool != nil {
+ myBoolStr = fmt.Sprintf("%t", *p.my_bool)
+ }
+ myStringStr := "nil"
+ if p.my_string != nil {
+ myStringStr = *p.my_string
+ }
+ return fmt.Sprintf(`selectsTestProvider {
+ my_bool: %v,
+ my_string: %s,
+ my_string_list: %s,
+ my_paths: %s,
+}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths)
+}
+
+var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]()
+
+type selectsMockModuleProperties struct {
+ My_bool proptools.Configurable[bool]
+ My_string proptools.Configurable[string]
+ My_string_list proptools.Configurable[[]string]
+ My_paths proptools.Configurable[[]string] `android:"path"`
+}
+
+type selectsMockModule struct {
+ ModuleBase
+ DefaultableModuleBase
+ properties selectsMockModuleProperties
+}
+
+func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
+ my_bool: p.properties.My_bool.Evaluate(ctx),
+ my_string: p.properties.My_string.Evaluate(ctx),
+ my_string_list: p.properties.My_string_list.Evaluate(ctx),
+ my_paths: p.properties.My_paths.Evaluate(ctx),
+ })
+}
+
+func newSelectsMockModule() Module {
+ m := &selectsMockModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, HostAndDeviceSupported, MultilibFirst)
+ InitDefaultableModule(m)
+ return m
+}
diff --git a/android/singleton.go b/android/singleton.go
index ccddeaf..76df1eb 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -87,6 +87,9 @@
// builder whenever a file matching the pattern as added or removed, without rerunning if a
// file that does not match the pattern is added to a searched directory.
GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+ // OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
+ OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})
}
type singletonAdaptor struct {
@@ -251,7 +254,7 @@
func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module {
// get module reference for visibility enforcement
- qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), s.ModuleType(referer))
+ qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), referer)
modules := s.SingletonContext.ModuleVariantsFromName(referer, name)
result := make([]Module, 0, len(modules))
@@ -279,3 +282,7 @@
func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
return s.SingletonContext.ModuleProvider(module, provider)
}
+
+func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) {
+ s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args)
+}
diff --git a/android/variable.go b/android/variable.go
index df2f8d4..acca6a4 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -194,9 +194,13 @@
// Suffix to add to generated Makefiles
Make_suffix *string `json:",omitempty"`
- BuildId *string `json:",omitempty"`
- BuildNumberFile *string `json:",omitempty"`
+ BuildId *string `json:",omitempty"`
+ BuildNumberFile *string `json:",omitempty"`
+ BuildHostnameFile *string `json:",omitempty"`
+ BuildThumbprintFile *string `json:",omitempty"`
+ DisplayBuildNumber *bool `json:",omitempty"`
+ Platform_display_version_name *string `json:",omitempty"`
Platform_version_name *string `json:",omitempty"`
Platform_sdk_version *int `json:",omitempty"`
Platform_sdk_codename *string `json:",omitempty"`
@@ -206,7 +210,6 @@
Platform_base_sdk_extension_version *int `json:",omitempty"`
Platform_version_active_codenames []string `json:",omitempty"`
Platform_version_all_preview_codenames []string `json:",omitempty"`
- Platform_vndk_version *string `json:",omitempty"`
Platform_systemsdk_versions []string `json:",omitempty"`
Platform_security_patch *string `json:",omitempty"`
Platform_preview_sdk_version *string `json:",omitempty"`
@@ -297,6 +300,8 @@
MinimizeJavaDebugInfo *bool `json:",omitempty"`
Build_from_text_stub *bool `json:",omitempty"`
+ BuildType *string `json:",omitempty"`
+
Check_elf_files *bool `json:",omitempty"`
UncompressPrivAppDex *bool `json:",omitempty"`
@@ -473,9 +478,8 @@
AfdoProfiles []string `json:",omitempty"`
- ProductManufacturer string `json:",omitempty"`
- ProductBrand string `json:",omitempty"`
- BuildVersionTags []string `json:",omitempty"`
+ ProductManufacturer string `json:",omitempty"`
+ ProductBrand string `json:",omitempty"`
ReleaseVersion string `json:",omitempty"`
ReleaseAconfigValueSets []string `json:",omitempty"`
@@ -496,11 +500,21 @@
BuildFromSourceStub *bool `json:",omitempty"`
- BuildIgnoreApexContributionContents []string `json:",omitempty"`
+ BuildIgnoreApexContributionContents *bool `json:",omitempty"`
HiddenapiExportableStubs *bool `json:",omitempty"`
ExportRuntimeApis *bool `json:",omitempty"`
+
+ AconfigContainerValidation string `json:",omitempty"`
+
+ ProductLocales []string `json:",omitempty"`
+
+ ProductDefaultWifiChannels []string `json:",omitempty"`
+
+ BoardUseVbmetaDigestInFingerprint *bool `json:",omitempty"`
+
+ OemProperties []string `json:",omitempty"`
}
type PartitionQualifiedVariablesType struct {
@@ -583,7 +597,6 @@
Platform_sdk_final: boolPtr(false),
Platform_version_active_codenames: []string{"S"},
Platform_version_all_preview_codenames: []string{"S"},
- Platform_vndk_version: stringPtr("S"),
HostArch: stringPtr("x86_64"),
HostSecondaryArch: stringPtr("x86"),
diff --git a/android/visibility.go b/android/visibility.go
index b387562..89c0adc 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -58,19 +58,14 @@
var visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern)
type visibilityModuleReference struct {
- name qualifiedModuleName
- isPartitionModule bool
+ name qualifiedModuleName
+ module Module
}
-func createVisibilityModuleReference(name, dir, typ string) visibilityModuleReference {
- isPartitionModule := false
- switch typ {
- case "android_filesystem", "android_system_image":
- isPartitionModule = true
- }
+func createVisibilityModuleReference(name, dir string, module Module) visibilityModuleReference {
return visibilityModuleReference{
- name: createQualifiedModuleName(name, dir),
- isPartitionModule: isPartitionModule,
+ name: createQualifiedModuleName(name, dir),
+ module: module,
}
}
@@ -214,21 +209,37 @@
return "//visibility:private"
}
+var anyPartitionRegex = regexp.MustCompile("^any_(system|system_ext|vendor|product|data|odm)_partition$")
+
// visibilityRule for //visibility:any_partition
-type anyPartitionRule struct{}
+type anyPartitionRule struct {
+ partitionType string
+}
var _ visibilityRule = anyPartitionRule{}
+type PartitionTypeInterface interface {
+ PartitionType() string
+}
+
func (r anyPartitionRule) matches(m visibilityModuleReference) bool {
- return m.isPartitionModule
+ if m2, ok := m.module.(PartitionTypeInterface); ok {
+ return m2.PartitionType() == r.partitionType
+ }
+ return false
}
func (r anyPartitionRule) String() string {
- return "//visibility:any_partition"
+ return "//visibility:any_" + r.partitionType + "_partition"
}
var visibilityRuleMap = NewOnceKey("visibilityRuleMap")
+type visibilityRulesForModule struct {
+ rule compositeRule
+ implicitPartitionRules compositeRule
+}
+
// The map from qualifiedModuleName to visibilityRule.
func moduleToVisibilityRuleMap(config Config) *sync.Map {
return config.Once(visibilityRuleMap, func() interface{} {
@@ -303,7 +314,7 @@
if pkg == "visibility" {
switch name {
- case "private", "public", "any_partition":
+ case "private", "public":
case "legacy_public":
ctx.PropertyErrorf(property, "//visibility:legacy_public must not be used")
continue
@@ -311,6 +322,10 @@
// This keyword does not create a rule so pretend it does not exist.
ruleCount -= 1
default:
+ if anyPartitionRegex.MatchString(name) {
+ // any_*_partition can be used with another visibility fields
+ continue
+ }
ctx.PropertyErrorf(property, "unrecognized visibility rule %q", v)
continue
}
@@ -349,15 +364,20 @@
// Parse the visibility rules that control access to the module and store them by id
// for use when enforcing the rules.
+ var rule compositeRule
primaryProperty := m.base().primaryVisibilityProperty
if primaryProperty != nil {
if visibility := primaryProperty.getStrings(); visibility != nil {
- rule := parseRules(ctx, currentPkg, primaryProperty.getName(), visibility)
- if rule != nil {
- moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, rule)
- }
+ rule = parseRules(ctx, currentPkg, primaryProperty.getName(), visibility)
}
}
+ ipr := implicitPartitionRules(ctx)
+ if rule != nil || ipr != nil {
+ moduleToVisibilityRuleMap(ctx.Config()).Store(qualifiedModuleId, visibilityRulesForModule{
+ rule: rule,
+ implicitPartitionRules: ipr,
+ })
+ }
}
func parseRules(ctx BaseModuleContext, currentPkg, property string, visibility []string) compositeRule {
@@ -389,8 +409,13 @@
hasNonPrivateRule = false
// This does not actually create a rule so continue onto the next rule.
continue
- case "any_partition":
- r = anyPartitionRule{}
+ default:
+ match := anyPartitionRegex.FindStringSubmatch(name)
+ if match != nil {
+ r = anyPartitionRule{
+ partitionType: match[1],
+ }
+ }
}
} else {
switch name {
@@ -429,6 +454,22 @@
return rules
}
+func implicitPartitionRules(ctx BaseModuleContext) compositeRule {
+ var result compositeRule
+ if ctx.SocSpecific() {
+ result = append(result, anyPartitionRule{partitionType: "vendor"})
+ } else if ctx.ProductSpecific() {
+ result = append(result, anyPartitionRule{partitionType: "product"})
+ } else if ctx.Module().InstallInData() {
+ result = append(result, anyPartitionRule{partitionType: "data"})
+ } else if ctx.SystemExtSpecific() {
+ result = append(result, anyPartitionRule{partitionType: "system_ext"})
+ } else if ctx.DeviceSpecific() {
+ result = append(result, anyPartitionRule{partitionType: "odm"})
+ }
+ return result
+}
+
func isAllowedFromOutsideVendor(pkg string, name string) bool {
if pkg == "vendor" {
return name == "__subpackages__"
@@ -467,7 +508,7 @@
}
func visibilityRuleEnforcer(ctx TopDownMutatorContext) {
- qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.ModuleType())
+ qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.Module())
// Visit all the dependencies making sure that this module has access to them all.
ctx.VisitDirectDeps(func(dep Module) {
@@ -502,10 +543,13 @@
// which is currently //visibility:public.
func effectiveVisibilityRules(config Config, qualified qualifiedModuleName) compositeRule {
moduleToVisibilityRule := moduleToVisibilityRuleMap(config)
- value, ok := moduleToVisibilityRule.Load(qualified)
+ value := visibilityRulesForModule{}
+ if valueRaw, ok := moduleToVisibilityRule.Load(qualified); ok {
+ value = valueRaw.(visibilityRulesForModule)
+ }
var rule compositeRule
- if ok {
- rule = value.(compositeRule)
+ if value.rule != nil {
+ rule = value.rule
} else {
rule = packageDefaultVisibility(moduleToVisibilityRule, qualified)
}
@@ -515,6 +559,20 @@
if rule == nil {
rule = defaultVisibility
}
+
+ // If a partition rule wasn't specified, add implicit partition visibility
+ // rules based on the partition properties like vendor: true.
+ foundPartitionRule := false
+ for _, r := range rule {
+ if _, ok := r.(anyPartitionRule); ok {
+ foundPartitionRule = true
+ break
+ }
+ }
+ if !foundPartitionRule {
+ rule = append(rule, value.implicitPartitionRules...)
+ }
+
return rule
}
@@ -528,7 +586,7 @@
for {
value, ok := moduleToVisibilityRule.Load(packageQualifiedId)
if ok {
- return value.(compositeRule)
+ return value.(visibilityRulesForModule).rule
}
if packageQualifiedId.isRootPackage() {
@@ -602,7 +660,7 @@
rule := effectiveVisibilityRules(ctx.Config(), qualified)
- currentModule := createVisibilityModuleReference(moduleName, dir, ctx.OtherModuleType(module))
+ currentModule := createVisibilityModuleReference(moduleName, dir, module)
// Modules are implicitly visible to other modules in the same package,
// without checking the visibility rules. Here we need to add that visibility
diff --git a/android/visibility_test.go b/android/visibility_test.go
index d4add7d..1a2eeca 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -1905,7 +1905,7 @@
},
},
{
- name: "any_partition visibility works",
+ name: "any_system_partition visibility works",
fs: MockFS{
"top/Android.bp": []byte(`
android_filesystem {
@@ -1916,12 +1916,32 @@
package(default_visibility=["//visibility:private"])
mock_library {
name: "bar",
- visibility: ["//visibility:any_partition"],
+ visibility: ["//visibility:any_system_partition"],
}`),
},
},
{
- name: "any_partition visibility doesn't work for non-partitions",
+ name: "any_system_partition visibility works with the other visibility",
+ fs: MockFS{
+ "top/Android.bp": []byte(`
+ android_filesystem {
+ name: "foo",
+ deps: ["bar"],
+ }`),
+ "top2/Android.bp": []byte(``),
+ "top/nested/Android.bp": []byte(`
+ package(default_visibility=["//visibility:private"])
+ mock_library {
+ name: "bar",
+ visibility: [
+ "//top2",
+ "//visibility:any_system_partition"
+ ],
+ }`),
+ },
+ },
+ {
+ name: "any_system_partition visibility doesn't work for non-partitions",
fs: MockFS{
"top/Android.bp": []byte(`
mock_library {
@@ -1931,11 +1951,77 @@
"top/nested/Android.bp": []byte(`
mock_library {
name: "bar",
- visibility: ["//visibility:any_partition"],
+ visibility: ["//visibility:any_system_partition"],
}`),
},
expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
},
+ {
+ name: "any_system_partition visibility doesn't work for vendor partitions",
+ fs: MockFS{
+ "top/Android.bp": []byte(`
+ android_filesystem {
+ name: "foo",
+ partition_type: "vendor",
+ deps: ["bar"],
+ }`),
+ "top/nested/Android.bp": []byte(`
+ package(default_visibility=["//visibility:private"])
+ mock_library {
+ name: "bar",
+ visibility: ["//visibility:any_system_partition"],
+ }`),
+ },
+ expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
+ },
+ {
+ name: "Vendor modules are visible to any vendor partition by default",
+ fs: MockFS{
+ "top/Android.bp": []byte(`
+ android_filesystem {
+ name: "foo",
+ partition_type: "vendor",
+ deps: ["bar"],
+ }`),
+ "top/nested/Android.bp": []byte(`
+ package(default_visibility=["//visibility:private"])
+ mock_library {
+ name: "bar",
+ vendor: true,
+ }`),
+ },
+ },
+ {
+ name: "Not visible to vendor partitions when using any_system_partiton, even if vendor: true",
+ fs: MockFS{
+ "top/Android.bp": []byte(`
+ android_filesystem {
+ name: "foo",
+ partition_type: "vendor",
+ deps: ["bar"],
+ }`),
+ "top/nested/Android.bp": []byte(`
+ package(default_visibility=["//visibility:private"])
+ mock_library {
+ name: "bar",
+ vendor: true,
+ visibility: ["//visibility:any_system_partition"],
+ }`),
+ },
+ expectedErrors: []string{`module "foo" variant "android_common": depends on //top/nested:bar which is not visible to this module`},
+ },
+ {
+ name: "unknown any_partition specs throw errors",
+ fs: MockFS{
+ "top/nested/Android.bp": []byte(`
+ package(default_visibility=["//visibility:private"])
+ mock_library {
+ name: "bar",
+ visibility: ["//visibility:any_unknown_partition"],
+ }`),
+ },
+ expectedErrors: []string{`unrecognized visibility rule "//visibility:any_unknown_partition"`},
+ },
}
func TestVisibility(t *testing.T) {
@@ -1957,8 +2043,7 @@
ctx.RegisterModuleType("mock_library", newMockLibraryModule)
ctx.RegisterModuleType("mock_parent", newMockParentFactory)
ctx.RegisterModuleType("mock_defaults", defaultsFactory)
- // For testing //visibility:any_partition. The module type doesn't matter, just that it's registered under the name "android_filesystem"
- ctx.RegisterModuleType("android_filesystem", newMockLibraryModule)
+ ctx.RegisterModuleType("android_filesystem", newMockFilesystemModule)
}),
prepareForTestWithFakePrebuiltModules,
// Add additional files to the mock filesystem
@@ -2012,6 +2097,37 @@
func (p *mockLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
}
+type mockFilesystemModuleProperties struct {
+ Partition_type *string
+ Deps []string
+}
+
+type mockFilesystemModule struct {
+ ModuleBase
+ properties mockFilesystemModuleProperties
+}
+
+func (j *mockFilesystemModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
+}
+
+func (p *mockFilesystemModule) GenerateAndroidBuildActions(ModuleContext) {
+}
+
+func (p *mockFilesystemModule) PartitionType() string {
+ if p.properties.Partition_type == nil {
+ return "system"
+ }
+ return *p.properties.Partition_type
+}
+
+func newMockFilesystemModule() Module {
+ m := &mockFilesystemModule{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, DeviceSupported, MultilibCommon)
+ return m
+}
+
type mockDefaults struct {
ModuleBase
DefaultsModuleBase
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 460f1ff..1dd479c 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -511,6 +511,22 @@
`,
},
{
+ // Unsupported function case because that doesn't work in bp
+ desc: "error for unsupported functions",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(filter-out filter-out-file.java ,$(call all-java-files-under, src))
+LOCAL_PACKAGE_NAME := foo
+include $(BUILD_PACKAGE)
+`,
+ expected: `
+android_app {
+ name: "foo",
+ srcs: ["UNSUPPORTED FUNCTION:filter-out filter-out-file.java src/**/*.java"],
+}
+ `,
+ },
+ {
desc: "ignore all-makefiles-under",
in: `
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index fb6be38..8a20bb0 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -413,6 +413,9 @@
p.accept('\t')
newLine = false
continue loop
+ } else if p.tok == '\n' {
+ p.accept('\n')
+ continue loop
} else if p.parseDirective() {
newLine = false
continue
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
index 9efebf8..db3313d 100644
--- a/androidmk/parser/parser_test.go
+++ b/androidmk/parser/parser_test.go
@@ -84,6 +84,22 @@
},
},
},
+ {
+ name: "Blank line in rule's command",
+ in: `all:
+ echo first line
+
+ echo second line`,
+ out: []Node{
+ &Rule{
+ Target: SimpleMakeString("all", NoPos),
+ RecipePos: NoPos,
+ Recipe: "echo first line\necho second line",
+ Prerequisites: SimpleMakeString("", NoPos),
+ },
+ },
+ },
+
}
func TestParse(t *testing.T) {
diff --git a/androidmk/parser/scope.go b/androidmk/parser/scope.go
index 8111c89..e1a523a 100644
--- a/androidmk/parser/scope.go
+++ b/androidmk/parser/scope.go
@@ -14,9 +14,7 @@
package parser
-import (
- "strings"
-)
+import "strings"
type Scope interface {
Get(name string) string
@@ -88,7 +86,7 @@
if fname == "call" {
return scope.Call(argVals[0], argVals[1:]), true
} else {
- return []string{"__builtin_func:" + fname + " " + strings.Join(argVals, " ")}, true
+ return []string{"UNSUPPORTED FUNCTION:" + fname + " " + strings.Join(argVals, " ")}, true
}
}
}
diff --git a/apex/Android.bp b/apex/Android.bp
index 27017ae..abae9e2 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -40,7 +40,6 @@
"dexpreopt_bootjars_test.go",
"platform_bootclasspath_test.go",
"systemserver_classpath_fragment_test.go",
- "vndk_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/apex/aconfig_test.go b/apex/aconfig_test.go
new file mode 100644
index 0000000..3e44f0b
--- /dev/null
+++ b/apex/aconfig_test.go
@@ -0,0 +1,755 @@
+// 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",
+ }`,
+ },
+ {
+ name: "Rust 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: ["libmy_rust_library"],
+ binaries: ["my_rust_binary"],
+ updatable: false,
+ }
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_ffi_shared {
+ name: "libmy_rust_library",
+ srcs: ["src/lib.rs"],
+ rustlibs: ["libmy_rust_aconfig_library_foo"],
+ crate_name: "my_rust_library",
+ apex_available: ["myapex"],
+ }
+ rust_binary {
+ name: "my_rust_binary",
+ srcs: ["foo/bar/MyClass.rs"],
+ rustlibs: ["libmy_rust_aconfig_library_bar"],
+ apex_available: ["myapex"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "otherapex",
+ srcs: ["foo.aconfig"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package",
+ container: "otherapex",
+ srcs: ["bar.aconfig"],
+ }
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ crate_name: "my_rust_aconfig_library_foo",
+ apex_available: ["myapex"],
+ mode: "exported",
+ }
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ crate_name: "my_rust_aconfig_library_bar",
+ 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: "Rust 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: ["libmy_rust_library"],
+ updatable: false,
+ }
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_ffi_shared {
+ name: "libmy_rust_library",
+ srcs: ["src/lib.rs"],
+ rustlibs: ["libmy_rust_aconfig_library_foo"],
+ crate_name: "my_rust_library",
+ apex_available: ["myapex"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "otherapex",
+ srcs: ["foo.aconfig"],
+ }
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ crate_name: "my_rust_aconfig_library_foo",
+ apex_available: ["myapex"],
+ }`,
+ expectedError: `.*libmy_rust_aconfig_library_foo/myapex depends on libmy_rust_aconfig_library_foo/otherapex/production across containers`,
+ },
+ {
+ name: "Rust 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_rust_binary"],
+ updatable: false,
+ }
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["src/lib.rs"],
+ apex_available: ["myapex"],
+ }
+ rust_binary {
+ name: "my_rust_binary",
+ srcs: ["foo/bar/MyClass.rs"],
+ rustlibs: ["libmy_rust_aconfig_library_bar"],
+ apex_available: ["myapex"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package",
+ container: "otherapex",
+ srcs: ["bar.aconfig"],
+ }
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ crate_name: "my_rust_aconfig_library_bar",
+ apex_available: ["myapex"],
+ }`,
+ expectedError: `.*libmy_rust_aconfig_library_bar/myapex depends on libmy_rust_aconfig_library_bar/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)
+ })
+ }
+}
diff --git a/apex/apex.go b/apex/apex.go
index 4b37d0f..4bc2601 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -357,6 +357,8 @@
// be removed from PRODUCT_PACKAGES.
Overrides []string
+ Multilib apexMultilibProperties
+
// Logging parent value.
Logging_parent string
@@ -736,7 +738,7 @@
// image variation name.
func (a *apexBundle) getImageVariationPair(deviceConfig android.DeviceConfig) (string, string) {
if a.vndkApex {
- return cc.VendorVariationPrefix, a.vndkVersion(deviceConfig)
+ return cc.VendorVariationPrefix, a.vndkVersion()
}
prefix := android.CoreVariation
@@ -745,9 +747,6 @@
if a.SocSpecific() || a.DeviceSpecific() {
prefix = cc.VendorVariationPrefix
vndkVersion = deviceConfig.VndkVersion()
- } else if a.ProductSpecific() {
- prefix = cc.ProductVariationPrefix
- vndkVersion = deviceConfig.PlatformVndkVersion()
}
} else {
if a.SocSpecific() || a.DeviceSpecific() {
@@ -756,9 +755,6 @@
prefix = cc.ProductVariation
}
}
- if vndkVersion == "current" {
- vndkVersion = deviceConfig.PlatformVndkVersion()
- }
return prefix, vndkVersion
}
@@ -1645,10 +1641,9 @@
return af
}
-func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile {
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
- fileToCopy := prebuilt.OutputFile()
- return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
+ return newApexFile(ctx, outputFile, outputFile.Base(), dirInApex, etc, prebuilt)
}
func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
@@ -1818,6 +1813,9 @@
if dt, ok := depTag.(*dependencyTag); ok && !dt.payload {
return false
}
+ if depTag == android.RequiredDepTag {
+ return false
+ }
ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
@@ -2117,7 +2115,10 @@
}
case prebuiltTag:
if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+ filesToCopy, _ := prebuilt.OutputFiles("")
+ for _, etcFile := range filesToCopy {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
+ }
addAconfigFiles(vctx, ctx, child)
} else {
ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
@@ -2256,7 +2257,10 @@
// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
} else if java.IsXmlPermissionsFileDepTag(depTag) {
if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+ filesToCopy, _ := prebuilt.OutputFiles("")
+ for _, etcFile := range filesToCopy {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
+ }
}
} else if rust.IsDylibDepTag(depTag) {
if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
@@ -2307,6 +2311,8 @@
// nothing
} else if depTag == android.DarwinUniversalVariantTag {
// nothing
+ } else if depTag == android.RequiredDepTag {
+ // nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
}
@@ -2314,9 +2320,15 @@
}
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")
}
}
@@ -2417,6 +2429,18 @@
// Set a provider for dexpreopt of bootjars
a.provideApexExportsInfo(ctx)
+
+ a.providePrebuiltInfo(ctx)
+}
+
+// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
+// with information about whether source or prebuilt of an apex was used during the build.
+func (a *apexBundle) providePrebuiltInfo(ctx android.ModuleContext) {
+ info := android.PrebuiltInfo{
+ Name: a.Name(),
+ Is_prebuilt: false,
+ }
+ android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
}
// Set a provider containing information about the jars and .prof provided by the apex
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 25c0cc4..e6ebff2 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -17,6 +17,8 @@
package apex
import (
+ "encoding/json"
+
"github.com/google/blueprint"
"android/soong/android"
@@ -129,3 +131,43 @@
// Export check result to Make. The path is added to droidcore.
ctx.Strict("APEX_ALLOWED_DEPS_CHECK", s.allowedApexDepsInfoCheckResult.String())
}
+
+func init() {
+ registerApexPrebuiltInfoComponents(android.InitRegistrationContext)
+}
+
+func registerApexPrebuiltInfoComponents(ctx android.RegistrationContext) {
+ ctx.RegisterParallelSingletonType("apex_prebuiltinfo_singleton", apexPrebuiltInfoFactory)
+}
+
+func apexPrebuiltInfoFactory() android.Singleton {
+ return &apexPrebuiltInfo{}
+}
+
+type apexPrebuiltInfo struct {
+ out android.WritablePath
+}
+
+func (a *apexPrebuiltInfo) GenerateBuildActions(ctx android.SingletonContext) {
+ prebuiltInfos := []android.PrebuiltInfo{}
+
+ ctx.VisitAllModules(func(m android.Module) {
+ prebuiltInfo, exists := android.SingletonModuleProvider(ctx, m, android.PrebuiltInfoProvider)
+ // Use prebuiltInfoProvider to filter out non apex soong modules.
+ // Use HideFromMake to filter out the unselected variants of a specific apex.
+ if exists && !m.IsHideFromMake() {
+ prebuiltInfos = append(prebuiltInfos, prebuiltInfo)
+ }
+ })
+
+ j, err := json.Marshal(prebuiltInfos)
+ if err != nil {
+ ctx.Errorf("Could not convert prebuilt info of apexes to json due to error: %v", err)
+ }
+ a.out = android.PathForOutput(ctx, "prebuilt_info.json")
+ android.WriteFileRule(ctx, a.out, string(j))
+}
+
+func (a *apexPrebuiltInfo) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoal("droidcore", a.out)
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9dc77c2..f523379 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -218,7 +218,6 @@
),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = proptools.StringPtr("current")
variables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
variables.Platform_sdk_codename = proptools.StringPtr("Q")
@@ -226,7 +225,6 @@
// "Tiramisu" needs to be in the next line for compatibility with soong code,
// not because of these tests specifically (it's not used by the tests)
variables.Platform_version_active_codenames = []string{"Q", "Tiramisu"}
- variables.Platform_vndk_version = proptools.StringPtr("29")
variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
}),
)
@@ -2062,13 +2060,13 @@
}
`)
- vendorVariant := "android_vendor.29_arm64_armv8-a"
+ vendorVariant := "android_vendor_arm64_armv8-a"
- mylib := ctx.ModuleForTests("mylib", vendorVariant+"_shared_myapex")
+ mylib := ctx.ModuleForTests("mylib", vendorVariant+"_shared_apex29")
// Ensure that mylib links with "current" LLNDK
libFlags := names(mylib.Rule("ld").Args["libFlags"])
- ensureListContains(t, libFlags, "out/soong/.intermediates/libbar/"+vendorVariant+"_shared_current/libbar.so")
+ ensureListContains(t, libFlags, "out/soong/.intermediates/libbar/"+vendorVariant+"_shared/libbar.so")
// Ensure that mylib is targeting 29
ccRule := ctx.ModuleForTests("mylib", vendorVariant+"_static_apex29").Output("obj/mylib.o")
@@ -3025,158 +3023,6 @@
ensureListNotContains(t, requireNativeLibs, ":vndk")
}
-func TestVendorApex_use_vndk_as_stable_TryingToIncludeVNDKLib(t *testing.T) {
- testApexError(t, `Trying to include a VNDK library`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["libc++"], // libc++ is a VNDK lib
- vendor: true,
- use_vndk_as_stable: true,
- updatable: false,
- }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }`)
-}
-
-func TestVendorApex_use_vndk_as_stable(t *testing.T) {
- // myapex myapex2
- // | |
- // mybin ------. mybin2
- // \ \ / |
- // (stable) .---\--------` |
- // \ / \ |
- // \ / \ /
- // libvndk libvendor
- // (vndk)
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- binaries: ["mybin"],
- vendor: true,
- use_vndk_as_stable: true,
- updatable: false,
- }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- cc_binary {
- name: "mybin",
- vendor: true,
- shared_libs: ["libvndk", "libvendor"],
- }
- cc_library {
- name: "libvndk",
- vndk: {
- enabled: true,
- },
- vendor_available: true,
- product_available: true,
- }
- cc_library {
- name: "libvendor",
- vendor: true,
- stl: "none",
- }
- apex {
- name: "myapex2",
- key: "myapex.key",
- binaries: ["mybin2"],
- vendor: true,
- use_vndk_as_stable: false,
- updatable: false,
- }
- cc_binary {
- name: "mybin2",
- vendor: true,
- shared_libs: ["libvndk", "libvendor"],
- }
- `,
- android.FixtureModifyConfig(func(config android.Config) {
- config.TestProductVariables.KeepVndk = proptools.BoolPtr(true)
- }),
- )
-
- vendorVariant := "android_vendor.29_arm64_armv8-a"
-
- for _, tc := range []struct {
- name string
- apexName string
- moduleName string
- moduleVariant string
- libs []string
- contents []string
- requireVndkNamespace bool
- }{
- {
- name: "use_vndk_as_stable",
- apexName: "myapex",
- moduleName: "mybin",
- moduleVariant: vendorVariant + "_apex10000",
- libs: []string{
- // should link with vendor variants of VNDK libs(libvndk/libc++)
- "out/soong/.intermediates/libvndk/" + vendorVariant + "_shared/libvndk.so",
- "out/soong/.intermediates/" + cc.DefaultCcCommonTestModulesDir + "libc++/" + vendorVariant + "_shared/libc++.so",
- // unstable Vendor libs as APEX variant
- "out/soong/.intermediates/libvendor/" + vendorVariant + "_shared_apex10000/libvendor.so",
- },
- contents: []string{
- "bin/mybin",
- "lib64/libvendor.so",
- // VNDK libs (libvndk/libc++) are not included
- },
- requireVndkNamespace: true,
- },
- {
- name: "!use_vndk_as_stable",
- apexName: "myapex2",
- moduleName: "mybin2",
- moduleVariant: vendorVariant + "_myapex2",
- libs: []string{
- // should link with "unique" APEX(myapex2) variant of VNDK libs(libvndk/libc++)
- "out/soong/.intermediates/libvndk/" + vendorVariant + "_shared_myapex2/libvndk.so",
- "out/soong/.intermediates/" + cc.DefaultCcCommonTestModulesDir + "libc++/" + vendorVariant + "_shared_myapex2/libc++.so",
- // unstable vendor libs have "merged" APEX variants
- "out/soong/.intermediates/libvendor/" + vendorVariant + "_shared_apex10000/libvendor.so",
- },
- contents: []string{
- "bin/mybin2",
- "lib64/libvendor.so",
- // VNDK libs are included as well
- "lib64/libvndk.so",
- "lib64/libc++.so",
- },
- requireVndkNamespace: false,
- },
- } {
- t.Run(tc.name, func(t *testing.T) {
- // Check linked libs
- ldRule := ctx.ModuleForTests(tc.moduleName, tc.moduleVariant).Rule("ld")
- libs := names(ldRule.Args["libFlags"])
- for _, lib := range tc.libs {
- ensureListContains(t, libs, lib)
- }
- // Check apex contents
- ensureExactContents(t, ctx, tc.apexName, "android_common_"+tc.apexName, tc.contents)
-
- // Check "requireNativeLibs"
- apexManifestRule := ctx.ModuleForTests(tc.apexName, "android_common_"+tc.apexName).Rule("apexManifestRule")
- requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
- if tc.requireVndkNamespace {
- ensureListContains(t, requireNativeLibs, ":vndk")
- } else {
- ensureListNotContains(t, requireNativeLibs, ":vndk")
- }
- })
- }
-}
-
func TestProductVariant(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -3202,7 +3048,7 @@
`)
cflags := strings.Fields(
- ctx.ModuleForTests("foo", "android_product.29_arm64_armv8-a_myapex").Rule("cc").Args["cFlags"])
+ ctx.ModuleForTests("foo", "android_product_arm64_armv8-a_apex10000").Rule("cc").Args["cFlags"])
ensureListContains(t, cflags, "-D__ANDROID_VNDK__")
ensureListContains(t, cflags, "-D__ANDROID_APEX__")
ensureListContains(t, cflags, "-D__ANDROID_PRODUCT__")
@@ -3823,166 +3669,6 @@
assertFileListEquals(t, files, actualFiles)
}
-func TestVndkApexCurrent(t *testing.T) {
- commonFiles := []string{
- "lib/libc++.so",
- "lib64/libc++.so",
- "etc/llndk.libraries.29.txt",
- "etc/vndkcore.libraries.29.txt",
- "etc/vndksp.libraries.29.txt",
- "etc/vndkprivate.libraries.29.txt",
- "etc/vndkproduct.libraries.29.txt",
- }
- testCases := []struct {
- vndkVersion string
- expectedFiles []string
- }{
- {
- vndkVersion: "current",
- expectedFiles: append(commonFiles,
- "lib/libvndk.so",
- "lib/libvndksp.so",
- "lib64/libvndk.so",
- "lib64/libvndksp.so"),
- },
- }
- for _, tc := range testCases {
- t.Run("VNDK.current with DeviceVndkVersion="+tc.vndkVersion, func(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
-
- cc_library {
- name: "libvndksp",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
-
- // VNDK-Ext should not cause any problems
-
- cc_library {
- name: "libvndk.ext",
- srcs: ["mylib2.cpp"],
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- system_shared_libs: [],
- stl: "none",
- }
-
- cc_library {
- name: "libvndksp.ext",
- srcs: ["mylib2.cpp"],
- vendor: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- extends: "libvndksp",
- },
- system_shared_libs: [],
- stl: "none",
- }
- `+vndkLibrariesTxtFiles("current"), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = proptools.StringPtr(tc.vndkVersion)
- variables.KeepVndk = proptools.BoolPtr(true)
- }))
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", tc.expectedFiles)
- })
- }
-}
-
-func TestVndkApexWithPrebuilt(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_prebuilt_library_shared {
- name: "libvndk",
- srcs: ["libvndk.so"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
-
- cc_prebuilt_library_shared {
- name: "libvndk.arm",
- srcs: ["libvndk.arm.so"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- enabled: false,
- arch: {
- arm: {
- enabled: true,
- },
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
- `+vndkLibrariesTxtFiles("current"),
- withFiles(map[string][]byte{
- "libvndk.so": nil,
- "libvndk.arm.so": nil,
- }))
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
- "lib/libvndk.so",
- "lib/libvndk.arm.so",
- "lib64/libvndk.so",
- "lib/libc++.so",
- "lib64/libc++.so",
- "etc/*",
- })
-}
-
func vndkLibrariesTxtFiles(vers ...string) (result string) {
for _, v := range vers {
if v == "current" {
@@ -4090,9 +3776,10 @@
func TestVndkApexNameRule(t *testing.T) {
ctx := testApex(t, `
apex_vndk {
- name: "com.android.vndk.current",
+ name: "com.android.vndk.v29",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
+ vndk_version: "29",
updatable: false,
}
apex_vndk {
@@ -4106,7 +3793,7 @@
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
- }`+vndkLibrariesTxtFiles("28", "current"))
+ }`+vndkLibrariesTxtFiles("28", "29"))
assertApexName := func(expected, moduleName string) {
module := ctx.ModuleForTests(moduleName, "android_common")
@@ -4114,51 +3801,10 @@
ensureContains(t, apexManifestRule.Args["opt"], "-v name "+expected)
}
- assertApexName("com.android.vndk.v29", "com.android.vndk.current")
+ assertApexName("com.android.vndk.v29", "com.android.vndk.v29")
assertApexName("com.android.vndk.v28", "com.android.vndk.v28")
}
-func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- file_contexts: ":myapex-file_contexts",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- native_bridge_supported: true,
- host_supported: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
- `+vndkLibrariesTxtFiles("current"),
- withNativeBridgeEnabled)
-
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
- "lib/libvndk.so",
- "lib64/libvndk.so",
- "lib/libc++.so",
- "lib64/libc++.so",
- "etc/*",
- })
-}
-
func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
testApexError(t, `module "com.android.vndk.current" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
apex_vndk {
@@ -4259,47 +3905,6 @@
})
}
-func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- file_contexts: ":myapex-file_contexts",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libz",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- stubs: {
- symbol_file: "libz.map.txt",
- versions: ["30"],
- }
- }
- `+vndkLibrariesTxtFiles("current"), withFiles(map[string][]byte{
- "libz.map.txt": nil,
- }))
-
- apexManifestRule := ctx.ModuleForTests("com.android.vndk.current", "android_common").Rule("apexManifestRule")
- provideNativeLibs := names(apexManifestRule.Args["provideNativeLibs"])
- ensureListEmpty(t, provideNativeLibs)
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
- "out/soong/.intermediates/libz/android_vendor.29_arm64_armv8-a_shared/libz.so:lib64/libz.so",
- "out/soong/.intermediates/libz/android_vendor.29_arm_armv7-a-neon_shared/libz.so:lib/libz.so",
- "*/*",
- })
-}
-
func TestVendorApexWithVndkPrebuilts(t *testing.T) {
ctx := testApex(t, "",
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -7334,6 +6939,15 @@
bpfs: ["overrideBpf"],
prebuilts: ["override_myetc"],
overrides: ["unknownapex"],
+ compile_multilib: "first",
+ multilib: {
+ lib32: {
+ native_shared_libs: ["mylib32"],
+ },
+ lib64: {
+ native_shared_libs: ["mylib64"],
+ },
+ },
logging_parent: "com.foo.bar",
package_name: "test.overridden.package",
key: "mynewapex.key",
@@ -7391,6 +7005,16 @@
name: "override_myetc",
src: "override_myprebuilt",
}
+
+ cc_library {
+ name: "mylib32",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_library {
+ name: "mylib64",
+ apex_available: [ "myapex" ],
+ }
`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(android.OverridableModule)
@@ -10047,7 +9671,6 @@
key: "myapex.key",
updatable: false,
java_libs: ["foo"],
- required: ["otherapex"],
}
apex_key {
@@ -11030,7 +10653,7 @@
}
`)
- inputs := result.ModuleForTests("myfilesystem", "android_common").Output("deps.zip").Implicits
+ inputs := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img").Implicits
android.AssertStringListDoesNotContain(t, "filesystem should not have libbar",
inputs.Strings(),
"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
@@ -11305,6 +10928,33 @@
],
}
+ rust_library {
+ name: "libaconfig_storage_read_api", // test mock
+ crate_name: "aconfig_storage_read_api",
+ srcs: ["src/lib.rs"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_library {
+ name: "liblogger", // test mock
+ crate_name: "logger",
+ srcs: ["src/lib.rs"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_library {
+ name: "liblog_rust", // test mock
+ crate_name: "log_rust",
+ srcs: ["src/lib.rs"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
rust_ffi_shared {
name: "libmy_rust_library",
srcs: ["src/lib.rs"],
@@ -11389,14 +11039,14 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 26 {
- t.Fatalf("Expected 26 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 32 {
+ t.Fatalf("Expected 28 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[22], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
- ensureMatches(t, copyCmds[23], "^cp -f .*/package.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[24], "^cp -f .*/flag.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[25], "^cp -f .*/flag.val .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[28], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[29], "^cp -f .*/package.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[30], "^cp -f .*/flag.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[31], "^cp -f .*/flag.val .*/image.apex/etc$")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
diff --git a/apex/builder.go b/apex/builder.go
index 6ad282a..9bd4b61 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -277,7 +277,7 @@
// VNDK APEX name is determined at runtime, so update "name" in apex_manifest
optCommands := []string{}
if a.vndkApex {
- apexName := vndkApexNamePrefix + a.vndkVersion(ctx.DeviceConfig())
+ apexName := vndkApexNamePrefix + a.vndkVersion()
optCommands = append(optCommands, "-v name "+apexName)
}
@@ -485,7 +485,7 @@
}
func isVintfFragment(fi apexFile) bool {
- isVintfFragment, _ := path.Match("etc/vintf/*.xml", fi.path())
+ isVintfFragment, _ := path.Match("etc/vintf/*", fi.path())
return isVintfFragment
}
@@ -1043,7 +1043,7 @@
if a.vndkApex {
overrideName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(vndkApexName)
if overridden {
- return overrideName + ".v" + a.vndkVersion(ctx.DeviceConfig())
+ return overrideName + ".v" + a.vndkVersion()
}
return ""
}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index cebbae9..ea847e1 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -121,6 +121,11 @@
// List of systemserverclasspath fragments inside this prebuilt APEX bundle and for which this
// APEX bundle will create an APEX variant.
Exported_systemserverclasspath_fragments []string
+
+ // Path to the .prebuilt_info file of the prebuilt apex.
+ // In case of mainline modules, the .prebuilt_info file contains the build_id that was used to
+ // generate the prebuilt.
+ Prebuilt_info *string `android:"path"`
}
// initPrebuiltCommon initializes the prebuiltCommon structure and performs initialization of the
@@ -819,6 +824,20 @@
}
}
+// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
+// with information about whether source or prebuilt of an apex was used during the build.
+func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) {
+ info := android.PrebuiltInfo{
+ Name: p.BaseModuleName(),
+ Is_prebuilt: true,
+ }
+ // If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
+ if p.prebuiltCommonProperties.Prebuilt_info != nil {
+ info.Prebuilt_info_file_path = android.PathForModuleSrc(ctx, *p.prebuiltCommonProperties.Prebuilt_info).String()
+ }
+ android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+}
+
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
@@ -846,6 +865,8 @@
// provide info used for generating the boot image
p.provideApexExportsInfo(ctx)
+ p.providePrebuiltInfo(ctx)
+
// Save the files that need to be made available to Make.
p.initApexFilesForAndroidMk(ctx)
@@ -1068,6 +1089,8 @@
// provide info used for generating the boot image
a.provideApexExportsInfo(ctx)
+ a.providePrebuiltInfo(ctx)
+
// Save the files that need to be made available to Make.
a.initApexFilesForAndroidMk(ctx)
diff --git a/apex/vndk.go b/apex/vndk.go
index 377c1c0..781aa3c 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -45,16 +45,12 @@
return bundle
}
-func (a *apexBundle) vndkVersion(config android.DeviceConfig) string {
- vndkVersion := proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
- if vndkVersion == "current" {
- vndkVersion = config.PlatformVndkVersion()
- }
- return vndkVersion
+func (a *apexBundle) vndkVersion() string {
+ return proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
}
type apexVndkProperties struct {
- // Indicates VNDK version of which this VNDK APEX bundles VNDK libs. Default is Platform VNDK Version.
+ // Indicates VNDK version of which this VNDK APEX bundles VNDK libs.
Vndk_version *string
}
@@ -64,7 +60,7 @@
mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
}
- vndkVersion := ab.vndkVersion(mctx.DeviceConfig())
+ vndkVersion := ab.vndkVersion()
if vndkVersion != "" {
apiLevel, err := android.ApiLevelFromUser(mctx, vndkVersion)
if err != nil {
@@ -73,17 +69,9 @@
}
targets := mctx.MultiTargets()
- if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) &&
- vndkVersion != mctx.DeviceConfig().PlatformVndkVersion() {
+ if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) {
// Disable VNDK APEXes for VNDK versions less than the minimum supported API
- // level for the primary architecture. This validation is skipped if the VNDK
- // version matches the platform VNDK version, which can occur when the device
- // config targets the 'current' VNDK (see `vndkVersion`).
- ab.Disable()
- }
- if proptools.String(ab.vndkProperties.Vndk_version) != "" &&
- mctx.DeviceConfig().PlatformVndkVersion() != "" &&
- apiLevel.GreaterThanOrEqualTo(android.ApiLevelOrPanic(mctx, mctx.DeviceConfig().PlatformVndkVersion())) {
+ // level for the primary architecture.
ab.Disable()
}
}
@@ -93,20 +81,11 @@
func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*cc.Module); ok && cc.IsForVndkApex(mctx, m) {
vndkVersion := m.VndkVersion()
- // For VNDK-Lite device, we gather core-variants of VNDK-Sp libraries, which doesn't have VNDK version defined
- if vndkVersion == "" {
- vndkVersion = mctx.DeviceConfig().PlatformVndkVersion()
- }
if vndkVersion == "" {
return
}
-
- if vndkVersion == mctx.DeviceConfig().PlatformVndkVersion() {
- vndkVersion = "current"
- } else {
- vndkVersion = "v" + vndkVersion
- }
+ vndkVersion = "v" + vndkVersion
vndkApexName := "com.android.vndk." + vndkVersion
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
deleted file mode 100644
index 894aece..0000000
--- a/apex/vndk_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package apex
-
-import (
- "testing"
-
- "github.com/google/blueprint/proptools"
-
- "android/soong/android"
-)
-
-func TestVndkApexUsesVendorVariant(t *testing.T) {
- bp := `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "mykey",
- updatable: false,
- }
- apex_key {
- name: "mykey",
- }
- cc_library {
- name: "libfoo",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- }
- ` + vndkLibrariesTxtFiles("current")
-
- ensureFileSrc := func(t *testing.T, files []fileInApex, path, src string) {
- t.Helper()
- for _, f := range files {
- if f.path == path {
- ensureContains(t, f.src, src)
- return
- }
- }
- t.Errorf("expected path %q not found", path)
- }
-
- t.Run("VNDK lib doesn't have an apex variant", func(t *testing.T) {
- ctx := testApex(t, bp)
-
- // libfoo doesn't have apex variants
- for _, variant := range ctx.ModuleVariantsForTests("libfoo") {
- ensureNotContains(t, variant, "_myapex")
- }
-
- // VNDK APEX doesn't create apex variant
- files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
- ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
- })
-
- t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
- ctx := testApex(t, bp)
-
- files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
- ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
- })
-
- t.Run("VNDK APEX supports coverage variants", func(t *testing.T) {
- ctx := testApex(t, bp,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.GcovCoverage = proptools.BoolPtr(true)
- variables.Native_coverage = proptools.BoolPtr(true)
- }),
- )
-
- files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
- ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
-
- files = getFiles(t, ctx, "com.android.vndk.current", "android_common_cov")
- ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared_cov/libfoo.so")
- })
-}
diff --git a/cc/Android.bp b/cc/Android.bp
index 9e4b763..93d9aa2 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -111,7 +111,6 @@
"test_data_test.go",
"tidy_test.go",
"vendor_public_library_test.go",
- "vendor_snapshot_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/cc/cc.go b/cc/cc.go
index 1f0b21e..fb5d096 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -767,6 +767,12 @@
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
@@ -1891,9 +1897,6 @@
vndkVersion = ctx.DeviceConfig().VndkVersion()
nameSuffix = VendorSuffix
}
- if vndkVersion == "current" {
- vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
- }
if c.VndkVersion() != vndkVersion && c.VndkVersion() != "" {
// add version suffix only if the module is using different vndk version than the
// version in product or vendor partition.
@@ -2975,6 +2978,9 @@
if depTag == stubImplDepTag {
return false
}
+ if depTag == android.RequiredDepTag {
+ return false
+ }
// Even if target lib has no vendor variant, keep checking dependency
// graph in case it depends on vendor_available or product_available
@@ -3152,6 +3158,10 @@
return
}
+ if depTag == android.RequiredDepTag {
+ return
+ }
+
if dep.Target().Os != ctx.Os() {
ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
return
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 6cc500b..74fae04 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -17,7 +17,6 @@
import (
"fmt"
"os"
- "path/filepath"
"reflect"
"regexp"
"runtime"
@@ -39,17 +38,6 @@
}
var prepareForCcTest = android.GroupFixturePreparers(
- PrepareForTestWithCcIncludeVndk,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.VendorApiLevel = StringPtr("202404")
- variables.DeviceVndkVersion = StringPtr("current")
- variables.KeepVndk = BoolPtr(true)
- variables.Platform_vndk_version = StringPtr("29")
- }),
-)
-
-// TODO(b/316829758) Update prepareForCcTest with this configuration and remove prepareForCcTestWithoutVndk
-var prepareForCcTestWithoutVndk = android.GroupFixturePreparers(
PrepareForIntegrationTestWithCc,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.VendorApiLevel = StringPtr("202404")
@@ -123,30 +111,14 @@
func testCcError(t *testing.T, pattern string, bp string) {
t.Helper()
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- testCcErrorWithConfig(t, pattern, config)
- return
-}
-
-// testCcErrorProductVndk runs tests using the prepareForCcTest
-//
-// See testCc for an explanation as to how to stop using this deprecated method.
-//
-// deprecated
-func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
- t.Helper()
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
testCcErrorWithConfig(t, pattern, config)
return
}
const (
coreVariant = "android_arm64_armv8-a_shared"
- vendorVariant = "android_vendor.29_arm64_armv8-a_shared"
- productVariant = "android_product.29_arm64_armv8-a_shared"
+ vendorVariant = "android_vendor_arm64_armv8-a_shared"
+ productVariant = "android_product_arm64_armv8-a_shared"
recoveryVariant = "android_recovery_arm64_armv8-a_shared"
)
@@ -302,44 +274,6 @@
checkInstallPartition(t, ctx, "libproduct_odmavailable", vendorVariant, "odm")
}
-func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
- isVndkSp bool, extends string, variant string) {
-
- t.Helper()
-
- mod := ctx.ModuleForTests(name, variant).Module().(*Module)
-
- // Check library properties.
- lib, ok := mod.compiler.(*libraryDecorator)
- if !ok {
- t.Errorf("%q must have libraryDecorator", name)
- } else if lib.baseInstaller.subDir != subDir {
- t.Errorf("%q must use %q as subdir but it is using %q", name, subDir,
- lib.baseInstaller.subDir)
- }
-
- // Check VNDK properties.
- if mod.vndkdep == nil {
- t.Fatalf("%q must have `vndkdep`", name)
- }
- if !mod.IsVndk() {
- t.Errorf("%q IsVndk() must equal to true", name)
- }
- if mod.IsVndkSp() != isVndkSp {
- t.Errorf("%q IsVndkSp() must equal to %t", name, isVndkSp)
- }
-
- // Check VNDK extension properties.
- isVndkExt := extends != ""
- if mod.IsVndkExt() != isVndkExt {
- t.Errorf("%q IsVndkExt() must equal to %t", name, isVndkExt)
- }
-
- if actualExtends := mod.getVndkExtendsModuleName(); actualExtends != extends {
- t.Errorf("%q must extend from %q but get %q", name, extends, actualExtends)
- }
-}
-
func checkWriteFileOutput(t *testing.T, ctx *android.TestContext, params android.TestingBuildParams, expected []string) {
t.Helper()
content := android.ContentFromFileRuleForTests(t, ctx, params)
@@ -347,344 +281,6 @@
assertArrayString(t, actual, expected)
}
-func checkVndkOutput(t *testing.T, ctx *android.TestContext, output string, expected []string) {
- t.Helper()
- vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
- checkWriteFileOutput(t, ctx, vndkSnapshot.Output(output), expected)
-}
-
-func checkVndkLibrariesOutput(t *testing.T, ctx *android.TestContext, module string, expected []string) {
- t.Helper()
- got := ctx.ModuleForTests(module, "android_common").Module().(*vndkLibrariesTxt).fileNames
- assertArrayString(t, got, expected)
-}
-
-func TestVndk(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_private",
- vendor_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- nocrt: true,
- stem: "libvndk-private",
- }
-
- cc_library {
- name: "libvndk_product",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- target: {
- vendor: {
- cflags: ["-DTEST"],
- },
- product: {
- cflags: ["-DTEST"],
- },
- },
- }
-
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- suffix: "-x",
- }
-
- cc_library {
- name: "libvndk_sp_private",
- vendor_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- private: true,
- },
- nocrt: true,
- target: {
- vendor: {
- suffix: "-x",
- },
- },
- }
-
- cc_library {
- name: "libvndk_sp_product_private",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- private: true,
- },
- nocrt: true,
- target: {
- vendor: {
- suffix: "-x",
- },
- product: {
- suffix: "-x",
- },
- },
- }
-
- cc_library {
- name: "libllndk",
- llndk: {
- symbol_file: "libllndk.map.txt",
- export_llndk_headers: ["libllndk_headers"],
- }
- }
-
- cc_library {
- name: "libclang_rt.hwasan-llndk",
- llndk: {
- symbol_file: "libclang_rt.hwasan.map.txt",
- }
- }
-
- cc_library_headers {
- name: "libllndk_headers",
- llndk: {
- llndk_headers: true,
- },
- export_include_dirs: ["include"],
- }
-
- llndk_libraries_txt {
- name: "llndk.libraries.txt",
- }
- vndkcore_libraries_txt {
- name: "vndkcore.libraries.txt",
- }
- vndksp_libraries_txt {
- name: "vndksp.libraries.txt",
- }
- vndkprivate_libraries_txt {
- name: "vndkprivate.libraries.txt",
- }
- vndkproduct_libraries_txt {
- name: "vndkproduct.libraries.txt",
- }
- vndkcorevariant_libraries_txt {
- name: "vndkcorevariant.libraries.txt",
- insert_vndk_version: false,
- }
- `
-
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
- ctx := testCcWithConfig(t, config)
-
- // subdir == "" because VNDK libs are not supposed to be installed separately.
- // They are installed as part of VNDK APEX instead.
- checkVndkModule(t, ctx, "libvndk", "", false, "", vendorVariant)
- checkVndkModule(t, ctx, "libvndk_private", "", false, "", vendorVariant)
- checkVndkModule(t, ctx, "libvndk_product", "", false, "", vendorVariant)
- checkVndkModule(t, ctx, "libvndk_sp", "", true, "", vendorVariant)
- checkVndkModule(t, ctx, "libvndk_sp_private", "", true, "", vendorVariant)
- checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", vendorVariant)
-
- checkVndkModule(t, ctx, "libvndk_product", "", false, "", productVariant)
- checkVndkModule(t, ctx, "libvndk_sp_product_private", "", true, "", productVariant)
-
- // Check VNDK snapshot output.
- snapshotDir := "vndk-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
-
- vndkLibPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
- "arm64", "armv8-a"))
- vndkLib2ndPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
- "arm", "armv7-a-neon"))
-
- vndkCoreLibPath := filepath.Join(vndkLibPath, "shared", "vndk-core")
- vndkSpLibPath := filepath.Join(vndkLibPath, "shared", "vndk-sp")
- llndkLibPath := filepath.Join(vndkLibPath, "shared", "llndk-stub")
-
- vndkCoreLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-core")
- vndkSpLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "vndk-sp")
- llndkLib2ndPath := filepath.Join(vndkLib2ndPath, "shared", "llndk-stub")
-
- variant := "android_vendor.29_arm64_armv8-a_shared"
- variant2nd := "android_vendor.29_arm_armv7-a-neon_shared"
-
- snapshotSingleton := ctx.SingletonForTests("vndk-snapshot")
-
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLibPath, variant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLib2ndPath, variant2nd)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
- CheckSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLibPath, variant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLib2ndPath, variant2nd)
-
- snapshotConfigsPath := filepath.Join(snapshotVariantPath, "configs")
- CheckSnapshot(t, ctx, snapshotSingleton, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "android_common")
- CheckSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "android_common")
- CheckSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "android_common")
- CheckSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "android_common")
- CheckSnapshot(t, ctx, snapshotSingleton, "vndkproduct.libraries.txt", "vndkproduct.libraries.txt", snapshotConfigsPath, "android_common")
-
- checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
- "LLNDK: libc.so",
- "LLNDK: libdl.so",
- "LLNDK: libft2.so",
- "LLNDK: libllndk.so",
- "LLNDK: libm.so",
- "VNDK-SP: libc++.so",
- "VNDK-SP: libvndk_sp-x.so",
- "VNDK-SP: libvndk_sp_private-x.so",
- "VNDK-SP: libvndk_sp_product_private-x.so",
- "VNDK-core: libvndk-private.so",
- "VNDK-core: libvndk.so",
- "VNDK-core: libvndk_product.so",
- "VNDK-private: libft2.so",
- "VNDK-private: libvndk-private.so",
- "VNDK-private: libvndk_sp_private-x.so",
- "VNDK-private: libvndk_sp_product_private-x.so",
- "VNDK-product: libc++.so",
- "VNDK-product: libvndk_product.so",
- "VNDK-product: libvndk_sp_product_private-x.so",
- })
- checkVndkLibrariesOutput(t, ctx, "llndk.libraries.txt", []string{"libc.so", "libclang_rt.hwasan-llndk.so", "libdl.so", "libft2.so", "libllndk.so", "libm.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk-private.so", "libvndk.so", "libvndk_product.so"})
- checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp-x.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt", []string{"libft2.so", "libvndk-private.so", "libvndk_sp_private-x.so", "libvndk_sp_product_private-x.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkproduct.libraries.txt", []string{"libc++.so", "libvndk_product.so", "libvndk_sp_product_private-x.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", nil)
-}
-
-func TestVndkWithHostSupported(t *testing.T) {
- t.Parallel()
- ctx := testCc(t, `
- cc_library {
- name: "libvndk_host_supported",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- host_supported: true,
- }
-
- cc_library {
- name: "libvndk_host_supported_but_disabled_on_device",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- host_supported: true,
- enabled: false,
- target: {
- host: {
- enabled: true,
- }
- }
- }
-
- vndkcore_libraries_txt {
- name: "vndkcore.libraries.txt",
- }
- `)
-
- checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt", []string{"libvndk_host_supported.so"})
-}
-
-func TestVndkLibrariesTxtAndroidMk(t *testing.T) {
- t.Parallel()
- bp := `
- llndk_libraries_txt {
- name: "llndk.libraries.txt",
- insert_vndk_version: true,
- }`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.KeepVndk = BoolPtr(true)
- ctx := testCcWithConfig(t, config)
-
- module := ctx.ModuleForTests("llndk.libraries.txt", "android_common")
- entries := android.AndroidMkEntriesForTest(t, ctx, module.Module())[0]
- assertArrayString(t, entries.EntryMap["LOCAL_MODULE_STEM"], []string{"llndk.libraries.29.txt"})
-}
-
-func TestVndkUsingCoreVariant(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk2",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- nocrt: true,
- }
-
- vndkcorevariant_libraries_txt {
- name: "vndkcorevariant.libraries.txt",
- insert_vndk_version: false,
- }
- `
-
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
- config.TestProductVariables.KeepVndk = BoolPtr(true)
-
- setVndkMustUseVendorVariantListForTest(config, []string{"libvndk"})
-
- ctx := testCcWithConfig(t, config)
-
- checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", []string{"libc++.so", "libvndk2.so", "libvndk_sp.so"})
-}
-
func TestDataLibs(t *testing.T) {
t.Parallel()
bp := `
@@ -702,9 +298,6 @@
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
ctx := testCcWithConfig(t, config)
module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
@@ -761,9 +354,6 @@
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
ctx := testCcWithConfig(t, config)
module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
@@ -859,247 +449,9 @@
}
}
-func TestVndkModuleError(t *testing.T) {
- t.Parallel()
- // Check the error message for vendor_available and product_available properties.
- testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
- cc_library {
- name: "libvndk",
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- `)
-
- testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
- cc_library {
- name: "libvndk",
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- `)
-
- testCcErrorProductVndk(t, "product properties must have the same values with the vendor properties for VNDK modules", `
- cc_library {
- name: "libvndkprop",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- target: {
- vendor: {
- cflags: ["-DTEST",],
- },
- },
- }
- `)
-}
-
-func TestVndkDepError(t *testing.T) {
- t.Parallel()
- // Check whether an error is emitted when a VNDK lib depends on a system lib.
- testCcError(t, "dependency \".*\" of \".*\" missing variant", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- shared_libs: ["libfwk"], // Cause error
- nocrt: true,
- }
-
- cc_library {
- name: "libfwk",
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK lib depends on a vendor lib.
- testCcError(t, "dependency \".*\" of \".*\" missing variant", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- shared_libs: ["libvendor"], // Cause error
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK-SP lib depends on a system lib.
- testCcError(t, "dependency \".*\" of \".*\" missing variant", `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- shared_libs: ["libfwk"], // Cause error
- nocrt: true,
- }
-
- cc_library {
- name: "libfwk",
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK-SP lib depends on a vendor lib.
- testCcError(t, "dependency \".*\" of \".*\" missing variant", `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- shared_libs: ["libvendor"], // Cause error
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK-SP lib depends on a VNDK lib.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- shared_libs: ["libvndk"], // Cause error
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK lib depends on a non-VNDK lib.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- shared_libs: ["libnonvndk"],
- nocrt: true,
- }
-
- cc_library {
- name: "libnonvndk",
- vendor_available: true,
- product_available: true,
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK-private lib depends on a non-VNDK lib.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndkprivate",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- shared_libs: ["libnonvndk"],
- nocrt: true,
- }
-
- cc_library {
- name: "libnonvndk",
- vendor_available: true,
- product_available: true,
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK-sp lib depends on a non-VNDK lib.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndksp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- shared_libs: ["libnonvndk"],
- nocrt: true,
- }
-
- cc_library {
- name: "libnonvndk",
- vendor_available: true,
- product_available: true,
- nocrt: true,
- }
- `)
-
- // Check whether an error is emitted when a VNDK-sp-private lib depends on a non-VNDK lib.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndkspprivate",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- private: true,
- },
- shared_libs: ["libnonvndk"],
- nocrt: true,
- }
-
- cc_library {
- name: "libnonvndk",
- vendor_available: true,
- product_available: true,
- nocrt: true,
- }
- `)
-}
-
func TestDoubleLoadbleDep(t *testing.T) {
t.Parallel()
- // okay to link : LLNDK -> double_loadable VNDK
+ // okay to link : LLNDK -> double_loadable
testCc(t, `
cc_library {
name: "libllndk",
@@ -1113,32 +465,9 @@
name: "libdoubleloadable",
vendor_available: true,
product_available: true,
- vndk: {
- enabled: true,
- },
double_loadable: true,
}
`)
- // okay to link : LLNDK -> VNDK-SP
- testCc(t, `
- cc_library {
- name: "libllndk",
- shared_libs: ["libvndksp"],
- llndk: {
- symbol_file: "libllndk.map.txt",
- }
- }
-
- cc_library {
- name: "libvndksp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- }
- `)
// okay to link : double_loadable -> double_loadable
testCc(t, `
cc_library {
@@ -1154,15 +483,12 @@
double_loadable: true,
}
`)
- // okay to link : double_loadable VNDK -> double_loadable VNDK private
+ // okay to link : double_loadable -> double_loadable
testCc(t, `
cc_library {
name: "libdoubleloadable",
vendor_available: true,
product_available: true,
- vndk: {
- enabled: true,
- },
double_loadable: true,
shared_libs: ["libnondoubleloadable"],
}
@@ -1171,10 +497,6 @@
name: "libnondoubleloadable",
vendor_available: true,
product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
double_loadable: true,
}
`)
@@ -1204,7 +526,7 @@
func TestDoubleLoadableDepError(t *testing.T) {
t.Parallel()
- // Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
+ // Check whether an error is emitted when a LLNDK depends on a non-double_loadable lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
cc_library {
name: "libllndk",
@@ -1218,9 +540,6 @@
name: "libnondoubleloadable",
vendor_available: true,
product_available: true,
- vndk: {
- enabled: true,
- },
}
`)
@@ -1285,999 +604,13 @@
`)
}
-func TestCheckVndkMembershipBeforeDoubleLoadable(t *testing.T) {
- t.Parallel()
- testCcError(t, "module \"libvndksp\" variant .*: .*: VNDK-SP must only depend on VNDK-SP", `
- cc_library {
- name: "libvndksp",
- shared_libs: ["libanothervndksp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- }
- }
-
- cc_library {
- name: "libllndk",
- shared_libs: ["libanothervndksp"],
- }
-
- cc_library {
- name: "libanothervndksp",
- vendor_available: true,
- product_available: true,
- }
- `)
-}
-
-func TestVndkExt(t *testing.T) {
- t.Parallel()
- // This test checks the VNDK-Ext properties.
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- cc_library {
- name: "libvndk2",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- target: {
- vendor: {
- suffix: "-suffix",
- },
- product: {
- suffix: "-suffix",
- },
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk2_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk2",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk2_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- extends: "libvndk2",
- },
- nocrt: true,
- }
- `
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
- ctx := testCcWithConfig(t, config)
-
- checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk", vendorVariant)
- checkVndkModule(t, ctx, "libvndk_ext_product", "vndk", false, "libvndk", productVariant)
-
- mod_vendor := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
- assertString(t, mod_vendor.outputFile.Path().Base(), "libvndk2-suffix.so")
-
- mod_product := ctx.ModuleForTests("libvndk2_ext_product", productVariant).Module().(*Module)
- assertString(t, mod_product.outputFile.Path().Base(), "libvndk2-suffix.so")
-}
-
-func TestVndkExtError(t *testing.T) {
- t.Parallel()
- // This test ensures an error is emitted in ill-formed vndk-ext definition.
- testCcError(t, "must set `vendor: true` or `product_specific: true` to set `extends: \".*\"`", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
- `)
-
- testCcError(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- `)
-
- testCcErrorProductVndk(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- `)
-
- testCcErrorProductVndk(t, "must not set at the same time as `vndk: {extends: \"\\.\\.\\.\"}`", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext_product",
- product_specific: true,
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
- `)
-}
-
-func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
- t.Parallel()
- // This test ensures an error is emitted for inconsistent support_system_process.
- testCcError(t, "module \".*\" with mismatched support_system_process", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- support_system_process: true,
- },
- nocrt: true,
- }
- `)
-
- testCcError(t, "module \".*\" with mismatched support_system_process", `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- },
- nocrt: true,
- }
- `)
-}
-
-func TestVndkExtVendorAvailableFalseError(t *testing.T) {
- t.Parallel()
- // This test ensures an error is emitted when a VNDK-Ext library extends a VNDK library
- // with `private: true`.
- testCcError(t, "`extends` refers module \".*\" which has `private: true`", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
- `)
-
- testCcErrorProductVndk(t, "`extends` refers module \".*\" which has `private: true`", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
- `)
-}
-
-func TestVendorModuleUseVndkExt(t *testing.T) {
- t.Parallel()
- // This test ensures a vendor module can depend on a VNDK-Ext library.
- testCc(t, `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- shared_libs: ["libvndk_ext", "libvndk_sp_ext"],
- nocrt: true,
- }
- `)
-}
-
-func TestVndkExtUseVendorLib(t *testing.T) {
- t.Parallel()
- // This test ensures a VNDK-Ext library can depend on a vendor library.
- testCc(t, `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- shared_libs: ["libvendor"],
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
- `)
-
- // This test ensures a VNDK-SP-Ext library can depend on a vendor library.
- testCc(t, `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- support_system_process: true,
- },
- shared_libs: ["libvendor"], // Cause an error
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
- `)
-}
-
-func TestProductVndkExtDependency(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- shared_libs: ["libproduct_for_vndklibs"],
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- support_system_process: true,
- },
- shared_libs: ["libproduct_for_vndklibs"],
- nocrt: true,
- }
-
- cc_library {
- name: "libproduct",
- product_specific: true,
- shared_libs: ["libvndk_ext_product", "libvndk_sp_ext_product"],
- nocrt: true,
- }
-
- cc_library {
- name: "libproduct_for_vndklibs",
- product_specific: true,
- nocrt: true,
- }
- `
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
- testCcWithConfig(t, config)
-}
-
-func TestVndkSpExtUseVndkError(t *testing.T) {
- t.Parallel()
- // This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK
- // library.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- support_system_process: true,
- },
- shared_libs: ["libvndk"], // Cause an error
- nocrt: true,
- }
- `)
-
- // This test ensures an error is emitted if a VNDK-SP-Ext library depends on a VNDK-Ext
- // library.
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- support_system_process: true,
- },
- shared_libs: ["libvndk_ext"], // Cause an error
- nocrt: true,
- }
- `)
-}
-
-func TestVndkUseVndkExtError(t *testing.T) {
- t.Parallel()
- // This test ensures an error is emitted if a VNDK/VNDK-SP library depends on a
- // VNDK-Ext/VNDK-SP-Ext library.
- testCcError(t, "dependency \".*\" of \".*\" missing variant", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk2",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- shared_libs: ["libvndk_ext"],
- nocrt: true,
- }
- `)
-
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk2",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- target: {
- vendor: {
- shared_libs: ["libvndk_ext"],
- },
- },
- nocrt: true,
- }
- `)
-
- testCcError(t, "dependency \".*\" of \".*\" missing variant", `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- support_system_process: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_2",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- shared_libs: ["libvndk_sp_ext"],
- nocrt: true,
- }
- `)
-
- testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk_sp",
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_sp2",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- target: {
- vendor: {
- shared_libs: ["libvndk_sp_ext"],
- },
- },
- nocrt: true,
- }
- `)
-}
-
-func TestEnforceProductVndkVersion(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library {
- name: "libllndk",
- llndk: {
- symbol_file: "libllndk.map.txt",
- }
- }
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- cc_library {
- name: "libvndk_sp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- nocrt: true,
- }
- cc_library {
- name: "libva",
- vendor_available: true,
- nocrt: true,
- }
- cc_library {
- name: "libpa",
- product_available: true,
- nocrt: true,
- }
- cc_library {
- name: "libboth_available",
- vendor_available: true,
- product_available: true,
- nocrt: true,
- srcs: ["foo.c"],
- target: {
- vendor: {
- suffix: "-vendor",
- },
- product: {
- suffix: "-product",
- },
- }
- }
- cc_library {
- name: "libproduct_va",
- product_specific: true,
- vendor_available: true,
- nocrt: true,
- }
- cc_library {
- name: "libprod",
- product_specific: true,
- shared_libs: [
- "libllndk",
- "libvndk",
- "libvndk_sp",
- "libpa",
- "libboth_available",
- "libproduct_va",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libvendor",
- vendor: true,
- shared_libs: [
- "libllndk",
- "libvndk",
- "libvndk_sp",
- "libva",
- "libboth_available",
- "libproduct_va",
- ],
- nocrt: true,
- }
- `
-
- ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
-
- checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
- checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
-
- mod_vendor := ctx.ModuleForTests("libboth_available", vendorVariant).Module().(*Module)
- assertString(t, mod_vendor.outputFile.Path().Base(), "libboth_available-vendor.so")
-
- mod_product := ctx.ModuleForTests("libboth_available", productVariant).Module().(*Module)
- assertString(t, mod_product.outputFile.Path().Base(), "libboth_available-product.so")
-
- ensureStringContains := func(t *testing.T, str string, substr string) {
- t.Helper()
- if !strings.Contains(str, substr) {
- t.Errorf("%q is not found in %v", substr, str)
- }
- }
- ensureStringNotContains := func(t *testing.T, str string, substr string) {
- t.Helper()
- if strings.Contains(str, substr) {
- t.Errorf("%q is found in %v", substr, str)
- }
- }
-
- // _static variant is used since _shared reuses *.o from the static variant
- vendor_static := ctx.ModuleForTests("libboth_available", strings.Replace(vendorVariant, "_shared", "_static", 1))
- product_static := ctx.ModuleForTests("libboth_available", strings.Replace(productVariant, "_shared", "_static", 1))
-
- vendor_cflags := vendor_static.Rule("cc").Args["cFlags"]
- ensureStringContains(t, vendor_cflags, "-D__ANDROID_VNDK__")
- ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR__")
- ensureStringNotContains(t, vendor_cflags, "-D__ANDROID_PRODUCT__")
- ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR_API__=202404")
-
- product_cflags := product_static.Rule("cc").Args["cFlags"]
- ensureStringContains(t, product_cflags, "-D__ANDROID_VNDK__")
- ensureStringContains(t, product_cflags, "-D__ANDROID_PRODUCT__")
- ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR__")
- ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR_API__=202404")
-}
-
-func TestEnforceProductVndkVersionErrors(t *testing.T) {
- t.Parallel()
- testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
- cc_library {
- name: "libprod",
- product_specific: true,
- shared_libs: [
- "libvendor",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
- `)
- testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
- cc_library {
- name: "libprod",
- product_specific: true,
- shared_libs: [
- "libsystem",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libsystem",
- nocrt: true,
- }
- `)
- testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
- cc_library {
- name: "libprod",
- product_specific: true,
- shared_libs: [
- "libva",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libva",
- vendor_available: true,
- nocrt: true,
- }
- `)
- testCcErrorProductVndk(t, "non-VNDK module should not link to \".*\" which has `private: true`", `
- cc_library {
- name: "libprod",
- product_specific: true,
- shared_libs: [
- "libvndk_private",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libvndk_private",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- nocrt: true,
- }
- `)
- testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.29", `
- cc_library {
- name: "libprod",
- product_specific: true,
- shared_libs: [
- "libsystem_ext",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libsystem_ext",
- system_ext_specific: true,
- nocrt: true,
- }
- `)
- testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:", `
- cc_library {
- name: "libsystem",
- shared_libs: [
- "libproduct_va",
- ],
- nocrt: true,
- }
- cc_library {
- name: "libproduct_va",
- product_specific: true,
- vendor_available: true,
- nocrt: true,
- }
- `)
-}
-
func TestMakeLinkType(t *testing.T) {
t.Parallel()
bp := `
cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- }
- cc_library {
- name: "libvndksp",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- }
- cc_library {
- name: "libvndkprivate",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- }
- cc_library {
name: "libvendor",
vendor: true,
}
- cc_library {
- name: "libvndkext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- }
vndk_prebuilt_shared {
name: "prevndk",
version: "27",
@@ -2307,40 +640,15 @@
private: true,
}
}
-
llndk_libraries_txt {
name: "llndk.libraries.txt",
}
- vndkcore_libraries_txt {
- name: "vndkcore.libraries.txt",
- }
- vndksp_libraries_txt {
- name: "vndksp.libraries.txt",
- }
- vndkprivate_libraries_txt {
- name: "vndkprivate.libraries.txt",
- }
- vndkcorevariant_libraries_txt {
- name: "vndkcorevariant.libraries.txt",
- insert_vndk_version: false,
- }
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
// native:vndk
ctx := testCcWithConfig(t, config)
- checkVndkLibrariesOutput(t, ctx, "vndkcore.libraries.txt",
- []string{"libvndk.so", "libvndkprivate.so"})
- checkVndkLibrariesOutput(t, ctx, "vndksp.libraries.txt",
- []string{"libc++.so", "libvndksp.so"})
- checkVndkLibrariesOutput(t, ctx, "llndk.libraries.txt",
- []string{"libc.so", "libdl.so", "libft2.so", "libllndk.so", "libllndkprivate.so", "libm.so"})
- checkVndkLibrariesOutput(t, ctx, "vndkprivate.libraries.txt",
- []string{"libft2.so", "libllndkprivate.so", "libvndkprivate.so"})
-
vendorVariant27 := "android_vendor.27_arm64_armv8-a_shared"
tests := []struct {
@@ -2348,15 +656,9 @@
name string
expected string
}{
- {vendorVariant, "libvndk", "native:vndk"},
- {vendorVariant, "libvndksp", "native:vndk"},
- {vendorVariant, "libvndkprivate", "native:vndk_private"},
{vendorVariant, "libvendor", "native:vendor"},
- {vendorVariant, "libvndkext", "native:vendor"},
{vendorVariant, "libllndk", "native:vndk"},
{vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"},
- {coreVariant, "libvndk", "native:platform"},
- {coreVariant, "libvndkprivate", "native:platform"},
{coreVariant, "libllndk", "native:platform"},
}
for _, test := range tests {
@@ -2674,21 +976,19 @@
`)
actual := result.ModuleVariantsForTests("libllndk")
for i := 0; i < len(actual); i++ {
- if !strings.HasPrefix(actual[i], "android_vendor.29_") {
+ if !strings.HasPrefix(actual[i], "android_vendor_") {
actual = append(actual[:i], actual[i+1:]...)
i--
}
}
expected := []string{
- "android_vendor.29_arm64_armv8-a_shared_current",
- "android_vendor.29_arm64_armv8-a_shared",
- "android_vendor.29_arm_armv7-a-neon_shared_current",
- "android_vendor.29_arm_armv7-a-neon_shared",
+ "android_vendor_arm64_armv8-a_shared",
+ "android_vendor_arm_armv7-a-neon_shared",
}
android.AssertArrayString(t, "variants for llndk stubs", expected, actual)
- params := result.ModuleForTests("libllndk", "android_vendor.29_arm_armv7-a-neon_shared").Description("generate stub")
- android.AssertSame(t, "use VNDK version for default stubs", "current", params.Args["apiLevel"])
+ params := result.ModuleForTests("libllndk", "android_vendor_arm_armv7-a-neon_shared").Description("generate stub")
+ android.AssertSame(t, "use Vendor API level for default stubs", "202404", params.Args["apiLevel"])
checkExportedIncludeDirs := func(module, variant string, expectedDirs ...string) {
t.Helper()
@@ -2699,11 +999,11 @@
}
checkExportedIncludeDirs("libllndk", "android_arm64_armv8-a_shared", "include")
- checkExportedIncludeDirs("libllndk", "android_vendor.29_arm64_armv8-a_shared", "include")
+ checkExportedIncludeDirs("libllndk", "android_vendor_arm64_armv8-a_shared", "include")
checkExportedIncludeDirs("libllndk_with_external_headers", "android_arm64_armv8-a_shared", "include")
- checkExportedIncludeDirs("libllndk_with_external_headers", "android_vendor.29_arm64_armv8-a_shared", "include_llndk")
+ checkExportedIncludeDirs("libllndk_with_external_headers", "android_vendor_arm64_armv8-a_shared", "include_llndk")
checkExportedIncludeDirs("libllndk_with_override_headers", "android_arm64_armv8-a_shared", "include")
- checkExportedIncludeDirs("libllndk_with_override_headers", "android_vendor.29_arm64_armv8-a_shared", "include_llndk")
+ checkExportedIncludeDirs("libllndk_with_override_headers", "android_vendor_arm64_armv8-a_shared", "include_llndk")
}
func TestLlndkHeaders(t *testing.T) {
@@ -2735,7 +1035,7 @@
`)
// _static variant is used since _shared reuses *.o from the static variant
- cc := ctx.ModuleForTests("libvendor", "android_vendor.29_arm_armv7-a-neon_static").Rule("cc")
+ cc := ctx.ModuleForTests("libvendor", "android_vendor_arm_armv7-a-neon_static").Rule("cc")
cflags := cc.Args["cFlags"]
if !strings.Contains(cflags, "-Imy_include") {
t.Errorf("cflags for libvendor must contain -Imy_include, but was %#v.", cflags)
@@ -2857,7 +1157,7 @@
// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
// and vendor variants.
- variant = "android_vendor.29_arm64_armv8-a_shared"
+ variant = "android_vendor_arm64_armv8-a_shared"
module = ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
@@ -2867,7 +1167,7 @@
// runtime_libs for product variants have '.product' suffixes if the modules have both core
// and product variants.
- variant = "android_product.29_arm64_armv8-a_shared"
+ variant = "android_product_arm64_armv8-a_shared"
module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available.product"}, module)
@@ -2884,7 +1184,7 @@
module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available"}, module)
- variant = "android_vendor.29_arm64_armv8-a_shared"
+ variant = "android_vendor_arm64_armv8-a_shared"
module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
checkRuntimeLibs(t, nil, module)
}
@@ -3067,9 +1367,6 @@
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
ctx := testCcWithConfig(t, config)
module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
@@ -4797,8 +3094,7 @@
}
}
-// TODO(b/316829758) Remove this test and do not set VNDK version from other tests
-func TestImageVariantsWithoutVndk(t *testing.T) {
+func TestImageVariants(t *testing.T) {
t.Parallel()
bp := `
@@ -4817,7 +3113,7 @@
}
`
- ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
hasDep := func(m android.Module, wantDep android.Module) bool {
t.Helper()
@@ -4845,7 +3141,7 @@
testDepWithVariant("product")
}
-func TestVendorSdkVersionWithoutVndk(t *testing.T) {
+func TestVendorSdkVersion(t *testing.T) {
t.Parallel()
bp := `
@@ -4863,7 +3159,7 @@
}
`
- ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
testSdkVersionFlag := func(module, version string) {
flags := ctx.ModuleForTests(module, "android_vendor_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "min sdk version", flags, "-target aarch64-linux-android"+version)
@@ -4873,7 +3169,7 @@
testSdkVersionFlag("libbar", "29")
ctx = android.GroupFixturePreparers(
- prepareForCcTestWithoutVndk,
+ prepareForCcTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
if variables.BuildFlags == nil {
variables.BuildFlags = make(map[string]string)
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 82beb29..10342a3 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -49,8 +49,8 @@
}
arm64Ldflags = []string{
- "-Wl,--hash-style=gnu",
"-Wl,-z,separate-code",
+ "-Wl,-z,separate-loadable-segments",
}
arm64Lldflags = arm64Ldflags
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 335ad56..f7d190b 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -42,7 +42,6 @@
"-Wl,-z,now",
"-Wl,--build-id=md5",
"-Wl,--fatal-warnings",
- "-Wl,--hash-style=gnu",
"-Wl,--no-undefined-version",
}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 603bc6d..3284e4b 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -38,7 +38,6 @@
}
armLdflags = []string{
- "-Wl,--hash-style=gnu",
"-Wl,-m,armelf",
// Revert this after b/322359235 is fixed
"-Wl,-mllvm", "-Wl,-enable-shrink-wrap=false",
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 6a84fee..47f0de1 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -23,24 +23,29 @@
var (
riscv64Cflags = []string{
- // Help catch common 32/64-bit errors.
+ // Help catch common 32/64-bit errors. (This is duplicated in all 64-bit
+ // architectures' cflags.)
"-Werror=implicit-function-declaration",
+ // This is already the driver's Android default, but duplicated here (and
+ // below) for ease of experimentation with additional extensions.
"-march=rv64gcv_zba_zbb_zbs",
- "-munaligned-access",
- // Until https://gitlab.com/qemu-project/qemu/-/issues/1976 is fixed...
+ // TODO: move to driver (https://github.com/google/android-riscv64/issues/111)
+ "-mno-strict-align",
+ // TODO: remove when qemu V works (https://gitlab.com/qemu-project/qemu/-/issues/1976)
+ // (Note that we'll probably want to wait for berberis to be good enough
+ // that most people don't care about qemu's V performance either!)
"-mno-implicit-float",
- // (https://github.com/google/android-riscv64/issues/124)
+ // TODO: remove when clang default changed (https://github.com/google/android-riscv64/issues/124)
"-mllvm -jump-is-expensive=false",
}
riscv64ArchVariantCflags = map[string][]string{}
riscv64Ldflags = []string{
- "-Wl,--hash-style=gnu",
+ // This is already the driver's Android default, but duplicated here (and
+ // above) for ease of experimentation with additional extensions.
"-march=rv64gcv_zba_zbb_zbs",
- "-munaligned-access",
- // We should change the default for this in clang, but for now...
- // (https://github.com/google/android-riscv64/issues/124)
+ // TODO: remove when clang default changed (https://github.com/google/android-riscv64/issues/124)
"-Wl,-mllvm -Wl,-jump-is-expensive=false",
}
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index b97d511..ca2c2b7 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -30,7 +30,7 @@
x86_64Cppflags = []string{}
x86_64Ldflags = []string{
- "-Wl,--hash-style=gnu",
+ "-Wl,-z,separate-loadable-segments",
}
X86_64Lldflags = x86_64Ldflags
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 2faa670..60b8339 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -33,9 +33,7 @@
x86Cppflags = []string{}
- x86Ldflags = []string{
- "-Wl,--hash-style=gnu",
- }
+ x86Ldflags = []string{}
x86ArchVariantCflags = map[string][]string{
"": []string{
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index f80be99..99d4ebb 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -46,7 +46,6 @@
"-Wl,-z,now",
"-Wl,--build-id=md5",
"-Wl,--fatal-warnings",
- "-Wl,--hash-style=gnu",
"-Wl,--no-undefined-version",
// Use the device gcc toolchain
diff --git a/cc/genrule.go b/cc/genrule.go
index 0fb3e2d..23e97d0 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -121,18 +121,7 @@
}
} else {
if vendorVariantRequired {
- // If vndkVersion is current, we can always use PlatformVndkVersion.
- // If not, we assume modules under proprietary paths are compatible for
- // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
- // PLATFORM_VNDK_VERSION.
- if vndkVersion == "current" || !snapshot.IsVendorProprietaryModule(ctx) {
- variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
- } else {
- variants = append(variants, VendorVariationPrefix+vndkVersion)
- }
- }
- if productVariantRequired {
- variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
+ variants = append(variants, VendorVariationPrefix+vndkVersion)
}
}
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index 05c644f..b3d5116 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -200,7 +200,7 @@
}
`
t.Helper()
- ctx := PrepareForTestWithCcIncludeVndk.RunTestWithBp(t, bp)
+ ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
variants := ctx.ModuleVariantsForTests("gen")
if !slices.Contains(variants, "android_vendor_arm64_armv8-a") {
@@ -210,3 +210,47 @@
t.Errorf(`expected product variant, but does not exist in %v`, variants)
}
}
+
+// cc_genrule is initialized to android.InitAndroidArchModule
+// that is an architecture-specific Android module.
+// So testing properties tagged with `android:"arch_variant"`
+// for cc_genrule.
+func TestMultilibGenruleOut(t *testing.T) {
+ bp := `
+ cc_genrule {
+ name: "gen",
+ cmd: "cp $(in) $(out)",
+ srcs: ["foo"],
+ multilib: {
+ lib32: {
+ out: [
+ "subdir32/external-module32",
+ ],
+ },
+ lib64: {
+ out: [
+ "subdir64/external-module64",
+ ],
+ },
+ },
+ }
+ `
+ result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
+ gen_32bit := result.ModuleForTests("gen", "android_arm_armv7-a-neon").OutputFiles(t, "")
+ android.AssertPathsEndWith(t,
+ "genrule_out",
+ []string{
+ "subdir32/external-module32",
+ },
+ gen_32bit,
+ )
+
+ gen_64bit := result.ModuleForTests("gen", "android_arm64_armv8-a").OutputFiles(t, "")
+ android.AssertPathsEndWith(t,
+ "genrule_out",
+ []string{
+ "subdir64/external-module64",
+ },
+ gen_64bit,
+ )
+}
diff --git a/cc/image.go b/cc/image.go
index d02a2f3..50d1b23 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -429,7 +429,6 @@
var vendorVariants []string
var productVariants []string
- platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
boardVndkVersion := mctx.DeviceConfig().VndkVersion()
recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
@@ -444,17 +443,13 @@
needVndkVersionVendorVariantForLlndk = boardVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, "30"))
}
}
- if boardVndkVersion == "current" {
- boardVndkVersion = platformVndkVersion
- }
-
if m.NeedsLlndkVariants() {
// This is an LLNDK library. The implementation of the library will be on /system,
// and vendor and product variants will be created with LLNDK stubs.
// The LLNDK libraries need vendor variants even if there is no VNDK.
coreVariantNeeded = true
- vendorVariants = append(vendorVariants, platformVndkVersion)
- productVariants = append(productVariants, platformVndkVersion)
+ vendorVariants = append(vendorVariants, "")
+ productVariants = append(productVariants, "")
// Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not
// provide the LLNDK stub libraries.
if needVndkVersionVendorVariantForLlndk {
@@ -465,7 +460,7 @@
// for system and product.
coreVariantNeeded = true
vendorVariants = append(vendorVariants, boardVndkVersion)
- productVariants = append(productVariants, platformVndkVersion)
+ productVariants = append(productVariants, "")
} else if m.IsSnapshotPrebuilt() {
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
// PRODUCT_EXTRA_VNDK_VERSIONS.
@@ -486,13 +481,13 @@
if snapshot.IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
+ vendorVariants = append(vendorVariants, "")
}
}
// product_available modules are available to /product.
if m.HasProductVariant() {
- productVariants = append(productVariants, platformVndkVersion)
+ productVariants = append(productVariants, "")
}
} else if vendorSpecific && m.SdkVersion() == "" {
// This will be available in /vendor (or /odm) only
@@ -505,13 +500,13 @@
// are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
if m.KernelHeadersDecorator() {
vendorVariants = append(vendorVariants,
- platformVndkVersion,
+ "",
boardVndkVersion,
)
} else if snapshot.IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
+ vendorVariants = append(vendorVariants, "")
}
} else {
// This is either in /system (or similar: /data), or is a
@@ -523,7 +518,7 @@
if coreVariantNeeded && productSpecific && m.SdkVersion() == "" {
// The module has "product_specific: true" that does not create core variant.
coreVariantNeeded = false
- productVariants = append(productVariants, platformVndkVersion)
+ productVariants = append(productVariants, "")
}
if m.RamdiskAvailable() {
diff --git a/cc/library.go b/cc/library.go
index e2b4d4f..5607632 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -677,18 +677,16 @@
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
if ctx.IsLlndk() {
+ vendorApiLevel := ctx.Config().VendorApiLevel()
+ if vendorApiLevel == "" {
+ // TODO(b/321892570): Some tests relying on old fixtures which
+ // doesn't set vendorApiLevel. Needs to fix them.
+ vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
+ }
// This is the vendor variant of an LLNDK library, build the LLNDK stubs.
- vndkVer := ctx.Module().(*Module).VndkVersion()
- if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" {
- // For non-enforcing devices, vndkVer is empty. Use "current" in that case, too.
- vndkVer = "current"
- }
- if library.stubsVersion() != "" {
- vndkVer = library.stubsVersion()
- }
nativeAbiResult := parseNativeAbiDefinition(ctx,
String(library.Properties.Llndk.Symbol_file),
- android.ApiLevelOrPanic(ctx, vndkVer), "--llndk")
+ android.ApiLevelOrPanic(ctx, vendorApiLevel), "--llndk")
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
if !Bool(library.Properties.Llndk.Unversioned) {
library.versionScriptPath = android.OptionalPathForPath(
@@ -1893,6 +1891,10 @@
if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
return library.Properties.Stubs.Symbol_file
}
+ // TODO(b/309880485): Distinguish platform, NDK, LLNDK, and APEX version scripts.
+ if library.baseLinker.Properties.Version_script != nil {
+ return library.baseLinker.Properties.Version_script
+ }
return nil
}
@@ -1913,12 +1915,15 @@
}
if library.hasLLNDKStubs() && ctx.Module().(*Module).InVendorOrProduct() {
- // LLNDK libraries only need a single stubs variant.
- return []string{android.FutureApiLevel.String()}
+ // LLNDK libraries only need a single stubs variant (""), which is
+ // added automatically in createVersionVariations().
+ return nil
}
// Future API level is implicitly added if there isn't
- return addCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
+ versions := addCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
+ normalizeVersions(ctx, versions)
+ return versions
}
func addCurrentVersionIfNotPresent(vers []string) []string {
@@ -2290,10 +2295,6 @@
return
}
versions := library.stubsVersions(mctx)
- if len(versions) <= 0 {
- return
- }
- normalizeVersions(mctx, versions)
if mctx.Failed() {
return
}
diff --git a/cc/library_stub.go b/cc/library_stub.go
index aab6664..cddb1b5 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -496,11 +496,10 @@
func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
var variations []string
- platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
if String(v.properties.Variant) == "llndk" {
- variations = append(variations, VendorVariationPrefix+platformVndkVersion)
- variations = append(variations, ProductVariationPrefix+platformVndkVersion)
+ variations = append(variations, VendorVariation)
+ variations = append(variations, ProductVariation)
}
return variations
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
index 528577a..4df0a41 100644
--- a/cc/library_stub_test.go
+++ b/cc/library_stub_test.go
@@ -71,8 +71,8 @@
android.AssertBoolEquals(t, "original library should be linked with non-stub variant", true, hasDirectDependency(t, ctx, libfoo, libbar))
android.AssertBoolEquals(t, "Stub library from API surface should be not linked with non-stub variant", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
- libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
- libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+ libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
+ libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfooVendor, libbar))
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfooVendor, libbarApiImportVendor))
@@ -102,8 +102,8 @@
ctx := prepareForCcTest.RunTestWithBp(t, bp)
- libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+ libfoo := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
+ libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
}
@@ -135,9 +135,9 @@
ctx := prepareForCcTest.RunTestWithBp(t, bp)
- libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
- libbar := ctx.ModuleForTests("libbar", "android_vendor.29_arm64_armv8-a_shared").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+ libfoo := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Module()
+ libbar := ctx.ModuleForTests("libbar", "android_vendor_arm64_armv8-a_shared").Module()
+ libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
@@ -174,13 +174,13 @@
}
`
ctx := prepareForCcTest.RunTestWithBp(t, bp)
- vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+ vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
- vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
+ vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
// Building the stub.so file first assembles its .h files in multi-tree out.
// These header files are required for compiling the other API domain (vendor in this case)
android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
@@ -223,17 +223,17 @@
ctx := prepareForCcTest.RunTestWithBp(t, bp)
- binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
- libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
- libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
+ binfoo := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Module()
+ libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
+ libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor_arm64_armv8-a").Module()
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
- binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
+ binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Rule("ld").Args["libFlags"]
android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar.llndk.apiimport.so")
- binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+ binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
}
@@ -446,12 +446,12 @@
binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
- libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+ libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))
- binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module()
+ binbaz := ctx.ModuleForTests("binbaz", "android_vendor_arm64_armv8-a").Module()
android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
diff --git a/cc/linker.go b/cc/linker.go
index 2c50db2..9686697 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -530,13 +530,6 @@
flags.Global.LdFlags = append(flags.Global.LdFlags, RpathFlags(ctx)...)
}
- if ctx.useSdk() {
- // The bionic linker now has support gnu style hashes (which are much faster!), but shipping
- // to older devices requires the old style hash. Fortunately, we can build with both and
- // it'll work anywhere.
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--hash-style=both")
- }
-
flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ToolchainLdflags())
// Version_script is not needed when linking stubs lib where the version
diff --git a/cc/lto.go b/cc/lto.go
index 05fa8ee..a084db7 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -90,10 +90,6 @@
} else if ctx.testBinary() || ctx.testLibrary() {
// Do not enable LTO for tests for better debugging.
ltoEnabled = false
- } else if ctx.isVndk() {
- // FIXME: ThinLTO for VNDK produces different output.
- // b/169217596
- ltoEnabled = false
}
lto.Properties.LtoDefault = ltoDefault
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 183e818..64193b1 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -325,13 +325,6 @@
if runtime.GOOS == "darwin" {
return false
}
- // abidw doesn't currently handle top-byte-ignore correctly. Disable ABI
- // dumping for those configs while we wait for a fix. We'll still have ABI
- // checking coverage from non-hwasan builds.
- // http://b/190554910
- if android.InList("hwaddress", config.SanitizeDevice()) {
- return false
- }
// http://b/156513478
return config.ReleaseNdkAbiMonitored()
}
diff --git a/cc/ndkstubgen/test_ndkstubgen.py b/cc/ndkstubgen/test_ndkstubgen.py
index 1e0bdf3..22f31d9 100755
--- a/cc/ndkstubgen/test_ndkstubgen.py
+++ b/cc/ndkstubgen/test_ndkstubgen.py
@@ -463,6 +463,98 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ def test_integration_with_llndk(self) -> None:
+ input_file = io.StringIO(textwrap.dedent("""\
+ VERSION_34 { # introduced=34
+ global:
+ foo;
+ bar; # llndk
+ };
+ VERSION_35 { # introduced=35
+ global:
+ wiggle;
+ waggle;
+ waggle; # llndk=202404
+ bubble; # llndk=202404
+ duddle;
+ duddle; # llndk=202504
+ } VERSION_34;
+ """))
+ f = copy(self.filter)
+ f.llndk = True
+ f.api = 202404
+ parser = symbolfile.SymbolFileParser(input_file, {}, f)
+ versions = parser.parse()
+
+ src_file = io.StringIO()
+ version_file = io.StringIO()
+ symbol_list_file = io.StringIO()
+
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file, f)
+ generator.write(versions)
+
+ expected_src = textwrap.dedent("""\
+ void foo() {}
+ void bar() {}
+ void waggle() {}
+ void bubble() {}
+ """)
+ self.assertEqual(expected_src, src_file.getvalue())
+
+ expected_version = textwrap.dedent("""\
+ VERSION_34 {
+ global:
+ foo;
+ bar;
+ };
+ VERSION_35 {
+ global:
+ waggle;
+ bubble;
+ } VERSION_34;
+ """)
+ self.assertEqual(expected_version, version_file.getvalue())
+
+ def test_integration_with_llndk_with_single_version_block(self) -> None:
+ input_file = io.StringIO(textwrap.dedent("""\
+ LIBANDROID {
+ global:
+ foo; # introduced=34
+ bar; # introduced=35
+ bar; # llndk=202404
+ baz; # introduced=35
+ };
+ """))
+ f = copy(self.filter)
+ f.llndk = True
+ f.api = 202404
+ parser = symbolfile.SymbolFileParser(input_file, {}, f)
+ versions = parser.parse()
+
+ src_file = io.StringIO()
+ version_file = io.StringIO()
+ symbol_list_file = io.StringIO()
+
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file, f)
+ generator.write(versions)
+
+ expected_src = textwrap.dedent("""\
+ void foo() {}
+ void bar() {}
+ """)
+ self.assertEqual(expected_src, src_file.getvalue())
+
+ expected_version = textwrap.dedent("""\
+ LIBANDROID {
+ global:
+ foo;
+ bar;
+ };
+ """)
+ self.assertEqual(expected_version, version_file.getvalue())
+
def test_empty_stub(self) -> None:
"""Tests that empty stubs can be generated.
diff --git a/cc/object_test.go b/cc/object_test.go
index c0d1331..004dfd3 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -41,7 +41,7 @@
{"android_arm64_armv8-a_sdk_29", "29"},
{"android_arm64_armv8-a_sdk_30", "30"},
{"android_arm64_armv8-a_sdk_current", "10000"},
- {"android_vendor.29_arm64_armv8-a", "29"},
+ {"android_vendor_arm64_armv8-a", "10000"},
}
ctx := prepareForCcTest.RunTestWithBp(t, bp)
@@ -50,7 +50,7 @@
expected := "-target aarch64-linux-android" + v.num + " "
android.AssertStringDoesContain(t, "cflag", cflags, expected)
}
- ctx = prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+ ctx = prepareForCcTest.RunTestWithBp(t, bp)
android.AssertStringDoesContain(t, "cflag",
ctx.ModuleForTests("crt_foo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"],
"-target aarch64-linux-android10000 ")
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index e769fe9..7d003a9 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -324,7 +324,7 @@
variations = append(ctx.Target().Variations(), blueprint.Variation{
Mutator: "image",
- Variation: ProductVariationPrefix + ctx.DeviceConfig().PlatformVndkVersion()})
+ Variation: ProductVariation})
if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py
index 345e9f9..4553616 100644
--- a/cc/symbolfile/__init__.py
+++ b/cc/symbolfile/__init__.py
@@ -103,13 +103,24 @@
@property
def has_llndk_tags(self) -> bool:
"""Returns True if any LL-NDK tags are set."""
- return 'llndk' in self.tags
+ for tag in self.tags:
+ if tag == 'llndk' or tag.startswith('llndk='):
+ return True
+ return False
@property
def has_platform_only_tags(self) -> bool:
"""Returns True if any platform-only tags are set."""
return 'platform-only' in self.tags
+ def copy_introduced_from(self, tags: Tags) -> None:
+ """Copies introduced= or introduced-*= tags."""
+ for tag in tags:
+ if tag.startswith('introduced=') or tag.startswith('introduced-'):
+ name, _ = split_tag(tag)
+ if not any(self_tag.startswith(name + '=') for self_tag in self.tags):
+ self.tags += (tag,)
+
@dataclass
class Symbol:
@@ -147,6 +158,8 @@
"""Returns true if this tag has an API level that may need decoding."""
if tag.startswith('llndk-deprecated='):
return True
+ if tag.startswith('llndk='):
+ return True
if tag.startswith('introduced='):
return True
if tag.startswith('introduced-'):
@@ -237,15 +250,22 @@
This defines the rules shared between version tagging and symbol tagging.
"""
- # The apex and llndk tags will only exclude APIs from other modes. If in
+ # LLNDK mode/tags follow the similar filtering except that API level checking
+ # is based llndk= instead of introduced=.
+ if self.llndk:
+ if tags.has_mode_tags and not tags.has_llndk_tags:
+ return True
+ if not symbol_in_arch(tags, self.arch):
+ return True
+ if not symbol_in_llndk_api(tags, self.arch, self.api):
+ return True
+ return False
# APEX or LLNDK mode and neither tag is provided, we fall back to the
# default behavior because all NDK symbols are implicitly available to
# APEX and LLNDK.
if tags.has_mode_tags:
if self.apex and tags.has_apex_tags:
return False
- if self.llndk and tags.has_llndk_tags:
- return False
if self.systemapi and tags.has_systemapi_tags:
return False
return True
@@ -266,6 +286,10 @@
return True
if version.tags.has_platform_only_tags:
return True
+ # Include all versions when targeting LLNDK because LLNDK symbols are self-versioned.
+ # Empty version block will be handled separately.
+ if self.llndk:
+ return False
return self._should_omit_tags(version.tags)
def should_omit_symbol(self, symbol: Symbol) -> bool:
@@ -292,6 +316,14 @@
# for the tagged architectures.
return not has_arch_tags
+def symbol_in_llndk_api(tags: Iterable[Tag], arch: Arch, api: int) -> bool:
+ """Returns true if the symbol is present for the given LLNDK API level."""
+ # Check llndk= first.
+ for tag in tags:
+ if tag.startswith('llndk='):
+ return api >= int(get_tag_value(tag))
+ # If not, we keep old behavior: NDK symbols in <= 34 are LLNDK symbols.
+ return symbol_in_api(tags, arch, 34)
def symbol_in_api(tags: Iterable[Tag], arch: Arch, api: int) -> bool:
"""Returns true if the symbol is present for the given API level."""
@@ -368,6 +400,7 @@
f'Unexpected contents at top level: {self.current_line}')
self.check_no_duplicate_symbols(versions)
+ self.check_llndk_introduced(versions)
return versions
def check_no_duplicate_symbols(self, versions: Iterable[Version]) -> None:
@@ -396,6 +429,31 @@
raise MultiplyDefinedSymbolError(
sorted(list(multiply_defined_symbols)))
+ def check_llndk_introduced(self, versions: Iterable[Version]) -> None:
+ """Raises errors when llndk= is missing for new llndk symbols."""
+ if not self.filter.llndk:
+ return
+
+ def assert_llndk_with_version(tags: Tags, name: str) -> None:
+ has_llndk_introduced = False
+ for tag in tags:
+ if tag.startswith('llndk='):
+ has_llndk_introduced = True
+ break
+ if not has_llndk_introduced:
+ raise ParseError(f'{name}: missing version. `llndk=yyyymm`')
+
+ arch = self.filter.arch
+ for version in versions:
+ # llndk symbols >= introduced=35 should be tagged
+ # explicitly with llndk=yyyymm.
+ for symbol in version.symbols:
+ if not symbol.tags.has_llndk_tags:
+ continue
+ if symbol_in_api(symbol.tags, arch, 34):
+ continue
+ assert_llndk_with_version(symbol.tags, symbol.name)
+
def parse_version(self) -> Version:
"""Parses a single version section and returns a Version object."""
assert self.current_line is not None
@@ -429,7 +487,9 @@
else:
raise ParseError('Unknown visiblity label: ' + visibility)
elif global_scope and not cpp_symbols:
- symbols.append(self.parse_symbol())
+ symbol = self.parse_symbol()
+ symbol.tags.copy_introduced_from(tags)
+ symbols.append(symbol)
else:
# We're in a hidden scope or in 'extern "C++"' block. Ignore
# everything.
diff --git a/cc/symbolfile/test_symbolfile.py b/cc/symbolfile/test_symbolfile.py
index 83becc2..8b412b9 100644
--- a/cc/symbolfile/test_symbolfile.py
+++ b/cc/symbolfile/test_symbolfile.py
@@ -344,6 +344,45 @@
self.assertInclude(f_llndk, s_none)
self.assertInclude(f_llndk, s_llndk)
+ def test_omit_llndk_versioned(self) -> None:
+ f_ndk = self.filter
+ f_ndk.api = 35
+
+ f_llndk = copy(f_ndk)
+ f_llndk.llndk = True
+ f_llndk.api = 202404
+
+ s = Symbol('foo', Tags())
+ s_llndk = Symbol('foo', Tags.from_strs(['llndk']))
+ s_llndk_202404 = Symbol('foo', Tags.from_strs(['llndk=202404']))
+ s_34 = Symbol('foo', Tags.from_strs(['introduced=34']))
+ s_34_llndk = Symbol('foo', Tags.from_strs(['introduced=34', 'llndk']))
+ s_35 = Symbol('foo', Tags.from_strs(['introduced=35']))
+ s_35_llndk_202404 = Symbol('foo', Tags.from_strs(['introduced=35', 'llndk=202404']))
+ s_35_llndk_202504 = Symbol('foo', Tags.from_strs(['introduced=35', 'llndk=202504']))
+
+ # When targeting NDK, omit LLNDK tags
+ self.assertInclude(f_ndk, s)
+ self.assertOmit(f_ndk, s_llndk)
+ self.assertOmit(f_ndk, s_llndk_202404)
+ self.assertInclude(f_ndk, s_34)
+ self.assertOmit(f_ndk, s_34_llndk)
+ self.assertInclude(f_ndk, s_35)
+ self.assertOmit(f_ndk, s_35_llndk_202404)
+ self.assertOmit(f_ndk, s_35_llndk_202504)
+
+ # When targeting LLNDK, old symbols without any mode tags are included as LLNDK
+ self.assertInclude(f_llndk, s)
+ # When targeting LLNDK, old symbols with #llndk are included as LLNDK
+ self.assertInclude(f_llndk, s_llndk)
+ self.assertInclude(f_llndk, s_llndk_202404)
+ self.assertInclude(f_llndk, s_34)
+ self.assertInclude(f_llndk, s_34_llndk)
+ # When targeting LLNDK, new symbols(>=35) should be tagged with llndk-introduced=.
+ self.assertOmit(f_llndk, s_35)
+ self.assertInclude(f_llndk, s_35_llndk_202404)
+ self.assertOmit(f_llndk, s_35_llndk_202504)
+
def test_omit_apex(self) -> None:
f_none = self.filter
f_apex = copy(f_none)
@@ -451,9 +490,12 @@
self.assertIsNone(version.base)
self.assertEqual(Tags.from_strs(['weak', 'introduced=35']), version.tags)
+ # Inherit introduced= tags from version block so that
+ # should_omit_tags() can differently based on introduced API level when treating
+ # LLNDK-available symbols.
expected_symbols = [
- Symbol('baz', Tags()),
- Symbol('qux', Tags.from_strs(['apex', 'llndk'])),
+ Symbol('baz', Tags.from_strs(['introduced=35'])),
+ Symbol('qux', Tags.from_strs(['apex', 'llndk', 'introduced=35'])),
]
self.assertEqual(expected_symbols, version.symbols)
@@ -601,6 +643,19 @@
]
self.assertEqual(expected_symbols, version.symbols)
+ def test_parse_llndk_version_is_missing(self) -> None:
+ input_file = io.StringIO(textwrap.dedent("""\
+ VERSION_1 { # introduced=35
+ foo;
+ bar; # llndk
+ };
+ """))
+ f = copy(self.filter)
+ f.llndk = True
+ parser = symbolfile.SymbolFileParser(input_file, {}, f)
+ with self.assertRaises(symbolfile.ParseError):
+ parser.parse()
+
def main() -> None:
suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/cc/testing.go b/cc/testing.go
index 9c2900c..3bdc383 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -305,10 +305,7 @@
recovery_available: true,
host_supported: true,
min_sdk_version: "29",
- vndk: {
- enabled: true,
- support_system_process: true,
- },
+ double_loadable: true,
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
@@ -624,19 +621,6 @@
android.FixtureOverrideTextFile(linuxBionicDefaultsPath, withLinuxBionic()),
)
-// This adds some additional modules and singletons which might negatively impact the performance
-// of tests so they are not included in the PrepareForIntegrationTestWithCc.
-var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
- PrepareForIntegrationTestWithCc,
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- snapshot.VendorSnapshotImageSingleton.Init(ctx)
- snapshot.RecoverySnapshotImageSingleton.Init(ctx)
- RegisterVendorSnapshotModules(ctx)
- RegisterRecoverySnapshotModules(ctx)
- ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
- }),
-)
-
// PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc. It also disables the test
// on mac, which doesn't support musl libc, and adds musl modules.
var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
@@ -722,7 +706,6 @@
snapshot.RecoverySnapshotImageSingleton.Init(ctx)
RegisterVendorSnapshotModules(ctx)
RegisterRecoverySnapshotModules(ctx)
- ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
RegisterVndkLibraryTxtTypes(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
diff --git a/cc/vendor_public_library_test.go b/cc/vendor_public_library_test.go
index 769be09..7385f2b 100644
--- a/cc/vendor_public_library_test.go
+++ b/cc/vendor_public_library_test.go
@@ -65,8 +65,8 @@
`)
coreVariant := "android_arm64_armv8-a_shared"
- vendorVariant := "android_vendor.29_arm64_armv8-a_shared"
- productVariant := "android_product.29_arm64_armv8-a_shared"
+ vendorVariant := "android_vendor_arm64_armv8-a_shared"
+ productVariant := "android_product_arm64_armv8-a_shared"
// test if header search paths are correctly added
// _static variant is used since _shared reuses *.o from the static variant
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
deleted file mode 100644
index 0a55431..0000000
--- a/cc/vendor_snapshot_test.go
+++ /dev/null
@@ -1,1751 +0,0 @@
-// Copyright 2021 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 cc
-
-import (
- "android/soong/android"
- "fmt"
- "path/filepath"
- "reflect"
- "strings"
- "testing"
-)
-
-func checkJsonContents(t *testing.T, ctx *android.TestContext, snapshotSingleton android.TestingSingleton, jsonPath string, key string, value string) {
- jsonOut := snapshotSingleton.MaybeOutput(jsonPath)
- if jsonOut.Rule == nil {
- t.Errorf("%q expected but not found", jsonPath)
- return
- }
- content := android.ContentFromFileRuleForTests(t, ctx, jsonOut)
- if !strings.Contains(content, fmt.Sprintf("%q:%q", key, value)) {
- t.Errorf("%q must include %q:%q but it only has %v", jsonPath, key, value, jsonOut.Args["content"])
- }
-}
-
-func TestVendorSnapshotCapture(t *testing.T) {
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor_override",
- vendor: true,
- nocrt: true,
- overrides: ["libvendor"],
- }
-
- cc_library {
- name: "libvendor_available",
- vendor_available: true,
- nocrt: true,
- min_sdk_version: "29",
- }
-
- cc_library_headers {
- name: "libvendor_headers",
- vendor_available: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "vendor_bin",
- vendor: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "vendor_available_bin",
- vendor_available: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "vendor_bin_override",
- vendor: true,
- nocrt: true,
- overrides: ["vendor_bin"],
- }
-
- cc_prebuilt_library_static {
- name: "libb",
- vendor_available: true,
- srcs: ["libb.a"],
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- }
-
- cc_object {
- name: "obj",
- vendor_available: true,
- }
-
- cc_library {
- name: "libllndk",
- llndk: {
- symbol_file: "libllndk.map.txt",
- },
- }
-`
-
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- ctx := testCcWithConfig(t, config)
-
- // Check Vendor snapshot output.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var jsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- // For shared libraries, only non-VNDK vendor_available modules are captured
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(sharedDir, "libvendor.so.json"),
- filepath.Join(sharedDir, "libvendor_available.so.json"))
-
- // LLNDK modules are not captured
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
-
- // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
- // Also cfi variants are captured, except for prebuilts like toolchain_library
- staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
- staticCfiVariant := fmt.Sprintf("android_vendor.29_%s_%s_static_cfi", archType, archVariant)
- staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(staticDir, "libb.a.json"),
- filepath.Join(staticDir, "libvndk.a.json"),
- filepath.Join(staticDir, "libvndk.cfi.a.json"),
- filepath.Join(staticDir, "libvendor.a.json"),
- filepath.Join(staticDir, "libvendor.cfi.a.json"),
- filepath.Join(staticDir, "libvendor_available.a.json"),
- filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
-
- checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libb.a.json"), "MinSdkVersion", "apex_inherit")
- checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libvendor_available.a.json"), "MinSdkVersion", "29")
-
- // For binary executables, all vendor:true and vendor_available modules are captured.
- if archType == "arm64" {
- binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
- binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(binaryDir, "vendor_bin.json"),
- filepath.Join(binaryDir, "vendor_available_bin.json"))
-
- checkOverrides(t, ctx, snapshotSingleton, filepath.Join(binaryDir, "vendor_bin_override.json"), []string{"vendor_bin"})
- }
-
- // For header libraries, all vendor:true and vendor_available modules are captured.
- headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
- jsonFiles = append(jsonFiles, filepath.Join(headerDir, "libvendor_headers.json"))
-
- // For object modules, all vendor:true and vendor_available modules are captured.
- objectVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
- objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
- CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
- jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
-
- checkOverrides(t, ctx, snapshotSingleton, filepath.Join(sharedDir, "libvendor_override.so.json"), []string{"libvendor"})
- }
-
- for _, jsonFile := range jsonFiles {
- // verify all json files exist
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("%q expected but not found", jsonFile)
- }
- }
-
- // fake snapshot should have all outputs in the normal snapshot.
- fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
- for _, output := range snapshotSingleton.AllOutputs() {
- fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
- if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
- t.Errorf("%q expected but not found", fakeOutput)
- }
- }
-}
-
-func TestVendorSnapshotDirected(t *testing.T) {
- bp := `
- cc_library_shared {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
-
- cc_library_shared {
- name: "libvendor_available",
- vendor_available: true,
- nocrt: true,
- }
-
- genrule {
- name: "libfoo_gen",
- cmd: "",
- out: ["libfoo.so"],
- }
-
- cc_prebuilt_library_shared {
- name: "libfoo",
- vendor: true,
- prefer: true,
- srcs: [":libfoo_gen"],
- }
-
- cc_library_shared {
- name: "libfoo",
- vendor: true,
- nocrt: true,
- }
-`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.DirectedVendorSnapshot = true
- config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
- config.TestProductVariables.VendorSnapshotModules["libvendor"] = true
- config.TestProductVariables.VendorSnapshotModules["libfoo"] = true
- ctx := testCcWithConfig(t, config)
-
- // Check Vendor snapshot output.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var includeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
- // Included modules
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
- // Check that snapshot captures "prefer: true" prebuilt
- CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
-
- // Excluded modules. Modules not included in the directed vendor snapshot
- // are still include as fake modules.
- CheckSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-}
-
-func TestVendorSnapshotUse(t *testing.T) {
- frameworkBp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "libvendor_available",
- vendor_available: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "lib32",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- compile_multilib: "32",
- }
-
- cc_library {
- name: "lib64",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- no_crt_pad_segment: true,
- stl: "none",
- system_shared_libs: [],
- compile_multilib: "64",
- }
-
- cc_library {
- name: "libllndk",
- llndk: {
- symbol_file: "libllndk.map.txt",
- },
- }
-
- cc_binary {
- name: "bin",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_binary {
- name: "bin32",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- compile_multilib: "32",
- }
-`
-
- vndkBp := `
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "31",
- target_arch: "arm64",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm64: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- arm: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- },
- }
-
- // old snapshot module which has to be ignored
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "26",
- target_arch: "arm64",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm64: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- arm: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- },
- }
-
- // different arch snapshot which has to be ignored
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "31",
- target_arch: "arm",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- },
- }
-
- vndk_prebuilt_shared {
- name: "libllndk",
- version: "31",
- target_arch: "arm64",
- vendor_available: true,
- product_available: true,
- arch: {
- arm64: {
- srcs: ["libllndk.so"],
- },
- arm: {
- srcs: ["libllndk.so"],
- },
- },
- }
-`
-
- vendorProprietaryBp := `
- cc_library {
- name: "libvendor_without_snapshot",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- no_crt_pad_segment: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library_shared {
- name: "libclient",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- no_crt_pad_segment: true,
- stl: "none",
- system_shared_libs: [],
- shared_libs: ["libvndk", "libvendor_available", "libllndk"],
- static_libs: ["libvendor", "libvendor_without_snapshot"],
- arch: {
- arm64: {
- shared_libs: ["lib64"],
- },
- arm: {
- shared_libs: ["lib32"],
- },
- },
- srcs: ["client.cpp"],
- }
-
- cc_library_shared {
- name: "libclient_cfi",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- no_crt_pad_segment: true,
- stl: "none",
- system_shared_libs: [],
- static_libs: ["libvendor"],
- sanitize: {
- cfi: true,
- },
- srcs: ["client.cpp"],
- }
-
- cc_library_shared {
- name: "libvndkext",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- no_crt_pad_segment: true,
- stl: "none",
- system_shared_libs: [],
- vndk: {
- extends: "libvndk",
- enabled: true,
- }
- }
-
- cc_binary {
- name: "bin_without_snapshot",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "libc++_static",
- system_shared_libs: [],
- static_libs: ["libvndk"],
- srcs: ["bin.cpp"],
- }
-
- vendor_snapshot {
- name: "vendor_snapshot",
- version: "31",
- arch: {
- arm64: {
- vndk_libs: [
- "libvndk",
- "libllndk",
- ],
- static_libs: [
- "libc++_static",
- "libc++demangle",
- "libunwind",
- "libvendor",
- "libvendor_available",
- "libvndk",
- "lib64",
- ],
- shared_libs: [
- "libvendor",
- "libvendor_override",
- "libvendor_available",
- "lib64",
- ],
- binaries: [
- "bin",
- "bin_override",
- ],
- },
- arm: {
- vndk_libs: [
- "libvndk",
- "libllndk",
- ],
- static_libs: [
- "libvendor",
- "libvendor_available",
- "libvndk",
- "lib32",
- ],
- shared_libs: [
- "libvendor",
- "libvendor_override",
- "libvendor_available",
- "lib32",
- ],
- binaries: [
- "bin32",
- ],
- },
- }
- }
-
- vendor_snapshot_static {
- name: "libvndk",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- arch: {
- arm64: {
- src: "libvndk.a",
- },
- arm: {
- src: "libvndk.a",
- },
- },
- shared_libs: ["libvndk"],
- export_shared_lib_headers: ["libvndk"],
- }
-
- vendor_snapshot_shared {
- name: "libvendor",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- no_crt_pad_segment: true,
- shared_libs: [
- "libvendor_without_snapshot",
- "libvendor_available",
- "libvndk",
- ],
- arch: {
- arm64: {
- src: "libvendor.so",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- src: "libvendor.so",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "libvendor_override",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- no_crt_pad_segment: true,
- overrides: ["libvendor"],
- shared_libs: [
- "libvendor_without_snapshot",
- "libvendor_available",
- "libvndk",
- ],
- arch: {
- arm64: {
- src: "override/libvendor.so",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- src: "override/libvendor.so",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_static {
- name: "lib32",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "32",
- vendor: true,
- arch: {
- arm: {
- src: "lib32.a",
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "lib32",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "32",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm: {
- src: "lib32.so",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "lib64",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- arch: {
- arm64: {
- src: "lib64.a",
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "lib64",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm64: {
- src: "lib64.so",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libvendor",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- arch: {
- arm64: {
- cfi: {
- src: "libvendor.cfi.a",
- export_include_dirs: ["include/libvendor_cfi"],
- },
- src: "libvendor.a",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- cfi: {
- src: "libvendor.cfi.a",
- export_include_dirs: ["include/libvendor_cfi"],
- },
- src: "libvendor.a",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "libvendor_available",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm64: {
- src: "libvendor_available.so",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- src: "libvendor_available.so",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libvendor_available",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- arch: {
- arm64: {
- src: "libvendor_available.a",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- src: "libvendor_available.so",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libc++_static",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- arch: {
- arm64: {
- src: "libc++_static.a",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libc++demangle",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- arch: {
- arm64: {
- src: "libc++demangle.a",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libunwind",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- arch: {
- arm64: {
- src: "libunwind.a",
- },
- },
- }
-
- vendor_snapshot_binary {
- name: "bin",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- arch: {
- arm64: {
- src: "bin",
- },
- },
- symlinks: ["binfoo", "binbar"],
- }
-
- vendor_snapshot_binary {
- name: "bin_override",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- overrides: ["bin"],
- arch: {
- arm64: {
- src: "override/bin",
- },
- },
- symlinks: ["binfoo", "binbar"],
- }
-
- vendor_snapshot_binary {
- name: "bin32",
- version: "31",
- target_arch: "arm64",
- compile_multilib: "32",
- vendor: true,
- arch: {
- arm: {
- src: "bin32",
- },
- },
- }
-
- // old snapshot module which has to be ignored
- vendor_snapshot_binary {
- name: "bin",
- version: "26",
- target_arch: "arm64",
- compile_multilib: "first",
- vendor: true,
- arch: {
- arm64: {
- src: "bin",
- },
- },
- }
-
- // different arch snapshot which has to be ignored
- vendor_snapshot_binary {
- name: "bin",
- version: "31",
- target_arch: "arm",
- compile_multilib: "first",
- vendor: true,
- arch: {
- arm64: {
- src: "bin",
- },
- },
- }
-`
- depsBp := GatherRequiredDepsForTest(android.Android)
-
- mockFS := map[string][]byte{
- "deps/Android.bp": []byte(depsBp),
- "framework/Android.bp": []byte(frameworkBp),
- "framework/symbol.txt": nil,
- "vendor/Android.bp": []byte(vendorProprietaryBp),
- "vendor/bin": nil,
- "vendor/override/bin": nil,
- "vendor/bin32": nil,
- "vendor/bin.cpp": nil,
- "vendor/client.cpp": nil,
- "vendor/include/libvndk/a.h": nil,
- "vendor/include/libvendor/b.h": nil,
- "vendor/include/libvendor_cfi/c.h": nil,
- "vendor/libc++_static.a": nil,
- "vendor/libc++demangle.a": nil,
- "vendor/libunwind.a": nil,
- "vendor/libvndk.a": nil,
- "vendor/libvendor.a": nil,
- "vendor/libvendor.cfi.a": nil,
- "vendor/libvendor.so": nil,
- "vendor/override/libvendor.so": nil,
- "vendor/lib32.a": nil,
- "vendor/lib32.so": nil,
- "vendor/lib64.a": nil,
- "vendor/lib64.so": nil,
- "vndk/Android.bp": []byte(vndkBp),
- "vndk/include/libvndk/a.h": nil,
- "vndk/libvndk.so": nil,
- "vndk/libllndk.so": nil,
- }
-
- config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("31")
- config.TestProductVariables.Platform_vndk_version = StringPtr("32")
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- sharedVariant := "android_vendor.31_arm64_armv8-a_shared"
- staticVariant := "android_vendor.31_arm64_armv8-a_static"
- binaryVariant := "android_vendor.31_arm64_armv8-a"
-
- sharedCfiVariant := "android_vendor.31_arm64_armv8-a_shared_cfi"
- staticCfiVariant := "android_vendor.31_arm64_armv8-a_static_cfi"
-
- shared32Variant := "android_vendor.31_arm_armv7-a-neon_shared"
- binary32Variant := "android_vendor.31_arm_armv7-a-neon"
-
- // libclient uses libvndk.vndk.31.arm64, libvendor.vendor_static.31.arm64, libvendor_without_snapshot
- libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
- for _, includeFlags := range []string{
- "-Ivndk/include/libvndk", // libvndk
- "-Ivendor/include/libvendor", // libvendor
- } {
- if !strings.Contains(libclientCcFlags, includeFlags) {
- t.Errorf("flags for libclient must contain %#v, but was %#v.",
- includeFlags, libclientCcFlags)
- }
- }
-
- libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
- for _, input := range [][]string{
- []string{sharedVariant, "libvndk.vndk.31.arm64"},
- []string{sharedVariant, "libllndk.vndk.31.arm64"},
- []string{staticVariant, "libvendor.vendor_static.31.arm64"},
- []string{staticVariant, "libvendor_without_snapshot"},
- } {
- outputPaths := GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
- if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
- t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
- }
-
- }
-
- libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
- if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib64"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
- }
-
- libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
- if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
- }
-
- libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
- if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "libllndk.vendor", "lib32"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
- }
-
- // libclient_cfi uses libvendor.vendor_static.31.arm64's cfi variant
- libclientCfiCcFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("cc").Args["cFlags"]
- if !strings.Contains(libclientCfiCcFlags, "-Ivendor/include/libvendor_cfi") {
- t.Errorf("flags for libclient_cfi must contain %#v, but was %#v.",
- "-Ivendor/include/libvendor_cfi", libclientCfiCcFlags)
- }
-
- libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"]
- libvendorCfiOutputPaths := GetOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
- if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) {
- t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags)
- }
-
- // bin_without_snapshot uses libvndk.vendor_static.31.arm64 (which reexports vndk's exported headers)
- binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
- if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivndk/include/libvndk") {
- t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
- "-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
- }
-
- binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
- libVndkStaticOutputPaths := GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
- if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
- t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
- libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
- }
-
- // libvendor.so is installed by libvendor.vendor_shared.31.arm64
- ctx.ModuleForTests("libvendor.vendor_shared.31.arm64", sharedVariant).Output("libvendor.so")
-
- // lib64.so is installed by lib64.vendor_shared.31.arm64
- ctx.ModuleForTests("lib64.vendor_shared.31.arm64", sharedVariant).Output("lib64.so")
-
- // lib32.so is installed by lib32.vendor_shared.31.arm64
- ctx.ModuleForTests("lib32.vendor_shared.31.arm64", shared32Variant).Output("lib32.so")
-
- // libvendor_available.so is installed by libvendor_available.vendor_shared.31.arm64
- ctx.ModuleForTests("libvendor_available.vendor_shared.31.arm64", sharedVariant).Output("libvendor_available.so")
-
- // libvendor_without_snapshot.so is installed by libvendor_without_snapshot
- ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so")
-
- // bin is installed by bin.vendor_binary.31.arm64
- bin64Module := ctx.ModuleForTests("bin.vendor_binary.31.arm64", binaryVariant)
- bin64Module.Output("bin")
-
- // also test symlinks
- bin64MkEntries := android.AndroidMkEntriesForTest(t, ctx, bin64Module.Module())
- bin64KatiSymlinks := bin64MkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"]
-
- // Either AndroidMk entries contain symlinks, or symlinks should be installed by Soong
- for _, symlink := range []string{"binfoo", "binbar"} {
- if inList(symlink, bin64KatiSymlinks) {
- continue
- }
-
- bin64Module.Output(symlink)
- }
-
- // bin32 is installed by bin32.vendor_binary.31.arm64
- ctx.ModuleForTests("bin32.vendor_binary.31.arm64", binary32Variant).Output("bin32")
-
- // bin_without_snapshot is installed by bin_without_snapshot
- ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
-
- // libvendor, libvendor_available and bin don't have vendor.31 variant
- libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
- if inList(sharedVariant, libvendorVariants) {
- t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
- }
-
- libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
- if inList(sharedVariant, libvendorAvailableVariants) {
- t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
- }
-
- binVariants := ctx.ModuleVariantsForTests("bin")
- if inList(binaryVariant, binVariants) {
- t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
- }
-
- // test overrides property
- binOverrideModule := ctx.ModuleForTests("bin_override.vendor_binary.31.arm64", binaryVariant)
- binOverrideModule.Output("bin")
- binOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, binOverrideModule.Module())
- binOverrideEntry := binOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
- if !inList("bin", binOverrideEntry) {
- t.Errorf("bin_override must override bin but was %q\n", binOverrideEntry)
- }
-
- libvendorOverrideModule := ctx.ModuleForTests("libvendor_override.vendor_shared.31.arm64", sharedVariant)
- libvendorOverrideModule.Output("libvendor.so")
- libvendorOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, libvendorOverrideModule.Module())
- libvendorOverrideEntry := libvendorOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
- if !inList("libvendor", libvendorOverrideEntry) {
- t.Errorf("libvendor_override must override libvendor but was %q\n", libvendorOverrideEntry)
- }
-}
-
-func TestVendorSnapshotSanitizer(t *testing.T) {
- bp := `
- vendor_snapshot {
- name: "vendor_snapshot",
- version: "28",
- arch: {
- arm64: {
- static_libs: [
- "libsnapshot",
- "note_memtag_heap_sync",
- ],
- objects: [
- "snapshot_object",
- ],
- vndk_libs: [
- "libclang_rt.hwasan",
- ],
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libsnapshot",
- vendor: true,
- target_arch: "arm64",
- version: "28",
- arch: {
- arm64: {
- src: "libsnapshot.a",
- cfi: {
- src: "libsnapshot.cfi.a",
- },
- hwasan: {
- src: "libsnapshot.hwasan.a",
- },
- },
- },
- }
-
- vendor_snapshot_static {
- name: "note_memtag_heap_sync",
- vendor: true,
- target_arch: "arm64",
- version: "28",
- arch: {
- arm64: {
- src: "note_memtag_heap_sync.a",
- },
- },
- }
-
- vndk_prebuilt_shared {
- name: "libclang_rt.hwasan",
- version: "28",
- target_arch: "arm64",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm64: {
- srcs: ["libclang_rt.hwasan.so"],
- },
- },
- }
-
- vendor_snapshot_object {
- name: "snapshot_object",
- vendor: true,
- target_arch: "arm64",
- version: "28",
- arch: {
- arm64: {
- src: "snapshot_object.o",
- },
- },
- stl: "none",
- }
-
- cc_test {
- name: "vstest",
- gtest: false,
- vendor: true,
- compile_multilib: "64",
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- static_libs: ["libsnapshot"],
- system_shared_libs: [],
- }
-`
-
- mockFS := map[string][]byte{
- "vendor/Android.bp": []byte(bp),
- "vendor/libc++demangle.a": nil,
- "vendor/libclang_rt.hwasan.so": nil,
- "vendor/libsnapshot.a": nil,
- "vendor/libsnapshot.cfi.a": nil,
- "vendor/libsnapshot.hwasan.a": nil,
- "vendor/note_memtag_heap_sync.a": nil,
- "vendor/snapshot_object.o": nil,
- }
-
- config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("28")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.SanitizeDevice = []string{"hwaddress"}
- ctx := testCcWithConfig(t, config)
-
- // Check non-cfi, cfi and hwasan variant.
- staticVariant := "android_vendor.28_arm64_armv8-a_static"
- staticCfiVariant := "android_vendor.28_arm64_armv8-a_static_cfi"
- staticHwasanVariant := "android_vendor.28_arm64_armv8-a_static_hwasan"
- staticHwasanCfiVariant := "android_vendor.28_arm64_armv8-a_static_hwasan_cfi"
-
- staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticVariant).Module().(*Module)
- assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
-
- staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticCfiVariant).Module().(*Module)
- assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
-
- staticHwasanModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanVariant).Module().(*Module)
- assertString(t, staticHwasanModule.outputFile.Path().Base(), "libsnapshot.hwasan.a")
-
- staticHwasanCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanCfiVariant).Module().(*Module)
- if !staticHwasanCfiModule.HiddenFromMake() || !staticHwasanCfiModule.PreventInstall() {
- t.Errorf("Hwasan and Cfi cannot enabled at the same time.")
- }
-
- snapshotObjModule := ctx.ModuleForTests("snapshot_object.vendor_object.28.arm64", "android_vendor.28_arm64_armv8-a").Module()
- snapshotObjMkEntries := android.AndroidMkEntriesForTest(t, ctx, snapshotObjModule)
- // snapshot object must not add ".hwasan" suffix
- assertString(t, snapshotObjMkEntries[0].EntryMap["LOCAL_MODULE"][0], "snapshot_object")
-}
-
-func TestVendorSnapshotExclude(t *testing.T) {
-
- // This test verifies that the exclude_from_vendor_snapshot property
- // makes its way from the Android.bp source file into the module data
- // structure. It also verifies that modules are correctly included or
- // excluded in the vendor snapshot based on their path (framework or
- // vendor) and the exclude_from_vendor_snapshot property.
-
- frameworkBp := `
- cc_library_shared {
- name: "libinclude",
- srcs: ["src/include.cpp"],
- vendor_available: true,
- }
- cc_library_shared {
- name: "libexclude",
- srcs: ["src/exclude.cpp"],
- vendor: true,
- exclude_from_vendor_snapshot: true,
- }
- cc_library_shared {
- name: "libavailable_exclude",
- srcs: ["src/exclude.cpp"],
- vendor_available: true,
- exclude_from_vendor_snapshot: true,
- }
- `
-
- vendorProprietaryBp := `
- cc_library_shared {
- name: "libvendor",
- srcs: ["vendor.cpp"],
- vendor: true,
- }
- `
-
- depsBp := GatherRequiredDepsForTest(android.Android)
-
- mockFS := map[string][]byte{
- "deps/Android.bp": []byte(depsBp),
- "framework/Android.bp": []byte(frameworkBp),
- "framework/include.cpp": nil,
- "framework/exclude.cpp": nil,
- "device/Android.bp": []byte(vendorProprietaryBp),
- "device/vendor.cpp": nil,
- }
-
- config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- // Test an include and exclude framework module.
- AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant)
- AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant)
- AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant)
-
- // A vendor module is excluded, but by its path, not the
- // exclude_from_vendor_snapshot property.
- AssertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false, vendorVariant)
-
- // Verify the content of the vendor snapshot.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var includeJsonFiles []string
- var excludeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
- // Included modules
- CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
-
- // Excluded modules
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-
- // Verify that each json file for an excluded module has no rule.
- for _, jsonFile := range excludeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
- t.Errorf("exclude json file %q found", jsonFile)
- }
- }
-}
-
-func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
-
- // This test verifies that using the exclude_from_vendor_snapshot
- // property on a module in a vendor proprietary path generates an
- // error. These modules are already excluded, so we prohibit using the
- // property in this way, which could add to confusion.
-
- vendorProprietaryBp := `
- cc_library_shared {
- name: "libvendor",
- srcs: ["vendor.cpp"],
- vendor: true,
- exclude_from_vendor_snapshot: true,
- }
- `
-
- depsBp := GatherRequiredDepsForTest(android.Android)
-
- mockFS := map[string][]byte{
- "deps/Android.bp": []byte(depsBp),
- "device/Android.bp": []byte(vendorProprietaryBp),
- "device/vendor.cpp": nil,
- }
-
- config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
- android.FailIfErrored(t, errs)
-
- _, errs = ctx.PrepareBuildActions(config)
- android.CheckErrorsAgainstExpectations(t, errs, []string{
- `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
- `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
- `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
- `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
- `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
- `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
- })
-}
-
-func TestRecoverySnapshotCapture(t *testing.T) {
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- recovery_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "librecovery",
- recovery: true,
- nocrt: true,
- }
-
- cc_library {
- name: "librecovery_available",
- recovery_available: true,
- nocrt: true,
- }
-
- cc_library_headers {
- name: "librecovery_headers",
- recovery_available: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "recovery_bin",
- recovery: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "recovery_available_bin",
- recovery_available: true,
- nocrt: true,
- }
-
- cc_prebuilt_library_static {
- name: "libb",
- recovery_available: true,
- srcs: ["libb.a"],
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- }
-
- cc_object {
- name: "obj",
- recovery_available: true,
- }
-`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- ctx := testCcWithConfig(t, config)
-
- // Check Recovery snapshot output.
-
- snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
- var jsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- // For shared libraries, only recovery_available modules are captured.
- sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(sharedDir, "libvndk.so.json"),
- filepath.Join(sharedDir, "librecovery.so.json"),
- filepath.Join(sharedDir, "librecovery_available.so.json"))
-
- // For static libraries, all recovery:true and recovery_available modules are captured.
- staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
- staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(staticDir, "libb.a.json"),
- filepath.Join(staticDir, "librecovery.a.json"),
- filepath.Join(staticDir, "librecovery_available.a.json"))
-
- // For binary executables, all recovery:true and recovery_available modules are captured.
- if archType == "arm64" {
- binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
- binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(binaryDir, "recovery_bin.json"),
- filepath.Join(binaryDir, "recovery_available_bin.json"))
- }
-
- // For header libraries, all vendor:true and vendor_available modules are captured.
- headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
- jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json"))
-
- // For object modules, all vendor:true and vendor_available modules are captured.
- objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
- objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
- CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
- jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
- }
-
- for _, jsonFile := range jsonFiles {
- // verify all json files exist
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("%q expected but not found", jsonFile)
- }
- }
-}
-
-func TestRecoverySnapshotExclude(t *testing.T) {
- // This test verifies that the exclude_from_recovery_snapshot property
- // makes its way from the Android.bp source file into the module data
- // structure. It also verifies that modules are correctly included or
- // excluded in the recovery snapshot based on their path (framework or
- // vendor) and the exclude_from_recovery_snapshot property.
-
- frameworkBp := `
- cc_library_shared {
- name: "libinclude",
- srcs: ["src/include.cpp"],
- recovery_available: true,
- }
- cc_library_shared {
- name: "libexclude",
- srcs: ["src/exclude.cpp"],
- recovery: true,
- exclude_from_recovery_snapshot: true,
- }
- cc_library_shared {
- name: "libavailable_exclude",
- srcs: ["src/exclude.cpp"],
- recovery_available: true,
- exclude_from_recovery_snapshot: true,
- }
- `
-
- vendorProprietaryBp := `
- cc_library_shared {
- name: "librecovery",
- srcs: ["recovery.cpp"],
- recovery: true,
- }
- `
-
- depsBp := GatherRequiredDepsForTest(android.Android)
-
- mockFS := map[string][]byte{
- "deps/Android.bp": []byte(depsBp),
- "framework/Android.bp": []byte(frameworkBp),
- "framework/include.cpp": nil,
- "framework/exclude.cpp": nil,
- "device/Android.bp": []byte(vendorProprietaryBp),
- "device/recovery.cpp": nil,
- }
-
- config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
- config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- ctx := CreateTestContext(config)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- // Test an include and exclude framework module.
- AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, recoveryVariant)
- AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, recoveryVariant)
- AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, recoveryVariant)
-
- // A recovery module is excluded, but by its path, not the
- // exclude_from_recovery_snapshot property.
- AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, recoveryVariant)
-
- // Verify the content of the recovery snapshot.
-
- snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
- var includeJsonFiles []string
- var excludeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
- // Included modules
- CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
-
- // Excluded modules
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
- CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-
- // Verify that each json file for an excluded module has no rule.
- for _, jsonFile := range excludeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
- t.Errorf("exclude json file %q found", jsonFile)
- }
- }
-}
-
-func TestRecoverySnapshotDirected(t *testing.T) {
- bp := `
- cc_library_shared {
- name: "librecovery",
- recovery: true,
- nocrt: true,
- }
-
- cc_library_shared {
- name: "librecovery_available",
- recovery_available: true,
- nocrt: true,
- }
-
- genrule {
- name: "libfoo_gen",
- cmd: "",
- out: ["libfoo.so"],
- }
-
- cc_prebuilt_library_shared {
- name: "libfoo",
- recovery: true,
- prefer: true,
- srcs: [":libfoo_gen"],
- }
-
- cc_library_shared {
- name: "libfoo",
- recovery: true,
- nocrt: true,
- }
-`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- config.TestProductVariables.DirectedRecoverySnapshot = true
- config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
- config.TestProductVariables.RecoverySnapshotModules["librecovery"] = true
- config.TestProductVariables.RecoverySnapshotModules["libfoo"] = true
- ctx := testCcWithConfig(t, config)
-
- // Check recovery snapshot output.
-
- snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
- var includeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
- // Included modules
- CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
- // Check that snapshot captures "prefer: true" prebuilt
- CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
-
- // Excluded modules. Modules not included in the directed recovery snapshot
- // are still include as fake modules.
- CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-}
-
-func TestSnapshotInRelativeInstallPath(t *testing.T) {
- bp := `
- cc_library {
- name: "libvendor_available",
- vendor_available: true,
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor_available_var",
- vendor_available: true,
- stem: "libvendor_available",
- relative_install_path: "var",
- nocrt: true,
- }
-`
-
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
- ctx := testCcWithConfig(t, config)
-
- // Check Vendor snapshot output.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var jsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- // For shared libraries, only non-VNDK vendor_available modules are captured
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- sharedDirVar := filepath.Join(sharedDir, "var")
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
- CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available_var", "libvendor_available.so", sharedDirVar, sharedVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(sharedDir, "libvendor_available.so.json"),
- filepath.Join(sharedDirVar, "libvendor_available.so.json"))
- }
-
- for _, jsonFile := range jsonFiles {
- // verify all json files exist
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("%q expected but not found", jsonFile)
- }
- }
-
- // fake snapshot should have all outputs in the normal snapshot.
- fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
- for _, output := range snapshotSingleton.AllOutputs() {
- fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
- if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
- t.Errorf("%q expected but not found", fakeOutput)
- }
- }
-}
diff --git a/cc/vndk.go b/cc/vndk.go
index 2b2ea64..ad0dcf3 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -42,28 +42,6 @@
)
func VndkLibrariesTxtModules(vndkVersion string, ctx android.BaseModuleContext) []string {
- // Return the list of vndk txt files for the vndk apex of the vndkVersion.
- if vndkVersion == "current" {
- // We can assume all txt files are snapshotted if we find one of them.
- currentVndkSnapshotted := ctx.OtherModuleExists(insertVndkVersion(llndkLibrariesTxt, ctx.DeviceConfig().PlatformVndkVersion()))
- if currentVndkSnapshotted {
- // If the current VNDK is already snapshotted (which can happen with
- // the `next` config), use the prebuilt txt files in the snapshot.
- // This is because the txt files built from source are probably be
- // for the in-development version.
- vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
- } else {
- // Use the txt files generated from the source
- return []string{
- llndkLibrariesTxtForApex,
- vndkCoreLibrariesTxt,
- vndkSpLibrariesTxt,
- vndkPrivateLibrariesTxt,
- vndkProductLibrariesTxt,
- }
- }
- }
-
// Snapshot vndks have their own *.libraries.VER.txt files.
// Note that snapshots don't have "vndkcorevariant.libraries.VER.txt"
result := []string{
@@ -376,15 +354,6 @@
if !p.MatchesWithDevice(mctx.DeviceConfig()) {
return false
}
-
- platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
- if platformVndkVersion != "" {
- // ignore prebuilt vndk modules that are newer than or equal to the platform vndk version
- platformVndkApiLevel := android.ApiLevelOrPanic(mctx, platformVndkVersion)
- if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, p.Version())) {
- return false
- }
- }
}
if lib, ok := m.linker.(libraryInterface); ok {
@@ -392,8 +361,7 @@
if lib.buildStubs() {
return false
}
- useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
- mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
+ useCoreVariant := mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant
}
return false
@@ -548,22 +516,9 @@
return filename
}
-func (txt *vndkLibrariesTxt) DepsMutator(mctx android.BottomUpMutatorContext) {
- versionedName := insertVndkVersion(txt.Name(), mctx.DeviceConfig().PlatformVndkVersion())
- if mctx.OtherModuleExists(versionedName) {
- // If the prebuilt vndk libraries txt files exist, install them instead.
- txt.HideFromMake()
- mctx.AddDependency(txt, nil, versionedName)
- }
-}
-
func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
filename := proptools.StringDefault(txt.properties.Stem, txt.Name())
- if Bool(txt.properties.Insert_vndk_version) {
- filename = insertVndkVersion(filename, ctx.DeviceConfig().PlatformVndkVersion())
- }
-
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
installPath := android.PathForModuleInstall(ctx, "etc")
@@ -639,34 +594,6 @@
func isVndkSnapshotAware(config android.DeviceConfig, m LinkableInterface,
apexInfo android.ApexInfo) (vndkType string, isVndkSnapshotLib bool) {
-
- if m.Target().NativeBridge == android.NativeBridgeEnabled {
- return "", false
- }
- // !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants.
- // !installable: Snapshot only cares about "installable" modules.
- // !m.IsLlndk: llndk stubs are required for building against snapshots.
- // IsSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense.
- // !outputFile.Valid: Snapshot requires valid output file.
- if !m.InVendor() || (!installable(m, apexInfo) && !m.IsLlndk()) || m.IsSnapshotPrebuilt() || !m.OutputFile().Valid() {
- return "", false
- }
- if !m.IsSnapshotLibrary() || !m.Shared() {
- return "", false
- }
- if m.VndkVersion() == config.PlatformVndkVersion() {
- if m.IsVndk() && !m.IsVndkExt() {
- if m.IsVndkSp() {
- return "vndk-sp", true
- } else {
- return "vndk-core", true
- }
- } else if m.HasLlndkStubs() && m.StubsVersion() == "" {
- // Use default version for the snapshot.
- return "llndk-stub", true
- }
- }
-
return "", false
}
@@ -679,10 +606,6 @@
return
}
- if ctx.DeviceConfig().PlatformVndkVersion() == "" {
- return
- }
-
var snapshotOutputs android.Paths
/*
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 43030b8..f4ba163 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -131,16 +131,6 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
- if platformVndkVersion != "" {
- platformVndkApiLevel := android.ApiLevelOrPanic(ctx, platformVndkVersion)
- if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, p.Version())) {
- // This prebuilt VNDK module is not required for the current build
- ctx.Module().HideFromMake()
- return nil
- }
- }
-
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
ctx.Module().HideFromMake()
return nil
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 5c2316a..eafd67a 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -22,7 +22,6 @@
"android/soong/android"
"android/soong/bp2build"
- "android/soong/starlark_import"
)
// A helper function to generate a Read-only Bazel workspace in outDir
@@ -47,14 +46,6 @@
}
}
- // Add starlark deps here, so that they apply to both queryview and apibp2build which
- // both run this function.
- starlarkDeps, err2 := starlark_import.GetNinjaDeps()
- if err2 != nil {
- return err2
- }
- ctx.AddNinjaFileDeps(starlarkDeps...)
-
return nil
}
diff --git a/cmd/symbols_map/Android.bp b/cmd/symbols_map/Android.bp
index 0ba3b07..e3ae6ed 100644
--- a/cmd/symbols_map/Android.bp
+++ b/cmd/symbols_map/Android.bp
@@ -5,17 +5,16 @@
blueprint_go_binary {
name: "symbols_map",
srcs: [
- "elf.go",
"r8.go",
"symbols_map.go",
],
testSrcs: [
- "elf_test.go",
"r8_test.go",
],
deps: [
"blueprint-pathtools",
"golang-protobuf-encoding-prototext",
+ "soong-elf",
"soong-response",
"symbols_map_proto",
],
diff --git a/cmd/symbols_map/symbols_map.go b/cmd/symbols_map/symbols_map.go
index 938446d..c56cf93 100644
--- a/cmd/symbols_map/symbols_map.go
+++ b/cmd/symbols_map/symbols_map.go
@@ -22,6 +22,7 @@
"strings"
"android/soong/cmd/symbols_map/symbols_map_proto"
+ "android/soong/elf"
"android/soong/response"
"github.com/google/blueprint/pathtools"
@@ -116,7 +117,7 @@
if *elfFile != "" {
typ = symbols_map_proto.Mapping_ELF
location = *elfFile
- identifier, err = elfIdentifier(*elfFile, true)
+ identifier, err = elf.Identifier(*elfFile, true)
if err != nil {
fmt.Fprintf(os.Stderr, "error reading elf identifier: %s\n", err)
os.Exit(1)
diff --git a/starlark_import/Android.bp b/elf/Android.bp
similarity index 63%
rename from starlark_import/Android.bp
rename to elf/Android.bp
index b43217b..6450be1 100644
--- a/starlark_import/Android.bp
+++ b/elf/Android.bp
@@ -1,4 +1,4 @@
-// Copyright 2023 Google Inc. All rights reserved.
+// Copyright 2016 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.
@@ -17,20 +17,12 @@
}
bootstrap_go_package {
- name: "soong-starlark",
- pkgPath: "android/soong/starlark_import",
+ name: "soong-elf",
+ pkgPath: "android/soong/elf",
srcs: [
- "starlark_import.go",
- "unmarshal.go",
+ "elf.go",
],
testSrcs: [
- "starlark_import_test.go",
- "unmarshal_test.go",
- ],
- deps: [
- "go-starlark-starlark",
- "go-starlark-starlarkstruct",
- "go-starlark-starlarkjson",
- "go-starlark-starlarktest",
+ "elf_test.go",
],
}
diff --git a/cmd/symbols_map/elf.go b/elf/elf.go
similarity index 94%
rename from cmd/symbols_map/elf.go
rename to elf/elf.go
index 950e3b2..e84a8ae 100644
--- a/cmd/symbols_map/elf.go
+++ b/elf/elf.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package elf
import (
"debug/elf"
@@ -26,9 +26,9 @@
const gnuBuildID = "GNU\x00"
-// elfIdentifier extracts the elf build ID from an elf file. If allowMissing is true it returns
+// Identifier extracts the elf build ID from an elf file. If allowMissing is true it returns
// an empty identifier if the file exists but the build ID note does not.
-func elfIdentifier(filename string, allowMissing bool) (string, error) {
+func Identifier(filename string, allowMissing bool) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", fmt.Errorf("failed to open %s: %w", filename, err)
diff --git a/cmd/symbols_map/elf_test.go b/elf/elf_test.go
similarity index 99%
rename from cmd/symbols_map/elf_test.go
rename to elf/elf_test.go
index a94c87f..a220770 100644
--- a/cmd/symbols_map/elf_test.go
+++ b/elf/elf_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package elf
import (
"bytes"
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 7642378..21a18df 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -57,6 +57,7 @@
ctx.RegisterModuleType("prebuilt_root_host", PrebuiltRootHostFactory)
ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
+ ctx.RegisterModuleType("prebuilt_usr_hyphendata", PrebuiltUserHyphenDataFactory)
ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
@@ -71,10 +72,15 @@
type prebuiltEtcProperties struct {
// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
+ // Mutually exclusive with srcs.
Src *string `android:"path,arch_variant"`
+ // Source files of this prebuilt. Can reference a genrule type module with the ":module" syntax.
+ // Mutually exclusive with src. When used, filename_from_src is set to true.
+ Srcs []string `android:"path,arch_variant"`
+
// Optional name for the installed file. If unspecified, name of the module is used as the file
- // name.
+ // name. Only available when using a single source (src).
Filename *string `android:"arch_variant"`
// When set to true, and filename property is not set, the name for the installed file
@@ -127,9 +133,9 @@
// Returns the sub install directory relative to BaseDir().
SubDir() string
- // Returns an android.OutputPath to the intermeidate file, which is the renamed prebuilt source
+ // Returns an android.OutputPath to the intermediate file, which is the renamed prebuilt source
// file.
- OutputFile() android.OutputPath
+ OutputFiles(tag string) (android.Paths, error)
}
type PrebuiltEtc struct {
@@ -142,8 +148,8 @@
properties prebuiltEtcProperties
subdirProperties prebuiltSubdirProperties
- sourceFilePath android.Path
- outputFilePath android.OutputPath
+ sourceFilePaths android.Paths
+ outputFilePaths android.OutputPaths
// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
installDirBase string
installDirBase64 string
@@ -246,6 +252,9 @@
}
func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
+ if len(p.properties.Srcs) > 0 {
+ panic(fmt.Errorf("SourceFilePath not available on multi-source prebuilt %q", p.Name()))
+ }
return android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
}
@@ -260,7 +269,10 @@
}
func (p *PrebuiltEtc) OutputFile() android.OutputPath {
- return p.outputFilePath
+ if len(p.properties.Srcs) > 0 {
+ panic(fmt.Errorf("OutputFile not available on multi-source prebuilt %q", p.Name()))
+ }
+ return p.outputFilePaths[0]
}
var _ android.OutputFileProducer = (*PrebuiltEtc)(nil)
@@ -268,7 +280,7 @@
func (p *PrebuiltEtc) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
- return android.Paths{p.outputFilePath}, nil
+ return p.outputFilePaths.Paths(), nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -301,50 +313,7 @@
return false
}
-func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- filename := proptools.String(p.properties.Filename)
- filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
- if p.properties.Src != nil {
- p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
-
- // Determine the output file basename.
- // If Filename is set, use the name specified by the property.
- // If Filename_from_src is set, use the source file name.
- // Otherwise use the module name.
- if filename != "" {
- if filenameFromSrc {
- ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
- return
- }
- } else if filenameFromSrc {
- filename = p.sourceFilePath.Base()
- } else {
- filename = ctx.ModuleName()
- }
- } else if ctx.Config().AllowMissingDependencies() {
- // If no srcs was set and AllowMissingDependencies is enabled then
- // mark the module as missing dependencies and set a fake source path
- // and file name.
- ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
- p.sourceFilePath = android.PathForModuleSrc(ctx)
- if filename == "" {
- filename = ctx.ModuleName()
- }
- } else {
- ctx.PropertyErrorf("src", "missing prebuilt source file")
- return
- }
-
- if strings.Contains(filename, "/") {
- ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
- return
- }
-
- // Check that `sub_dir` and `relative_install_path` are not set at the same time.
- if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
- ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
- }
-
+func (p *PrebuiltEtc) installBaseDir(ctx android.ModuleContext) string {
// If soc install dir was specified and SOC specific is set, set the installDirPath to the
// specified socInstallDirBase.
installBaseDir := p.installDirBase
@@ -357,47 +326,138 @@
if p.installAvoidMultilibConflict && !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
installBaseDir = filepath.Join(installBaseDir, ctx.Arch().ArchType.String())
}
+ return installBaseDir
+}
- p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())
+func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var installs []installProperties
- // Call InstallFile even when uninstallable to make the module included in the package
- ip := installProperties{
- installable: p.Installable(),
- filename: filename,
- sourceFilePath: p.sourceFilePath,
- symlinks: p.properties.Symlinks,
+ if p.properties.Src != nil && len(p.properties.Srcs) > 0 {
+ ctx.PropertyErrorf("src", "src is set. Cannot set srcs")
}
- p.addInstallRules(ctx, ip)
+
+ // Check that `sub_dir` and `relative_install_path` are not set at the same time.
+ if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
+ ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
+ }
+ p.installDirPath = android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir())
+
+ filename := proptools.String(p.properties.Filename)
+ filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
+ if p.properties.Src != nil {
+ p.sourceFilePaths = android.PathsForModuleSrc(ctx, []string{proptools.String(p.properties.Src)})
+ // If the source was not found, set a fake source path to
+ // support AllowMissingDependencies executions.
+ if len(p.sourceFilePaths) == 0 {
+ p.sourceFilePaths = android.Paths{android.PathForModuleSrc(ctx)}
+ }
+
+ // Determine the output file basename.
+ // If Filename is set, use the name specified by the property.
+ // If Filename_from_src is set, use the source file name.
+ // Otherwise use the module name.
+ if filename != "" {
+ if filenameFromSrc {
+ ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
+ return
+ }
+ } else if filenameFromSrc {
+ filename = p.sourceFilePaths[0].Base()
+ } else {
+ filename = ctx.ModuleName()
+ }
+ if strings.Contains(filename, "/") {
+ ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
+ return
+ }
+ p.outputFilePaths = android.OutputPaths{android.PathForModuleOut(ctx, filename).OutputPath}
+
+ ip := installProperties{
+ filename: filename,
+ sourceFilePath: p.sourceFilePaths[0],
+ outputFilePath: p.outputFilePaths[0],
+ installDirPath: p.installDirPath,
+ symlinks: p.properties.Symlinks,
+ }
+ installs = append(installs, ip)
+ } else if len(p.properties.Srcs) > 0 {
+ if filename != "" {
+ ctx.PropertyErrorf("filename", "filename cannot be set when using srcs")
+ }
+ if len(p.properties.Symlinks) > 0 {
+ ctx.PropertyErrorf("symlinks", "symlinks cannot be set when using srcs")
+ }
+ if p.properties.Filename_from_src != nil {
+ ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs")
+ }
+ p.sourceFilePaths = android.PathsForModuleSrc(ctx, p.properties.Srcs)
+ for _, src := range p.sourceFilePaths {
+ filename := src.Base()
+ output := android.PathForModuleOut(ctx, filename).OutputPath
+ ip := installProperties{
+ filename: filename,
+ sourceFilePath: src,
+ outputFilePath: output,
+ installDirPath: p.installDirPath,
+ }
+ p.outputFilePaths = append(p.outputFilePaths, output)
+ installs = append(installs, ip)
+ }
+ } else if ctx.Config().AllowMissingDependencies() {
+ // If no srcs was set and AllowMissingDependencies is enabled then
+ // mark the module as missing dependencies and set a fake source path
+ // and file name.
+ ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
+ p.sourceFilePaths = android.Paths{android.PathForModuleSrc(ctx)}
+ if filename == "" {
+ filename = ctx.ModuleName()
+ }
+ p.outputFilePaths = android.OutputPaths{android.PathForModuleOut(ctx, filename).OutputPath}
+ ip := installProperties{
+ filename: filename,
+ sourceFilePath: p.sourceFilePaths[0],
+ outputFilePath: p.outputFilePaths[0],
+ installDirPath: p.installDirPath,
+ }
+ installs = append(installs, ip)
+ } else {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ return
+ }
+
+ // Call InstallFile even when uninstallable to make the module included in the package.
+ if !p.Installable() {
+ p.SkipInstall()
+ }
+ for _, ip := range installs {
+ ip.addInstallRules(ctx)
+ }
android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
type installProperties struct {
- installable bool
filename string
sourceFilePath android.Path
+ outputFilePath android.OutputPath
+ installDirPath android.InstallPath
symlinks []string
}
// utility function to add install rules to the build graph.
// Reduces code duplication between Soong and Mixed build analysis
-func (p *PrebuiltEtc) addInstallRules(ctx android.ModuleContext, ip installProperties) {
- if !ip.installable {
- p.SkipInstall()
- }
-
+func (ip *installProperties) addInstallRules(ctx android.ModuleContext) {
// Copy the file from src to a location in out/ with the correct `filename`
// This ensures that outputFilePath has the correct name for others to
// use, as the source file may have a different name.
- p.outputFilePath = android.PathForModuleOut(ctx, ip.filename).OutputPath
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
- Output: p.outputFilePath,
+ Output: ip.outputFilePath,
Input: ip.sourceFilePath,
})
- installPath := ctx.InstallFile(p.installDirPath, ip.filename, p.outputFilePath)
+ installPath := ctx.InstallFile(ip.installDirPath, ip.filename, ip.outputFilePath)
for _, sl := range ip.symlinks {
- ctx.InstallSymlink(p.installDirPath, sl, installPath)
+ ctx.InstallSymlink(ip.installDirPath, sl, installPath)
}
}
@@ -421,15 +481,15 @@
class = "ETC"
}
- return []android.AndroidMkEntries{android.AndroidMkEntries{
+ return []android.AndroidMkEntries{{
Class: class,
SubName: nameSuffix,
- OutputFile: android.OptionalPathForPath(p.outputFilePath),
+ OutputFile: android.OptionalPathForPath(p.outputFilePaths[0]),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_TAGS", "optional")
entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePaths[0].Base())
if len(p.properties.Symlinks) > 0 {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
}
@@ -552,6 +612,17 @@
return module
}
+// prebuilt_usr_hyphendata is for a prebuilt artifact that is installed in
+// <partition>/usr/hyphen-data/<sub_dir> directory.
+func PrebuiltUserHyphenDataFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/hyphen-data")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_font installs a font in <partition>/fonts directory.
func PrebuiltFontFactory() android.Module {
module := &PrebuiltEtc{}
@@ -700,7 +771,11 @@
targetArch := "arch-" + m.Target().Arch.ArchType.String()
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName())
- snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.OutputFile(), snapshotLibOut, s.Fake))
+ outputs, _ := m.OutputFiles("")
+ for _, output := range outputs {
+ cp := copyFile(ctx, output, snapshotLibOut, s.Fake)
+ snapshotOutputs = append(snapshotOutputs, cp)
+ }
prop := snapshot.SnapshotJsonFlags{}
propOut := snapshotLibOut + ".json"
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index df11709..dd9958c 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -15,7 +15,6 @@
package etc
import (
- "fmt"
"os"
"path/filepath"
"testing"
@@ -23,7 +22,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/snapshot"
)
func TestMain(m *testing.M) {
@@ -40,18 +38,6 @@
}),
)
-var prepareForPrebuiltEtcSnapshotTest = android.GroupFixturePreparers(
- prepareForPrebuiltEtcTest,
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- snapshot.VendorSnapshotImageSingleton.Init(ctx)
- snapshot.RecoverySnapshotImageSingleton.Init(ctx)
- }),
- android.FixtureModifyConfig(func(config android.Config) {
- config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
- config.TestProductVariables.RecoverySnapshotVersion = proptools.StringPtr("current")
- }),
-)
-
func TestPrebuiltEtcVariants(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
@@ -96,7 +82,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePath.Base())
+ android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePaths[0].Base())
}
func TestPrebuiltEtcGlob(t *testing.T) {
@@ -113,10 +99,24 @@
`)
p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
- android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePath.Base())
+ android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePaths[0].Base())
p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
- android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePath.Base())
+ android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePaths[0].Base())
+}
+
+func TestPrebuiltEtcMultipleSrcs(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo",
+ srcs: ["*.conf"],
+ }
+ `)
+
+ p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertStringEquals(t, "output file path", "bar.conf", p.outputFilePaths[0].Base())
+ android.AssertStringEquals(t, "output file path", "baz.conf", p.outputFilePaths[1].Base())
+ android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base())
}
func TestPrebuiltEtcAndroidMk(t *testing.T) {
@@ -273,6 +273,20 @@
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
}
+func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
+ prebuilt_usr_hyphendata {
+ name: "foo.conf",
+ src: "foo.conf",
+ sub_dir: "bar",
+ }
+ `)
+
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar"
+ android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath)
+}
+
func TestPrebuiltFontInstallDirPath(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_font {
@@ -387,110 +401,3 @@
})
}
}
-
-func checkIfSnapshotTaken(t *testing.T, result *android.TestResult, image string, moduleName string) {
- checkIfSnapshotExistAsExpected(t, result, image, moduleName, true)
-}
-
-func checkIfSnapshotNotTaken(t *testing.T, result *android.TestResult, image string, moduleName string) {
- checkIfSnapshotExistAsExpected(t, result, image, moduleName, false)
-}
-
-func checkIfSnapshotExistAsExpected(t *testing.T, result *android.TestResult, image string, moduleName string, expectToExist bool) {
- snapshotSingleton := result.SingletonForTests(image + "-snapshot")
- archType := "arm64"
- archVariant := "armv8-a"
- archDir := fmt.Sprintf("arch-%s", archType)
-
- snapshotDir := fmt.Sprintf("%s-snapshot", image)
- snapshotVariantPath := filepath.Join(snapshotDir, archType)
- outputDir := filepath.Join(snapshotVariantPath, archDir, "etc")
- imageVariant := ""
- if image == "recovery" {
- imageVariant = "recovery_"
- }
- mod := result.ModuleForTests(moduleName, fmt.Sprintf("android_%s%s_%s", imageVariant, archType, archVariant))
- outputFiles := mod.OutputFiles(t, "")
- if len(outputFiles) != 1 {
- t.Errorf("%q must have single output\n", moduleName)
- return
- }
- snapshotPath := filepath.Join(outputDir, moduleName)
-
- if expectToExist {
- out := snapshotSingleton.Output(snapshotPath)
-
- if out.Input.String() != outputFiles[0].String() {
- t.Errorf("The input of snapshot %q must be %q, but %q", "prebuilt_vendor", out.Input.String(), outputFiles[0])
- }
-
- snapshotJsonPath := snapshotPath + ".json"
-
- if snapshotSingleton.MaybeOutput(snapshotJsonPath).Rule == nil {
- t.Errorf("%q expected but not found", snapshotJsonPath)
- }
- } else {
- out := snapshotSingleton.MaybeOutput(snapshotPath)
- if out.Rule != nil {
- t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
- }
- }
-}
-
-func TestPrebuiltTakeSnapshot(t *testing.T) {
- var testBp = `
- prebuilt_etc {
- name: "prebuilt_vendor",
- src: "foo.conf",
- vendor: true,
- }
-
- prebuilt_etc {
- name: "prebuilt_vendor_indirect",
- src: "foo.conf",
- vendor: true,
- }
-
- prebuilt_etc {
- name: "prebuilt_recovery",
- src: "bar.conf",
- recovery: true,
- }
-
- prebuilt_etc {
- name: "prebuilt_recovery_indirect",
- src: "bar.conf",
- recovery: true,
- }
- `
-
- t.Run("prebuilt: vendor and recovery snapshot", func(t *testing.T) {
- result := prepareForPrebuiltEtcSnapshotTest.RunTestWithBp(t, testBp)
-
- checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor")
- checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor_indirect")
- checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery")
- checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
- })
-
- t.Run("prebuilt: directed snapshot", func(t *testing.T) {
- prepareForPrebuiltEtcDirectedSnapshotTest := android.GroupFixturePreparers(
- prepareForPrebuiltEtcSnapshotTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.TestProductVariables.DirectedVendorSnapshot = true
- config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
- config.TestProductVariables.VendorSnapshotModules["prebuilt_vendor"] = true
- config.TestProductVariables.DirectedRecoverySnapshot = true
- config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
- config.TestProductVariables.RecoverySnapshotModules["prebuilt_recovery"] = true
- }),
- )
-
- result := prepareForPrebuiltEtcDirectedSnapshotTest.RunTestWithBp(t, testBp)
-
- checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor")
- checkIfSnapshotNotTaken(t, result, "vendor", "prebuilt_vendor_indirect")
- checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery")
- checkIfSnapshotNotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
- })
-}
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index cdf6682..18dd553 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -10,6 +10,7 @@
"soong",
"soong-android",
"soong-bpf", // for testing
+ "soong-phony", // for testing
"soong-linkerconfig",
],
srcs: [
@@ -17,6 +18,7 @@
"avb_gen_vbmeta_image.go",
"bootimg.go",
"filesystem.go",
+ "fsverity_metadata.go",
"logical_partition.go",
"raw_binary.go",
"system_image.go",
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 6612a6f..e640c5d 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -19,6 +19,7 @@
"fmt"
"io"
"path/filepath"
+ "slices"
"strings"
"android/soong/android"
@@ -35,6 +36,7 @@
func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_filesystem", filesystemFactory)
ctx.RegisterModuleType("android_system_image", systemImageFactory)
+ ctx.RegisterModuleType("android_system_image_defaults", systemImageDefaultsFactory)
ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
ctx.RegisterModuleType("avb_add_hash_footer_defaults", avbAddHashFooterDefaultsFactory)
ctx.RegisterModuleType("avb_gen_vbmeta_image", avbGenVbmetaImageFactory)
@@ -56,7 +58,7 @@
output android.OutputPath
installDir android.InstallPath
- // For testing. Keeps the result of CopyDepsToZip()
+ // For testing. Keeps the result of CopySpecsToDir()
entries []string
}
@@ -87,6 +89,10 @@
// is ext4.
Type *string
+ // Identifies which partition this is for //visibility:any_system_image (and others) visibility
+ // checks, and will be used in the future for API surface checks.
+ Partition_type *string
+
// file_contexts file to make image. Currently, only ext4 is supported.
File_contexts *string `android:"path"`
@@ -109,6 +115,14 @@
// Mount point for this image. Default is "/"
Mount_point *string
+
+ // If set to the name of a partition ("system", "vendor", etc), this filesystem module
+ // will also include the contents of the make-built staging directories. If any soong
+ // modules would be installed to the same location as a make module, they will overwrite
+ // the make version.
+ Include_make_built_files string
+
+ Fsverity fsverityProperties
}
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -165,9 +179,16 @@
return f.BaseModuleName() + ".img"
}
+func (f *filesystem) partitionName() string {
+ return proptools.StringDefault(f.properties.Partition_name, f.Name())
+}
+
var pctx = android.NewPackageContext("android/soong/filesystem")
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if !android.InList(f.PartitionType(), validPartitions) {
+ ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, f.PartitionType())
+ }
switch f.fsType(ctx) {
case ext4Type:
f.output = f.buildImageUsingBuildImage(ctx)
@@ -183,13 +204,9 @@
ctx.InstallFile(f.installDir, f.installFileName(), f.output)
}
-// root zip will contain extra files/dirs that are not from the `deps` property.
-func (f *filesystem) buildRootZip(ctx android.ModuleContext) android.OutputPath {
- rootDir := android.PathForModuleGen(ctx, "root").OutputPath
- builder := android.NewRuleBuilder(pctx, ctx)
- builder.Command().Text("rm -rf").Text(rootDir.String())
- builder.Command().Text("mkdir -p").Text(rootDir.String())
-
+// Copy extra files/dirs that are not from the `deps` property to `rootDir`, checking for conflicts with files
+// already in `rootDir`.
+func (f *filesystem) buildNonDepsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.OutputPath) {
// create dirs and symlinks
for _, dir := range f.properties.Dirs {
// OutputPath.Join verifies dir
@@ -212,65 +229,45 @@
// OutputPath.Join verifies name. don't need to verify target.
dst := rootDir.Join(ctx, name)
-
+ builder.Command().Textf("(! [ -e %s -o -L %s ] || (echo \"%s already exists from an earlier stage of the build\" && exit 1))", dst, dst, dst)
builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String()))
builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String())
}
// create extra files if there's any
- rootForExtraFiles := android.PathForModuleGen(ctx, "root-extra").OutputPath
- var extraFiles android.OutputPaths
if f.buildExtraFiles != nil {
- extraFiles = f.buildExtraFiles(ctx, rootForExtraFiles)
+ rootForExtraFiles := android.PathForModuleGen(ctx, "root-extra").OutputPath
+ extraFiles := f.buildExtraFiles(ctx, rootForExtraFiles)
for _, f := range extraFiles {
- rel, _ := filepath.Rel(rootForExtraFiles.String(), f.String())
- if strings.HasPrefix(rel, "..") {
- panic(fmt.Errorf("%q is not under %q\n", f, rootForExtraFiles))
+ rel, err := filepath.Rel(rootForExtraFiles.String(), f.String())
+ if err != nil || strings.HasPrefix(rel, "..") {
+ ctx.ModuleErrorf("can't make %q relative to %q", f, rootForExtraFiles)
}
}
- }
-
- // Zip them all
- zipOut := android.PathForModuleGen(ctx, "root.zip").OutputPath
- zipCommand := builder.Command().BuiltTool("soong_zip")
- zipCommand.FlagWithOutput("-o ", zipOut).
- FlagWithArg("-C ", rootDir.String()).
- Flag("-L 0"). // no compression because this will be unzipped soon
- FlagWithArg("-D ", rootDir.String()).
- Flag("-d") // include empty directories
- if len(extraFiles) > 0 {
- zipCommand.FlagWithArg("-C ", rootForExtraFiles.String())
- for _, f := range extraFiles {
- zipCommand.FlagWithInput("-f ", f)
+ if len(extraFiles) > 0 {
+ builder.Command().BuiltTool("merge_directories").
+ Implicits(extraFiles.Paths()).
+ Text(rootDir.String()).
+ Text(rootForExtraFiles.String())
}
}
-
- builder.Command().Text("rm -rf").Text(rootDir.String())
-
- builder.Build("zip_root", fmt.Sprintf("zipping root contents for %s", ctx.ModuleName()))
- return zipOut
}
func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.OutputPath {
- depsZipFile := android.PathForModuleOut(ctx, "deps.zip").OutputPath
- f.entries = f.CopyDepsToZip(ctx, f.gatherFilteredPackagingSpecs(ctx), depsZipFile)
-
- builder := android.NewRuleBuilder(pctx, ctx)
- depsBase := proptools.StringDefault(f.properties.Base_dir, ".")
- rebasedDepsZip := android.PathForModuleOut(ctx, "rebased_deps.zip").OutputPath
- builder.Command().
- BuiltTool("zip2zip").
- FlagWithInput("-i ", depsZipFile).
- FlagWithOutput("-o ", rebasedDepsZip).
- Text("**/*:" + proptools.ShellEscape(depsBase)) // zip2zip verifies depsBase
-
rootDir := android.PathForModuleOut(ctx, "root").OutputPath
- rootZip := f.buildRootZip(ctx)
- builder.Command().
- BuiltTool("zipsync").
- FlagWithArg("-d ", rootDir.String()). // zipsync wipes this. No need to clear.
- Input(rootZip).
- Input(rebasedDepsZip)
+ rebasedDir := rootDir
+ if f.properties.Base_dir != nil {
+ rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir)
+ }
+ builder := android.NewRuleBuilder(pctx, ctx)
+ // Wipe the root dir to get rid of leftover files from prior builds
+ builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir)
+ specs := f.gatherFilteredPackagingSpecs(ctx)
+ f.entries = f.CopySpecsToDir(ctx, builder, specs, rebasedDir)
+
+ f.buildNonDepsFiles(ctx, builder, rootDir)
+ f.addMakeBuiltFiles(ctx, builder, rootDir)
+ f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
// run host_init_verifier
// Ideally we should have a concept of pluggable linters that verify the generated image.
@@ -311,18 +308,16 @@
}
func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) {
- type prop struct {
- name string
- value string
- }
-
- var props []prop
var deps android.Paths
+ var propFileString strings.Builder
addStr := func(name string, value string) {
- props = append(props, prop{name, value})
+ propFileString.WriteString(name)
+ propFileString.WriteRune('=')
+ propFileString.WriteString(value)
+ propFileString.WriteRune('\n')
}
addPath := func(name string, path android.Path) {
- props = append(props, prop{name, path.String()})
+ addStr(name, path.String())
deps = append(deps, path)
}
@@ -352,13 +347,12 @@
addStr("avb_algorithm", algorithm)
key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key))
addPath("avb_key_path", key)
- partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
- addStr("partition_name", partitionName)
+ addStr("partition_name", f.partitionName())
avb_add_hashtree_footer_args := "--do_not_generate_fec"
if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" {
avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm
}
- securityPatchKey := "com.android.build." + partitionName + ".security_patch"
+ securityPatchKey := "com.android.build." + f.partitionName() + ".security_patch"
securityPatchValue := ctx.Config().PlatformSecurityPatch()
avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue
addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args)
@@ -376,15 +370,7 @@
addStr("hash_seed", uuid)
}
propFile = android.PathForModuleOut(ctx, "prop").OutputPath
- builder := android.NewRuleBuilder(pctx, ctx)
- builder.Command().Text("rm").Flag("-rf").Output(propFile)
- for _, p := range props {
- builder.Command().
- Text("echo").
- Flag(`"` + p.name + "=" + p.value + `"`).
- Text(">>").Output(propFile)
- }
- builder.Build("build_filesystem_prop", fmt.Sprintf("Creating filesystem props for %s", f.BaseModuleName()))
+ android.WriteFileRuleVerbatim(ctx, propFile, propFileString.String())
return propFile, deps
}
@@ -398,25 +384,23 @@
ctx.PropertyErrorf("file_contexts", "file_contexts is not supported for compressed cpio image.")
}
- depsZipFile := android.PathForModuleOut(ctx, "deps.zip").OutputPath
- f.entries = f.CopyDepsToZip(ctx, f.gatherFilteredPackagingSpecs(ctx), depsZipFile)
-
- builder := android.NewRuleBuilder(pctx, ctx)
- depsBase := proptools.StringDefault(f.properties.Base_dir, ".")
- rebasedDepsZip := android.PathForModuleOut(ctx, "rebased_deps.zip").OutputPath
- builder.Command().
- BuiltTool("zip2zip").
- FlagWithInput("-i ", depsZipFile).
- FlagWithOutput("-o ", rebasedDepsZip).
- Text("**/*:" + proptools.ShellEscape(depsBase)) // zip2zip verifies depsBase
+ if f.properties.Include_make_built_files != "" {
+ ctx.PropertyErrorf("include_make_built_files", "include_make_built_files is not supported for compressed cpio image.")
+ }
rootDir := android.PathForModuleOut(ctx, "root").OutputPath
- rootZip := f.buildRootZip(ctx)
- builder.Command().
- BuiltTool("zipsync").
- FlagWithArg("-d ", rootDir.String()). // zipsync wipes this. No need to clear.
- Input(rootZip).
- Input(rebasedDepsZip)
+ rebasedDir := rootDir
+ if f.properties.Base_dir != nil {
+ rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir)
+ }
+ builder := android.NewRuleBuilder(pctx, ctx)
+ // Wipe the root dir to get rid of leftover files from prior builds
+ builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir)
+ specs := f.gatherFilteredPackagingSpecs(ctx)
+ f.entries = f.CopySpecsToDir(ctx, builder, specs, rebasedDir)
+
+ f.buildNonDepsFiles(ctx, builder, rootDir)
+ f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
cmd := builder.Command().
@@ -439,6 +423,45 @@
return output
}
+var validPartitions = []string{
+ "system",
+ "userdata",
+ "cache",
+ "system_other",
+ "vendor",
+ "product",
+ "system_ext",
+ "odm",
+ "vendor_dlkm",
+ "odm_dlkm",
+ "system_dlkm",
+}
+
+func (f *filesystem) addMakeBuiltFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.Path) {
+ partition := f.properties.Include_make_built_files
+ if partition == "" {
+ return
+ }
+ if !slices.Contains(validPartitions, partition) {
+ ctx.PropertyErrorf("include_make_built_files", "Expected one of %#v, found %q", validPartitions, partition)
+ return
+ }
+ stampFile := fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/staging_dir.stamp", ctx.Config().DeviceName(), partition)
+ fileListFile := fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partition)
+ stagingDir := fmt.Sprintf("target/product/%s/%s", ctx.Config().DeviceName(), partition)
+
+ builder.Command().BuiltTool("merge_directories").
+ Implicit(android.PathForArbitraryOutput(ctx, stampFile)).
+ Text("--ignore-duplicates").
+ FlagWithInput("--file-list", android.PathForArbitraryOutput(ctx, fileListFile)).
+ Text(rootDir.String()).
+ Text(android.PathForArbitraryOutput(ctx, stagingDir).String())
+}
+
+func (f *filesystem) PartitionType() string {
+ return proptools.StringDefault(f.properties.Partition_type, "system")
+}
+
var _ android.AndroidMkEntriesProvider = (*filesystem)(nil)
// Implements android.AndroidMkEntriesProvider
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index c448105..5c780f8 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -16,12 +16,14 @@
import (
"os"
+ "path/filepath"
"testing"
"android/soong/android"
"android/soong/bpf"
"android/soong/cc"
"android/soong/etc"
+ "android/soong/phony"
"github.com/google/blueprint/proptools"
)
@@ -35,6 +37,7 @@
bpf.PrepareForTestWithBpf,
etc.PrepareForTestWithPrebuiltEtc,
cc.PrepareForIntegrationTestWithCc,
+ phony.PrepareForTestWithPhony,
PrepareForTestWithFilesystemBuildComponents,
)
@@ -46,6 +49,7 @@
common: {
deps: [
"bpf.o",
+ "phony",
],
},
lib32: {
@@ -75,6 +79,20 @@
cc_library {
name: "libbar",
+ required: ["libbaz"],
+ }
+
+ cc_library {
+ name: "libbaz",
+ }
+
+ phony {
+ name: "phony",
+ required: ["libquz"],
+ }
+
+ cc_library {
+ name: "libquz",
}
`)
@@ -86,6 +104,8 @@
"bin/foo",
"lib/libbar.so",
"lib64/libbar.so",
+ "lib64/libbaz.so",
+ "lib64/libquz.so",
"etc/bpf/bpf.o",
}
for _, e := range expected {
@@ -93,6 +113,22 @@
}
}
+func TestIncludeMakeBuiltFiles(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ android_filesystem {
+ name: "myfilesystem",
+ include_make_built_files: "system",
+ }
+ `)
+
+ output := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img")
+
+ stampFile := filepath.Join(result.Config.OutDir(), "target/product/test_device/obj/PACKAGING/system_intermediates/staging_dir.stamp")
+ fileListFile := filepath.Join(result.Config.OutDir(), "target/product/test_device/obj/PACKAGING/system_intermediates/file_list.txt")
+ android.AssertStringListContains(t, "deps of filesystem must include the staging dir stamp file", output.Implicits.Strings(), stampFile)
+ android.AssertStringListContains(t, "deps of filesystem must include the staging dir file list", output.Implicits.Strings(), fileListFile)
+}
+
func TestFileSystemFillsLinkerConfigWithStubLibs(t *testing.T) {
result := fixture.RunTestWithBp(t, `
android_system_image {
@@ -270,7 +306,7 @@
}
`)
- inputs := result.ModuleForTests("myfilesystem", "android_common").Output("deps.zip").Implicits
+ inputs := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img").Implicits
android.AssertStringListContains(t, "filesystem should have libbar even for unbundled build",
inputs.Strings(),
"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
@@ -314,7 +350,7 @@
`)
filesystem := result.ModuleForTests("myfilesystem", "android_common_cov")
- inputs := filesystem.Output("deps.zip").Implicits
+ inputs := filesystem.Output("myfilesystem.img").Implicits
android.AssertStringListContains(t, "filesystem should have libfoo(cov)",
inputs.Strings(),
"out/soong/.intermediates/libfoo/android_arm64_armv8-a_shared_cov/libfoo.so")
@@ -328,3 +364,72 @@
t.Error("prebuilt should use cov variant of filesystem")
}
}
+
+func TestSystemImageDefaults(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ android_system_image_defaults {
+ name: "defaults",
+ multilib: {
+ common: {
+ deps: [
+ "phony",
+ ],
+ },
+ lib64: {
+ deps: [
+ "libbar",
+ ],
+ },
+ },
+ compile_multilib: "both",
+ }
+
+ android_system_image {
+ name: "system",
+ defaults: ["defaults"],
+ multilib: {
+ lib32: {
+ deps: [
+ "foo",
+ "libbar",
+ ],
+ },
+ },
+ }
+
+ cc_binary {
+ name: "foo",
+ compile_multilib: "prefer32",
+ }
+
+ cc_library {
+ name: "libbar",
+ required: ["libbaz"],
+ }
+
+ cc_library {
+ name: "libbaz",
+ }
+
+ phony {
+ name: "phony",
+ required: ["libquz"],
+ }
+
+ cc_library {
+ name: "libquz",
+ }
+ `)
+
+ fs := result.ModuleForTests("system", "android_common").Module().(*systemImage)
+ expected := []string{
+ "bin/foo",
+ "lib/libbar.so",
+ "lib64/libbar.so",
+ "lib64/libbaz.so",
+ "lib64/libquz.so",
+ }
+ for _, e := range expected {
+ android.AssertStringListContains(t, "missing entry", fs.entries, e)
+ }
+}
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
new file mode 100644
index 0000000..70f94e0
--- /dev/null
+++ b/filesystem/fsverity_metadata.go
@@ -0,0 +1,166 @@
+// Copyright (C) 2024 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 filesystem
+
+import (
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+)
+
+type fsverityProperties struct {
+ // Patterns of files for fsverity metadata generation. For each matched file, a .fsv_meta file
+ // will be generated and included to the filesystem image.
+ // etc/security/fsverity/BuildManifest.apk will also be generated which contains information
+ // about generated .fsv_meta files.
+ Inputs []string
+}
+
+func (f *filesystem) writeManifestGeneratorListFile(ctx android.ModuleContext, outputPath android.OutputPath, matchedSpecs []android.PackagingSpec, rebasedDir android.OutputPath) {
+ var buf strings.Builder
+ for _, spec := range matchedSpecs {
+ buf.WriteString(rebasedDir.Join(ctx, spec.RelPathInPackage()).String())
+ buf.WriteRune('\n')
+ }
+ android.WriteFileRuleVerbatim(ctx, outputPath, buf.String())
+}
+
+func (f *filesystem) buildFsverityMetadataFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir android.OutputPath, rebasedDir android.OutputPath) {
+ match := func(path string) bool {
+ for _, pattern := range f.properties.Fsverity.Inputs {
+ if matched, err := filepath.Match(pattern, path); matched {
+ return true
+ } else if err != nil {
+ ctx.PropertyErrorf("fsverity.inputs", "bad pattern %q", pattern)
+ return false
+ }
+ }
+ return false
+ }
+
+ var matchedSpecs []android.PackagingSpec
+ for _, relPath := range android.SortedKeys(specs) {
+ if match(relPath) {
+ matchedSpecs = append(matchedSpecs, specs[relPath])
+ }
+ }
+
+ if len(matchedSpecs) == 0 {
+ return
+ }
+
+ fsverityBuilderPath := android.PathForModuleOut(ctx, "fsverity_builder.sh")
+ metadataGeneratorPath := ctx.Config().HostToolPath(ctx, "fsverity_metadata_generator")
+ fsverityPath := ctx.Config().HostToolPath(ctx, "fsverity")
+
+ cmd := builder.Command().Tool(fsverityBuilderPath)
+
+ // STEP 1: generate .fsv_meta
+ var sb strings.Builder
+ sb.WriteString("set -e\n")
+ cmd.Implicit(metadataGeneratorPath).Implicit(fsverityPath)
+ for _, spec := range matchedSpecs {
+ // srcPath is copied by CopySpecsToDir()
+ srcPath := rebasedDir.Join(ctx, spec.RelPathInPackage())
+ destPath := rebasedDir.Join(ctx, spec.RelPathInPackage()+".fsv_meta")
+ sb.WriteString(metadataGeneratorPath.String())
+ sb.WriteString(" --fsverity-path ")
+ sb.WriteString(fsverityPath.String())
+ sb.WriteString(" --signature none --hash-alg sha256 --output ")
+ sb.WriteString(destPath.String())
+ sb.WriteRune(' ')
+ sb.WriteString(srcPath.String())
+ sb.WriteRune('\n')
+ }
+
+ // STEP 2: generate signed BuildManifest.apk
+ // STEP 2-1: generate build_manifest.pb
+ assetsPath := android.PathForModuleOut(ctx, "fsverity_manifest/assets")
+ manifestPbPath := assetsPath.Join(ctx, "build_manifest.pb")
+ manifestGeneratorPath := ctx.Config().HostToolPath(ctx, "fsverity_manifest_generator")
+ cmd.Implicit(manifestGeneratorPath)
+ sb.WriteString("rm -rf ")
+ sb.WriteString(assetsPath.String())
+ sb.WriteString(" && mkdir -p ")
+ sb.WriteString(assetsPath.String())
+ sb.WriteRune('\n')
+ sb.WriteString(manifestGeneratorPath.String())
+ sb.WriteString(" --fsverity-path ")
+ sb.WriteString(fsverityPath.String())
+ sb.WriteString(" --base-dir ")
+ sb.WriteString(rootDir.String())
+ sb.WriteString(" --output ")
+ sb.WriteString(manifestPbPath.String())
+ sb.WriteRune(' ')
+
+ manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list")
+ f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath.OutputPath, matchedSpecs, rebasedDir)
+ sb.WriteRune('@')
+ sb.WriteString(manifestGeneratorListPath.String())
+ sb.WriteRune('\n')
+ cmd.Implicit(manifestGeneratorListPath)
+
+ // STEP 2-2: generate BuildManifest.apk (unsigned)
+ aapt2Path := ctx.Config().HostToolPath(ctx, "aapt2")
+ apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", "BuildManifest.apk")
+ manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml")
+ // package-export is currently generated by Makefile.
+ // TODO(b/330282551): fully migrate into Soong
+ frameworkResPath := android.PathForArbitraryOutput(ctx, "target/common/obj/APPS/framework-res_intermediates/package-export.apk")
+ cmd.Implicit(aapt2Path)
+ cmd.Implicit(manifestTemplatePath)
+ cmd.Implicit(frameworkResPath)
+
+ sb.WriteString(aapt2Path.String())
+ sb.WriteString(" link -o ")
+ sb.WriteString(apkPath.String())
+ sb.WriteString(" -A ")
+ sb.WriteString(assetsPath.String())
+ sb.WriteString(" -I ")
+ sb.WriteString(frameworkResPath.String())
+ minSdkVersion := ctx.Config().PlatformSdkCodename()
+ if minSdkVersion == "REL" {
+ minSdkVersion = ctx.Config().PlatformSdkVersion().String()
+ }
+ sb.WriteString(" --min-sdk-version ")
+ sb.WriteString(minSdkVersion)
+ sb.WriteString(" --version-code ")
+ sb.WriteString(ctx.Config().PlatformSdkVersion().String())
+ sb.WriteString(" --version-name ")
+ sb.WriteString(ctx.Config().AppsDefaultVersionName())
+ sb.WriteString(" --manifest ")
+ sb.WriteString(manifestTemplatePath.String())
+ sb.WriteString(" --rename-manifest-package com.android.security.fsverity_metadata.")
+ sb.WriteString(f.partitionName())
+ sb.WriteRune('\n')
+
+ // STEP 2-3: sign BuildManifest.apk
+ apksignerPath := ctx.Config().HostToolPath(ctx, "apksigner")
+ pemPath, keyPath := ctx.Config().DefaultAppCertificate(ctx)
+ cmd.Implicit(apksignerPath)
+ cmd.Implicit(pemPath)
+ cmd.Implicit(keyPath)
+ sb.WriteString(apksignerPath.String())
+ sb.WriteString(" sign --in ")
+ sb.WriteString(apkPath.String())
+ sb.WriteString(" --cert ")
+ sb.WriteString(pemPath.String())
+ sb.WriteString(" --key ")
+ sb.WriteString(keyPath.String())
+ sb.WriteRune('\n')
+
+ android.WriteExecutableFileRuleVerbatim(ctx, fsverityBuilderPath, sb.String())
+}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 34f4ffb..92bb206 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -21,6 +21,7 @@
type systemImage struct {
filesystem
+ android.DefaultableModuleBase
properties systemImageProperties
}
@@ -39,10 +40,14 @@
module.filesystem.buildExtraFiles = module.buildExtraFiles
module.filesystem.filterPackagingSpec = module.filterPackagingSpec
initFilesystemModule(&module.filesystem)
+ android.InitDefaultableModule(module)
return module
}
func (s *systemImage) buildExtraFiles(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths {
+ if s.filesystem.properties.Partition_type != nil {
+ ctx.PropertyErrorf("partition_type", "partition_type must be unset on an android_system_image module. It is assumed to be 'system'.")
+ }
lc := s.buildLinkerConfigFile(ctx, root)
// Add more files if needed
return []android.OutputPath{lc}
@@ -53,19 +58,40 @@
output := root.Join(ctx, "system", "etc", "linker.config.pb")
// we need "Module"s for packaging items
- var otherModules []android.Module
+ modulesInPackageByModule := make(map[android.Module]bool)
+ modulesInPackageByName := make(map[string]bool)
+
deps := s.gatherFilteredPackagingSpecs(ctx)
ctx.WalkDeps(func(child, parent android.Module) bool {
for _, ps := range child.PackagingSpecs() {
if _, ok := deps[ps.RelPathInPackage()]; ok {
- otherModules = append(otherModules, child)
+ modulesInPackageByModule[child] = true
+ modulesInPackageByName[child.Name()] = true
+ return true
}
}
return true
})
+ provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
+ for mod := range modulesInPackageByModule {
+ provideModules = append(provideModules, mod)
+ }
+
+ var requireModules []android.Module
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ _, parentInPackage := modulesInPackageByModule[parent]
+ _, childInPackageName := modulesInPackageByName[child.Name()]
+
+ // When parent is in the package, and child (or its variant) is not, this can be from an interface.
+ if parentInPackage && !childInPackageName {
+ requireModules = append(requireModules, child)
+ }
+ return true
+ })
+
builder := android.NewRuleBuilder(pctx, ctx)
- linkerconfig.BuildLinkerConfig(ctx, builder, input, otherModules, output)
+ linkerconfig.BuildLinkerConfig(ctx, builder, input, provideModules, requireModules, output)
builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
return output
}
@@ -76,3 +102,17 @@
func (s *systemImage) filterPackagingSpec(ps android.PackagingSpec) bool {
return ps.Partition() == "system"
}
+
+type systemImageDefaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+// android_system_image_defaults is a default module for android_system_image module.
+func systemImageDefaultsFactory() android.Module {
+ module := &systemImageDefaults{}
+ module.AddProperties(&android.PackagingProperties{})
+ module.AddProperties(&systemImageProperties{})
+ android.InitDefaultsModule(module)
+ return module
+}
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 60b1366..7c71b77 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -21,9 +21,4 @@
"com.google.pixel.camera.hal.manifest",
// go/keep-sorted end
}
-
- SandboxingDenyPathList = []string{
- // go/keep-sorted start
- // go/keep-sorted end
- }
)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 6f66088..43f4fe5 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -317,7 +317,17 @@
// required relative locations of the tool and its dependencies, use those
// instead. They will be copied to those relative locations in the sbox
// sandbox.
- packagedTools = append(packagedTools, specs...)
+ // Care must be taken since TransitivePackagingSpec may return device-side
+ // paths via the required property. Filter them out.
+ for i, ps := range specs {
+ if ps.Partition() != "" {
+ if i == 0 {
+ panic("first PackagingSpec is assumed to be the host-side tool")
+ }
+ continue
+ }
+ packagedTools = append(packagedTools, ps)
+ }
// Assume that the first PackagingSpec of the module is the tool.
addLocationLabel(tag.label, packagedToolLocation{specs[0]})
} else {
@@ -808,7 +818,7 @@
type genRuleProperties struct {
// names of the output files that will be generated
- Out []string
+ Out []string `android:"arch_variant"`
}
var Bool = proptools.Bool
@@ -842,19 +852,15 @@
type sandboxingAllowlistSets struct {
sandboxingDenyModuleSet map[string]bool
- sandboxingDenyPathSet map[string]bool
}
func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSets {
return ctx.Config().Once(sandboxingAllowlistKey, func() interface{} {
sandboxingDenyModuleSet := map[string]bool{}
- sandboxingDenyPathSet := map[string]bool{}
android.AddToStringSet(sandboxingDenyModuleSet, SandboxingDenyModuleList)
- android.AddToStringSet(sandboxingDenyPathSet, SandboxingDenyPathList)
return &sandboxingAllowlistSets{
sandboxingDenyModuleSet: sandboxingDenyModuleSet,
- sandboxingDenyPathSet: sandboxingDenyPathSet,
}
}).(*sandboxingAllowlistSets)
}
@@ -864,8 +870,7 @@
return r.SandboxTools()
}
sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
- if sandboxingAllowlistSets.sandboxingDenyPathSet[ctx.ModuleDir()] ||
- sandboxingAllowlistSets.sandboxingDenyModuleSet[ctx.ModuleName()] {
+ if sandboxingAllowlistSets.sandboxingDenyModuleSet[ctx.ModuleName()] {
return r.SandboxTools()
}
return r.SandboxInputs()
diff --git a/java/aar.go b/java/aar.go
index b3239ba..fef0d8c 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -104,6 +104,9 @@
// Filter only specified product and ignore other products
Filter_product *string `blueprint:"mutated"`
+
+ // Names of aconfig_declarations modules that specify aconfig flags that the module depends on.
+ Flags_packages []string
}
type aapt struct {
@@ -161,7 +164,9 @@
}
func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool {
- return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault())
+ return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault()) &&
+ // TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries.
+ !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib")
}
func (a *aapt) filterProduct() string {
@@ -348,6 +353,7 @@
classLoaderContexts dexpreopt.ClassLoaderContextMap
excludedLibs []string
enforceDefaultTargetSdkVersion bool
+ forceNonFinalResourceIDs bool
extraLinkFlags []string
aconfigTextFiles android.Paths
}
@@ -383,11 +389,6 @@
// Add additional manifest files to transitive manifests.
additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
transitiveManifestPaths := append(android.Paths{manifestPath}, additionalManifests...)
- // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import
- // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies
- // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of
- // android_library_import modules. If this is fixed, staticManifestsDepSet can be dropped completely in favor of
- // staticResourcesNodesDepSet.manifests()
transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...)
if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
@@ -455,6 +456,11 @@
// as imports. The resources from dependencies will not be merged into this module's package-res.apk, and
// instead modules depending on this module will reference package-res.apk from all transitive static
// dependencies.
+ for _, sharedDep := range sharedDeps {
+ if sharedDep.usedResourceProcessor {
+ transitiveRJars = append(transitiveRJars, sharedDep.rJar)
+ }
+ }
for _, staticDep := range staticDeps {
linkDeps = append(linkDeps, staticDep.resPackage)
linkFlags = append(linkFlags, "-I "+staticDep.resPackage.String())
@@ -462,11 +468,6 @@
transitiveRJars = append(transitiveRJars, staticDep.rJar)
}
}
- for _, sharedDep := range sharedDeps {
- if sharedDep.usedResourceProcessor {
- transitiveRJars = append(transitiveRJars, sharedDep.rJar)
- }
- }
} else {
// When building an app or building a library without ResourceProcessorBusyBox enabled all static
// dependencies are compiled into this module's package-res.apk as overlays.
@@ -541,7 +542,8 @@
if a.useResourceProcessorBusyBox(ctx) {
rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
- resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags)
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags,
+ opts.forceNonFinalResourceIDs)
aapt2ExtractExtraPackages(ctx, extraPackages, rJar)
transitiveRJars = append(transitiveRJars, rJar)
a.rJar = rJar
@@ -556,6 +558,10 @@
transitiveAaptResourcePackagesFile := android.PathForModuleOut(ctx, "transitive-res-packages")
android.WriteFileRule(ctx, transitiveAaptResourcePackagesFile, strings.Join(transitiveAaptResourcePackages, "\n"))
+ // Reverse the list of R.jar files so that the current module comes first, and direct dependencies come before
+ // transitive dependencies.
+ transitiveRJars = android.ReversePaths(transitiveRJars)
+
a.aaptSrcJar = srcJar
a.transitiveAaptRJars = transitiveRJars
a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
@@ -601,7 +607,8 @@
// using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and
// supports producing classes for static dependencies that only include resources from that dependency.
func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path,
- rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string) {
+ rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string,
+ forceNonFinalIds bool) {
var args []string
var deps android.Paths
@@ -611,6 +618,9 @@
// to ResourceProcessorBusyBox so that it can regenerate R.class files with the final resource IDs for each
// package.
args, deps = transitiveDeps.resourceProcessorDeps()
+ if forceNonFinalIds {
+ args = append(args, "--finalFields=false")
+ }
} else {
// When compiling a library don't pass any dependencies as it only needs to generate an R.class file for this
// library. Pass --finalFields=false so that the R.class file contains non-final fields so they don't get
@@ -750,7 +760,8 @@
// reverse later.
// NOTE: this is legacy and probably incorrect behavior, for most other cases (e.g. conflicting classes in
// dependencies) the highest priority dependency is listed first, but for resources the highest priority
- // dependency has to be listed last.
+ // dependency has to be listed last. This is also inconsistent with the way manifests from the same
+ // transitive dependencies are merged.
staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
android.ReverseSliceInPlace(staticResourcesNodeDepSets))
sharedResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
@@ -800,6 +811,10 @@
a.aapt.deps(ctx, sdkDep)
}
a.usesLibrary.deps(ctx, false)
+
+ for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -813,13 +828,14 @@
sdkContext: android.SdkContext(a),
classLoaderContexts: a.classLoaderContexts,
enforceDefaultTargetSdkVersion: false,
+ aconfigTextFiles: getAconfigFilePaths(ctx),
},
)
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
a.hideApexVariantFromMake = !apexInfo.IsForPlatform()
- a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+ a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
ctx.CheckbuildFile(a.aapt.proguardOptionsFile)
ctx.CheckbuildFile(a.aapt.exportPackage)
@@ -960,7 +976,8 @@
properties AARImportProperties
- classpathFile android.WritablePath
+ headerJarFile android.WritablePath
+ implementationJarFile android.WritablePath
proguardFlags android.WritablePath
exportPackage android.WritablePath
transitiveAaptResourcePackagesFile android.Path
@@ -981,6 +998,9 @@
sdkVersion android.SdkSpec
minSdkVersion android.ApiLevel
+ usesLibrary
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
+
// Single aconfig "cache file" merged from this module and all dependencies.
mergedAconfigFiles map[string]android.Paths
}
@@ -993,7 +1013,7 @@
case ".aar":
return []android.Path{a.aarPath}, nil
case "":
- return []android.Path{a.classpathFile}, nil
+ return []android.Path{a.implementationJarFile}, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -1076,6 +1096,8 @@
ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
+
+ a.usesLibrary.deps(ctx, false)
}
type JniPackageInfo struct {
@@ -1134,27 +1156,33 @@
}
extractedAARDir := android.PathForModuleOut(ctx, "aar")
- a.classpathFile = extractedAARDir.Join(ctx, "classes-combined.jar")
+ classpathFile := extractedAARDir.Join(ctx, ctx.ModuleName()+".jar")
a.manifest = extractedAARDir.Join(ctx, "AndroidManifest.xml")
a.rTxt = extractedAARDir.Join(ctx, "R.txt")
a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
+ transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{
ProguardFlagsFiles: android.NewDepSet[android.Path](
android.POSTORDER,
android.Paths{a.proguardFlags},
+ transitiveProguardFlags,
+ ),
+ UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path](
+ android.POSTORDER,
nil,
+ transitiveUnconditionalExportedFlags,
),
})
ctx.Build(pctx, android.BuildParams{
Rule: unzipAAR,
Input: a.aarPath,
- Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, a.rTxt},
+ Outputs: android.WritablePaths{classpathFile, a.proguardFlags, a.manifest, a.assetsPackage, a.rTxt},
Description: "unzip AAR",
Args: map[string]string{
"outDir": extractedAARDir.String(),
- "combinedClassesJar": a.classpathFile.String(),
+ "combinedClassesJar": classpathFile.String(),
"assetsPackage": a.assetsPackage.String(),
},
})
@@ -1209,7 +1237,7 @@
linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil)
a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
- resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil)
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil, false)
aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)
@@ -1227,13 +1255,7 @@
a.resourcesNodesDepSet = resourcesNodesDepSetBuilder.Build()
manifestDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(a.manifest)
- // TODO(b/288358614): Soong has historically not merged manifests from dependencies of android_library_import
- // modules. Merging manifests from dependencies could remove the need for pom2bp to generate the "-nodeps" copies
- // of androidx libraries, but doing so triggers errors due to errors introduced by existing dependencies of
- // android_library_import modules. If this is fixed, AndroidLibraryDependency.ManifestsDepSet can be dropped
- // completely in favor of AndroidLibraryDependency.ResourceNodesDepSet.manifest
- //manifestDepSetBuilder.Transitive(transitiveStaticDeps.manifests)
- _ = staticManifestsDepSet
+ manifestDepSetBuilder.Transitive(staticManifestsDepSet)
a.manifestsDepSet = manifestDepSetBuilder.Build()
transitiveAaptResourcePackages := staticDeps.resPackages().Strings()
@@ -1245,12 +1267,49 @@
a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
a.collectTransitiveHeaderJars(ctx)
+
+ a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+
+ var staticJars android.Paths
+ var staticHeaderJars android.Paths
+ ctx.VisitDirectDeps(func(module android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ tag := ctx.OtherModuleDependencyTag(module)
+ switch tag {
+ case staticLibTag:
+ staticJars = append(staticJars, dep.ImplementationJars...)
+ staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
+ }
+ }
+ addCLCFromDep(ctx, module, a.classLoaderContexts)
+ })
+
+ var implementationJarFile android.OutputPath
+ if len(staticJars) > 0 {
+ combineJars := append(android.Paths{classpathFile}, staticJars...)
+ implementationJarFile = android.PathForModuleOut(ctx, "combined", ctx.ModuleName()+".jar").OutputPath
+ TransformJarsToJar(ctx, implementationJarFile, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+ } else {
+ implementationJarFile = classpathFile
+ }
+
+ // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
+ a.implementationJarFile = implementationJarFile.WithoutRel()
+
+ if len(staticHeaderJars) > 0 {
+ combineJars := append(android.Paths{classpathFile}, staticHeaderJars...)
+ a.headerJarFile = android.PathForModuleOut(ctx, "turbine-combined", ctx.ModuleName()+".jar")
+ TransformJarsToJar(ctx, a.headerJarFile, "combine header jars", combineJars, android.OptionalPath{}, false, nil, nil)
+ } else {
+ a.headerJarFile = classpathFile
+ }
+
android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(a.classpathFile),
+ HeaderJars: android.PathsIfNonNil(a.headerJarFile),
TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
- ImplementationJars: android.PathsIfNonNil(a.classpathFile),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(a.implementationJarFile),
+ ImplementationJars: android.PathsIfNonNil(a.implementationJarFile),
StubsLinkType: Implementation,
// TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
@@ -1283,15 +1342,15 @@
}
func (a *AARImport) HeaderJars() android.Paths {
- return android.Paths{a.classpathFile}
+ return android.Paths{a.headerJarFile}
}
func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
- return android.Paths{a.classpathFile}
+ return android.Paths{a.implementationJarFile}
}
-func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
- return nil
+func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ return OptionalDexJarPath{}
}
func (a *AARImport) DexJarInstallPath() android.Path {
@@ -1299,9 +1358,11 @@
}
func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
- return nil
+ return a.classLoaderContexts
}
+var _ UsesLibraryDependency = (*AARImport)(nil)
+
var _ android.ApexModule = (*AARImport)(nil)
// Implements android.ApexModule
@@ -1310,7 +1371,7 @@
}
// Implements android.ApexModule
-func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
+func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
return nil
}
@@ -1324,7 +1385,10 @@
func AARImportFactory() android.Module {
module := &AARImport{}
- module.AddProperties(&module.properties)
+ module.AddProperties(
+ &module.properties,
+ &module.usesLibrary.usesLibraryProperties,
+ )
android.InitPrebuiltModule(module, &module.properties.Aars)
android.InitApexModule(module)
diff --git a/java/aar_test.go b/java/aar_test.go
index 4d4e5d0..3361bf9 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -81,3 +81,95 @@
})
}
}
+
+func TestLibraryFlagsPackages(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ android_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ "baz",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+
+ // android_library module depends on aconfig_declarations listed in flags_packages
+ android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
+
+ android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
+
+ aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+}
+
+func TestAndroidLibraryOutputFilesRel(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ android_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+
+ android_library_import {
+ name: "bar",
+ aars: ["bar.aar"],
+
+ }
+
+ android_library_import {
+ name: "baz",
+ aars: ["baz.aar"],
+ static_libs: ["bar"],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ bar := result.ModuleForTests("bar", "android_common")
+ baz := result.ModuleForTests("baz", "android_common")
+
+ fooOutputPath := android.OutputFileForModule(android.PathContext(nil), foo.Module(), "")
+ barOutputPath := android.OutputFileForModule(android.PathContext(nil), bar.Module(), "")
+ bazOutputPath := android.OutputFileForModule(android.PathContext(nil), baz.Module(), "")
+
+ android.AssertPathRelativeToTopEquals(t, "foo output path",
+ "out/soong/.intermediates/foo/android_common/javac/foo.jar", fooOutputPath)
+ android.AssertPathRelativeToTopEquals(t, "bar output path",
+ "out/soong/.intermediates/bar/android_common/aar/bar.jar", barOutputPath)
+ android.AssertPathRelativeToTopEquals(t, "baz output path",
+ "out/soong/.intermediates/baz/android_common/combined/baz.jar", bazOutputPath)
+
+ android.AssertStringEquals(t, "foo relative output path",
+ "foo.jar", fooOutputPath.Rel())
+ android.AssertStringEquals(t, "bar relative output path",
+ "bar.jar", barOutputPath.Rel())
+ android.AssertStringEquals(t, "baz relative output path",
+ "baz.jar", bazOutputPath.Rel())
+}
diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go
index 5909b1e..7c91884 100644
--- a/java/android_manifest_test.go
+++ b/java/android_manifest_test.go
@@ -92,10 +92,9 @@
"out/soong/.intermediates/transitive/android_common/manifest_fixer/AndroidManifest.xml",
"transitive/AndroidManifest2.xml",
"out/soong/.intermediates/transitive_import/android_common/aar/AndroidManifest.xml",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/AndroidManifest.xml",
"out/soong/.intermediates/direct_import/android_common/aar/AndroidManifest.xml",
- // TODO(b/288358614): Soong has historically not merged manifests from dependencies of
- // android_library_import modules.
-
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/AndroidManifest.xml",
},
manifestMergerRule.Implicits)
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 498962f..a52d439 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -211,7 +211,7 @@
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
OverrideName: prebuilt.BaseModuleName(),
- OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
+ OutputFile: android.OptionalPathForPath(prebuilt.combinedImplementationFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
@@ -219,8 +219,8 @@
if prebuilt.dexJarFile.IsSet() {
entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile.Path())
}
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedHeaderFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedImplementationFile)
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion.String())
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
@@ -262,13 +262,13 @@
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
+ OutputFile: android.OptionalPathForPath(prebuilt.implementationJarFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.headerJarFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.implementationJarFile)
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage)
entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackagesFile)
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
diff --git a/java/app.go b/java/app.go
index 9736ffd..7b25775 100755
--- a/java/app.go
+++ b/java/app.go
@@ -169,9 +169,6 @@
// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
// from PRODUCT_PACKAGES.
Overrides []string
-
- // Names of aconfig_declarations modules that specify aconfig flags that the app depends on.
- Flags_packages []string
}
type AndroidApp struct {
@@ -290,6 +287,10 @@
}
a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
+
+ for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -317,10 +318,6 @@
`must be names of android_app_certificate modules in the form ":module"`)
}
}
-
- for _, aconfig_declaration := range a.overridableAppProperties.Flags_packages {
- ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
- }
}
func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -457,6 +454,21 @@
return proptools.BoolDefault(a.overridableAppProperties.Rename_resources_package, true)
}
+func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) {
+ ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) {
+ if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
+ aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
+ "flags_packages property, but %s is not aconfig_declarations module type",
+ dep.Name(),
+ )
+ }
+ })
+
+ return aconfigTextFilePaths
+}
+
func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
usePlatformAPI := proptools.Bool(a.Module.deviceProperties.Platform_apis)
if ctx.Module().(android.SdkContext).SdkVersion(ctx).Kind == android.SdkModule {
@@ -507,26 +519,17 @@
a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
}
- var aconfigTextFilePaths android.Paths
- ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) {
- if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
- aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
- } else {
- ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
- "flags_packages property, but %s is not aconfig_declarations module type",
- dep.Name(),
- )
- }
- })
-
+ // Use non final ids if we are doing optimized shrinking and are using R8.
+ nonFinalIds := Bool(a.dexProperties.Optimize.Optimized_shrink_resources) && a.dexer.effectiveOptimizeEnabled()
a.aapt.buildActions(ctx,
aaptBuildActionOptions{
sdkContext: android.SdkContext(a),
classLoaderContexts: a.classLoaderContexts,
excludedLibs: a.usesLibraryProperties.Exclude_uses_libs,
enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(),
+ forceNonFinalResourceIDs: nonFinalIds,
extraLinkFlags: aaptLinkFlags,
- aconfigTextFiles: aconfigTextFilePaths,
+ aconfigTextFiles: getAconfigFilePaths(ctx),
},
)
@@ -547,7 +550,13 @@
staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
- a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
+ if !Bool(a.dexProperties.Optimize.Optimized_shrink_resources) {
+ // When using the optimized shrinking the R8 enqueuer will traverse the xml files that become
+ // live for code references and (transitively) mark these as live.
+ // In this case we explicitly don't wan't the aapt2 generated keep files (which would keep the now
+ // dead code alive)
+ a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
+ }
}
func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
@@ -580,7 +589,7 @@
var packageResources = a.exportPackage
if ctx.ModuleName() != "framework-res" {
- if Bool(a.dexProperties.Optimize.Shrink_resources) {
+ if a.dexProperties.resourceShrinkingEnabled() {
protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
aapt2Convert(ctx, protoFile, packageResources, "proto")
a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
@@ -603,7 +612,7 @@
}
a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
- if Bool(a.dexProperties.Optimize.Shrink_resources) {
+ if a.dexProperties.resourceShrinkingEnabled() {
binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
packageResources = binaryResources
@@ -755,7 +764,7 @@
// Unlike installApkName, a.stem should respect base module name for override_android_app.
// Therefore, use ctx.ModuleName() instead of a.Name().
- a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
+ a.stem = proptools.StringDefault(a.overridableProperties.Stem, ctx.ModuleName())
// Check if the install APK name needs to be overridden.
// Both android_app and override_android_app module are expected to possess
@@ -763,7 +772,7 @@
// from the base module. Therefore, use a.Name() which represents
// the module name for both android_app and override_android_app.
a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(
- proptools.StringDefault(a.overridableDeviceProperties.Stem, a.Name()))
+ proptools.StringDefault(a.overridableProperties.Stem, a.Name()))
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
@@ -912,6 +921,13 @@
}
a.buildAppDependencyInfo(ctx)
+
+ providePrebuiltInfo(ctx,
+ prebuiltInfoProps{
+ baseModuleName: a.BaseModuleName(),
+ isPrebuilt: false,
+ },
+ )
}
type appDepsInterface interface {
@@ -1316,6 +1332,14 @@
a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
+ InstalledFiles: a.data,
+ OutputFile: a.OutputFile(),
+ TestConfig: a.testConfig,
+ HostRequiredModuleNames: a.HostRequiredModuleNames(),
+ TestSuites: a.testProperties.Test_suites,
+ IsHost: false,
+ })
}
func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
@@ -1494,7 +1518,7 @@
func OverrideAndroidAppModuleFactory() android.Module {
m := &OverrideAndroidApp{}
m.AddProperties(
- &OverridableDeviceProperties{},
+ &OverridableProperties{},
&overridableAppProperties{},
)
diff --git a/java/app_import.go b/java/app_import.go
index dc84fc2..7387e16 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -150,6 +150,11 @@
// If unspecified, follows the naming convention that the source module of
// the prebuilt is Name() without "prebuilt_" prefix
Source_module_name *string
+
+ // Path to the .prebuilt_info file of the prebuilt app.
+ // In case of mainline modules, the .prebuilt_info file contains the build_id that was used
+ // to generate the prebuilt.
+ Prebuilt_info *string `android:"path"`
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -413,6 +418,14 @@
}
android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
+ providePrebuiltInfo(ctx,
+ prebuiltInfoProps{
+ baseModuleName: a.BaseModuleName(),
+ isPrebuilt: true,
+ prebuiltInfo: a.properties.Prebuilt_info,
+ },
+ )
+
// TODO: androidmk converter jni libs
}
diff --git a/java/app_set.go b/java/app_set.go
index d2d3b06..33d3ade 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -48,6 +48,11 @@
// Names of modules to be overridden. Listed modules can only be other apps
// (in Make or Soong).
Overrides []string
+
+ // Path to the .prebuilt_info file of the prebuilt app.
+ // In case of mainline modules, the .prebuilt_info file contains the build_id that was used
+ // to generate the prebuilt.
+ Prebuilt_info *string `android:"path"`
}
type AndroidAppSet struct {
@@ -117,6 +122,27 @@
return result
}
+type prebuiltInfoProps struct {
+ baseModuleName string
+ isPrebuilt bool
+ prebuiltInfo *string
+}
+
+// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
+// with information about whether source or prebuilt of an apex was used during the build.
+func providePrebuiltInfo(ctx android.ModuleContext, p prebuiltInfoProps) {
+ info := android.PrebuiltInfo{
+ Name: p.baseModuleName,
+ Is_prebuilt: p.isPrebuilt,
+ }
+ // If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json.
+ if p.prebuiltInfo != nil {
+ prebuiltInfoFile := android.PathForModuleSrc(ctx, *p.prebuiltInfo)
+ info.Prebuilt_info_file_path = prebuiltInfoFile.String()
+ }
+ android.SetProvider(ctx, android.PrebuiltInfoProvider, info)
+}
+
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk")
@@ -157,6 +183,15 @@
installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
}
ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput)
+
+ providePrebuiltInfo(ctx,
+ prebuiltInfoProps{
+ baseModuleName: as.BaseModuleName(),
+ isPrebuilt: true,
+ prebuiltInfo: as.properties.Prebuilt_info,
+ },
+ )
+
}
func (as *AndroidAppSet) InstallBypassMake() bool { return true }
diff --git a/java/app_test.go b/java/app_test.go
index 28bea0a..8262777 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -829,12 +829,12 @@
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
},
appCombined: []string{
"out/soong/.intermediates/app/android_common/javac/app.jar",
"out/soong/.intermediates/direct/android_common/combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
},
directResources: nil,
@@ -849,12 +849,12 @@
directClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
},
directCombined: []string{
"out/soong/.intermediates/direct/android_common/javac/direct.jar",
"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
},
transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -928,13 +928,13 @@
"out/soong/.intermediates/app/android_common/busybox/R.jar",
"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
},
appCombined: []string{
"out/soong/.intermediates/app/android_common/javac/app.jar",
"out/soong/.intermediates/app/android_common/busybox/R.jar",
"out/soong/.intermediates/direct/android_common/combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
},
directResources: nil,
@@ -948,17 +948,17 @@
directSrcJars: nil,
directClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
- "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
- "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
- "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
"out/soong/.intermediates/direct/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
},
directCombined: []string{
"out/soong/.intermediates/direct/android_common/javac/direct.jar",
"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
},
transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -981,9 +981,9 @@
sharedSrcJars: nil,
sharedClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/busybox/R.jar",
"out/soong/.intermediates/shared_transitive_static/android_common/busybox/R.jar",
"out/soong/.intermediates/shared_transitive_shared/android_common/busybox/R.jar",
- "out/soong/.intermediates/shared/android_common/busybox/R.jar",
"out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
"out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
},
@@ -1034,13 +1034,13 @@
"out/soong/.intermediates/app/android_common/busybox/R.jar",
"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
},
appCombined: []string{
"out/soong/.intermediates/app/android_common/javac/app.jar",
"out/soong/.intermediates/app/android_common/busybox/R.jar",
"out/soong/.intermediates/direct/android_common/combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
},
dontVerifyDirect: true,
@@ -1075,12 +1075,12 @@
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
},
appCombined: []string{
"out/soong/.intermediates/app/android_common/javac/app.jar",
"out/soong/.intermediates/direct/android_common/combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
},
directResources: nil,
@@ -1094,16 +1094,16 @@
directSrcJars: nil,
directClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
- "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
- "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
"out/soong/.intermediates/direct/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
+ "out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
},
directCombined: []string{
"out/soong/.intermediates/direct/android_common/javac/direct.jar",
"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
},
dontVerifyTransitive: true,
@@ -1137,12 +1137,12 @@
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
},
appCombined: []string{
"out/soong/.intermediates/app/android_common/javac/app.jar",
"out/soong/.intermediates/direct/android_common/combined/direct.jar",
- "out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
},
directResources: nil,
@@ -1157,12 +1157,12 @@
directClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
},
directCombined: []string{
"out/soong/.intermediates/direct/android_common/javac/direct.jar",
"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
- "out/soong/.intermediates/transitive_import/android_common/aar/classes-combined.jar",
+ "out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
},
transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -3625,7 +3625,10 @@
android_app {
name: "foo",
sdk_version: "current",
- static_libs: ["lib1"],
+ static_libs: [
+ "lib1",
+ "lib3",
+ ],
}
android_library {
@@ -3633,22 +3636,49 @@
sdk_version: "current",
optimize: {
proguard_flags_files: ["lib1proguard.cfg"],
+ },
+ static_libs: ["lib2"],
+ }
+
+ android_library {
+ name: "lib2",
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["lib2proguard.cfg"],
}
}
+
+ android_library_import {
+ name: "lib3",
+ sdk_version: "current",
+ aars: ["lib3.aar"],
+ static_libs: ["lib4"],
+ }
+
+ android_library {
+ name: "lib4",
+ sdk_version: "current",
+ optimize: {
+ proguard_flags_files: ["lib4proguard.cfg"],
+ }
+ }
+
+
`)
m := ctx.ModuleForTests("foo", "android_common")
- hasLib1Proguard := false
- for _, s := range m.Rule("java.r8").Implicits.Strings() {
- if s == "lib1proguard.cfg" {
- hasLib1Proguard = true
- break
- }
- }
+ r8 := m.Rule("java.r8")
+ implicits := r8.Implicits.RelativeToTop().Strings()
+ android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg")
+ android.AssertStringListContains(t, "r8 implicits", implicits, "lib2proguard.cfg")
+ android.AssertStringListContains(t, "r8 implicits", implicits, "lib4proguard.cfg")
+ android.AssertStringListContains(t, "r8 implicits", implicits, "out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
- if !hasLib1Proguard {
- t.Errorf("App does not use library proguard config")
- }
+ flags := r8.Args["r8Flags"]
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib1proguard.cfg")
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib2proguard.cfg")
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib4proguard.cfg")
+ android.AssertStringDoesContain(t, "r8 flags", flags, "-include out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
}
func TestTargetSdkVersionManifestFixer(t *testing.T) {
@@ -4401,3 +4431,20 @@
dexpreopt := result.ModuleForTests("app", "android_common").MaybeRule("dexpreopt").Rule
android.AssertBoolEquals(t, "dexpreopt should be disabled if optional_uses_libs does not have an implementation", true, dexpreopt == nil)
}
+
+func TestAppStem(t *testing.T) {
+ ctx := testApp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ stem: "foo-new",
+ sdk_version: "current",
+ }`)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ outputs := fmt.Sprint(foo.AllOutputs())
+ if !strings.Contains(outputs, "foo-new.apk") {
+ t.Errorf("Module output does not contain expected apk %s", "foo-new.apk")
+ }
+}
diff --git a/java/base.go b/java/base.go
index d8ccec6..e2f20ce 100644
--- a/java/base.go
+++ b/java/base.go
@@ -26,7 +26,6 @@
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
- "android/soong/aconfig"
"android/soong/android"
"android/soong/dexpreopt"
"android/soong/java/config"
@@ -95,9 +94,6 @@
// if not blank, used as prefix to generate repackage rule
Jarjar_prefix *string
- // if set to true, skip the jarjar repackaging
- Skip_jarjar_repackage *bool
-
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -306,8 +302,8 @@
HiddenAPIFlagFileProperties
}
-// Device properties that can be overridden by overriding module (e.g. override_android_app)
-type OverridableDeviceProperties struct {
+// Properties that can be overridden by overriding module (e.g. override_android_app)
+type OverridableProperties struct {
// set the name of the output. If not set, `name` is used.
// To override a module with this property set, overriding module might need to set this as well.
// Otherwise, both the overridden and the overriding modules will have the same output name, which
@@ -435,7 +431,7 @@
protoProperties android.ProtoProperties
deviceProperties DeviceProperties
- overridableDeviceProperties OverridableDeviceProperties
+ overridableProperties OverridableProperties
// jar file containing header classes including static library dependencies, suitable for
// inserting into the bootclasspath/classpath of another compile
@@ -617,6 +613,7 @@
func (j *Module) addHostProperties() {
j.AddProperties(
&j.properties,
+ &j.overridableProperties,
&j.protoProperties,
&j.usesLibraryProperties,
)
@@ -626,7 +623,6 @@
j.addHostProperties()
j.AddProperties(
&j.deviceProperties,
- &j.overridableDeviceProperties,
&j.dexer.dexProperties,
&j.dexpreoptProperties,
&j.linter.properties,
@@ -805,7 +801,7 @@
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
- if ctx.DeviceConfig().VndkVersion() != "" && ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
+ if ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
// Require java_sdk_library at inter-partition java dependency to ensure stable
// interface between partitions. If inter-partition java_library dependency is detected,
// raise build error because java_library doesn't have a stable interface.
@@ -1104,13 +1100,11 @@
jarjarProviderData := j.collectJarJarRules(ctx)
if jarjarProviderData != nil {
android.SetProvider(ctx, JarJarProvider, *jarjarProviderData)
- if !proptools.Bool(j.properties.Skip_jarjar_repackage) {
- text := getJarJarRuleText(jarjarProviderData)
- if text != "" {
- ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
- android.WriteFileRule(ctx, ruleTextFile, text)
- j.repackageJarjarRules = ruleTextFile
- }
+ text := getJarJarRuleText(jarjarProviderData)
+ if text != "" {
+ ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
+ android.WriteFileRule(ctx, ruleTextFile, text)
+ j.repackageJarjarRules = ruleTextFile
}
}
@@ -1220,14 +1214,15 @@
}
android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- AidlIncludeDirs: j.exportAidlIncludeDirs,
- ExportedPlugins: j.exportedPluginJars,
- ExportedPluginClasses: j.exportedPluginClasses,
- ExportedPluginDisableTurbine: j.exportedDisableTurbine,
- StubsLinkType: j.stubsLinkType,
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ StubsLinkType: j.stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
})
j.outputFile = j.headerJarFile
@@ -1294,10 +1289,12 @@
return
}
+ kotlinJarPath := j.repackageFlagsIfNecessary(ctx, kotlinJar.OutputPath, jarName, "kotlinc")
+
// Make javac rule depend on the kotlinc rule
flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
- kotlinJars = append(kotlinJars, kotlinJar)
+ kotlinJars = append(kotlinJars, kotlinJarPath)
kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
// Jar kotlin classes into the final jar after javac
@@ -1377,6 +1374,7 @@
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
jars = append(jars, classes)
}
}
@@ -1389,11 +1387,13 @@
for idx, shardSrcJars := range shardSrcJarsList {
classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
nil, shardSrcJars, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
jars = append(jars, classes)
}
}
} else {
classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
jars = append(jars, classes)
}
if ctx.Failed() {
@@ -1552,16 +1552,6 @@
}
}
- // Automatic jarjar rules propagation
- if j.repackageJarjarRules != nil {
- repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", jarName).OutputPath
- TransformJarJar(ctx, repackagedJarjarFile, outputFile, j.repackageJarjarRules)
- outputFile = repackagedJarjarFile
- if ctx.Failed() {
- return
- }
- }
-
// Check package restrictions if necessary.
if len(j.properties.Permitted_packages) > 0 {
// Time stamp file created by the package check rule.
@@ -1730,22 +1720,23 @@
android.CollectDependencyAconfigFiles(ctx, &j.mergedAconfigFiles)
android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
- ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
- ResourceJars: android.PathsIfNonNil(j.resourceJar),
- AidlIncludeDirs: j.exportAidlIncludeDirs,
- SrcJarArgs: j.srcJarArgs,
- SrcJarDeps: j.srcJarDeps,
- TransitiveSrcFiles: j.transitiveSrcFiles,
- ExportedPlugins: j.exportedPluginJars,
- ExportedPluginClasses: j.exportedPluginClasses,
- ExportedPluginDisableTurbine: j.exportedDisableTurbine,
- JacocoReportClassesFile: j.jacocoReportClassesFile,
- StubsLinkType: j.stubsLinkType,
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
+ ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
+ ResourceJars: android.PathsIfNonNil(j.resourceJar),
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ SrcJarArgs: j.srcJarArgs,
+ SrcJarDeps: j.srcJarDeps,
+ TransitiveSrcFiles: j.transitiveSrcFiles,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ JacocoReportClassesFile: j.jacocoReportClassesFile,
+ StubsLinkType: j.stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
})
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1756,10 +1747,7 @@
return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs)
}
-func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
- transitiveUnconditionalExportedFlags := []*android.DepSet[android.Path]{}
- transitiveProguardFlags := []*android.DepSet[android.Path]{}
-
+func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) {
ctx.VisitDirectDeps(func(m android.Module) {
depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
depTag := ctx.OtherModuleDependencyTag(m)
@@ -1774,6 +1762,12 @@
}
})
+ return transitiveProguardFlags, transitiveUnconditionalExportedFlags
+}
+
+func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
+ transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
+
directUnconditionalExportedFlags := android.Paths{}
proguardFlagsForThisModule := android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)
exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files)
@@ -2296,6 +2290,7 @@
// annotation processor that generates API is incompatible with the turbine
// optimization.
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
case pluginTag:
if plugin, ok := module.(*Plugin); ok {
if plugin.pluginProperties.Processor_class != nil {
@@ -2354,6 +2349,8 @@
deps.staticJars = append(deps.staticJars, dep.Srcs()...)
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
}
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
} else {
switch tag {
case bootClasspathTag:
@@ -2551,7 +2548,7 @@
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 {
@@ -2679,6 +2676,16 @@
return result
}
+// Repackage the flags if the jarjar rule txt for the flags is generated
+func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.WritablePath, jarName, info string) android.WritablePath {
+ if j.repackageJarjarRules == nil {
+ return infile
+ }
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info+jarName)
+ TransformJarJar(ctx, repackagedJarjarFile, infile, j.repackageJarjarRules)
+ return repackagedJarjarFile
+}
+
func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
deps.processorPath = append(deps.processorPath, pluginJars...)
deps.processorClasses = append(deps.processorClasses, pluginClasses...)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 7c45d30..cc3da76 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -77,7 +77,7 @@
return javaSdkLibrarySdkMemberType
}
- return javaBootLibsSdkMemberType
+ return JavaBootLibsSdkMemberType
}
func (b bootclasspathFragmentContentDependencyTag) ExportMember() bool {
diff --git a/java/builder.go b/java/builder.go
index b07a622..5d84d0b 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -120,6 +120,8 @@
`--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED ` +
`--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ` +
`--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED ` +
+ `--add-exports=jdk.internal.opt/jdk.internal.opt=ALL-UNNAMED ` +
`-jar ${config.JavaKytheExtractorJar} ` +
`${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
diff --git a/java/config/config.go b/java/config/config.go
index 6a945ac..3159a05 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -52,6 +52,7 @@
"core-icu4j",
"core-oj",
"core-libart",
+ "wear-sdk.impl",
}
)
@@ -131,12 +132,7 @@
if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
return override
}
- switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN") {
- case "true":
- return "21"
- default:
- return "17"
- }
+ return "21"
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
diff --git a/java/dex.go b/java/dex.go
index 4474c63..6caaa7f 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -66,6 +66,12 @@
// If true, optimize for size by removing unused resources. Defaults to false.
Shrink_resources *bool
+ // If true, use optimized resource shrinking in R8, overriding the
+ // Shrink_resources setting. Defaults to false.
+ // Optimized shrinking means that R8 will trace and treeshake resources together with code
+ // and apply additional optimizations. This implies non final fields in the R classes.
+ Optimized_shrink_resources *bool
+
// Flags to pass to proguard.
Proguard_flags []string
@@ -105,6 +111,10 @@
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
+func (d *DexProperties) resourceShrinkingEnabled() bool {
+ return BoolDefault(d.Optimize.Optimized_shrink_resources, Bool(d.Optimize.Shrink_resources))
+}
+
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -351,10 +361,14 @@
r8Flags = append(r8Flags, "-ignorewarnings")
}
+ // resourcesInput is empty when we don't use resource shrinking, if on, pass these to R8
if d.resourcesInput.Valid() {
r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
r8Deps = append(r8Deps, d.resourcesInput.Path())
r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
+ if Bool(opt.Optimized_shrink_resources) {
+ r8Flags = append(r8Flags, "--optimized-resource-shrinking")
+ }
}
return r8Flags, r8Deps
diff --git a/java/droiddoc.go b/java/droiddoc.go
index df40d01..aec40b3 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -21,7 +21,6 @@
"github.com/google/blueprint/proptools"
- "android/soong/aconfig"
"android/soong/android"
"android/soong/java/config"
)
@@ -222,8 +221,6 @@
stubsSrcJar android.WritablePath
exportableStubsSrcJar android.WritablePath
-
- runtimeStubsSrcJar android.WritablePath
}
func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
@@ -416,7 +413,7 @@
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 "+
diff --git a/java/droidstubs.go b/java/droidstubs.go
index f4bcaca..02b81a4 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -227,7 +227,6 @@
type annotationFlagsParams struct {
migratingNullability bool
validatingNullability bool
- extractAnnotations bool
nullabilityWarningsFile android.WritablePath
annotationsZip android.WritablePath
}
@@ -243,19 +242,16 @@
stubConfig stubsCommandConfigParams
}
type stubsCommandConfigParams struct {
- stubsType StubsType
- javaVersion javaVersion
- deps deps
- checkApi bool
- generateStubs bool
- doApiLint bool
- doCheckReleased bool
- writeSdkValues bool
- migratingNullability bool
- validatingNullability bool
- annotationsEnabled bool
- apiLevelsAnnotationsEnabled bool
- extractAnnotations bool
+ stubsType StubsType
+ javaVersion javaVersion
+ deps deps
+ checkApi bool
+ generateStubs bool
+ doApiLint bool
+ doCheckReleased bool
+ writeSdkValues bool
+ migratingNullability bool
+ validatingNullability bool
}
// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
@@ -372,7 +368,7 @@
ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
}
if ret == nil && err == nil {
- err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
+ err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
}
return ret, err
}
@@ -482,34 +478,41 @@
}
func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
- if checkApi || String(d.properties.Api_filename) != "" {
- filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
- uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
- cmd.FlagWithOutput("--api ", uncheckedApiFile)
+ apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
+ uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
+ cmd.FlagWithOutput("--api ", uncheckedApiFile)
+ if checkApi || String(d.properties.Api_filename) != "" {
if stubsType == Everything {
d.apiFile = uncheckedApiFile
} else if stubsType == Exportable {
d.exportableApiFile = uncheckedApiFile
}
} else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
- // If check api is disabled then make the source file available for export.
- d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
+ if stubsType == Everything {
+ // If check api is disabled then make the source file available for export.
+ d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
+ } else if stubsType == Exportable {
+ d.exportableApiFile = uncheckedApiFile
+ }
}
+ removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
+ uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
+ cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
if checkApi || String(d.properties.Removed_api_filename) != "" {
- filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
- uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
- cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
-
if stubsType == Everything {
d.removedApiFile = uncheckedRemovedFile
} else if stubsType == Exportable {
d.exportableRemovedApiFile = uncheckedRemovedFile
}
} else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
- // If check api is disabled then make the source removed api file available for export.
- d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
+ if stubsType == Everything {
+ // If check api is disabled then make the source removed api file available for export.
+ d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
+ } else if stubsType == Exportable {
+ d.exportableRemovedApiFile = uncheckedRemovedFile
+ }
}
if stubsDir.Valid() {
@@ -525,30 +528,30 @@
}
func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
- cmd.Flag(config.MetalavaAnnotationsFlags)
+ if Bool(d.properties.Annotations_enabled) {
+ cmd.Flag(config.MetalavaAnnotationsFlags)
- if params.migratingNullability {
- previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
- cmd.FlagWithInput("--migrate-nullness ", previousApi)
- }
+ if params.migratingNullability {
+ previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
+ cmd.FlagWithInput("--migrate-nullness ", previousApi)
+ }
- if s := String(d.properties.Validate_nullability_from_list); s != "" {
- cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
- }
+ if s := String(d.properties.Validate_nullability_from_list); s != "" {
+ cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
+ }
- if params.validatingNullability {
- cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
- }
+ if params.validatingNullability {
+ cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
+ }
- if params.extractAnnotations {
cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
- }
- if len(d.properties.Merge_annotations_dirs) != 0 {
- d.mergeAnnoDirFlags(ctx, cmd)
- }
+ if len(d.properties.Merge_annotations_dirs) != 0 {
+ d.mergeAnnoDirFlags(ctx, cmd)
+ }
- cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
+ cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
+ }
}
func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
@@ -573,11 +576,9 @@
})
}
-func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params stubsCommandParams) {
+func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
var apiVersions android.Path
- stubsType := params.stubConfig.stubsType
- apiVersionsXml := params.apiVersionsXml
- if params.stubConfig.apiLevelsAnnotationsEnabled {
+ if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
apiVersions = apiVersionsXml
} else {
@@ -588,9 +589,7 @@
} else if stubsType == Exportable {
apiVersions = s.exportableArtifacts.apiVersionsXml
} else {
- // if the stubs type does not generate api-versions.xml file, default to using the
- // everything artifacts
- apiVersions = s.everythingArtifacts.apiVersionsXml
+ ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
}
} else {
ctx.PropertyErrorf("api_levels_module",
@@ -688,6 +687,23 @@
}
}
+func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
+ if len(d.Javadoc.properties.Out) > 0 {
+ ctx.PropertyErrorf("out", "out property may not be combined with check_api")
+ }
+
+ apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
+ removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
+
+ cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
+ cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
+
+ baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
+ if baselineFile.Valid() {
+ cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
+ }
+}
+
func metalavaUseRbe(ctx android.ModuleContext) bool {
return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
}
@@ -824,16 +840,17 @@
annotationParams := annotationFlagsParams{
migratingNullability: params.stubConfig.migratingNullability,
validatingNullability: params.stubConfig.validatingNullability,
- extractAnnotations: params.stubConfig.extractAnnotations,
nullabilityWarningsFile: params.nullabilityWarningsFile,
annotationsZip: params.annotationsZip,
}
- if params.stubConfig.annotationsEnabled {
- d.annotationsFlags(ctx, cmd, annotationParams)
- }
+ d.annotationsFlags(ctx, cmd, annotationParams)
d.inclusionAnnotationsFlags(ctx, cmd)
- d.apiLevelsAnnotationsFlags(ctx, cmd, params)
+ d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
+
+ if params.stubConfig.doCheckReleased {
+ d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
+ }
d.expandArgs(ctx, cmd)
@@ -863,13 +880,13 @@
d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
}
- if params.annotationsEnabled {
+ if Bool(d.properties.Annotations_enabled) {
if params.validatingNullability {
d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
}
d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
}
- if params.apiLevelsAnnotationsEnabled {
+ if Bool(d.properties.Api_levels_annotations_enabled) {
d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
}
@@ -993,25 +1010,12 @@
// Add "check released" options. (Detect incompatible API changes from the last public release)
if doCheckReleased {
- if len(d.Javadoc.properties.Out) > 0 {
- ctx.PropertyErrorf("out", "out property may not be combined with check_api")
- }
-
- apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
- removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
- updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
-
d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
-
- cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
- cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
-
if baselineFile.Valid() {
- cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
+ updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
}
-
// Note this string includes quote ($' ... '), which decodes the "\n"s.
msg := `$'\n******************************\n` +
`You have tried to change the API from what has been previously released in\n` +
@@ -1047,7 +1051,7 @@
optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
}
- if params.annotationsEnabled {
+ if Bool(d.properties.Annotations_enabled) {
if params.validatingNullability {
d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
@@ -1055,7 +1059,7 @@
d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
}
- if params.apiLevelsAnnotationsEnabled {
+ if Bool(d.properties.Api_levels_annotations_enabled) {
d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
}
@@ -1073,38 +1077,6 @@
d.optionalStubCmd(ctx, optionalCmdParams)
}
-// Sandbox rule for generating runtime stubs
-func (d *Droidstubs) runtimeStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
-
- // We are only interested in generating the stubs srcjar,
- // not other artifacts for the runtime stubs
- params.checkApi = false
- params.writeSdkValues = false
- params.validatingNullability = false
- params.extractAnnotations = false
- params.apiLevelsAnnotationsEnabled = false
-
- optionalCmdParams := stubsCommandParams{
- stubConfig: params,
- }
-
- d.Javadoc.runtimeStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
- optionalCmdParams.stubsSrcJar = d.Javadoc.runtimeStubsSrcJar
-
- // If aconfig_declarations property is not defined, all flagged apis symbols are stripped
- // as no aconfig flags are enabled. In such case, the runtime stubs are identical to the
- // exportable stubs, thus no additional metalava invocation is needed.
- if len(d.properties.Aconfig_declarations) == 0 {
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- Text("cp").Flag("-f").
- Input(d.exportableStubsSrcJar).Output(d.runtimeStubsSrcJar)
- rule.Build(fmt.Sprintf("metalava_%s", params.stubsType.String()), "metalava merged")
- } else {
- d.optionalStubCmd(ctx, optionalCmdParams)
- }
-}
-
func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
@@ -1176,8 +1148,6 @@
annotationsEnabled := Bool(d.properties.Annotations_enabled)
- extractAnnotations := annotationsEnabled
-
migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
String(d.properties.Validate_nullability_from_list) != "")
@@ -1185,40 +1155,27 @@
checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
- apiLevelsAnnotationsEnabled := proptools.Bool(d.properties.Api_levels_annotations_enabled)
-
stubCmdParams := stubsCommandConfigParams{
- javaVersion: javaVersion,
- deps: deps,
- checkApi: checkApi,
- generateStubs: generateStubs,
- doApiLint: doApiLint,
- doCheckReleased: doCheckReleased,
- writeSdkValues: writeSdkValues,
- migratingNullability: migratingNullability,
- validatingNullability: validatingNullability,
- annotationsEnabled: annotationsEnabled,
- apiLevelsAnnotationsEnabled: apiLevelsAnnotationsEnabled,
- extractAnnotations: extractAnnotations,
+ javaVersion: javaVersion,
+ deps: deps,
+ checkApi: checkApi,
+ generateStubs: generateStubs,
+ doApiLint: doApiLint,
+ doCheckReleased: doCheckReleased,
+ writeSdkValues: writeSdkValues,
+ migratingNullability: migratingNullability,
+ validatingNullability: validatingNullability,
}
stubCmdParams.stubsType = Everything
// Create default (i.e. "everything" stubs) rule for metalava
d.everythingStubCmd(ctx, stubCmdParams)
- // The module generates "exportable" stubs regardless of whether
+ // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
// aconfig_declarations property is defined or not. If the property is not defined, the module simply
// strips all flagged apis to generate the "exportable" stubs
stubCmdParams.stubsType = Exportable
d.exportableStubCmd(ctx, stubCmdParams)
- // "runtime" stubs do not generate any other artifacts than the stubs.
- // Therefore, metalava does not have to run for "runtime" configuration
- // when the module does not generate stubs.
- if stubCmdParams.generateStubs {
- stubCmdParams.stubsType = Runtime
- d.runtimeStubCmd(ctx, stubCmdParams)
- }
-
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
if len(d.Javadoc.properties.Out) > 0 {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index c86e8bf..8da695f 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -397,47 +397,23 @@
"bar",
],
}
- droidstubs {
- name: "baz",
- srcs: ["a/A.java"],
- api_surface: "public",
- check_api: {
- current: {
- api_file: "a/current.txt",
- removed_api_file: "a/removed.txt",
- }
- },
- }
`)
// Check that droidstubs depend on aconfig_declarations
android.AssertBoolEquals(t, "foo expected to depend on bar",
CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
- fooModule := result.ModuleForTests("foo", "android_common")
+ m := result.ModuleForTests("foo", "android_common")
android.AssertStringDoesContain(t, "foo generates revert annotations file",
- strings.Join(fooModule.AllOutputs(), ""), "revert-annotations-exportable.txt")
+ strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
// revert-annotations.txt passed to exportable stubs generation metalava command
- exportableManifest := fooModule.Output("metalava_exportable.sbox.textproto")
- exportableCmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, exportableManifest).Commands[0].Command)
- android.AssertStringDoesContain(t, "flagged api hide command not included", exportableCmdline, "revert-annotations-exportable.txt")
+ manifest := m.Output("metalava_exportable.sbox.textproto")
+ cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
+ android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
- strings.Join(fooModule.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
-
- // revert-annotations.txt passed to runtime stubs generation metalava command
- runtimeManifest := fooModule.Output("metalava_runtime.sbox.textproto")
- runtimeCmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, runtimeManifest).Commands[0].Command)
- android.AssertStringDoesContain(t, "flagged api hide command not included", runtimeCmdline, "revert-annotations-runtime.txt")
-
- android.AssertStringDoesContain(t, "foo generates runtime stubs jar",
- strings.Join(fooModule.AllOutputs(), ""), "runtime/foo-stubs.srcjar")
-
- // If aconfig_declarations property is not defined, the runtime stubs is a copy of the exportable stubs
- bazModule := result.ModuleForTests("baz", "android_common")
- bazRuntimeCmdline := bazModule.Rule("metalava_runtime").RuleParams.Command
- android.AssertStringDoesContain(t, "copy command should include the input stub", bazRuntimeCmdline, "exportable/baz-stubs.srcjar")
+ strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
}
func TestReleaseExportRuntimeApis(t *testing.T) {
diff --git a/java/java.go b/java/java.go
index 794020d..c5bdf9d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -21,10 +21,10 @@
import (
"fmt"
"path/filepath"
+ "slices"
"sort"
"strings"
- "android/soong/aconfig"
"android/soong/remoteexec"
"android/soong/testing"
@@ -83,8 +83,8 @@
// Register sdk member types.
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
android.RegisterSdkMemberType(javaLibsSdkMemberType)
- android.RegisterSdkMemberType(javaBootLibsSdkMemberType)
- android.RegisterSdkMemberType(javaSystemserverLibsSdkMemberType)
+ android.RegisterSdkMemberType(JavaBootLibsSdkMemberType)
+ android.RegisterSdkMemberType(JavaSystemserverLibsSdkMemberType)
android.RegisterSdkMemberType(javaTestSdkMemberType)
}
@@ -155,7 +155,7 @@
// either java_libs, or java_header_libs would end up exporting more information than was strictly
// necessary. The java_boot_libs property to allow those modules to be exported as part of the
// sdk/module_exports without exposing any unnecessary information.
- javaBootLibsSdkMemberType = &librarySdkMemberType{
+ JavaBootLibsSdkMemberType = &librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_boot_libs",
SupportsSdk: true,
@@ -194,7 +194,7 @@
// either java_libs, or java_header_libs would end up exporting more information than was strictly
// necessary. The java_systemserver_libs property to allow those modules to be exported as part of
// the sdk/module_exports without exposing any unnecessary information.
- javaSystemserverLibsSdkMemberType = &librarySdkMemberType{
+ JavaSystemserverLibsSdkMemberType = &librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_systemserver_libs",
SupportsSdk: true,
@@ -310,6 +310,10 @@
// implementation jars. If the provider is set by java_sdk_library, the link type is "unknown"
// and selection between the stub jar vs implementation jar is deferred to SdkLibrary.sdkJars(...)
StubsLinkType StubsLinkType
+
+ // AconfigIntermediateCacheOutputPaths is a path to the cache files collected from the
+ // java_aconfig_library modules that are statically linked to this module.
+ AconfigIntermediateCacheOutputPaths android.Paths
}
var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
@@ -346,6 +350,12 @@
return j.kytheFiles
}
+func (d dependencyTag) PropagateAconfigValidation() bool {
+ return d.static
+}
+
+var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
+
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
@@ -355,6 +365,8 @@
// 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 +412,7 @@
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}
@@ -680,10 +692,11 @@
return true
}
- // Store uncompressed dex files that are preopted on /system.
- if !dexpreopter.dexpreoptDisabled(ctx, libName) && (ctx.Host() || !dexpreopter.odexOnSystemOther(ctx, libName, dexpreopter.installPath)) {
+ // Store uncompressed dex files that are preopted on /system or /system_other.
+ if !dexpreopter.dexpreoptDisabled(ctx, libName) {
return true
}
+
if ctx.Config().UncompressPrivAppDex() &&
inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules()) {
return true
@@ -889,7 +902,7 @@
}
}
- j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+ j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
proguardSpecInfo := j.collectProguardSpecInfo(ctx)
android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
@@ -1425,6 +1438,14 @@
j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
+ InstalledFiles: j.data,
+ OutputFile: j.outputFile,
+ TestConfig: j.testConfig,
+ RequiredModuleNames: j.RequiredModuleNames(),
+ TestSuites: j.testProperties.Test_suites,
+ IsHost: true,
+ })
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1686,7 +1707,7 @@
}
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
+ j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
if ctx.Arch().ArchType == android.Common {
// Compile the jar
@@ -2172,7 +2193,7 @@
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 "+
@@ -2325,6 +2346,9 @@
// List of shared java libs that this module has dependencies to
Libs []string
+ // List of static java libs that this module has dependencies to
+ Static_libs []string
+
// List of files to remove from the jar file(s)
Exclude_files []string
@@ -2377,9 +2401,10 @@
dexJarFileErr error
dexJarInstallFile android.Path
- combinedClasspathFile android.Path
- classLoaderContexts dexpreopt.ClassLoaderContextMap
- exportAidlIncludeDirs android.Paths
+ combinedImplementationFile android.Path
+ combinedHeaderFile android.Path
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
+ exportAidlIncludeDirs android.Paths
hideApexVariantFromMake bool
@@ -2463,6 +2488,7 @@
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
sdkDeps(ctx, android.SdkContext(j), j.dexer)
@@ -2492,23 +2518,13 @@
func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.commonBuildActions(ctx)
- jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
-
- jarName := j.Stem() + ".jar"
- outputFile := android.PathForModuleOut(ctx, "combined", jarName)
- TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
- false, j.properties.Exclude_files, j.properties.Exclude_dirs)
- if Bool(j.properties.Jetifier) {
- inputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
- TransformJetifier(ctx, outputFile, inputFile)
- }
- j.combinedClasspathFile = outputFile
j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
var flags javaBuilderFlags
j.collectTransitiveHeaderJars(ctx)
+ var staticJars android.Paths
+ var staticHeaderJars android.Paths
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
@@ -2518,6 +2534,8 @@
flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
case staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
+ staticJars = append(staticJars, dep.ImplementationAndResourcesJars...)
+ staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
}
@@ -2531,6 +2549,46 @@
addCLCFromDep(ctx, module, j.classLoaderContexts)
})
+ jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
+ jarName := j.Stem() + ".jar"
+
+ // Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output
+ // file of the module to be named jarName.
+ outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+ implementationJars := append(slices.Clone(jars), staticJars...)
+ TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
+ false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+
+ // If no dependencies have separate header jars then there is no need to create a separate
+ // header jar for this module.
+ reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars)
+
+ var headerOutputFile android.WritablePath
+ if reuseImplementationJarAsHeaderJar {
+ headerOutputFile = outputFile
+ } else {
+ headerJars := append(slices.Clone(jars), staticHeaderJars...)
+ headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{},
+ false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+ }
+
+ if Bool(j.properties.Jetifier) {
+ inputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
+ TransformJetifier(ctx, outputFile, inputFile)
+
+ if !reuseImplementationJarAsHeaderJar {
+ headerInputFile := headerOutputFile
+ headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName)
+ TransformJetifier(ctx, headerOutputFile, headerInputFile)
+ } else {
+ headerOutputFile = outputFile
+ }
+ }
+ j.combinedHeaderFile = headerOutputFile
+ j.combinedImplementationFile = outputFile
+
j.maybeInstall(ctx, jarName, outputFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
@@ -2614,11 +2672,11 @@
}
android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.combinedClasspathFile),
+ HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile),
- ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
+ ImplementationJars: android.PathsIfNonNil(j.combinedImplementationFile),
AidlIncludeDirs: j.exportAidlIncludeDirs,
StubsLinkType: j.stubsLinkType,
// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
@@ -2646,7 +2704,7 @@
func (j *Import) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "", ".jar":
- return android.Paths{j.combinedClasspathFile}, nil
+ return android.Paths{j.combinedImplementationFile}, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -2655,17 +2713,11 @@
var _ android.OutputFileProducer = (*Import)(nil)
func (j *Import) HeaderJars() android.Paths {
- if j.combinedClasspathFile == nil {
- return nil
- }
- return android.Paths{j.combinedClasspathFile}
+ return android.PathsIfNonNil(j.combinedHeaderFile)
}
func (j *Import) ImplementationAndResourcesJars() android.Paths {
- if j.combinedClasspathFile == nil {
- return nil
- }
- return android.Paths{j.combinedClasspathFile}
+ return android.PathsIfNonNil(j.combinedImplementationFile)
}
func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
@@ -2997,7 +3049,7 @@
module.AddProperties(
&CommonProperties{},
&DeviceProperties{},
- &OverridableDeviceProperties{},
+ &OverridableProperties{},
&DexProperties{},
&DexpreoptProperties{},
&android.ProtoProperties{},
diff --git a/java/java_test.go b/java/java_test.go
index 2f3ccb9..2676aa5 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -588,10 +588,11 @@
javac := fooModule.Rule("javac")
combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
barModule := ctx.ModuleForTests("bar", "android_common")
- barJar := barModule.Rule("combineJar").Output
+ barJar := barModule.Output("combined/bar.jar").Output
bazModule := ctx.ModuleForTests("baz", "android_common")
bazJar := bazModule.Rule("combineJar").Output
- sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
+ sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").
+ Output("combined/sdklib.stubs.jar").Output
fooLibrary := fooModule.Module().(*Library)
assertDeepEquals(t, "foo unique sources incorrect",
@@ -1035,7 +1036,7 @@
}
}
-func TestJavaLibrary(t *testing.T) {
+func TestJavaLibraryOutputFiles(t *testing.T) {
testJavaWithFS(t, "", map[string][]byte{
"libcore/Android.bp": []byte(`
java_library {
@@ -1052,7 +1053,7 @@
})
}
-func TestJavaImport(t *testing.T) {
+func TestJavaImportOutputFiles(t *testing.T) {
testJavaWithFS(t, "", map[string][]byte{
"libcore/Android.bp": []byte(`
java_import {
@@ -1068,6 +1069,85 @@
})
}
+func TestJavaImport(t *testing.T) {
+ bp := `
+ java_library {
+ name: "source_library",
+ srcs: ["source.java"],
+ }
+
+ java_import {
+ name: "import_with_no_deps",
+ jars: ["no_deps.jar"],
+ }
+
+ java_import {
+ name: "import_with_source_deps",
+ jars: ["source_deps.jar"],
+ static_libs: ["source_library"],
+ }
+
+ java_import {
+ name: "import_with_import_deps",
+ jars: ["import_deps.jar"],
+ static_libs: ["import_with_no_deps"],
+ }
+ `
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ source := ctx.ModuleForTests("source_library", "android_common")
+ sourceJar := source.Output("javac/source_library.jar")
+ sourceHeaderJar := source.Output("turbine-combined/source_library.jar")
+ sourceJavaInfo, _ := android.SingletonModuleProvider(ctx, source.Module(), JavaInfoProvider)
+
+ // The source library produces separate implementation and header jars
+ android.AssertPathsRelativeToTopEquals(t, "source library implementation jar",
+ []string{sourceJar.Output.String()}, sourceJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "source library header jar",
+ []string{sourceHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars)
+
+ importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common")
+ importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar")
+ importWithNoDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
+
+ // An import with no deps produces a single jar used as both the header and implementation jar.
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar",
+ []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps header jar",
+ []string{importWithNoDepsJar.Output.String()}, importWithNoDepsJavaInfo.HeaderJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps combined inputs",
+ []string{"no_deps.jar"}, importWithNoDepsJar.Inputs)
+
+ importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common")
+ importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar")
+ importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar")
+ importWithSourceDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
+
+ // An import with source deps produces separate header and implementation jars.
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar",
+ []string{importWithSourceDepsJar.Output.String()}, importWithSourceDepsJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps header jar",
+ []string{importWithSourceDepsHeaderJar.Output.String()}, importWithSourceDepsJavaInfo.HeaderJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps combined implementation jar inputs",
+ []string{"source_deps.jar", sourceJar.Output.String()}, importWithSourceDepsJar.Inputs)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps combined header jar inputs",
+ []string{"source_deps.jar", sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs)
+
+ importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common")
+ importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar")
+ importWithImportDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
+
+ // An import with only import deps produces a single jar used as both the header and implementation jar.
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar",
+ []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.ImplementationAndResourcesJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps header jar",
+ []string{importWithImportDepsJar.Output.String()}, importWithImportDepsJavaInfo.HeaderJars)
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps combined implementation jar inputs",
+ []string{"import_deps.jar", importWithNoDepsJar.Output.String()}, importWithImportDepsJar.Inputs)
+}
+
var compilerFlagsTestCases = []struct {
in string
out bool
@@ -2643,6 +2723,70 @@
}
}
+func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) {
+ bp := `
+ // multiple variations of platform_compat_config
+ // source
+ platform_compat_config {
+ name: "myconfig",
+ }
+ // prebuilt "v1"
+ prebuilt_platform_compat_config {
+ name: "myconfig",
+ metadata: "myconfig.xml",
+ }
+ // prebuilt "v2"
+ prebuilt_platform_compat_config {
+ name: "myconfig.v2",
+ source_module_name: "myconfig", // without source_module_name, the singleton will merge two .xml files
+ metadata: "myconfig.v2.xml",
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedPlatformCompatConfigXml string
+ }{
+ {
+ desc: "Source platform_compat_config is selected using apex_contributions",
+ selectedDependencyName: "myconfig",
+ expectedPlatformCompatConfigXml: "out/soong/.intermediates/myconfig/android_common/myconfig_meta.xml",
+ },
+ {
+ desc: "Prebuilt platform_compat_config v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_myconfig",
+ expectedPlatformCompatConfigXml: "myconfig.xml",
+ },
+ {
+ desc: "Prebuilt platform_compat_config v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_myconfig.v2",
+ expectedPlatformCompatConfigXml: "myconfig.v2.xml",
+ },
+ }
+
+ for _, tc := range testCases {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithPlatformCompatConfig,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ mergedGlobalConfig := ctx.SingletonForTests("platform_compat_config_singleton").Output("compat_config/merged_compat_config.xml")
+ android.AssertIntEquals(t, "The merged compat config file should only have a single dependency", 1, len(mergedGlobalConfig.Implicits))
+ android.AssertStringEquals(t, "The merged compat config file is missing the appropriate platform compat config", mergedGlobalConfig.Implicits[0].String(), tc.expectedPlatformCompatConfigXml)
+ }
+}
+
func TestApiLibraryAconfigDeclarations(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
@@ -2693,3 +2837,38 @@
cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
}
+
+func TestJavaLibHostWithStem(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library_host {
+ name: "foo",
+ srcs: ["a.java"],
+ stem: "foo-new",
+ }
+ `)
+
+ buildOS := ctx.Config().BuildOS.String()
+ foo := ctx.ModuleForTests("foo", buildOS+"_common")
+
+ outputs := fmt.Sprint(foo.AllOutputs())
+ if !strings.Contains(outputs, "foo-new.jar") {
+ t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
+ }
+}
+
+func TestJavaLibWithStem(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ stem: "foo-new",
+ }
+ `)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ outputs := fmt.Sprint(foo.AllOutputs())
+ if !strings.Contains(outputs, "foo-new.jar") {
+ t.Errorf("Module output does not contain expected jar %s", "foo-new.jar")
+ }
+}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 2197304..2fc6c02 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -20,6 +20,7 @@
"android/soong/android"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -184,6 +185,11 @@
type prebuiltCompatConfigProperties struct {
Metadata *string `android:"path"`
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
func (module *prebuiltCompatConfigModule) Prebuilt() *android.Prebuilt {
@@ -198,6 +204,10 @@
return module.metadataFile
}
+func (module *prebuiltCompatConfigModule) BaseModuleName() string {
+ return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
+}
+
var _ platformCompatConfigMetadataProvider = (*prebuiltCompatConfigModule)(nil)
func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 94e9c6c..6a79e58 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -158,6 +158,21 @@
mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
}
+func createCombinedApiFilegroupModule(mctx android.LoadHookContext, name string, srcs []string) {
+ filegroupProps := struct {
+ Name *string
+ Srcs []string
+ }{}
+ filegroupProps.Name = proptools.StringPtr(name)
+
+ var transformedSrcs []string
+ for _, src := range srcs {
+ transformedSrcs = append(transformedSrcs, ":"+src)
+ }
+ filegroupProps.Srcs = transformedSrcs
+ mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
+}
+
func createLatestApiModuleExtensionVersionFile(mctx android.LoadHookContext, name string, version string) {
genruleProps := struct {
Name *string
@@ -252,6 +267,10 @@
return module + ".api." + scope + "." + version
}
+func PrebuiltApiCombinedModuleName(module, scope, version string) string {
+ return module + ".api.combined." + scope + "." + version
+}
+
func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
// <apiver>/<scope>/api/<module>.txt
apiLevelFiles := globApiDirs(mctx, p, "api/*.txt")
@@ -307,7 +326,9 @@
}
// Sort the keys in order to make build.ninja stable
- for _, k := range android.SortedKeys(latest) {
+ sortedLatestKeys := android.SortedKeys(latest)
+
+ for _, k := range sortedLatestKeys {
info := latest[k]
name := PrebuiltApiModuleName(info.module, info.scope, "latest")
latestExtensionVersionModuleName := PrebuiltApiModuleName(info.module, info.scope, "latest.extension_version")
@@ -333,11 +354,25 @@
}
}
// Create empty incompatibilities files for remaining modules
- for _, k := range android.SortedKeys(latest) {
+ // If the incompatibility module has been created, create a corresponding combined module
+ for _, k := range sortedLatestKeys {
if _, ok := incompatibilities[k]; !ok {
createEmptyFile(mctx, PrebuiltApiModuleName(latest[k].module+"-incompatibilities", latest[k].scope, "latest"))
}
}
+
+ // Create combined latest api and removed api files modules.
+ // The combined modules list all api files of the api scope and its subset api scopes.
+ for _, k := range sortedLatestKeys {
+ info := latest[k]
+ name := PrebuiltApiCombinedModuleName(info.module, info.scope, "latest")
+
+ var srcs []string
+ currentApiScope := scopeByName[info.scope]
+ srcs = append(srcs, PrebuiltApiModuleName(info.module, currentApiScope.name, "latest"))
+
+ createCombinedApiFilegroupModule(mctx, name, srcs)
+ }
}
func createPrebuiltApiModules(mctx android.LoadHookContext) {
diff --git a/java/rro.go b/java/rro.go
index 3e0f8e9..72170fc 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -122,6 +122,10 @@
ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
+
+ for _, aconfig_declaration := range r.aaptProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -151,6 +155,7 @@
sdkContext: r,
enforceDefaultTargetSdkVersion: false,
extraLinkFlags: aaptLinkFlags,
+ aconfigTextFiles: getAconfigFilePaths(ctx),
},
)
diff --git a/java/rro_test.go b/java/rro_test.go
index c4a4d04..d697ec6 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -405,3 +405,49 @@
android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir)
}
}
+
+func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ runtime_resource_overlay {
+ name: "foo",
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ "baz",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+
+ // runtime_resource_overlay module depends on aconfig_declarations listed in flags_packages
+ android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
+
+ android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
+
+ aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+}
diff --git a/java/sdk.go b/java/sdk.go
index 3591ccd..d972c19 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -31,7 +31,6 @@
var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
-var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
func UseApiFingerprint(ctx android.BaseModuleContext) (useApiFingerprint bool, fingerprintSdkVersion string, fingerprintDeps android.OutputPath) {
if ctx.Config().UnbundledBuild() && !ctx.Config().AlwaysUsePrebuiltSdks() {
@@ -45,8 +44,8 @@
useApiFingerprint = apiFingerprintTrue || dessertShaIsSet
if apiFingerprintTrue {
- fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
- fingerprintDeps = ApiFingerprintPath(ctx)
+ fingerprintSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", android.ApiFingerprintPath(ctx).String())
+ fingerprintDeps = android.ApiFingerprintPath(ctx)
}
if dessertShaIsSet {
fingerprintSdkVersion = ctx.Config().Getenv("UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA")
@@ -337,7 +336,7 @@
// Create api_fingerprint.txt
func createAPIFingerprint(ctx android.SingletonContext) {
- out := ApiFingerprintPath(ctx)
+ out := android.ApiFingerprintPath(ctx)
rule := android.NewRuleBuilder(pctx, ctx)
@@ -378,17 +377,11 @@
rule.Build("api_fingerprint", "generate api_fingerprint.txt")
}
-func ApiFingerprintPath(ctx android.PathContext) android.OutputPath {
- return ctx.Config().Once(apiFingerprintPathKey, func() interface{} {
- return android.PathForOutput(ctx, "api_fingerprint.txt")
- }).(android.OutputPath)
-}
-
func sdkMakeVars(ctx android.MakeVarsContext) {
if ctx.Config().AlwaysUsePrebuiltSdks() {
return
}
ctx.Strict("FRAMEWORK_AIDL", sdkFrameworkAidlPath(ctx).String())
- ctx.Strict("API_FINGERPRINT", ApiFingerprintPath(ctx).String())
+ ctx.Strict("API_FINGERPRINT", android.ApiFingerprintPath(ctx).String())
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index cdd0448..5ddc675 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -30,6 +30,7 @@
"android/soong/android"
"android/soong/dexpreopt"
+ "android/soong/etc"
)
const (
@@ -1672,12 +1673,16 @@
return PrebuiltApiModuleName(name, apiScope.name, "latest")
}
+func latestPrebuiltApiCombinedModuleName(name string, apiScope *apiScope) string {
+ return PrebuiltApiCombinedModuleName(name, apiScope.name, "latest")
+}
+
func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
return ":" + module.latestApiModuleName(apiScope)
}
func (module *SdkLibrary) latestApiModuleName(apiScope *apiScope) string {
- return latestPrebuiltApiModuleName(module.distStem(), apiScope)
+ return latestPrebuiltApiCombinedModuleName(module.distStem(), apiScope)
}
func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string {
@@ -1685,7 +1690,7 @@
}
func (module *SdkLibrary) latestRemovedApiModuleName(apiScope *apiScope) string {
- return latestPrebuiltApiModuleName(module.distStem()+"-removed", apiScope)
+ return latestPrebuiltApiCombinedModuleName(module.distStem()+"-removed", apiScope)
}
func (module *SdkLibrary) latestIncompatibilitiesFilegroupName(apiScope *apiScope) string {
@@ -1993,20 +1998,25 @@
if !Bool(module.sdkLibraryProperties.No_dist) {
// Dist the api txt and removed api txt artifacts for sdk builds.
distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
+ stubsTypeTagPrefix := ""
+ if mctx.Config().ReleaseHiddenApiExportableStubs() {
+ stubsTypeTagPrefix = ".exportable"
+ }
for _, p := range []struct {
tag string
pattern string
}{
// "exportable" api files are copied to the dist directory instead of the
- // "everything" api files.
- {tag: ".exportable.api.txt", pattern: "%s.txt"},
- {tag: ".exportable.removed-api.txt", pattern: "%s-removed.txt"},
+ // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
+ // is set. Otherwise, the "everything" api files are copied to the dist directory.
+ {tag: "%s.api.txt", pattern: "%s.txt"},
+ {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
} {
props.Dists = append(props.Dists, android.Dist{
Targets: []string{"sdk", "win_sdk"},
Dir: distDir,
Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
- Tag: proptools.StringPtr(p.tag),
+ Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
})
}
}
@@ -2079,7 +2089,7 @@
mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
-func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
props := libraryProperties{}
props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
@@ -2095,13 +2105,22 @@
}
props.Compile_dex = compileDex
+ if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
+ props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+ props.Dist.Tag = proptools.StringPtr(".jar")
+ }
+
return props
}
func (module *SdkLibrary) createTopLevelStubsLibrary(
mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
- props := module.topLevelStubsLibraryProps(mctx, apiScope)
+ // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
+ doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
// Add the stub compiling java_library/java_api_library as static lib based on build config
@@ -2117,18 +2136,11 @@
func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
mctx android.DefaultableHookContext, apiScope *apiScope) {
- props := module.topLevelStubsLibraryProps(mctx, apiScope)
+ // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
+ doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
- // Dist the class jar artifact for sdk builds.
- // "exportable" stubs are copied to dist for sdk builds instead of the "everything" stubs.
- if !Bool(module.sdkLibraryProperties.No_dist) {
- props.Dist.Targets = []string{"sdk", "win_sdk"}
- props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
- props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
- props.Dist.Tag = proptools.StringPtr(".jar")
- }
-
staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
props.Static_libs = append(props.Static_libs, staticLib)
@@ -3163,10 +3175,12 @@
}
// from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) OutputFile() android.OutputPath {
- return module.outputFilePath
+func (module *sdkLibraryXml) OutputFiles(tag string) (android.Paths, error) {
+ return android.OutputPaths{module.outputFilePath}.Paths(), nil
}
+var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
+
// from android.ApexModule
func (module *sdkLibraryXml) AvailableFor(what string) bool {
return true
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 93ef408..a19d382 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -139,10 +139,10 @@
exportedComponentsInfo, _ := android.SingletonModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
expectedFooExportedComponents := []string{
- "foo-removed.api.public.latest",
- "foo-removed.api.system.latest",
- "foo.api.public.latest",
- "foo.api.system.latest",
+ "foo-removed.api.combined.public.latest",
+ "foo-removed.api.combined.system.latest",
+ "foo.api.combined.public.latest",
+ "foo.api.combined.system.latest",
"foo.stubs",
"foo.stubs.exportable",
"foo.stubs.exportable.system",
@@ -556,8 +556,8 @@
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
`dex2oatd`,
- `sdklib-removed.api.public.latest`,
- `sdklib.api.public.latest`,
+ `sdklib-removed.api.combined.public.latest`,
+ `sdklib.api.combined.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
`sdklib.stubs.exportable`,
@@ -960,8 +960,8 @@
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
`dex2oatd`,
`prebuilt_sdklib`,
- `sdklib-removed.api.public.latest`,
- `sdklib.api.public.latest`,
+ `sdklib-removed.api.combined.public.latest`,
+ `sdklib.api.combined.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
`sdklib.stubs.exportable`,
@@ -1039,8 +1039,8 @@
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
`prebuilt_sdklib`,
- `sdklib-removed.api.public.latest`,
- `sdklib.api.public.latest`,
+ `sdklib-removed.api.combined.public.latest`,
+ `sdklib.api.combined.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
`sdklib.stubs.exportable`,
@@ -1239,7 +1239,6 @@
libraryType string
fromPartition string
toPartition string
- enforceVendorInterface bool
enforceProductInterface bool
enforceJavaSdkLibraryCheck bool
allowList []string
@@ -1274,9 +1273,6 @@
android.FixtureWithRootAndroidBp(bpFile),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
- if info.enforceVendorInterface {
- variables.DeviceVndkVersion = proptools.StringPtr("current")
- }
variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
variables.InterPartitionJavaLibraryAllowList = info.allowList
}),
@@ -1304,7 +1300,6 @@
libraryType: "java_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: false,
}, "")
@@ -1313,7 +1308,6 @@
libraryType: "java_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: false,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1322,7 +1316,6 @@
libraryType: "java_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, errorMessage)
@@ -1331,7 +1324,6 @@
libraryType: "java_library",
fromPartition: "vendor",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, errorMessage)
@@ -1340,7 +1332,6 @@
libraryType: "java_library",
fromPartition: "vendor",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
allowList: []string{"bar"},
@@ -1350,7 +1341,6 @@
libraryType: "java_library",
fromPartition: "vendor",
toPartition: "product",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, errorMessage)
@@ -1359,7 +1349,6 @@
libraryType: "java_sdk_library",
fromPartition: "product",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1368,7 +1357,6 @@
libraryType: "java_sdk_library",
fromPartition: "vendor",
toPartition: "system",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1377,7 +1365,6 @@
libraryType: "java_sdk_library",
fromPartition: "vendor",
toPartition: "product",
- enforceVendorInterface: true,
enforceProductInterface: true,
enforceJavaSdkLibraryCheck: true,
}, "")
@@ -1393,6 +1380,11 @@
"sdklib_group_foo",
"sdklib_owner_foo",
"foo"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib_no_group",
diff --git a/java/system_modules.go b/java/system_modules.go
index 92e31cd..8e2d5d8 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -64,6 +64,7 @@
// useful on Android, and (b) it causes errors with later versions of jlink
// when the jdk.internal.module is absent from java.base (as it is here).
` --disable-plugin system-modules && ` +
+ `rm -rf ${workDir} && ` +
`cp ${config.JrtFsJar} ${outDir}/lib/`,
CommandDeps: []string{
"${moduleInfoJavaPath}",
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 59c5466..b291e70 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -189,7 +189,7 @@
return javaSdkLibrarySdkMemberType
}
- return javaSystemserverLibsSdkMemberType
+ return JavaSystemserverLibsSdkMemberType
}
func (b systemServerClasspathFragmentContentDependencyTag) ExportMember() bool {
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index 78b62d9..98aa408 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -89,7 +89,7 @@
output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
builder := android.NewRuleBuilder(pctx, ctx)
- BuildLinkerConfig(ctx, builder, input, nil, output)
+ BuildLinkerConfig(ctx, builder, input, nil, nil, output)
builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
l.outputFilePath = output
@@ -101,7 +101,7 @@
}
func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder,
- input android.Path, otherModules []android.Module, output android.OutputPath) {
+ input android.Path, provideModules []android.Module, requireModules []android.Module, output android.OutputPath) {
// First, convert the input json to protobuf format
interimOutput := android.PathForModuleOut(ctx, "temp.pb")
@@ -111,9 +111,9 @@
FlagWithInput("-s ", input).
FlagWithOutput("-o ", interimOutput)
- // Secondly, if there's provideLibs gathered from otherModules, append them
+ // Secondly, if there's provideLibs gathered from provideModules, append them
var provideLibs []string
- for _, m := range otherModules {
+ for _, m := range provideModules {
if c, ok := m.(*cc.Module); ok && cc.IsStubTarget(c) {
for _, ps := range c.PackagingSpecs() {
provideLibs = append(provideLibs, ps.FileName())
@@ -122,18 +122,45 @@
}
provideLibs = android.FirstUniqueStrings(provideLibs)
sort.Strings(provideLibs)
+
+ var requireLibs []string
+ for _, m := range requireModules {
+ if c, ok := m.(*cc.Module); ok && c.HasStubsVariants() && !c.Host() {
+ requireLibs = append(requireLibs, c.ImplementationModuleName(ctx)+".so")
+ }
+ }
+
+ requireLibs = android.FirstUniqueStrings(requireLibs)
+ sort.Strings(requireLibs)
+
if len(provideLibs) > 0 {
+ prevOutput := interimOutput
+ interimOutput = android.PathForModuleOut(ctx, "temp_provideLibs.pb")
builder.Command().
BuiltTool("conv_linker_config").
Flag("append").
- FlagWithInput("-s ", interimOutput).
- FlagWithOutput("-o ", output).
+ FlagWithInput("-s ", prevOutput).
+ FlagWithOutput("-o ", interimOutput).
FlagWithArg("--key ", "provideLibs").
FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(provideLibs, " ")))
- } else {
- // If nothing to add, just cp to the final output
- builder.Command().Text("cp").Input(interimOutput).Output(output)
+ builder.Temporary(prevOutput)
}
+ if len(requireLibs) > 0 {
+ prevOutput := interimOutput
+ interimOutput = android.PathForModuleOut(ctx, "temp_requireLibs.pb")
+ builder.Command().
+ BuiltTool("conv_linker_config").
+ Flag("append").
+ FlagWithInput("-s ", prevOutput).
+ FlagWithOutput("-o ", interimOutput).
+ FlagWithArg("--key ", "requireLibs").
+ FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(requireLibs, " ")))
+ builder.Temporary(prevOutput)
+ }
+
+ // cp to the final output
+ builder.Command().Text("cp").Input(interimOutput).Output(output)
+
builder.Temporary(interimOutput)
builder.DeleteTemporaryFiles()
}
diff --git a/phony/phony.go b/phony/phony.go
index b8dbd00..5469238 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -23,10 +23,17 @@
)
func init() {
- android.RegisterModuleType("phony", PhonyFactory)
- android.RegisterModuleType("phony_rule", PhonyRuleFactory)
+ registerPhonyModuleTypes(android.InitRegistrationContext)
}
+func registerPhonyModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("phony", PhonyFactory)
+ ctx.RegisterModuleType("phony_rule", PhonyRuleFactory)
+ ctx.RegisterModuleType("phony_rule_defaults", PhonyRuleDefaultsFactory)
+}
+
+var PrepareForTestWithPhony = android.FixtureRegisterWithContext(registerPhonyModuleTypes)
+
type phony struct {
android.ModuleBase
requiredModuleNames []string
@@ -79,6 +86,7 @@
type PhonyRule struct {
android.ModuleBase
+ android.DefaultableModuleBase
properties PhonyProperties
}
@@ -96,6 +104,7 @@
module := &PhonyRule{}
android.InitAndroidModule(module)
module.AddProperties(&module.properties)
+ android.InitDefaultableModule(module)
return module
}
@@ -113,3 +122,45 @@
},
}
}
+
+// PhonyRuleDefaults
+type PhonyRuleDefaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+// phony_rule_defaults provides a set of properties that can be inherited by other phony_rules.
+//
+// A module can use the properties from a phony_rule_defaults module using `defaults: ["defaults_module_name"]`. Each
+// property in the defaults module that exists in the depending module will be prepended to the depending module's
+// value for that property.
+//
+// Example:
+//
+// phony_rule_defaults {
+// name: "add_module1_defaults",
+// phony_deps: [
+// "module1",
+// ],
+// }
+//
+// phony_rule {
+// name: "example",
+// defaults: ["add_module1_defaults"],
+// }
+//
+// is functionally identical to:
+//
+// phony_rule {
+// name: "example",
+// phony_deps: [
+// "module1",
+// ],
+// }
+func PhonyRuleDefaultsFactory() android.Module {
+ module := &PhonyRuleDefaults{}
+ module.AddProperties(&PhonyProperties{})
+ android.InitDefaultsModule(module)
+
+ return module
+}
diff --git a/python/python.go b/python/python.go
index d3cbd76..2b1974e 100644
--- a/python/python.go
+++ b/python/python.go
@@ -545,7 +545,6 @@
var stagedProtoSrcs android.Paths
for _, srcFile := range protoSrcs {
stagedProtoSrc := pkgPathStagingDir.Join(ctx, pkgPath, srcFile.Rel())
- rule.Command().Text("mkdir -p").Flag(filepath.Base(stagedProtoSrc.String()))
rule.Command().Text("cp -f").Input(srcFile).Output(stagedProtoSrc)
stagedProtoSrcs = append(stagedProtoSrcs, stagedProtoSrc)
}
diff --git a/python/scripts/precompile_python.py b/python/scripts/precompile_python.py
index aa1a5df..07b8fe9 100644
--- a/python/scripts/precompile_python.py
+++ b/python/scripts/precompile_python.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import print_function
import argparse
import py_compile
import os
@@ -63,11 +64,23 @@
parser.add_argument('dst_zip')
args = parser.parse_args()
+ errors = []
with open(args.dst_zip, 'wb') as outf, open(args.src_zip, 'rb') as inf:
with zipfile.ZipFile(outf, mode='w') as outzip, zipfile.ZipFile(inf, mode='r') as inzip:
for name in inzip.namelist():
with inzip.open(name, mode='r') as inzipf:
- process_one_file(name, inzipf, outzip)
+ try:
+ process_one_file(name, inzipf, outzip)
+ except py_compile.PyCompileError as e:
+ errors.append(e)
+
+ if errors:
+ for i, error in enumerate(errors):
+ # Print an empty line in between each error
+ if i > 0:
+ print(file=sys.stderr)
+ print(str(error).strip(), file=sys.stderr)
+ sys.exit(1)
if __name__ == "__main__":
diff --git a/rust/Android.bp b/rust/Android.bp
index 637042d..c5e94a0 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -62,7 +62,6 @@
"sanitize_test.go",
"source_provider_test.go",
"test_test.go",
- "vendor_snapshot_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/rust/builder.go b/rust/builder.go
index c855cfb..2f5e12a 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -32,7 +32,7 @@
"-C linker=${config.RustLinker} " +
"-C link-args=\"${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
"--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
- " && grep \"^$out:\" $out.d.raw > $out.d",
+ " && grep ^$out: $out.d.raw > $out.d",
CommandDeps: []string{"$rustcCmd"},
// Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
// Rustc emits unneeded dependency lines for the .d and input .rs files.
diff --git a/rust/compiler.go b/rust/compiler.go
index c1bdbeb..03fdf2b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -75,6 +75,8 @@
strippedOutputFilePath() android.OptionalPath
checkedCrateRootPath() (android.Path, error)
+
+ Aliases() map[string]string
}
func (compiler *baseCompiler) edition() string {
@@ -140,6 +142,12 @@
// flags to pass to the linker
Ld_flags []string `android:"arch_variant"`
+ // Rust crate dependencies to rename. Each entry should be a string of the form "dependencyname:alias".
+ //
+ // "dependencyname" here should be the name of the crate, not the Android module. This is
+ // equivalent to writing `alias = { package = "dependencyname" }` in a `Cargo.toml`.
+ Aliases []string
+
// list of rust rlib crate dependencies
Rlibs []string `android:"arch_variant"`
@@ -281,6 +289,18 @@
return Bool(compiler.Properties.Prefer_rlib)
}
+func (compiler *baseCompiler) Aliases() map[string]string {
+ aliases := map[string]string{}
+ for _, entry := range compiler.Properties.Aliases {
+ dep, alias, found := strings.Cut(entry, ":")
+ if !found {
+ panic(fmt.Errorf("invalid aliases entry %q missing ':'", entry))
+ }
+ aliases[dep] = alias
+ }
+ return aliases
+}
+
func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage {
// For devices, we always link stdlibs in as dylibs by default.
if compiler.preferRlib() {
diff --git a/rust/config/global.go b/rust/config/global.go
index 418eca4..e28dbaa 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -25,7 +25,7 @@
pctx = android.NewPackageContext("android/soong/rust/config")
ExportedVars = android.NewExportedVariables(pctx)
- RustDefaultVersion = "1.75.0"
+ RustDefaultVersion = "1.76.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/rust/image_test.go b/rust/image_test.go
index fb4d9c1..ba94906 100644
--- a/rust/image_test.go
+++ b/rust/image_test.go
@@ -24,7 +24,7 @@
// Test that cc modules can link against vendor_available rust_ffi_static libraries.
func TestVendorLinkage(t *testing.T) {
- ctx := testRustVndk(t, `
+ ctx := testRust(t, `
cc_binary {
name: "fizz_vendor",
static_libs: ["libfoo_vendor"],
@@ -38,7 +38,7 @@
}
`)
- vendorBinary := ctx.ModuleForTests("fizz_vendor", "android_vendor.29_arm64_armv8-a").Module().(*cc.Module)
+ vendorBinary := ctx.ModuleForTests("fizz_vendor", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
if !android.InList("libfoo_vendor.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
t.Errorf("vendorBinary should have a dependency on libfoo_vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
@@ -46,8 +46,8 @@
}
// Test that variants which use the vndk emit the appropriate cfg flag.
-func TestImageVndkCfgFlag(t *testing.T) {
- ctx := testRustVndk(t, `
+func TestImageCfgFlag(t *testing.T) {
+ ctx := testRust(t, `
rust_ffi_static {
name: "libfoo",
crate_name: "foo",
@@ -57,7 +57,7 @@
}
`)
- vendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_static").Rule("rustc")
+ vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_static").Rule("rustc")
if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vndk'") {
t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
@@ -69,7 +69,7 @@
t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
}
- product := ctx.ModuleForTests("libfoo", "android_product.29_arm64_armv8-a_static").Rule("rustc")
+ product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_static").Rule("rustc")
if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vndk'") {
t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
}
@@ -95,7 +95,7 @@
// Test that cc modules can link against vendor_ramdisk_available rust_ffi_static libraries.
func TestVendorRamdiskLinkage(t *testing.T) {
- ctx := testRustVndk(t, `
+ ctx := testRust(t, `
cc_library_static {
name: "libcc_vendor_ramdisk",
static_libs: ["libfoo_vendor_ramdisk"],
@@ -119,7 +119,7 @@
// Test that prebuilt libraries cannot be made vendor available.
func TestForbiddenVendorLinkage(t *testing.T) {
- testRustVndkError(t, "Rust prebuilt modules not supported for non-system images.", `
+ testRustError(t, "Rust prebuilt modules not supported for non-system images.", `
rust_prebuilt_library {
name: "librust_prebuilt",
crate_name: "rust_prebuilt",
diff --git a/rust/library.go b/rust/library.go
index 7f004fc..3560d73 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -54,9 +54,13 @@
Shared VariantLibraryProperties `android:"arch_variant"`
Static VariantLibraryProperties `android:"arch_variant"`
- // path to include directories to pass to cc_* modules, only relevant for static/shared variants.
+ // TODO: Remove this when all instances of Include_dirs have been removed from rust_ffi modules.
+ // path to include directories to pass to cc_* modules, only relevant for static/shared variants (deprecated, use export_include_dirs instead).
Include_dirs []string `android:"path,arch_variant"`
+ // path to include directories to export to cc_* modules, only relevant for static/shared variants.
+ Export_include_dirs []string `android:"path,arch_variant"`
+
// Whether this library is part of the Rust toolchain sysroot.
Sysroot *bool
}
@@ -465,6 +469,7 @@
flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
if library.shared() || library.static() {
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
+ library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Export_include_dirs)...)
}
if library.shared() {
if ctx.Darwin() {
diff --git a/rust/library_test.go b/rust/library_test.go
index e03074d..7275b66 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -403,3 +403,22 @@
}
}
+
+func TestRustFFIExportedIncludes(t *testing.T) {
+ ctx := testRust(t, `
+ rust_ffi {
+ name: "libbar",
+ srcs: ["foo.rs"],
+ crate_name: "bar",
+ export_include_dirs: ["rust_includes"],
+ host_supported: true,
+ }
+ cc_library_static {
+ name: "libfoo",
+ srcs: ["foo.cpp"],
+ shared_libs: ["libbar"],
+ host_supported: true,
+ }`)
+ libfooStatic := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_static").Rule("cc")
+ android.AssertStringDoesContain(t, "cFlags for lib module", libfooStatic.Args["cFlags"], " -Irust_includes ")
+}
diff --git a/rust/rust.go b/rust/rust.go
index 245ed2e..7d81c72 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1063,6 +1063,12 @@
return nil
}
+func (d dependencyTag) PropagateAconfigValidation() bool {
+ return d == rlibDepTag || d == sourceDepTag
+}
+
+var _ android.PropagateAconfigValidationDependencyTag = dependencyTag{}
+
var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
var (
@@ -1136,6 +1142,7 @@
}
}
}
+
func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
@@ -1427,16 +1434,29 @@
mod.transitiveAndroidMkSharedLibs = android.NewDepSet[string](android.PREORDER, directAndroidMkSharedLibs, transitiveAndroidMkSharedLibs)
var rlibDepFiles RustLibraries
+ aliases := mod.compiler.Aliases()
for _, dep := range directRlibDeps {
- rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
+ crateName := dep.CrateName()
+ if alias, aliased := aliases[crateName]; aliased {
+ crateName = alias
+ }
+ rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
}
var dylibDepFiles RustLibraries
for _, dep := range directDylibDeps {
- dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
+ crateName := dep.CrateName()
+ if alias, aliased := aliases[crateName]; aliased {
+ crateName = alias
+ }
+ dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
}
var procMacroDepFiles RustLibraries
for _, dep := range directProcMacroDeps {
- procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
+ crateName := dep.CrateName()
+ if alias, aliased := aliases[crateName]; aliased {
+ crateName = alias
+ }
+ procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
}
var staticLibDepFiles android.Paths
diff --git a/rust/rust_test.go b/rust/rust_test.go
index d609c2f..6d083f6 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -37,11 +37,7 @@
genrule.PrepareForTestWithGenRuleBuildComponents,
- PrepareForTestWithRustIncludeVndk,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = StringPtr("current")
- variables.Platform_vndk_version = StringPtr("29")
- }),
+ PrepareForIntegrationTestWithRust,
)
var rustMockedFiles = android.MockFS{
@@ -73,60 +69,21 @@
return result.TestContext
}
-func testRustVndk(t *testing.T, bp string) *android.TestContext {
- return testRustVndkFs(t, bp, rustMockedFiles)
-}
-
const (
- sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared"
- rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
- rlibDylibStdVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
- dylibVendorVariant = "android_vendor.29_arm64_armv8-a_dylib"
+ sharedVendorVariant = "android_vendor_arm64_armv8-a_shared"
+ rlibVendorVariant = "android_vendor_arm64_armv8-a_rlib_rlib-std"
+ rlibDylibStdVendorVariant = "android_vendor_arm64_armv8-a_rlib_rlib-std"
+ dylibVendorVariant = "android_vendor_arm64_armv8-a_dylib"
sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared"
rlibRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_dylib-std"
rlibRlibStdRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std"
dylibRecoveryVariant = "android_recovery_arm64_armv8-a_dylib"
binaryCoreVariant = "android_arm64_armv8-a"
- binaryVendorVariant = "android_vendor.29_arm64_armv8-a"
- binaryProductVariant = "android_product.29_arm64_armv8-a"
+ binaryVendorVariant = "android_vendor_arm64_armv8-a"
+ binaryProductVariant = "android_product_arm64_armv8-a"
binaryRecoveryVariant = "android_recovery_arm64_armv8-a"
)
-func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext {
- return testRustVndkFsVersions(t, bp, fs, "current", "current", "29")
-}
-
-func testRustVndkFsVersions(t *testing.T, bp string, fs android.MockFS, device_version, product_version, vndk_version string) *android.TestContext {
- skipTestIfOsNotSupported(t)
- result := android.GroupFixturePreparers(
- prepareForRustTest,
- fs.AddToFixture(),
- android.FixtureModifyProductVariables(
- func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = StringPtr(device_version)
- variables.Platform_vndk_version = StringPtr(vndk_version)
- },
- ),
- ).RunTestWithBp(t, bp)
- return result.TestContext
-}
-
-func testRustRecoveryFsVersions(t *testing.T, bp string, fs android.MockFS, device_version, vndk_version, recovery_version string) *android.TestContext {
- skipTestIfOsNotSupported(t)
- result := android.GroupFixturePreparers(
- prepareForRustTest,
- fs.AddToFixture(),
- android.FixtureModifyProductVariables(
- func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = StringPtr(device_version)
- variables.RecoverySnapshotVersion = StringPtr(recovery_version)
- variables.Platform_vndk_version = StringPtr(vndk_version)
- },
- ),
- ).RunTestWithBp(t, bp)
- return result.TestContext
-}
-
// testRustCov returns a TestContext in which a basic environment has been
// setup. This environment explicitly enables coverage.
func testRustCov(t *testing.T, bp string) *android.TestContext {
@@ -158,27 +115,6 @@
RunTestWithBp(t, bp)
}
-// testRustVndkError is similar to testRustError, but can be used to test VNDK-related errors.
-func testRustVndkError(t *testing.T, pattern string, bp string) {
- testRustVndkFsError(t, pattern, bp, rustMockedFiles)
-}
-
-func testRustVndkFsError(t *testing.T, pattern string, bp string, fs android.MockFS) {
- skipTestIfOsNotSupported(t)
- android.GroupFixturePreparers(
- prepareForRustTest,
- fs.AddToFixture(),
- android.FixtureModifyProductVariables(
- func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = StringPtr("current")
- variables.Platform_vndk_version = StringPtr("VER")
- },
- ),
- ).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
- RunTestWithBp(t, bp)
-}
-
// testRustCtx is used to build a particular test environment. Unless your
// tests requires a specific setup, prefer the wrapping functions: testRust,
// testRustCov or testRustError.
@@ -470,6 +406,35 @@
m.Output("libwaldo.dylib.so.bloaty.csv")
}
+// Test that aliases are respected.
+func TestRustAliases(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library {
+ name: "libbar",
+ crate_name: "bar",
+ srcs: ["src/lib.rs"],
+ }
+ rust_library {
+ name: "libbaz",
+ crate_name: "baz",
+ srcs: ["src/lib.rs"],
+ }
+ rust_binary {
+ name: "foo",
+ srcs: ["src/main.rs"],
+ rustlibs: ["libbar", "libbaz"],
+ aliases: ["bar:bar_renamed"],
+ }`)
+
+ fooRustc := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+ if !strings.Contains(fooRustc.Args["libFlags"], "--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so") {
+ t.Errorf("--extern bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
+ }
+ if !strings.Contains(fooRustc.Args["libFlags"], "--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so") {
+ t.Errorf("--extern baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so flag not being passed to rustc for rust_binary with aliases. libFlags: %#v", fooRustc.Args["libFlags"])
+ }
+}
+
func assertString(t *testing.T, got, expected string) {
t.Helper()
if got != expected {
diff --git a/rust/testing.go b/rust/testing.go
index d9cacdc..4e9a6c6 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -43,11 +43,7 @@
// Preparer that will allow use of all rust modules fully.
var PrepareForIntegrationTestWithRust = android.GroupFixturePreparers(
PrepareForTestWithRustDefaultModules,
-)
-
-var PrepareForTestWithRustIncludeVndk = android.GroupFixturePreparers(
- PrepareForIntegrationTestWithRust,
- cc.PrepareForTestWithCcIncludeVndk,
+ cc.PrepareForIntegrationTestWithCc,
)
func GatherRequiredDepsForTest() string {
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
deleted file mode 100644
index 7ebe66b..0000000
--- a/rust/vendor_snapshot_test.go
+++ /dev/null
@@ -1,1573 +0,0 @@
-// Copyright 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 rust
-
-import (
- "fmt"
- "path/filepath"
- "reflect"
- "strings"
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
-)
-
-func TestVendorSnapshotCapture(t *testing.T) {
- bp := `
- rust_ffi {
- name: "libffivendor_available",
- crate_name: "ffivendor_available",
- srcs: ["lib.rs"],
- vendor_available: true,
- include_dirs: ["rust_headers/"],
- }
-
- rust_ffi {
- name: "libffivendor",
- crate_name: "ffivendor",
- srcs: ["lib.rs"],
- vendor: true,
- include_dirs: ["rust_headers/"],
- }
-
- rust_library {
- name: "librustvendor_available",
- crate_name: "rustvendor_available",
- srcs: ["lib.rs"],
- vendor_available: true,
- }
-
- rust_library {
- name: "librustvendor",
- crate_name: "rustvendor",
- srcs: ["lib.rs"],
- vendor: true,
- }
-
- rust_binary {
- name: "vendor_available_bin",
- vendor_available: true,
- srcs: ["srcs/lib.rs"],
- }
-
- rust_binary {
- name: "vendor_bin",
- vendor: true,
- srcs: ["srcs/lib.rs"],
- }
- `
- skipTestIfOsNotSupported(t)
- result := android.GroupFixturePreparers(
- prepareForRustTest,
- rustMockedFiles.AddToFixture(),
- android.FixtureModifyProductVariables(
- func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = StringPtr("current")
- variables.Platform_vndk_version = StringPtr("29")
- },
- ),
- ).RunTestWithBp(t, bp)
- ctx := result.TestContext
-
- // Check Vendor snapshot output.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
- var jsonFiles []string
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- // For shared libraries, only non-VNDK vendor_available modules are captured
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(sharedDir, "libffivendor_available.so.json"))
-
- // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
- staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
- staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.a", staticDir, staticVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor", "libffivendor.a", staticDir, staticVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(staticDir, "libffivendor_available.a.json"))
- jsonFiles = append(jsonFiles,
- filepath.Join(staticDir, "libffivendor.a.json"))
-
- // For rlib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
- rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
- rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib", rlibDir, rlibVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
- jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librustvendor.rlib.json"))
-
- // For rlib libraries, all rlib-std variants vendor:true and vendor_available modules (including VNDK) are captured.
- rlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibStdVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib-std.rlib", rlibDir, rlibStdVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
- jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librustvendor.rlib.json"))
-
- // For dylib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
- dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
- dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.dylib.so", dylibDir, dylibVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
- jsonFiles = append(jsonFiles,
- filepath.Join(dylibDir, "librustvendor.dylib.so.json"))
-
- // For binary executables, all vendor:true and vendor_available modules are captured.
- if archType == "arm64" {
- binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
- binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(binaryDir, "vendor_available_bin.json"))
- jsonFiles = append(jsonFiles,
- filepath.Join(binaryDir, "vendor_bin.json"))
- }
- }
-
- for _, jsonFile := range jsonFiles {
- // verify all json files exist
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("%q expected but not found; #%v", jsonFile, jsonFiles)
- }
- }
-
- // fake snapshot should have all outputs in the normal snapshot.
- fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
-
- for _, output := range snapshotSingleton.AllOutputs() {
- fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
- if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
- t.Errorf("%q expected but not found", fakeOutput)
- }
- }
-}
-
-func TestVendorSnapshotDirected(t *testing.T) {
- bp := `
- rust_ffi_shared {
- name: "libffivendor_available",
- crate_name: "ffivendor_available",
- srcs: ["lib.rs"],
- vendor_available: true,
- }
-
- rust_library {
- name: "librustvendor_available",
- crate_name: "rustvendor_available",
- srcs: ["lib.rs"],
- vendor_available: true,
- }
-
- rust_ffi_shared {
- name: "libffivendor_exclude",
- crate_name: "ffivendor_exclude",
- srcs: ["lib.rs"],
- vendor_available: true,
- }
-
- rust_library {
- name: "librustvendor_exclude",
- crate_name: "rustvendor_exclude",
- srcs: ["lib.rs"],
- vendor_available: true,
- }
-`
- ctx := testRustVndk(t, bp)
- ctx.Config().TestProductVariables.VendorSnapshotModules = make(map[string]bool)
- ctx.Config().TestProductVariables.VendorSnapshotModules["librustvendor_available"] = true
- ctx.Config().TestProductVariables.VendorSnapshotModules["libffivendor_available"] = true
- ctx.Config().TestProductVariables.DirectedVendorSnapshot = true
-
- // Check Vendor snapshot output.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var includeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
- rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
- dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
- // Included modules
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib-std.rlib.json"))
- includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_available.dylib.so.json"))
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_available.so.json"))
-
- // Excluded modules. Modules not included in the directed vendor snapshot
- // are still include as fake modules.
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib", rlibDir, rlibVariant)
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.dylib.so", dylibDir, dylibVariant)
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "libffivendor_exclude", "libffivendor_exclude.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib.json"))
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib-std.rlib.json"))
- includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_exclude.dylib.so.json"))
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_exclude.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-}
-
-func TestVendorSnapshotExclude(t *testing.T) {
-
- // This test verifies that the exclude_from_vendor_snapshot property
- // makes its way from the Android.bp source file into the module data
- // structure. It also verifies that modules are correctly included or
- // excluded in the vendor snapshot based on their path (framework or
- // vendor) and the exclude_from_vendor_snapshot property.
-
- frameworkBp := `
- rust_ffi_shared {
- name: "libinclude",
- crate_name: "include",
- srcs: ["include.rs"],
- vendor_available: true,
- }
-
- rust_ffi_shared {
- name: "libexclude",
- crate_name: "exclude",
- srcs: ["exclude.rs"],
- vendor: true,
- exclude_from_vendor_snapshot: true,
- }
-
- rust_ffi_shared {
- name: "libavailable_exclude",
- crate_name: "available_exclude",
- srcs: ["lib.rs"],
- vendor_available: true,
- exclude_from_vendor_snapshot: true,
- }
-
- rust_library {
- name: "librust_include",
- crate_name: "rust_include",
- srcs: ["include.rs"],
- vendor_available: true,
- }
-
- rust_library {
- name: "librust_exclude",
- crate_name: "rust_exclude",
- srcs: ["exclude.rs"],
- vendor: true,
- exclude_from_vendor_snapshot: true,
- }
-
- rust_library {
- name: "librust_available_exclude",
- crate_name: "rust_available_exclude",
- srcs: ["lib.rs"],
- vendor_available: true,
- exclude_from_vendor_snapshot: true,
- }
- `
-
- mockFS := map[string][]byte{
- "framework/Android.bp": []byte(frameworkBp),
- "framework/include.rs": nil,
- "framework/exclude.rs": nil,
- }
-
- ctx := testRustVndkFs(t, "", mockFS)
-
- // Test an include and exclude framework module.
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, sharedVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, sharedVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, sharedVendorVariant)
-
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibVendorVariant)
-
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibDylibStdVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibDylibStdVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibDylibStdVendorVariant)
-
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, dylibVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, dylibVendorVariant)
- cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, dylibVendorVariant)
-
- // Verify the content of the vendor snapshot.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var includeJsonFiles []string
- var excludeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
-
- rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant)
- rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
- rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant)
- dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
- // Included modules
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib-std.rlib.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.dylib.so", dylibDir, dylibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librust_include.dylib.so.json"))
-
- // Excluded modules
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_exclude.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.rlib-std.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.dylib.so", dylibDir, dylibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_exclude.dylib.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.dylib.so", dylibDir, dylibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_available_exclude.dylib.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-
- // Verify that each json file for an excluded module has no rule.
- for _, jsonFile := range excludeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
- t.Errorf("exclude json file %q found", jsonFile)
- }
- }
-}
-
-func TestVendorSnapshotUse(t *testing.T) {
- frameworkBp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "libvendor_available",
- vendor_available: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- cc_library {
- name: "lib32",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- compile_multilib: "32",
- }
-
- cc_library {
- name: "lib64",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- stl: "none",
- system_shared_libs: [],
- compile_multilib: "64",
- }
-
- rust_binary {
- name: "bin",
- vendor: true,
- srcs: ["bin.rs"],
- }
-
- rust_binary {
- name: "bin32",
- vendor: true,
- compile_multilib: "32",
- srcs: ["bin.rs"],
- }
-
- rust_library {
- name: "librust_vendor_available",
- crate_name: "rust_vendor",
- vendor_available: true,
- srcs: ["client.rs"],
- }
-
-`
-
- vndkBp := `
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "30",
- target_arch: "arm64",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm64: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- arm: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- },
- }
-
- // old snapshot module which has to be ignored
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "26",
- target_arch: "arm64",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm64: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- arm: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- },
- }
-
- // different arch snapshot which has to be ignored
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "30",
- target_arch: "arm",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- arch: {
- arm: {
- srcs: ["libvndk.so"],
- export_include_dirs: ["include/libvndk"],
- },
- },
- }
-`
-
- vendorProprietaryBp := `
- cc_library {
- name: "libvendor_without_snapshot",
- vendor: true,
- nocrt: true,
- no_libcrt: true,
- no_crt_pad_segment: true,
- stl: "none",
- system_shared_libs: [],
- }
-
- rust_ffi_shared {
- name: "libclient",
- crate_name: "client",
- vendor: true,
- shared_libs: ["libvndk", "libvendor_available"],
- static_libs: ["libvendor", "libvendor_without_snapshot"],
- rustlibs: ["librust_vendor_available"],
- arch: {
- arm64: {
- shared_libs: ["lib64"],
- },
- arm: {
- shared_libs: ["lib32"],
- },
- },
- srcs: ["client.rs"],
- }
-
- rust_library {
- name: "libclient_rust",
- crate_name: "client_rust",
- vendor: true,
- shared_libs: ["libvndk", "libvendor_available"],
- static_libs: ["libvendor", "libvendor_without_snapshot"],
- rustlibs: ["librust_vendor_available"],
- arch: {
- arm64: {
- shared_libs: ["lib64"],
- },
- arm: {
- shared_libs: ["lib32"],
- },
- },
- srcs: ["client.rs"],
- }
-
- rust_binary {
- name: "bin_without_snapshot",
- vendor: true,
- static_libs: ["libvndk"],
- srcs: ["bin.rs"],
- rustlibs: ["librust_vendor_available"],
- }
-
- vendor_snapshot {
- name: "vendor_snapshot",
- version: "30",
- arch: {
- arm64: {
- vndk_libs: [
- "libvndk",
- ],
- static_libs: [
- "libvendor",
- "libvndk",
- "libclang_rt.builtins",
- "note_memtag_heap_sync",
- ],
- shared_libs: [
- "libvendor_available",
- "lib64",
- ],
- rlibs: [
- "libstd",
- "librust_vendor_available",
- "librust_vendor_available.rlib-std"
- ],
- dylibs: [
- "libstd",
- "librust_vendor_available",
- ],
- binaries: [
- "bin",
- ],
- objects: [
- "crtend_so",
- "crtbegin_so",
- "crtbegin_dynamic",
- "crtend_android"
- ],
- },
- arm: {
- vndk_libs: [
- "libvndk",
- ],
- static_libs: [
- "libvendor",
- "libvndk",
- "libclang_rt.builtins",
- ],
- shared_libs: [
- "libvendor_available",
- "lib32",
- ],
- rlibs: [
- "libstd",
- "librust_vendor_available",
- ],
- dylibs: [
- "libstd",
- "librust_vendor_available",
- ],
- binaries: [
- "bin32",
- ],
- objects: [
- "crtend_so",
- "crtbegin_so",
- "crtbegin_dynamic",
- "crtend_android"
- ],
-
- },
- }
- }
-
- vendor_snapshot_object {
- name: "crtend_so",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- stl: "none",
- crt: true,
- arch: {
- arm64: {
- src: "crtend_so.o",
- },
- arm: {
- src: "crtend_so.o",
- },
- },
- }
-
- vendor_snapshot_object {
- name: "crtbegin_so",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- stl: "none",
- crt: true,
- arch: {
- arm64: {
- src: "crtbegin_so.o",
- },
- arm: {
- src: "crtbegin_so.o",
- },
- },
- }
-
- vendor_snapshot_rlib {
- name: "libstd",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- sysroot: true,
- arch: {
- arm64: {
- src: "libstd.rlib",
- },
- arm: {
- src: "libstd.rlib",
- },
- },
- }
-
- vendor_snapshot_rlib {
- name: "librust_vendor_available",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- arch: {
- arm64: {
- src: "librust_vendor_available.rlib",
- },
- arm: {
- src: "librust_vendor_available.rlib",
- },
- },
- }
-
- vendor_snapshot_rlib {
- name: "librust_vendor_available.rlib-std",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- arch: {
- arm64: {
- src: "librust_vendor_available.rlib-std.rlib",
- },
- arm: {
- src: "librust_vendor_available.rlib-std.rlib",
- },
- },
- }
-
- vendor_snapshot_dylib {
- name: "libstd",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- sysroot: true,
- arch: {
- arm64: {
- src: "libstd.dylib.so",
- },
- arm: {
- src: "libstd.dylib.so",
- },
- },
- }
-
- vendor_snapshot_dylib {
- name: "librust_vendor_available",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- arch: {
- arm64: {
- src: "librust_vendor_available.dylib.so",
- },
- arm: {
- src: "librust_vendor_available.dylib.so",
- },
- },
- }
-
- vendor_snapshot_object {
- name: "crtend_android",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- stl: "none",
- crt: true,
- arch: {
- arm64: {
- src: "crtend_so.o",
- },
- arm: {
- src: "crtend_so.o",
- },
- },
- }
-
- vendor_snapshot_object {
- name: "crtbegin_dynamic",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- stl: "none",
- crt: true,
- arch: {
- arm64: {
- src: "crtbegin_so.o",
- },
- arm: {
- src: "crtbegin_so.o",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libvndk",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- arch: {
- arm64: {
- src: "libvndk.a",
- },
- arm: {
- src: "libvndk.a",
- },
- },
- shared_libs: ["libvndk"],
- export_shared_lib_headers: ["libvndk"],
- }
-
- vendor_snapshot_static {
- name: "libclang_rt.builtins",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- arch: {
- arm: {
- src: "libclang_rt.builtins-arm-android.a",
- },
- arm64: {
- src: "libclang_rt.builtins-aarch64-android.a",
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "lib32",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "32",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm: {
- src: "lib32.so",
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "lib64",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm64: {
- src: "lib64.so",
- },
- },
- }
- vendor_snapshot_shared {
- name: "liblog",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm64: {
- src: "liblog.so",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libvendor",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- arch: {
- arm64: {
- src: "libvendor.a",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- src: "libvendor.a",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_shared {
- name: "libvendor_available",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "both",
- vendor: true,
- no_crt_pad_segment: true,
- arch: {
- arm64: {
- src: "libvendor_available.so",
- export_include_dirs: ["include/libvendor"],
- },
- arm: {
- src: "libvendor_available.so",
- export_include_dirs: ["include/libvendor"],
- },
- },
- }
-
- vendor_snapshot_binary {
- name: "bin",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "64",
- vendor: true,
- arch: {
- arm64: {
- src: "bin",
- },
- },
- }
-
- vendor_snapshot_binary {
- name: "bin32",
- version: "30",
- target_arch: "arm64",
- compile_multilib: "32",
- vendor: true,
- arch: {
- arm: {
- src: "bin32",
- },
- },
- }
-
- // Test sanitizers use the snapshot libraries
- rust_binary {
- name: "memtag_binary",
- srcs: ["vendor/bin.rs"],
- vendor: true,
- compile_multilib: "64",
- sanitize: {
- memtag_heap: true,
- diag: {
- memtag_heap: true,
- }
- },
- }
-
- // old snapshot module which has to be ignored
- vendor_snapshot_binary {
- name: "bin",
- version: "26",
- target_arch: "arm64",
- compile_multilib: "first",
- vendor: true,
- arch: {
- arm64: {
- src: "bin",
- },
- },
- }
-
- // different arch snapshot which has to be ignored
- vendor_snapshot_binary {
- name: "bin",
- version: "30",
- target_arch: "arm",
- compile_multilib: "first",
- vendor: true,
- arch: {
- arm64: {
- src: "bin",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "note_memtag_heap_sync",
- vendor: true,
- target_arch: "arm64",
- version: "30",
- arch: {
- arm64: {
- src: "note_memtag_heap_sync.a",
- },
- },
- }
-
-`
-
- mockFS := android.MockFS{
- "framework/Android.bp": []byte(frameworkBp),
- "framework/bin.rs": nil,
- "note_memtag_heap_sync.a": nil,
- "vendor/Android.bp": []byte(vendorProprietaryBp),
- "vendor/bin": nil,
- "vendor/bin32": nil,
- "vendor/bin.rs": nil,
- "vendor/client.rs": nil,
- "vendor/include/libvndk/a.h": nil,
- "vendor/include/libvendor/b.h": nil,
- "vendor/libvndk.a": nil,
- "vendor/libvendor.a": nil,
- "vendor/libvendor.so": nil,
- "vendor/lib32.so": nil,
- "vendor/lib64.so": nil,
- "vendor/liblog.so": nil,
- "vendor/libstd.rlib": nil,
- "vendor/librust_vendor_available.rlib": nil,
- "vendor/librust_vendor_available.rlib-std.rlib": nil,
- "vendor/libstd.dylib.so": nil,
- "vendor/librust_vendor_available.dylib.so": nil,
- "vendor/crtbegin_so.o": nil,
- "vendor/crtend_so.o": nil,
- "vendor/libclang_rt.builtins-aarch64-android.a": nil,
- "vendor/libclang_rt.builtins-arm-android.a": nil,
- "vndk/Android.bp": []byte(vndkBp),
- "vndk/include/libvndk/a.h": nil,
- "vndk/libvndk.so": nil,
- }
-
- sharedVariant := "android_vendor.30_arm64_armv8-a_shared"
- rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_dylib-std"
- rlibRlibStdVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
- dylibVariant := "android_vendor.30_arm64_armv8-a_dylib"
- staticVariant := "android_vendor.30_arm64_armv8-a_static"
- binaryVariant := "android_vendor.30_arm64_armv8-a"
-
- shared32Variant := "android_vendor.30_arm_armv7-a-neon_shared"
- binary32Variant := "android_vendor.30_arm_armv7-a-neon"
-
- ctx := testRustVndkFsVersions(t, "", mockFS, "30", "current", "31")
-
- // libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot
- libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").Args["linkFlags"]
- for _, input := range [][]string{
- []string{sharedVariant, "libvndk.vndk.30.arm64"},
- []string{staticVariant, "libvendor.vendor_static.30.arm64"},
- []string{staticVariant, "libvendor_without_snapshot"},
- } {
- outputPaths := cc.GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
- if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
- t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
- }
- }
-
- libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).transitiveAndroidMkSharedLibs.ToList()
- if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib64", "liblog.vendor", "libc.vendor", "libm.vendor", "libdl.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
- }
-
- libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
- if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
- }
-
- libclientAndroidMkDylibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkDylibs
- if g, w := libclientAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient libclientAndroidMkDylibs %q, got %q", w, libclientAndroidMkDylibs)
- }
-
- libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).transitiveAndroidMkSharedLibs.ToList()
- if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib32", "liblog.vendor", "libc.vendor", "libm.vendor", "libdl.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
- }
-
- libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs
- if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
- }
-
- libclientRlibStdRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibRlibStdVariant).Module().(*Module).Properties.AndroidMkRlibs
- if g, w := libclientRlibStdRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g)
- }
-
- libclientRustDylibAndroidMkDylibs := ctx.ModuleForTests("libclient_rust", dylibVariant).Module().(*Module).Properties.AndroidMkDylibs
- if g, w := libclientRustDylibAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted dylib libclient libclientRustDylibAndroidMkDylibs %q, got %q", w, g)
- }
-
- // rust vendor snapshot must have ".vendor" suffix in AndroidMk
- librustVendorAvailableSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_rlib.30.arm64", rlibVariant).Module()
- librustVendorSnapshotMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
- expectedRustVendorSnapshotName := "librust_vendor_available.vendor"
- if librustVendorSnapshotMkName != expectedRustVendorSnapshotName {
- t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotMkName, expectedRustVendorSnapshotName)
- }
-
- librustVendorAvailableDylibSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_dylib.30.arm64", dylibVariant).Module()
- librustVendorSnapshotDylibMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableDylibSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
- expectedRustVendorDylibSnapshotName := "librust_vendor_available.vendor"
- if librustVendorSnapshotDylibMkName != expectedRustVendorDylibSnapshotName {
- t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotDylibMkName, expectedRustVendorDylibSnapshotName)
- }
-
- rustVendorBinModule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Module()
- rustVendorBinMkDylibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_DYLIB_LIBRARIES"][0]
- if rustVendorBinMkDylibName != expectedRustVendorSnapshotName {
- t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName)
- }
-
- binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").Args["linkFlags"]
- libVndkStaticOutputPaths := cc.GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"})
- if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
- t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
- libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
- }
-
- // bin is installed by bin.vendor_binary.30.arm64
- ctx.ModuleForTests("bin.vendor_binary.30.arm64", binaryVariant).Output("bin")
-
- // bin32 is installed by bin32.vendor_binary.30.arm64
- ctx.ModuleForTests("bin32.vendor_binary.30.arm64", binary32Variant).Output("bin32")
-
- // bin_without_snapshot is installed by bin_without_snapshot
- ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
-
- // libvendor, libvendor_available and bin don't have vendor.30 variant
- libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
- if android.InList(sharedVariant, libvendorVariants) {
- t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
- }
-
- libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
- if android.InList(sharedVariant, libvendorAvailableVariants) {
- t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
- }
-
- binVariants := ctx.ModuleVariantsForTests("bin")
- if android.InList(binaryVariant, binVariants) {
- t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
- }
-
- memtagStaticLibs := ctx.ModuleForTests("memtag_binary", "android_vendor.30_arm64_armv8-a").Module().(*Module).Properties.AndroidMkStaticLibs
- if g, w := memtagStaticLibs, []string{"libclang_rt.builtins.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) {
- t.Errorf("wanted memtag_binary AndroidMkStaticLibs %q, got %q", w, g)
- }
-}
-
-func TestRecoverySnapshotCapture(t *testing.T) {
- bp := `
- rust_ffi {
- name: "librecovery",
- recovery: true,
- srcs: ["foo.rs"],
- crate_name: "recovery",
- }
-
- rust_ffi {
- name: "librecovery_available",
- recovery_available: true,
- srcs: ["foo.rs"],
- crate_name: "recovery_available",
- }
-
- rust_library {
- name: "librecovery_rustlib",
- recovery: true,
- srcs: ["foo.rs"],
- crate_name: "recovery_rustlib",
- }
-
- rust_library {
- name: "librecovery_available_rustlib",
- recovery_available: true,
- srcs: ["foo.rs"],
- crate_name: "recovery_available_rustlib",
- }
-
- rust_binary {
- name: "recovery_bin",
- recovery: true,
- srcs: ["foo.rs"],
- }
-
- rust_binary {
- name: "recovery_available_bin",
- recovery_available: true,
- srcs: ["foo.rs"],
- }
-
-`
- // Check Recovery snapshot output.
-
- ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "", "29", "current")
- snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
- var jsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- // For shared libraries, all recovery:true and recovery_available modules are captured.
- sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(sharedDir, "librecovery.so.json"),
- filepath.Join(sharedDir, "librecovery_available.so.json"))
-
- // For static libraries, all recovery:true and recovery_available modules are captured.
- staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
- staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(staticDir, "librecovery.a.json"),
- filepath.Join(staticDir, "librecovery_available.a.json"))
-
- // For rlib libraries, all recovery:true and recovery_available modules are captured.
- rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
- rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"),
- filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
-
- rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"),
- filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
-
- // For dylib libraries, all recovery:true and recovery_available modules are captured.
- dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
- dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"),
- filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
-
- // For binary executables, all recovery:true and recovery_available modules are captured.
- if archType == "arm64" {
- binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
- binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(binaryDir, "recovery_bin.json"),
- filepath.Join(binaryDir, "recovery_available_bin.json"))
- }
- }
-
- for _, jsonFile := range jsonFiles {
- // verify all json files exist
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("%q expected but not found", jsonFile)
- }
- }
-}
-
-func TestRecoverySnapshotExclude(t *testing.T) {
- // This test verifies that the exclude_from_recovery_snapshot property
- // makes its way from the Android.bp source file into the module data
- // structure. It also verifies that modules are correctly included or
- // excluded in the recovery snapshot based on their path (framework or
- // vendor) and the exclude_from_recovery_snapshot property.
-
- frameworkBp := `
- rust_ffi_shared {
- name: "libinclude",
- srcs: ["src/include.rs"],
- recovery_available: true,
- crate_name: "include",
- }
- rust_ffi_shared {
- name: "libexclude",
- srcs: ["src/exclude.rs"],
- recovery: true,
- exclude_from_recovery_snapshot: true,
- crate_name: "exclude",
- }
- rust_ffi_shared {
- name: "libavailable_exclude",
- srcs: ["src/exclude.rs"],
- recovery_available: true,
- exclude_from_recovery_snapshot: true,
- crate_name: "available_exclude",
- }
- rust_library {
- name: "libinclude_rustlib",
- srcs: ["src/include.rs"],
- recovery_available: true,
- crate_name: "include_rustlib",
- }
- rust_library {
- name: "libexclude_rustlib",
- srcs: ["src/exclude.rs"],
- recovery: true,
- exclude_from_recovery_snapshot: true,
- crate_name: "exclude_rustlib",
- }
- rust_library {
- name: "libavailable_exclude_rustlib",
- srcs: ["src/exclude.rs"],
- recovery_available: true,
- exclude_from_recovery_snapshot: true,
- crate_name: "available_exclude_rustlib",
- }
- `
-
- vendorProprietaryBp := `
- rust_ffi_shared {
- name: "librecovery",
- srcs: ["recovery.rs"],
- recovery: true,
- crate_name: "recovery",
- }
- rust_library {
- name: "librecovery_rustlib",
- srcs: ["recovery.rs"],
- recovery: true,
- crate_name: "recovery_rustlib",
- }
- `
-
- mockFS := map[string][]byte{
- "framework/Android.bp": []byte(frameworkBp),
- "framework/include.rs": nil,
- "framework/exclude.rs": nil,
- "device/Android.bp": []byte(vendorProprietaryBp),
- "device/recovery.rs": nil,
- }
-
- ctx := testRustRecoveryFsVersions(t, "", mockFS, "", "29", "current")
-
- // Test an include and exclude framework module.
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, sharedRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, sharedRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, sharedRecoveryVariant)
-
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
-
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRlibStdRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRlibStdRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant)
-
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, dylibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, dylibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, dylibRecoveryVariant)
-
- // A recovery module is excluded, but by its path not the exclude_from_recovery_snapshot property
- // ('device/' and 'vendor/' are default excluded). See snapshot/recovery_snapshot.go for more detail.
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, sharedRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRlibStdRecoveryVariant)
- cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, dylibRecoveryVariant)
-
- // Verify the content of the recovery snapshot.
-
- snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
- var includeJsonFiles []string
- var excludeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
- rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
- dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
- // Included modules
-
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib-std.rlib.json"))
-
- // Excluded modules
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
-
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib", rlibDir, rlibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib.json"))
-
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib-std.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib-std.rlib.json"))
-
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.dylib.so", dylibDir, dylibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.dylib.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.dylib.so.json"))
- cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.dylib.so", dylibDir, dylibVariant)
- excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.dylib.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found", jsonFile)
- }
- }
-
- // Verify that each json file for an excluded module has no rule.
- for _, jsonFile := range excludeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
- t.Errorf("exclude json file %q found", jsonFile)
- }
- }
-}
-
-func TestRecoverySnapshotDirected(t *testing.T) {
- bp := `
- rust_ffi_shared {
- name: "librecovery",
- recovery: true,
- crate_name: "recovery",
- srcs: ["foo.rs"],
- }
-
- rust_ffi_shared {
- name: "librecovery_available",
- recovery_available: true,
- crate_name: "recovery_available",
- srcs: ["foo.rs"],
- }
-
- rust_library {
- name: "librecovery_rustlib",
- recovery: true,
- crate_name: "recovery",
- srcs: ["foo.rs"],
- }
-
- rust_library {
- name: "librecovery_available_rustlib",
- recovery_available: true,
- crate_name: "recovery_available",
- srcs: ["foo.rs"],
- }
-
- /* TODO: Uncomment when Rust supports the "prefer" property for prebuilts
- rust_library_rlib {
- name: "libfoo_rlib",
- recovery: true,
- crate_name: "foo",
- }
-
- rust_prebuilt_rlib {
- name: "libfoo_rlib",
- recovery: true,
- prefer: true,
- srcs: ["libfoo.rlib"],
- crate_name: "foo",
- }
- */
-`
- ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "current", "29", "current")
- ctx.Config().TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
- ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery"] = true
- ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rustlib"] = true
- ctx.Config().TestProductVariables.DirectedRecoverySnapshot = true
-
- // Check recovery snapshot output.
- snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
-
- var includeJsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
- rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant)
- rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant)
- dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
- dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib")
-
- // Included modules
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"))
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"))
-
- // TODO: When Rust supports the "prefer" property for prebuilts, perform this check.
- /*
- // Check that snapshot captures "prefer: true" prebuilt
- cc.CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo_rlib", "libfoo_rlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo_rlib.rlib.json"))
- */
-
- // Excluded modules. Modules not included in the directed recovery snapshot
- // are still included as fake modules.
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json"))
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json"))
- cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant)
- includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json"))
- }
-
- // Verify that each json file for an included module has a rule.
- for _, jsonFile := range includeJsonFiles {
- if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
- t.Errorf("include json file %q not found, %#v", jsonFile, includeJsonFiles)
- }
- }
-}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index e2fd59f..d039a81 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -292,3 +292,27 @@
name: "keep-flagged-apis",
src: "keep-flagged-apis.sh",
}
+
+python_binary_host {
+ name: "merge_directories",
+ main: "merge_directories.py",
+ srcs: [
+ "merge_directories.py",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
+
+python_binary_host {
+ name: "buildinfo",
+ main: "buildinfo.py",
+ srcs: ["buildinfo.py"],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/scripts/buildinfo.py b/scripts/buildinfo.py
new file mode 100755
index 0000000..e4fb0da
--- /dev/null
+++ b/scripts/buildinfo.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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.
+#
+"""A tool for generating buildinfo.prop"""
+
+import argparse
+import contextlib
+import subprocess
+
+def parse_args():
+ """Parse commandline arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--use-vbmeta-digest-in-fingerprint', action='store_true')
+ parser.add_argument('--build-flavor', required=True)
+ parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')),
+ parser.add_argument('--build-id', required=True)
+ parser.add_argument('--build-keys', required=True)
+ parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r'))
+ parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r'))
+ parser.add_argument('--build-type', required=True)
+ parser.add_argument('--build-username', required=True)
+ parser.add_argument('--build-variant', required=True)
+ parser.add_argument('--cpu-abis', action='append', required=True)
+ parser.add_argument('--date-file', required=True, type=argparse.FileType('r'))
+ parser.add_argument('--default-locale')
+ parser.add_argument('--default-wifi-channels', action='append', default=[])
+ parser.add_argument('--device', required=True)
+ parser.add_argument("--display-build-number", action='store_true')
+ parser.add_argument('--platform-base-os', required=True)
+ parser.add_argument('--platform-display-version', required=True)
+ parser.add_argument('--platform-min-supported-target-sdk-version', required=True)
+ parser.add_argument('--platform-preview-sdk-fingerprint-file',
+ required=True,
+ type=argparse.FileType('r'))
+ parser.add_argument('--platform-preview-sdk-version', required=True)
+ parser.add_argument('--platform-sdk-version', required=True)
+ parser.add_argument('--platform-security-patch', required=True)
+ parser.add_argument('--platform-version', required=True)
+ parser.add_argument('--platform-version-codename',required=True)
+ parser.add_argument('--platform-version-all-codenames', action='append', required=True)
+ parser.add_argument('--platform-version-known-codenames', required=True)
+ parser.add_argument('--platform-version-last-stable', required=True)
+ parser.add_argument('--product', required=True)
+
+ parser.add_argument('--out', required=True, type=argparse.FileType('w'))
+
+ return parser.parse_args()
+
+def main():
+ option = parse_args()
+
+ build_hostname = option.build_hostname_file.read().strip()
+ build_number = option.build_number_file.read().strip()
+ build_version_tags = option.build_keys
+ if option.build_type == "debug":
+ build_version_tags = "debug," + build_version_tags
+
+ raw_date = option.date_file.read().strip()
+ date = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip()
+ date_utc = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip()
+
+ # build_desc is human readable strings that describe this build. This has the same info as the
+ # build fingerprint.
+ # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys"
+ build_desc = f"{option.product}-{option.build_variant} {option.platform_version} " \
+ f"{option.build_id} {build_number} {build_version_tags}"
+
+ platform_preview_sdk_fingerprint = option.platform_preview_sdk_fingerprint_file.read().strip()
+
+ with contextlib.redirect_stdout(option.out):
+ print("# begin build properties")
+ print("# autogenerated by buildinfo.py")
+
+ # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest.
+ if option.use_vbmeta_digest_in_fingerprint:
+ print(f"ro.build.legacy.id={option.build_id}")
+ else:
+ print(f"ro.build.id?={option.build_id}")
+
+ # ro.build.display.id is shown under Settings -> About Phone
+ if option.build_variant == "user":
+ # User builds should show:
+ # release build number or branch.buld_number non-release builds
+
+ # Dev. branches should have DISPLAY_BUILD_NUMBER set
+ if option.display_build_number:
+ print(f"ro.build.display.id?={option.build_id} {build_number} {option.build_keys}")
+ else:
+ print(f"ro.build.display.id?={option.build_id} {option.build_keys}")
+ else:
+ # Non-user builds should show detailed build information (See build desc above)
+ print(f"ro.build.display.id?={build_desc}")
+ print(f"ro.build.version.incremental={build_number}")
+ print(f"ro.build.version.sdk={option.platform_sdk_version}")
+ print(f"ro.build.version.preview_sdk={option.platform_preview_sdk_version}")
+ print(f"ro.build.version.preview_sdk_fingerprint={platform_preview_sdk_fingerprint}")
+ print(f"ro.build.version.codename={option.platform_version_codename}")
+ print(f"ro.build.version.all_codenames={','.join(option.platform_version_all_codenames)}")
+ print(f"ro.build.version.known_codenames={option.platform_version_known_codenames}")
+ print(f"ro.build.version.release={option.platform_version_last_stable}")
+ print(f"ro.build.version.release_or_codename={option.platform_version}")
+ print(f"ro.build.version.release_or_preview_display={option.platform_display_version}")
+ print(f"ro.build.version.security_patch={option.platform_security_patch}")
+ print(f"ro.build.version.base_os={option.platform_base_os}")
+ print(f"ro.build.version.min_supported_target_sdk={option.platform_min_supported_target_sdk_version}")
+ print(f"ro.build.date={date}")
+ print(f"ro.build.date.utc={date_utc}")
+ print(f"ro.build.type={option.build_variant}")
+ print(f"ro.build.user={option.build_username}")
+ print(f"ro.build.host={build_hostname}")
+ # TODO: Remove any tag-related optional property declarations once the goals
+ # from go/arc-android-sigprop-changes have been achieved.
+ print(f"ro.build.tags?={build_version_tags}")
+ # ro.build.flavor are used only by the test harness to distinguish builds.
+ # Only add _asan for a sanitized build if it isn't already a part of the
+ # flavor (via a dedicated lunch config for example).
+ print(f"ro.build.flavor={option.build_flavor}")
+
+ # These values are deprecated, use "ro.product.cpu.abilist"
+ # instead (see below).
+ print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
+ print(f"# use ro.product.cpu.abilist instead.")
+ print(f"ro.product.cpu.abi={option.cpu_abis[0]}")
+ if len(option.cpu_abis) > 1:
+ print(f"ro.product.cpu.abi2={option.cpu_abis[1]}")
+
+ if option.default_locale:
+ print(f"ro.product.locale={option.default_locale}")
+ print(f"ro.wifi.channels={' '.join(option.default_wifi_channels)}")
+
+ print(f"# ro.build.product is obsolete; use ro.product.device")
+ print(f"ro.build.product={option.device}")
+
+ print(f"# Do not try to parse description or thumbprint")
+ print(f"ro.build.description?={build_desc}")
+ if option.build_thumbprint_file:
+ build_thumbprint = option.build_thumbprint_file.read().strip()
+ print(f"ro.build.thumbprint={build_thumbprint}")
+
+ print(f"# end build properties")
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/merge_directories.py b/scripts/merge_directories.py
new file mode 100755
index 0000000..3f8631b
--- /dev/null
+++ b/scripts/merge_directories.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+import argparse
+import os
+import shutil
+import sys
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Given a list of directories, this script will copy the contents of all of "
+ "them into the first directory, erroring out if any duplicate files are found."
+ )
+ parser.add_argument(
+ "--ignore-duplicates",
+ action="store_true",
+ help="Don't error out on duplicate files, just skip them. The file from the earliest "
+ "directory listed on the command line will be the winner."
+ )
+ parser.add_argument(
+ "--file-list",
+ help="Path to a text file containing paths relative to in_dir. Only these paths will be "
+ "copied out of in_dir."
+ )
+ parser.add_argument("out_dir")
+ parser.add_argument("in_dir")
+ args = parser.parse_args()
+
+ if not os.path.isdir(args.out_dir):
+ sys.exit(f"error: {args.out_dir} must be a directory")
+ if not os.path.isdir(args.in_dir):
+ sys.exit(f"error: {args.in_dir} must be a directory")
+
+ file_list = None
+ if args.file_list:
+ with open(file_list_file, "r") as f:
+ file_list = f.read().strip().splitlines()
+
+ in_dir = args.in_dir
+ for root, dirs, files in os.walk(in_dir):
+ rel_root = os.path.relpath(root, in_dir)
+ dst_root = os.path.join(args.out_dir, rel_root)
+ made_parent_dirs = False
+ for f in files:
+ src = os.path.join(root, f)
+ dst = os.path.join(dst_root, f)
+ p = os.path.normpath(os.path.join(rel_root, f))
+ if file_list is not None and p not in file_list:
+ continue
+ if os.path.lexists(dst):
+ if args.ignore_duplicates:
+ continue
+ sys.exit(f"error: {p} exists in both {args.out_dir} and {in_dir}")
+
+ if not made_parent_dirs:
+ os.makedirs(dst_root, exist_ok=True)
+ made_parent_dirs = True
+
+ shutil.copy2(src, dst, follow_symlinks=False)
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/test_config_fixer.py b/scripts/test_config_fixer.py
index 07e01a1..2876bcb 100644
--- a/scripts/test_config_fixer.py
+++ b/scripts/test_config_fixer.py
@@ -19,6 +19,7 @@
from __future__ import print_function
import argparse
+import json
import sys
from xml.dom import minidom
@@ -31,6 +32,8 @@
KNOWN_PREPARERS = ['com.android.tradefed.targetprep.TestAppInstallSetup',
'com.android.tradefed.targetprep.suite.SuiteApkInstaller']
+KNOWN_TEST_RUNNERS = ['com.android.tradefed.testtype.AndroidJUnitTest']
+
MAINLINE_CONTROLLER = 'com.android.tradefed.testtype.suite.module.MainlineTestModuleController'
def parse_args():
@@ -43,8 +46,12 @@
help=('overwrite package fields in the test config'))
parser.add_argument('--test-file-name', default='', dest='test_file_name',
help=('overwrite test file name in the test config'))
+ parser.add_argument('--orig-test-file-name', default='', dest='orig_test_file_name',
+ help=('Use with test-file-name to only override a single apk'))
parser.add_argument('--mainline-package-name', default='', dest='mainline_package_name',
help=('overwrite mainline module package name in the test config'))
+ parser.add_argument('--test-runner-options', default='', dest='test_runner_options',
+ help=('Add test runner options in the test config'))
parser.add_argument('input', help='input test config file')
parser.add_argument('output', help='output test config file')
return parser.parse_args()
@@ -76,6 +83,18 @@
if option.getAttribute('name') == "test-file-name":
option.setAttribute('value', test_file_name)
+def overwrite_single_test_file_name(test_config_doc, orig_test_file_name, new_test_file_name):
+
+ test_config = parse_test_config(test_config_doc)
+ tests = get_children_with_tag(test_config, 'target_preparer')
+
+ for test in tests:
+ if test.getAttribute('class') in KNOWN_PREPARERS:
+ options = get_children_with_tag(test, 'option')
+ for option in options:
+ if option.getAttribute('name') == "test-file-name" and option.getAttribute('value') == orig_test_file_name:
+ option.setAttribute('value', new_test_file_name)
+
def overwrite_mainline_module_package_name(test_config_doc, mainline_package_name):
test_config = parse_test_config(test_config_doc)
@@ -86,6 +105,31 @@
if option.getAttribute('name') == "mainline-module-package-name":
option.setAttribute('value', mainline_package_name)
+def add_test_runner_options_toplevel(test_config_doc, test_runner_options):
+
+ test_config = parse_test_config(test_config_doc)
+
+ test_config.appendChild(test_config_doc.createComment("Options from Android.bp"))
+ test_config.appendChild(test_config_doc.createTextNode("\n"))
+ for new_option in json.loads(test_runner_options):
+ option = test_config_doc.createElement("option")
+ # name and value are mandatory,
+ name = new_option.get('Name')
+ if not name:
+ raise RuntimeError('"name" must set in test_runner_option"')
+ value = new_option.get('Value')
+ if not value:
+ raise RuntimeError('"value" must set in test_runner_option"')
+ option.setAttribute('name', name) # 'include-filter')
+ option.setAttribute('value', value) # 'android.test.example.devcodelab.DevCodelabTest#testHelloFail')
+ key = new_option.get('Key')
+ if key:
+ option.setAttribute('key', key) # 'include-filter')
+ # add tab and newline for readability
+ test_config.appendChild(test_config_doc.createTextNode(" "))
+ test_config.appendChild(option)
+ test_config.appendChild(test_config_doc.createTextNode("\n"))
+
def main():
"""Program entry point."""
try:
@@ -100,11 +144,20 @@
overwrite_package_name(doc, manifest_doc, args.package_name)
if args.test_file_name:
- overwrite_test_file_name(doc, args.test_file_name)
+ if args.orig_test_file_name:
+ overwrite_single_test_file_name(doc, args.orig_test_file_name, args.test_file_name)
+ else:
+ # You probably never want to override the test_file_name if there
+ # are several in the xml, but this is currently only used on generated
+ # AndroidTest.xml where there is only a single test-file-name (no data)
+ overwrite_test_file_name(doc, args.test_file_name)
if args.mainline_package_name:
overwrite_mainline_module_package_name(doc, args.mainline_package_name)
+ if args.test_runner_options:
+ add_test_runner_options_toplevel(doc, args.test_runner_options)
+
with open(args.output, 'w') as f:
write_xml(f, doc)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 5d41958..8d3bbfa 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -152,6 +152,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [],
+}
+
prebuilt_bootclasspath_fragment {
name: "art-bootclasspath-fragment",
prefer: false,
@@ -187,6 +192,7 @@
apex_available: ["com.android.art"],
jars: ["java_boot_libs/snapshot/jars/are/invalid/core2.jar"],
}
+
`),
checkAllCopyRules(`
.intermediates/art-bootclasspath-fragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
@@ -353,6 +359,15 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_myothersdklibrary",
+ "prebuilt_mysdklibrary",
+ "prebuilt_mycoreplatform",
+ ],
+}
+
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
prefer: false,
@@ -642,6 +657,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mysdklibrary"],
+}
+
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
prefer: false,
@@ -881,6 +901,14 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_mynewlibrary",
+ "prebuilt_mysdklibrary",
+ ],
+}
+
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
prefer: false,
@@ -1008,6 +1036,9 @@
android.FixtureMergeEnv(map[string]string{
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ }),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{
@@ -1226,6 +1257,9 @@
android.FixtureMergeEnv(map[string]string{
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ }),
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 265579a..9490d12 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -123,6 +123,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_sdkmember"],
+}
+
cc_prebuilt_library_shared {
name: "sdkmember",
prefer: false,
@@ -226,6 +231,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_crtobj"],
+}
+
cc_prebuilt_object {
name: "crtobj",
prefer: false,
@@ -333,6 +343,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
@@ -406,6 +421,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
@@ -465,6 +485,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mymodule_exports.contributions",
+ contents: ["prebuilt_mynativebinary"],
+}
+
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
@@ -523,6 +548,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativebinary"],
+}
+
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
@@ -621,6 +651,14 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: [
+ "prebuilt_mynativebinary",
+ "prebuilt_mynativelib",
+ ],
+}
+
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
@@ -696,6 +734,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mymodule_exports.contributions",
+ contents: ["prebuilt_linker"],
+}
+
cc_prebuilt_binary {
name: "linker",
prefer: false,
@@ -755,6 +798,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
@@ -856,6 +904,15 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_mynativelib",
+ "prebuilt_myothernativelib",
+ "prebuilt_mysystemnativelib",
+ ],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
@@ -953,6 +1010,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
@@ -1029,6 +1091,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
@@ -1095,6 +1162,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
@@ -1158,6 +1230,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
@@ -1222,6 +1299,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library {
name: "mynativelib",
prefer: false,
@@ -1298,6 +1380,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library {
name: "mynativelib",
prefer: false,
@@ -1394,6 +1481,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library {
name: "mynativelib",
prefer: false,
@@ -1520,6 +1612,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
@@ -1572,6 +1669,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativeheaders"],
+}
+
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
@@ -1594,6 +1696,9 @@
PrepareForTestWithSdkBuildComponents,
ccTestFs.AddToFixture(),
prepareForTestWithNativeBridgeTarget,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ android.RegisterApexContributionsBuildComponents(ctx)
+ }),
).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1616,6 +1721,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativeheaders"],
+}
+
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
@@ -1679,6 +1789,9 @@
cc.PrepareForTestWithCcDefaultModules,
PrepareForTestWithSdkBuildComponents,
ccTestFs.AddToFixture(),
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ android.RegisterApexContributionsBuildComponents(ctx)
+ }),
).RunTestWithBp(t, fmt.Sprintf(`
sdk {
name: "mysdk",
@@ -1701,6 +1814,11 @@
checkAndroidBpContents(fmt.Sprintf(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativeheaders"],
+}
+
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
@@ -1750,6 +1868,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativeheaders"],
+}
+
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
@@ -1807,6 +1930,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativeheaders"],
+}
+
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
@@ -1870,6 +1998,15 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_sslnil",
+ "prebuilt_sslempty",
+ "prebuilt_sslnonempty",
+ ],
+}
+
cc_prebuilt_library_shared {
name: "sslnil",
prefer: false,
@@ -1943,6 +2080,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_sslvariants"],
+}
+
cc_prebuilt_library_shared {
name: "sslvariants",
prefer: false,
@@ -2002,6 +2144,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_stubslib"],
+}
+
cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
@@ -2056,6 +2203,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_stubslib"],
+}
+
cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
@@ -2114,6 +2266,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mylib"],
+}
+
cc_prebuilt_library_shared {
name: "mylib",
prefer: false,
@@ -2178,6 +2335,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mynativelib"],
+}
+
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
diff --git a/sdk/compat_config_sdk_test.go b/sdk/compat_config_sdk_test.go
index 45e8e0e..75b5229 100644
--- a/sdk/compat_config_sdk_test.go
+++ b/sdk/compat_config_sdk_test.go
@@ -36,6 +36,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myconfig"],
+}
+
prebuilt_platform_compat_config {
name: "myconfig",
prefer: false,
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 2605fd1..9d0a242 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -46,6 +46,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 1b2b0f1..275860f 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -108,6 +108,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -154,6 +159,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -193,6 +203,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -245,6 +260,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -291,6 +311,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -313,6 +338,9 @@
android.FixtureMergeEnv(map[string]string{
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ }),
).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -395,6 +423,11 @@
checkAndroidBpContents(fmt.Sprintf(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mylib"],
+}
+
java_import {
name: "mylib",
prefer: false,
@@ -459,6 +492,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: [],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -504,6 +542,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -542,6 +585,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_myjavatests"],
+}
+
java_test_import {
name: "myjavatests",
prefer: false,
@@ -582,6 +630,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: ["prebuilt_myjavatests"],
+}
+
java_test_import {
name: "myjavatests",
prefer: false,
@@ -661,6 +714,15 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_exported-system-module",
+ "prebuilt_myjavalib",
+ "prebuilt_my-system-modules",
+ ],
+}
+
java_import {
name: "exported-system-module",
prefer: false,
@@ -790,6 +852,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_my-system-modules"],
+}
+
java_import {
name: "mysdk_system-module",
prefer: false,
@@ -854,6 +921,15 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "myexports.contributions",
+ contents: [
+ "prebuilt_hostjavalib",
+ "prebuilt_androidjavalib",
+ "prebuilt_myjavalib",
+ ],
+}
+
java_import {
name: "hostjavalib",
prefer: false,
@@ -920,6 +996,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -993,6 +1074,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib-foo"],
+}
+
java_sdk_library_import {
name: "myjavalib-foo",
prefer: false,
@@ -1046,6 +1132,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1093,6 +1184,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1147,6 +1243,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1204,6 +1305,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1272,6 +1378,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1320,6 +1431,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1371,6 +1487,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1436,6 +1557,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1509,6 +1635,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1569,6 +1700,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
@@ -1626,6 +1762,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_sdk_library_import {
name: "myjavalib",
prefer: false,
diff --git a/sdk/license_sdk_test.go b/sdk/license_sdk_test.go
index 829edf1..754f019 100644
--- a/sdk/license_sdk_test.go
+++ b/sdk/license_sdk_test.go
@@ -69,6 +69,11 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
diff --git a/sdk/member_trait_test.go b/sdk/member_trait_test.go
index 99caf13..673d6fb 100644
--- a/sdk/member_trait_test.go
+++ b/sdk/member_trait_test.go
@@ -137,6 +137,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -202,6 +207,17 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_myjavalib",
+ "prebuilt_myjavalib_extra",
+ "prebuilt_myjavalib_special",
+ "prebuilt_anotherjavalib",
+ "prebuilt_anotherjavalib_special",
+ ],
+}
+
java_test_import {
name: "myjavalib",
prefer: false,
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index c4df146..f9d49d9 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -118,6 +118,16 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: [
+ "prebuilt_myjavalib",
+ "prebuilt_mypublicjavalib",
+ "prebuilt_mydefaultedjavalib",
+ "prebuilt_myprivatejavalib",
+ ],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -398,6 +408,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_myjavalib"],
+}
+
java_import {
name: "myjavalib",
prefer: false,
@@ -453,6 +468,11 @@
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mysdklibrary"],
+}
+
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
prefer: false,
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 3c0b8ae..c1c4ed6 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -34,6 +34,9 @@
env["SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE"] = targetBuildRelease
}
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ }),
prepareForSdkTestWithApex,
android.FixtureWithRootAndroidBp(sdk+`
@@ -242,6 +245,11 @@
expectedLatestSnapshot := `
// This is auto-generated. DO NOT EDIT.
+apex_contributions_defaults {
+ name: "mysdk.contributions",
+ contents: ["prebuilt_mysdklibrary"],
+}
+
java_sdk_library_import {
name: "mysdklibrary",
prefer: false,
diff --git a/sdk/update.go b/sdk/update.go
index 095e0c2..b8ae38a 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -24,6 +24,7 @@
"android/soong/apex"
"android/soong/cc"
+ "android/soong/java"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -89,19 +90,6 @@
indentLevel int
}
-// generatedFile abstracts operations for writing contents into a file and emit a build rule
-// for the file.
-type generatedFile struct {
- generatedContents
- path android.OutputPath
-}
-
-func newGeneratedFile(ctx android.ModuleContext, path ...string) *generatedFile {
- return &generatedFile{
- path: android.PathForModuleOut(ctx, path...).OutputPath,
- }
-}
-
func (gc *generatedContents) Indent() {
gc.indentLevel++
}
@@ -122,26 +110,6 @@
_, _ = fmt.Fprintf(&(gc.content), format, args...)
}
-func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) {
- rb := android.NewRuleBuilder(pctx, ctx)
-
- content := gf.content.String()
-
- // ninja consumes newline characters in rspfile_content. Prevent it by
- // escaping the backslash in the newline character. The extra backslash
- // is removed when the rspfile is written to the actual script file
- content = strings.ReplaceAll(content, "\n", "\\n")
-
- rb.Command().
- Implicits(implicits).
- Text("echo -n").Text(proptools.ShellEscape(content)).
- // convert \\n to \n
- Text("| sed 's/\\\\n/\\n/g' >").Output(gf.path)
- rb.Command().
- Text("chmod a+x").Output(gf.path)
- rb.Build(gf.path.Base(), "Build "+gf.path.Base())
-}
-
// Collect all the members.
//
// Updates the sdk module with a list of sdkMemberVariantDep instances and details as to which
@@ -170,7 +138,7 @@
var container android.Module
if parent != ctx.Module() {
- container = parent.(android.Module)
+ container = parent
}
minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child)
@@ -179,7 +147,7 @@
s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
sdkVariant: s,
memberType: memberType,
- variant: child.(android.Module),
+ variant: child,
minApiLevel: minApiLevel,
container: container,
export: export,
@@ -375,7 +343,7 @@
snapshotDir := android.PathForModuleOut(ctx, "snapshot")
- bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
+ bp := android.PathForModuleOut(ctx, "snapshot", "Android.bp")
bpFile := &bpFile{
modules: make(map[string]*bpModule),
@@ -389,7 +357,7 @@
sdk: s,
snapshotDir: snapshotDir.OutputPath,
copies: make(map[string]string),
- filesToZip: []android.Path{bp.path},
+ filesToZip: []android.Path{bp},
bpFile: bpFile,
prebuiltModules: make(map[string]*bpModule),
allMembersByName: allMembersByName,
@@ -421,6 +389,7 @@
// Create the prebuilt modules for each of the member modules.
traits := s.gatherTraits()
+ memberNames := []string{} // soong module names of the members. contains the prebuilt_ prefix.
for _, member := range members {
memberType := member.memberType
if !memberType.ArePrebuiltsRequired() {
@@ -442,6 +411,38 @@
prebuiltModule := memberType.AddPrebuiltModule(memberCtx, member)
s.createMemberSnapshot(memberCtx, member, prebuiltModule.(*bpModule))
+
+ if member.memberType != android.LicenseModuleSdkMemberType && !builder.isInternalMember(member.name) {
+ // More exceptions
+ // 1. Skip BCP and SCCP fragments
+ // 2. Skip non-sdk contents of BCP and SCCP fragments
+ //
+ // The non-sdk contents of BCP/SSCP fragments should only be used for dexpreopt and hiddenapi,
+ // and are not available to the rest of the build.
+ if android.InList(member.memberType,
+ []android.SdkMemberType{
+ // bcp
+ java.BootclasspathFragmentSdkMemberType,
+ java.JavaBootLibsSdkMemberType,
+ // sscp
+ java.SystemServerClasspathFragmentSdkMemberType,
+ java.JavaSystemserverLibsSdkMemberType,
+ },
+ ) {
+ continue
+ }
+
+ memberNames = append(memberNames, android.PrebuiltNameFromSource(member.name))
+ }
+ }
+
+ // create an apex_contributions_defaults for this module's sdk.
+ // this module type is supported in V and above.
+ if targetApiLevel.GreaterThan(android.ApiLevelUpsideDownCake) {
+ ac := newModule("apex_contributions_defaults")
+ ac.AddProperty("name", s.Name()+".contributions")
+ ac.AddProperty("contents", memberNames)
+ bpFile.AddModule(ac)
}
// Create a transformer that will transform a module by replacing any references
@@ -463,17 +464,14 @@
}
// generate Android.bp
- bp = newGeneratedFile(ctx, "snapshot", "Android.bp")
- generateBpContents(&bp.generatedContents, bpFile)
-
- contents := bp.content.String()
+ contents := generateBpContents(bpFile)
// If the snapshot is being generated for the current build release then check the syntax to make
// sure that it is compatible.
if targetBuildRelease == buildReleaseCurrent {
syntaxCheckSnapshotBpFile(ctx, contents)
}
- bp.build(pctx, ctx, nil)
+ android.WriteFileRuleVerbatim(ctx, bp, contents)
// Copy the build number file into the snapshot.
builder.CopyToSnapshot(ctx.Config().BuildNumberFile(ctx), BUILD_NUMBER_FILE)
@@ -522,16 +520,14 @@
modules := s.generateInfoData(ctx, memberVariantDeps)
// Output the modules information as pretty printed JSON.
- info := newGeneratedFile(ctx, fmt.Sprintf("%s%s.info", ctx.ModuleName(), snapshotFileSuffix))
+ info := android.PathForModuleOut(ctx, fmt.Sprintf("%s%s.info", ctx.ModuleName(), snapshotFileSuffix))
output, err := json.MarshalIndent(modules, "", " ")
if err != nil {
ctx.ModuleErrorf("error generating %q: %s", info, err)
}
builder.infoContents = string(output)
- info.generatedContents.UnindentedPrintf("%s", output)
- info.build(pctx, ctx, nil)
- infoPath := info.path
- installedInfo := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), infoPath.Base(), infoPath)
+ android.WriteFileRuleVerbatim(ctx, info, builder.infoContents)
+ installedInfo := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), info.Base(), info)
s.infoFile = android.OptionalPathForPath(installedInfo)
// Install the zip, making sure that the info file has been installed as well.
@@ -718,105 +714,6 @@
}
}
-// snapshotModuleStaticProperties contains snapshot static (i.e. not dynamically generated) properties.
-type snapshotModuleStaticProperties struct {
- Compile_multilib string `android:"arch_variant"`
-}
-
-// combinedSnapshotModuleProperties are the properties that are associated with the snapshot module.
-type combinedSnapshotModuleProperties struct {
- // The sdk variant from which this information was collected.
- sdkVariant *sdk
-
- // Static snapshot module properties.
- staticProperties *snapshotModuleStaticProperties
-
- // The dynamically generated member list properties.
- dynamicProperties interface{}
-}
-
-// collateSnapshotModuleInfo collates all the snapshot module info from supplied sdk variants.
-func (s *sdk) collateSnapshotModuleInfo(ctx android.BaseModuleContext, sdkVariants []*sdk, memberVariantDeps []sdkMemberVariantDep) []*combinedSnapshotModuleProperties {
- sdkVariantToCombinedProperties := map[*sdk]*combinedSnapshotModuleProperties{}
- var list []*combinedSnapshotModuleProperties
- for _, sdkVariant := range sdkVariants {
- staticProperties := &snapshotModuleStaticProperties{
- Compile_multilib: sdkVariant.multilibUsages.String(),
- }
- dynamicProperties := s.dynamicSdkMemberTypes.createMemberTypeListProperties()
-
- combinedProperties := &combinedSnapshotModuleProperties{
- sdkVariant: sdkVariant,
- staticProperties: staticProperties,
- dynamicProperties: dynamicProperties,
- }
- sdkVariantToCombinedProperties[sdkVariant] = combinedProperties
-
- list = append(list, combinedProperties)
- }
-
- for _, memberVariantDep := range memberVariantDeps {
- // If the member dependency is internal then do not add the dependency to the snapshot member
- // list properties.
- if !memberVariantDep.export {
- continue
- }
-
- combined := sdkVariantToCombinedProperties[memberVariantDep.sdkVariant]
- memberListProperty := s.memberTypeListProperty(memberVariantDep.memberType)
- memberName := ctx.OtherModuleName(memberVariantDep.variant)
-
- if memberListProperty.getter == nil {
- continue
- }
-
- // Append the member to the appropriate list, if it is not already present in the list.
- memberList := memberListProperty.getter(combined.dynamicProperties)
- if !android.InList(memberName, memberList) {
- memberList = append(memberList, memberName)
- }
- memberListProperty.setter(combined.dynamicProperties, memberList)
- }
-
- return list
-}
-
-func (s *sdk) optimizeSnapshotModuleProperties(ctx android.ModuleContext, list []*combinedSnapshotModuleProperties) *combinedSnapshotModuleProperties {
-
- // Extract the dynamic properties and add them to a list of propertiesContainer.
- propertyContainers := []propertiesContainer{}
- for _, i := range list {
- propertyContainers = append(propertyContainers, sdkVariantPropertiesContainer{
- sdkVariant: i.sdkVariant,
- properties: i.dynamicProperties,
- })
- }
-
- // Extract the common members, removing them from the original properties.
- commonDynamicProperties := s.dynamicSdkMemberTypes.createMemberTypeListProperties()
- extractor := newCommonValueExtractor(commonDynamicProperties)
- extractCommonProperties(ctx, extractor, commonDynamicProperties, propertyContainers)
-
- // Extract the static properties and add them to a list of propertiesContainer.
- propertyContainers = []propertiesContainer{}
- for _, i := range list {
- propertyContainers = append(propertyContainers, sdkVariantPropertiesContainer{
- sdkVariant: i.sdkVariant,
- properties: i.staticProperties,
- })
- }
-
- commonStaticProperties := &snapshotModuleStaticProperties{}
- extractor = newCommonValueExtractor(commonStaticProperties)
- extractCommonProperties(ctx, extractor, &commonStaticProperties, propertyContainers)
-
- return &combinedSnapshotModuleProperties{
- sdkVariant: nil,
- staticProperties: commonStaticProperties,
- dynamicProperties: commonDynamicProperties,
- }
-}
-
type propertyTag struct {
name string
}
@@ -885,7 +782,8 @@
}
}
-func generateBpContents(contents *generatedContents, bpFile *bpFile) {
+func generateBpContents(bpFile *bpFile) string {
+ contents := &generatedContents{}
contents.IndentedPrintf("// This is auto-generated. DO NOT EDIT.\n")
for _, bpModule := range bpFile.order {
contents.IndentedPrintf("\n")
@@ -893,6 +791,7 @@
outputPropertySet(contents, bpModule.bpPropertySet)
contents.IndentedPrintf("}\n")
}
+ return contents.content.String()
}
func outputPropertySet(contents *generatedContents, set *bpPropertySet) {
@@ -1007,7 +906,7 @@
contents.IndentedPrintf("}")
default:
- panic(fmt.Errorf("Unknown type: %T of value %#v", value, value))
+ panic(fmt.Errorf("unknown type: %T of value %#v", value, value))
}
}
@@ -1018,9 +917,7 @@
}
func (s *sdk) GetAndroidBpContentsForTests() string {
- contents := &generatedContents{}
- generateBpContents(contents, s.builderForTests.bpFile)
- return contents.content.String()
+ return generateBpContents(s.builderForTests.bpFile)
}
func (s *sdk) GetInfoContentsForTests() string {
@@ -1334,7 +1231,7 @@
case "lib64":
return m | multilib64
default:
- panic(fmt.Errorf("Unknown Multilib field in ArchType, expected 'lib32' or 'lib64', found %q", multilib))
+ panic(fmt.Errorf("unknown Multilib field in ArchType, expected 'lib32' or 'lib64', found %q", multilib))
}
}
@@ -1349,7 +1246,7 @@
case multilibBoth:
return "both"
default:
- panic(fmt.Errorf("Unknown multilib value, found %b, expected one of %b, %b, %b or %b",
+ panic(fmt.Errorf("unknown multilib value, found %b, expected one of %b, %b, %b or %b",
m, multilibNone, multilib32, multilib64, multilibBoth))
}
}
@@ -2302,20 +2199,6 @@
optimizableProperties() interface{}
}
-// A wrapper for sdk variant related properties to allow them to be optimized.
-type sdkVariantPropertiesContainer struct {
- sdkVariant *sdk
- properties interface{}
-}
-
-func (c sdkVariantPropertiesContainer) optimizableProperties() interface{} {
- return c.properties
-}
-
-func (c sdkVariantPropertiesContainer) String() string {
- return c.sdkVariant.String()
-}
-
// Extract common properties from a slice of property structures of the same type.
//
// All the property structures must be of the same type.
diff --git a/starlark_import/README.md b/starlark_import/README.md
deleted file mode 100644
index e444759..0000000
--- a/starlark_import/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# starlark_import package
-
-This allows soong to read constant information from starlark files. At package initialization
-time, soong will read `build/bazel/constants_exported_to_soong.bzl`, and then make the
-variables from that file available via `starlark_import.GetStarlarkValue()`. So to import
-a new variable, it must be added to `constants_exported_to_soong.bzl` and then it can
-be accessed by name.
-
-Only constant information can be read, since this is not a full bazel execution but a
-standalone starlark interpreter. This means you can't use bazel contructs like `rule`,
-`provider`, `select`, `glob`, etc.
-
-All starlark files that were loaded must be added as ninja deps that cause soong to rerun.
-The loaded files can be retrieved via `starlark_import.GetNinjaDeps()`.
diff --git a/starlark_import/starlark_import.go b/starlark_import/starlark_import.go
deleted file mode 100644
index ebe4247..0000000
--- a/starlark_import/starlark_import.go
+++ /dev/null
@@ -1,306 +0,0 @@
-// 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 starlark_import
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "sort"
- "strings"
- "sync"
- "time"
-
- "go.starlark.net/starlark"
- "go.starlark.net/starlarkjson"
- "go.starlark.net/starlarkstruct"
-)
-
-func init() {
- go func() {
- startTime := time.Now()
- v, d, err := runStarlarkFile("//build/bazel/constants_exported_to_soong.bzl")
- endTime := time.Now()
- //fmt.Fprintf(os.Stderr, "starlark run time: %s\n", endTime.Sub(startTime).String())
- globalResult.Set(starlarkResult{
- values: v,
- ninjaDeps: d,
- err: err,
- startTime: startTime,
- endTime: endTime,
- })
- }()
-}
-
-type starlarkResult struct {
- values starlark.StringDict
- ninjaDeps []string
- err error
- startTime time.Time
- endTime time.Time
-}
-
-// setOnce wraps a value and exposes Set() and Get() accessors for it.
-// The Get() calls will block until a Set() has been called.
-// A second call to Set() will panic.
-// setOnce must be created using newSetOnce()
-type setOnce[T any] struct {
- value T
- lock sync.Mutex
- wg sync.WaitGroup
- isSet bool
-}
-
-func (o *setOnce[T]) Set(value T) {
- o.lock.Lock()
- defer o.lock.Unlock()
- if o.isSet {
- panic("Value already set")
- }
-
- o.value = value
- o.isSet = true
- o.wg.Done()
-}
-
-func (o *setOnce[T]) Get() T {
- if !o.isSet {
- o.wg.Wait()
- }
- return o.value
-}
-
-func newSetOnce[T any]() *setOnce[T] {
- result := &setOnce[T]{}
- result.wg.Add(1)
- return result
-}
-
-var globalResult = newSetOnce[starlarkResult]()
-
-func GetStarlarkValue[T any](key string) (T, error) {
- result := globalResult.Get()
- if result.err != nil {
- var zero T
- return zero, result.err
- }
- if !result.values.Has(key) {
- var zero T
- return zero, fmt.Errorf("a starlark variable by that name wasn't found, did you update //build/bazel/constants_exported_to_soong.bzl?")
- }
- return Unmarshal[T](result.values[key])
-}
-
-func GetNinjaDeps() ([]string, error) {
- result := globalResult.Get()
- if result.err != nil {
- return nil, result.err
- }
- return result.ninjaDeps, nil
-}
-
-func getTopDir() (string, error) {
- // It's hard to communicate the top dir to this package in any other way than reading the
- // arguments directly, because we need to know this at package initialization time. Many
- // soong constants that we'd like to read from starlark are initialized during package
- // initialization.
- for i, arg := range os.Args {
- if arg == "--top" {
- if i < len(os.Args)-1 && os.Args[i+1] != "" {
- return os.Args[i+1], nil
- }
- }
- }
-
- // When running tests, --top is not passed. Instead, search for the top dir manually
- cwd, err := os.Getwd()
- if err != nil {
- return "", err
- }
- for cwd != "/" {
- if _, err := os.Stat(filepath.Join(cwd, "build/soong/soong_ui.bash")); err == nil {
- return cwd, nil
- }
- cwd = filepath.Dir(cwd)
- }
- return "", fmt.Errorf("could not find top dir")
-}
-
-const callerDirKey = "callerDir"
-
-type modentry struct {
- globals starlark.StringDict
- err error
-}
-
-func unsupportedMethod(t *starlark.Thread, fn *starlark.Builtin, _ starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) {
- return nil, fmt.Errorf("%sthis file is read by soong, and must therefore be pure starlark and include only constant information. %q is not allowed", t.CallStack().String(), fn.Name())
-}
-
-var builtins = starlark.StringDict{
- "aspect": starlark.NewBuiltin("aspect", unsupportedMethod),
- "glob": starlark.NewBuiltin("glob", unsupportedMethod),
- "json": starlarkjson.Module,
- "provider": starlark.NewBuiltin("provider", unsupportedMethod),
- "rule": starlark.NewBuiltin("rule", unsupportedMethod),
- "struct": starlark.NewBuiltin("struct", starlarkstruct.Make),
- "select": starlark.NewBuiltin("select", unsupportedMethod),
- "transition": starlark.NewBuiltin("transition", unsupportedMethod),
-}
-
-// Takes a module name (the first argument to the load() function) and returns the path
-// it's trying to load, stripping out leading //, and handling leading :s.
-func cleanModuleName(moduleName string, callerDir string) (string, error) {
- if strings.Count(moduleName, ":") > 1 {
- return "", fmt.Errorf("at most 1 colon must be present in starlark path: %s", moduleName)
- }
-
- // We don't have full support for external repositories, but at least support skylib's dicts.
- if moduleName == "@bazel_skylib//lib:dicts.bzl" {
- return "external/bazel-skylib/lib/dicts.bzl", nil
- }
-
- localLoad := false
- if strings.HasPrefix(moduleName, "@//") {
- moduleName = moduleName[3:]
- } else if strings.HasPrefix(moduleName, "//") {
- moduleName = moduleName[2:]
- } else if strings.HasPrefix(moduleName, ":") {
- moduleName = moduleName[1:]
- localLoad = true
- } else {
- return "", fmt.Errorf("load path must start with // or :")
- }
-
- if ix := strings.LastIndex(moduleName, ":"); ix >= 0 {
- moduleName = moduleName[:ix] + string(os.PathSeparator) + moduleName[ix+1:]
- }
-
- if filepath.Clean(moduleName) != moduleName {
- return "", fmt.Errorf("load path must be clean, found: %s, expected: %s", moduleName, filepath.Clean(moduleName))
- }
- if strings.HasPrefix(moduleName, "../") {
- return "", fmt.Errorf("load path must not start with ../: %s", moduleName)
- }
- if strings.HasPrefix(moduleName, "/") {
- return "", fmt.Errorf("load path starts with /, use // for a absolute path: %s", moduleName)
- }
-
- if localLoad {
- return filepath.Join(callerDir, moduleName), nil
- }
-
- return moduleName, nil
-}
-
-// loader implements load statement. The format of the loaded module URI is
-//
-// [//path]:base
-//
-// The file path is $ROOT/path/base if path is present, <caller_dir>/base otherwise.
-func loader(thread *starlark.Thread, module string, topDir string, moduleCache map[string]*modentry, moduleCacheLock *sync.Mutex, filesystem map[string]string) (starlark.StringDict, error) {
- modulePath, err := cleanModuleName(module, thread.Local(callerDirKey).(string))
- if err != nil {
- return nil, err
- }
- moduleCacheLock.Lock()
- e, ok := moduleCache[modulePath]
- if e == nil {
- if ok {
- moduleCacheLock.Unlock()
- return nil, fmt.Errorf("cycle in load graph")
- }
-
- // Add a placeholder to indicate "load in progress".
- moduleCache[modulePath] = nil
- moduleCacheLock.Unlock()
-
- childThread := &starlark.Thread{Name: "exec " + module, Load: thread.Load}
-
- // Cheating for the sake of testing:
- // propagate starlarktest's Reporter key, otherwise testing
- // the load function may cause panic in starlarktest code.
- const testReporterKey = "Reporter"
- if v := thread.Local(testReporterKey); v != nil {
- childThread.SetLocal(testReporterKey, v)
- }
-
- childThread.SetLocal(callerDirKey, filepath.Dir(modulePath))
-
- if filesystem != nil {
- globals, err := starlark.ExecFile(childThread, filepath.Join(topDir, modulePath), filesystem[modulePath], builtins)
- e = &modentry{globals, err}
- } else {
- globals, err := starlark.ExecFile(childThread, filepath.Join(topDir, modulePath), nil, builtins)
- e = &modentry{globals, err}
- }
-
- // Update the cache.
- moduleCacheLock.Lock()
- moduleCache[modulePath] = e
- }
- moduleCacheLock.Unlock()
- return e.globals, e.err
-}
-
-// Run runs the given starlark file and returns its global variables and a list of all starlark
-// files that were loaded. The top dir for starlark's // is found via getTopDir().
-func runStarlarkFile(filename string) (starlark.StringDict, []string, error) {
- topDir, err := getTopDir()
- if err != nil {
- return nil, nil, err
- }
- return runStarlarkFileWithFilesystem(filename, topDir, nil)
-}
-
-func runStarlarkFileWithFilesystem(filename string, topDir string, filesystem map[string]string) (starlark.StringDict, []string, error) {
- if !strings.HasPrefix(filename, "//") && !strings.HasPrefix(filename, ":") {
- filename = "//" + filename
- }
- filename, err := cleanModuleName(filename, "")
- if err != nil {
- return nil, nil, err
- }
- moduleCache := make(map[string]*modentry)
- moduleCache[filename] = nil
- moduleCacheLock := &sync.Mutex{}
- mainThread := &starlark.Thread{
- Name: "main",
- Print: func(_ *starlark.Thread, msg string) {
- // Ignore prints
- },
- Load: func(thread *starlark.Thread, module string) (starlark.StringDict, error) {
- return loader(thread, module, topDir, moduleCache, moduleCacheLock, filesystem)
- },
- }
- mainThread.SetLocal(callerDirKey, filepath.Dir(filename))
-
- var result starlark.StringDict
- if filesystem != nil {
- result, err = starlark.ExecFile(mainThread, filepath.Join(topDir, filename), filesystem[filename], builtins)
- } else {
- result, err = starlark.ExecFile(mainThread, filepath.Join(topDir, filename), nil, builtins)
- }
- return result, sortedStringKeys(moduleCache), err
-}
-
-func sortedStringKeys(m map[string]*modentry) []string {
- s := make([]string, 0, len(m))
- for k := range m {
- s = append(s, k)
- }
- sort.Strings(s)
- return s
-}
diff --git a/starlark_import/starlark_import_test.go b/starlark_import/starlark_import_test.go
deleted file mode 100644
index 8a58e3b..0000000
--- a/starlark_import/starlark_import_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// 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 starlark_import
-
-import (
- "strings"
- "testing"
-
- "go.starlark.net/starlark"
-)
-
-func TestBasic(t *testing.T) {
- globals, _, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
- "a.bzl": `
-my_string = "hello, world!"
-`})
- if err != nil {
- t.Error(err)
- return
- }
-
- if globals["my_string"].(starlark.String) != "hello, world!" {
- t.Errorf("Expected %q, got %q", "hello, world!", globals["my_string"].String())
- }
-}
-
-func TestLoad(t *testing.T) {
- globals, _, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
- "a.bzl": `
-load("//b.bzl", _b_string = "my_string")
-my_string = "hello, " + _b_string
-`,
- "b.bzl": `
-my_string = "world!"
-`})
- if err != nil {
- t.Error(err)
- return
- }
-
- if globals["my_string"].(starlark.String) != "hello, world!" {
- t.Errorf("Expected %q, got %q", "hello, world!", globals["my_string"].String())
- }
-}
-
-func TestLoadRelative(t *testing.T) {
- globals, ninjaDeps, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
- "a.bzl": `
-load(":b.bzl", _b_string = "my_string")
-load("//foo/c.bzl", _c_string = "my_string")
-my_string = "hello, " + _b_string
-c_string = _c_string
-`,
- "b.bzl": `
-my_string = "world!"
-`,
- "foo/c.bzl": `
-load(":d.bzl", _d_string = "my_string")
-my_string = "hello, " + _d_string
-`,
- "foo/d.bzl": `
-my_string = "world!"
-`})
- if err != nil {
- t.Error(err)
- return
- }
-
- if globals["my_string"].(starlark.String) != "hello, world!" {
- t.Errorf("Expected %q, got %q", "hello, world!", globals["my_string"].String())
- }
-
- expectedNinjaDeps := []string{
- "a.bzl",
- "b.bzl",
- "foo/c.bzl",
- "foo/d.bzl",
- }
- if !slicesEqual(ninjaDeps, expectedNinjaDeps) {
- t.Errorf("Expected %v ninja deps, got %v", expectedNinjaDeps, ninjaDeps)
- }
-}
-
-func TestLoadCycle(t *testing.T) {
- _, _, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
- "a.bzl": `
-load(":b.bzl", _b_string = "my_string")
-my_string = "hello, " + _b_string
-`,
- "b.bzl": `
-load(":a.bzl", _a_string = "my_string")
-my_string = "hello, " + _a_string
-`})
- if err == nil || !strings.Contains(err.Error(), "cycle in load graph") {
- t.Errorf("Expected cycle in load graph, got: %v", err)
- return
- }
-}
-
-func slicesEqual[T comparable](a []T, b []T) bool {
- if len(a) != len(b) {
- return false
- }
- for i := range a {
- if a[i] != b[i] {
- return false
- }
- }
- return true
-}
diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go
deleted file mode 100644
index b243471..0000000
--- a/starlark_import/unmarshal.go
+++ /dev/null
@@ -1,304 +0,0 @@
-// 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 starlark_import
-
-import (
- "fmt"
- "math"
- "reflect"
- "unsafe"
-
- "go.starlark.net/starlark"
- "go.starlark.net/starlarkstruct"
-)
-
-func Unmarshal[T any](value starlark.Value) (T, error) {
- x, err := UnmarshalReflect(value, reflect.TypeOf((*T)(nil)).Elem())
- return x.Interface().(T), err
-}
-
-func UnmarshalReflect(value starlark.Value, ty reflect.Type) (reflect.Value, error) {
- if ty == reflect.TypeOf((*starlark.Value)(nil)).Elem() {
- return reflect.ValueOf(value), nil
- }
- zero := reflect.Zero(ty)
- if value == nil {
- panic("nil value")
- }
- var result reflect.Value
- if ty.Kind() == reflect.Interface {
- var err error
- ty, err = typeOfStarlarkValue(value)
- if err != nil {
- return zero, err
- }
- }
- if ty.Kind() == reflect.Map {
- result = reflect.MakeMap(ty)
- } else {
- result = reflect.Indirect(reflect.New(ty))
- }
-
- switch v := value.(type) {
- case starlark.String:
- if result.Type().Kind() != reflect.String {
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- result.SetString(v.GoString())
- case starlark.Int:
- signedValue, signedOk := v.Int64()
- unsignedValue, unsignedOk := v.Uint64()
- switch result.Type().Kind() {
- case reflect.Int64:
- if !signedOk {
- return zero, fmt.Errorf("starlark int didn't fit in go int64")
- }
- result.SetInt(signedValue)
- case reflect.Int32:
- if !signedOk || signedValue > math.MaxInt32 || signedValue < math.MinInt32 {
- return zero, fmt.Errorf("starlark int didn't fit in go int32")
- }
- result.SetInt(signedValue)
- case reflect.Int16:
- if !signedOk || signedValue > math.MaxInt16 || signedValue < math.MinInt16 {
- return zero, fmt.Errorf("starlark int didn't fit in go int16")
- }
- result.SetInt(signedValue)
- case reflect.Int8:
- if !signedOk || signedValue > math.MaxInt8 || signedValue < math.MinInt8 {
- return zero, fmt.Errorf("starlark int didn't fit in go int8")
- }
- result.SetInt(signedValue)
- case reflect.Int:
- if !signedOk || signedValue > math.MaxInt || signedValue < math.MinInt {
- return zero, fmt.Errorf("starlark int didn't fit in go int")
- }
- result.SetInt(signedValue)
- case reflect.Uint64:
- if !unsignedOk {
- return zero, fmt.Errorf("starlark int didn't fit in go uint64")
- }
- result.SetUint(unsignedValue)
- case reflect.Uint32:
- if !unsignedOk || unsignedValue > math.MaxUint32 {
- return zero, fmt.Errorf("starlark int didn't fit in go uint32")
- }
- result.SetUint(unsignedValue)
- case reflect.Uint16:
- if !unsignedOk || unsignedValue > math.MaxUint16 {
- return zero, fmt.Errorf("starlark int didn't fit in go uint16")
- }
- result.SetUint(unsignedValue)
- case reflect.Uint8:
- if !unsignedOk || unsignedValue > math.MaxUint8 {
- return zero, fmt.Errorf("starlark int didn't fit in go uint8")
- }
- result.SetUint(unsignedValue)
- case reflect.Uint:
- if !unsignedOk || unsignedValue > math.MaxUint {
- return zero, fmt.Errorf("starlark int didn't fit in go uint")
- }
- result.SetUint(unsignedValue)
- default:
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- case starlark.Float:
- f := float64(v)
- switch result.Type().Kind() {
- case reflect.Float64:
- result.SetFloat(f)
- case reflect.Float32:
- if f > math.MaxFloat32 || f < -math.MaxFloat32 {
- return zero, fmt.Errorf("starlark float didn't fit in go float32")
- }
- result.SetFloat(f)
- default:
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- case starlark.Bool:
- if result.Type().Kind() != reflect.Bool {
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- result.SetBool(bool(v))
- case starlark.Tuple:
- if result.Type().Kind() != reflect.Slice {
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- elemType := result.Type().Elem()
- // TODO: Add this grow call when we're on go 1.20
- //result.Grow(v.Len())
- for i := 0; i < v.Len(); i++ {
- elem, err := UnmarshalReflect(v.Index(i), elemType)
- if err != nil {
- return zero, err
- }
- result = reflect.Append(result, elem)
- }
- case *starlark.List:
- if result.Type().Kind() != reflect.Slice {
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- elemType := result.Type().Elem()
- // TODO: Add this grow call when we're on go 1.20
- //result.Grow(v.Len())
- for i := 0; i < v.Len(); i++ {
- elem, err := UnmarshalReflect(v.Index(i), elemType)
- if err != nil {
- return zero, err
- }
- result = reflect.Append(result, elem)
- }
- case *starlark.Dict:
- if result.Type().Kind() != reflect.Map {
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- keyType := result.Type().Key()
- valueType := result.Type().Elem()
- for _, pair := range v.Items() {
- key := pair.Index(0)
- value := pair.Index(1)
-
- unmarshalledKey, err := UnmarshalReflect(key, keyType)
- if err != nil {
- return zero, err
- }
- unmarshalledValue, err := UnmarshalReflect(value, valueType)
- if err != nil {
- return zero, err
- }
-
- result.SetMapIndex(unmarshalledKey, unmarshalledValue)
- }
- case *starlarkstruct.Struct:
- if result.Type().Kind() != reflect.Struct {
- return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
- }
- if result.NumField() != len(v.AttrNames()) {
- return zero, fmt.Errorf("starlark struct and go struct have different number of fields (%d and %d)", len(v.AttrNames()), result.NumField())
- }
- for _, attrName := range v.AttrNames() {
- attr, err := v.Attr(attrName)
- if err != nil {
- return zero, err
- }
-
- // TODO(b/279787235): this should probably support tags to rename the field
- resultField := result.FieldByName(attrName)
- if resultField == (reflect.Value{}) {
- return zero, fmt.Errorf("starlark struct had field %s, but requested struct type did not", attrName)
- }
- // This hack allows us to change unexported fields
- resultField = reflect.NewAt(resultField.Type(), unsafe.Pointer(resultField.UnsafeAddr())).Elem()
- x, err := UnmarshalReflect(attr, resultField.Type())
- if err != nil {
- return zero, err
- }
- resultField.Set(x)
- }
- default:
- return zero, fmt.Errorf("unimplemented starlark type: %s", value.Type())
- }
-
- return result, nil
-}
-
-func typeOfStarlarkValue(value starlark.Value) (reflect.Type, error) {
- var err error
- switch v := value.(type) {
- case starlark.String:
- return reflect.TypeOf(""), nil
- case *starlark.List:
- innerType := reflect.TypeOf("")
- if v.Len() > 0 {
- innerType, err = typeOfStarlarkValue(v.Index(0))
- if err != nil {
- return nil, err
- }
- }
- for i := 1; i < v.Len(); i++ {
- innerTypeI, err := typeOfStarlarkValue(v.Index(i))
- if err != nil {
- return nil, err
- }
- if innerType != innerTypeI {
- return nil, fmt.Errorf("List must contain elements of entirely the same type, found %v and %v", innerType, innerTypeI)
- }
- }
- return reflect.SliceOf(innerType), nil
- case *starlark.Dict:
- keyType := reflect.TypeOf("")
- valueType := reflect.TypeOf("")
- keys := v.Keys()
- if v.Len() > 0 {
- firstKey := keys[0]
- keyType, err = typeOfStarlarkValue(firstKey)
- if err != nil {
- return nil, err
- }
- firstValue, found, err := v.Get(firstKey)
- if !found {
- err = fmt.Errorf("value not found")
- }
- if err != nil {
- return nil, err
- }
- valueType, err = typeOfStarlarkValue(firstValue)
- if err != nil {
- return nil, err
- }
- }
- for _, key := range keys {
- keyTypeI, err := typeOfStarlarkValue(key)
- if err != nil {
- return nil, err
- }
- if keyType != keyTypeI {
- return nil, fmt.Errorf("dict must contain elements of entirely the same type, found %v and %v", keyType, keyTypeI)
- }
- value, found, err := v.Get(key)
- if !found {
- err = fmt.Errorf("value not found")
- }
- if err != nil {
- return nil, err
- }
- valueTypeI, err := typeOfStarlarkValue(value)
- if valueType.Kind() != reflect.Interface && valueTypeI != valueType {
- // If we see conflicting value types, change the result value type to an empty interface
- valueType = reflect.TypeOf([]interface{}{}).Elem()
- }
- }
- return reflect.MapOf(keyType, valueType), nil
- case starlark.Int:
- return reflect.TypeOf(0), nil
- case starlark.Float:
- return reflect.TypeOf(0.0), nil
- case starlark.Bool:
- return reflect.TypeOf(true), nil
- default:
- return nil, fmt.Errorf("unimplemented starlark type: %s", value.Type())
- }
-}
-
-// UnmarshalNoneable is like Unmarshal, but it will accept None as the top level (but not nested)
-// starlark value. If the value is None, a nil pointer will be returned, otherwise a pointer
-// to the result of Unmarshal will be returned.
-func UnmarshalNoneable[T any](value starlark.Value) (*T, error) {
- if _, ok := value.(starlark.NoneType); ok {
- return nil, nil
- }
- ret, err := Unmarshal[T](value)
- return &ret, err
-}
diff --git a/starlark_import/unmarshal_test.go b/starlark_import/unmarshal_test.go
deleted file mode 100644
index bc0ea4c..0000000
--- a/starlark_import/unmarshal_test.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// 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 starlark_import
-
-import (
- "reflect"
- "testing"
-
- "go.starlark.net/starlark"
-)
-
-func createStarlarkValue(t *testing.T, code string) starlark.Value {
- t.Helper()
- result, err := starlark.ExecFile(&starlark.Thread{}, "main.bzl", "x = "+code, builtins)
- if err != nil {
- panic(err)
- }
- return result["x"]
-}
-
-func TestUnmarshalConcreteType(t *testing.T) {
- x, err := Unmarshal[string](createStarlarkValue(t, `"foo"`))
- if err != nil {
- t.Error(err)
- return
- }
- if x != "foo" {
- t.Errorf(`Expected "foo", got %q`, x)
- }
-}
-
-func TestUnmarshalConcreteTypeWithInterfaces(t *testing.T) {
- x, err := Unmarshal[map[string]map[string]interface{}](createStarlarkValue(t,
- `{"foo": {"foo2": "foo3"}, "bar": {"bar2": ["bar3"]}}`))
- if err != nil {
- t.Error(err)
- return
- }
- expected := map[string]map[string]interface{}{
- "foo": {"foo2": "foo3"},
- "bar": {"bar2": []string{"bar3"}},
- }
- if !reflect.DeepEqual(x, expected) {
- t.Errorf(`Expected %v, got %v`, expected, x)
- }
-}
-
-func TestUnmarshalToStarlarkValue(t *testing.T) {
- x, err := Unmarshal[map[string]starlark.Value](createStarlarkValue(t,
- `{"foo": "Hi", "bar": None}`))
- if err != nil {
- t.Error(err)
- return
- }
- if x["foo"].(starlark.String).GoString() != "Hi" {
- t.Errorf("Expected \"Hi\", got: %q", x["foo"].(starlark.String).GoString())
- }
- if x["bar"].Type() != "NoneType" {
- t.Errorf("Expected \"NoneType\", got: %q", x["bar"].Type())
- }
-}
-
-func TestUnmarshal(t *testing.T) {
- testCases := []struct {
- input string
- expected interface{}
- }{
- {
- input: `"foo"`,
- expected: "foo",
- },
- {
- input: `5`,
- expected: 5,
- },
- {
- input: `["foo", "bar"]`,
- expected: []string{"foo", "bar"},
- },
- {
- input: `("foo", "bar")`,
- expected: []string{"foo", "bar"},
- },
- {
- input: `("foo",5)`,
- expected: []interface{}{"foo", 5},
- },
- {
- input: `{"foo": 5, "bar": 10}`,
- expected: map[string]int{"foo": 5, "bar": 10},
- },
- {
- input: `{"foo": ["qux"], "bar": []}`,
- expected: map[string][]string{"foo": {"qux"}, "bar": nil},
- },
- {
- input: `struct(Foo="foo", Bar=5)`,
- expected: struct {
- Foo string
- Bar int
- }{Foo: "foo", Bar: 5},
- },
- {
- // Unexported fields version of the above
- input: `struct(foo="foo", bar=5)`,
- expected: struct {
- foo string
- bar int
- }{foo: "foo", bar: 5},
- },
- {
- input: `{"foo": "foo2", "bar": ["bar2"], "baz": 5, "qux": {"qux2": "qux3"}, "quux": {"quux2": "quux3", "quux4": 5}}`,
- expected: map[string]interface{}{
- "foo": "foo2",
- "bar": []string{"bar2"},
- "baz": 5,
- "qux": map[string]string{"qux2": "qux3"},
- "quux": map[string]interface{}{
- "quux2": "quux3",
- "quux4": 5,
- },
- },
- },
- }
-
- for _, tc := range testCases {
- x, err := UnmarshalReflect(createStarlarkValue(t, tc.input), reflect.TypeOf(tc.expected))
- if err != nil {
- t.Error(err)
- continue
- }
- if !reflect.DeepEqual(x.Interface(), tc.expected) {
- t.Errorf(`Expected %#v, got %#v`, tc.expected, x.Interface())
- }
- }
-}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 2258232..b9b68be 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -54,15 +54,13 @@
}
type syspropRustGenRule struct {
- android.ModuleBase
+ *rust.BaseSourceProvider
- properties syspropGenProperties
-
- genSrcs android.Paths
+ properties rustLibraryProperties
}
var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
-var _ android.OutputFileProducer = (*syspropRustGenRule)(nil)
+var _ rust.SourceProvider = (*syspropRustGenRule)(nil)
var (
syspropJava = pctx.AndroidStaticRule("syspropJava",
@@ -144,7 +142,7 @@
// syspropRustGenRule module generates rust source files containing generated rust APIs.
// It also depends on check api rule, so api check has to pass to use sysprop_library.
-func (g *syspropRustGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (g *syspropRustGenRule) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
var checkApiFileTimeStamp android.WritablePath
ctx.VisitDirectDeps(func(dep android.Module) {
@@ -153,26 +151,47 @@
}
})
- for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
- syspropDir := strings.TrimSuffix(syspropFile.String(), syspropFile.Ext())
- outputDir := android.PathForModuleGen(ctx, syspropDir, "src")
- libPath := android.PathForModuleGen(ctx, syspropDir, "src", "lib.rs")
- parsersPath := android.PathForModuleGen(ctx, syspropDir, "src", "gen_parsers_and_formatters.rs")
+ outputDir := android.PathForModuleOut(ctx, "src")
+ libFile := outputDir.Join(ctx, "lib.rs")
+ g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, libFile)
+ libFileLines := []string{"//! Autogenerated system property accessors."}
+
+ for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Sysprop_srcs) {
+ moduleName := syspropPathToRustModule(syspropFile)
+ moduleDir := outputDir.Join(ctx, moduleName)
+ modulePath := moduleDir.Join(ctx, "mod.rs")
ctx.Build(pctx, android.BuildParams{
Rule: syspropRust,
Description: "sysprop_rust " + syspropFile.Rel(),
- Outputs: android.WritablePaths{libPath, parsersPath},
+ Output: modulePath,
Input: syspropFile,
Implicit: checkApiFileTimeStamp,
Args: map[string]string{
"scope": g.properties.Scope,
- "out_dir": outputDir.String(),
+ "out_dir": moduleDir.String(),
},
})
- g.genSrcs = append(g.genSrcs, libPath, parsersPath)
+ g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, modulePath)
+ libFileLines = append(libFileLines, fmt.Sprintf("pub mod %s;", moduleName))
}
+
+ libFileSource := strings.Join(libFileLines, "\n")
+ android.WriteFileRule(ctx, libFile, libFileSource)
+
+ return libFile
+}
+
+func (g *syspropRustGenRule) SourceProviderProps() []interface{} {
+ return append(g.BaseSourceProvider.SourceProviderProps(), &g.Properties)
+}
+
+// syspropPathToRustModule takes a path to a .sysprop file and returns the name to use for the
+// corresponding Rust module.
+func syspropPathToRustModule(syspropFilename android.Path) string {
+ filenameBase := strings.TrimSuffix(syspropFilename.Base(), ".sysprop")
+ return strings.ToLower(filenameBase)
}
func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -181,15 +200,13 @@
ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
}
-func (g *syspropRustGenRule) OutputFiles(_ string) (android.Paths, error) {
- return g.genSrcs, nil
-}
-
func syspropRustGenFactory() android.Module {
- g := &syspropRustGenRule{}
- g.AddProperties(&g.properties)
- android.InitAndroidModule(g)
- return g
+ g := &syspropRustGenRule{
+ BaseSourceProvider: rust.NewSourceProvider(),
+ }
+ sourceProvider := rust.NewSourceProviderModule(android.DeviceSupported, g, false, false)
+ sourceProvider.AddProperties(&g.properties)
+ return sourceProvider.Init()
}
type syspropLibrary struct {
@@ -309,10 +326,6 @@
return m.BaseModuleName() + "_java_gen_public"
}
-func (m *syspropLibrary) rustGenModuleName() string {
- return m.rustCrateName() + "_rust_gen"
-}
-
func (m *syspropLibrary) rustGenStubName() string {
return "lib" + m.rustCrateName() + "_rust"
}
@@ -529,6 +542,9 @@
type rustLibraryProperties struct {
Name *string
+ Sysprop_srcs []string `android:"path"`
+ Scope string
+ Check_api *string
Srcs []string
Installable *bool
Crate_name string
@@ -668,18 +684,15 @@
}
// Generate a Rust implementation library.
- ctx.CreateModule(syspropRustGenFactory, &syspropGenProperties{
- Srcs: m.properties.Srcs,
- Scope: scope,
- Name: proptools.StringPtr(m.rustGenModuleName()),
- Check_api: proptools.StringPtr(ctx.ModuleName()),
- })
rustProps := rustLibraryProperties{
- Name: proptools.StringPtr(m.rustGenStubName()),
- Srcs: []string{":" + m.rustGenModuleName()},
- Installable: proptools.BoolPtr(false),
- Crate_name: m.rustCrateName(),
+ Name: proptools.StringPtr(m.rustGenStubName()),
+ Sysprop_srcs: m.properties.Srcs,
+ Scope: scope,
+ Check_api: proptools.StringPtr(ctx.ModuleName()),
+ Installable: proptools.BoolPtr(false),
+ Crate_name: m.rustCrateName(),
Rustlibs: []string{
+ "liblog_rust",
"librustutils",
},
Vendor_available: m.properties.Vendor_available,
@@ -687,7 +700,7 @@
Apex_available: m.ApexProperties.Apex_available,
Min_sdk_version: proptools.StringPtr("29"),
}
- ctx.CreateModule(rust.RustLibraryFactory, &rustProps)
+ ctx.CreateModule(syspropRustGenFactory, &rustProps)
// syspropLibraries will be used by property_contexts to check types.
// Record absolute paths of sysprop_library to prevent soong_namespace problem.
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 9dd696f..7d4e69d 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -72,6 +72,15 @@
vendor_available: true,
min_sdk_version: "29",
}
+
+ rust_library {
+ name: "liblog_rust",
+ crate_name: "log",
+ srcs: ["log/src/lib.rs"],
+ product_available: true,
+ vendor_available: true,
+ min_sdk_version: "29",
+ }
`
mockFS := android.MockFS{
@@ -115,6 +124,7 @@
"com/android2/OdmProperties.sysprop": nil,
"librustutils/lib.rs": nil,
+ "log/src/lib.rs": nil,
}
result := android.GroupFixturePreparers(
@@ -124,8 +134,6 @@
PrepareForTestWithSyspropBuildComponents,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceSystemSdkVersions = []string{"28"}
- variables.DeviceVndkVersion = proptools.StringPtr("current")
- variables.Platform_vndk_version = proptools.StringPtr("29")
variables.DeviceCurrentApiLevelForVendorModules = proptools.StringPtr("28")
}),
java.FixtureWithPrebuiltApis(map[string][]string{
@@ -248,10 +256,10 @@
// Check for generated cc_library
for _, variant := range []string{
- "android_vendor.29_arm_armv7-a-neon_shared",
- "android_vendor.29_arm_armv7-a-neon_static",
- "android_vendor.29_arm64_armv8-a_shared",
- "android_vendor.29_arm64_armv8-a_static",
+ "android_vendor_arm_armv7-a-neon_shared",
+ "android_vendor_arm_armv7-a-neon_static",
+ "android_vendor_arm64_armv8-a_shared",
+ "android_vendor_arm64_armv8-a_static",
} {
result.ModuleForTests("libsysprop-platform", variant)
result.ModuleForTests("libsysprop-vendor", variant)
@@ -260,10 +268,10 @@
// product variant of vendor-owned sysprop_library
for _, variant := range []string{
- "android_product.29_arm_armv7-a-neon_shared",
- "android_product.29_arm_armv7-a-neon_static",
- "android_product.29_arm64_armv8-a_shared",
- "android_product.29_arm64_armv8-a_static",
+ "android_product_arm_armv7-a-neon_shared",
+ "android_product_arm_armv7-a-neon_static",
+ "android_product_arm64_armv8-a_shared",
+ "android_product_arm64_armv8-a_static",
} {
result.ModuleForTests("libsysprop-vendor-on-product", variant)
}
@@ -286,16 +294,16 @@
// Check for exported includes
coreVariant := "android_arm64_armv8-a_static"
- vendorVariant := "android_vendor.29_arm64_armv8-a_static"
- productVariant := "android_product.29_arm64_armv8-a_static"
+ vendorVariant := "android_vendor_arm64_armv8-a_static"
+ productVariant := "android_product_arm64_armv8-a_static"
platformInternalPath := "libsysprop-platform/android_arm64_armv8-a_static/gen/sysprop/include"
- platformPublicVendorPath := "libsysprop-platform/android_vendor.29_arm64_armv8-a_static/gen/sysprop/public/include"
+ platformPublicVendorPath := "libsysprop-platform/android_vendor_arm64_armv8-a_static/gen/sysprop/public/include"
- platformOnProductPath := "libsysprop-platform-on-product/android_product.29_arm64_armv8-a_static/gen/sysprop/public/include"
+ platformOnProductPath := "libsysprop-platform-on-product/android_product_arm64_armv8-a_static/gen/sysprop/public/include"
- vendorInternalPath := "libsysprop-vendor/android_vendor.29_arm64_armv8-a_static/gen/sysprop/include"
- vendorOnProductPath := "libsysprop-vendor-on-product/android_product.29_arm64_armv8-a_static/gen/sysprop/public/include"
+ vendorInternalPath := "libsysprop-vendor/android_vendor_arm64_armv8-a_static/gen/sysprop/include"
+ vendorOnProductPath := "libsysprop-vendor-on-product/android_product_arm64_armv8-a_static/gen/sysprop/public/include"
platformClient := result.ModuleForTests("cc-client-platform", coreVariant)
platformFlags := platformClient.Rule("cc").Args["cFlags"]
diff --git a/tests/androidmk_test.sh b/tests/androidmk_test.sh
index b81828b..aecc4e8 100755
--- a/tests/androidmk_test.sh
+++ b/tests/androidmk_test.sh
@@ -5,7 +5,7 @@
# How to run: bash path-to-script/androidmk_test.sh
# Tests of converting license functionality of the androidmk tool
REAL_TOP="$(readlink -f "$(dirname "$0")"/../../..)"
-"$REAL_TOP/build/soong/soong_ui.bash" --make-mode androidmk
+"$REAL_TOP/build/soong/soong_ui.bash" --make-mode TARGET_RELEASE=trunk_staging androidmk
source "$(dirname "$0")/lib.sh"
diff --git a/tests/apex_cc_module_arch_variant_tests.sh b/tests/apex_cc_module_arch_variant_tests.sh
deleted file mode 100755
index 1f5e003..0000000
--- a/tests/apex_cc_module_arch_variant_tests.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2022 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.
-
-set -uo pipefail
-
-# Integration test for verifying arch variant cflags set on cc modules included
-# in Bazel-built apexes in the real source tree.
-
-if [ ! -e "build/make/core/Makefile" ]; then
- echo "$0 must be run from the top of the Android source tree."
- exit 1
-fi
-
-############
-# Test Setup
-############
-
-OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
-BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel"
-
-export TARGET_PRODUCT="aosp_arm64"
-[ "$#" -ge 1 ] && export TARGET_PRODUCT="$1"
-ARCH_VARIANT_CFLAG="armv8-a"
-[ "$#" -ge 2 ] && ARCH_VARIANT_CFLAG="$2"
-CPU_VARIANT_CFLAG=""
-[ "$#" -ge 3 ] && CPU_VARIANT_CFLAG="$3"
-
-function call_bazel() {
- build/bazel/bin/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
-}
-
-function cleanup {
- # call bazel clean because some bazel outputs don't have w bits.
- call_bazel clean
- rm -rf "${OUTPUT_DIR}"
-}
-trap cleanup EXIT
-
-######################
-# Run bp2build / Bazel
-######################
-build/soong/soong_ui.bash --make-mode BP2BUILD_VERBOSE=1 --skip-soong-tests bp2build
-
-# Number of CppCompile actions with arch variant flag
-actions_with_arch_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
-
-# Number of all CppCompile actions
-all_cppcompile_actions_num=0
-aquery_summary=$(call_bazel aquery --config=bp2build --config=ci --config=android --output=summary \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' \
- | egrep -o '.*opt-ST.*: ([0-9]+)$' \
- | cut -d: -f2 -)
-
-while read -r num;
-do
- all_cppcompile_actions_num=$(($all_cppcompile_actions_num + $num))
-done <<< "$aquery_summary"
-
-if [ $actions_with_arch_variant_num -eq $all_cppcompile_actions_num ]
-then
- echo "Pass: arch variant is set."
-else
- echo "Error: number of CppCompile actions with arch variant set: actual=$actions_with_arch_variant_num, expected=$all_cppcompile_actions_num"
- exit 1
-fi
-
-if [ $CPU_VARIANT_CFLAG ]
-then
- # Number of CppCompiler actions with cpu variant flag
- actions_with_cpu_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
-
- if [ $actions_with_cpu_variant_num -eq $all_cppcompile_actions_num ]
- then
- echo "Pass: cpu variant is set."
- else
- echo "Error: number of CppCompile actions with cpu variant set: actual=$actions_with_cpu_variant_num, expected=$all_cppcompile_actions_num"
- exit 1
- fi
-fi
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
deleted file mode 100755
index 8893060..0000000
--- a/tests/apex_comparison_tests.sh
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2022 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.
-
-set -euo pipefail
-
-# Soong/Bazel integration test for building unbundled apexes in the real source tree.
-#
-# These tests build artifacts from head and compares their contents.
-
-if [ ! -e "build/make/core/Makefile" ]; then
- echo "$0 must be run from the top of the Android source tree."
- exit 1
-fi
-
-############
-# Test Setup
-############
-
-OUTPUT_DIR="$(mktemp -d $(pwd)/tmp.XXXXXX)"
-SOONG_OUTPUT_DIR="$OUTPUT_DIR/soong"
-BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel"
-
-export TARGET_PRODUCT="module_arm"
-[ "$#" -eq 1 ] && export TARGET_PRODUCT="$1"
-
-function call_bazel() {
- build/bazel/bin/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
-}
-
-function cleanup {
- # call bazel clean because some bazel outputs don't have w bits.
- call_bazel clean
- rm -rf "${OUTPUT_DIR}"
-}
-
-function deapexer() {
- DEBUGFS_PATH="$(realpath $(call_bazel cquery --config=bp2build --config=linux_x86_64 --config=ci --output=files //external/e2fsprogs/debugfs))"
- call_bazel run --config=bp2build //system/apex/tools:deapexer -- --debugfs_path=$DEBUGFS_PATH $@
-}
-
-trap cleanup EXIT
-
-###########
-# Run Soong
-###########
-export UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true # don't rely on prebuilts
-export TARGET_BUILD_APPS="com.android.adbd com.android.tzdata build.bazel.examples.apex.minimal"
-packages/modules/common/build/build_unbundled_mainline_module.sh \
- --product "$TARGET_PRODUCT" \
- --dist_dir "$SOONG_OUTPUT_DIR"
-
-######################
-# Run bp2build / Bazel
-######################
-build/soong/soong_ui.bash --make-mode BP2BUILD_VERBOSE=1 --skip-soong-tests bp2build
-
-BAZEL_OUT="$(call_bazel info --config=bp2build output_path)"
-
-call_bazel build --config=bp2build --config=ci --config=android \
- //packages/modules/adb/apex:com.android.adbd \
- //system/timezone/apex:com.android.tzdata \
- //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal
-BAZEL_ADBD="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //packages/modules/adb/apex:com.android.adbd))"
-BAZEL_TZDATA="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //system/timezone/apex:com.android.tzdata))"
-BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))"
-
-# # Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
-call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs
-
-#######
-# Tests
-#######
-
-function compare_deapexer_list() {
- local BAZEL_APEX=$1; shift
- local APEX=$1; shift
-
- # Compare the outputs of `deapexer list`, which lists the contents of the apex filesystem image.
- local SOONG_APEX="$SOONG_OUTPUT_DIR/$APEX"
-
- local SOONG_LIST="$OUTPUT_DIR/soong.list"
- local BAZEL_LIST="$OUTPUT_DIR/bazel.list"
-
- deapexer list "$SOONG_APEX" > "$SOONG_LIST"
- deapexer list "$BAZEL_APEX" > "$BAZEL_LIST"
-
- if cmp -s "$SOONG_LIST" "$BAZEL_LIST"
- then
- echo "ok: $APEX"
- else
- echo "contents of $APEX are different between Soong and Bazel:"
- echo
- echo expected
- echo
- cat "$SOONG_LIST"
- echo
- echo got
- echo
- cat "$BAZEL_LIST"
- exit 1
- fi
-}
-
-compare_deapexer_list "${BAZEL_ADBD}" com.android.adbd.apex
-compare_deapexer_list "${BAZEL_TZDATA}" com.android.tzdata.apex
-compare_deapexer_list "${BAZEL_MINIMAL}" build.bazel.examples.apex.minimal.apex
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 5fc05f8..2e40950 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -9,6 +9,8 @@
readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
+readonly target_product="${TARGET_PRODUCT:-aosp_arm}"
+
function test_smoke {
setup
run_soong
@@ -18,10 +20,10 @@
setup
run_soong
local -r bootstrap_mtime1=$(stat -c "%y" out/soong/bootstrap.ninja)
- local -r output_mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r output_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
run_soong
local -r bootstrap_mtime2=$(stat -c "%y" out/soong/bootstrap.ninja)
- local -r output_mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r output_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$bootstrap_mtime1" == "$bootstrap_mtime2" ]]; then
# Bootstrapping is always done. It doesn't take a measurable amount of time.
@@ -60,7 +62,7 @@
touch a/my_little_binary_host.py
run_soong
- grep -q "^# Module:.*my_little_binary_host" out/soong/build.ninja || fail "module not found"
+ grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".ninja || fail "module not found"
cat > a/Android.bp <<'EOF'
python_binary_host {
@@ -71,14 +73,14 @@
touch a/my_great_binary_host.py
run_soong
- grep -q "^# Module:.*my_little_binary_host" out/soong/build.ninja && fail "old module found"
- grep -q "^# Module:.*my_great_binary_host" out/soong/build.ninja || fail "new module not found"
+ grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".ninja && fail "old module found"
+ grep -q "^# Module:.*my_great_binary_host" out/soong/build."${target_product}".ninja || fail "new module not found"
}
function test_add_android_bp() {
setup
run_soong
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
mkdir -p a
cat > a/Android.bp <<'EOF'
@@ -90,12 +92,12 @@
touch a/my_little_binary_host.py
run_soong
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" == "$mtime2" ]]; then
fail "Output Ninja file did not change"
fi
- grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja || fail "New module not in output"
+ grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja || fail "New module not in output"
run_soong
}
@@ -112,12 +114,12 @@
touch a/my_little_binary_host.py
run_soong
- grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja || fail "Module not in output"
+ grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja || fail "Module not in output"
rm a/Android.bp
run_soong
- if grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja; then
+ if grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja; then
fail "Old module in output"
fi
}
@@ -141,16 +143,12 @@
EOF
touch a/my_little_binary_host.py
run_soong
- local -r ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
- local glob_deps_file=out/soong/globs/build/0.d
-
- if [ -e "$glob_deps_file" ]; then
- fail "Glob deps file unexpectedly written on first build"
- fi
+ local glob_deps_file=out/soong/globs/"${target_product}"/0.d
run_soong
- local -r ninja_mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
# There is an ineffiencency in glob that requires bpglob to rerun once for each glob to update
# the entry in the .ninja_log. It doesn't update the output file, but we can detect the rerun
@@ -166,7 +164,7 @@
fi
run_soong
- local -r ninja_mtime3=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
local -r glob_deps_mtime3=$(stat -c "%y" "$glob_deps_file")
if [[ "$ninja_mtime2" != "$ninja_mtime3" ]]; then
@@ -191,17 +189,17 @@
EOF
touch a/my_little_binary_host.py
run_soong
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
touch a/my_little_library.py
run_soong
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" == "$mtime2" ]]; then
fail "Output Ninja file did not change"
fi
- grep -q my_little_library.py out/soong/build.ninja || fail "new file is not in output"
+ grep -q my_little_library.py out/soong/build."${target_product}".ninja || fail "new file is not in output"
}
function test_soong_build_rerun_iff_environment_changes() {
@@ -267,17 +265,17 @@
export CHERRY=TASTY
run_soong
- grep -q "CHERRY IS TASTY" out/soong/build.ninja \
+ grep -q "CHERRY IS TASTY" out/soong/build."${target_product}".ninja \
|| fail "first value of environment variable is not used"
export CHERRY=RED
run_soong
- grep -q "CHERRY IS RED" out/soong/build.ninja \
+ grep -q "CHERRY IS RED" out/soong/build."${target_product}".ninja \
|| fail "second value of environment variable not used"
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
run_soong
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" != "$mtime2" ]]; then
fail "Output Ninja file changed when environment variable did not"
fi
@@ -287,7 +285,7 @@
function test_create_global_include_directory() {
setup
run_soong
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
# Soong needs to know if top level directories like hardware/ exist for use
# as global include directories. Make sure that doesn't cause regens for
@@ -295,7 +293,7 @@
mkdir -p system/core
run_soong
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" != "$mtime2" ]]; then
fail "Output Ninja file changed when top level directory changed"
fi
@@ -305,7 +303,7 @@
mkdir -p system/core/include
run_soong
- local -r mtime3=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime2" = "$mtime3" ]]; then
fail "Output Ninja file did not change when global include directory created"
fi
@@ -315,7 +313,7 @@
function test_add_file_to_soong_build() {
setup
run_soong
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
mkdir -p vendor/foo/picard
cat > vendor/foo/picard/Android.bp <<'EOF'
@@ -377,12 +375,12 @@
EOF
run_soong
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" == "$mtime2" ]]; then
fail "Output Ninja file did not change"
fi
- grep -q "Make it so" out/soong/build.ninja || fail "New action not present"
+ grep -q "Make it so" out/soong/build."${target_product}".ninja || fail "New action not present"
}
# Tests a glob in a build= statement in an Android.bp file, which is interpreted
@@ -455,9 +453,9 @@
EOF
run_soong
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
- grep -q "Make it so" out/soong/build.ninja || fail "Original action not present"
+ grep -q "Make it so" out/soong/build."${target_product}".ninja || fail "Original action not present"
cat > build/soong/picard/foob.bp <<'EOF'
bootstrap_go_package {
@@ -487,14 +485,14 @@
EOF
run_soong
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" == "$mtime2" ]]; then
fail "Output Ninja file did not change"
fi
- grep -q "Engage" out/soong/build.ninja || fail "New action not present"
+ grep -q "Engage" out/soong/build."${target_product}".ninja || fail "New action not present"
- if grep -q "Make it so" out/soong/build.ninja; then
+ if grep -q "Make it so" out/soong/build."${target_product}".ninja; then
fail "Original action still present"
fi
}
@@ -512,7 +510,7 @@
setup
run_soong
- local -r ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
run_soong soong_docs
local -r docs_mtime1=$(stat -c "%y" out/soong/docs/soong_build.html)
@@ -525,7 +523,7 @@
fi
run_soong
- local -r ninja_mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
fail "Output Ninja file changed on null build"
@@ -565,144 +563,6 @@
fi
}
-function test_bp2build_smoke {
- setup
- run_soong bp2build
- [[ -e out/soong/bp2build_workspace_marker ]] || fail "bp2build marker file not created"
- [[ -e out/soong/workspace ]] || fail "Bazel workspace not created"
-}
-
-function test_bp2build_generates_marker_file {
- setup
-
- run_soong bp2build
-
- if [[ ! -f "./out/soong/bp2build_files_marker" ]]; then
- fail "bp2build marker file was not generated"
- fi
-
- if [[ ! -f "./out/soong/bp2build_workspace_marker" ]]; then
- fail "symlink forest marker file was not generated"
- fi
-}
-
-function test_bp2build_add_irrelevant_file {
- setup
-
- mkdir -p a/b
- touch a/b/c.txt
- cat > a/b/Android.bp <<'EOF'
-filegroup {
- name: "c",
- srcs: ["c.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
- if [[ ! -e out/soong/bp2build/a/b/BUILD.bazel ]]; then
- fail "BUILD file in symlink forest was not created";
- fi
-
- local -r mtime1=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel)
-
- touch a/irrelevant.txt
- run_soong bp2build
- local -r mtime2=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel)
-
- if [[ "$mtime1" != "$mtime2" ]]; then
- fail "BUILD.bazel file was regenerated"
- fi
-
- if [[ ! -e "out/soong/workspace/a/irrelevant.txt" ]]; then
- fail "New file was not symlinked into symlink forest"
- fi
-}
-
-function test_bp2build_add_android_bp {
- setup
-
- mkdir -p a
- touch a/a.txt
- cat > a/Android.bp <<'EOF'
-filegroup {
- name: "a",
- srcs: ["a.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
- [[ -e out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created"
- [[ -L out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked"
-
- mkdir -p b
- touch b/b.txt
- cat > b/Android.bp <<'EOF'
-filegroup {
- name: "b",
- srcs: ["b.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
- [[ -e out/soong/bp2build/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created"
- [[ -L out/soong/workspace/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked"
-}
-
-function test_bp2build_null_build {
- setup
-
- run_soong bp2build
- local -r mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- run_soong bp2build
- local -r mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- if [[ "$mtime1" != "$mtime2" ]]; then
- fail "Output Ninja file changed on null build"
- fi
-}
-
-function test_bp2build_add_to_glob {
- setup
-
- mkdir -p a
- touch a/a1.txt
- cat > a/Android.bp <<'EOF'
-filegroup {
- name: "a",
- srcs: ["*.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
- grep -q a1.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a1.txt not in ${GENERATED_BUILD_FILE_NAME} file"
-
- touch a/a2.txt
- run_soong bp2build
- grep -q a2.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a2.txt not in ${GENERATED_BUILD_FILE_NAME} file"
-}
-
-function test_multiple_soong_build_modes() {
- setup
- run_soong json-module-graph bp2build nothing
- if [[ ! -f "out/soong/bp2build_workspace_marker" ]]; then
- fail "bp2build marker file was not generated"
- fi
-
-
- if [[ ! -f "out/soong/module-graph.json" ]]; then
- fail "JSON file was not created"
- fi
-
- if [[ ! -f "out/soong/build.ninja" ]]; then
- fail "Main build.ninja file was not created"
- fi
-}
-
function test_dump_json_module_graph() {
setup
run_soong json-module-graph
@@ -715,13 +575,13 @@
setup
run_soong
- local -r ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
run_soong json-module-graph
local -r json_mtime1=$(stat -c "%y" out/soong/module-graph.json)
run_soong
- local -r ninja_mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
fail "Output Ninja file changed after writing JSON module graph"
fi
@@ -734,143 +594,6 @@
}
-function test_bp2build_bazel_workspace_structure {
- setup
-
- mkdir -p a/b
- touch a/a.txt
- touch a/b/b.txt
- cat > a/b/Android.bp <<'EOF'
-filegroup {
- name: "b",
- srcs: ["b.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
- [[ -e out/soong/workspace ]] || fail "Bazel workspace not created"
- [[ -d out/soong/workspace/a/b ]] || fail "module directory not a directory"
- [[ -L "out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked"
- [[ "$(readlink -f out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/b/${GENERATED_BUILD_FILE_NAME}"$ ]] \
- || fail "BUILD files symlinked at the wrong place"
- [[ -L out/soong/workspace/a/b/b.txt ]] || fail "a/b/b.txt not symlinked"
- [[ -L out/soong/workspace/a/a.txt ]] || fail "a/b/a.txt not symlinked"
- [[ ! -e out/soong/workspace/out ]] || fail "out directory symlinked"
-}
-
-function test_bp2build_bazel_workspace_add_file {
- setup
-
- mkdir -p a
- touch a/a.txt
- cat > a/Android.bp <<EOF
-filegroup {
- name: "a",
- srcs: ["a.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
-
- touch a/a2.txt # No reference in the .bp file needed
- run_soong bp2build
- [[ -L out/soong/workspace/a/a2.txt ]] || fail "a/a2.txt not symlinked"
-}
-
-function test_bp2build_build_file_precedence {
- setup
-
- mkdir -p a
- touch a/a.txt
- touch a/${GENERATED_BUILD_FILE_NAME}
- cat > a/Android.bp <<EOF
-filegroup {
- name: "a",
- srcs: ["a.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong bp2build
- [[ -L "out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked"
- [[ "$(readlink -f out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/${GENERATED_BUILD_FILE_NAME}"$ ]] \
- || fail "${GENERATED_BUILD_FILE_NAME} files symlinked to the wrong place"
-}
-
-function test_bp2build_fails_fast {
- setup
-
- mkdir -p "a/${GENERATED_BUILD_FILE_NAME}"
- cat > a/Android.bp <<EOF
-filegroup {
- name: "a",
- srcs: ["a.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- mkdir -p "b/${GENERATED_BUILD_FILE_NAME}"
- cat > b/Android.bp <<EOF
-filegroup {
- name: "b",
- srcs: ["b.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- if run_soong bp2build >& "$MOCK_TOP/errors"; then
- fail "Build should have failed"
- fi
-
- # we should expect at least one error
- grep -q -E "(a|b)/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for ${GENERATED_BUILD_FILE_NAME} not found"
-}
-
-function test_bp2build_back_and_forth_null_build {
- setup
-
- run_soong
- local -r output_mtime1=$(stat -c "%y" out/soong/build.ninja)
-
- run_soong bp2build
- local -r output_mtime2=$(stat -c "%y" out/soong/build.ninja)
- if [[ "$output_mtime1" != "$output_mtime2" ]]; then
- fail "Output Ninja file changed when switching to bp2build"
- fi
-
- local -r marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- run_soong
- local -r output_mtime3=$(stat -c "%y" out/soong/build.ninja)
- local -r marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
- if [[ "$output_mtime1" != "$output_mtime3" ]]; then
- fail "Output Ninja file changed when switching to regular build from bp2build"
- fi
- if [[ "$marker_mtime1" != "$marker_mtime2" ]]; then
- fail "bp2build marker file changed when switching to regular build from bp2build"
- fi
-
- run_soong bp2build
- local -r output_mtime4=$(stat -c "%y" out/soong/build.ninja)
- local -r marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker)
- if [[ "$output_mtime1" != "$output_mtime4" ]]; then
- fail "Output Ninja file changed when switching back to bp2build"
- fi
- if [[ "$marker_mtime1" != "$marker_mtime3" ]]; then
- fail "bp2build marker file changed when switching back to bp2build"
- fi
-}
-
-function test_queryview_smoke() {
- setup
-
- run_soong queryview
- [[ -e out/soong/queryview/WORKSPACE ]] || fail "queryview WORKSPACE file not created"
-
-}
-
function test_queryview_null_build() {
setup
@@ -886,14 +609,14 @@
}
# This test verifies that adding a new glob to a blueprint file only
-# causes build.ninja to be regenerated on the *next* build, and *not*
+# causes build."${target_product}".ninja to be regenerated on the *next* build, and *not*
# the build after. (This is a regression test for a bug where globs
# resulted in two successive regenerations.)
function test_new_glob_incrementality {
setup
run_soong nothing
- local -r mtime1=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
mkdir -p globdefpkg/
cat > globdefpkg/Android.bp <<'EOF'
@@ -904,14 +627,14 @@
EOF
run_soong nothing
- local -r mtime2=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime1" == "$mtime2" ]]; then
fail "Ninja file was not regenerated, despite a new bp file"
fi
run_soong nothing
- local -r mtime3=$(stat -c "%y" out/soong/build.ninja)
+ local -r mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
if [[ "$mtime2" != "$mtime3" ]]; then
fail "Ninja file was regenerated despite no previous bp changes"
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
deleted file mode 100755
index 8a64a56..0000000
--- a/tests/bp2build_bazel_test.sh
+++ /dev/null
@@ -1,445 +0,0 @@
-#!/bin/bash -eu
-
-set -o pipefail
-
-# Test that bp2build and Bazel can play nicely together
-
-source "$(dirname "$0")/lib.sh"
-
-readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
-
-function test_bp2build_null_build {
- setup
- run_soong bp2build
- local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- run_soong bp2build
- local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- if [[ "$output_mtime1" != "$output_mtime2" ]]; then
- fail "Output bp2build marker file changed on null build"
- fi
-}
-
-# Tests that, if bp2build reruns due to a blueprint file changing, that
-# BUILD files whose contents are unchanged are not regenerated.
-function test_bp2build_unchanged {
- setup
-
- mkdir -p pkg
- touch pkg/x.txt
- cat > pkg/Android.bp <<'EOF'
-filegroup {
- name: "x",
- srcs: ["x.txt"],
- bazel_module: {bp2build_available: true},
- }
-EOF
-
- run_soong bp2build
- local -r buildfile_mtime1=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
- local -r marker_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- # Force bp2build to rerun by updating the timestamp of a blueprint file.
- touch pkg/Android.bp
-
- run_soong bp2build
- local -r buildfile_mtime2=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
- local -r marker_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- if [[ "$marker_mtime1" == "$marker_mtime2" ]]; then
- fail "Expected bp2build marker file to change"
- fi
- if [[ "$buildfile_mtime1" != "$buildfile_mtime2" ]]; then
- fail "BUILD.bazel was updated even though contents are same"
- fi
-
- # Force bp2build to rerun by updating the timestamp of the constants_exported_to_soong.bzl file.
- touch build/bazel/constants_exported_to_soong.bzl
-
- run_soong bp2build
- local -r buildfile_mtime3=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
- local -r marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- if [[ "$marker_mtime2" == "$marker_mtime3" ]]; then
- fail "Expected bp2build marker file to change"
- fi
- if [[ "$buildfile_mtime2" != "$buildfile_mtime3" ]]; then
- fail "BUILD.bazel was updated even though contents are same"
- fi
-}
-
-# Tests that blueprint files that are deleted are not present when the
-# bp2build tree is regenerated.
-function test_bp2build_deleted_blueprint {
- setup
-
- mkdir -p pkg
- touch pkg/x.txt
- cat > pkg/Android.bp <<'EOF'
-filegroup {
- name: "x",
- srcs: ["x.txt"],
- bazel_module: {bp2build_available: true},
- }
-EOF
-
- run_soong bp2build
- if [[ ! -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then
- fail "Expected pkg/BUILD.bazel to be generated"
- fi
-
- rm pkg/Android.bp
-
- run_soong bp2build
- if [[ -e "./out/soong/bp2build/pkg/BUILD.bazel" ]]; then
- fail "Expected pkg/BUILD.bazel to be deleted"
- fi
-}
-
-function test_bp2build_null_build_with_globs {
- setup
-
- mkdir -p foo/bar
- cat > foo/bar/Android.bp <<'EOF'
-filegroup {
- name: "globs",
- srcs: ["*.txt"],
- }
-EOF
- touch foo/bar/a.txt foo/bar/b.txt
-
- run_soong bp2build
- local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- run_soong bp2build
- local -r output_mtime2=$(stat -c "%y" out/soong/bp2build_workspace_marker)
-
- if [[ "$output_mtime1" != "$output_mtime2" ]]; then
- fail "Output bp2build marker file changed on null build"
- fi
-}
-
-function test_different_relative_outdir {
- setup
-
- mkdir -p a
- touch a/g.txt
- cat > a/Android.bp <<'EOF'
-filegroup {
- name: "g",
- srcs: ["g.txt"],
- bazel_module: {bp2build_available: true},
- }
-EOF
-
- # A directory under $MOCK_TOP
- outdir=out2
- trap "rm -rf $outdir" EXIT
- # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
- (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
-}
-
-function test_different_absolute_outdir {
- setup
-
- mkdir -p a
- touch a/g.txt
- cat > a/Android.bp <<'EOF'
-filegroup {
- name: "g",
- srcs: ["g.txt"],
- bazel_module: {bp2build_available: true},
- }
-EOF
-
- # A directory under /tmp/...
- outdir=$(mktemp -t -d st.XXXXX)
- trap 'rm -rf $outdir' EXIT
- # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
- (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
-}
-
-function _bp2build_generates_all_buildfiles {
- setup
-
- mkdir -p foo/convertible_soong_module
- cat > foo/convertible_soong_module/Android.bp <<'EOF'
-genrule {
- name: "the_answer",
- cmd: "echo '42' > $(out)",
- out: [
- "the_answer.txt",
- ],
- bazel_module: {
- bp2build_available: true,
- },
- }
-EOF
-
- mkdir -p foo/unconvertible_soong_module
- cat > foo/unconvertible_soong_module/Android.bp <<'EOF'
-genrule {
- name: "not_the_answer",
- cmd: "echo '43' > $(out)",
- out: [
- "not_the_answer.txt",
- ],
- bazel_module: {
- bp2build_available: false,
- },
- }
-EOF
-
- run_soong bp2build
-
- if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
- fail "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
- fi
-
- if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
- fail "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
- fi
-
- if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
- fail "missing BUILD target the_answer in convertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
- fi
-
- if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
- fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
- fi
-
- if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"; then
- fail "missing filegroup in unconvertible_soong_module/${GENERATED_BUILD_FILE_NAME}"
- fi
-
- # NOTE: We don't actually use the extra BUILD file for anything here
- run_bazel build --config=android --config=bp2build --config=ci //foo/...
-
- local -r the_answer_file="$(find -L bazel-out -name the_answer.txt)"
- if [[ ! -f "${the_answer_file}" ]]; then
- fail "Expected the_answer.txt to be generated, but was missing"
- fi
- if ! grep 42 "${the_answer_file}"; then
- fail "Expected to find 42 in '${the_answer_file}'"
- fi
-}
-
-function test_bp2build_generates_all_buildfiles {
- _save_trap=$(trap -p EXIT)
- trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
- _bp2build_generates_all_buildfiles
- eval "${_save_trap}"
-}
-
-function test_build_files_take_precedence {
- _save_trap=$(trap -p EXIT)
- trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
- _build_files_take_precedence
- eval "${_save_trap}"
-}
-
-function _build_files_take_precedence {
- setup
-
- # This specific directory is hardcoded in bp2build as being one
- # where the BUILD file should be intentionally kept.
- mkdir -p testpkg/keep_build_file
- cat > testpkg/keep_build_file/Android.bp <<'EOF'
-genrule {
- name: "print_origin",
- cmd: "echo 'from_soong' > $(out)",
- out: [
- "origin.txt",
- ],
- bazel_module: {
- bp2build_available: true,
- },
- }
-EOF
-
- run_soong bp2build
- run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
-
- local -r output_file="$(find -L bazel-out -name origin.txt)"
- if [[ ! -f "${output_file}" ]]; then
- fail "Expected origin.txt to be generated, but was missing"
- fi
- if ! grep from_soong "${output_file}"; then
- fail "Expected to find 'from_soong' in '${output_file}'"
- fi
-
- cat > testpkg/keep_build_file/BUILD.bazel <<'EOF'
-genrule(
- name = "print_origin",
- outs = ["origin.txt"],
- cmd = "echo 'from_bazel' > $@",
-)
-EOF
-
- # Clean the workspace. There is a test infrastructure bug where run_bazel
- # will symlink Android.bp files in the source directory again and thus
- # pollute the workspace.
- # TODO: b/286059878 - Remove this clean after the underlying bug is fixed.
- run_soong clean
- run_soong bp2build
- run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
- if ! grep from_bazel "${output_file}"; then
- fail "Expected to find 'from_bazel' in '${output_file}'"
- fi
-}
-
-function test_bp2build_symlinks_files {
- setup
- mkdir -p foo
- touch foo/BLANK1
- touch foo/BLANK2
- touch foo/F2D
- touch foo/BUILD
-
- run_soong bp2build
-
- if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
- fail "./out/soong/workspace/foo/BUILD should be omitted"
- fi
- for file in BLANK1 BLANK2 F2D
- do
- if [[ ! -L "./out/soong/workspace/foo/$file" ]]; then
- fail "./out/soong/workspace/foo/$file should exist"
- fi
- done
- local -r BLANK1_BEFORE=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
-
- rm foo/BLANK2
- rm foo/F2D
- mkdir foo/F2D
- touch foo/F2D/BUILD
-
- run_soong bp2build
-
- if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
- fail "./out/soong/workspace/foo/BUILD should be omitted"
- fi
- local -r BLANK1_AFTER=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
- if [[ "$BLANK1_AFTER" != "$BLANK1_BEFORE" ]]; then
- fail "./out/soong/workspace/foo/BLANK1 should be untouched"
- fi
- if [[ -e "./out/soong/workspace/foo/BLANK2" ]]; then
- fail "./out/soong/workspace/foo/BLANK2 should be removed"
- fi
- if [[ -L "./out/soong/workspace/foo/F2D" ]] || [[ ! -d "./out/soong/workspace/foo/F2D" ]]; then
- fail "./out/soong/workspace/foo/F2D should be a dir"
- fi
-}
-
-function test_cc_correctness {
- setup
-
- mkdir -p a
- cat > a/Android.bp <<EOF
-cc_object {
- name: "qq",
- srcs: ["qq.cc"],
- bazel_module: {
- bp2build_available: true,
- },
- stl: "none",
- system_shared_libs: [],
-}
-EOF
-
- cat > a/qq.cc <<EOF
-#include "qq.h"
-int qq() {
- return QQ;
-}
-EOF
-
- cat > a/qq.h <<EOF
-#define QQ 1
-EOF
-
- run_soong bp2build
-
- run_bazel build --config=android --config=bp2build --config=ci //a:qq
- local -r output_mtime1=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
-
- run_bazel build --config=android --config=bp2build --config=ci //a:qq
- local -r output_mtime2=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
-
- if [[ "$output_mtime1" != "$output_mtime2" ]]; then
- fail "output changed on null build"
- fi
-
- cat > a/qq.h <<EOF
-#define QQ 2
-EOF
-
- run_bazel build --config=android --config=bp2build --config=ci //a:qq
- local -r output_mtime3=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
-
- if [[ "$output_mtime1" == "$output_mtime3" ]]; then
- fail "output not changed when included header changed"
- fi
-}
-
-# Regression test for the following failure during symlink forest creation:
-#
-# Cannot stat '/tmp/st.rr054/foo/bar/unresolved_symlink': stat /tmp/st.rr054/foo/bar/unresolved_symlink: no such file or directory
-#
-function test_bp2build_null_build_with_unresolved_symlink_in_source() {
- setup
-
- mkdir -p foo/bar
- ln -s /tmp/non-existent foo/bar/unresolved_symlink
- cat > foo/bar/Android.bp <<'EOF'
-filegroup {
- name: "fg",
- srcs: ["unresolved_symlink/non-existent-file.txt"],
- }
-EOF
-
- run_soong bp2build
-
- dest=$(readlink -f out/soong/workspace/foo/bar/unresolved_symlink)
- if [[ "$dest" != "/tmp/non-existent" ]]; then
- fail "expected to plant an unresolved symlink out/soong/workspace/foo/bar/unresolved_symlink that resolves to /tmp/non-existent"
- fi
-}
-
-function test_bazel_standalone_output_paths_contain_product_name {
- setup
- mkdir -p a
- cat > a/Android.bp <<EOF
-cc_object {
- name: "qq",
- srcs: ["qq.cc"],
- bazel_module: {
- bp2build_available: true,
- },
- stl: "none",
- system_shared_libs: [],
-}
-EOF
-
- cat > a/qq.cc <<EOF
-#include "qq.h"
-int qq() {
- return QQ;
-}
-EOF
-
- cat > a/qq.h <<EOF
-#define QQ 1
-EOF
-
- export TARGET_PRODUCT=aosp_arm; run_soong bp2build
- local -r output=$(run_bazel cquery //a:qq --output=files --config=android --config=bp2build --config=ci)
- if [[ ! $(echo ${output} | grep "bazel-out/aosp_arm") ]]; then
- fail "Did not find the product name '${TARGET_PRODUCT}' in the output path. This can cause " \
- "unnecessary rebuilds when toggling between products as bazel outputs for different products will " \
- "clobber each other. Output paths are: \n${output}"
- fi
-}
-
-scan_and_run_tests
diff --git a/tests/dcla_apex_comparison_test.sh b/tests/dcla_apex_comparison_test.sh
deleted file mode 100755
index e3c189f..0000000
--- a/tests/dcla_apex_comparison_test.sh
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2023 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.
-
-set -euo pipefail
-
-# Soong/Bazel integration test to build the mainline modules in mixed build and
-# compare the DCLA libs extracted from those modules to ensure they are identical.
-
-if [ ! -e "build/make/core/Makefile" ]; then
- echo "$0 must be run from the top of the Android source tree."
- exit 1
-fi
-
-TARGET_PRODUCTS=(
- module_arm64
- module_x86_64
-)
-
-MODULES=(
- # These modules depend on the DCLA libs
- com.android.adbd
- com.android.art
- com.android.art.debug
- com.android.art.testing
- com.android.btservices
- com.android.conscrypt
- com.android.i18n
- com.android.media
- com.android.media.swcodec
- com.android.resolv
- com.android.runtime
- com.android.tethering
-)
-
-BAZEL_TARGETS=(
- //packages/modules/adb/apex:com.android.adbd
- //frameworks/av/apex:com.android.media.swcodec
-)
-
-DCLA_LIBS=(
- libbase.so
- libc++.so
- libcrypto.so
- libcutils.so
- libstagefright_flacdec.so
- libutils.so
-)
-
-if [[ -z ${OUT_DIR+x} ]]; then
- OUT_DIR="out"
-fi
-
-if [[ -z ${ANDROID_HOST_OUT+x} ]]; then
- export ANDROID_HOST_OUT="out/host/linux-x86"
-fi
-
-######################
-# Build deapexer and debugfs
-######################
-DEAPEXER="${ANDROID_HOST_OUT}/bin/deapexer"
-DEBUGFS="${ANDROID_HOST_OUT}/bin/debugfs"
-if [[ ! -f "${DEAPEXER}" ]] || [[ ! -f "${DEBUGFS}" ]]; then
- build/soong/soong_ui.bash --make-mode --skip-soong-tests deapexer debugfs
-fi
-
-DEAPEXER="${DEAPEXER} --debugfs_path=${DEBUGFS}"
-
-############
-# Test Setup
-############
-OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
-
-function call_bazel() {
- build/bazel/bin/bazel $@
-}
-
-function cleanup {
- rm -rf "${OUTPUT_DIR}"
-}
-trap cleanup EXIT
-
-#######
-# Tests
-#######
-
-function extract_dcla_libs() {
- local product=$1; shift
- local modules=("$@"); shift
-
- for module in "${modules[@]}"; do
- local apex="${OUTPUT_DIR}/${product}/${module}.apex"
- local extract_dir="${OUTPUT_DIR}/${product}/${module}/extract"
-
- $DEAPEXER extract "${apex}" "${extract_dir}"
- done
-}
-
-function compare_dcla_libs() {
- local product=$1; shift
- local modules=("$@"); shift
-
- for lib in "${DCLA_LIBS[@]}"; do
- for arch in lib lib64; do
- local prev_sha=""
- for module in "${modules[@]}"; do
- local file="${OUTPUT_DIR}/${product}/${module}/extract/${arch}/${lib}"
- if [[ ! -f "${file}" ]]; then
- # not all libs are present in a module
- echo "file doesn't exist: ${file}"
- continue
- fi
- sha=$(sha1sum ${file})
- sha="${sha% *}"
- if [ "${prev_sha}" == "" ]; then
- prev_sha="${sha}"
- elif [ "${sha}" != "${prev_sha}" ] && { [ "${lib}" != "libcrypto.so" ] || [[ "${module}" != *"com.android.tethering" ]]; }; then
- echo "Test failed, ${lib} has different hash value"
- exit 1
- fi
- done
- done
- done
-}
-
-export UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true # don't rely on prebuilts
-export TARGET_BUILD_APPS="${MODULES[@]}"
-for product in "${TARGET_PRODUCTS[@]}"; do
- ###########
- # Build the mainline modules
- ###########
- packages/modules/common/build/build_unbundled_mainline_module.sh \
- --product "${product}" \
- --dist_dir "${OUTPUT_DIR}/${product}"
-
- bazel_apexes=()
- if [[ -n ${TEST_BAZEL+x} ]] && [ "${TEST_BAZEL}" = true ]; then
- export TARGET_PRODUCT="${product/module/aosp}"
- call_bazel build --config=bp2build --config=ci --config=android "${BAZEL_TARGETS[@]}"
- for target in "${BAZEL_TARGETS[@]}"; do
- apex_path="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files $target))"
- mkdir -p ${OUTPUT_DIR}/${product}
- bazel_apex="bazel_$(basename $apex_path)"
- mv $apex_path ${OUTPUT_DIR}/${product}/${bazel_apex}
- bazel_apexes+=(${bazel_apex%".apex"})
- done
- fi
-
- all_modeuls=(${MODULES[@]} ${bazel_apexes[@]})
- extract_dcla_libs "${product}" "${all_modeuls[@]}"
- compare_dcla_libs "${product}" "${all_modeuls[@]}"
-done
-
-echo "Test passed"
diff --git a/tests/lib.sh b/tests/lib.sh
index e0b319e..4c320d0 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -140,7 +140,7 @@
# shellcheck disable=SC2120
function run_soong {
- USE_RBE=false build/soong/soong_ui.bash --make-mode --skip-ninja --skip-config --soong-only --skip-soong-tests "$@"
+ USE_RBE=false TARGET_PRODUCT=aosp_arm TARGET_RELEASE=trunk_staging TARGET_BUILD_VARIANT=userdebug build/soong/soong_ui.bash --make-mode --skip-ninja --skip-config --soong-only --skip-soong-tests "$@"
}
function create_mock_bazel {
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
deleted file mode 100755
index ca63fdf..0000000
--- a/tests/mixed_mode_test.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/bash
-
-set -o pipefail
-
-# This test exercises mixed builds where Soong and Bazel cooperate in building
-# Android.
-#
-# When the execroot is deleted, the Bazel server process will automatically
-# terminate itself.
-
-source "$(dirname "$0")/lib.sh"
-
-function test_bazel_smoke {
- setup
-
- run_soong bp2build
-
- run_bazel info --config=bp2build
-}
-
-function test_add_irrelevant_file {
- setup
-
- mkdir -p soong_tests/a/b
- touch soong_tests/a/b/c.txt
- cat > soong_tests/a/b/Android.bp <<'EOF'
-filegroup {
- name: "c",
- srcs: ["c.txt"],
- bazel_module: { bp2build_available: true },
-}
-EOF
-
- run_soong --bazel-mode-staging nothing
-
- if [[ ! -e out/soong/bp2build/soong_tests/a/b/BUILD.bazel ]]; then
- fail "BUILD.bazel not created"
- fi
-
- if [[ ! -e out/soong/build.ninja ]]; then
- fail "build.ninja not created"
- fi
-
- local mtime_build1=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
- local mtime_ninja1=$(stat -c "%y" out/soong/build.ninja)
-
- touch soong_tests/a/irrelevant.txt
-
- run_soong --bazel-mode-staging nothing
- local mtime_build2=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
- local mtime_ninja2=$(stat -c "%y" out/soong/build.ninja)
-
- if [[ "$mtime_build1" != "$mtime_build2" ]]; then
- fail "BUILD.bazel was generated"
- fi
-
- if [[ "$mtime_ninja1" != "$mtime_ninja2" ]]; then
- fail "build.ninja was regenerated"
- fi
-
- if [[ ! -e out/soong/workspace/soong_tests/a/irrelevant.txt ]]; then
- fail "new file was not symlinked"
- fi
-}
-
-function test_force_enabled_modules {
- setup
- # b/273910287 - test force enable modules
- mkdir -p soong_tests/a/b
- cat > soong_tests/a/b/Android.bp <<'EOF'
-genrule {
- name: "touch-file",
- out: ["fake-out.txt"],
- cmd: "touch $(out)",
- bazel_module: { bp2build_available: true },
-}
-
-genrule {
- name: "unenabled-touch-file",
- out: ["fake-out2.txt"],
- cmd: "touch $(out)",
- bazel_module: { bp2build_available: false },
-}
-EOF
- run_soong --bazel-mode-staging --bazel-force-enabled-modules=touch-file nothing
- local bazel_contained=`grep out/soong/.intermediates/soong_tests/a/b/touch-file/gen/fake-out.txt out/soong/build.ninja`
- if [[ $bazel_contained == '' ]]; then
- fail "Bazel actions not found for force-enabled module"
- fi
-
- unused=`run_soong --bazel-force-enabled-modules=unenabled-touch-file --ensure-allowlist-integrity nothing >/dev/null`
-
- if [[ $? -ne 1 ]]; then
- fail "Expected failure due to force-enabling an unenabled module "
- fi
-}
-
-
-scan_and_run_tests
diff --git a/tests/persistent_bazel_test.sh b/tests/persistent_bazel_test.sh
deleted file mode 100755
index 9b7b58f..0000000
--- a/tests/persistent_bazel_test.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/bash -eu
-
-# Copyright (C) 2023 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.
-
-set -o pipefail
-
-source "$(dirname "$0")/lib.sh"
-
-# This test verifies that adding USE_PERSISTENT_BAZEL creates a Bazel process
-# that outlasts the build process.
-# This test should only be run in sandboxed environments (because this test
-# verifies a Bazel process using global process list, and may spawn lingering
-# Bazel processes).
-function test_persistent_bazel {
- setup
-
- # Ensure no existing Bazel process.
- if [[ -e out/bazel/output/server/server.pid.txt ]]; then
- kill $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null || true
- if kill -0 $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null ; then
- fail "Error killing pre-setup bazel"
- fi
- fi
-
- USE_PERSISTENT_BAZEL=1 run_soong nothing
-
- if ! kill -0 $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null ; then
- fail "Persistent bazel process expected, but not found after first build"
- fi
- BAZEL_PID=$(cat out/bazel/output/server/server.pid.txt)
-
- USE_PERSISTENT_BAZEL=1 run_soong nothing
-
- if ! kill -0 $BAZEL_PID 2>/dev/null ; then
- fail "Bazel pid $BAZEL_PID was killed after second build"
- fi
-
- kill $BAZEL_PID 2>/dev/null
- if ! kill -0 $BAZEL_PID 2>/dev/null ; then
- fail "Error killing bazel on shutdown"
- fi
-}
-
-# Verifies that USE_PERSISTENT_BAZEL mode operates as expected in the event
-# that there are Bazel failures.
-function test_bazel_failure {
- setup
-
- # Ensure no existing Bazel process.
- if [[ -e out/bazel/output/server/server.pid.txt ]]; then
- kill $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null || true
- if kill -0 $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null ; then
- fail "Error killing pre-setup bazel"
- fi
- fi
-
- # Introduce a syntax error in a BUILD file which is used in every build
- # (Note this is a BUILD file which is copied as part of test setup, so this
- # has no effect on sources outside of this test.
- rm -rf build/bazel/rules
-
- USE_PERSISTENT_BAZEL=1 run_soong nothing 1>out/failurelog.txt 2>&1 && fail "Expected build failure" || true
-
- if ! grep -sq "cannot load //build/bazel/rules/common/api_constants.bzl" out/failurelog.txt ; then
- fail "Expected error to contain 'cannot load //build/bazel/rules/common/api_constants.bzl', instead got:\n$(cat out/failurelog.txt)"
- fi
-
- kill $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null || true
-}
-
-scan_and_run_tests
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 231e18b..0235f2b 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -4,25 +4,6 @@
TOP="$(readlink -f "$(dirname "$0")"/../../..)"
"$TOP/build/soong/tests/androidmk_test.sh"
-"$TOP/build/soong/tests/b_args_test.sh"
"$TOP/build/soong/tests/bootstrap_test.sh"
-"$TOP/build/soong/tests/mixed_mode_test.sh"
-"$TOP/build/soong/tests/bp2build_bazel_test.sh"
-"$TOP/build/soong/tests/persistent_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
-"$TOP/build/soong/tests/stale_metrics_files_test.sh"
-"$TOP/build/soong/tests/symlink_forest_rerun_test.sh"
"$TOP/prebuilts/build-tools/linux-x86/bin/py3-cmd" "$TOP/build/bazel/ci/rbc_dashboard.py" aosp_arm64-userdebug
-
-# The following tests build against the full source tree and don't rely on the
-# mock client.
-"$TOP/build/soong/tests/apex_comparison_tests.sh"
-"$TOP/build/soong/tests/apex_comparison_tests.sh" "module_arm64only"
-TEST_BAZEL=true extra_build_params=--bazel-mode-staging "$TOP/build/soong/tests/dcla_apex_comparison_test.sh"
-#BUILD_BROKEN_DISABLE_BAZEL=true "$TOP/build/soong/tests/dcla_apex_comparison_test.sh"
-"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh"
-"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_arm" "armv7-a"
-"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_cf_arm64_phone" "armv8-a" "cortex-a53"
-
-"$TOP/build/bazel/ci/b_test.sh"
-"$TOP/build/soong/tests/symlinks_path_test.sh"
diff --git a/tests/stale_metrics_files_test.sh b/tests/stale_metrics_files_test.sh
deleted file mode 100755
index 0da89c3..0000000
--- a/tests/stale_metrics_files_test.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash -e
-
-# This test ensures that stale metrics files are deleted after each run
-
-# Run bazel
-# Note - bp2build metrics are present after clean runs, only
-build/soong/soong_ui.bash --make-mode clean
-build/bazel/bin/b build libcore:all
-soong_build_metrics_files=("out/soong_build_metrics.pb" "out/build_progress.pb" "out/soong_metrics" "out/bp2build_metrics.pb")
-bazel_build_metrics_files=("out/bazel_metrics.pb" "out/build_progress.pb" "out/soong_metrics" "out/bp2build_metrics.pb")
-
-# Ensure bazel metrics files are present
-for i in ${!bazel_build_metrics_files[@]};
-do
- file=${bazel_build_metrics_files[$i]}
- if [[ ! -f $file ]]; then
- echo "Missing metrics file for Bazel build " $file
- exit 1
- fi
-done
-
-
-# Run a soong build
-build/soong/soong_ui.bash --make-mode nothing
-
-for i in ${!soong_build_metrics_files[@]};
-do
- file=${soong_build_metrics_files[$i]}
- if [[ ! -f $file ]]; then
- echo "Missing metrics file for Soong build " $file
- exit 1
- fi
-done
-
-# Ensure that bazel_metrics.pb is deleted
-if [[ -f out/bazel_metrics.pb ]]; then
- echo "Stale out/bazel_metrics.pb file detected"
- exit 1
-fi
-
-# Run bazel again - to make sure that soong_build_metrics.pb gets deleted
-build/bazel/bin/b build libcore:all
-
-if [[ -f out/soong_build_metrics.pb ]]; then
- echo "Stale out/soong_build_metrics.pb file detected"
- exit 1
-fi
diff --git a/tests/symlink_forest_rerun_test.sh b/tests/symlink_forest_rerun_test.sh
deleted file mode 100755
index 74e779e..0000000
--- a/tests/symlink_forest_rerun_test.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash -eu
-
-set -o pipefail
-
-# Tests that symlink forest will replant if soong_build has changed
-# Any change to the build system should trigger a rerun
-
-source "$(dirname "$0")/lib.sh"
-
-function test_symlink_forest_reruns {
- setup
-
- mkdir -p a
- touch a/g.txt
- cat > a/Android.bp <<'EOF'
-filegroup {
- name: "g",
- srcs: ["g.txt"],
- }
-EOF
-
- run_soong g
-
- mtime=`cat out/soong/workspace/soong_build_mtime`
- # rerun with no changes - ensure that it hasn't changed
- run_soong g
- newmtime=`cat out/soong/workspace/soong_build_mtime`
- if [[ ! "$mtime" == "$mtime" ]]; then
- fail "symlink forest reran when it shouldn't have"
- fi
-
- # change exit codes to force a soong_build rebuild.
- sed -i 's/os.Exit(1)/os.Exit(2)/g' build/soong/bp2build/symlink_forest.go
-
- run_soong g
- newmtime=`cat out/soong/workspace/soong_build_mtime`
- if [[ "$mtime" == "$newmtime" ]]; then
- fail "symlink forest did not rerun when it should have"
- fi
-
-}
-
-scan_and_run_tests
diff --git a/tests/symlinks_path_test.sh b/tests/symlinks_path_test.sh
deleted file mode 100755
index ed42911..0000000
--- a/tests/symlinks_path_test.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash -eu
-
-set -o pipefail
-
-# Test that relative symlinks work by recreating the bug in b/259191764
-# In some cases, developers prefer to move their checkouts. This causes
-# issues in that symlinked files (namely, the bazel wrapper script)
-# cannot be found. As such, we implemented relative symlinks so that a
-# moved checkout doesn't need a full clean before rebuilding.
-# The bazel output base will still need to be removed, as Starlark
-# doesn't seem to support relative symlinks yet.
-
-source "$(dirname "$0")/lib.sh"
-
-function check_link_has_mock_top_prefix {
- input_link=$1
- link_target=`readlink $input_link`
- if [[ $link_target != "$MOCK_TOP"* ]]; then
- echo "Symlink for file $input_link -> $link_target doesn't start with $MOCK_TOP"
- exit 1
- fi
-}
-
-function test_symlinks_updated_when_top_dir_changed {
- setup
-
- mkdir -p a
- touch a/g.txt
- cat > a/Android.bp <<'EOF'
-filegroup {
- name: "g",
- srcs: ["g.txt"],
- bazel_module: {bp2build_available: true},
-}
-EOF
- # A directory under $MOCK_TOP
- outdir=out2
-
- # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
- (export OUT_DIR=$MOCK_TOP/$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
-
- g_txt="out2/soong/workspace/a/g.txt"
- check_link_has_mock_top_prefix "$g_txt"
-
- move_mock_top
-
- (export OUT_DIR=$MOCK_TOP/$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
- check_link_has_mock_top_prefix "$g_txt"
-}
-
-scan_and_run_tests
\ No newline at end of file
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
index f0336a3..e852584 100644
--- a/tradefed/Android.bp
+++ b/tradefed/Android.bp
@@ -13,6 +13,7 @@
"autogen.go",
"config.go",
"makevars.go",
+ "providers.go",
],
pluginFor: ["soong_build"],
}
diff --git a/tradefed/providers.go b/tradefed/providers.go
new file mode 100644
index 0000000..66cb625
--- /dev/null
+++ b/tradefed/providers.go
@@ -0,0 +1,26 @@
+package tradefed
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+// Output files we need from a base test that we derive from.
+type BaseTestProviderData struct {
+ // data files and apps for android_test
+ InstalledFiles android.Paths
+ // apk for android_test
+ OutputFile android.Path
+ // Either handwritten or generated TF xml.
+ TestConfig android.Path
+ // Other modules we require to be installed to run tests. We expect base to build them.
+ HostRequiredModuleNames []string
+ RequiredModuleNames []string
+ // List of test suites base uses.
+ TestSuites []string
+ // Used for bases that are Host
+ IsHost bool
+}
+
+var BaseTestProviderKey = blueprint.NewProvider[BaseTestProviderData]()
diff --git a/tradefed_modules/Android.bp b/tradefed_modules/Android.bp
new file mode 100644
index 0000000..9969ae2
--- /dev/null
+++ b/tradefed_modules/Android.bp
@@ -0,0 +1,21 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-tradefed-modules",
+ pkgPath: "android/soong/tradefed_modules",
+ deps: [
+ "blueprint",
+ "soong-android",
+ "soong-java",
+ "soong-tradefed",
+ ],
+ srcs: [
+ "test_module_config.go",
+ ],
+ testSrcs: [
+ "test_module_config_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
new file mode 100644
index 0000000..6867537
--- /dev/null
+++ b/tradefed_modules/test_module_config.go
@@ -0,0 +1,321 @@
+package tradefed_modules
+
+import (
+ "android/soong/android"
+ "android/soong/tradefed"
+ "encoding/json"
+ "fmt"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterTestModuleConfigBuildComponents(android.InitRegistrationContext)
+}
+
+// Register the license_kind module type.
+func RegisterTestModuleConfigBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("test_module_config", TestModuleConfigFactory)
+ ctx.RegisterModuleType("test_module_config_host", TestModuleConfigHostFactory)
+}
+
+type testModuleConfigModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ base android.Module
+
+ tradefedProperties
+
+ // Our updated testConfig.
+ testConfig android.OutputPath
+ manifest android.InstallPath
+ provider tradefed.BaseTestProviderData
+}
+
+// Host is mostly the same as non-host, just some diffs for AddDependency and
+// AndroidMkEntries, but the properties are the same.
+type testModuleConfigHostModule struct {
+ testModuleConfigModule
+}
+
+// Properties to list in Android.bp for this module.
+type tradefedProperties struct {
+ // Module name of the base test that we will run.
+ Base *string `android:"path,arch_variant"`
+
+ // Tradefed Options to add to tradefed xml when not one of the include or exclude filter or property.
+ // Sample: [{name: "TestRunnerOptionName", value: "OptionValue" }]
+ Options []tradefed.Option
+
+ // List of tradefed include annotations to add to tradefed xml, like "android.platform.test.annotations.Presubmit".
+ // Tests will be restricted to those matching an include_annotation or include_filter.
+ Include_annotations []string
+
+ // List of tradefed include annotations to add to tradefed xml, like "android.support.test.filters.FlakyTest".
+ // Tests matching an exclude annotation or filter will be skipped.
+ Exclude_annotations []string
+
+ // List of tradefed include filters to add to tradefed xml, like "fully.qualified.class#method".
+ // Tests will be restricted to those matching an include_annotation or include_filter.
+ Include_filters []string
+
+ // List of tradefed exclude filters to add to tradefed xml, like "fully.qualified.class#method".
+ // Tests matching an exclude annotation or filter will be skipped.
+ Exclude_filters []string
+
+ // List of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string
+}
+
+type dependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+var (
+ testModuleConfigTag = dependencyTag{name: "TestModuleConfigBase"}
+ testModuleConfigHostTag = dependencyTag{name: "TestModuleConfigHostBase"}
+ pctx = android.NewPackageContext("android/soong/tradefed_modules")
+)
+
+func (m *testModuleConfigModule) InstallInTestcases() bool {
+ return true
+}
+
+func (m *testModuleConfigModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if m.Base == nil {
+ ctx.ModuleErrorf("'base' field must be set to a 'android_test' module.")
+ return
+ }
+ ctx.AddDependency(ctx.Module(), testModuleConfigTag, *m.Base)
+}
+
+// Takes base's Tradefed Config xml file and generates a new one with the test properties
+// appeneded from this module.
+// Rewrite the name of the apk in "test-file-name" to be our module's name, rather than the original one.
+func (m *testModuleConfigModule) fixTestConfig(ctx android.ModuleContext, baseTestConfig android.Path) android.OutputPath {
+ // Test safe to do when no test_runner_options, but check for that earlier?
+ fixedConfig := android.PathForModuleOut(ctx, "test_config_fixer", ctx.ModuleName()+".config")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ command := rule.Command().BuiltTool("test_config_fixer").Input(baseTestConfig).Output(fixedConfig)
+ options := m.composeOptions()
+ if len(options) == 0 {
+ ctx.ModuleErrorf("Test options must be given when using test_module_config. Set include/exclude filter or annotation.")
+ }
+ xmlTestModuleConfigSnippet, _ := json.Marshal(options)
+ escaped := proptools.NinjaAndShellEscape(string(xmlTestModuleConfigSnippet))
+ command.FlagWithArg("--test-file-name=", ctx.ModuleName()+".apk").
+ FlagWithArg("--orig-test-file-name=", *m.tradefedProperties.Base+".apk").
+ FlagWithArg("--test-runner-options=", escaped)
+ rule.Build("fix_test_config", "fix test config")
+ return fixedConfig.OutputPath
+}
+
+// Convert --exclude_filters: ["filter1", "filter2"] ->
+// [ Option{Name: "exclude-filters", Value: "filter1"}, Option{Name: "exclude-filters", Value: "filter2"},
+// ... + include + annotations ]
+func (m *testModuleConfigModule) composeOptions() []tradefed.Option {
+ options := m.Options
+ for _, e := range m.Exclude_filters {
+ options = append(options, tradefed.Option{Name: "exclude-filter", Value: e})
+ }
+ for _, i := range m.Include_filters {
+ options = append(options, tradefed.Option{Name: "include-filter", Value: i})
+ }
+ for _, e := range m.Exclude_annotations {
+ options = append(options, tradefed.Option{Name: "exclude-annotation", Value: e})
+ }
+ for _, i := range m.Include_annotations {
+ options = append(options, tradefed.Option{Name: "include-annotation", Value: i})
+ }
+ return options
+}
+
+// Files to write and where they come from:
+// 1) test_module_config.manifest
+// - Leave a trail of where we got files from in case other tools need it.
+//
+// 2) $Module.config
+// - comes from base's module.config (AndroidTest.xml), and then we add our test_options.
+// provider.TestConfig
+// [rules via soong_app_prebuilt]
+//
+// 3) $ARCH/$Module.apk
+// - comes from base
+// provider.OutputFile
+// [rules via soong_app_prebuilt]
+//
+// 4) [bases data]
+// - We copy all of bases data (like helper apks) to our install directory too.
+// Since we call AndroidMkEntries on base, it will write out LOCAL_COMPATIBILITY_SUPPORT_FILES
+// with this data and app_prebuilt.mk will generate the rules to copy it from base.
+// We have no direct rules here to add to ninja.
+//
+// If we change to symlinks, this all needs to change.
+func (m *testModuleConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ m.validateBase(ctx, &testModuleConfigTag, "android_test", false)
+ m.generateManifestAndConfig(ctx)
+
+}
+
+// Any test suites in base should not be repeated in the derived class, except "general-tests".
+// We may restrict derived tests to only be "general-tests" as it doesn't make sense to add a slice
+// of a test to compatibility suite.
+//
+// Returns ErrorMessage, false on problems
+// Returns _, true if okay.
+func (m *testModuleConfigModule) validateTestSuites(ctx android.ModuleContext) bool {
+ if len(m.tradefedProperties.Test_suites) == 0 {
+ ctx.ModuleErrorf("At least one test-suite must be set or this won't run. Use \"general-tests\"")
+ return false
+ }
+
+ derivedSuites := make(map[string]bool)
+ // See if any suites in base is also in derived (other than general-tests)
+ for _, s := range m.tradefedProperties.Test_suites {
+ if s != "general-tests" {
+ derivedSuites[s] = true
+ }
+ }
+ if len(derivedSuites) == 0 {
+ return true
+ }
+ for _, baseSuite := range m.provider.TestSuites {
+ if derivedSuites[baseSuite] {
+ ctx.ModuleErrorf("TestSuite %s exists in the base, do not add it here", baseSuite)
+ return false
+ }
+ }
+
+ return true
+}
+
+func TestModuleConfigFactory() android.Module {
+ module := &testModuleConfigModule{}
+
+ module.AddProperties(&module.tradefedProperties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
+ return module
+}
+
+func TestModuleConfigHostFactory() android.Module {
+ module := &testModuleConfigHostModule{}
+
+ module.AddProperties(&module.tradefedProperties)
+ android.InitAndroidMultiTargetsArchModule(module, android.HostSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
+ return module
+}
+
+// Implements android.AndroidMkEntriesProvider
+var _ android.AndroidMkEntriesProvider = (*testModuleConfigModule)(nil)
+
+func (m *testModuleConfigModule) AndroidMkEntries() []android.AndroidMkEntries {
+ // We rely on base writing LOCAL_COMPATIBILITY_SUPPORT_FILES for its data files
+ entriesList := m.base.(android.AndroidMkEntriesProvider).AndroidMkEntries()
+ entries := &entriesList[0]
+ entries.OutputFile = android.OptionalPathForPath(m.provider.OutputFile)
+ entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE", m.Name()) // out module name, not base's
+
+ // Out update config file with extra options.
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", m.testConfig)
+ entries.SetString("LOCAL_MODULE_TAGS", "tests")
+
+ // Don't append to base's test-suites, only use the ones we define, so clear it before
+ // appending to it.
+ entries.SetString("LOCAL_COMPATIBILITY_SUITE", "")
+ entries.AddCompatibilityTestSuites(m.tradefedProperties.Test_suites...)
+
+ if len(m.provider.HostRequiredModuleNames) > 0 {
+ entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", m.provider.HostRequiredModuleNames...)
+ }
+ if len(m.provider.RequiredModuleNames) > 0 {
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", m.provider.RequiredModuleNames...)
+ }
+
+ if m.provider.IsHost == false {
+ // Not needed for jar_host_test
+ //
+ // Clear the JNI symbols because they belong to base not us. Either transform the names in the string
+ // or clear the variable because we don't need it, we are copying bases libraries not generating
+ // new ones.
+ entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", "")
+ }
+ })
+ return entriesList
+}
+
+func (m *testModuleConfigHostModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if m.Base == nil {
+ ctx.ModuleErrorf("'base' field must be set to a 'java_test_host' module")
+ return
+ }
+ ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), testModuleConfigHostTag, *m.Base)
+}
+
+// File to write:
+// 1) out/host/linux-x86/testcases/derived-module/test_module_config.manifest # contains base's name.
+// 2) out/host/linux-x86/testcases/derived-module/derived-module.config # Update AnroidTest.xml
+// 3) out/host/linux-x86/testcases/derived-module/base.jar
+// - written via soong_java_prebuilt.mk
+//
+// 4) out/host/linux-x86/testcases/derived-module/* # data dependencies from base.
+// - written via soong_java_prebuilt.mk
+func (m *testModuleConfigHostModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ m.validateBase(ctx, &testModuleConfigHostTag, "java_test_host", true)
+ m.generateManifestAndConfig(ctx)
+}
+
+// Ensure the base listed is the right type by checking that we get the expected provider data.
+// Returns false on errors and the context is updated with an error indicating the baseType expected.
+func (m *testModuleConfigModule) validateBase(ctx android.ModuleContext, depTag *dependencyTag, baseType string, baseShouldBeHost bool) {
+ ctx.VisitDirectDepsWithTag(*depTag, func(dep android.Module) {
+ if provider, ok := android.OtherModuleProvider(ctx, dep, tradefed.BaseTestProviderKey); ok {
+ if baseShouldBeHost == provider.IsHost {
+ m.base = dep
+ m.provider = provider
+ } else {
+ if baseShouldBeHost {
+ ctx.ModuleErrorf("'android_test' module used as base, but 'java_test_host' expected.")
+ } else {
+ ctx.ModuleErrorf("'java_test_host' module used as base, but 'android_test' expected.")
+ }
+ }
+ } else {
+ ctx.ModuleErrorf("'%s' module used as base but it is not a '%s' module.", *m.Base, baseType)
+ }
+ })
+}
+
+// Actions to write:
+// 1. manifest file to testcases dir
+// 2. New Module.config / AndroidTest.xml file with our options.
+func (m *testModuleConfigModule) generateManifestAndConfig(ctx android.ModuleContext) {
+ if !m.validateTestSuites(ctx) {
+ return
+ }
+ // Ensure the provider is accurate
+ if m.provider.TestConfig == nil {
+ return
+ }
+
+ // 1) A manifest file listing the base, write text to a tiny file.
+ installDir := android.PathForModuleInstall(ctx, ctx.ModuleName())
+ manifest := android.PathForModuleOut(ctx, "test_module_config.manifest")
+ android.WriteFileRule(ctx, manifest, fmt.Sprintf("{%q: %q}", "base", *m.tradefedProperties.Base))
+ // build/soong/android/androidmk.go has this comment:
+ // Assume the primary install file is last
+ // so we need to Install our file last.
+ ctx.InstallFile(installDir, manifest.Base(), manifest)
+
+ // 2) Module.config / AndroidTest.xml
+ m.testConfig = m.fixTestConfig(ctx, m.provider.TestConfig)
+}
+
+var _ android.AndroidMkEntriesProvider = (*testModuleConfigHostModule)(nil)
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
new file mode 100644
index 0000000..41dd3d4
--- /dev/null
+++ b/tradefed_modules/test_module_config_test.go
@@ -0,0 +1,361 @@
+// 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 tradefed_modules
+
+import (
+ "android/soong/android"
+ "android/soong/java"
+ "strconv"
+ "strings"
+ "testing"
+)
+
+const bp = `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+
+ android_test_helper_app {
+ name: "HelperApp",
+ srcs: ["helper.java"],
+ }
+
+ android_test {
+ name: "base",
+ sdk_version: "current",
+ data: [":HelperApp", "data/testfile"],
+ }
+
+ test_module_config {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }
+
+`
+
+// Ensure we create files needed and set the AndroidMkEntries needed
+func TestModuleConfigAndroidTest(t *testing.T) {
+
+ ctx := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).RunTestWithBp(t, bp)
+
+ derived := ctx.ModuleForTests("derived_test", "android_common")
+ // Assert there are rules to create these files.
+ derived.Output("test_module_config.manifest")
+ derived.Output("test_config_fixer/derived_test.config")
+
+ // Ensure some basic rules exist.
+ ctx.ModuleForTests("base", "android_common").Output("package-res.apk")
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
+
+ // Ensure some entries from base are there, specifically support files for data and helper apps.
+ assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
+
+ // And some new derived entries are there.
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE_TAGS"], []string{"tests"})
+
+ // And ones we override
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
+
+ android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
+}
+
+// Make sure we call test-config-fixer with the right args.
+func TestModuleConfigOptions(t *testing.T) {
+
+ ctx := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).RunTestWithBp(t, bp)
+
+ // Check that we generate a rule to make a new AndroidTest.xml/Module.config file.
+ derived := ctx.ModuleForTests("derived_test", "android_common")
+ rule_cmd := derived.Rule("fix_test_config").RuleParams.Command
+ android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd,
+ `--test-file-name=derived_test.apk --orig-test-file-name=base.apk --test-runner-options='[{"Name":"exclude-filter","Key":"","Value":"android.test.example.devcodelab.DevCodelabTest#testHelloFail"},{"Name":"include-annotation","Key":"","Value":"android.platform.test.annotations.LargeTest"}]'`)
+}
+
+// Ensure we error for a base we don't support.
+func TestModuleConfigWithHostBaseShouldFailWithExplicitMessage(t *testing.T) {
+ badBp := `
+ java_test_host {
+ name: "base",
+ srcs: ["a.java"],
+ }
+
+ test_module_config {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("'java_test_host' module used as base, but 'android_test' expected")).
+ RunTestWithBp(t, badBp)
+}
+
+func TestModuleConfigBadBaseShouldFailWithGeneralMessage(t *testing.T) {
+ badBp := `
+ java_library {
+ name: "base",
+ srcs: ["a.java"],
+ }
+
+ test_module_config {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsOneErrorPattern("'base' module used as base but it is not a 'android_test' module.")).
+ RunTestWithBp(t, badBp)
+}
+
+func TestModuleConfigNoBaseShouldFail(t *testing.T) {
+ badBp := `
+ java_library {
+ name: "base",
+ srcs: ["a.java"],
+ }
+
+ test_module_config {
+ name: "derived_test",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsOneErrorPattern("'base' field must be set to a 'android_test' module.")).
+ RunTestWithBp(t, badBp)
+}
+
+// Ensure we error for a base we don't support.
+func TestModuleConfigNoFiltersOrAnnotationsShouldFail(t *testing.T) {
+ badBp := `
+ android_test {
+ name: "base",
+ sdk_version: "current",
+ srcs: ["a.java"],
+ }
+
+ test_module_config {
+ name: "derived_test",
+ base: "base",
+ test_suites: ["general-tests"],
+ }`
+
+ ctx := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")).
+ RunTestWithBp(t, badBp)
+
+ ctx.ModuleForTests("derived_test", "android_common")
+}
+
+func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) {
+ multiBp := `
+ android_test {
+ name: "base",
+ sdk_version: "current",
+ srcs: ["a.java"],
+ }
+
+ test_module_config {
+ name: "derived_test",
+ base: "base",
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }
+
+ test_module_config {
+ name: "another_derived_test",
+ base: "base",
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }`
+
+ ctx := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).RunTestWithBp(t, multiBp)
+
+ {
+ derived := ctx.ModuleForTests("derived_test", "android_common")
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
+ // All these should be the same in both derived tests
+ assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
+ // Except this one, which points to the updated tradefed xml file.
+ android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "derived_test/android_common/test_config_fixer/derived_test.config")
+ // And this one, the module name.
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
+ }
+
+ {
+ derived := ctx.ModuleForTests("another_derived_test", "android_common")
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
+ // All these should be the same in both derived tests
+ assertEntryPairValues(t, entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{"HelperApp.apk", "data/testfile"})
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_SOONG_JNI_LIBS_SYMBOLS"], []string{""})
+ // Except this one, which points to the updated tradefed xml file.
+ android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0], "another_derived_test/android_common/test_config_fixer/another_derived_test.config")
+ // And this one, the module name.
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"another_derived_test"})
+ }
+}
+
+// Test_module_config_host rule is allowed to depend on java_test_host
+func TestModuleConfigHostBasics(t *testing.T) {
+ bp := `
+ java_test_host {
+ name: "base",
+ srcs: ["a.java"],
+ test_suites: ["suiteA", "general-tests", "suiteB"],
+ }
+
+ test_module_config_host {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests"],
+ }`
+
+ ctx := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).RunTestWithBp(t, bp)
+
+ variant := ctx.Config.BuildOS.String() + "_common"
+ derived := ctx.ModuleForTests("derived_test", variant)
+ mod := derived.Module().(*testModuleConfigHostModule)
+ allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)
+ entries := allEntries[0]
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_MODULE"], []string{"derived_test"})
+
+ if !mod.Host() {
+ t.Errorf("host bit is not set for a java_test_host module.")
+ }
+ actualData, _ := strconv.ParseBool(entries.EntryMap["LOCAL_IS_UNIT_TEST"][0])
+ android.AssertBoolEquals(t, "LOCAL_IS_UNIT_TEST", true, actualData)
+
+}
+
+// When you pass an 'android_test' as base, the warning message is a bit obscure,
+// talking about variants, but it is something. Ideally we could do better.
+func TestModuleConfigHostBadBaseShouldFailWithVariantWarning(t *testing.T) {
+ badBp := `
+ android_test {
+ name: "base",
+ sdk_version: "current",
+ srcs: ["a.java"],
+ }
+
+ test_module_config_host {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("missing variant")).
+ RunTestWithBp(t, badBp)
+}
+
+func TestModuleConfigHostNeedsATestSuite(t *testing.T) {
+ badBp := `
+ java_test_host {
+ name: "base",
+ srcs: ["a.java"],
+ }
+
+ test_module_config_host {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("At least one test-suite must be set")).
+ RunTestWithBp(t, badBp)
+}
+
+func TestModuleConfigHostDuplicateTestSuitesGiveErrors(t *testing.T) {
+ badBp := `
+ java_test_host {
+ name: "base",
+ srcs: ["a.java"],
+ test_suites: ["general-tests", "some-compat"],
+ }
+
+ test_module_config_host {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["general-tests", "some-compat"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("TestSuite some-compat exists in the base")).
+ RunTestWithBp(t, badBp)
+}
+
+// Use for situations where the entries map contains pairs: [srcPath:installedPath1, srcPath2:installedPath2]
+// and we want to compare the RHS of the pairs, i.e. installedPath1, installedPath2
+func assertEntryPairValues(t *testing.T, actual []string, expected []string) {
+ for i, e := range actual {
+ parts := strings.Split(e, ":")
+ if len(parts) != 2 {
+ t.Errorf("Expected entry to have a value delimited by :, received: %s", e)
+ return
+ }
+ android.AssertStringEquals(t, "", parts[1], expected[i])
+ }
+}
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index e7896ab..a29f413 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -23,6 +23,7 @@
"cts/",
"dalvik/",
"developers/",
+ "frameworks/",
// Do not block other directories in kernel/, see b/319658303.
"kernel/configs/",
"kernel/prebuilts/",
diff --git a/ui/build/config.go b/ui/build/config.go
index 1a25397..7426a78 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -386,22 +386,21 @@
// Configure Java-related variables, including adding it to $PATH
java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
- java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
java21Home := filepath.Join("prebuilts/jdk/jdk21", ret.HostPrebuiltTag())
javaHome := func() string {
if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
return override
}
- if ret.environ.IsEnvTrue("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN") {
- return java21Home
- }
if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
- ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
+ ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
}
if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
- ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
+ ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
}
- return java17Home
+ if toolchain21, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN"); ok && toolchain21 != "true" {
+ ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
+ }
+ return java21Home
}()
absJavaHome := absPath(ctx, javaHome)
@@ -1387,7 +1386,9 @@
}
func (c *configImpl) rbeSockAddr(dir string) (string, error) {
- maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
+ // Absolute path socket addresses have a prefix of //. This should
+ // be included in the length limit.
+ maxNameLen := len(syscall.RawSockaddrUnix{}.Path) - 2
base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
name := filepath.Join(dir, base)
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 2f25a8c..81c678d 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -94,7 +94,6 @@
"gcert": Allowed,
"gcertstatus": Allowed,
"gcloud": Allowed,
- "getopt": Allowed,
"git": Allowed,
"hexdump": Allowed,
"jar": Allowed,
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index fa04207..5142a41 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -163,7 +163,7 @@
return
}
fmt.Fprintln(ctx.Writer, "")
- fmt.Fprintln(ctx.Writer, "\033[33mWARNING: Missing LOAS credentials, please run `gcert`. This will result in failing builds in the future, see go/rbe-android-default-announcement.\033[0m")
+ fmt.Fprintln(ctx.Writer, "\033[33mWARNING: Missing LOAS credentials, please run `gcert`. This is required for a successful build execution. See go/rbe-android-default-announcement for more information.\033[0m")
fmt.Fprintln(ctx.Writer, "")
}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index f4e3fb8..8c3ff29 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -206,10 +206,11 @@
}
if msg.EdgeStarted != nil {
action := &Action{
- Description: msg.EdgeStarted.GetDesc(),
- Outputs: msg.EdgeStarted.Outputs,
- Inputs: msg.EdgeStarted.Inputs,
- Command: msg.EdgeStarted.GetCommand(),
+ Description: msg.EdgeStarted.GetDesc(),
+ Outputs: msg.EdgeStarted.Outputs,
+ Inputs: msg.EdgeStarted.Inputs,
+ Command: msg.EdgeStarted.GetCommand(),
+ ChangedInputs: msg.EdgeStarted.ChangedInputs,
}
n.status.StartAction(action)
running[msg.EdgeStarted.GetId()] = action
diff --git a/ui/status/ninja_frontend/frontend.pb.go b/ui/status/ninja_frontend/frontend.pb.go
index d8344c8..fce7ca2 100644
--- a/ui/status/ninja_frontend/frontend.pb.go
+++ b/ui/status/ninja_frontend/frontend.pb.go
@@ -363,6 +363,8 @@
Command *string `protobuf:"bytes,6,opt,name=command" json:"command,omitempty"`
// Edge uses console.
Console *bool `protobuf:"varint,7,opt,name=console" json:"console,omitempty"`
+ // Changed inputs.
+ ChangedInputs []string `protobuf:"bytes,8,rep,name=changed_inputs,json=changedInputs" json:"changed_inputs,omitempty"`
}
func (x *Status_EdgeStarted) Reset() {
@@ -446,6 +448,13 @@
return false
}
+func (x *Status_EdgeStarted) GetChangedInputs() []string {
+ if x != nil {
+ return x.ChangedInputs
+ }
+ return nil
+}
+
type Status_EdgeFinished struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -678,7 +687,7 @@
var file_frontend_proto_rawDesc = []byte{
0x0a, 0x0e, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x12, 0x05, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x22, 0xa9, 0x0b, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
+ 0x12, 0x05, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x22, 0xdb, 0x0b, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x64, 0x67, 0x65,
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x2e,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x64, 0x67, 0x65,
@@ -717,7 +726,7 @@
0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x65, 0x73, 0x74, 0x69,
0x6d, 0x61, 0x74, 0x65, 0x64, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x0f,
0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x1a,
- 0xb6, 0x01, 0x0a, 0x0b, 0x45, 0x64, 0x67, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12,
+ 0xe8, 0x01, 0x0a, 0x0b, 0x45, 0x64, 0x67, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12,
0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16,
@@ -728,50 +737,54 @@
0x64, 0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18,
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18,
0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x1a, 0xf3, 0x03, 0x0a, 0x0c, 0x45, 0x64, 0x67,
- 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64,
- 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x65, 0x6e, 0x64,
- 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06,
- 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75,
- 0x74, 0x70, 0x75, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d,
- 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d,
- 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65,
- 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69,
- 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62,
- 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62,
- 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66,
- 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e,
- 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11,
- 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74,
- 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61,
- 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69,
- 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69,
- 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f,
- 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a,
- 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f,
- 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f,
- 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18,
- 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
- 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f,
- 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f,
- 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a,
- 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65,
- 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61,
- 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x92,
- 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x65,
- 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x69, 0x6e, 0x6a,
- 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x05, 0x6c, 0x65,
- 0x76, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x34, 0x0a,
- 0x05, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00,
- 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a,
- 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55,
- 0x47, 0x10, 0x03, 0x42, 0x2a, 0x48, 0x03, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x2f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64,
+ 0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73,
+ 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x1a, 0xf3, 0x03, 0x0a, 0x0c, 0x45,
+ 0x64, 0x67, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65,
+ 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x65,
+ 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16,
+ 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+ 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74,
+ 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54,
+ 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f,
+ 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73,
+ 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65,
+ 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d,
+ 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a,
+ 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
+ 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f,
+ 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f,
+ 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a,
+ 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
+ 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+ 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e,
+ 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
+ 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e,
+ 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04,
+ 0x74, 0x61, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73,
+ 0x1a, 0x92, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x05,
+ 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x69,
+ 0x6e, 0x6a, 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x05,
+ 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
+ 0x34, 0x0a, 0x05, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f,
+ 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12,
+ 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45,
+ 0x42, 0x55, 0x47, 0x10, 0x03, 0x42, 0x2a, 0x48, 0x03, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74,
+ 0x75, 0x73, 0x2f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x64,
}
var (
diff --git a/ui/status/ninja_frontend/frontend.proto b/ui/status/ninja_frontend/frontend.proto
index 42b251b..faa0d34 100644
--- a/ui/status/ninja_frontend/frontend.proto
+++ b/ui/status/ninja_frontend/frontend.proto
@@ -54,6 +54,8 @@
optional string command = 6;
// Edge uses console.
optional bool console = 7;
+ // Changed inputs since last build.
+ repeated string changed_inputs = 8;
}
message EdgeFinished {
diff --git a/ui/status/status.go b/ui/status/status.go
index da78994..52ed56a 100644
--- a/ui/status/status.go
+++ b/ui/status/status.go
@@ -41,6 +41,10 @@
// It's optional, but one of either Description or Command should be
// set.
Command string
+
+ // ChangedInputs is the (optional) list of inputs that have changed
+ // since last time this action was run.
+ ChangedInputs []string
}
// ActionResult describes the result of running an Action.
diff --git a/ui/tracer/status.go b/ui/tracer/status.go
index f973613..8acf561 100644
--- a/ui/tracer/status.go
+++ b/ui/tracer/status.go
@@ -15,9 +15,10 @@
package tracer
import (
- "android/soong/ui/status"
"strings"
"time"
+
+ "android/soong/ui/status"
)
func (t *tracerImpl) StatusTracer() status.StatusOutput {
@@ -110,6 +111,7 @@
VoluntaryContextSwitches: result.Stats.VoluntaryContextSwitches,
InvoluntaryContextSwitches: result.Stats.InvoluntaryContextSwitches,
Tags: s.parseTags(result.Stats.Tags),
+ ChangedInputs: result.Action.ChangedInputs,
},
})
}
@@ -125,6 +127,7 @@
VoluntaryContextSwitches uint64 `json:"voluntary_context_switches"`
InvoluntaryContextSwitches uint64 `json:"involuntary_context_switches"`
Tags map[string]string `json:"tags"`
+ ChangedInputs []string `json:"changed_inputs"`
}
func (s *statusOutput) Flush() {}