Merge tag 'android-16.0.0_r1' of https://android.googlesource.com/platform/build/soong into HEAD
Android 16.0.0 release 1
Change-Id: Ide1ec574e3f9743d18ee70b928056bb7fe248f80
diff --git a/Android.bp b/Android.bp
index 434ee9f..7134591 100644
--- a/Android.bp
+++ b/Android.bp
@@ -150,10 +150,11 @@
arch: {
arm64: {
cflags: [
- // Prevent the compiler from optimizing code using SVE, as the
- // baremetal environment might not have configured the hardware.
- "-Xclang -target-feature",
- "-Xclang -sve",
+ // Override the global -march= flag (as set by TARGET_ARCH_VARIANT)
+ // and explicitly use the baseline architecture (ARMv8-A is the first
+ // version with 64-bit support) to avoid emitting potentially
+ // unsupported instructions.
+ "-march=armv8-a",
],
},
},
@@ -175,12 +176,18 @@
footer_files: [
":applied_backported_fixes",
],
+ dist: {
+ targets: [
+ "droidcore-unbundled",
+ "sdk",
+ ],
+ },
// Currently, only microdroid, Ravenwood, and cf system image can refer to system-build.prop
visibility: [
- "//build/make/target/product/generic",
- "//build/make/target/product/gsi",
+ "//build/soong/fsgen",
"//packages/modules/Virtualization/build/microdroid",
"//frameworks/base/ravenwood",
+ "//visibility:any_system_partition",
],
}
@@ -190,7 +197,14 @@
system_ext_specific: true,
product_config: ":product_config",
relative_install_path: "etc", // system_ext/etc/build.prop
- visibility: ["//build/make/target/product/gsi"],
+ dist: {
+ targets: ["droidcore-unbundled"],
+ dest: "build.prop-system_ext",
+ },
+ visibility: [
+ "//build/make/target/product/gsi",
+ "//build/soong/fsgen",
+ ],
}
build_prop {
@@ -199,7 +213,14 @@
product_specific: true,
product_config: ":product_config",
relative_install_path: "etc", // product/etc/build.prop
- visibility: ["//build/make/target/product/gsi"],
+ dist: {
+ targets: ["droidcore-unbundled"],
+ dest: "build.prop-product",
+ },
+ visibility: [
+ "//build/make/target/product/gsi",
+ "//build/soong/fsgen",
+ ],
}
build_prop {
@@ -208,7 +229,11 @@
device_specific: true,
product_config: ":product_config",
relative_install_path: "etc", // odm/etc/build.prop
- visibility: ["//visibility:private"],
+ dist: {
+ targets: ["droidcore-unbundled"],
+ dest: "build.prop-odm",
+ },
+ visibility: ["//build/soong/fsgen"],
}
build_prop {
@@ -244,5 +269,17 @@
ramdisk: true,
product_config: ":product_config",
relative_install_path: "etc/ramdisk", // ramdisk/system/etc/ramdisk/build.prop
+ dist: {
+ targets: ["droidcore-unbundled"],
+ dest: "build.prop-ramdisk",
+ },
visibility: ["//visibility:private"],
}
+
+all_apex_certs {
+ name: "all_apex_certs",
+ visibility: [
+ "//cts/tests/tests/security",
+ "//cts/hostsidetests/appsecurity",
+ ],
+}
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index 402cf16..a15fe86 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -17,6 +17,7 @@
"aconfig_values.go",
"aconfig_value_set.go",
"all_aconfig_declarations.go",
+ "all_aconfig_declarations_extension.go",
"exported_java_aconfig_library.go",
"init.go",
"testing.go",
@@ -25,7 +26,21 @@
"aconfig_declarations_test.go",
"aconfig_values_test.go",
"aconfig_value_set_test.go",
- "all_aconfig_declarations_test.go",
+ "all_aconfig_declarations_extension_test.go",
],
pluginFor: ["soong_build"],
}
+
+all_aconfig_declarations {
+ name: "all_aconfig_declarations",
+ visibility: [
+ "//vendor:__subpackages__", // for vendor extensions
+ ],
+ api_signature_files: [
+ ":frameworks-base-api-current.txt",
+ ":frameworks-base-api-system-current.txt",
+ ":frameworks-base-api-system-server-current.txt",
+ ":frameworks-base-api-module-lib-current.txt",
+ ],
+ finalized_flags_file: ":latest-finalized-flags",
+}
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 9a9e568..b068398 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -47,7 +47,7 @@
// are from RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS.
ReleaseConfigValues []AconfigReleaseConfigValue
- // Container(system/vendor/apex) that this module belongs to
+ // Container(system/system_ext/vendor/apex) that this module belongs to
Container string
// The flags will only be repackaged if this prop is true.
@@ -88,13 +88,6 @@
ctx.PropertyErrorf("container", "missing container property")
}
- // treating system_ext as system partition as we are combining them as one container
- // TODO remove this logic once we start enforcing that system_ext cannot be specified as
- // container in the container field.
- if module.properties.Container == "system_ext" {
- module.properties.Container = "system"
- }
-
// Add a dependency on the aconfig_value_sets defined in
// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
// match our package.
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index e89cd31..c39008b 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -37,7 +37,7 @@
`
result := runTest(t, android.FixtureExpectsNoErrors, bp)
- module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
+ module := result.ModuleForTests(t, "module_name", "").Module().(*DeclarationsModule)
// Check that the provider has the right contents
depData, _ := android.OtherModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
@@ -66,7 +66,7 @@
`
result := runTest(t, android.FixtureExpectsNoErrors, bp)
- module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
+ module := result.ModuleForTests(t, "module_name", "").Module().(*DeclarationsModule)
depData, _ := android.OtherModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
android.AssertBoolEquals(t, "exportable", depData.Exportable, false)
}
@@ -84,7 +84,7 @@
`
result := runTest(t, android.FixtureExpectsNoErrors, bp)
- module := result.ModuleForTests("module_name", "")
+ module := result.ModuleForTests(t, "module_name", "")
rule := module.Rule("aconfig")
android.AssertStringEquals(t, "rule must contain container", rule.Args["container"], "--container com.android.foo")
}
@@ -204,7 +204,7 @@
fixture = fixture.ExtendWithErrorHandler(test.errorHandler)
}
result := fixture.RunTestWithBp(t, test.bp)
- module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
+ module := result.ModuleForTests(t, "module_name", "").Module().(*DeclarationsModule)
depData, _ := android.OtherModuleProvider(result, module, android.AconfigReleaseDeclarationsProviderKey)
expectedKeys := []string{""}
for _, rc := range strings.Split(test.buildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"], " ") {
diff --git a/aconfig/aconfig_value_set_test.go b/aconfig/aconfig_value_set_test.go
index 3b7281e..1f04244 100644
--- a/aconfig/aconfig_value_set_test.go
+++ b/aconfig/aconfig_value_set_test.go
@@ -37,7 +37,7 @@
`
result := runTest(t, android.FixtureExpectsNoErrors, bp)
- module := result.ModuleForTests("module_name", "").Module().(*ValueSetModule)
+ module := result.ModuleForTests(t, "module_name", "").Module().(*ValueSetModule)
// Check that the provider has the right contents
depData, _ := android.OtherModuleProvider(result, module, valueSetProviderKey)
@@ -88,7 +88,7 @@
checkModuleHasDependency := func(name, variant, dep string) bool {
t.Helper()
- module := result.ModuleForTests(name, variant).Module()
+ module := result.ModuleForTests(t, name, variant).Module()
depFound := false
result.VisitDirectDeps(module, func(m blueprint.Module) {
if m.Name() == dep {
diff --git a/aconfig/aconfig_values_test.go b/aconfig/aconfig_values_test.go
index ddbea57..0bec14b 100644
--- a/aconfig/aconfig_values_test.go
+++ b/aconfig/aconfig_values_test.go
@@ -30,7 +30,7 @@
`
result := runTest(t, android.FixtureExpectsNoErrors, bp)
- module := result.ModuleForTests("module_name", "").Module().(*ValuesModule)
+ module := result.ModuleForTests(t, "module_name", "").Module().(*ValuesModule)
// Check that the provider has the right contents
depData, _ := android.OtherModuleProvider(result, module, valuesProviderKey)
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index 6ad54da..5a52624 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -19,6 +19,9 @@
"slices"
"android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
// A singleton module that collects all of the aconfig flags declared in the
@@ -28,17 +31,36 @@
// Note that this is ALL aconfig_declarations modules present in the tree, not just
// ones that are relevant to the product currently being built, so that that infra
// doesn't need to pull from multiple builds and merge them.
-func AllAconfigDeclarationsFactory() android.Singleton {
- return &allAconfigDeclarationsSingleton{releaseMap: make(map[string]allAconfigReleaseDeclarationsSingleton)}
+func AllAconfigDeclarationsFactory() android.SingletonModule {
+ module := &allAconfigDeclarationsSingleton{releaseMap: make(map[string]allAconfigReleaseDeclarationsSingleton)}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
}
+type allAconfigDeclarationsInfo struct {
+ parsedFlagsFile android.Path
+}
+
+var allAconfigDeclarationsInfoProvider = blueprint.NewProvider[allAconfigDeclarationsInfo]()
+
type allAconfigReleaseDeclarationsSingleton struct {
intermediateBinaryProtoPath android.OutputPath
intermediateTextProtoPath android.OutputPath
}
+type ApiSurfaceContributorProperties struct {
+ Api_signature_files proptools.Configurable[[]string] `android:"arch_variant,path"`
+ Finalized_flags_file string `android:"arch_variant,path"`
+}
+
type allAconfigDeclarationsSingleton struct {
+ android.SingletonModuleBase
+
releaseMap map[string]allAconfigReleaseDeclarationsSingleton
+ properties ApiSurfaceContributorProperties
+
+ finalizedFlags android.OutputPath
}
func (this *allAconfigDeclarationsSingleton) sortedConfigNames() []string {
@@ -50,12 +72,80 @@
return names
}
-func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+func GenerateFinalizedFlagsForApiSurface(ctx android.ModuleContext, outputPath android.WritablePath,
+ parsedFlagsFile android.Path, apiSurface ApiSurfaceContributorProperties) {
+
+ apiSignatureFiles := android.Paths{}
+ for _, apiSignatureFile := range apiSurface.Api_signature_files.GetOrDefault(ctx, nil) {
+ if path := android.PathForModuleSrc(ctx, apiSignatureFile); path != nil {
+ apiSignatureFiles = append(apiSignatureFiles, path)
+ }
+ }
+ finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: RecordFinalizedFlagsRule,
+ Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile),
+ Output: outputPath,
+ Args: map[string]string{
+ "api_signature_files": android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "),
+ "finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(),
+ "parsed_flags_file": "--parsed-flags-file " + parsedFlagsFile.String(),
+ },
+ })
+}
+
+func GenerateExportedFlagCheck(ctx android.ModuleContext, outputPath android.WritablePath,
+ parsedFlagsFile android.Path, apiSurface ApiSurfaceContributorProperties) {
+
+ apiSignatureFiles := android.Paths{}
+ for _, apiSignatureFile := range apiSurface.Api_signature_files.GetOrDefault(ctx, nil) {
+ if path := android.PathForModuleSrc(ctx, apiSignatureFile); path != nil {
+ apiSignatureFiles = append(apiSignatureFiles, path)
+ }
+ }
+ finalizedFlagsFile := android.PathForModuleSrc(ctx, apiSurface.Finalized_flags_file)
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: ExportedFlagCheckRule,
+ Inputs: append(apiSignatureFiles, finalizedFlagsFile, parsedFlagsFile),
+ Output: outputPath,
+ Args: map[string]string{
+ "api_signature_files": android.JoinPathsWithPrefix(apiSignatureFiles, "--api-signature-file "),
+ "finalized_flags_file": "--finalized-flags-file " + finalizedFlagsFile.String(),
+ "parsed_flags_file": "--parsed-flags-file " + parsedFlagsFile.String(),
+ },
+ })
+}
+
+func (this *allAconfigDeclarationsSingleton) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ parsedFlagsFile := android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
+ this.finalizedFlags = android.PathForIntermediates(ctx, "finalized-flags.txt")
+ GenerateFinalizedFlagsForApiSurface(ctx, this.finalizedFlags, parsedFlagsFile, this.properties)
+
+ depsFiles := android.Paths{this.finalizedFlags}
+ if checkExportedFlag, ok := ctx.Config().GetBuildFlag("RELEASE_EXPORTED_FLAG_CHECK"); ok {
+ if checkExportedFlag == "true" {
+ invalidExportedFlags := android.PathForIntermediates(ctx, "invalid_exported_flags.txt")
+ GenerateExportedFlagCheck(ctx, invalidExportedFlags, parsedFlagsFile, this.properties)
+ depsFiles = append(depsFiles, invalidExportedFlags)
+ ctx.Phony("droidcore", invalidExportedFlags)
+ }
+ }
+
+ ctx.Phony("all_aconfig_declarations", depsFiles...)
+
+ android.SetProvider(ctx, allAconfigDeclarationsInfoProvider, allAconfigDeclarationsInfo{
+ parsedFlagsFile: parsedFlagsFile,
+ })
+}
+
+func (this *allAconfigDeclarationsSingleton) GenerateSingletonBuildActions(ctx android.SingletonContext) {
for _, rcName := range append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...) {
// Find all of the aconfig_declarations modules
var packages = make(map[string]int)
var cacheFiles android.Paths
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey)
if !ok {
return
@@ -65,15 +155,16 @@
})
var numOffendingPkg = 0
+ offendingPkgsMessage := ""
for pkg, cnt := range packages {
if cnt > 1 {
- fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
+ offendingPkgsMessage += fmt.Sprintf("%d aconfig_declarations found for package %s\n", cnt, pkg)
numOffendingPkg++
}
}
if numOffendingPkg > 0 {
- panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
+ panic("Only one aconfig_declarations allowed for each package.\n" + offendingPkgsMessage)
}
// Generate build action for aconfig (binary proto output)
@@ -105,9 +196,7 @@
})
ctx.Phony("all_aconfig_declarations_textproto", this.releaseMap[rcName].intermediateTextProtoPath)
}
-}
-func (this *allAconfigDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
for _, rcName := range this.sortedConfigNames() {
ctx.DistForGoal("droid", this.releaseMap[rcName].intermediateBinaryProtoPath)
for _, goal := range []string{"docs", "droid", "sdk"} {
@@ -115,4 +204,5 @@
ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateTextProtoPath, assembleFileName(rcName, "flags.textproto"))
}
}
+ ctx.DistForGoalWithFilename("sdk", this.finalizedFlags, "finalized-flags.txt")
}
diff --git a/aconfig/all_aconfig_declarations_extension.go b/aconfig/all_aconfig_declarations_extension.go
new file mode 100644
index 0000000..d5a4588
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_extension.go
@@ -0,0 +1,88 @@
+// Copyright 2025 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 aconfig
+
+import (
+ "android/soong/android"
+ "path"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func AllAconfigDeclarationsExtensionFactory() android.Module {
+ module := &allAconfigDeclarationsExtension{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+type allAconfigDeclarationsExtensionProperties struct {
+ // all_aconfig_declarations module that this module extends. Defaults to
+ // all_aconfig_declarations.
+ Base *string
+
+ // Directory where the dist artifact should be placed in.
+ Dist_dir *string
+
+ ApiSurfaceContributorProperties
+}
+
+type allAconfigDeclarationsExtension struct {
+ android.ModuleBase
+
+ properties allAconfigDeclarationsExtensionProperties
+
+ finalizedFlags android.ModuleOutPath
+}
+
+type allAconfigDeclarationsDependencyTagStruct struct {
+ blueprint.BaseDependencyTag
+}
+
+var allAconfigDeclarationsDependencyTag allAconfigDeclarationsDependencyTagStruct
+
+func (ext *allAconfigDeclarationsExtension) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), allAconfigDeclarationsDependencyTag, proptools.StringDefault(ext.properties.Base, "all_aconfig_declarations"))
+}
+
+func (ext *allAconfigDeclarationsExtension) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+ var parsedFlagsFile android.Path
+ ctx.VisitDirectDepsProxyWithTag(allAconfigDeclarationsDependencyTag, func(proxy android.ModuleProxy) {
+ if info, ok := android.OtherModuleProvider(ctx, proxy, allAconfigDeclarationsInfoProvider); ok {
+ parsedFlagsFile = info.parsedFlagsFile
+ } else {
+ ctx.PropertyErrorf("base", "base must provide allAconfigDeclarationsInfo")
+ }
+ })
+
+ ext.finalizedFlags = android.PathForModuleOut(ctx, "finalized-flags.txt")
+
+ GenerateFinalizedFlagsForApiSurface(ctx,
+ ext.finalizedFlags,
+ parsedFlagsFile,
+ ext.properties.ApiSurfaceContributorProperties,
+ )
+
+ ctx.Phony(ctx.ModuleName(), ext.finalizedFlags)
+
+ ctx.DistForGoalWithFilename("sdk", ext.finalizedFlags, path.Join(proptools.String(ext.properties.Dist_dir), "finalized-flags.txt"))
+
+ // This module must not set any provider or call `ctx.SetOutputFiles`!
+ // This module is only used to depend on the singleton module all_aconfig_declarations and
+ // generate the custom finalized-flags.txt file in dist builds, and should not be depended
+ // by other modules.
+}
diff --git a/aconfig/all_aconfig_declarations_extension_test.go b/aconfig/all_aconfig_declarations_extension_test.go
new file mode 100644
index 0000000..5bd99d0
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_extension_test.go
@@ -0,0 +1,50 @@
+// Copyright 2025 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 aconfig
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestAllAconfigDeclarationsExtension(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ android.FixtureMergeMockFs(
+ android.MockFS{
+ "a.txt": nil,
+ "flags.txt": nil,
+ },
+ ),
+ ).RunTestWithBp(t, `
+ all_aconfig_declarations {
+ name: "all_aconfig_declarations",
+ }
+
+ all_aconfig_declarations_extension {
+ name: "custom_aconfig_declarations",
+ base: "all_aconfig_declarations",
+ api_signature_files: [
+ "a.txt",
+ ],
+ finalized_flags_file: "flags.txt",
+ }
+ `)
+
+ finalizedFlags := result.ModuleForTests(t, "custom_aconfig_declarations", "").Output("finalized-flags.txt")
+ android.AssertStringContainsEquals(t, "must depend on all_aconfig_declarations", strings.Join(finalizedFlags.Inputs.Strings(), " "), "all_aconfig_declarations.pb", true)
+}
diff --git a/aconfig/all_aconfig_declarations_test.go b/aconfig/all_aconfig_declarations_test.go
deleted file mode 100644
index 0b2021e..0000000
--- a/aconfig/all_aconfig_declarations_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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 aconfig
-
-import (
- "testing"
-
- "android/soong/android"
-)
-
-func TestTwoAconfigDeclarationsPerPackage(t *testing.T) {
- bp := `
- aconfig_declarations {
- name: "module_name.foo",
- package: "com.example.package",
- container: "com.android.foo",
- srcs: [
- "foo.aconfig",
- ],
- }
-
- aconfig_declarations {
- name: "module_name.bar",
- package: "com.example.package",
- container: "com.android.foo",
- srcs: [
- "bar.aconfig",
- ],
- }
- `
- errMsg := "Only one aconfig_declarations allowed for each package."
- android.GroupFixturePreparers(
- PrepareForTestWithAconfigBuildComponents).
- ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(errMsg)).
- RunTestWithBp(t, bp)
-}
diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go
index 3b40755..3a06e72 100644
--- a/aconfig/build_flags/build_flags_singleton.go
+++ b/aconfig/build_flags/build_flags_singleton.go
@@ -15,6 +15,8 @@
package build_flags
import (
+ "fmt"
+
"android/soong/android"
)
@@ -41,7 +43,7 @@
var flagsFiles android.Paths
// Find all of the release_config_contribution modules
var contributionDirs android.Paths
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
decl, ok := android.OtherModuleProvider(ctx, module, BuildFlagDeclarationsProviderKey)
if ok {
flagsFiles = append(flagsFiles, decl.IntermediateCacheOutputPath)
@@ -110,9 +112,7 @@
this.configsBinaryProtoPath,
this.configsTextProtoPath,
)
-}
-func (this *allBuildFlagDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.DistForGoal("droid", this.flagsBinaryProtoPath)
for _, goal := range []string{"docs", "droid", "sdk", "release_config_metadata"} {
ctx.DistForGoalWithFilename(goal, this.flagsBinaryProtoPath, "build_flags/all_flags.pb")
@@ -120,4 +120,26 @@
ctx.DistForGoalWithFilename(goal, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb")
ctx.DistForGoalWithFilename(goal, this.configsTextProtoPath, "build_flags/all_release_config_contributions.textproto")
}
+
+ if ctx.Config().HasDeviceProduct() {
+ flagsDir := android.PathForOutput(ctx, "release-config")
+ baseAllRelease := fmt.Sprintf("all_release_configs-%s", ctx.Config().DeviceProduct())
+
+ distAllReleaseConfigsArtifact := func(ext string) {
+ ctx.DistForGoalWithFilename(
+ "droid",
+ flagsDir.Join(ctx, fmt.Sprintf("%s.%s", baseAllRelease, ext)),
+ fmt.Sprintf("build_flags/all_release_configs.%s", ext),
+ )
+ }
+
+ distAllReleaseConfigsArtifact("pb")
+ distAllReleaseConfigsArtifact("textproto")
+ distAllReleaseConfigsArtifact("json")
+ ctx.DistForGoalWithFilename(
+ "droid",
+ flagsDir.Join(ctx, fmt.Sprintf("inheritance_graph-%s.dot", ctx.Config().DeviceProduct())),
+ fmt.Sprintf("build_flags/inheritance_graph-%s.dot", ctx.Config().DeviceProduct()),
+ )
+ }
}
diff --git a/aconfig/codegen/aconfig_declarations_group_test.go b/aconfig/codegen/aconfig_declarations_group_test.go
index ef954ce..c822ef8 100644
--- a/aconfig/codegen/aconfig_declarations_group_test.go
+++ b/aconfig/codegen/aconfig_declarations_group_test.go
@@ -74,7 +74,7 @@
// Check if srcjar files are correctly passed to the reverse dependency of
// aconfig_declarations_group module
- bazModule := result.ModuleForTests("baz", "android_common")
+ bazModule := result.ModuleForTests(t, "baz", "android_common")
bazJavacSrcjars := bazModule.Rule("javac").Args["srcJars"]
errorMessage := "baz javac argument expected to contain srcjar provided by aconfig_declrations_group"
android.AssertStringDoesContain(t, errorMessage, bazJavacSrcjars, "foo-java.srcjar")
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index 8c4bfe6..ce37456 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -22,7 +22,6 @@
"github.com/google/blueprint/proptools"
"fmt"
- "strconv"
"strings"
)
@@ -32,8 +31,6 @@
var ccDeclarationsTag = ccDeclarationsTagType{}
-const baseLibDep = "server_configurable_flags"
-
const libBaseDep = "libbase"
const libLogDep = "liblog"
const libAconfigStorageReadApiCcDep = "libaconfig_storage_read_api_cc"
@@ -86,15 +83,11 @@
// Add a dependency for the aconfig flags base library if it is not forced read only
if mode != "force-read-only" {
- deps.SharedLibs = append(deps.SharedLibs, baseLibDep)
-
+ deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep)
+ deps.SharedLibs = append(deps.SharedLibs, libBaseDep)
+ deps.SharedLibs = append(deps.SharedLibs, libLogDep)
}
- // TODO: after storage migration is over, don't add these in force-read-only-mode.
- deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep)
- deps.SharedLibs = append(deps.SharedLibs, libBaseDep)
- deps.SharedLibs = append(deps.SharedLibs, libLogDep)
-
// TODO: It'd be really nice if we could reexport this library and not make everyone do it.
return deps
@@ -104,7 +97,7 @@
result := cc.GeneratedSource{}
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
- declarationsModules := ctx.GetDirectDepsWithTag(ccDeclarationsTag)
+ declarationsModules := ctx.GetDirectDepsProxyWithTag(ccDeclarationsTag)
if len(declarationsModules) != 1 {
panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
}
@@ -134,7 +127,7 @@
func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContext, flags cc.Flags, deps cc.PathDeps) {
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
- declarationsModules := ctx.GetDirectDepsWithTag(ccDeclarationsTag)
+ declarationsModules := ctx.GetDirectDepsProxyWithTag(ccDeclarationsTag)
if len(declarationsModules) != 1 {
panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
}
@@ -156,7 +149,6 @@
Args: map[string]string{
"gendir": this.generatedDir.String(),
"mode": mode,
- "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
},
})
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
index c308ed4..5cb3f8b 100644
--- a/aconfig/codegen/cc_aconfig_library_test.go
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -81,7 +81,7 @@
}
`, bpMode))
- module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared")
+ module := result.ModuleForTests(t, "my_cc_aconfig_library", "android_arm64_armv8-a_shared")
rule := module.Rule("cc_aconfig_library")
android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
}
@@ -209,7 +209,7 @@
cc.PrepareForTestWithCcDefaultModules).
ExtendWithErrorHandler(android.FixtureExpectsNoErrors).RunTestWithBp(t, bp)
- module := result.ModuleForTests("my_cc_library", "android_vendor_arm64_armv8-a_shared").Module()
+ module := result.ModuleForTests(t, "my_cc_library", "android_vendor_arm64_armv8-a_shared").Module()
entry := android.AndroidMkInfoForTest(t, result.TestContext, module).PrimaryInfo
@@ -254,13 +254,13 @@
}
`))
- module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared").Module()
- dependOnBaseLib := false
+ module := result.ModuleForTests(t, "my_cc_aconfig_library", "android_arm64_armv8-a_shared").Module()
+ dependOnReadLib := false
result.VisitDirectDeps(module, func(dep blueprint.Module) {
- if dep.Name() == baseLibDep {
- dependOnBaseLib = true
+ if dep.Name() == libAconfigStorageReadApiCcDep {
+ dependOnReadLib = true
}
})
- android.AssertBoolEquals(t, "should not have dependency on server_configuriable_flags",
- dependOnBaseLib, false)
+ android.AssertBoolEquals(t, "should not have dependency on libaconfig_storage_read_api_cc",
+ dependOnReadLib, false)
}
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index ed0b3ed..325e367 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -26,6 +26,7 @@
// For java_aconfig_library: Generate java library
javaRule = pctx.AndroidStaticRule("java_aconfig_library",
blueprint.RuleParams{
+ // LINT.IfChange
Command: `rm -rf ${out}.tmp` +
` && mkdir -p ${out}.tmp` +
` && ${aconfig} create-java-lib` +
@@ -33,14 +34,17 @@
` --cache ${in}` +
` --out ${out}.tmp` +
` --allow-instrumentation ${debug}` +
+ ` --new-exported ${new_exported}` +
+ ` --check-api-level ${check_api_level}` +
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
` && rm -rf ${out}.tmp`,
+ // LINT.ThenChange(/aconfig/init.go)
CommandDeps: []string{
"$aconfig",
"$soong_zip",
},
Restat: true,
- }, "mode", "debug")
+ }, "mode", "debug", "new_exported", "check_api_level")
// For cc_aconfig_library: Generate C++ library
cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
@@ -50,12 +54,11 @@
` && ${aconfig} create-cpp-lib` +
` --mode ${mode}` +
` --cache ${in}` +
- ` --out ${gendir}` +
- ` --allow-instrumentation ${debug}`,
+ ` --out ${gendir}`,
CommandDeps: []string{
"$aconfig",
},
- }, "gendir", "mode", "debug")
+ }, "gendir", "mode")
// For rust_aconfig_library: Generate Rust library
rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
@@ -65,12 +68,11 @@
` && ${aconfig} create-rust-lib` +
` --mode ${mode}` +
` --cache ${in}` +
- ` --allow-instrumentation ${debug}` +
` --out ${gendir}`,
CommandDeps: []string{
"$aconfig",
},
- }, "gendir", "mode", "debug")
+ }, "gendir", "mode")
)
func init() {
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index 9f399bf..7b9da8e 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -98,14 +98,24 @@
ctx.PropertyErrorf("mode", "exported mode requires its aconfig_declaration has exportable prop true")
}
+ var newExported bool
+ if useNewExported, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_NEW_EXPORTED"); ok {
+ // The build flag (RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY) is the negation of the aconfig flag
+ // (allow-read-write) for historical reasons.
+ // Bool build flags are always "" for false, and generally "true" for true.
+ newExported = useNewExported == "true"
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: javaRule,
Input: declarations.IntermediateCacheOutputPath,
Output: srcJarPath,
Description: "aconfig.srcjar",
Args: map[string]string{
- "mode": mode,
- "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
+ "mode": mode,
+ "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
+ "new_exported": strconv.FormatBool(newExported),
+ "check_api_level": strconv.FormatBool(ctx.Config().ReleaseAconfigCheckApiLevel()),
},
})
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index d8372f3..b9455f7 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -57,7 +57,7 @@
}
`)
- module := result.ModuleForTests("my_module", "android_common").Module()
+ module := result.ModuleForTests(t, "my_module", "android_common").Module()
entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
@@ -189,7 +189,7 @@
}
`, bpMode))
- module := result.ModuleForTests("my_java_aconfig_library", "android_common")
+ module := result.ModuleForTests(t, "my_java_aconfig_library", "android_common")
rule := module.Rule("java_aconfig_library")
android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
}
@@ -260,7 +260,7 @@
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package.bar",
- container: "vendor",
+ container: "system_ext",
srcs: ["bar.aconfig"],
}
@@ -282,7 +282,7 @@
}
`)
- module := result.ModuleForTests("my_module", "android_common").Module()
+ module := result.ModuleForTests(t, "my_module", "android_common").Module()
entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/intermediate.pb")
diff --git a/aconfig/codegen/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
index 4b896c3..53818c2 100644
--- a/aconfig/codegen/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -2,7 +2,6 @@
import (
"fmt"
- "strconv"
"android/soong/android"
"android/soong/rust"
@@ -83,7 +82,6 @@
Args: map[string]string{
"gendir": generatedDir.String(),
"mode": mode,
- "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
},
})
a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
@@ -102,7 +100,6 @@
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")
diff --git a/aconfig/codegen/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go
index 523b464..6701021 100644
--- a/aconfig/codegen/rust_aconfig_library_test.go
+++ b/aconfig/codegen/rust_aconfig_library_test.go
@@ -57,13 +57,13 @@
}
`))
- sourceVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
+ sourceVariant := result.ModuleForTests(t, "libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
rule := sourceVariant.Rule("rust_aconfig_library")
android.AssertStringEquals(t, "rule must contain production mode", rule.Args["mode"], "production")
- dylibVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
- rlibRlibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
- rlibDylibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")
+ dylibVariant := result.ModuleForTests(t, "libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
+ rlibRlibStdVariant := result.ModuleForTests(t, "libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
+ rlibDylibStdVariant := result.ModuleForTests(t, "libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")
variants := []android.TestingModule{
dylibVariant,
@@ -143,7 +143,7 @@
}
`, bpMode))
- module := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
+ module := result.ModuleForTests(t, "libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
rule := module.Rule("rust_aconfig_library")
android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
}
diff --git a/aconfig/exported_java_aconfig_library.go b/aconfig/exported_java_aconfig_library.go
index a64cac8..ffb2a0c 100644
--- a/aconfig/exported_java_aconfig_library.go
+++ b/aconfig/exported_java_aconfig_library.go
@@ -15,6 +15,8 @@
package aconfig
import (
+ "strconv"
+
"android/soong/android"
)
@@ -29,7 +31,7 @@
func (this *exportedJavaDeclarationsLibrarySingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Find all of the aconfig_declarations modules
var cacheFiles android.Paths
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
if !ok {
return
@@ -37,6 +39,16 @@
cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath)
})
+ var newExported bool
+ if useNewExported, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_NEW_EXPORTED"); ok {
+ newExported = useNewExported == "true"
+ }
+
+ var newStorage bool
+ if useNewStorage, ok := ctx.Config().GetBuildFlag("RELEASE_READ_FROM_NEW_STORAGE"); ok {
+ newStorage = useNewStorage == "true"
+ }
+
// Generate build action for aconfig
this.intermediatePath = android.PathForIntermediates(ctx, "exported_java_aconfig_library.jar")
ctx.Build(pctx, android.BuildParams{
@@ -45,12 +57,12 @@
Output: this.intermediatePath,
Description: "exported_java_aconfig_library",
Args: map[string]string{
- "cache_files": android.JoinPathsWithPrefix(cacheFiles, " "),
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, " "),
+ "use_new_storage": strconv.FormatBool(newStorage),
+ "use_new_exported": strconv.FormatBool(newExported),
+ "check_api_level": strconv.FormatBool(ctx.Config().ReleaseAconfigCheckApiLevel()),
},
})
ctx.Phony("exported_java_aconfig_library", this.intermediatePath)
-}
-
-func (this *exportedJavaDeclarationsLibrarySingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.DistForGoalWithFilename("sdk", this.intermediatePath, "android-flags.jar")
}
diff --git a/aconfig/init.go b/aconfig/init.go
index 621d619..d8d5470 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -70,14 +70,28 @@
"${aconfig}",
},
}, "cache_files")
+ RecordFinalizedFlagsRule = pctx.AndroidStaticRule("RecordFinalizedFlagsRule",
+ blueprint.RuleParams{
+ Command: `${record-finalized-flags} ${parsed_flags_file} ${finalized_flags_file} ${api_signature_files} > ${out}`,
+ CommandDeps: []string{
+ "${record-finalized-flags}",
+ },
+ }, "api_signature_files", "finalized_flags_file", "parsed_flags_file")
+ ExportedFlagCheckRule = pctx.AndroidStaticRule("ExportedFlagCheckRule",
+ blueprint.RuleParams{
+ Command: `${exported-flag-check} ${parsed_flags_file} ${finalized_flags_file} ${api_signature_files} > ${out}`,
+ CommandDeps: []string{
+ "${exported-flag-check}",
+ },
+ }, "api_signature_files", "finalized_flags_file", "parsed_flags_file")
CreateStorageRule = pctx.AndroidStaticRule("aconfig_create_storage",
blueprint.RuleParams{
- Command: `${aconfig} create-storage --container ${container} --file ${file_type} --out ${out} ${cache_files}`,
+ Command: `${aconfig} create-storage --container ${container} --file ${file_type} --out ${out} ${cache_files} --version ${version}`,
CommandDeps: []string{
"${aconfig}",
},
- }, "container", "file_type", "cache_files")
+ }, "container", "file_type", "cache_files", "version")
// For exported_java_aconfig_library: Generate a JAR from all
// java_aconfig_libraries to be consumed by apps built outside the
@@ -88,31 +102,43 @@
// exported flags (only). Finally collect all generated code
// into the ${out} JAR file.
blueprint.RuleParams{
+ // LINT.IfChange
Command: `rm -rf ${out}.tmp` +
`&& for cache in ${cache_files}; do ` +
` if [ -n "$$(${aconfig} dump-cache --dedup --cache $$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
- ` ${aconfig} create-java-lib --cache $$cache --mode=exported --out ${out}.tmp; ` +
+ ` ${aconfig} create-java-lib` +
+ ` --cache $$cache` +
+ ` --mode=exported` +
+ ` --allow-instrumentation ${use_new_storage}` +
+ ` --new-exported ${use_new_exported}` +
+ ` --single-exported-file true` +
+ ` --check-api-level ${check_api_level}` +
+ ` --out ${out}.tmp; ` +
` fi ` +
`done` +
`&& $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
`&& rm -rf ${out}.tmp`,
+ // LINT.ThenChange(/aconfig/codegen/init.go)
CommandDeps: []string{
"$aconfig",
"$soong_zip",
},
- }, "cache_files")
+ }, "cache_files", "use_new_storage", "use_new_exported", "check_api_level")
)
func init() {
RegisterBuildComponents(android.InitRegistrationContext)
pctx.HostBinToolVariable("aconfig", "aconfig")
pctx.HostBinToolVariable("soong_zip", "soong_zip")
+ pctx.HostBinToolVariable("record-finalized-flags", "record-finalized-flags")
+ pctx.HostBinToolVariable("exported-flag-check", "exported-flag-check")
}
func RegisterBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
ctx.RegisterModuleType("aconfig_values", ValuesFactory)
ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
- ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
+ ctx.RegisterSingletonModuleType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
ctx.RegisterParallelSingletonType("exported_java_aconfig_library", ExportedJavaDeclarationsLibraryFactory)
+ ctx.RegisterModuleType("all_aconfig_declarations_extension", AllAconfigDeclarationsExtensionFactory)
}
diff --git a/aidl_library/aidl_library_test.go b/aidl_library/aidl_library_test.go
index 1660456..63a08b9 100644
--- a/aidl_library/aidl_library_test.go
+++ b/aidl_library/aidl_library_test.go
@@ -46,7 +46,7 @@
}.AddToFixture(),
).RunTest(t).TestContext
- foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+ foo := ctx.ModuleForTests(t, "foo", "").Module().(*AidlLibrary)
actualInfo, _ := android.OtherModuleProvider(ctx, foo, AidlLibraryProvider)
android.AssertArrayString(
@@ -95,7 +95,7 @@
}.AddToFixture(),
).RunTest(t).TestContext
- foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+ foo := ctx.ModuleForTests(t, "foo", "").Module().(*AidlLibrary)
actualInfo, _ := android.OtherModuleProvider(ctx, foo, AidlLibraryProvider)
android.AssertArrayString(
diff --git a/android/Android.bp b/android/Android.bp
index dfea8f9..97d634f 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -11,6 +11,8 @@
"blueprint-depset",
"blueprint-gobtools",
"blueprint-metrics",
+ "blueprint-pool",
+ "blueprint-syncmap",
"sbox_proto",
"soong",
"soong-android_team_proto",
@@ -79,8 +81,10 @@
"namespace.go",
"neverallow.go",
"ninja_deps.go",
+ "nothing.go",
"notices.go",
"onceper.go",
+ "otatools_package_cert_zip.go",
"override_module.go",
"package.go",
"package_ctx.go",
@@ -92,10 +96,14 @@
"prebuilt.go",
"prebuilt_build_tool.go",
"product_config.go",
+ "product_packages_file.go",
"proto.go",
"provider.go",
+ "provider_keys.go",
"raw_files.go",
+ "recovery_build_prop.go",
"register.go",
+ "removed_package.go",
"rule_builder.go",
"sandbox.go",
"sbom.go",
@@ -107,8 +115,10 @@
"soong_config_modules.go",
"team.go",
"test_asserts.go",
+ "test_mapping_zip.go",
"test_suites.go",
"testing.go",
+ "transition.go",
"util.go",
"variable.go",
"vendor_api_levels.go",
@@ -120,7 +130,6 @@
"all_teams_test.go",
"android_test.go",
"androidmk_test.go",
- "apex_test.go",
"arch_test.go",
"blueprint_e2e_test.go",
"build_prop_test.go",
@@ -136,6 +145,7 @@
"license_kind_test.go",
"license_test.go",
"licenses_test.go",
+ "makevars_test.go",
"module_test.go",
"mutator_test.go",
"namespace_test.go",
@@ -154,6 +164,7 @@
"singleton_module_test.go",
"soong_config_modules_test.go",
"test_suites_test.go",
+ "transition_test.go",
"util_test.go",
"variable_test.go",
"vintf_fragment_test.go",
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index 210a656..bb73f0b 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -92,11 +92,11 @@
if asError {
ctx.ModuleErrorf(msg)
} else {
- fmt.Printf("WARNING: " + msg)
+ fmt.Print("WARNING: " + msg)
}
} else {
if !asError {
- fmt.Printf("PASSED: " + msg)
+ fmt.Print("PASSED: " + msg)
}
}
}
@@ -136,7 +136,7 @@
AconfigFiles: mergedAconfigFiles,
ModeInfos: mergedModeInfos,
})
- ctx.setAconfigPaths(getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles))
+ ctx.setAconfigPaths(getAconfigFilePaths(getContainer(ctx.Module()), mergedAconfigFiles))
}
}
@@ -147,7 +147,8 @@
return
}
data.Extra = append(data.Extra, func(w io.Writer, outputFile Path) {
- AndroidMkEmitAssignList(w, "LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles).Strings())
+ AndroidMkEmitAssignList(w, "LOCAL_ACONFIG_FILES", getAconfigFilePaths(
+ getContainerUsingProviders(ctx, mod), info.AconfigFiles).Strings())
})
// If there is a Custom writer, it needs to support this provider.
if data.Custom != nil {
@@ -179,24 +180,29 @@
// All of the files in the module potentially depend on the aconfig flag values.
for idx, _ := range *entries {
(*entries)[idx].ExtraEntries = append((*entries)[idx].ExtraEntries,
- func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
- entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles))
+ func(_ AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
+ entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(
+ getContainerUsingProviders(ctx, mod), info.AconfigFiles))
},
)
}
}
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
func aconfigUpdateAndroidMkInfos(ctx fillInEntriesContext, mod Module, infos *AndroidMkProviderInfo) {
info, ok := OtherModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
if !ok || len(info.AconfigFiles) == 0 {
return
}
// All of the files in the module potentially depend on the aconfig flag values.
- infos.PrimaryInfo.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles))
+ infos.PrimaryInfo.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(
+ getContainerUsingProviders(ctx, mod), info.AconfigFiles))
if len(infos.ExtraInfo) > 0 {
for _, ei := range (*infos).ExtraInfo {
- ei.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles))
+ ei.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(
+ getContainerUsingProviders(ctx, mod), info.AconfigFiles))
}
}
}
@@ -224,19 +230,37 @@
return Paths{output}
}
-func getAconfigFilePaths(m *ModuleBase, aconfigFiles map[string]Paths) (paths Paths) {
- // TODO(b/311155208): The default container here should be system.
+func getContainer(m Module) string {
container := "system"
-
- if m.SocSpecific() {
+ base := m.base()
+ if base.SocSpecific() {
container = "vendor"
- } else if m.ProductSpecific() {
+ } else if base.ProductSpecific() {
container = "product"
- } else if m.SystemExtSpecific() {
- // system_ext and system partitions should be treated as one container
- container = "system"
+ } else if base.SystemExtSpecific() {
+ container = "system_ext"
}
+ return container
+}
+
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
+func getContainerUsingProviders(ctx OtherModuleProviderContext, m Module) string {
+ container := "system"
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider)
+ if commonInfo.Vendor || commonInfo.Proprietary || commonInfo.SocSpecific {
+ container = "vendor"
+ } else if commonInfo.ProductSpecific {
+ container = "product"
+ } else if commonInfo.SystemExtSpecific {
+ container = "system_ext"
+ }
+
+ return container
+}
+
+func getAconfigFilePaths(container string, aconfigFiles map[string]Paths) (paths Paths) {
paths = append(paths, aconfigFiles[container]...)
if container == "system" {
// TODO(b/311155208): Once the default container is system, we can drop this.
diff --git a/android/all_teams.go b/android/all_teams.go
index 01be396..18a050f 100644
--- a/android/all_teams.go
+++ b/android/all_teams.go
@@ -78,19 +78,19 @@
t.teams = make(map[string]teamProperties)
t.teams_for_mods = make(map[string]moduleTeamAndTestInfo)
- ctx.VisitAllModules(func(module Module) {
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
bpFile := ctx.BlueprintFile(module)
// Package Modules and Team Modules are stored in a map so we can look them up by name for
// modules without a team.
- if pack, ok := module.(*packageModule); ok {
+ if pack, ok := OtherModuleProvider(ctx, module, PackageInfoProvider); ok {
// Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in t context.
pkgKey := bpFile
- t.packages[pkgKey] = pack.properties
+ t.packages[pkgKey] = pack.Properties
return
}
- if team, ok := module.(*teamModule); ok {
- t.teams[team.Name()] = team.properties
+ if team, ok := OtherModuleProvider(ctx, module, TeamInfoProvider); ok {
+ t.teams[module.Name()] = team.Properties
return
}
@@ -116,7 +116,7 @@
testOnly: testModInfo.TestOnly,
topLevelTestTarget: testModInfo.TopLevelTarget,
kind: ctx.ModuleType(module),
- teamName: module.base().Team(),
+ teamName: OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).Team,
}
t.teams_for_mods[module.Name()] = entry
@@ -134,9 +134,6 @@
WriteFileRuleVerbatim(ctx, t.outputPath, string(data))
ctx.Phony("all_teams", t.outputPath)
-}
-
-func (t *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
ctx.DistForGoal("all_teams", t.outputPath)
}
diff --git a/android/all_teams_test.go b/android/all_teams_test.go
index fa8c048..3b200f6 100644
--- a/android/all_teams_test.go
+++ b/android/all_teams_test.go
@@ -131,7 +131,7 @@
func getTeamProtoOutput(t *testing.T, ctx *TestResult) *team_proto.AllTeams {
teams := new(team_proto.AllTeams)
- config := ctx.SingletonForTests("all_teams")
+ config := ctx.SingletonForTests(t, "all_teams")
allOutputs := config.AllOutputs()
protoPath := allOutputs[0]
diff --git a/android/android_info.go b/android/android_info.go
index a8d3d4e..9a68d10 100644
--- a/android/android_info.go
+++ b/android/android_info.go
@@ -79,6 +79,7 @@
})
ctx.SetOutputFiles(Paths{androidInfoProp}, "")
+ ctx.SetOutputFiles(Paths{androidInfoTxt}, ".txt")
}
// android_info module generate a file named android-info.txt that contains various information
@@ -86,6 +87,6 @@
func AndroidInfoFactory() Module {
module := &androidInfoModule{}
module.AddProperties(&module.properties)
- InitAndroidModule(module)
+ InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
return module
}
diff --git a/android/androidmk.go b/android/androidmk.go
index 590cce3..e328359 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -64,7 +64,6 @@
type AndroidMkData struct {
Class string
SubName string
- DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
@@ -79,6 +78,12 @@
Entries AndroidMkEntries
}
+type AndroidMkDataInfo struct {
+ Class string
+}
+
+var AndroidMkDataInfoProvider = blueprint.NewProvider[AndroidMkDataInfo]()
+
type AndroidMkExtraFunc func(w io.Writer, outputFile Path)
// Interface for modules to declare their Android.mk outputs. Note that every module needs to
@@ -108,8 +113,6 @@
SubName string
// If set, this value overrides the base module name. SubName is still appended.
OverrideName string
- // Dist files to output
- DistFiles TaggedDistFiles
// The output file for Kati to process and/or install. If absent, the module is skipped.
OutputFile OptionalPath
// If true, the module is skipped and does not appear on the final Android-<product name>.mk
@@ -166,7 +169,7 @@
type androidMkExtraEntriesContext struct {
ctx fillInEntriesContext
- mod blueprint.Module
+ mod Module
}
func (a *androidMkExtraEntriesContext) Provider(provider blueprint.AnyProviderKey) (any, bool) {
@@ -333,36 +336,34 @@
dest string
}
-// Compute the contributions that the module makes to the dist.
-func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContributions {
- amod := mod.(Module).base()
+func (d *distCopy) String() string {
+ if len(d.dest) == 0 {
+ return d.from.String()
+ }
+ return fmt.Sprintf("%s:%s", d.from.String(), d.dest)
+}
+
+type distCopies []distCopy
+
+func (d *distCopies) Strings() (ret []string) {
+ if d == nil {
+ return
+ }
+ for _, dist := range *d {
+ ret = append(ret, dist.String())
+ }
+ return
+}
+
+// This gets the dist contributuions from the given module that were specified in the Android.bp
+// file using the dist: property. It does not include contribututions that the module's
+// implementation may have defined with ctx.DistForGoals(), for that, see DistProvider.
+func getDistContributions(ctx ConfigAndOtherModuleProviderContext, mod Module) *distContributions {
+ amod := mod.base()
name := amod.BaseModuleName()
- // Collate the set of associated tag/paths available for copying to the dist.
- // Start with an empty (nil) set.
- var availableTaggedDists TaggedDistFiles
-
- // Then merge in any that are provided explicitly by the module.
- if a.DistFiles != nil {
- // Merge the DistFiles into the set.
- availableTaggedDists = availableTaggedDists.merge(a.DistFiles)
- }
-
- // If no paths have been provided for the DefaultDistTag and the output file is
- // valid then add that as the default dist path.
- if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() {
- availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path())
- }
-
- info := OtherModuleProviderOrDefault(a.entryContext, mod, InstallFilesProvider)
- // If the distFiles created by GenerateTaggedDistFiles contains paths for the
- // DefaultDistTag then that takes priority so delete any existing paths.
- if _, ok := info.DistFiles[DefaultDistTag]; ok {
- delete(availableTaggedDists, DefaultDistTag)
- }
-
- // Finally, merge the distFiles created by GenerateTaggedDistFiles.
- availableTaggedDists = availableTaggedDists.merge(info.DistFiles)
+ info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
+ availableTaggedDists := info.DistFiles
if len(availableTaggedDists) == 0 {
// Nothing dist-able for this module.
@@ -372,7 +373,7 @@
// Collate the contributions this module makes to the dist.
distContributions := &distContributions{}
- if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
+ if !exemptFromRequiredApplicableLicensesProperty(mod) {
distContributions.licenseMetadataFile = info.LicenseMetadataFile
}
@@ -434,13 +435,18 @@
suffix = *dist.Suffix
}
- productString := ""
- if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
- productString = fmt.Sprintf("_%s", a.entryContext.Config().DeviceProduct())
+ prependProductString := ""
+ if proptools.Bool(dist.Prepend_artifact_with_product) {
+ prependProductString = fmt.Sprintf("%s-", ctx.Config().DeviceProduct())
}
- if suffix != "" || productString != "" {
- dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
+ appendProductString := ""
+ if proptools.Bool(dist.Append_artifact_with_product) {
+ appendProductString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct())
+ }
+
+ if suffix != "" || appendProductString != "" || prependProductString != "" {
+ dest = prependProductString + strings.TrimSuffix(dest, ext) + suffix + appendProductString + ext
}
if dist.Dir != nil {
@@ -483,8 +489,8 @@
// Compute the list of Make strings to declare phony goals and dist-for-goals
// calls from the module's dist and dists properties.
-func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
- distContributions := a.getDistContributions(mod)
+func (a *AndroidMkEntries) GetDistForGoals(mod Module) []string {
+ distContributions := getDistContributions(a.entryContext, mod)
if distContributions == nil {
return nil
}
@@ -504,12 +510,14 @@
HasMutatorFinished(mutatorName string) bool
}
-func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
+func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod Module) {
a.entryContext = ctx
a.EntryMap = make(map[string][]string)
- amod := mod.(Module)
- base := amod.base()
+ base := mod.base()
name := base.BaseModuleName()
+ if bmn, ok := mod.(baseModuleName); ok {
+ name = bmn.BaseModuleName()
+ }
if a.OverrideName != "" {
name = a.OverrideName
}
@@ -517,10 +525,10 @@
if a.Include == "" {
a.Include = "$(BUILD_PREBUILT)"
}
- a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...)
- a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...)
- a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
- a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
+ a.Required = append(a.Required, mod.RequiredModuleNames(ctx)...)
+ a.Required = append(a.Required, mod.VintfFragmentModuleNames(ctx)...)
+ a.Host_required = append(a.Host_required, mod.HostRequiredModuleNames()...)
+ a.Target_required = append(a.Target_required, mod.TargetRequiredModuleNames()...)
for _, distString := range a.GetDistForGoals(mod) {
fmt.Fprintln(&a.header, distString)
@@ -528,6 +536,14 @@
fmt.Fprintf(&a.header, "\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s\n", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))
+ // Add the TestSuites from the provider to LOCAL_SOONG_PROVIDER_TEST_SUITES.
+ // LOCAL_SOONG_PROVIDER_TEST_SUITES will be compared against LOCAL_COMPATIBILITY_SUITES
+ // in make and enforced they're the same, to ensure we've successfully translated all
+ // LOCAL_COMPATIBILITY_SUITES usages to the provider.
+ if testSuiteInfo, ok := OtherModuleProvider(ctx, mod, TestSuiteInfoProvider); ok {
+ a.AddStrings("LOCAL_SOONG_PROVIDER_TEST_SUITES", testSuiteInfo.TestSuites...)
+ }
+
// Collect make variable assignment entries.
a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
a.SetString("LOCAL_MODULE", name+a.SubName)
@@ -536,7 +552,7 @@
a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
- a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
+ a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(mod))
// If the install rule was generated by Soong tell Make about it.
info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
@@ -700,24 +716,29 @@
type androidMkSingleton struct{}
-func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
- // Skip if Soong wasn't invoked from Make.
- if !ctx.Config().KatiEnabled() {
- return
- }
+func allModulesSorted(ctx SingletonContext) []Module {
+ var allModules []Module
- var androidMkModulesList []blueprint.Module
-
- ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
- androidMkModulesList = append(androidMkModulesList, module)
+ ctx.VisitAllModules(func(module Module) {
+ allModules = append(allModules, module)
})
// Sort the module list by the module names to eliminate random churns, which may erroneously
// invoke additional build processes.
- sort.SliceStable(androidMkModulesList, func(i, j int) bool {
- return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
+ sort.SliceStable(allModules, func(i, j int) bool {
+ return ctx.ModuleName(allModules[i]) < ctx.ModuleName(allModules[j])
})
+ return allModules
+}
+
+func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // If running in soong-only mode, more limited version of this singleton is run as
+ // soong only androidmk singleton
+ if !ctx.Config().KatiEnabled() {
+ return
+ }
+
transMk := PathForOutput(ctx, "Android"+String(ctx.Config().productVariables.Make_suffix)+".mk")
if ctx.Failed() {
return
@@ -725,7 +746,7 @@
moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json")
- err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList)
+ err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, allModulesSorted(ctx))
if err != nil {
ctx.Errorf(err.Error())
}
@@ -736,7 +757,202 @@
})
}
-func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []blueprint.Module) error {
+type soongOnlyAndroidMkSingleton struct {
+ Singleton
+}
+
+func soongOnlyAndroidMkSingletonFactory() Singleton {
+ return &soongOnlyAndroidMkSingleton{}
+}
+
+func (so *soongOnlyAndroidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+ if !ctx.Config().KatiEnabled() {
+ so.soongOnlyBuildActions(ctx, allModulesSorted(ctx))
+ }
+}
+
+// In soong-only mode, we don't do most of the androidmk stuff. But disted files are still largely
+// defined through the androidmk mechanisms, so this function is an alternate implementation of
+// the androidmk singleton that just focuses on getting the dist contributions
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
+func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []Module) {
+ allDistContributions, moduleInfoJSONs := getSoongOnlyDataFromMods(ctx, mods)
+
+ singletonDists := getSingletonDists(ctx.Config())
+ singletonDists.lock.Lock()
+ if contribution := distsToDistContributions(singletonDists.dists); contribution != nil {
+ allDistContributions = append(allDistContributions, *contribution)
+ }
+ singletonDists.lock.Unlock()
+
+ // Build module-info.json. Only in builds with HasDeviceProduct(), as we need a named
+ // device to have a TARGET_OUT folder.
+ if ctx.Config().HasDeviceProduct() {
+ preMergePath := PathForOutput(ctx, "module_info_pre_merging.json")
+ moduleInfoJSONPath := pathForInstall(ctx, Android, X86_64, "", "module-info.json")
+ if err := writeModuleInfoJSON(ctx, moduleInfoJSONs, preMergePath); err != nil {
+ ctx.Errorf("%s", err)
+ }
+ builder := NewRuleBuilder(pctx, ctx)
+ builder.Command().
+ BuiltTool("merge_module_info_json").
+ FlagWithOutput("-o ", moduleInfoJSONPath).
+ Input(preMergePath)
+ builder.Build("merge_module_info_json", "merge module info json")
+ ctx.Phony("module-info", moduleInfoJSONPath)
+ ctx.Phony("droidcore-unbundled", moduleInfoJSONPath)
+ allDistContributions = append(allDistContributions, distContributions{
+ copiesForGoals: []*copiesForGoals{{
+ goals: "general-tests droidcore-unbundled",
+ copies: []distCopy{{
+ from: moduleInfoJSONPath,
+ dest: "module-info.json",
+ }},
+ }},
+ })
+ }
+
+ // Build dist.mk for the packaging step to read and generate dist targets
+ distMkFile := absolutePath(filepath.Join(ctx.Config().katiPackageMkDir(), "dist.mk"))
+
+ var goalOutputPairs []string
+ var srcDstPairs []string
+ for _, contributions := range allDistContributions {
+ for _, copiesForGoal := range contributions.copiesForGoals {
+ goals := strings.Fields(copiesForGoal.goals)
+ for _, copy := range copiesForGoal.copies {
+ for _, goal := range goals {
+ goalOutputPairs = append(goalOutputPairs, fmt.Sprintf(" %s:%s", goal, copy.dest))
+ }
+ srcDstPairs = append(srcDstPairs, fmt.Sprintf(" %s:%s", copy.from.String(), copy.dest))
+ }
+ }
+ }
+ // There are duplicates in the lists that we need to remove
+ goalOutputPairs = SortedUniqueStrings(goalOutputPairs)
+ srcDstPairs = SortedUniqueStrings(srcDstPairs)
+ var buf strings.Builder
+ buf.WriteString("DIST_SRC_DST_PAIRS :=")
+ for _, srcDstPair := range srcDstPairs {
+ buf.WriteString(srcDstPair)
+ }
+ buf.WriteString("\nDIST_GOAL_OUTPUT_PAIRS :=")
+ for _, goalOutputPair := range goalOutputPairs {
+ buf.WriteString(goalOutputPair)
+ }
+ buf.WriteString("\n")
+
+ writeValueIfChanged(ctx, distMkFile, buf.String())
+}
+
+func writeValueIfChanged(ctx SingletonContext, path string, value string) {
+ if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
+ ctx.Errorf("%s\n", err)
+ return
+ }
+ previousValue := ""
+ rawPreviousValue, err := os.ReadFile(path)
+ if err == nil {
+ previousValue = string(rawPreviousValue)
+ }
+
+ if previousValue != value {
+ if err = os.WriteFile(path, []byte(value), 0666); err != nil {
+ ctx.Errorf("Failed to write: %v", err)
+ }
+ }
+}
+
+func distsToDistContributions(dists []dist) *distContributions {
+ if len(dists) == 0 {
+ return nil
+ }
+
+ copyGoals := []*copiesForGoals{}
+ for _, dist := range dists {
+ for _, goal := range dist.goals {
+ copyGoals = append(copyGoals, &copiesForGoals{
+ goals: goal,
+ copies: dist.paths,
+ })
+ }
+ }
+
+ return &distContributions{
+ copiesForGoals: copyGoals,
+ }
+}
+
+// getSoongOnlyDataFromMods gathers data from the given modules needed in soong-only builds.
+// Currently, this is the dist contributions, and the module-info.json contents.
+func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distContributions, []*ModuleInfoJSON) {
+ var allDistContributions []distContributions
+ var moduleInfoJSONs []*ModuleInfoJSON
+ for _, mod := range mods {
+ if distInfo, ok := OtherModuleProvider(ctx, mod, DistProvider); ok {
+ if contribution := distsToDistContributions(distInfo.Dists); contribution != nil {
+ allDistContributions = append(allDistContributions, *contribution)
+ }
+ }
+
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider)
+ if commonInfo.SkipAndroidMkProcessing {
+ continue
+ }
+ if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok {
+ // Deep copy the provider info since we need to modify the info later
+ info := deepCopyAndroidMkProviderInfo(info)
+ info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo)
+ if info.PrimaryInfo.disabled() {
+ continue
+ }
+ if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...)
+ }
+ if contribution := getDistContributions(ctx, mod); contribution != nil {
+ allDistContributions = append(allDistContributions, *contribution)
+ }
+ } else {
+ if x, ok := mod.(AndroidMkDataProvider); ok {
+ data := x.AndroidMk()
+
+ if data.Include == "" {
+ data.Include = "$(BUILD_PREBUILT)"
+ }
+
+ data.fillInData(ctx, mod)
+ if data.Entries.disabled() {
+ continue
+ }
+ if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...)
+ }
+ if contribution := getDistContributions(ctx, mod); contribution != nil {
+ allDistContributions = append(allDistContributions, *contribution)
+ }
+ }
+ if x, ok := mod.(AndroidMkEntriesProvider); ok {
+ entriesList := x.AndroidMkEntries()
+ for _, entries := range entriesList {
+ entries.fillInEntries(ctx, mod)
+ if entries.disabled() {
+ continue
+ }
+ if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...)
+ }
+ if contribution := getDistContributions(ctx, mod); contribution != nil {
+ allDistContributions = append(allDistContributions, *contribution)
+ }
+ }
+ }
+ }
+ }
+ return allDistContributions, moduleInfoJSONs
+}
+
+func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []Module) error {
buf := &bytes.Buffer{}
var moduleInfoJSONs []*ModuleInfoJSON
@@ -751,8 +967,8 @@
return err
}
- if amod, ok := mod.(Module); ok && ctx.PrimaryModule(amod) == amod {
- typeStats[ctx.ModuleType(amod)] += 1
+ if ctx.PrimaryModule(mod) == mod {
+ typeStats[ctx.ModuleType(mod)] += 1
}
}
@@ -796,7 +1012,7 @@
return nil
}
-func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod blueprint.Module) error {
+func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod Module) error {
defer func() {
if r := recover(); r != nil {
panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
@@ -827,12 +1043,11 @@
return err
}
-func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) {
+func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod Module) {
// Get the preamble content through AndroidMkEntries logic.
data.Entries = AndroidMkEntries{
Class: data.Class,
SubName: data.SubName,
- DistFiles: data.DistFiles,
OutputFile: data.OutputFile,
Disabled: data.Disabled,
Include: data.Include,
@@ -851,9 +1066,9 @@
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
- mod blueprint.Module, provider AndroidMkDataProvider) error {
+ mod Module, provider AndroidMkDataProvider) error {
- amod := mod.(Module).base()
+ amod := mod.base()
if shouldSkipAndroidMkProcessing(ctx, amod) {
return nil
}
@@ -865,7 +1080,7 @@
}
data.fillInData(ctx, mod)
- aconfigUpdateAndroidMkData(ctx, mod.(Module), &data)
+ aconfigUpdateAndroidMkData(ctx, mod, &data)
prefix := ""
if amod.ArchSpecific() {
@@ -920,7 +1135,7 @@
if !data.Entries.disabled() {
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON...)
}
}
@@ -946,23 +1161,28 @@
}
func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
- mod blueprint.Module, provider AndroidMkEntriesProvider) error {
- if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) {
+ mod Module, provider AndroidMkEntriesProvider) error {
+ if shouldSkipAndroidMkProcessing(ctx, mod.base()) {
return nil
}
entriesList := provider.AndroidMkEntries()
- aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
+ aconfigUpdateAndroidMkEntries(ctx, mod, &entriesList)
+
+ moduleInfoJSON, providesModuleInfoJSON := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider)
// Any new or special cases here need review to verify correct propagation of license information.
for _, entries := range entriesList {
entries.fillInEntries(ctx, mod)
entries.write(w)
- }
- if len(entriesList) > 0 && !entriesList[0].disabled() {
- if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ if providesModuleInfoJSON && !entries.disabled() {
+ // append only the name matching moduleInfoJSON entry
+ for _, m := range moduleInfoJSON {
+ if m.RegisterNameOverride == entries.OverrideName && m.SubName == entries.SubName {
+ *moduleInfoJSONs = append(*moduleInfoJSONs, m)
+ }
+ }
}
}
@@ -1065,8 +1285,6 @@
SubName string
// If set, this value overrides the base module name. SubName is still appended.
OverrideName string
- // Dist files to output
- DistFiles TaggedDistFiles
// The output file for Kati to process and/or install. If absent, the module is skipped.
OutputFile OptionalPath
// If true, the module is skipped and does not appear on the final Android-<product name>.mk
@@ -1106,30 +1324,33 @@
// TODO: rename it to AndroidMkEntriesProvider after AndroidMkEntriesProvider interface is gone.
var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]()
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
- mod blueprint.Module, providerInfo *AndroidMkProviderInfo) error {
- if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) {
+ mod Module, providerInfo *AndroidMkProviderInfo) error {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider)
+ if commonInfo.SkipAndroidMkProcessing {
return nil
}
// Deep copy the provider info since we need to modify the info later
info := deepCopyAndroidMkProviderInfo(providerInfo)
- aconfigUpdateAndroidMkInfos(ctx, mod.(Module), &info)
+ aconfigUpdateAndroidMkInfos(ctx, mod, &info)
// Any new or special cases here need review to verify correct propagation of license information.
- info.PrimaryInfo.fillInEntries(ctx, mod)
+ info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo)
info.PrimaryInfo.write(w)
if len(info.ExtraInfo) > 0 {
for _, ei := range info.ExtraInfo {
- ei.fillInEntries(ctx, mod)
+ ei.fillInEntries(ctx, mod, commonInfo)
ei.write(w)
}
}
if !info.PrimaryInfo.disabled() {
if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
- *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON...)
}
}
@@ -1251,14 +1472,14 @@
a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...)
}
-func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
+func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) {
helperInfo := AndroidMkInfo{
EntryMap: make(map[string][]string),
}
- amod := mod.(Module)
- base := amod.base()
- name := base.BaseModuleName()
+ name := commonInfo.BaseModuleName
if a.OverrideName != "" {
name = a.OverrideName
}
@@ -1266,17 +1487,22 @@
if a.Include == "" {
a.Include = "$(BUILD_PREBUILT)"
}
- a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...)
- a.Required = append(a.Required, amod.VintfFragmentModuleNames(ctx)...)
- a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
- a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
+ a.Required = append(a.Required, commonInfo.RequiredModuleNames...)
+ a.Required = append(a.Required, commonInfo.VintfFragmentModuleNames...)
+ a.Host_required = append(a.Host_required, commonInfo.HostRequiredModuleNames...)
+ a.Target_required = append(a.Target_required, commonInfo.TargetRequiredModuleNames...)
- for _, distString := range a.GetDistForGoals(ctx, mod) {
- a.HeaderStrings = append(a.HeaderStrings, distString)
+ a.HeaderStrings = append(a.HeaderStrings, a.GetDistForGoals(ctx, mod, commonInfo)...)
+ a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), commonInfo.BaseModuleName, ctx.ModuleSubDir(mod)))
+
+ // Add the TestSuites from the provider to LOCAL_SOONG_PROVIDER_TEST_SUITES.
+ // LOCAL_SOONG_PROVIDER_TEST_SUITES will be compared against LOCAL_COMPATIBILITY_SUITES
+ // in make and enforced they're the same, to ensure we've successfully translated all
+ // LOCAL_COMPATIBILITY_SUITES usages to the provider.
+ if testSuiteInfo, ok := OtherModuleProvider(ctx, mod, TestSuiteInfoProvider); ok {
+ helperInfo.AddStrings("LOCAL_SOONG_PROVIDER_TEST_SUITES", testSuiteInfo.TestSuites...)
}
- a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod)))
-
// Collect make variable assignment entries.
helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
helperInfo.SetString("LOCAL_MODULE", name+a.SubName)
@@ -1285,7 +1511,7 @@
helperInfo.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
helperInfo.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
helperInfo.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)
- helperInfo.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
+ helperInfo.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(mod))
// If the install rule was generated by Soong tell Make about it.
info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
@@ -1300,7 +1526,7 @@
// Soong may not have generated the install rule also when `no_full_install: true`.
// Mark this module as uninstallable in order to prevent Make from creating an
// install rule there.
- helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
+ helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", commonInfo.NoFullInstall)
}
if info.UncheckedModule {
@@ -1315,31 +1541,31 @@
helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
}
- if am, ok := mod.(ApexModule); ok {
- helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
+ if commonInfo.IsApexModule {
+ helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", commonInfo.NotAvailableForPlatform)
}
- archStr := base.Arch().ArchType.String()
+ archStr := commonInfo.Target.Arch.ArchType.String()
host := false
- switch base.Os().Class {
+ switch commonInfo.Target.Os.Class {
case Host:
- if base.Target().HostCross {
+ if commonInfo.Target.HostCross {
// Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
- if base.Arch().ArchType != Common {
+ if commonInfo.Target.Arch.ArchType != Common {
helperInfo.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr)
}
} else {
// Make cannot identify LOCAL_MODULE_HOST_ARCH:= common.
- if base.Arch().ArchType != Common {
+ if commonInfo.Target.Arch.ArchType != Common {
helperInfo.SetString("LOCAL_MODULE_HOST_ARCH", archStr)
}
}
host = true
case Device:
// Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common.
- if base.Arch().ArchType != Common {
- if base.Target().NativeBridge {
- hostArchStr := base.Target().NativeBridgeHostArchName
+ if commonInfo.Target.Arch.ArchType != Common {
+ if commonInfo.Target.NativeBridge {
+ hostArchStr := commonInfo.Target.NativeBridgeHostArchName
if hostArchStr != "" {
helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
}
@@ -1348,27 +1574,28 @@
}
}
- if !base.InVendorRamdisk() {
+ if !commonInfo.InVendorRamdisk {
helperInfo.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths)
}
if len(info.VintfFragmentsPaths) > 0 {
helperInfo.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths)
}
- helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
- if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
+ helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", commonInfo.Proprietary)
+ if commonInfo.Vendor || commonInfo.SocSpecific {
helperInfo.SetString("LOCAL_VENDOR_MODULE", "true")
}
- helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific))
- helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific))
- helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific))
- if base.commonProperties.Owner != nil {
- helperInfo.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner)
+ helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", commonInfo.DeviceSpecific)
+ helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", commonInfo.ProductSpecific)
+ helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", commonInfo.SystemExtSpecific)
+ if commonInfo.Owner != "" {
+ helperInfo.SetString("LOCAL_MODULE_OWNER", commonInfo.Owner)
}
}
if host {
- makeOs := base.Os().String()
- if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
+ os := commonInfo.Target.Os
+ makeOs := os.String()
+ if os == Linux || os == LinuxBionic || os == LinuxMusl {
makeOs = "linux"
}
helperInfo.SetString("LOCAL_MODULE_HOST_OS", makeOs)
@@ -1426,8 +1653,10 @@
// Compute the list of Make strings to declare phony goals and dist-for-goals
// calls from the module's dist and dists properties.
-func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod blueprint.Module) []string {
- distContributions := a.getDistContributions(ctx, mod)
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
+func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) []string {
+ distContributions := getDistContributions(ctx, mod)
if distContributions == nil {
return nil
}
@@ -1435,131 +1664,6 @@
return generateDistContributionsForMake(distContributions)
}
-// Compute the contributions that the module makes to the dist.
-func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod blueprint.Module) *distContributions {
- amod := mod.(Module).base()
- name := amod.BaseModuleName()
-
- // Collate the set of associated tag/paths available for copying to the dist.
- // Start with an empty (nil) set.
- var availableTaggedDists TaggedDistFiles
-
- // Then merge in any that are provided explicitly by the module.
- if a.DistFiles != nil {
- // Merge the DistFiles into the set.
- availableTaggedDists = availableTaggedDists.merge(a.DistFiles)
- }
-
- // If no paths have been provided for the DefaultDistTag and the output file is
- // valid then add that as the default dist path.
- if _, ok := availableTaggedDists[DefaultDistTag]; !ok && a.OutputFile.Valid() {
- availableTaggedDists = availableTaggedDists.addPathsForTag(DefaultDistTag, a.OutputFile.Path())
- }
-
- info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
- // If the distFiles created by GenerateTaggedDistFiles contains paths for the
- // DefaultDistTag then that takes priority so delete any existing paths.
- if _, ok := info.DistFiles[DefaultDistTag]; ok {
- delete(availableTaggedDists, DefaultDistTag)
- }
-
- // Finally, merge the distFiles created by GenerateTaggedDistFiles.
- availableTaggedDists = availableTaggedDists.merge(info.DistFiles)
-
- if len(availableTaggedDists) == 0 {
- // Nothing dist-able for this module.
- return nil
- }
-
- // Collate the contributions this module makes to the dist.
- distContributions := &distContributions{}
-
- if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
- distContributions.licenseMetadataFile = info.LicenseMetadataFile
- }
-
- // Iterate over this module's dist structs, merged from the dist and dists properties.
- for _, dist := range amod.Dists() {
- // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
- goals := strings.Join(dist.Targets, " ")
-
- // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
- var tag string
- if dist.Tag == nil {
- // If the dist struct does not specify a tag, use the default output files tag.
- tag = DefaultDistTag
- } else {
- tag = *dist.Tag
- }
-
- // Get the paths of the output files to be dist'd, represented by the tag.
- // Can be an empty list.
- tagPaths := availableTaggedDists[tag]
- if len(tagPaths) == 0 {
- // Nothing to dist for this tag, continue to the next dist.
- continue
- }
-
- if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
- errorMessage := "%s: Cannot apply dest/suffix for more than one dist " +
- "file for %q goals tag %q in module %s. The list of dist files, " +
- "which should have a single element, is:\n%s"
- panic(fmt.Errorf(errorMessage, mod, goals, tag, name, tagPaths))
- }
-
- copiesForGoals := distContributions.getCopiesForGoals(goals)
-
- // Iterate over each path adding a copy instruction to copiesForGoals
- for _, path := range tagPaths {
- // It's possible that the Path is nil from errant modules. Be defensive here.
- if path == nil {
- tagName := "default" // for error message readability
- if dist.Tag != nil {
- tagName = *dist.Tag
- }
- panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
- }
-
- dest := filepath.Base(path.String())
-
- if dist.Dest != nil {
- var err error
- if dest, err = validateSafePath(*dist.Dest); err != nil {
- // This was checked in ModuleBase.GenerateBuildActions
- panic(err)
- }
- }
-
- ext := filepath.Ext(dest)
- suffix := ""
- if dist.Suffix != nil {
- suffix = *dist.Suffix
- }
-
- productString := ""
- if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
- productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct())
- }
-
- if suffix != "" || productString != "" {
- dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
- }
-
- if dist.Dir != nil {
- var err error
- if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
- // This was checked in ModuleBase.GenerateBuildActions
- panic(err)
- }
- }
-
- copiesForGoals.addCopyInstruction(path, dest)
- }
- }
-
- return distContributions
-}
-
func deepCopyAndroidMkProviderInfo(providerInfo *AndroidMkProviderInfo) AndroidMkProviderInfo {
info := AndroidMkProviderInfo{
PrimaryInfo: deepCopyAndroidMkInfo(&providerInfo.PrimaryInfo),
@@ -1577,9 +1681,8 @@
Class: mkinfo.Class,
SubName: mkinfo.SubName,
OverrideName: mkinfo.OverrideName,
- // There is no modification on DistFiles or OutputFile, so no need to
+ // There is no modification on OutputFile, so no need to
// make their deep copy.
- DistFiles: mkinfo.DistFiles,
OutputFile: mkinfo.OutputFile,
Disabled: mkinfo.Disabled,
Include: mkinfo.Include,
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index f63b227..cd61133 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -34,7 +34,6 @@
}
data AndroidMkData
- distFiles TaggedDistFiles
outputFile OptionalPath
}
@@ -73,7 +72,6 @@
path := PathForTesting("default-dist.out")
defaultDistPaths = Paths{path}
m.setOutputFiles(ctx, defaultDistPaths)
- m.distFiles = MakeDefaultDistFiles(path)
case defaultDistFiles_Tagged:
// Module types that set AndroidMkEntry.DistFiles to the result of calling
@@ -84,11 +82,6 @@
// will be the same as empty-string-tag output.
defaultDistPaths = PathsForTesting("one.out")
m.setOutputFiles(ctx, defaultDistPaths)
-
- // This must be called after setting defaultDistPaths/outputFile as
- // GenerateTaggedDistFiles calls into outputFiles property which may use
- // those fields.
- m.distFiles = m.GenerateTaggedDistFiles(ctx)
}
}
@@ -113,7 +106,6 @@
return []AndroidMkEntries{
{
Class: "CUSTOM_MODULE",
- DistFiles: m.distFiles,
OutputFile: m.outputFile,
},
}
@@ -144,7 +136,7 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- module := result.ModuleForTests("foo", "").Module().(*customModule)
+ module := result.ModuleForTests(t, "foo", "").Module().(*customModule)
return result.TestContext, module
}
@@ -354,7 +346,7 @@
if len(entries) != 1 {
t.Errorf("Expected a single AndroidMk entry, got %d", len(entries))
}
- distContributions := entries[0].getDistContributions(module)
+ distContributions := getDistContributions(ctx, module)
if err := compareContributions(expectedContributions, distContributions); err != nil {
t.Errorf("%s\nExpected Contributions\n%sActualContributions\n%s",
@@ -656,8 +648,8 @@
default_dist_files: "none",
dist_output_file: false,
dists: [
- // The following is silently ignored because there is not default file
- // in either the dist files or the output file.
+ // The following will dist one.out because there's no default dist file provided
+ // (default_dist_files: "none") and one.out is the outputfile for the "" tag.
{
targets: ["my_goal"],
},
@@ -672,6 +664,12 @@
{
goals: "my_goal",
copies: []distCopy{
+ distCopyForTest("one.out", "one.out"),
+ },
+ },
+ {
+ goals: "my_goal",
+ copies: []distCopy{
distCopyForTest("two.out", "two.out"),
distCopyForTest("three/four.out", "four.out"),
},
diff --git a/android/apex.go b/android/apex.go
index db93912..57baff5 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -17,7 +17,6 @@
import (
"fmt"
"slices"
- "sort"
"strconv"
"strings"
"sync"
@@ -55,23 +54,32 @@
// to true.
UsePlatformApis bool
- // List of Apex variant names that this module is associated with. This initially is the
- // same as the `ApexVariationName` field. Then when multiple apex variants are merged in
- // mergeApexVariations, ApexInfo struct of the merged variant holds the list of apexBundles
- // that are merged together.
- InApexVariants []string
-
// True if this is for a prebuilt_apex.
//
// If true then this will customize the apex processing to make it suitable for handling
// prebuilt_apex, e.g. it will prevent ApexInfos from being merged together.
//
- // See Prebuilt.ApexInfoMutator for more information.
+ // Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
+ // across prebuilt_apex modules. That is because there is no way to determine whether two
+ // prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
+ // been built from different source at different times or they could have been built with different
+ // build options that affect the libraries.
+ //
+ // While it may be possible to provide sufficient information to determine whether two prebuilt_apex
+ // modules were compatible it would be a lot of work and would not provide much benefit for a couple
+ // of reasons:
+ // - The number of prebuilt_apex modules that will be exporting files for the same module will be
+ // low as the prebuilt_apex only exports files for the direct dependencies that require it and
+ // very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
+ // few com.android.art* apex files that contain the same contents and could export files for the
+ // same modules but only one of them needs to do so. Contrast that with source apex modules which
+ // need apex specific variants for every module that contributes code to the apex, whether direct
+ // or indirect.
+ // - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
+ // extra copying of files. Contrast that with source apex modules that has to build each variant
+ // from source.
ForPrebuiltApex bool
- // Returns the name of the test apexes that this module is included in.
- TestApexes []string
-
// Returns the name of the overridden apex (com.android.foo)
BaseApexName string
@@ -79,19 +87,34 @@
ApexAvailableName string
}
-// AllApexInfo holds the ApexInfo of all apexes that include this module.
-type AllApexInfo struct {
- ApexInfos []ApexInfo
+func (a ApexInfo) Variation() string {
+ return a.ApexVariationName
+}
+
+// Minimize is called during a transition from a module with a unique variation per apex to a module that should
+// share variations between apexes. It returns a minimized ApexInfo that removes any apex names and replaces
+// the variation name with one computed from the remaining properties.
+func (a ApexInfo) Minimize() ApexInfo {
+ info := ApexInfo{
+ MinSdkVersion: a.MinSdkVersion,
+ UsePlatformApis: a.UsePlatformApis,
+ }
+ info.ApexVariationName = info.mergedName()
+ return info
+}
+
+type ApexAvailableInfo struct {
+ // Returns the apex names that this module is available for
+ ApexAvailableFor []string
}
var ApexInfoProvider = blueprint.NewMutatorProvider[ApexInfo]("apex_mutate")
-var AllApexInfoProvider = blueprint.NewMutatorProvider[*AllApexInfo]("apex_info")
+var ApexAvailableInfoProvider = blueprint.NewMutatorProvider[ApexAvailableInfo]("apex_mutate")
func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
(*d)["Apex"] = map[string]interface{}{
"ApexVariationName": i.ApexVariationName,
"MinSdkVersion": i.MinSdkVersion,
- "InApexVariants": i.InApexVariants,
"ForPrebuiltApex": i.ForPrebuiltApex,
}
}
@@ -105,6 +128,9 @@
// thus wouldn't be merged.
func (i ApexInfo) mergedName() string {
name := "apex" + strconv.Itoa(i.MinSdkVersion.FinalOrFutureInt())
+ if i.UsePlatformApis {
+ name += "_p"
+ }
return name
}
@@ -114,49 +140,54 @@
return i.ApexVariationName == ""
}
-// InApexVariant tells whether this apex variant of the module is part of the given apexVariant or
-// not.
-func (i ApexInfo) InApexVariant(apexVariant string) bool {
- for _, a := range i.InApexVariants {
- if a == apexVariant {
- return true
- }
- }
- return false
-}
-
// To satisfy the comparable interface
func (i ApexInfo) Equal(other any) bool {
otherApexInfo, ok := other.(ApexInfo)
return ok && i.ApexVariationName == otherApexInfo.ApexVariationName &&
i.MinSdkVersion == otherApexInfo.MinSdkVersion &&
i.Updatable == otherApexInfo.Updatable &&
- i.UsePlatformApis == otherApexInfo.UsePlatformApis &&
- slices.Equal(i.InApexVariants, otherApexInfo.InApexVariants)
+ i.UsePlatformApis == otherApexInfo.UsePlatformApis
}
// ApexBundleInfo contains information about the dependencies of an apex
type ApexBundleInfo struct {
}
-var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_info")
+var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_mutate")
-// DepIsInSameApex defines an interface that should be used to determine whether a given dependency
-// should be considered as part of the same APEX as the current module or not. Note: this was
-// extracted from ApexModule to make it easier to define custom subsets of the ApexModule interface
-// and improve code navigation within the IDE.
-type DepIsInSameApex interface {
- // DepIsInSameApex tests if the other module 'dep' is considered as part of the same APEX as
- // this module. For example, a static lib dependency usually returns true here, while a
+// DepInSameApexChecker defines an interface that should be used to determine whether a given dependency
+// should be considered as part of the same APEX as the current module or not.
+type DepInSameApexChecker interface {
+ // OutgoingDepIsInSameApex tests if the module depended on via 'tag' is considered as part of
+ // the same APEX as this module. For example, a static lib dependency usually returns true here, while a
// shared lib dependency to a stub library returns false.
//
// This method must not be called directly without first ignoring dependencies whose tags
// implement ExcludeFromApexContentsTag. Calls from within the func passed to WalkPayloadDeps()
// are fine as WalkPayloadDeps() will ignore those dependencies automatically. Otherwise, use
// IsDepInSameApex instead.
- DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
+ OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool
+
+ // IncomingDepIsInSameApex tests if this module depended on via 'tag' is considered as part of
+ // the same APEX as the depending module module. For example, a static lib dependency usually
+ // returns true here, while a shared lib dependency to a stub library returns false.
+ //
+ // This method must not be called directly without first ignoring dependencies whose tags
+ // implement ExcludeFromApexContentsTag. Calls from within the func passed to WalkPayloadDeps()
+ // are fine as WalkPayloadDeps() will ignore those dependencies automatically. Otherwise, use
+ // IsDepInSameApex instead.
+ IncomingDepIsInSameApex(tag blueprint.DependencyTag) bool
}
+// DepInSameApexInfo is a provider that wraps around a DepInSameApexChecker that can be
+// used to check if a dependency belongs to the same apex as the module when walking
+// through the dependencies of a module.
+type DepInSameApexInfo struct {
+ Checker DepInSameApexChecker
+}
+
+var DepInSameApexInfoProvider = blueprint.NewMutatorProvider[DepInSameApexInfo]("apex_unique")
+
func IsDepInSameApex(ctx BaseModuleContext, module, dep Module) bool {
depTag := ctx.OtherModuleDependencyTag(dep)
if _, ok := depTag.(ExcludeFromApexContentsTag); ok {
@@ -164,7 +195,25 @@
// apex as the parent.
return false
}
- return module.(DepIsInSameApex).DepIsInSameApex(ctx, dep)
+
+ if !EqualModules(ctx.Module(), module) {
+ if moduleInfo, ok := OtherModuleProvider(ctx, module, DepInSameApexInfoProvider); ok {
+ if !moduleInfo.Checker.OutgoingDepIsInSameApex(depTag) {
+ return false
+ }
+ }
+ } else {
+ if m, ok := ctx.Module().(ApexModule); ok && !m.GetDepInSameApexChecker().OutgoingDepIsInSameApex(depTag) {
+ return false
+ }
+ }
+ if depInfo, ok := OtherModuleProvider(ctx, dep, DepInSameApexInfoProvider); ok {
+ if !depInfo.Checker.IncomingDepIsInSameApex(depTag) {
+ return false
+ }
+ }
+
+ return true
}
// ApexModule is the interface that a module type is expected to implement if the module has to be
@@ -182,7 +231,6 @@
// mergedName) when the two APEXes have the same min_sdk_version requirement.
type ApexModule interface {
Module
- DepIsInSameApex
apexModuleBase() *ApexModuleBase
@@ -213,6 +261,12 @@
// apex_available property of the module.
AvailableFor(what string) bool
+ // Returns the apexes that are available for this module, valid values include
+ // "//apex_available:platform", "//apex_available:anyapex" and specific apexes.
+ // There are some differences between this one and the ApexAvailable on
+ // ApexModuleBase for cc, java library and sdkLibraryXml.
+ ApexAvailableFor() []string
+
// AlwaysRequiresPlatformApexVariant allows the implementing module to determine whether an
// APEX mutator should always be created for it.
//
@@ -228,16 +282,15 @@
// check-platform-availability mutator in the apex package.
SetNotAvailableForPlatform()
- // Returns nil (success) if this module should support the given sdk version. Returns an
- // error if not. No default implementation is provided for this method. A module type
- // implementing this interface should provide an implementation. A module supports an sdk
- // version when the module's min_sdk_version is equal to or less than the given sdk version.
- ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion ApiLevel) error
+ // Returns the min sdk version that the module supports, .
+ MinSdkVersionSupported(ctx BaseModuleContext) ApiLevel
// Returns true if this module needs a unique variation per apex, effectively disabling the
// deduping. This is turned on when, for example if use_apex_name_macro is set so that each
// apex variant should be built with different macro definitions.
UniqueApexVariations() bool
+
+ GetDepInSameApexChecker() DepInSameApexChecker
}
// Properties that are common to all module types implementing ApexModule interface.
@@ -257,16 +310,10 @@
// See ApexModule.UniqueApexVariants()
UniqueApexVariationsForDeps bool `blueprint:"mutated"`
-
- // The test apexes that includes this apex variant
- TestApexes []string `blueprint:"mutated"`
}
// Marker interface that identifies dependencies that are excluded from APEX contents.
//
-// Unless the tag also implements the AlwaysRequireApexVariantTag this will prevent an apex variant
-// from being created for the module.
-//
// At the moment the sdk.sdkRequirementsMutator relies on the fact that the existing tags which
// implement this interface do not define dependencies onto members of an sdk_snapshot. If that
// changes then sdk.sdkRequirementsMutator will need fixing.
@@ -277,17 +324,6 @@
ExcludeFromApexContents()
}
-// Marker interface that identifies dependencies that always requires an APEX variant to be created.
-//
-// It is possible for a dependency to require an apex variant but exclude the module from the APEX
-// contents. See sdk.sdkMemberDependencyTag.
-type AlwaysRequireApexVariantTag interface {
- blueprint.DependencyTag
-
- // Return true if this tag requires that the target dependency has an apex variant.
- AlwaysRequireApexVariant() bool
-}
-
// Interface that identifies dependencies to skip Apex dependency check
type SkipApexAllowedDependenciesCheck interface {
// Returns true to skip the Apex dependency check, which limits the allowed dependency in build.
@@ -306,6 +342,61 @@
apexInfosLock sync.Mutex // protects apexInfos during parallel apexInfoMutator
}
+func (m *ApexModuleBase) ApexTransitionMutatorSplit(ctx BaseModuleContext) []ApexInfo {
+ return []ApexInfo{{}}
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorOutgoing(ctx OutgoingTransitionContext, info ApexInfo) ApexInfo {
+ if !ctx.Module().(ApexModule).GetDepInSameApexChecker().OutgoingDepIsInSameApex(ctx.DepTag()) {
+ return ApexInfo{}
+ }
+ return info
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorIncoming(ctx IncomingTransitionContext, info ApexInfo) ApexInfo {
+ module := ctx.Module().(ApexModule)
+ if !module.CanHaveApexVariants() {
+ return ApexInfo{}
+ }
+
+ if !ctx.Module().(ApexModule).GetDepInSameApexChecker().IncomingDepIsInSameApex(ctx.DepTag()) {
+ return ApexInfo{}
+ }
+
+ if info.ApexVariationName == "" {
+ return ApexInfo{}
+ }
+
+ if !ctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps && !info.ForPrebuiltApex {
+ return info.Minimize()
+ }
+ return info
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorMutate(ctx BottomUpMutatorContext, info ApexInfo) {
+ SetProvider(ctx, ApexInfoProvider, info)
+
+ module := ctx.Module().(ApexModule)
+ base := module.apexModuleBase()
+
+ platformVariation := info.ApexVariationName == ""
+ if !platformVariation {
+ // Do some validity checks.
+ // TODO(jiyong): is this the right place?
+ base.checkApexAvailableProperty(ctx)
+
+ SetProvider(ctx, ApexAvailableInfoProvider, ApexAvailableInfo{
+ ApexAvailableFor: module.ApexAvailableFor(),
+ })
+ }
+ if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
+ // Do not install the module for platform, but still allow it to output
+ // uninstallable AndroidMk entries in certain cases when they have side
+ // effects. TODO(jiyong): move this routine to somewhere else
+ module.MakeUninstallable()
+ }
+}
+
// Initializes ApexModuleBase struct. Not calling this (even when inheriting from ApexModuleBase)
// prevents the module from being mutated for apexBundle.
func InitApexModule(m ApexModule) {
@@ -334,6 +425,10 @@
return CopyOf(availableToPlatformList)
}
+func (m *ApexModuleBase) ApexAvailableFor() []string {
+ return m.ApexAvailable()
+}
+
// Implements ApexModule
func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
m.apexInfosLock.Lock()
@@ -373,11 +468,6 @@
return false
}
-// Returns the test apexes that this module is included in.
-func (m *ApexModuleBase) TestApexes() []string {
- return m.ApexProperties.TestApexes
-}
-
// Implements ApexModule
func (m *ApexModuleBase) UniqueApexVariations() bool {
// If needed, this will bel overridden by concrete types inheriting
@@ -386,11 +476,17 @@
}
// Implements ApexModule
-func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
- // By default, if there is a dependency from A to B, we try to include both in the same
- // APEX, unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning
- // true. This is overridden by some module types like apex.ApexBundle, cc.Module,
- // java.Module, etc.
+func (m *ApexModuleBase) GetDepInSameApexChecker() DepInSameApexChecker {
+ return BaseDepInSameApexChecker{}
+}
+
+type BaseDepInSameApexChecker struct{}
+
+func (m BaseDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return true
+}
+
+func (m BaseDepInSameApexChecker) IncomingDepIsInSameApex(tag blueprint.DependencyTag) bool {
return true
}
@@ -428,13 +524,17 @@
if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) {
return true
}
+ // TODO b/383863941: Remove once legacy name is no longer used
+ if (apex_name == "com.android.btservices" && what == "com.android.bt") || (apex_name == "com.android.bt" && what == "com.android.btservices") {
+ return true
+ }
}
return false
}
// Implements ApexModule
func (m *ApexModuleBase) AvailableFor(what string) bool {
- return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
+ return CheckAvailableForApex(what, m.ApexAvailableFor())
}
// Implements ApexModule
@@ -494,204 +594,14 @@
return true
}
-// mergeApexVariations deduplicates apex variations that would build identically into a common
-// variation. It returns the reduced list of variations and a list of aliases from the original
-// variation names to the new variation names.
-func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
- seen := make(map[string]int)
- for _, apexInfo := range apexInfos {
- // If this is for a prebuilt apex then use the actual name of the apex variation to prevent this
- // from being merged with other ApexInfo. See Prebuilt.ApexInfoMutator for more information.
- if apexInfo.ForPrebuiltApex {
- merged = append(merged, apexInfo)
- continue
- }
-
- // Merge the ApexInfo together. If a compatible ApexInfo exists then merge the information from
- // this one into it, otherwise create a new merged ApexInfo from this one and save it away so
- // other ApexInfo instances can be merged into it.
- variantName := apexInfo.ApexVariationName
- mergedName := apexInfo.mergedName()
- if index, exists := seen[mergedName]; exists {
- // Variants having the same mergedName are deduped
- merged[index].InApexVariants = append(merged[index].InApexVariants, variantName)
- merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
- // Platform APIs is allowed for this module only when all APEXes containing
- // the module are with `use_platform_apis: true`.
- merged[index].UsePlatformApis = merged[index].UsePlatformApis && apexInfo.UsePlatformApis
- merged[index].TestApexes = append(merged[index].TestApexes, apexInfo.TestApexes...)
- } else {
- seen[mergedName] = len(merged)
- apexInfo.ApexVariationName = mergedName
- apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants)
- apexInfo.TestApexes = CopyOf(apexInfo.TestApexes)
- merged = append(merged, apexInfo)
- }
- aliases = append(aliases, [2]string{variantName, mergedName})
- }
- return merged, aliases
-}
-
-// IncomingApexTransition is called by apexTransitionMutator.IncomingTransition on modules that can be in apexes.
-// The incomingVariation can be either the name of an apex if the dependency is coming directly from an apex
-// module, or it can be the name of an apex variation (e.g. apex10000) if it is coming from another module that
-// is in the apex.
-func IncomingApexTransition(ctx IncomingTransitionContext, incomingVariation string) string {
- module := ctx.Module().(ApexModule)
- base := module.apexModuleBase()
-
- var apexInfos []ApexInfo
- if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- apexInfos = allApexInfos.ApexInfos
- }
-
- // Dependencies from platform variations go to the platform variation.
- if incomingVariation == "" {
- return ""
- }
-
- if len(apexInfos) == 0 {
- if ctx.IsAddingDependency() {
- // If this module has no apex variations we can't do any mapping on the incoming variation, just return it
- // and let the caller get a "missing variant" error.
- return incomingVariation
- } else {
- // If this module has no apex variations the use the platform variation.
- return ""
- }
- }
-
- // Convert the list of apex infos into from the AllApexInfoProvider into the merged list
- // of apex variations and the aliases from apex names to apex variations.
- var aliases [][2]string
- if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, aliases = mergeApexVariations(apexInfos)
- }
-
- // Check if the incoming variation matches an apex name, and if so use the corresponding
- // apex variation.
- aliasIndex := slices.IndexFunc(aliases, func(alias [2]string) bool {
- return alias[0] == incomingVariation
- })
- if aliasIndex >= 0 {
- return aliases[aliasIndex][1]
- }
-
- // Check if the incoming variation matches an apex variation.
- apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
- return info.ApexVariationName == incomingVariation
- })
- if apexIndex >= 0 {
- return incomingVariation
- }
-
- return ""
-}
-
-func MutateApexTransition(ctx BaseModuleContext, variation string) {
- module := ctx.Module().(ApexModule)
- base := module.apexModuleBase()
- platformVariation := variation == ""
-
- var apexInfos []ApexInfo
- if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- apexInfos = allApexInfos.ApexInfos
- }
-
- // Shortcut
- if len(apexInfos) == 0 {
- return
- }
-
- // Do some validity checks.
- // TODO(jiyong): is this the right place?
- base.checkApexAvailableProperty(ctx)
-
- if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, _ = mergeApexVariations(apexInfos)
- }
-
- if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
- // Do not install the module for platform, but still allow it to output
- // uninstallable AndroidMk entries in certain cases when they have side
- // effects. TODO(jiyong): move this routine to somewhere else
- module.MakeUninstallable()
- }
- if !platformVariation {
- var thisApexInfo ApexInfo
-
- apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
- return info.ApexVariationName == variation
- })
- if apexIndex >= 0 {
- thisApexInfo = apexInfos[apexIndex]
- } else {
- panic(fmt.Errorf("failed to find apexInfo for incoming variation %q", variation))
- }
-
- SetProvider(ctx, ApexInfoProvider, thisApexInfo)
- }
-
- // Set the value of TestApexes in every single apex variant.
- // This allows each apex variant to be aware of the test apexes in the user provided apex_available.
- var testApexes []string
- for _, a := range apexInfos {
- testApexes = append(testApexes, a.TestApexes...)
- }
- base.ApexProperties.TestApexes = testApexes
-
-}
-
-func ApexInfoMutator(ctx TopDownMutatorContext, module ApexModule) {
- base := module.apexModuleBase()
- if len(base.apexInfos) > 0 {
- apexInfos := slices.Clone(base.apexInfos)
- slices.SortFunc(apexInfos, func(a, b ApexInfo) int {
- return strings.Compare(a.ApexVariationName, b.ApexVariationName)
- })
- SetProvider(ctx, AllApexInfoProvider, &AllApexInfo{apexInfos})
- // base.apexInfos is only needed to propagate the list of apexes from the apex module to its
- // contents within apexInfoMutator. Clear it so it doesn't accidentally get used later.
- base.apexInfos = nil
- }
-}
-
// UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies that are
// in the same APEX have unique APEX variations so that the module can link against the right
// variant.
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
- // anyInSameApex returns true if the two ApexInfo lists contain any values in an
- // InApexVariants list in common. It is used instead of DepIsInSameApex because it needs to
- // determine if the dep is in the same APEX due to being directly included, not only if it
- // is included _because_ it is a dependency.
- anyInSameApex := func(a, b ApexModule) bool {
- collectApexes := func(m ApexModule) []string {
- if allApexInfo, ok := OtherModuleProvider(mctx, m, AllApexInfoProvider); ok {
- var ret []string
- for _, info := range allApexInfo.ApexInfos {
- ret = append(ret, info.InApexVariants...)
- }
- return ret
- }
- return nil
- }
-
- aApexes := collectApexes(a)
- bApexes := collectApexes(b)
- sort.Strings(bApexes)
- for _, aApex := range aApexes {
- index := sort.SearchStrings(bApexes, aApex)
- if index < len(bApexes) && bApexes[index] == aApex {
- return true
- }
- }
- return false
- }
-
// If any of the dependencies requires unique apex variations, so does this module.
mctx.VisitDirectDeps(func(dep Module) {
if depApexModule, ok := dep.(ApexModule); ok {
- if anyInSameApex(depApexModule, am) &&
+ if IsDepInSameApex(mctx, am, depApexModule) &&
(depApexModule.UniqueApexVariations() ||
depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
@@ -736,6 +646,13 @@
FullListPath() Path
}
+type ApexBundleDepsData struct {
+ Updatable bool
+ FlatListPath Path
+}
+
+var ApexBundleDepsDataProvider = blueprint.NewProvider[ApexBundleDepsData]()
+
func (d *ApexBundleDepsInfo) FlatListPath() Path {
return d.flatListPath
}
@@ -778,7 +695,7 @@
// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
-type PayloadDepsCallback func(ctx BaseModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
+type PayloadDepsCallback func(ctx BaseModuleContext, from, to ModuleProxy, externalDep bool) bool
type WalkPayloadDepsFunc func(ctx BaseModuleContext, do PayloadDepsCallback)
// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
@@ -806,40 +723,63 @@
return
}
- walk(ctx, func(ctx BaseModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
+ walk(ctx, func(ctx BaseModuleContext, from, to ModuleProxy, externalDep bool) bool {
if externalDep {
// external deps are outside the payload boundary, which is "stable"
// interface. We don't have to check min_sdk_version for external
// dependencies.
return false
}
- if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
+ if !IsDepInSameApex(ctx, from, to) {
return false
}
- if m, ok := to.(ModuleWithMinSdkVersionCheck); ok {
- // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version
- // to trigger the check.
- if !m.MinSdkVersion(ctx).Specified() {
- ctx.OtherModuleErrorf(m, "must set min_sdk_version")
+ if info, ok := OtherModuleProvider(ctx, to, CommonModuleInfoProvider); ok && info.ModuleWithMinSdkVersionCheck {
+ if info.MinSdkVersion.ApiLevel == nil || !info.MinSdkVersion.ApiLevel.Specified() {
+ // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version
+ // to trigger the check.
+ ctx.OtherModuleErrorf(to, "must set min_sdk_version")
}
return false
}
- if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
- toName := ctx.OtherModuleName(to)
+ if err := ShouldSupportSdkVersion(ctx, to, minSdkVersion); err != nil {
ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
"\n\nDependency path: %s\n\n"+
"Consider adding 'min_sdk_version: %q' to %q",
minSdkVersion, ctx.ModuleName(), err.Error(),
ctx.GetPathString(false),
- minSdkVersion, toName)
+ minSdkVersion, ctx.OtherModuleName(to))
return false
}
return true
})
}
+type MinSdkVersionFromValueContext interface {
+ Config() Config
+ DeviceConfig() DeviceConfig
+ ModuleErrorContext
+}
+
+// Returns nil (success) if this module should support the given sdk version. Returns an
+// error if not. No default implementation is provided for this method. A module type
+// implementing this interface should provide an implementation. A module supports an sdk
+// version when the module's min_sdk_version is equal to or less than the given sdk version.
+func ShouldSupportSdkVersion(ctx BaseModuleContext, module Module, sdkVersion ApiLevel) error {
+ info, ok := OtherModuleProvider(ctx, module, CommonModuleInfoProvider)
+ if !ok || info.MinSdkVersionSupported.IsNone() {
+ return fmt.Errorf("min_sdk_version is not specified")
+ }
+ minVer := info.MinSdkVersionSupported
+
+ if minVer.GreaterThan(sdkVersion) {
+ return fmt.Errorf("newer SDK(%v)", minVer)
+ }
+
+ return nil
+}
+
// Construct ApiLevel object from min_sdk_version string value
-func MinSdkVersionFromValue(ctx EarlyModuleContext, value string) ApiLevel {
+func MinSdkVersionFromValue(ctx MinSdkVersionFromValueContext, value string) ApiLevel {
if value == "" {
return NoneApiLevel
}
@@ -880,3 +820,21 @@
// to generate the mainline module prebuilt.
Prebuilt_info_file_path string `json:",omitempty"`
}
+
+// FragmentInApexTag is embedded into a dependency tag to allow apex modules to annotate
+// their fragments in a way that allows the java bootclasspath modules to traverse from
+// the apex to the fragment.
+type FragmentInApexTag struct{}
+
+func (FragmentInApexTag) isFragmentInApexTag() {}
+
+type isFragmentInApexTagIntf interface {
+ isFragmentInApexTag()
+}
+
+// IsFragmentInApexTag returns true if the dependency tag embeds FragmentInApexTag,
+// signifying that it is a dependency from an apex module to its fragment.
+func IsFragmentInApexTag(tag blueprint.DependencyTag) bool {
+ _, ok := tag.(isFragmentInApexTagIntf)
+ return ok
+}
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index ce34278..fe7a835 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -104,19 +104,8 @@
AcDepTag = apexContributionsDepTag{}
)
-// Creates a dep to each selected apex_contributions
-func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) {
- // 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.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...)
- }
-}
-
// Set PrebuiltSelectionInfoProvider in post deps phase
-func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
+func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BottomUpMutatorContext) {
addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
for _, content := range m.Contents() {
// Verify that the module listed in contents exists in the tree
@@ -135,13 +124,23 @@
}
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()) {
+ deps := ctx.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...)
+ for _, child := range deps {
+ if child == nil {
+ continue
+ }
+ 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/apex_test.go b/android/apex_test.go
deleted file mode 100644
index 78597b2..0000000
--- a/android/apex_test.go
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
- "reflect"
- "testing"
-)
-
-func Test_mergeApexVariations(t *testing.T) {
- const (
- ForPrebuiltApex = true
- NotForPrebuiltApex = false
- )
- tests := []struct {
- name string
- in []ApexInfo
- wantMerged []ApexInfo
- wantAliases [][2]string
- }{
- {
- name: "single",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- },
- },
- {
- name: "merge",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo", "bar"},
- }},
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge version",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: uncheckedFinalApiLevel(30),
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "apex30",
- MinSdkVersion: uncheckedFinalApiLevel(30),
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex30"},
- },
- },
- {
- name: "merge updatable",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge when for prebuilt_apex",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- // This one should not be merged in with the others because it is for
- // a prebuilt_apex.
- {
- ApexVariationName: "baz",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"baz"},
- ForPrebuiltApex: ForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "baz",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"baz"},
- ForPrebuiltApex: ForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "merge different UsePlatformApis but don't allow using platform api",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "merge same UsePlatformApis and allow using platform api",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- gotMerged, gotAliases := mergeApexVariations(tt.in)
- if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
- t.Errorf("mergeApexVariations() gotMerged = %v, want %v", gotMerged, tt.wantMerged)
- }
- if !reflect.DeepEqual(gotAliases, tt.wantAliases) {
- t.Errorf("mergeApexVariations() gotAliases = %v, want %v", gotAliases, tt.wantAliases)
- }
- })
- }
-}
diff --git a/android/api_levels.go b/android/api_levels.go
index 2b1d01d..c83fae8 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -19,6 +19,8 @@
"fmt"
"strconv"
"strings"
+
+ "github.com/google/blueprint/gobtools"
)
func init() {
@@ -52,6 +54,34 @@
isPreview bool
}
+type apiLevelGob struct {
+ Value string
+ Number int
+ IsPreview bool
+}
+
+func (a *ApiLevel) ToGob() *apiLevelGob {
+ return &apiLevelGob{
+ Value: a.value,
+ Number: a.number,
+ IsPreview: a.isPreview,
+ }
+}
+
+func (a *ApiLevel) FromGob(data *apiLevelGob) {
+ a.value = data.Value
+ a.number = data.Number
+ a.isPreview = data.IsPreview
+}
+
+func (a ApiLevel) GobEncode() ([]byte, error) {
+ return gobtools.CustomGobEncode[apiLevelGob](&a)
+}
+
+func (a *ApiLevel) GobDecode(data []byte) error {
+ return gobtools.CustomGobDecode[apiLevelGob](data, a)
+}
+
func (this ApiLevel) FinalInt() int {
if this.IsInvalid() {
panic(fmt.Errorf("%v is not a recognized api_level\n", this))
@@ -252,6 +282,9 @@
isPreview: true,
}
+// A special ApiLevel that all modules should at least support.
+var MinApiLevel = ApiLevel{number: 1}
+
// Sentinel ApiLevel to validate that an apiLevel is either an int or a recognized codename.
var InvalidApiLevel = NewInvalidApiLevel("invalid")
@@ -311,7 +344,7 @@
// ApiLevelFrom converts the given string `raw` to an ApiLevel.
// If `raw` is invalid (empty string, unrecognized codename etc.) it returns an invalid ApiLevel
-func ApiLevelFrom(ctx PathContext, raw string) ApiLevel {
+func ApiLevelFrom(ctx ConfigContext, raw string) ApiLevel {
ret, err := ApiLevelFromUser(ctx, raw)
if err != nil {
return NewInvalidApiLevel(raw)
@@ -333,7 +366,7 @@
//
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
-func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
+func ApiLevelFromUser(ctx ConfigContext, raw string) (ApiLevel, error) {
return ApiLevelFromUserWithConfig(ctx.Config(), raw)
}
@@ -413,7 +446,7 @@
// Converts an API level string `raw` into an ApiLevel in the same method as
// `ApiLevelFromUser`, but the input is assumed to have no errors and any errors
// will panic instead of returning an error.
-func ApiLevelOrPanic(ctx PathContext, raw string) ApiLevel {
+func ApiLevelOrPanic(ctx ConfigContext, raw string) ApiLevel {
value, err := ApiLevelFromUser(ctx, raw)
if err != nil {
panic(err.Error())
@@ -465,6 +498,7 @@
"Tiramisu": 33,
"UpsideDownCake": 34,
"VanillaIceCream": 35,
+ "Baklava": 36,
}, nil
}
diff --git a/android/arch.go b/android/arch.go
index 3cd6e4b..d6b2971 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1553,7 +1553,7 @@
config.BuildOS = func() OsType {
switch runtime.GOOS {
case "linux":
- if Bool(config.productVariables.HostMusl) {
+ if Bool(config.productVariables.HostMusl) || runtime.GOARCH == "arm64" {
return LinuxMusl
}
return Linux
@@ -1565,11 +1565,25 @@
}()
config.BuildArch = func() ArchType {
- switch runtime.GOARCH {
- case "amd64":
- return X86_64
+ switch runtime.GOOS {
+ case "linux":
+ switch runtime.GOARCH {
+ case "amd64":
+ return X86_64
+ case "arm64":
+ return Arm64
+ default:
+ panic(fmt.Sprintf("unsupported arch: %s", runtime.GOARCH))
+ }
+ case "darwin":
+ switch runtime.GOARCH {
+ case "amd64":
+ return X86_64
+ default:
+ panic(fmt.Sprintf("unsupported arch: %s", runtime.GOARCH))
+ }
default:
- panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH))
+ panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
}
}()
diff --git a/android/arch_list.go b/android/arch_list.go
index 389f194..8659549 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -27,6 +27,8 @@
"armv8-2a-dotprod",
"armv9-a",
"armv9-2a",
+ "armv9-3a",
+ "armv9-4a",
},
X86: {
"alderlake",
@@ -151,6 +153,12 @@
"armv9-2a": {
"dotprod",
},
+ "armv9-3a": {
+ "dotprod",
+ },
+ "armv9-4a": {
+ "dotprod",
+ },
},
X86: {
"alderlake": {
diff --git a/android/arch_test.go b/android/arch_test.go
index 7914884..adb655f 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -432,7 +432,7 @@
var ret []string
variants := ctx.ModuleVariantsForTests(name)
for _, variant := range variants {
- m := ctx.ModuleForTests(name, variant)
+ m := ctx.ModuleForTests(t, name, variant)
if m.Module().Enabled(PanickingConfigAndErrorContext(ctx)) {
ret = append(ret, variant)
}
@@ -442,7 +442,7 @@
moduleMultiTargets := func(ctx *TestContext, name string, variant string) []string {
var ret []string
- targets := ctx.ModuleForTests(name, variant).Module().MultiTargets()
+ targets := ctx.ModuleForTests(t, name, variant).Module().MultiTargets()
for _, t := range targets {
ret = append(ret, t.String())
}
@@ -546,7 +546,7 @@
var ret []string
variants := ctx.ModuleVariantsForTests(name)
for _, variant := range variants {
- m := ctx.ModuleForTests(name, variant)
+ m := ctx.ModuleForTests(t, name, variant)
if m.Module().Enabled(PanickingConfigAndErrorContext(ctx)) {
ret = append(ret, variant)
}
@@ -758,7 +758,7 @@
for _, want := range tt.results {
t.Run(want.module+"_"+want.variant, func(t *testing.T) {
- got := result.ModuleForTests(want.module, want.variant).Module().(*testArchPropertiesModule).properties.A
+ got := result.ModuleForTests(t, want.module, want.variant).Module().(*testArchPropertiesModule).properties.A
AssertArrayString(t, "arch mutator property", want.property, got)
})
}
diff --git a/android/base_module_context.go b/android/base_module_context.go
index 06819d6..5cb9e71 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -34,8 +34,6 @@
blueprintBaseModuleContext() blueprint.BaseModuleContext
- EqualModules(m1, m2 Module) bool
-
// OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
// It is intended for use inside the visit functions of Visit* and WalkDeps.
OtherModuleName(m blueprint.Module) string
@@ -53,6 +51,9 @@
// dependencies on the module being visited, it returns the dependency tag used for the current dependency.
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+ // OtherModuleSubDir returns the string representing the variations of a module.
+ OtherModuleSubDir(m blueprint.Module) string
+
// OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
// passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
OtherModuleExists(name string) bool
@@ -88,6 +89,11 @@
// This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+ // OtherModuleHasProvider returns true if the module has the given provider set. This
+ // can avoid copying the provider if the caller only cares about the existence of
+ // the provider.
+ OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool
+
// OtherModuleIsAutoGenerated returns true if the module is auto generated by another module
// instead of being defined in Android.bp file.
OtherModuleIsAutoGenerated(m blueprint.Module) bool
@@ -110,15 +116,14 @@
GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
+ GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy
+
// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
// none exists. It panics if the dependency does not have the specified tag. It skips any
// dependencies that are not an android.Module.
GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module
- // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
- // name, or nil if none exists. If there are multiple dependencies on the same module it returns
- // the first DependencyTag.
- GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+ GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy
// VisitDirectDeps calls visit for each direct dependency. If there are multiple
// direct dependencies on the same module visit will be called multiple times on that module
@@ -255,14 +260,17 @@
}
func getWrappedModule(module blueprint.Module) blueprint.Module {
+ if mp, isProxy := module.(*ModuleProxy); isProxy {
+ return mp.module
+ }
if mp, isProxy := module.(ModuleProxy); isProxy {
return mp.module
}
return module
}
-func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
- return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
+func EqualModules(m1, m2 Module) bool {
+ return blueprint.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
}
func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
@@ -277,6 +285,9 @@
func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
}
+func (b *baseModuleContext) OtherModuleSubDir(m blueprint.Module) string {
+ return b.bp.OtherModuleSubDir(getWrappedModule(m))
+}
func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
return b.bp.OtherModuleDependencyVariantExists(variations, name)
@@ -292,7 +303,11 @@
}
func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
- return b.bp.OtherModuleProvider(m, provider)
+ return b.bp.OtherModuleProvider(getWrappedModule(m), provider)
+}
+
+func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.AnyProviderKey) bool {
+ return b.bp.OtherModuleHasProvider(getWrappedModule(m), provider)
}
func (b *baseModuleContext) OtherModuleIsAutoGenerated(m blueprint.Module) bool {
@@ -314,6 +329,13 @@
return nil
}
+func (b *baseModuleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
+ if module := b.bp.GetDirectDepProxyWithTag(name, tag); module != nil {
+ return &ModuleProxy{*module}
+ }
+ return nil
+}
+
func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
return b.bp
}
@@ -388,7 +410,7 @@
return &aModule
}
- if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled {
+ if !OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).Enabled {
if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
if b.Config().AllowMissingDependencies() {
b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
@@ -402,53 +424,30 @@
return &aModule
}
-type dep struct {
- mod blueprint.Module
- tag blueprint.DependencyTag
-}
-
-func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
- var deps []dep
+func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []Module {
+ var deps []Module
b.VisitDirectDeps(func(module Module) {
if module.base().BaseModuleName() == name {
returnedTag := b.bp.OtherModuleDependencyTag(module)
if tag == nil || returnedTag == tag {
- deps = append(deps, dep{module, returnedTag})
+ deps = append(deps, module)
}
}
})
return deps
}
-func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
- deps := b.getDirectDepsInternal(name, tag)
- if len(deps) == 1 {
- return deps[0].mod, deps[0].tag
- } else if len(deps) >= 2 {
- panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
- name, b.ModuleName()))
- } else {
- return nil, nil
- }
-}
-
-func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
- foundDeps := b.getDirectDepsInternal(name, nil)
- deps := map[blueprint.Module]bool{}
- for _, dep := range foundDeps {
- deps[dep.mod] = true
- }
- if len(deps) == 1 {
- return foundDeps[0].mod, foundDeps[0].tag
- } else if len(deps) >= 2 {
- // this could happen if two dependencies have the same name in different namespaces
- // TODO(b/186554727): this should not occur if namespaces are handled within
- // getDirectDepsInternal.
- panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
- name, b.ModuleName()))
- } else {
- return nil, nil
- }
+func (b *baseModuleContext) getDirectDepsProxyInternal(name string, tag blueprint.DependencyTag) []ModuleProxy {
+ var deps []ModuleProxy
+ b.VisitDirectDepsProxy(func(module ModuleProxy) {
+ if OtherModulePointerProviderOrDefault(b, module, CommonModuleInfoProvider).BaseModuleName == name {
+ returnedTag := b.OtherModuleDependencyTag(module)
+ if tag == nil || returnedTag == tag {
+ deps = append(deps, module)
+ }
+ }
+ })
+ return deps
}
func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
@@ -461,11 +460,14 @@
return deps
}
-// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
-// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
-// first DependencyTag.
-func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
- return b.getDirectDepFirstTag(name)
+func (b *baseModuleContext) GetDirectDepsProxyWithTag(tag blueprint.DependencyTag) []ModuleProxy {
+ var deps []ModuleProxy
+ b.VisitDirectDepsProxy(func(module ModuleProxy) {
+ if b.OtherModuleDependencyTag(module) == tag {
+ deps = append(deps, module)
+ }
+ })
+ return deps
}
func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
diff --git a/android/build_prop_test.go b/android/build_prop_test.go
index e75975a..e136a1a 100644
--- a/android/build_prop_test.go
+++ b/android/build_prop_test.go
@@ -36,6 +36,6 @@
res := GroupFixturePreparers(
FixtureRegisterWithContext(registerBuildPropComponents),
).RunTestWithBp(t, bp)
- buildPropCmd := res.ModuleForTests("vendor-build.prop", "").Rule("vendor-build.prop_.vendor-build.prop").RuleParams.Command
+ buildPropCmd := res.ModuleForTests(t, "vendor-build.prop", "").Rule("vendor-build.prop_.vendor-build.prop").RuleParams.Command
AssertStringDoesContain(t, "Could not find android-info in prop files of vendor build.prop", buildPropCmd, "--prop-files=out/soong/.intermediates/board-info/android-info.prop")
}
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 0b876c3..16a3853 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -18,7 +18,9 @@
"bytes"
"encoding/csv"
"fmt"
+ "path/filepath"
"slices"
+ "sort"
"strconv"
"strings"
@@ -43,6 +45,7 @@
STATIC_DEP_FILES string
WHOLE_STATIC_DEPS string
WHOLE_STATIC_DEP_FILES string
+ HEADER_LIBS string
LICENSES string
// module_type=package
@@ -71,6 +74,7 @@
"static_dep_files",
"whole_static_deps",
"whole_static_dep_files",
+ "header_libs",
"licenses",
"pkg_default_applicable_licenses",
@@ -106,6 +110,8 @@
ComplianceMetadataProp.WHOLE_STATIC_DEPS,
// Space separated file paths of whole static dependencies
ComplianceMetadataProp.WHOLE_STATIC_DEP_FILES,
+ // Space separated modules name of header libs
+ ComplianceMetadataProp.HEADER_LIBS,
ComplianceMetadataProp.LICENSES,
// module_type=package
ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES,
@@ -123,27 +129,37 @@
// dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility
// methods to get/set properties' values.
type ComplianceMetadataInfo struct {
- properties map[string]string
+ properties map[string]string
+ filesContained []string
+ prebuiltFilesCopied []string
}
type complianceMetadataInfoGob struct {
- Properties map[string]string
+ Properties map[string]string
+ FilesContained []string
+ PrebuiltFilesCopied []string
}
func NewComplianceMetadataInfo() *ComplianceMetadataInfo {
return &ComplianceMetadataInfo{
- properties: map[string]string{},
+ properties: map[string]string{},
+ filesContained: make([]string, 0),
+ prebuiltFilesCopied: make([]string, 0),
}
}
func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob {
return &complianceMetadataInfoGob{
- Properties: m.properties,
+ Properties: m.properties,
+ FilesContained: m.filesContained,
+ PrebuiltFilesCopied: m.prebuiltFilesCopied,
}
}
func (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) {
m.properties = data.Properties
+ m.filesContained = data.FilesContained
+ m.prebuiltFilesCopied = data.PrebuiltFilesCopied
}
func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
@@ -165,6 +181,22 @@
c.SetStringValue(propertyName, strings.TrimSpace(strings.Join(value, " ")))
}
+func (c *ComplianceMetadataInfo) SetFilesContained(files []string) {
+ c.filesContained = files
+}
+
+func (c *ComplianceMetadataInfo) GetFilesContained() []string {
+ return c.filesContained
+}
+
+func (c *ComplianceMetadataInfo) SetPrebuiltFilesCopied(files []string) {
+ c.prebuiltFilesCopied = files
+}
+
+func (c *ComplianceMetadataInfo) GetPrebuiltFilesCopied() []string {
+ return c.prebuiltFilesCopied
+}
+
func (c *ComplianceMetadataInfo) getStringValue(propertyName string) string {
if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
@@ -271,16 +303,18 @@
writerToCsv(csvWriter, columnNames)
rowId := -1
- ctx.VisitAllModules(func(module Module) {
- if !module.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider)
+ if !commonInfo.Enabled {
return
}
+
moduleType := ctx.ModuleType(module)
if moduleType == "package" {
metadataMap := map[string]string{
ComplianceMetadataProp.NAME: ctx.ModuleName(module),
ComplianceMetadataProp.MODULE_TYPE: ctx.ModuleType(module),
- ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES: strings.Join(module.base().primaryLicensesProperty.getStrings(), " "),
+ ComplianceMetadataProp.PKG_DEFAULT_APPLICABLE_LICENSES: strings.Join(commonInfo.PrimaryLicensesProperty.getStrings(), " "),
}
rowId = rowId + 1
metadata := []string{strconv.Itoa(rowId)}
@@ -290,8 +324,7 @@
writerToCsv(csvWriter, metadata)
return
}
- if provider, ok := ctx.otherModuleProvider(module, ComplianceMetadataProvider); ok {
- metadataInfo := provider.(*ComplianceMetadataInfo)
+ if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok {
rowId = rowId + 1
metadata := []string{strconv.Itoa(rowId)}
for _, propertyName := range COMPLIANCE_METADATA_PROPS {
@@ -311,6 +344,44 @@
makeMetadataCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-metadata.csv")
makeModulesCsv := PathForOutput(ctx, "compliance-metadata", deviceProduct, "make-modules.csv")
+ productOutPath := filepath.Join(ctx.Config().OutDir(), "target", "product", String(ctx.Config().productVariables.DeviceName))
+ if !ctx.Config().KatiEnabled() {
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ // In soong-only build the installed file list is from android_device module
+ if androidDeviceInfo, ok := OtherModuleProvider(ctx, module, AndroidDeviceInfoProvider); ok && androidDeviceInfo.Main_device {
+ if metadataInfo, ok := OtherModuleProvider(ctx, module, ComplianceMetadataProvider); ok {
+ if len(metadataInfo.filesContained) > 0 || len(metadataInfo.prebuiltFilesCopied) > 0 {
+ allFiles := make([]string, 0, len(metadataInfo.filesContained)+len(metadataInfo.prebuiltFilesCopied))
+ allFiles = append(allFiles, metadataInfo.filesContained...)
+ prebuiltFilesSrcDest := make(map[string]string)
+ for _, srcDestPair := range metadataInfo.prebuiltFilesCopied {
+ prebuiltFilePath := filepath.Join(productOutPath, strings.Split(srcDestPair, ":")[1])
+ allFiles = append(allFiles, prebuiltFilePath)
+ prebuiltFilesSrcDest[prebuiltFilePath] = srcDestPair
+ }
+ sort.Strings(allFiles)
+
+ csvHeaders := "installed_file,module_path,is_soong_module,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,static_libs,whole_static_libs,license_text"
+ csvContent := make([]string, 0, len(allFiles)+1)
+ csvContent = append(csvContent, csvHeaders)
+ for _, file := range allFiles {
+ if _, ok := prebuiltFilesSrcDest[file]; ok {
+ srcDestPair := prebuiltFilesSrcDest[file]
+ csvContent = append(csvContent, file+",,,,"+srcDestPair+",,,,,")
+ } else {
+ csvContent = append(csvContent, file+",,Y,,,,,,,")
+ }
+ }
+
+ WriteFileRuleVerbatim(ctx, makeMetadataCsv, strings.Join(csvContent, "\n"))
+ WriteFileRuleVerbatim(ctx, makeModulesCsv, "name,module_path,module_class,module_type,static_libs,whole_static_libs,built_files,installed_files")
+ }
+ return
+ }
+ }
+ })
+ }
+
// Import metadata from Make and Soong to sqlite3 database
complianceMetadataDb := PathForOutput(ctx, "compliance-metadata", deviceProduct, "compliance-metadata.db")
ctx.Build(pctx, BuildParams{
diff --git a/android/config.go b/android/config.go
index b811c55..b92eb7e 100644
--- a/android/config.go
+++ b/android/config.go
@@ -22,6 +22,7 @@
"fmt"
"os"
"path/filepath"
+ "reflect"
"runtime"
"strconv"
"strings"
@@ -83,6 +84,7 @@
OutDir string
SoongOutDir string
SoongVariables string
+ KatiSuffix string
ModuleGraphFile string
ModuleActionsFile string
@@ -107,6 +109,10 @@
const testKeyDir = "build/make/target/product/security"
+func (c Config) genericConfig() Config {
+ return Config{c.config.genericConfig}
+}
+
// SoongOutDir returns the build output directory for the configuration.
func (c Config) SoongOutDir() string {
return c.soongOutDir
@@ -199,6 +205,11 @@
return c.config.productVariables.ReleaseAconfigValueSets
}
+// If native modules should have symbols stripped by default. Default false, enabled for build tools
+func (c Config) StripByDefault() bool {
+ return proptools.Bool(c.config.productVariables.StripByDefault)
+}
+
func (c Config) ReleaseAconfigExtraReleaseConfigs() []string {
result := []string{}
if val, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"]; ok {
@@ -232,11 +243,6 @@
return c.config.productVariables.ReleaseAconfigFlagDefaultPermission
}
-// Enable object size sanitizer
-func (c Config) ReleaseBuildObjectSizeSanitizer() bool {
- return c.config.productVariables.GetBuildFlagBool("RELEASE_BUILD_OBJECT_SIZE_SANITIZER")
-}
-
// The flag indicating behavior for the tree wrt building modules or using prebuilts
// derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE
func (c Config) ReleaseDefaultModuleBuildFromSource() bool {
@@ -289,6 +295,14 @@
return c.config.productVariables.GetBuildFlagBool("RELEASE_USE_SYSTEM_FEATURE_BUILD_FLAGS")
}
+func (c Config) ReleaseFingerprintAconfigPackages() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_FINGERPRINT_ACONFIG_PACKAGES")
+}
+
+func (c Config) ReleaseAconfigCheckApiLevel() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_ACONFIG_CHECK_API_LEVEL")
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -345,6 +359,7 @@
// Changes behavior based on whether Kati runs after soong_build, or if soong_build
// runs standalone.
katiEnabled bool
+ katiSuffix string
captureBuild bool // true for tests, saves build parameters for each module
ignoreEnvironment bool // true for tests, returns empty from all Getenv calls
@@ -362,7 +377,7 @@
// regenerate build.ninja.
ninjaFileDepsSet sync.Map
- OncePer
+ *OncePer
// If buildFromSourceStub is true then the Java API stubs are
// built from the source Java files, not the signature text files.
@@ -372,18 +387,44 @@
// modules that aren't mixed-built for at least one variant will cause a build
// failure
ensureAllowlistIntegrity bool
+
+ // If isGeneric is true, this config is the generic config.
+ isGeneric bool
+
+ // InstallPath requires the device name.
+ // This is only for the installPath.
+ deviceNameToInstall *string
+
+ // Copy of this config struct but some product-specific variables are
+ // replaced with the generic configuration values.
+ genericConfig *config
}
type partialCompileFlags struct {
- // Is partial compilation enabled at all?
- enabled bool
-
// Whether to use d8 instead of r8
- use_d8 bool
+ Use_d8 bool
+
+ // Whether to disable stub validation. This is slightly more surgical
+ // than DISABLE_STUB_VALIDATION, in that it only applies to partial
+ // compile builds.
+ Disable_stub_validation bool
+
+ // Whether to disable api lint.
+ Disable_api_lint bool
// Add others as needed.
}
+// These are the flags when `SOONG_PARTIAL_COMPILE` is empty or not set.
+var defaultPartialCompileFlags = partialCompileFlags{}
+
+// These are the flags when `SOONG_PARTIAL_COMPILE=true`.
+var enabledPartialCompileFlags = partialCompileFlags{
+ Use_d8: true,
+ Disable_stub_validation: false,
+ Disable_api_lint: false,
+}
+
type deviceConfig struct {
config *config
OncePer
@@ -417,11 +458,6 @@
// To add a new feature to the list, add the field in the struct
// `partialCompileFlags` above, and then add the name of the field in the
// switch statement below.
-var defaultPartialCompileFlags = partialCompileFlags{
- // Set any opt-out flags here. Opt-in flags are off by default.
- enabled: false,
-}
-
func (c *config) parsePartialCompileFlags(isEngBuild bool) (partialCompileFlags, error) {
if !isEngBuild {
return partialCompileFlags{}, nil
@@ -461,16 +497,31 @@
state = "+"
}
switch tok {
+ case "all":
+ // Turn on **all** of the flags.
+ ret = partialCompileFlags{
+ Use_d8: true,
+ Disable_stub_validation: true,
+ Disable_api_lint: true,
+ }
case "true":
- ret = defaultPartialCompileFlags
- ret.enabled = true
+ ret = enabledPartialCompileFlags
case "false":
// Set everything to false.
ret = partialCompileFlags{}
- case "enabled":
- ret.enabled = makeVal(state, defaultPartialCompileFlags.enabled)
+
+ case "api_lint", "enable_api_lint":
+ ret.Disable_api_lint = !makeVal(state, !defaultPartialCompileFlags.Disable_api_lint)
+ case "disable_api_lint":
+ ret.Disable_api_lint = makeVal(state, defaultPartialCompileFlags.Disable_api_lint)
+
+ case "stub_validation", "enable_stub_validation":
+ ret.Disable_stub_validation = !makeVal(state, !defaultPartialCompileFlags.Disable_stub_validation)
+ case "disable_stub_validation":
+ ret.Disable_stub_validation = makeVal(state, defaultPartialCompileFlags.Disable_stub_validation)
+
case "use_d8":
- ret.use_d8 = makeVal(state, defaultPartialCompileFlags.use_d8)
+ ret.Use_d8 = makeVal(state, defaultPartialCompileFlags.Use_d8)
default:
return partialCompileFlags{}, fmt.Errorf("Unknown SOONG_PARTIAL_COMPILE value: %v", tok)
}
@@ -604,11 +655,9 @@
}
}
-// NewConfig creates a new Config object. The srcDir argument specifies the path
-// to the root source directory. It also loads the config file, if found.
-func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) {
+func initConfig(cmdArgs CmdArgs, availableEnv map[string]string) (*config, error) {
// Make a config with default options.
- config := &config{
+ newConfig := &config{
ProductVariablesFileName: cmdArgs.SoongVariables,
env: availableEnv,
@@ -616,75 +665,78 @@
outDir: cmdArgs.OutDir,
soongOutDir: cmdArgs.SoongOutDir,
runGoTests: cmdArgs.RunGoTests,
+ katiSuffix: cmdArgs.KatiSuffix,
multilibConflicts: make(map[ArchType]bool),
moduleListFile: cmdArgs.ModuleListFile,
fs: pathtools.NewOsFs(absSrcDir),
+ OncePer: &OncePer{},
+
buildFromSourceStub: cmdArgs.BuildFromSourceStub,
}
variant, ok := os.LookupEnv("TARGET_BUILD_VARIANT")
isEngBuild := !ok || variant == "eng"
- config.deviceConfig = &deviceConfig{
- config: config,
+ newConfig.deviceConfig = &deviceConfig{
+ config: newConfig,
}
// Soundness check of the build and source directories. This won't catch strange
// configurations with symlinks, but at least checks the obvious case.
absBuildDir, err := filepath.Abs(cmdArgs.SoongOutDir)
if err != nil {
- return Config{}, err
+ return &config{}, err
}
absSrcDir, err := filepath.Abs(".")
if err != nil {
- return Config{}, err
+ return &config{}, err
}
if strings.HasPrefix(absSrcDir, absBuildDir) {
- return Config{}, fmt.Errorf("Build dir must not contain source directory")
+ return &config{}, fmt.Errorf("Build dir must not contain source directory")
}
// Load any configurable options from the configuration file
- err = loadConfig(config)
+ err = loadConfig(newConfig)
if err != nil {
- return Config{}, err
+ return &config{}, err
}
KatiEnabledMarkerFile := filepath.Join(cmdArgs.SoongOutDir, ".soong.kati_enabled")
if _, err := os.Stat(absolutePath(KatiEnabledMarkerFile)); err == nil {
- config.katiEnabled = true
+ newConfig.katiEnabled = true
}
- determineBuildOS(config)
+ determineBuildOS(newConfig)
// Sets up the map of target OSes to the finer grained compilation targets
// that are configured from the product variables.
- targets, err := decodeTargetProductVariables(config)
+ targets, err := decodeTargetProductVariables(newConfig)
if err != nil {
- return Config{}, err
+ return &config{}, err
}
- config.partialCompileFlags, err = config.parsePartialCompileFlags(isEngBuild)
+ newConfig.partialCompileFlags, err = newConfig.parsePartialCompileFlags(isEngBuild)
if err != nil {
- return Config{}, err
+ return &config{}, err
}
// Make the CommonOS OsType available for all products.
targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
var archConfig []archConfig
- if config.NdkAbis() {
+ if newConfig.NdkAbis() {
archConfig = getNdkAbisConfig()
- } else if config.AmlAbis() {
+ } else if newConfig.AmlAbis() {
archConfig = getAmlAbisConfig()
}
if archConfig != nil {
androidTargets, err := decodeAndroidArchSettings(archConfig)
if err != nil {
- return Config{}, err
+ return &config{}, err
}
targets[Android] = androidTargets
}
@@ -692,37 +744,113 @@
multilib := make(map[string]bool)
for _, target := range targets[Android] {
if seen := multilib[target.Arch.ArchType.Multilib]; seen {
- config.multilibConflicts[target.Arch.ArchType] = true
+ newConfig.multilibConflicts[target.Arch.ArchType] = true
}
multilib[target.Arch.ArchType.Multilib] = true
}
// Map of OS to compilation targets.
- config.Targets = targets
+ newConfig.Targets = targets
// Compilation targets for host tools.
- config.BuildOSTarget = config.Targets[config.BuildOS][0]
- config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0]
+ newConfig.BuildOSTarget = newConfig.Targets[newConfig.BuildOS][0]
+ newConfig.BuildOSCommonTarget = getCommonTargets(newConfig.Targets[newConfig.BuildOS])[0]
// Compilation targets for Android.
- if len(config.Targets[Android]) > 0 {
- config.AndroidCommonTarget = getCommonTargets(config.Targets[Android])[0]
- config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0]
+ if len(newConfig.Targets[Android]) > 0 {
+ newConfig.AndroidCommonTarget = getCommonTargets(newConfig.Targets[Android])[0]
+ newConfig.AndroidFirstDeviceTarget = FirstTarget(newConfig.Targets[Android], "lib64", "lib32")[0]
}
setBuildMode := func(arg string, mode SoongBuildMode) {
if arg != "" {
- if config.BuildMode != AnalysisNoBazel {
+ if newConfig.BuildMode != AnalysisNoBazel {
fmt.Fprintf(os.Stderr, "buildMode is already set, illegal argument: %s", arg)
os.Exit(1)
}
- config.BuildMode = mode
+ newConfig.BuildMode = mode
}
}
setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
setBuildMode(cmdArgs.DocFile, GenerateDocFile)
- config.productVariables.Build_from_text_stub = boolPtr(config.BuildFromTextStub())
+ newConfig.productVariables.Build_from_text_stub = boolPtr(newConfig.BuildFromTextStub())
+
+ newConfig.deviceNameToInstall = newConfig.productVariables.DeviceName
+
+ return newConfig, err
+}
+
+// Replace variables in config.productVariables that have tags with "generic" key.
+// A generic tag may have a string or an int value for the generic configuration.
+// If the value is "unset", generic configuration will unset the variable.
+func overrideGenericConfig(config *config) {
+ config.genericConfig.isGeneric = true
+ type_pv := reflect.TypeOf(config.genericConfig.productVariables)
+ value_pv := reflect.ValueOf(&config.genericConfig.productVariables)
+ for i := range type_pv.NumField() {
+ type_pv_field := type_pv.Field(i)
+ generic_value := type_pv_field.Tag.Get("generic")
+ // If a product variable has an annotation of "generic" tag, use the
+ // value of the tag to set the generic variable.
+ if generic_value != "" {
+ value_pv_field := value_pv.Elem().Field(i)
+
+ if generic_value == "unset" {
+ // unset the product variable
+ value_pv_field.SetZero()
+ continue
+ }
+
+ kind_of_type_pv := type_pv_field.Type.Kind()
+ is_pointer := false
+ if kind_of_type_pv == reflect.Pointer {
+ is_pointer = true
+ kind_of_type_pv = type_pv_field.Type.Elem().Kind()
+ }
+
+ switch kind_of_type_pv {
+ case reflect.String:
+ if is_pointer {
+ value_pv_field.Set(reflect.ValueOf(stringPtr(generic_value)))
+ } else {
+ value_pv_field.Set(reflect.ValueOf(generic_value))
+ }
+ case reflect.Int:
+ generic_int, err := strconv.Atoi(generic_value)
+ if err != nil {
+ panic(fmt.Errorf("Only an int value can be assigned to int variable: %s", err))
+ }
+ if is_pointer {
+ value_pv_field.Set(reflect.ValueOf(intPtr(generic_int)))
+ } else {
+ value_pv_field.Set(reflect.ValueOf(generic_int))
+ }
+ default:
+ panic(fmt.Errorf("Unknown type to replace for generic variable: %s", &kind_of_type_pv))
+ }
+ }
+ }
+
+ // OncePer must be a singleton.
+ config.genericConfig.OncePer = config.OncePer
+ // keep the device name to get the install path.
+ config.genericConfig.deviceNameToInstall = config.deviceNameToInstall
+}
+
+// NewConfig creates a new Config object. It also loads the config file, if
+// found. The Config object includes a duplicated Config object in it for the
+// generic configuration that does not provide any product specific information.
+func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) {
+ config, err := initConfig(cmdArgs, availableEnv)
+ if err != nil {
+ return Config{}, err
+ }
+
+ // Initialize generic configuration.
+ config.genericConfig, err = initConfig(cmdArgs, availableEnv)
+ // Update product specific variables with the generic configuration.
+ overrideGenericConfig(config)
return Config{config}, err
}
@@ -764,11 +892,7 @@
// BlueprintToolLocation returns the directory containing build system tools
// from Blueprint, like soong_zip and merge_zips.
func (c *config) HostToolDir() string {
- if c.KatiEnabled() {
- return filepath.Join(c.outDir, "host", c.PrebuiltOS(), "bin")
- } else {
- return filepath.Join(c.soongOutDir, "host", c.PrebuiltOS(), "bin")
- }
+ return filepath.Join(c.outDir, "host", c.PrebuiltOS(), "bin")
}
func (c *config) HostToolPath(ctx PathContext, tool string) Path {
@@ -802,11 +926,18 @@
func (c *config) PrebuiltOS() string {
switch runtime.GOOS {
case "linux":
- return "linux-x86"
+ switch runtime.GOARCH {
+ case "amd64":
+ return "linux-x86"
+ case "arm64":
+ return "linux-arm64"
+ default:
+ panic(fmt.Errorf("Unknown GOARCH %s", runtime.GOARCH))
+ }
case "darwin":
return "darwin-x86"
default:
- panic("Unknown GOOS")
+ panic(fmt.Errorf("Unknown GOOS %s", runtime.GOOS))
}
}
@@ -907,7 +1038,7 @@
// require them to run and get the current build fingerprint. This ensures they
// don't rebuild on every incremental build when the build number changes.
func (c *config) BuildFingerprintFile(ctx PathContext) Path {
- return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildFingerprintFile))
+ return PathForArbitraryOutput(ctx, "target", "product", *c.deviceNameToInstall, String(c.productVariables.BuildFingerprintFile))
}
// BuildNumberFile returns the path to a text file containing metadata
@@ -935,7 +1066,7 @@
// 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))
+ return PathForArbitraryOutput(ctx, "target", "product", *c.deviceNameToInstall, String(c.productVariables.BuildThumbprintFile))
}
// DeviceName returns the name of the current device target.
@@ -983,6 +1114,10 @@
return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
}
+func (c *config) PlatformSdkVersionFull() string {
+ return proptools.StringDefault(c.productVariables.Platform_sdk_version_full, "")
+}
+
func (c *config) RawPlatformSdkVersion() *int {
return c.productVariables.Platform_sdk_version
}
@@ -1168,6 +1303,10 @@
return otaPaths
}
+func (c *config) ExtraOtaRecoveryKeys() []string {
+ return c.productVariables.ExtraOtaRecoveryKeys
+}
+
func (c *config) BuildKeys() string {
defaultCert := String(c.productVariables.DefaultAppCertificate)
if defaultCert == "" || defaultCert == filepath.Join(testKeyDir, "testkey") {
@@ -1317,7 +1456,16 @@
}
func (c *config) RunErrorProne() bool {
- return c.IsEnvTrue("RUN_ERROR_PRONE")
+ return c.IsEnvTrue("RUN_ERROR_PRONE") || c.RunErrorProneInline()
+}
+
+// Returns if the errorprone build should be run "inline", that is, using errorprone as part
+// of the main javac compilation instead of its own separate compilation. This is good for CI
+// but bad for local development, because if you toggle errorprone+inline on/off it will repeatedly
+// clobber java files from the old configuration.
+func (c *config) RunErrorProneInline() bool {
+ value := strings.ToLower(c.Getenv("RUN_ERROR_PRONE"))
+ return c.IsEnvTrue("RUN_ERROR_PRONE_INLINE") || value == "inline"
}
// XrefCorpusName returns the Kythe cross-reference corpus name.
@@ -1503,6 +1651,10 @@
return c.productVariables.GetBuildFlagBool("RELEASE_BOARD_API_LEVEL_FROZEN")
}
+func (c *config) katiPackageMkDir() string {
+ return filepath.Join(c.soongOutDir, "kati_packaging"+c.katiSuffix)
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
@@ -2151,12 +2303,20 @@
return c.productVariables.GetBuildFlagBool("RELEASE_USE_OPTIMIZED_RESOURCE_SHRINKING_BY_DEFAULT")
}
-func (c *config) UseResourceProcessorByDefault() bool {
- return c.productVariables.GetBuildFlagBool("RELEASE_USE_RESOURCE_PROCESSOR_BY_DEFAULT")
+func (c *config) UseR8FullModeByDefault() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_R8_FULL_MODE_BY_DEFAULT")
}
-func (c *config) UseTransitiveJarsInClasspath() bool {
- return c.productVariables.GetBuildFlagBool("RELEASE_USE_TRANSITIVE_JARS_IN_CLASSPATH")
+func (c *config) UseR8OnlyRuntimeVisibleAnnotations() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_R8_ONLY_RUNTIME_VISIBLE_ANNOTATIONS")
+}
+
+func (c *config) UseR8StoreStoreFenceConstructorInlining() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_R8_STORE_STORE_FENCE_CONSTRUCTOR_INLINING")
+}
+
+func (c *config) UseR8GlobalCheckNotNullFlags() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_R8_GLOBAL_CHECK_NOT_NULL_FLAGS")
}
func (c *config) UseDexV41() bool {
@@ -2169,13 +2329,13 @@
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "com.android.adservices",
"RELEASE_APEX_CONTRIBUTIONS_APPSEARCH": "com.android.appsearch",
"RELEASE_APEX_CONTRIBUTIONS_ART": "com.android.art",
- "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH": "com.android.btservices",
+ "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH": "com.android.bt",
"RELEASE_APEX_CONTRIBUTIONS_CAPTIVEPORTALLOGIN": "",
"RELEASE_APEX_CONTRIBUTIONS_CELLBROADCAST": "com.android.cellbroadcast",
"RELEASE_APEX_CONTRIBUTIONS_CONFIGINFRASTRUCTURE": "com.android.configinfrastructure",
"RELEASE_APEX_CONTRIBUTIONS_CONNECTIVITY": "com.android.tethering",
"RELEASE_APEX_CONTRIBUTIONS_CONSCRYPT": "com.android.conscrypt",
- "RELEASE_APEX_CONTRIBUTIONS_CRASHRECOVERY": "",
+ "RELEASE_APEX_CONTRIBUTIONS_CRASHRECOVERY": "com.android.crashrecovery",
"RELEASE_APEX_CONTRIBUTIONS_DEVICELOCK": "com.android.devicelock",
"RELEASE_APEX_CONTRIBUTIONS_DOCUMENTSUIGOOGLE": "",
"RELEASE_APEX_CONTRIBUTIONS_EXTSERVICES": "com.android.extservices",
@@ -2186,9 +2346,10 @@
"RELEASE_APEX_CONTRIBUTIONS_MODULE_METADATA": "",
"RELEASE_APEX_CONTRIBUTIONS_NETWORKSTACKGOOGLE": "",
"RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS": "com.android.neuralnetworks",
+ "RELEASE_APEX_CONTRIBUTIONS_NFC": "com.android.nfcservices",
"RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION": "com.android.ondevicepersonalization",
"RELEASE_APEX_CONTRIBUTIONS_PERMISSION": "com.android.permission",
- "RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS": "",
+ "RELEASE_APEX_CONTRIBUTIONS_PROFILING": "com.android.profiling",
"RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING": "com.android.rkpd",
"RELEASE_APEX_CONTRIBUTIONS_RESOLV": "com.android.resolv",
"RELEASE_APEX_CONTRIBUTIONS_SCHEDULING": "com.android.scheduling",
@@ -2197,6 +2358,7 @@
"RELEASE_APEX_CONTRIBUTIONS_STATSD": "com.android.os.statsd",
"RELEASE_APEX_CONTRIBUTIONS_TELEMETRY_TVP": "",
"RELEASE_APEX_CONTRIBUTIONS_TZDATA": "com.android.tzdata",
+ "RELEASE_APEX_CONTRIBUTIONS_UPROBESTATS": "com.android.uprobestats",
"RELEASE_APEX_CONTRIBUTIONS_UWB": "com.android.uwb",
"RELEASE_APEX_CONTRIBUTIONS_WIFI": "com.android.wifi",
}
@@ -2239,10 +2401,18 @@
}
func (c *config) UseDebugArt() bool {
+ // If the ArtTargetIncludeDebugBuild product variable is set then return its value.
if c.productVariables.ArtTargetIncludeDebugBuild != nil {
return Bool(c.productVariables.ArtTargetIncludeDebugBuild)
}
+ // If the RELEASE_APEX_CONTRIBUTIONS_ART build flag is set to use a prebuilt ART apex
+ // then don't use the debug apex.
+ if val, ok := c.GetBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART"); ok && val != "" {
+ return false
+ }
+
+ // Default to the debug apex for eng builds.
return Bool(c.productVariables.Eng)
}
@@ -2266,10 +2436,6 @@
return PathsForSource(ctx, c.productVariables.VendorPropFiles)
}
-func (c *config) ExtraAllowedDepsTxt() string {
- return String(c.productVariables.ExtraAllowedDepsTxt)
-}
-
func (c *config) EnableUffdGc() string {
return String(c.productVariables.EnableUffdGc)
}
diff --git a/android/config_test.go b/android/config_test.go
index adb5ffa..81b7c3e 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -77,7 +77,7 @@
func TestProductConfigAnnotations(t *testing.T) {
err := validateConfigAnnotations(&ProductVariables{})
if err != nil {
- t.Errorf(err.Error())
+ t.Error(err.Error())
}
}
@@ -213,13 +213,18 @@
})
}
-func (p partialCompileFlags) updateEnabled(value bool) partialCompileFlags {
- p.enabled = value
+func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags {
+ p.Use_d8 = value
return p
}
-func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags {
- p.use_d8 = value
+func (p partialCompileFlags) updateDisableApiLint(value bool) partialCompileFlags {
+ p.Disable_api_lint = value
+ return p
+}
+
+func (p partialCompileFlags) updateDisableStubValidation(value bool) partialCompileFlags {
+ p.Disable_stub_validation = value
return p
}
@@ -239,12 +244,31 @@
}{
{"", true, defaultPartialCompileFlags},
{"false", true, partialCompileFlags{}},
- {"true", true, defaultPartialCompileFlags.updateEnabled(true)},
+ {"true", true, enabledPartialCompileFlags},
{"true", false, partialCompileFlags{}},
- {"true,use_d8", true, defaultPartialCompileFlags.updateEnabled(true).updateUseD8(true)},
- {"true,-use_d8", true, defaultPartialCompileFlags.updateEnabled(true).updateUseD8(false)},
+ {"all", true, partialCompileFlags{}.updateUseD8(true).updateDisableApiLint(true).updateDisableStubValidation(true)},
+
+ // This verifies both use_d8 and the processing order.
+ {"true,use_d8", true, enabledPartialCompileFlags.updateUseD8(true)},
+ {"true,-use_d8", true, enabledPartialCompileFlags.updateUseD8(false)},
{"use_d8,false", true, partialCompileFlags{}},
{"false,+use_d8", true, partialCompileFlags{}.updateUseD8(true)},
+
+ // disable_api_lint can be specified with any of 3 options.
+ {"false,-api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
+ {"false,-enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
+ {"false,+disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
+ {"false,+api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
+ {"false,+enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
+ {"false,-disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
+
+ // disable_stub_validation can be specified with any of 3 options.
+ {"false,-stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
+ {"false,-enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
+ {"false,+disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
+ {"false,+stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
+ {"false,+enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
+ {"false,-disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
}
for _, test := range tests {
@@ -257,3 +281,72 @@
})
}
}
+
+type configTestProperties struct {
+ Use_generic_config *bool
+}
+
+type configTestModule struct {
+ ModuleBase
+ properties configTestProperties
+}
+
+func (d *configTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ deviceName := ctx.Config().DeviceName()
+ if ctx.ModuleName() == "foo" {
+ if ctx.Module().UseGenericConfig() {
+ ctx.PropertyErrorf("use_generic_config", "must not be set for this test")
+ }
+ } else if ctx.ModuleName() == "bar" {
+ if !ctx.Module().UseGenericConfig() {
+ ctx.ModuleErrorf("\"use_generic_config: true\" must be set for this test")
+ }
+ }
+
+ if ctx.Module().UseGenericConfig() {
+ if deviceName != "generic" {
+ ctx.ModuleErrorf("Device name for this module must be \"generic\" but %q\n", deviceName)
+ }
+ } else {
+ if deviceName == "generic" {
+ ctx.ModuleErrorf("Device name for this module must not be \"generic\"\n")
+ }
+ }
+}
+
+func configTestModuleFactory() Module {
+ module := &configTestModule{}
+ module.AddProperties(&module.properties)
+ InitAndroidModule(module)
+ return module
+}
+
+var prepareForConfigTest = GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", configTestModuleFactory)
+ }),
+)
+
+func TestGenericConfig(t *testing.T) {
+ bp := `
+ test {
+ name: "foo",
+ }
+
+ test {
+ name: "bar",
+ use_generic_config: true,
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForConfigTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ foo := result.Module("foo", "").(*configTestModule)
+ bar := result.Module("bar", "").(*configTestModule)
+
+ AssertBoolEquals(t, "Do not use generic config", false, foo.UseGenericConfig())
+ AssertBoolEquals(t, "Use generic config", true, bar.UseGenericConfig())
+}
diff --git a/android/configurable_properties.go b/android/configurable_properties.go
index 2c794a1..bde33e9 100644
--- a/android/configurable_properties.go
+++ b/android/configurable_properties.go
@@ -7,7 +7,8 @@
// to indicate a "default" case.
func CreateSelectOsToBool(cases map[string]*bool) proptools.Configurable[bool] {
var resultCases []proptools.ConfigurableCase[bool]
- for pattern, value := range cases {
+ for _, pattern := range SortedKeys(cases) {
+ value := cases[pattern]
if pattern == "" {
resultCases = append(resultCases, proptools.NewConfigurableCase(
[]proptools.ConfigurablePattern{proptools.NewDefaultConfigurablePattern()},
diff --git a/android/configured_jars.go b/android/configured_jars.go
index c7b808f..657826e 100644
--- a/android/configured_jars.go
+++ b/android/configured_jars.go
@@ -264,7 +264,7 @@
subdir = filepath.Join("apex", apex, "javalib")
}
- if ostype.Class == Host {
+ if ostype.Class == Host || cfg.IsEnvTrue("ART_USE_SIMULATOR") {
paths[i] = filepath.Join(cfg.Getenv("OUT_DIR"), "host", cfg.PrebuiltOS(), subdir, name)
} else {
paths[i] = filepath.Join("/", subdir, name)
diff --git a/android/container.go b/android/container.go
index 27b17ed..547fe81 100644
--- a/android/container.go
+++ b/android/container.go
@@ -31,28 +31,25 @@
// and the corresponding functions are called from [exceptionHandleFunctionsTable] map.
// ----------------------------------------------------------------------------
-type exceptionHandleFunc func(ModuleContext, Module, Module) bool
+type exceptionHandleFunc func(ModuleContext, Module, ModuleProxy) bool
type StubsAvailableModule interface {
IsStubsModule() bool
}
// Returns true if the dependency module is a stubs module
-var depIsStubsModule exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool {
- if stubsModule, ok := dep.(StubsAvailableModule); ok {
- return stubsModule.IsStubsModule()
- }
- return false
+var depIsStubsModule exceptionHandleFunc = func(mctx ModuleContext, _ Module, dep ModuleProxy) bool {
+ return OtherModulePointerProviderOrDefault(mctx, dep, CommonModuleInfoProvider).IsStubsModule
}
// Returns true if the dependency module belongs to any of the apexes.
-var depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _, dep Module) bool {
+var depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _ Module, dep ModuleProxy) bool {
depContainersInfo, _ := getContainerModuleInfo(mctx, dep)
return InList(ApexContainer, depContainersInfo.belongingContainers)
}
// Returns true if the module and the dependent module belongs to common apexes.
-var belongsToCommonApexes exceptionHandleFunc = func(mctx ModuleContext, m, dep Module) bool {
+var belongsToCommonApexes exceptionHandleFunc = func(mctx ModuleContext, m Module, dep ModuleProxy) bool {
mContainersInfo, _ := getContainerModuleInfo(mctx, m)
depContainersInfo, _ := getContainerModuleInfo(mctx, dep)
@@ -62,7 +59,7 @@
// Returns true when all apexes that the module belongs to are non updatable.
// For an apex module to be allowed to depend on a non-apex partition module,
// all apexes that the module belong to must be non updatable.
-var belongsToNonUpdatableApex exceptionHandleFunc = func(mctx ModuleContext, m, _ Module) bool {
+var belongsToNonUpdatableApex exceptionHandleFunc = func(mctx ModuleContext, m Module, _ ModuleProxy) bool {
mContainersInfo, _ := getContainerModuleInfo(mctx, m)
return !mContainersInfo.UpdatableApex()
@@ -70,7 +67,7 @@
// Returns true if the dependency is added via dependency tags that are not used to tag dynamic
// dependency tags.
-var depIsNotDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool {
+var depIsNotDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m Module, dep ModuleProxy) bool {
mInstallable, _ := m.(InstallableModule)
depTag := ctx.OtherModuleDependencyTag(dep)
return !InList(depTag, mInstallable.DynamicDependencyTags())
@@ -79,7 +76,7 @@
// Returns true if the dependency is added via dependency tags that are not used to tag static
// or dynamic dependency tags. These dependencies do not affect the module in compile time or in
// runtime, thus are not significant enough to raise an error.
-var depIsNotStaticOrDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool {
+var depIsNotStaticOrDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m Module, dep ModuleProxy) bool {
mInstallable, _ := m.(InstallableModule)
depTag := ctx.OtherModuleDependencyTag(dep)
return !InList(depTag, append(mInstallable.StaticDependencyTags(), mInstallable.DynamicDependencyTags()...))
@@ -106,7 +103,7 @@
}
// Returns true when the dependency is globally allowlisted for inter-container dependency
-var depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool {
+var depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _ Module, dep ModuleProxy) bool {
return InList(dep.Name(), globallyAllowlistedDependencies)
}
@@ -170,8 +167,8 @@
}
var apexContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
- _, ok := ModuleProvider(mctx, AllApexInfoProvider)
- return ok
+ // TODO(b/394955484): a module can't determine the apexes it belongs to any more
+ return false
}
var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
@@ -197,10 +194,11 @@
func determineUnstableModule(mctx ModuleContext) bool {
module := mctx.Module()
+
unstableModule := module.Name() == "framework-minus-apex"
if installable, ok := module.(InstallableModule); ok {
for _, staticDepTag := range installable.StaticDependencyTags() {
- mctx.VisitDirectDepsWithTag(staticDepTag, func(dep Module) {
+ mctx.VisitDirectDepsProxyWithTag(staticDepTag, func(dep ModuleProxy) {
if unstableInfo, ok := OtherModuleProvider(mctx, dep, unstableInfoProvider); ok {
unstableModule = unstableModule || unstableInfo.ContainsPlatformPrivateApis
}
@@ -382,7 +380,7 @@
func (c *ContainersInfo) ApexNames() (ret []string) {
for _, apex := range c.belongingApexes {
- ret = append(ret, apex.InApexVariants...)
+ ret = append(ret, apex.BaseApexName)
}
slices.Sort(ret)
return ret
@@ -400,7 +398,7 @@
var ContainersInfoProvider = blueprint.NewProvider[ContainersInfo]()
-func satisfyAllowedExceptions(ctx ModuleContext, allowedExceptionLabels []exceptionHandleFuncLabel, m, dep Module) bool {
+func satisfyAllowedExceptions(ctx ModuleContext, allowedExceptionLabels []exceptionHandleFuncLabel, m Module, dep ModuleProxy) bool {
for _, label := range allowedExceptionLabels {
if exceptionHandleFunctionsTable[label](ctx, m, dep) {
return true
@@ -409,7 +407,7 @@
return false
}
-func (c *ContainersInfo) GetViolations(mctx ModuleContext, m, dep Module, depInfo ContainersInfo) []string {
+func (c *ContainersInfo) GetViolations(mctx ModuleContext, m Module, dep ModuleProxy, depInfo ContainersInfo) []string {
var violations []string
// Any containers that the module belongs to but the dependency does not belong to must be examined.
@@ -443,19 +441,15 @@
}
}
- var belongingApexes []ApexInfo
- if apexInfo, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- belongingApexes = apexInfo.ApexInfos
- }
-
return ContainersInfo{
belongingContainers: containers,
- belongingApexes: belongingApexes,
+ // TODO(b/394955484): a module can't determine the apexes it belongs to any more
+ belongingApexes: nil,
}
}
func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) {
- if ctx.Module() == module {
+ if EqualModules(ctx.Module(), module) {
return ctx.getContainersInfo(), true
}
@@ -479,8 +473,8 @@
func checkContainerViolations(ctx ModuleContext) {
if _, ok := ctx.Module().(InstallableModule); ok {
containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module())
- ctx.VisitDirectDeps(func(dep Module) {
- if !dep.Enabled(ctx) {
+ ctx.VisitDirectDepsProxy(func(dep ModuleProxy) {
+ if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled {
return
}
diff --git a/android/container_violations.go b/android/container_violations.go
index efbc8da..4c6386d 100644
--- a/android/container_violations.go
+++ b/android/container_violations.go
@@ -32,22 +32,22 @@
},
"Bluetooth": {
- "app-compat-annotations", // apex [com.android.btservices] -> system
- "framework-bluetooth-pre-jarjar", // apex [com.android.btservices] -> system
+ "app-compat-annotations", // apex [com.android.bt] -> system
+ "framework-bluetooth-pre-jarjar", // apex [com.android.bt] -> system
},
"bluetooth-nano-protos": {
- "libprotobuf-java-nano", // apex [com.android.btservices] -> apex [com.android.wifi, test_com.android.wifi]
+ "libprotobuf-java-nano", // apex [com.android.bt] -> apex [com.android.wifi, test_com.android.wifi]
},
"bluetooth.change-ids": {
- "app-compat-annotations", // apex [com.android.btservices] -> system
+ "app-compat-annotations", // apex [com.android.bt] -> system
},
"CarServiceUpdatable": {
"modules-utils-os", // apex [com.android.car.framework] -> apex [com.android.permission, test_com.android.permission]
"modules-utils-preconditions", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.appsearch, com.android.cellbroadcast, com.android.extservices, com.android.ondevicepersonalization, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.cellbroadcast, test_com.android.wifi]
- "modules-utils-shell-command-handler", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.art, com.android.art.debug, com.android.art.testing, com.android.btservices, com.android.configinfrastructure, com.android.mediaprovider, com.android.nfcservices, com.android.permission, com.android.scheduling, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.mediaprovider, test_com.android.permission, test_com.android.wifi, test_imgdiag_com.android.art, test_jitzygote_com.android.art]
+ "modules-utils-shell-command-handler", // apex [com.android.car.framework] -> apex [com.android.adservices, com.android.art, com.android.art.debug, com.android.art.testing, com.android.bt, com.android.configinfrastructure, com.android.mediaprovider, com.android.nfcservices, com.android.permission, com.android.scheduling, com.android.tethering, com.android.uwb, com.android.wifi, test_com.android.mediaprovider, test_com.android.permission, test_com.android.wifi, test_imgdiag_com.android.art, test_jitzygote_com.android.art]
},
"cellbroadcastreceiver_aconfig_flags_lib": {
@@ -414,10 +414,6 @@
"framework", // cts -> unstable
},
- "CtsMediaBetterTogetherTestCases": {
- "framework", // cts -> unstable
- },
-
"CtsMediaCodecTestCases": {
"framework", // cts -> unstable
},
@@ -478,6 +474,11 @@
"framework", // cts -> unstable
},
+ // TODO(b/387499846): Remove once migrated to sdk_version.
+ "CtsMediaRouterTestCases": {
+ "framework", // cts -> unstable
+ },
+
"CtsMediaRouterHostSideTestBluetoothPermissionsApp": {
"framework", // cts -> unstable
},
@@ -490,6 +491,11 @@
"framework", // cts -> unstable
},
+ // TODO(b/387500109): Remove once migrated to sdk_version.
+ "CtsMediaSessionTestCases": {
+ "framework", // cts -> unstable
+ },
+
"CtsMediaV2TestCases": {
"framework", // cts -> unstable
},
@@ -824,7 +830,7 @@
},
"devicelockcontroller-lib": {
- "modules-utils-expresslog", // apex [com.android.devicelock] -> apex [com.android.btservices, com.android.car.framework]
+ "modules-utils-expresslog", // apex [com.android.devicelock] -> apex [com.android.bt, com.android.car.framework]
},
"FederatedCompute": {
@@ -836,7 +842,7 @@
},
"framework-bluetooth.impl": {
- "app-compat-annotations", // apex [com.android.btservices] -> system
+ "app-compat-annotations", // apex [com.android.bt] -> system
},
"framework-configinfrastructure.impl": {
@@ -848,6 +854,13 @@
"framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
},
+ // TODO(b/382743602): Remove "app-compat-annotations" and depend on the stub version jar
+ // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
+ "framework-connectivity-b.impl": {
+ "app-compat-annotations", // apex [com.android.tethering] -> system
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
"framework-connectivity.impl": {
"app-compat-annotations", // apex [com.android.tethering] -> system
},
@@ -900,10 +913,6 @@
"libnativeloader_vendor_shared_lib", // system -> vendor
},
- "MctsMediaBetterTogetherTestCases": {
- "framework", // cts -> unstable
- },
-
"MctsMediaCodecTestCases": {
"framework", // cts -> unstable
},
@@ -940,6 +949,16 @@
"framework", // cts -> unstable
},
+ // TODO(b/387499846): Remove once migrated to sdk_version.
+ "MctsMediaRouterTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ // TODO(b/387500109): Remove once migrated to sdk_version.
+ "MctsMediaSessionTestCases": {
+ "framework", // cts -> unstable
+ },
+
"MctsMediaTranscodingTestCases": {
"framework", // cts -> unstable
},
@@ -974,7 +993,11 @@
},
"NfcNciApex": {
+ // TODO(b/383782511): Remove the violations once the infra is fixed.
+ "android.nfc.flags-aconfig-java", // apex [com.android.nfcservices] -> system
"android.permission.flags-aconfig-java", // apex [com.android.nfcservices] -> apex [com.android.permission, test_com.android.permission]
+ // TODO(b/383782511): Remove the violations once the infra is fixed.
+ "framework-nfc.impl", // apex [com.android.nfcservices] -> system
},
"okhttp-norepackage": {
@@ -994,7 +1017,7 @@
},
"PlatformProperties": {
- "sysprop-library-stub-platform", // apex [com.android.btservices, com.android.nfcservices, com.android.tethering, com.android.virt, com.android.wifi, test_com.android.wifi] -> system
+ "sysprop-library-stub-platform", // apex [com.android.bt, com.android.nfcservices, com.android.tethering, com.android.virt, com.android.wifi, test_com.android.wifi] -> system
},
"safety-center-config": {
@@ -1030,8 +1053,8 @@
},
"service-bluetooth-pre-jarjar": {
- "framework-bluetooth-pre-jarjar", // apex [com.android.btservices] -> system
- "service-bluetooth.change-ids", // apex [com.android.btservices] -> system
+ "framework-bluetooth-pre-jarjar", // apex [com.android.bt] -> system
+ "service-bluetooth.change-ids", // apex [com.android.bt] -> system
},
"service-connectivity": {
@@ -1051,6 +1074,13 @@
"framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
},
+ // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
+ "service-connectivity-b-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-b-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
"service-entitlement": {
"auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
diff --git a/android/csuite_config_test.go b/android/csuite_config_test.go
index b8a176e..7e25aac 100644
--- a/android/csuite_config_test.go
+++ b/android/csuite_config_test.go
@@ -32,7 +32,6 @@
if len(variants) > 1 {
t.Errorf("expected 1, got %d", len(variants))
}
- outputFilename := result.ModuleForTests(
- "plain", variants[0]).Module().(*CSuiteConfig).OutputFilePath.Base()
+ outputFilename := result.ModuleForTests(t, "plain", variants[0]).Module().(*CSuiteConfig).OutputFilePath.Base()
AssertStringEquals(t, "output file name", "plain", outputFilename)
}
diff --git a/android/deapexer.go b/android/deapexer.go
index 4049d2b..6d00dcd 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -75,8 +75,6 @@
// map from the name of an exported file from a prebuilt_apex to the path to that file. The
// exported file name is the apex relative path, e.g. javalib/core-libart.jar.
- //
- // See Prebuilt.ApexInfoMutator for more information.
exports map[string]WritablePath
// name of the java libraries exported from the apex
diff --git a/android/defaults.go b/android/defaults.go
index 510ebe0..0fc1768 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -178,6 +178,7 @@
module.AddProperties(
&hostAndDeviceProperties{},
commonProperties,
+ &baseProperties{},
&ApexProperties{},
&distProperties{})
diff --git a/android/defaults_test.go b/android/defaults_test.go
index 0ad0fb8..24f1461 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -123,8 +123,8 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- missingDefaults := result.ModuleForTests("missing_defaults", "").Output("out")
- missingTransitiveDefaults := result.ModuleForTests("missing_transitive_defaults", "").Output("out")
+ missingDefaults := result.ModuleForTests(t, "missing_defaults", "").Output("out")
+ missingTransitiveDefaults := result.ModuleForTests(t, "missing_transitive_defaults", "").Output("out")
AssertSame(t, "missing_defaults rule", ErrorRule, missingDefaults.Rule)
diff --git a/android/defs.go b/android/defs.go
index 9f3fb1e..57fcc9b 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -51,6 +51,14 @@
},
"cpFlags", "extraCmds")
+ // A copy rule wrapped with bash.
+ CpWithBash = pctx.AndroidStaticRule("CpWithBash",
+ blueprint.RuleParams{
+ Command: "/bin/bash -c \"rm -f $out && cp $cpFlags $cpPreserveSymlinks $in $out$extraCmds\"",
+ Description: "cp $out",
+ },
+ "cpFlags", "extraCmds")
+
// A copy rule that doesn't preserve symlinks.
CpNoPreserveSymlink = pctx.AndroidStaticRule("CpNoPreserveSymlink",
blueprint.RuleParams{
@@ -74,6 +82,14 @@
},
"cpFlags", "extraCmds")
+ // A copy executable rule wrapped with bash
+ CpExecutableWithBash = pctx.AndroidStaticRule("CpExecutableWithBash",
+ blueprint.RuleParams{
+ Command: "/bin/bash -c \"(rm -f $out && cp $cpFlags $cpPreserveSymlinks $in $out ) && (chmod +x $out$extraCmds )\"",
+ Description: "cp $out",
+ },
+ "cpFlags", "extraCmds")
+
// A timestamp touch rule.
Touch = pctx.AndroidStaticRule("Touch",
blueprint.RuleParams{
@@ -89,6 +105,14 @@
},
"fromPath")
+ // A symlink rule wrapped with bash
+ SymlinkWithBash = pctx.AndroidStaticRule("SymlinkWithBash",
+ blueprint.RuleParams{
+ Command: "/bin/bash -c \"rm -f $out && ln -sfn $fromPath $out\"",
+ Description: "symlink $out",
+ },
+ "fromPath")
+
ErrorRule = pctx.AndroidStaticRule("Error",
blueprint.RuleParams{
Command: `echo "$error" && false`,
@@ -119,3 +143,13 @@
return ctx.Config().RBEWrapper()
})
}
+
+// CopyFileRule creates a ninja rule to copy path to outPath.
+func CopyFileRule(ctx ModuleContext, path Path, outPath OutputPath) {
+ ctx.Build(pctx, BuildParams{
+ Rule: Cp,
+ Input: path,
+ Output: outPath,
+ Description: "copy " + outPath.Base(),
+ })
+}
diff --git a/android/deptag_test.go b/android/deptag_test.go
index eb4fa89..9037871 100644
--- a/android/deptag_test.go
+++ b/android/deptag_test.go
@@ -90,10 +90,10 @@
config := result.Config
- hostFoo := result.ModuleForTests("foo", config.BuildOSCommonTarget.String()).Description("install")
- hostInstallDep := result.ModuleForTests("install_dep", config.BuildOSCommonTarget.String()).Description("install")
- hostTransitive := result.ModuleForTests("transitive", config.BuildOSCommonTarget.String()).Description("install")
- hostDep := result.ModuleForTests("dep", config.BuildOSCommonTarget.String()).Description("install")
+ hostFoo := result.ModuleForTests(t, "foo", config.BuildOSCommonTarget.String()).Description("install")
+ hostInstallDep := result.ModuleForTests(t, "install_dep", config.BuildOSCommonTarget.String()).Description("install")
+ hostTransitive := result.ModuleForTests(t, "transitive", config.BuildOSCommonTarget.String()).Description("install")
+ hostDep := result.ModuleForTests(t, "dep", config.BuildOSCommonTarget.String()).Description("install")
if g, w := hostFoo.Implicits.Strings(), hostInstallDep.Output.String(); !InList(w, g) {
t.Errorf("expected host dependency %q, got %q", w, g)
@@ -111,10 +111,10 @@
t.Errorf("expected no host dependency %q, got %q", w, g)
}
- deviceFoo := result.ModuleForTests("foo", "android_common").Description("install")
- deviceInstallDep := result.ModuleForTests("install_dep", "android_common").Description("install")
- deviceTransitive := result.ModuleForTests("transitive", "android_common").Description("install")
- deviceDep := result.ModuleForTests("dep", "android_common").Description("install")
+ deviceFoo := result.ModuleForTests(t, "foo", "android_common").Description("install")
+ deviceInstallDep := result.ModuleForTests(t, "install_dep", "android_common").Description("install")
+ deviceTransitive := result.ModuleForTests(t, "transitive", "android_common").Description("install")
+ deviceDep := result.ModuleForTests(t, "dep", "android_common").Description("install")
if g, w := deviceFoo.OrderOnly.Strings(), deviceInstallDep.Output.String(); !InList(w, g) {
t.Errorf("expected device dependency %q, got %q", w, g)
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 5e971ef..300edf1 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -146,6 +146,13 @@
}
func (e *earlyModuleContext) Config() Config {
+ // Only the system image may use the generic config.
+ // If a module builds multiple image variations, provide the generic config only for the core
+ // variant which is installed in the system partition. Other image variant may still read the
+ // original configurations.
+ if e.Module().base().UseGenericConfig() && e.Module().base().commonProperties.ImageVariation == "" {
+ return e.EarlyModuleContext.Config().(Config).genericConfig()
+ }
return e.EarlyModuleContext.Config().(Config)
}
@@ -182,7 +189,7 @@
}
func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
- e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args...)
+ e.EarlyModuleContext.OtherModulePropertyErrorf(getWrappedModule(module), property, fmt, args...)
}
func (e *earlyModuleContext) HasMutatorFinished(mutatorName string) bool {
diff --git a/android/filegroup.go b/android/filegroup.go
index 67e5add1f..4fad52a 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -41,11 +41,11 @@
Exclude_srcs proptools.Configurable[[]string] `android:"path"`
- // Sources the will be included in the filegroup, but any module dependencies will be added
+ // Sources that will be included in the filegroup, but any module dependencies will be added
// using the device os and the device's first architecture's variant.
Device_first_srcs proptools.Configurable[[]string] `android:"path_device_first"`
- // Sources the will be included in the filegroup, but any module dependencies will be added
+ // Sources that will be included in the filegroup, but any module dependencies will be added
// using the device os and the common architecture's variant.
Device_common_srcs proptools.Configurable[[]string] `android:"path_device_common"`
@@ -104,7 +104,6 @@
if fg.properties.Path != nil {
srcs = PathsWithModuleSrcSubDir(ctx, srcs, String(fg.properties.Path))
}
- SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
var aconfigDeclarations []string
var intermediateCacheOutputPaths Paths
@@ -132,10 +131,11 @@
return append(Paths{}, fg.srcs...)
}
-func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) {
+func (fg *fileGroup) MakeVars(_ MakeVarsModuleContext) []ModuleMakeVarsValue {
if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
- ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " "))
+ return []ModuleMakeVarsValue{{makeVar, strings.Join(fg.srcs.Strings(), " ")}}
}
+ return nil
}
// Defaults
diff --git a/android/fixture.go b/android/fixture.go
index 5ad47e8..ea52b95 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -1048,7 +1048,7 @@
// Module returns the module with the specific name and of the specified variant.
func (r *TestResult) Module(name string, variant string) Module {
- return r.ModuleForTests(name, variant).Module()
+ return r.ModuleForTests(r.fixture.t, name, variant).Module()
}
// CollateErrs adds additional errors to the result and returns true if there is more than one
diff --git a/android/gen_notice.go b/android/gen_notice.go
index 9adde9e..45f90f4 100644
--- a/android/gen_notice.go
+++ b/android/gen_notice.go
@@ -19,6 +19,7 @@
"path/filepath"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -35,34 +36,31 @@
type genNoticeBuildRules struct{}
func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
- ctx.VisitAllModules(func(m Module) {
- gm, ok := m.(*genNoticeModule)
+ ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+ gm, ok := OtherModuleProvider(ctx, m, GenNoticeInfoProvider)
if !ok {
return
}
- if len(gm.missing) > 0 {
- missingReferencesRule(ctx, gm)
+ if len(gm.Missing) > 0 {
+ missingReferencesRule(ctx, m, &gm)
return
}
out := BuildNoticeTextOutputFromLicenseMetadata
- if proptools.Bool(gm.properties.Xml) {
+ if gm.Xml {
out = BuildNoticeXmlOutputFromLicenseMetadata
- } else if proptools.Bool(gm.properties.Html) {
+ } else if gm.Html {
out = BuildNoticeHtmlOutputFromLicenseMetadata
}
defaultName := ""
- if len(gm.properties.For) > 0 {
- defaultName = gm.properties.For[0]
+ if len(gm.For) > 0 {
+ defaultName = gm.For[0]
}
- modules := make([]Module, 0)
- for _, name := range gm.properties.For {
- mods := ctx.ModuleVariantsFromName(gm, name)
+ modules := make([]ModuleProxy, 0)
+ for _, name := range gm.For {
+ mods := ctx.ModuleVariantsFromName(m, name)
for _, mod := range mods {
- if mod == nil {
- continue
- }
- if !mod.Enabled(ctx) { // don't depend on variants without build rules
+ if !OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider).Enabled { // don't depend on variants without build rules
continue
}
modules = append(modules, mod)
@@ -71,8 +69,8 @@
if ctx.Failed() {
return
}
- out(ctx, gm.output, ctx.ModuleName(gm),
- proptools.StringDefault(gm.properties.ArtifactName, defaultName),
+ out(ctx, gm.Output, ctx.ModuleName(m),
+ proptools.StringDefault(gm.ArtifactName, defaultName),
[]string{
filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()) + "/",
ctx.Config().OutDir() + "/",
@@ -115,6 +113,22 @@
missing []string
}
+type GenNoticeInfo struct {
+ // For specifies the modules for which to generate a notice file.
+ For []string
+ // ArtifactName specifies the internal name to use for the notice file.
+ // It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
+ ArtifactName *string
+ // Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
+ Html bool
+ // Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
+ Xml bool
+ Output OutputPath
+ Missing []string
+}
+
+var GenNoticeInfoProvider = blueprint.NewProvider[GenNoticeInfo]()
+
func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
if ctx.ContainsProperty("licenses") {
ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
@@ -176,6 +190,15 @@
}
out := m.getStem() + m.getSuffix()
m.output = PathForModuleOut(ctx, out).OutputPath
+
+ SetProvider(ctx, GenNoticeInfoProvider, GenNoticeInfo{
+ For: m.properties.For,
+ ArtifactName: m.properties.ArtifactName,
+ Xml: proptools.Bool(m.properties.Xml),
+ Html: proptools.Bool(m.properties.Html),
+ Output: m.output,
+ Missing: m.missing,
+ })
ctx.SetOutputFiles(Paths{m.output}, "")
}
@@ -205,17 +228,17 @@
}
// missingReferencesRule emits an ErrorRule for missing module references.
-func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
- if len(m.missing) < 1 {
+func missingReferencesRule(ctx BuilderContext, m ModuleProxy, genInfo *GenNoticeInfo) {
+ if len(genInfo.Missing) < 1 {
panic(fmt.Errorf("missing references rule requested with no missing references"))
}
ctx.Build(pctx, BuildParams{
Rule: ErrorRule,
- Output: m.output,
- Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
+ Output: genInfo.Output,
+ Description: "notice for " + proptools.StringDefault(genInfo.ArtifactName, "container"),
Args: map[string]string{
- "error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
+ "error": m.Name() + " references missing module(s): " + strings.Join(genInfo.Missing, ", "),
},
})
}
diff --git a/android/hooks.go b/android/hooks.go
index f8022d0..5d509a4 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -100,12 +100,12 @@
l.appendPrependHelper(props, proptools.PrependMatchingProperties)
}
-func (l *loadHookContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module {
- return l.bp.CreateModule(factory, name, props...)
+func (l *loadHookContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) Module {
+ return bpModuleToModule(l.bp.CreateModule(factory, name, props...))
}
-func (l *loadHookContext) createModuleInDirectory(factory blueprint.ModuleFactory, name, moduleDir string, props ...interface{}) blueprint.Module {
- return l.bp.CreateModuleInDirectory(factory, name, moduleDir, props...)
+func (l *loadHookContext) createModuleInDirectory(factory blueprint.ModuleFactory, name, moduleDir string, props ...interface{}) Module {
+ return bpModuleToModule(l.bp.CreateModuleInDirectory(factory, name, moduleDir, props...))
}
type specifyDirectory struct {
@@ -130,8 +130,8 @@
type createModuleContext interface {
Module() Module
HasMutatorFinished(mutatorName string) bool
- createModule(blueprint.ModuleFactory, string, ...interface{}) blueprint.Module
- createModuleInDirectory(blueprint.ModuleFactory, string, string, ...interface{}) blueprint.Module
+ createModule(blueprint.ModuleFactory, string, ...interface{}) Module
+ createModuleInDirectory(blueprint.ModuleFactory, string, string, ...interface{}) Module
}
func createModule(ctx createModuleContext, factory ModuleFactory, ext string, specifyDirectory specifyDirectory, props ...interface{}) Module {
diff --git a/android/init.go b/android/init.go
index d3a13d0..af50323 100644
--- a/android/init.go
+++ b/android/init.go
@@ -17,6 +17,7 @@
import "encoding/gob"
func init() {
+ gob.Register(applicableLicensesPropertyImpl{})
gob.Register(extraFilesZip{})
gob.Register(InstallPath{})
gob.Register(ModuleGenPath{})
diff --git a/android/license.go b/android/license.go
index 5bffc25..7b4aeeb 100644
--- a/android/license.go
+++ b/android/license.go
@@ -18,6 +18,15 @@
"github.com/google/blueprint"
)
+type LicenseInfo struct {
+ PackageName *string
+ EffectiveLicenseText NamedPaths
+ EffectiveLicenseKinds []string
+ EffectiveLicenseConditions []string
+}
+
+var LicenseInfoProvider = blueprint.NewProvider[LicenseInfo]()
+
type licenseKindDependencyTag struct {
blueprint.BaseDependencyTag
}
@@ -69,16 +78,24 @@
func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) {
// license modules have no licenses, but license_kinds must refer to license_kind modules
- mergeStringProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName())
namePathProps(&m.base().commonProperties.Effective_license_text, m.properties.Package_name, PathsForModuleSrc(ctx, m.properties.License_text)...)
- for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
- if lk, ok := module.(*licenseKindModule); ok {
- mergeStringProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...)
- mergeStringProps(&m.base().commonProperties.Effective_license_kinds, ctx.OtherModuleName(module))
+ var conditions []string
+ var kinds []string
+ for _, module := range ctx.GetDirectDepsProxyWithTag(licenseKindTag) {
+ if lk, ok := OtherModuleProvider(ctx, module, LicenseKindInfoProvider); ok {
+ conditions = append(conditions, lk.Conditions...)
+ kinds = append(kinds, ctx.OtherModuleName(module))
} else {
ctx.ModuleErrorf("license_kinds property %q is not a license_kind module", ctx.OtherModuleName(module))
}
}
+
+ SetProvider(ctx, LicenseInfoProvider, LicenseInfo{
+ PackageName: m.properties.Package_name,
+ EffectiveLicenseText: m.base().commonProperties.Effective_license_text,
+ EffectiveLicenseKinds: SortedUniqueStrings(kinds),
+ EffectiveLicenseConditions: SortedUniqueStrings(conditions),
+ })
}
func LicenseFactory() Module {
diff --git a/android/license_kind.go b/android/license_kind.go
index 838dedd..1ca6954 100644
--- a/android/license_kind.go
+++ b/android/license_kind.go
@@ -14,6 +14,14 @@
package android
+import "github.com/google/blueprint"
+
+type LicenseKindInfo struct {
+ Conditions []string
+}
+
+var LicenseKindInfoProvider = blueprint.NewProvider[LicenseKindInfo]()
+
func init() {
RegisterLicenseKindBuildComponents(InitRegistrationContext)
}
@@ -43,8 +51,10 @@
// Nothing to do.
}
-func (m *licenseKindModule) GenerateAndroidBuildActions(ModuleContext) {
- // Nothing to do.
+func (m *licenseKindModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ SetProvider(ctx, LicenseKindInfoProvider, LicenseKindInfo{
+ Conditions: m.properties.Conditions,
+ })
}
func LicenseKindFactory() Module {
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 3df36e6..0b880dd 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -15,11 +15,11 @@
package android
import (
- "github.com/google/blueprint/depset"
"sort"
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/depset"
"github.com/google/blueprint/proptools"
)
@@ -64,8 +64,8 @@
var allDepOutputFiles Paths
var allDepMetadataDepSets []depset.DepSet[Path]
- ctx.VisitDirectDeps(func(dep Module) {
- if !dep.Enabled(ctx) {
+ ctx.VisitDirectDepsProxy(func(dep ModuleProxy) {
+ if !OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled {
return
}
@@ -81,7 +81,7 @@
if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
- if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
+ if isContainer || isInstallDepNeeded(ctx, dep) {
allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
}
diff --git a/android/licenses.go b/android/licenses.go
index 53d0555..3877921 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -22,6 +22,7 @@
"sync"
"github.com/google/blueprint"
+ "github.com/google/blueprint/gobtools"
)
// Adds cross-cutting licenses dependency to propagate license metadata through the build system.
@@ -67,6 +68,31 @@
licensesProperty *[]string
}
+type applicableLicensesPropertyImplGob struct {
+ Name string
+ LicensesProperty []string
+}
+
+func (a *applicableLicensesPropertyImpl) ToGob() *applicableLicensesPropertyImplGob {
+ return &applicableLicensesPropertyImplGob{
+ Name: a.name,
+ LicensesProperty: *a.licensesProperty,
+ }
+}
+
+func (a *applicableLicensesPropertyImpl) FromGob(data *applicableLicensesPropertyImplGob) {
+ a.name = data.Name
+ a.licensesProperty = &data.LicensesProperty
+}
+
+func (a applicableLicensesPropertyImpl) GobEncode() ([]byte, error) {
+ return gobtools.CustomGobEncode[applicableLicensesPropertyImplGob](&a)
+}
+
+func (a *applicableLicensesPropertyImpl) GobDecode(data []byte) error {
+ return gobtools.CustomGobDecode[applicableLicensesPropertyImplGob](data, a)
+}
+
func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
return applicableLicensesPropertyImpl{
name: name,
@@ -227,16 +253,18 @@
}
var licenses []string
- for _, module := range ctx.GetDirectDepsWithTag(licensesTag) {
- if l, ok := module.(*licenseModule); ok {
+ var texts NamedPaths
+ var conditions []string
+ var kinds []string
+ for _, module := range ctx.GetDirectDepsProxyWithTag(licensesTag) {
+ if l, ok := OtherModuleProvider(ctx, module, LicenseInfoProvider); ok {
licenses = append(licenses, ctx.OtherModuleName(module))
- if m.base().commonProperties.Effective_package_name == nil && l.properties.Package_name != nil {
- m.base().commonProperties.Effective_package_name = l.properties.Package_name
+ if m.base().commonProperties.Effective_package_name == nil && l.PackageName != nil {
+ m.base().commonProperties.Effective_package_name = l.PackageName
}
- mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
- mergeNamedPathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
- mergeStringProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
- mergeStringProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
+ texts = append(texts, l.EffectiveLicenseText...)
+ kinds = append(kinds, l.EffectiveLicenseKinds...)
+ conditions = append(conditions, l.EffectiveLicenseConditions...)
} else {
propertyName := "licenses"
primaryProperty := m.base().primaryLicensesProperty
@@ -247,17 +275,15 @@
}
}
+ m.base().commonProperties.Effective_license_text = SortedUniqueNamedPaths(texts)
+ m.base().commonProperties.Effective_license_kinds = SortedUniqueStrings(kinds)
+ m.base().commonProperties.Effective_license_conditions = SortedUniqueStrings(conditions)
+
// Make the license information available for other modules.
- licenseInfo := LicenseInfo{
+ licenseInfo := LicensesInfo{
Licenses: licenses,
}
- SetProvider(ctx, LicenseInfoProvider, licenseInfo)
-}
-
-// Update a property string array with a distinct union of its values and a list of new values.
-func mergeStringProps(prop *[]string, values ...string) {
- *prop = append(*prop, values...)
- *prop = SortedUniqueStrings(*prop)
+ SetProvider(ctx, LicensesInfoProvider, licenseInfo)
}
// Update a property NamedPath array with a distinct union of its values and a list of new values.
@@ -274,12 +300,6 @@
*prop = SortedUniqueNamedPaths(*prop)
}
-// Update a property NamedPath array with a distinct union of its values and a list of new values.
-func mergeNamedPathProps(prop *NamedPaths, values ...NamedPath) {
- *prop = append(*prop, values...)
- *prop = SortedUniqueNamedPaths(*prop)
-}
-
// Get the licenses property falling back to the package default.
func getLicenses(ctx BaseModuleContext, module Module) []string {
if exemptFromRequiredApplicableLicensesProperty(module) {
@@ -336,14 +356,14 @@
return true
}
-// LicenseInfo contains information about licenses for a specific module.
-type LicenseInfo struct {
+// LicensesInfo contains information about licenses for a specific module.
+type LicensesInfo struct {
// The list of license modules this depends upon, either explicitly or through default package
// configuration.
Licenses []string
}
-var LicenseInfoProvider = blueprint.NewProvider[LicenseInfo]()
+var LicensesInfoProvider = blueprint.NewProvider[LicensesInfo]()
func init() {
RegisterMakeVarsProvider(pctx, licensesMakeVarsProvider)
@@ -357,9 +377,7 @@
ctx.Strict("HTMLNOTICE", ctx.Config().HostToolPath(ctx, "htmlnotice").String())
ctx.Strict("XMLNOTICE", ctx.Config().HostToolPath(ctx, "xmlnotice").String())
ctx.Strict("TEXTNOTICE", ctx.Config().HostToolPath(ctx, "textnotice").String())
- ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String())
ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
- ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
}
diff --git a/android/licenses_test.go b/android/licenses_test.go
index 8a81e12..0c371e8 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -7,15 +7,13 @@
)
var licensesTests = []struct {
- name string
- fs MockFS
- expectedErrors []string
- effectiveLicenses map[string][]string
- effectiveInheritedLicenses map[string][]string
- effectivePackage map[string]string
- effectiveNotices map[string][]string
- effectiveKinds map[string][]string
- effectiveConditions map[string][]string
+ name string
+ fs MockFS
+ expectedErrors []string
+ effectivePackage map[string]string
+ effectiveNotices map[string][]string
+ effectiveKinds map[string][]string
+ effectiveConditions map[string][]string
}{
{
name: "invalid module type without licenses property",
@@ -69,11 +67,6 @@
licenses: ["top_Apache2"],
}`),
},
- effectiveLicenses: map[string][]string{
- "libexample1": []string{"top_Apache2"},
- "libnested": []string{"top_Apache2"},
- "libother": []string{"top_Apache2"},
- },
effectiveKinds: map[string][]string{
"libexample1": []string{"notice"},
"libnested": []string{"notice"},
@@ -146,18 +139,6 @@
deps: ["libexample"],
}`),
},
- effectiveLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
- "libsamepackage": []string{"nested_other", "top_other"},
- "libnested": []string{"nested_other", "top_other"},
- "libother": []string{"nested_other", "top_other"},
- },
effectiveKinds: map[string][]string{
"libexample": []string{"nested_notice", "top_notice"},
"libsamepackage": []string{},
@@ -217,20 +198,6 @@
deps: ["libexample"],
}`),
},
- effectiveLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
- "libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
- "libsamepackage": []string{"other", "top_nested"},
- "libnested": []string{"other", "top_nested"},
- "libother": []string{"other", "top_nested"},
- "liboutsider": []string{"other", "top_nested"},
- },
effectiveKinds: map[string][]string{
"libexample": []string{},
"libsamepackage": []string{},
@@ -284,14 +251,6 @@
defaults: ["top_defaults"],
}`),
},
- effectiveLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
- "libdefaults": []string{"notice"},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
- "libdefaults": []string{"notice"},
- },
},
// Package default_applicable_licenses tests
@@ -326,14 +285,6 @@
deps: ["libexample"],
}`),
},
- effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "liboutsider": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "liboutsider": []string{"top_notice"},
- },
},
{
name: "package default_applicable_licenses not inherited to subpackages",
@@ -369,18 +320,6 @@
deps: ["libexample", "libother", "libnested"],
}`),
},
- effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
- "liboutsider": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
- "liboutsider": []string{"top_notice", "outsider"},
- },
},
{
name: "verify that prebuilt dependencies are included",
@@ -409,12 +348,6 @@
deps: [":module"],
}`),
},
- effectiveLicenses: map[string][]string{
- "other": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "other": []string{"prebuilt", "top_sources"},
- },
},
{
name: "verify that prebuilt dependencies are ignored for licenses reasons (preferred)",
@@ -444,13 +377,6 @@
deps: [":module"],
}`),
},
- effectiveLicenses: map[string][]string{
- "other": []string{},
- },
- effectiveInheritedLicenses: map[string][]string{
- "module": []string{"prebuilt", "top_sources"},
- "other": []string{"prebuilt", "top_sources"},
- },
},
}
@@ -470,10 +396,6 @@
ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
RunTest(t)
- if test.effectiveLicenses != nil {
- checkEffectiveLicenses(t, result, test.effectiveLicenses)
- }
-
if test.effectivePackage != nil {
checkEffectivePackage(t, result, test.effectivePackage)
}
@@ -489,114 +411,10 @@
if test.effectiveConditions != nil {
checkEffectiveConditions(t, result, test.effectiveConditions)
}
-
- if test.effectiveInheritedLicenses != nil {
- checkEffectiveInheritedLicenses(t, result, test.effectiveInheritedLicenses)
- }
})
}
}
-func checkEffectiveLicenses(t *testing.T, result *TestResult, effectiveLicenses map[string][]string) {
- actualLicenses := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- actualLicenses[m.Name()] = base.commonProperties.Effective_licenses
- })
-
- for moduleName, expectedLicenses := range effectiveLicenses {
- licenses, ok := actualLicenses[moduleName]
- if !ok {
- licenses = []string{}
- }
- if !compareUnorderedStringArrays(expectedLicenses, licenses) {
- t.Errorf("effective licenses mismatch for module %q: expected %q, found %q", moduleName, expectedLicenses, licenses)
- }
- }
-}
-
-func checkEffectiveInheritedLicenses(t *testing.T, result *TestResult, effectiveInheritedLicenses map[string][]string) {
- actualLicenses := make(map[string][]string)
- result.Context.Context.VisitAllModules(func(m blueprint.Module) {
- if _, ok := m.(*licenseModule); ok {
- return
- }
- if _, ok := m.(*licenseKindModule); ok {
- return
- }
- if _, ok := m.(*packageModule); ok {
- return
- }
- module, ok := m.(Module)
- if !ok {
- t.Errorf("%q not a module", m.Name())
- return
- }
- base := module.base()
- if base == nil {
- return
- }
- inherited := make(map[string]bool)
- for _, l := range base.commonProperties.Effective_licenses {
- inherited[l] = true
- }
- result.Context.Context.VisitDepsDepthFirst(m, func(c blueprint.Module) {
- if _, ok := c.(*licenseModule); ok {
- return
- }
- if _, ok := c.(*licenseKindModule); ok {
- return
- }
- if _, ok := c.(*packageModule); ok {
- return
- }
- cmodule, ok := c.(Module)
- if !ok {
- t.Errorf("%q not a module", c.Name())
- return
- }
- cbase := cmodule.base()
- if cbase == nil {
- return
- }
- for _, l := range cbase.commonProperties.Effective_licenses {
- inherited[l] = true
- }
- })
- actualLicenses[m.Name()] = []string{}
- for l := range inherited {
- actualLicenses[m.Name()] = append(actualLicenses[m.Name()], l)
- }
- })
-
- for moduleName, expectedInheritedLicenses := range effectiveInheritedLicenses {
- licenses, ok := actualLicenses[moduleName]
- if !ok {
- licenses = []string{}
- }
- if !compareUnorderedStringArrays(expectedInheritedLicenses, licenses) {
- t.Errorf("effective inherited licenses mismatch for module %q: expected %q, found %q", moduleName, expectedInheritedLicenses, licenses)
- }
- }
-}
-
func checkEffectivePackage(t *testing.T, result *TestResult, effectivePackage map[string]string) {
actualPackage := make(map[string]string)
result.Context.Context.VisitAllModules(func(m blueprint.Module) {
diff --git a/android/logtags.go b/android/logtags.go
index 7929057..074f402 100644
--- a/android/logtags.go
+++ b/android/logtags.go
@@ -14,7 +14,11 @@
package android
-import "github.com/google/blueprint"
+import (
+ "strings"
+
+ "github.com/google/blueprint"
+)
func init() {
RegisterParallelSingletonType("logtags", LogtagsSingleton)
@@ -38,19 +42,28 @@
func (l *logtagsSingleton) GenerateBuildActions(ctx SingletonContext) {
var allLogtags Paths
- ctx.VisitAllModules(func(module Module) {
- if !module.ExportedToMake() {
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ExportedToMake {
return
}
if logtagsInfo, ok := OtherModuleProvider(ctx, module, LogtagsProviderKey); ok {
allLogtags = append(allLogtags, logtagsInfo.Logtags...)
}
})
+ allLogtags = SortedUniquePaths(allLogtags)
+ filteredLogTags := make([]Path, 0, len(allLogtags))
+ for _, p := range allLogtags {
+ // Logic copied from make:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=987;drc=0585bb1bcf4c89065adaf709f48acc8b869fd3ce
+ if !strings.HasPrefix(p.String(), "vendor/") && !strings.HasPrefix(p.String(), "device/") && !strings.HasPrefix(p.String(), "out/") {
+ filteredLogTags = append(filteredLogTags, p)
+ }
+ }
builder := NewRuleBuilder(pctx, ctx)
builder.Command().
BuiltTool("merge-event-log-tags").
FlagWithOutput("-o ", MergedLogtagsPath(ctx)).
- Inputs(SortedUniquePaths(allLogtags))
+ Inputs(filteredLogTags)
builder.Build("all-event-log-tags.txt", "merge logtags")
}
diff --git a/android/makevars.go b/android/makevars.go
index 8305d8e..7017e7d 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -65,24 +65,6 @@
// dependencies to be added to it. Phony can be called on the same name multiple
// times to add additional dependencies.
Phony(names string, deps ...Path)
-
- // DistForGoal creates a rule to copy one or more Paths to the artifacts
- // directory on the build server when the specified goal is built.
- DistForGoal(goal string, paths ...Path)
-
- // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
- // directory on the build server with the given filename when the specified
- // goal is built.
- DistForGoalWithFilename(goal string, path Path, filename string)
-
- // DistForGoals creates a rule to copy one or more Paths to the artifacts
- // directory on the build server when any of the specified goals are built.
- DistForGoals(goals []string, paths ...Path)
-
- // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
- // directory on the build server with the given filename when any of the
- // specified goals are built.
- DistForGoalsWithFilename(goals []string, path Path, filename string)
}
// MakeVarsContext contains the set of functions available for MakeVarsProvider
@@ -102,6 +84,7 @@
Errorf(format string, args ...interface{})
VisitAllModules(visit func(Module))
+ VisitAllModuleProxies(visit func(proxy ModuleProxy))
VisitAllModulesIf(pred func(Module) bool, visit func(Module))
// Verify the make variable matches the Soong version, fail the build
@@ -126,7 +109,7 @@
// MakeVarsModuleContext contains the set of functions available for modules
// implementing the ModuleMakeVarsProvider interface.
type MakeVarsModuleContext interface {
- BaseMakeVarsContext
+ Config() Config
}
var _ PathContext = MakeVarsContext(nil)
@@ -168,14 +151,21 @@
return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
}
+type ModuleMakeVarsValue struct {
+ // Make variable name.
+ Name string
+ // Make variable value.
+ Value string
+}
+
// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make.
type ModuleMakeVarsProvider interface {
- Module
-
// MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make.
- MakeVars(ctx MakeVarsModuleContext)
+ MakeVars(ctx MakeVarsModuleContext) []ModuleMakeVarsValue
}
+var ModuleMakeVarsInfoProvider = blueprint.NewProvider[[]ModuleMakeVarsValue]()
+
// /////////////////////////////////////////////////////////////////////////////
func makeVarsSingletonFunc() Singleton {
@@ -185,6 +175,7 @@
type makeVarsSingleton struct {
varsForTesting []makeVarsVariable
installsForTesting []byte
+ lateForTesting []byte
}
type makeVarsProvider struct {
@@ -197,11 +188,9 @@
type makeVarsContext struct {
SingletonContext
- config Config
pctx PackageContext
vars []makeVarsVariable
phonies []phony
- dists []dist
}
var _ MakeVarsContext = &makeVarsContext{}
@@ -220,7 +209,7 @@
type dist struct {
goals []string
- paths []string
+ paths distCopies
}
func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
@@ -262,29 +251,41 @@
vars = append(vars, mctx.vars...)
phonies = append(phonies, mctx.phonies...)
- dists = append(dists, mctx.dists...)
}
- ctx.VisitAllModules(func(m Module) {
- if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled(ctx) {
+ singletonDists := getSingletonDists(ctx.Config())
+ singletonDists.lock.Lock()
+ dists = append(dists, singletonDists.dists...)
+ singletonDists.lock.Unlock()
+
+ ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, m, CommonModuleInfoProvider)
+ if provider, ok := OtherModuleProvider(ctx, m, ModuleMakeVarsInfoProvider); ok &&
+ commonInfo.Enabled {
mctx := &makeVarsContext{
SingletonContext: ctx,
}
-
- provider.MakeVars(mctx)
+ for _, val := range provider {
+ if val.Name != "" {
+ mctx.StrictRaw(val.Name, val.Value)
+ }
+ }
vars = append(vars, mctx.vars...)
phonies = append(phonies, mctx.phonies...)
- dists = append(dists, mctx.dists...)
}
- if m.ExportedToMake() {
+ if commonInfo.ExportedToMake {
info := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider)
katiInstalls = append(katiInstalls, info.KatiInstalls...)
katiInitRcInstalls = append(katiInitRcInstalls, info.KatiInitRcInstalls...)
katiVintfManifestInstalls = append(katiVintfManifestInstalls, info.KatiVintfInstalls...)
katiSymlinks = append(katiSymlinks, info.KatiSymlinks...)
}
+
+ if distInfo, ok := OtherModuleProvider(ctx, m, DistProvider); ok {
+ dists = append(dists, distInfo.Dists...)
+ }
})
compareKatiInstalls := func(a, b katiInstall) int {
@@ -318,19 +319,12 @@
sort.Slice(phonies, func(i, j int) bool {
return phonies[i].name < phonies[j].name
})
- lessArr := func(a, b []string) bool {
- if len(a) == len(b) {
- for i := range a {
- if a[i] < b[i] {
- return true
- }
- }
- return false
- }
- return len(a) < len(b)
- }
sort.Slice(dists, func(i, j int) bool {
- return lessArr(dists[i].goals, dists[j].goals) || lessArr(dists[i].paths, dists[j].paths)
+ goals := slices.Compare(dists[i].goals, dists[j].goals)
+ if goals != 0 {
+ return goals < 0
+ }
+ return slices.Compare(dists[i].paths.Strings(), dists[j].paths.Strings()) < 0
})
outBytes := s.writeVars(vars)
@@ -354,6 +348,7 @@
if ctx.Config().RunningInsideUnitTest() {
s.varsForTesting = vars
s.installsForTesting = installsBytes
+ s.lateForTesting = lateOutBytes
}
}
@@ -458,7 +453,7 @@
for _, dist := range dists {
fmt.Fprintf(buf, ".PHONY: %s\n", strings.Join(dist.goals, " "))
fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
- strings.Join(dist.goals, " "), strings.Join(dist.paths, " "))
+ strings.Join(dist.goals, " "), strings.Join(dist.paths.Strings(), " "))
}
return buf.Bytes()
@@ -607,13 +602,6 @@
c.phonies = append(c.phonies, phony{name, deps})
}
-func (c *makeVarsContext) addDist(goals []string, paths []string) {
- c.dists = append(c.dists, dist{
- goals: goals,
- paths: paths,
- })
-}
-
func (c *makeVarsContext) Strict(name, ninjaStr string) {
c.addVariable(name, ninjaStr, true, false)
}
@@ -637,19 +625,3 @@
func (c *makeVarsContext) Phony(name string, deps ...Path) {
c.addPhony(name, Paths(deps).Strings())
}
-
-func (c *makeVarsContext) DistForGoal(goal string, paths ...Path) {
- c.DistForGoals([]string{goal}, paths...)
-}
-
-func (c *makeVarsContext) DistForGoalWithFilename(goal string, path Path, filename string) {
- c.DistForGoalsWithFilename([]string{goal}, path, filename)
-}
-
-func (c *makeVarsContext) DistForGoals(goals []string, paths ...Path) {
- c.addDist(goals, Paths(paths).Strings())
-}
-
-func (c *makeVarsContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
- c.addDist(goals, []string{path.String() + ":" + filename})
-}
diff --git a/android/makevars_test.go b/android/makevars_test.go
new file mode 100644
index 0000000..387d457
--- /dev/null
+++ b/android/makevars_test.go
@@ -0,0 +1,96 @@
+package android
+
+import (
+ "regexp"
+ "testing"
+)
+
+func TestDistFilesInGenerateAndroidBuildActions(t *testing.T) {
+ result := GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("my_module_type", newDistFileModule)
+ ctx.RegisterParallelSingletonType("my_singleton", newDistFileSingleton)
+ ctx.RegisterParallelSingletonModuleType("my_singleton_module", newDistFileSingletonModule)
+ }),
+ FixtureModifyConfig(SetKatiEnabledForTests),
+ PrepareForTestWithMakevars,
+ ).RunTestWithBp(t, `
+ my_module_type {
+ name: "foo",
+ }
+ my_singleton_module {
+ name: "bar"
+ }
+ `)
+
+ lateContents := string(result.SingletonForTests(t, "makevars").Singleton().(*makeVarsSingleton).lateForTesting)
+ matched, err := regexp.MatchString(`call dist-for-goals,my_goal,.*/my_file.txt:my_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_file.txt, but got: %s", lateContents)
+ }
+ matched, err = regexp.MatchString(`call dist-for-goals,my_singleton_goal,.*/my_singleton_file.txt:my_singleton_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_singleton_file.txt, but got: %s", lateContents)
+ }
+ matched, err = regexp.MatchString(`call dist-for-goals,my_singleton_module_module_goal,.*/my_singleton_module_module_file.txt:my_singleton_module_module_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_singleton_module_module_file.txt, but got: %s", lateContents)
+ }
+ matched, err = regexp.MatchString(`call dist-for-goals,my_singleton_module_singleton_goal,.*/my_singleton_module_singleton_file.txt:my_singleton_module_singleton_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_singleton_module_singleton_file.txt, but got: %s", lateContents)
+ }
+}
+
+type distFileModule struct {
+ ModuleBase
+}
+
+func newDistFileModule() Module {
+ m := &distFileModule{}
+ InitAndroidModule(m)
+ return m
+}
+
+func (m *distFileModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ out := PathForModuleOut(ctx, "my_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_goal", out)
+}
+
+type distFileSingleton struct {
+}
+
+func newDistFileSingleton() Singleton {
+ return &distFileSingleton{}
+}
+
+func (d *distFileSingleton) GenerateBuildActions(ctx SingletonContext) {
+ out := PathForOutput(ctx, "my_singleton_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_singleton_goal", out)
+}
+
+type distFileSingletonModule struct {
+ SingletonModuleBase
+}
+
+func newDistFileSingletonModule() SingletonModule {
+ sm := &distFileSingletonModule{}
+ InitAndroidSingletonModule(sm)
+ return sm
+}
+
+// GenerateAndroidBuildActions implements SingletonModule.
+func (d *distFileSingletonModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ out := PathForModuleOut(ctx, "my_singleton_module_module_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_singleton_module_module_goal", out)
+}
+
+// GenerateSingletonBuildActions implements SingletonModule.
+func (d *distFileSingletonModule) GenerateSingletonBuildActions(ctx SingletonContext) {
+ out := PathForOutput(ctx, "my_singleton_module_singleton_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_singleton_module_singleton_goal", out)
+}
diff --git a/android/metrics.go b/android/metrics.go
index 6834b1b..dc51703 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -57,8 +57,8 @@
func (soongMetricsSingleton) GenerateBuildActions(ctx SingletonContext) {
metrics := getSoongMetrics(ctx.Config())
- ctx.VisitAllModules(func(m Module) {
- if ctx.PrimaryModule(m) == m {
+ ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+ if ctx.PrimaryModuleProxy(m) == m {
metrics.modules++
}
metrics.variants++
diff --git a/android/module.go b/android/module.go
index a9f6b94..1538861 100644
--- a/android/module.go
+++ b/android/module.go
@@ -15,12 +15,14 @@
package android
import (
+ "errors"
"fmt"
"net/url"
"path/filepath"
"reflect"
"slices"
"sort"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -43,6 +45,14 @@
// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
GenerateAndroidBuildActions(ModuleContext)
+ // CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished.
+ // If all interactions with this module are handled via providers instead of direct access
+ // to the module then it can free memory attached to the module.
+ // This is a temporary measure to reduce memory usage, eventually blueprint's reference
+ // to the Module should be dropped after GenerateAndroidBuildActions once all accesses
+ // can be done through providers.
+ CleanupAfterBuildActions()
+
// Add dependencies to the components of a module, i.e. modules that are created
// by the module and which are considered to be part of the creating module.
//
@@ -94,7 +104,6 @@
ReplacedByPrebuilt()
IsReplacedByPrebuilt() bool
ExportedToMake() bool
- EffectiveLicenseKinds() []string
EffectiveLicenseFiles() Paths
AddProperties(props ...interface{})
@@ -128,6 +137,9 @@
// WARNING: This should not be used outside build/soong/fsgen
// Overrides returns the list of modules which should not be installed if this module is installed.
Overrides() []string
+
+ // If this is true, the module must not read product-specific configurations.
+ UseGenericConfig() bool
}
// Qualified id for a module
@@ -196,6 +208,12 @@
// no change to the artifact file name.
Append_artifact_with_product *bool `android:"arch_variant"`
+ // If true, then the artifact file will be prepended with <product name>-. For
+ // example, if the product is coral and the module is an android_app module
+ // of name foo, then the artifact would be coral-foo.apk. If false, there is
+ // no change to the artifact file name.
+ Prepend_artifact_with_product *bool `android:"arch_variant"`
+
// A string tag to select the OutputFiles associated with the tag.
//
// If no tag is specified then it will select the default dist paths provided
@@ -257,6 +275,8 @@
Name *string
}
+// Properties common to all modules inheriting from ModuleBase. These properties are automatically
+// inherited by sub-modules created with ctx.CreateModule()
type commonProperties struct {
// emit build rules for this module
//
@@ -315,8 +335,6 @@
// Describes the licenses applicable to this module. Must reference license modules.
Licenses []string
- // Flattened from direct license dependencies. Equal to Licenses unless particular module adds more.
- Effective_licenses []string `blueprint:"mutated"`
// Override of module name when reporting licenses
Effective_package_name *string `blueprint:"mutated"`
// Notice files
@@ -409,15 +427,6 @@
// VINTF manifest fragments to be installed if this module is installed
Vintf_fragments proptools.Configurable[[]string] `android:"path"`
- // names of other modules to install if this module is installed
- Required proptools.Configurable[[]string] `android:"arch_variant"`
-
- // names of other modules to install on host if this module is installed
- Host_required []string `android:"arch_variant"`
-
- // names of other modules to install on target if this module is installed
- Target_required []string `android:"arch_variant"`
-
// The OsType of artifacts that this module variant is responsible for creating.
//
// Set by osMutator
@@ -516,6 +525,28 @@
// List of module names that are prevented from being installed when this module gets
// installed.
Overrides []string
+
+ // Set to true if this module must be generic and does not require product-specific information.
+ // To be included in the system image, this property must be set to true.
+ Use_generic_config *bool
+}
+
+// Properties common to all modules inheriting from ModuleBase. Unlike commonProperties, these
+// properties are NOT automatically inherited by sub-modules created with ctx.CreateModule()
+type baseProperties struct {
+ // names of other modules to install if this module is installed
+ Required proptools.Configurable[[]string] `android:"arch_variant"`
+
+ // names of other modules to install on host if this module is installed
+ Host_required []string `android:"arch_variant"`
+
+ // names of other modules to install on target if this module is installed
+ Target_required []string `android:"arch_variant"`
+
+ // If this is a soong config module, this property will be set to the name of the original
+ // module type. This is used by neverallow to ensure you can't bypass a ModuleType() matcher
+ // just by creating a soong config module type.
+ Soong_config_base_module_type *string `blueprint:"mutated"`
}
type distProperties struct {
@@ -610,17 +641,6 @@
return t
}
-func MakeDefaultDistFiles(paths ...Path) TaggedDistFiles {
- for _, p := range paths {
- if p == nil {
- panic("The path to a dist file cannot be nil.")
- }
- }
-
- // The default OutputFile tag is the empty "" string.
- return TaggedDistFiles{DefaultDistTag: paths}
-}
-
type hostAndDeviceProperties struct {
// If set to true, build a variant of the module for the host. Defaults to false.
Host_supported *bool
@@ -716,6 +736,7 @@
m.AddProperties(
&base.nameProperties,
&base.commonProperties,
+ &base.baseProperties,
&base.distProperties)
initProductVariableModule(m)
@@ -834,6 +855,7 @@
nameProperties nameProperties
commonProperties commonProperties
+ baseProperties baseProperties
distProperties distProperties
variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
@@ -990,8 +1012,9 @@
// 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.
+ // 4. aosp_kernel-build-tools invokes soong with `--soong-only`. Therefore, the absence of
+ // ALLOW_MISSING_DEPENDENCIES didn't cause a problem, as previously only make processed required
+ // dependencies.
// 5. Now, since Soong understands `required` deps, it tries to build `boot_signer` and the
// absence of external/bouncycastle fails the build.
//
@@ -1001,11 +1024,19 @@
pv := ctx.Config().productVariables
fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil
if fullManifest {
- addRequiredDeps(ctx)
addVintfFragmentDeps(ctx)
}
}
+// required property can be overridden too; handle it separately
+func (m *ModuleBase) baseOverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
+ pv := ctx.Config().productVariables
+ fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil
+ if fullManifest {
+ addRequiredDeps(ctx)
+ }
+}
+
// addRequiredDeps adds required, target_required, and host_required as dependencies.
func addRequiredDeps(ctx BottomUpMutatorContext) {
addDep := func(target Target, depName string) {
@@ -1049,7 +1080,7 @@
hostTargets = append(hostTargets, ctx.Config().BuildOSCommonTarget)
if ctx.Device() {
- for _, depName := range ctx.Module().RequiredModuleNames(ctx) {
+ for _, depName := range append(ctx.Module().RequiredModuleNames(ctx), ctx.Module().VintfFragmentModuleNames(ctx)...) {
for _, target := range deviceTargets {
addDep(target, depName)
}
@@ -1062,7 +1093,7 @@
}
if ctx.Host() {
- for _, depName := range ctx.Module().RequiredModuleNames(ctx) {
+ for _, depName := range append(ctx.Module().RequiredModuleNames(ctx), ctx.Module().VintfFragmentModuleNames(ctx)...) {
for _, target := range hostTargets {
// When a host module requires another host module, don't make a
// dependency if they have different OSes (i.e. hostcross).
@@ -1085,6 +1116,10 @@
InstallAlwaysNeededDependencyTag
}{}
+func IsVintfDepTag(depTag blueprint.DependencyTag) bool {
+ return depTag == vintfDepTag
+}
+
func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
// Vintf manifests in the recovery partition will be ignored.
if !ctx.Device() || ctx.Module().InstallInRecovery() {
@@ -1103,7 +1138,7 @@
// of nil pointer dereference errors, but we should resolve the missing dependencies.
continue
}
- if vintfModule, ok := vintf.(*vintfFragmentModule); ok {
+ if vintfModule, ok := vintf.(*VintfFragmentModule); ok {
vintfPartition := vintfModule.PartitionTag(deviceConfig)
if modPartition != vintfPartition {
ctx.ModuleErrorf("Module %q(%q) and Vintf_fragment %q(%q) are installed to different partitions.",
@@ -1220,6 +1255,13 @@
tag := proptools.StringDefault(dist.Tag, DefaultDistTag)
distFileForTagFromProvider, err := outputFilesForModuleFromProvider(ctx, m.module, tag)
+
+ // If the module doesn't define output files for the DefaultDistTag, try the files under
+ // the "" tag.
+ if tag == DefaultDistTag && errors.Is(err, ErrUnsupportedOutputTag) {
+ distFileForTagFromProvider, err = outputFilesForModuleFromProvider(ctx, m.module, "")
+ }
+
if err != OutputFilesProviderNotSet {
if err != nil && tag != DefaultDistTag {
ctx.PropertyErrorf("dist.tag", "%s", err.Error())
@@ -1458,10 +1500,6 @@
return m.commonProperties.NamespaceExportedToMake
}
-func (m *ModuleBase) EffectiveLicenseKinds() []string {
- return m.commonProperties.Effective_license_kinds
-}
-
func (m *ModuleBase) EffectiveLicenseFiles() Paths {
result := make(Paths, 0, len(m.commonProperties.Effective_license_text))
for _, p := range m.commonProperties.Effective_license_text {
@@ -1475,12 +1513,13 @@
func (m *ModuleBase) computeInstallDeps(ctx ModuleContext) ([]depset.DepSet[InstallPath], []depset.DepSet[PackagingSpec]) {
var installDeps []depset.DepSet[InstallPath]
var packagingSpecs []depset.DepSet[PackagingSpec]
- ctx.VisitDirectDeps(func(dep Module) {
- if isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
+ ctx.VisitDirectDepsProxy(func(dep ModuleProxy) {
+ if isInstallDepNeeded(ctx, dep) {
// Installation is still handled by Make, so anything hidden from Make is not
// installable.
info := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider)
- if !dep.IsHideFromMake() && !dep.IsSkipInstall() {
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider)
+ if !commonInfo.HideFromMake && !commonInfo.SkipInstall {
installDeps = append(installDeps, info.TransitiveInstallFiles)
}
// Add packaging deps even when the dependency is not installed so that uninstallable
@@ -1494,13 +1533,13 @@
// isInstallDepNeeded returns true if installing the output files of the current module
// should also install the output files of the given dependency and dependency tag.
-func isInstallDepNeeded(dep Module, tag blueprint.DependencyTag) bool {
+func isInstallDepNeeded(ctx ModuleContext, dep ModuleProxy) bool {
// Don't add a dependency from the platform to a library provided by an apex.
- if dep.base().commonProperties.UninstallableApexPlatformVariant {
+ if OtherModulePointerProviderOrDefault(ctx, dep, CommonModuleInfoProvider).UninstallableApexPlatformVariant {
return false
}
// Only install modules if the dependency tag is an InstallDepNeeded tag.
- return IsInstallDepNeededTag(tag)
+ return IsInstallDepNeededTag(ctx.OtherModuleDependencyTag(dep))
}
func (m *ModuleBase) NoAddressSanitizer() bool {
@@ -1617,15 +1656,15 @@
}
func (m *ModuleBase) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
- return m.base().commonProperties.Required.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
+ return m.base().baseProperties.Required.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
func (m *ModuleBase) HostRequiredModuleNames() []string {
- return m.base().commonProperties.Host_required
+ return m.base().baseProperties.Host_required
}
func (m *ModuleBase) TargetRequiredModuleNames() []string {
- return m.base().commonProperties.Target_required
+ return m.base().baseProperties.Target_required
}
func (m *ModuleBase) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string {
@@ -1650,55 +1689,41 @@
}
+// generateModuleTarget generates phony targets so that you can do `m <module-name>`.
+// It will be run on every variant of the module, so it relies on the fact that phony targets
+// are deduped to merge all the deps from different variants together.
func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
- var allInstalledFiles InstallPaths
- var allCheckbuildTargets Paths
- ctx.VisitAllModuleVariantProxies(func(module ModuleProxy) {
- var checkbuildTarget Path
- var uncheckedModule bool
- var skipAndroidMkProcessing bool
- if ctx.EqualModules(m.module, module) {
- allInstalledFiles = append(allInstalledFiles, ctx.installFiles...)
- checkbuildTarget = ctx.checkbuildTarget
- uncheckedModule = ctx.uncheckedModule
- skipAndroidMkProcessing = shouldSkipAndroidMkProcessing(ctx, m)
- } else {
- info := OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider)
- allInstalledFiles = append(allInstalledFiles, info.InstallFiles...)
- checkbuildTarget = info.CheckbuildTarget
- uncheckedModule = info.UncheckedModule
- skipAndroidMkProcessing = OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).SkipAndroidMkProcessing
- }
- // A module's -checkbuild phony targets should
- // not be created if the module is not exported to make.
- // Those could depend on the build target and fail to compile
- // for the current build target.
- if (!ctx.Config().KatiEnabled() || !skipAndroidMkProcessing) && !uncheckedModule && checkbuildTarget != nil {
- allCheckbuildTargets = append(allCheckbuildTargets, checkbuildTarget)
- }
- })
-
- var deps Paths
-
var namespacePrefix string
nameSpace := ctx.Namespace().Path
if nameSpace != "." {
namespacePrefix = strings.ReplaceAll(nameSpace, "/", ".") + "-"
}
- var info FinalModuleBuildTargetsInfo
+ var deps Paths
+ var info ModuleBuildTargetsInfo
- if len(allInstalledFiles) > 0 {
+ if len(ctx.installFiles) > 0 {
name := namespacePrefix + ctx.ModuleName() + "-install"
- ctx.Phony(name, allInstalledFiles.Paths()...)
+ installFiles := ctx.installFiles.Paths()
+ ctx.Phony(name, installFiles...)
info.InstallTarget = PathForPhony(ctx, name)
- deps = append(deps, info.InstallTarget)
+ deps = append(deps, installFiles...)
}
- if len(allCheckbuildTargets) > 0 {
+ // A module's -checkbuild phony targets should
+ // not be created if the module is not exported to make.
+ // Those could depend on the build target and fail to compile
+ // for the current build target.
+ if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil {
name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
- ctx.Phony(name, allCheckbuildTargets...)
- deps = append(deps, PathForPhony(ctx, name))
+ ctx.Phony(name, ctx.checkbuildTarget)
+ deps = append(deps, ctx.checkbuildTarget)
+ }
+
+ if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 {
+ name := namespacePrefix + ctx.ModuleName() + "-outputs"
+ ctx.Phony(name, outputFiles...)
+ deps = append(deps, outputFiles...)
}
if len(deps) > 0 {
@@ -1708,9 +1733,20 @@
}
ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
+ if ctx.Device() {
+ // Generate a target suffix for use in atest etc.
+ ctx.Phony(namespacePrefix+ctx.ModuleName()+"-target"+suffix, deps...)
+ } else {
+ // Generate a host suffix for use in atest etc.
+ ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host"+suffix, deps...)
+ if ctx.Target().HostCross {
+ // Generate a host-cross suffix for use in atest etc.
+ ctx.Phony(namespacePrefix+ctx.ModuleName()+"-host-cross"+suffix, deps...)
+ }
+ }
info.BlueprintDir = ctx.ModuleDir()
- SetProvider(ctx, FinalModuleBuildTargetsProvider, info)
+ SetProvider(ctx, ModuleBuildTargetsProvider, info)
}
}
@@ -1850,42 +1886,112 @@
Srcs Paths
}
-var SourceFilesInfoKey = blueprint.NewProvider[SourceFilesInfo]()
+var SourceFilesInfoProvider = blueprint.NewProvider[SourceFilesInfo]()
-type FinalModuleBuildTargetsInfo struct {
- // Used by buildTargetSingleton to create checkbuild and per-directory build targets
- // Only set on the final variant of each module
+// ModuleBuildTargetsInfo is used by buildTargetSingleton to create checkbuild and
+// per-directory build targets.
+type ModuleBuildTargetsInfo struct {
InstallTarget WritablePath
CheckbuildTarget WritablePath
BlueprintDir string
}
-var FinalModuleBuildTargetsProvider = blueprint.NewProvider[FinalModuleBuildTargetsInfo]()
+var ModuleBuildTargetsProvider = blueprint.NewProvider[ModuleBuildTargetsInfo]()
type CommonModuleInfo struct {
Enabled bool
// Whether the module has been replaced by a prebuilt
ReplacedByPrebuilt bool
// The Target of artifacts that this module variant is responsible for creating.
- CompileTarget Target
+ Target Target
SkipAndroidMkProcessing bool
BaseModuleName string
CanHaveApexVariants bool
+ MinSdkVersion ApiLevelOrPlatform
+ SdkVersion string
+ NotAvailableForPlatform bool
+ // There some subtle differences between this one and the one above.
+ NotInPlatform bool
+ // UninstallableApexPlatformVariant is set by MakeUninstallable called by the apex
+ // mutator. MakeUninstallable also sets HideFromMake. UninstallableApexPlatformVariant
+ // is used to avoid adding install or packaging dependencies into libraries provided
+ // by apexes.
+ UninstallableApexPlatformVariant bool
+ MinSdkVersionSupported ApiLevel
+ ModuleWithMinSdkVersionCheck bool
+ // Tests if this module can be installed to APEX as a file. For example, this would return
+ // true for shared libs while return false for static libs because static libs are not
+ // installable module (but it can still be mutated for APEX)
+ IsInstallableToApex bool
+ HideFromMake bool
+ SkipInstall bool
+ IsStubsModule bool
+ Host bool
+ IsApexModule bool
+ // The primary licenses property, may be nil, records license metadata for the module.
+ PrimaryLicensesProperty applicableLicensesProperty
+ Owner string
+ Vendor bool
+ Proprietary bool
+ SocSpecific bool
+ ProductSpecific bool
+ SystemExtSpecific bool
+ DeviceSpecific bool
+ // When set to true, this module is not installed to the full install path (ex: under
+ // out/target/product/<name>/<partition>). It can be installed only to the packaging
+ // modules like android_filesystem.
+ NoFullInstall bool
+ InVendorRamdisk bool
+ ExemptFromRequiredApplicableLicensesProperty bool
+ RequiredModuleNames []string
+ HostRequiredModuleNames []string
+ TargetRequiredModuleNames []string
+ VintfFragmentModuleNames []string
+ Dists []Dist
+ ExportedToMake bool
+ Team string
+ PartitionTag string
}
-var CommonModuleInfoKey = blueprint.NewProvider[CommonModuleInfo]()
-
-type PrebuiltModuleProviderData struct {
- // Empty for now
+type ApiLevelOrPlatform struct {
+ ApiLevel *ApiLevel
+ IsPlatform bool
}
-var PrebuiltModuleProviderKey = blueprint.NewProvider[PrebuiltModuleProviderData]()
+var CommonModuleInfoProvider = blueprint.NewProvider[*CommonModuleInfo]()
-type HostToolProviderData struct {
+type PrebuiltModuleInfo struct {
+ SourceExists bool
+ UsePrebuilt bool
+}
+
+var PrebuiltModuleInfoProvider = blueprint.NewProvider[PrebuiltModuleInfo]()
+
+type HostToolProviderInfo struct {
HostToolPath OptionalPath
}
-var HostToolProviderKey = blueprint.NewProvider[HostToolProviderData]()
+var HostToolProviderInfoProvider = blueprint.NewProvider[HostToolProviderInfo]()
+
+type DistInfo struct {
+ Dists []dist
+}
+
+var DistProvider = blueprint.NewProvider[DistInfo]()
+
+type SourceFileGenerator interface {
+ GeneratedSourceFiles() Paths
+ GeneratedHeaderDirs() Paths
+ GeneratedDeps() Paths
+}
+
+type GeneratedSourceInfo struct {
+ GeneratedSourceFiles Paths
+ GeneratedHeaderDirs Paths
+ GeneratedDeps Paths
+}
+
+var GeneratedSourceInfoProvider = blueprint.NewProvider[GeneratedSourceInfo]()
func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
ctx := &moduleContext{
@@ -2058,14 +2164,19 @@
}
if sourceFileProducer, ok := m.module.(SourceFileProducer); ok {
- SetProvider(ctx, SourceFilesInfoKey, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()})
+ srcs := sourceFileProducer.Srcs()
+ for _, src := range srcs {
+ if src == nil {
+ ctx.ModuleErrorf("SourceFileProducer cannot return nil srcs")
+ return
+ }
+ }
+ SetProvider(ctx, SourceFilesInfoProvider, SourceFilesInfo{Srcs: sourceFileProducer.Srcs()})
}
- if ctx.IsFinalModule(m.module) {
- m.generateModuleTarget(ctx)
- if ctx.Failed() {
- return
- }
+ m.generateModuleTarget(ctx)
+ if ctx.Failed() {
+ return
}
ctx.TransitiveInstallFiles = depset.New[InstallPath](depset.TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles)
@@ -2075,47 +2186,85 @@
SetProvider(ctx, InstallFilesProvider, installFiles)
buildLicenseMetadata(ctx, ctx.licenseMetadataFile)
- if ctx.moduleInfoJSON != nil {
- var installed InstallPaths
- installed = append(installed, ctx.katiInstalls.InstallPaths()...)
- installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
- installed = append(installed, ctx.katiInitRcInstalls.InstallPaths()...)
- installed = append(installed, ctx.katiVintfInstalls.InstallPaths()...)
- installedStrings := installed.Strings()
+ if len(ctx.moduleInfoJSON) > 0 {
+ for _, moduleInfoJSON := range ctx.moduleInfoJSON {
+ if moduleInfoJSON.Disabled {
+ continue
+ }
+ var installed InstallPaths
+ installed = append(installed, ctx.katiInstalls.InstallPaths()...)
+ installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
+ installed = append(installed, ctx.katiInitRcInstalls.InstallPaths()...)
+ installed = append(installed, ctx.katiVintfInstalls.InstallPaths()...)
+ installedStrings := installed.Strings()
- var targetRequired, hostRequired []string
- if ctx.Host() {
- targetRequired = m.commonProperties.Target_required
- } else {
- hostRequired = m.commonProperties.Host_required
- }
+ var targetRequired, hostRequired []string
+ if ctx.Host() {
+ targetRequired = m.baseProperties.Target_required
+ } else {
+ hostRequired = m.baseProperties.Host_required
+ }
+ hostRequired = append(hostRequired, moduleInfoJSON.ExtraHostRequired...)
- var data []string
- for _, d := range ctx.testData {
- data = append(data, d.ToRelativeInstallPath())
- }
+ var data []string
+ for _, d := range ctx.testData {
+ data = append(data, d.ToRelativeInstallPath())
+ }
- if ctx.moduleInfoJSON.Uninstallable {
- installedStrings = nil
- if len(ctx.moduleInfoJSON.CompatibilitySuites) == 1 && ctx.moduleInfoJSON.CompatibilitySuites[0] == "null-suite" {
- ctx.moduleInfoJSON.CompatibilitySuites = nil
- ctx.moduleInfoJSON.TestConfig = nil
- ctx.moduleInfoJSON.AutoTestConfig = nil
- data = nil
+ if moduleInfoJSON.Uninstallable {
+ installedStrings = nil
+ if len(moduleInfoJSON.CompatibilitySuites) == 1 && moduleInfoJSON.CompatibilitySuites[0] == "null-suite" {
+ moduleInfoJSON.CompatibilitySuites = nil
+ moduleInfoJSON.TestConfig = nil
+ moduleInfoJSON.AutoTestConfig = nil
+ data = nil
+ }
+ }
+
+ // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
+ // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite,
+ // we add the full test suite to our list. This was inherited from
+ // AndroidMkEntries.AddCompatibilityTestSuites.
+ suites := moduleInfoJSON.CompatibilitySuites
+ if PrefixInList(suites, "mts-") && !InList("mts", suites) {
+ suites = append(suites, "mts")
+ }
+ if PrefixInList(suites, "mcts-") && !InList("mcts", suites) {
+ suites = append(suites, "mcts")
+ }
+ moduleInfoJSON.CompatibilitySuites = suites
+
+ required := append(m.RequiredModuleNames(ctx), m.VintfFragmentModuleNames(ctx)...)
+ required = append(required, moduleInfoJSON.ExtraRequired...)
+
+ registerName := moduleInfoJSON.RegisterNameOverride
+ if len(registerName) == 0 {
+ registerName = m.moduleInfoRegisterName(ctx, moduleInfoJSON.SubName)
+ }
+
+ moduleName := moduleInfoJSON.ModuleNameOverride
+ if len(moduleName) == 0 {
+ moduleName = m.BaseModuleName() + moduleInfoJSON.SubName
+ }
+
+ supportedVariants := moduleInfoJSON.SupportedVariantsOverride
+ if moduleInfoJSON.SupportedVariantsOverride == nil {
+ supportedVariants = []string{m.moduleInfoVariant(ctx)}
+ }
+
+ moduleInfoJSON.core = CoreModuleInfoJSON{
+ RegisterName: registerName,
+ Path: []string{ctx.ModuleDir()},
+ Installed: installedStrings,
+ ModuleName: moduleName,
+ SupportedVariants: supportedVariants,
+ TargetDependencies: targetRequired,
+ HostDependencies: hostRequired,
+ Data: data,
+ Required: required,
}
}
- ctx.moduleInfoJSON.core = CoreModuleInfoJSON{
- RegisterName: m.moduleInfoRegisterName(ctx, ctx.moduleInfoJSON.SubName),
- Path: []string{ctx.ModuleDir()},
- Installed: installedStrings,
- ModuleName: m.BaseModuleName() + ctx.moduleInfoJSON.SubName,
- SupportedVariants: []string{m.moduleInfoVariant(ctx)},
- TargetDependencies: targetRequired,
- HostDependencies: hostRequired,
- Data: data,
- Required: append(m.RequiredModuleNames(ctx), m.VintfFragmentModuleNames(ctx)...),
- }
SetProvider(ctx, ModuleInfoJSONProvider, ctx.moduleInfoJSON)
}
@@ -2133,35 +2282,131 @@
Phonies: ctx.phonies,
})
}
+
+ if len(ctx.dists) > 0 {
+ SetProvider(ctx, DistProvider, DistInfo{
+ Dists: ctx.dists,
+ })
+ }
+
buildComplianceMetadataProvider(ctx, m)
commonData := CommonModuleInfo{
- ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
- CompileTarget: m.commonProperties.CompileTarget,
- SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
- BaseModuleName: m.BaseModuleName(),
+ Enabled: m.Enabled(ctx),
+ ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
+ Target: m.commonProperties.CompileTarget,
+ SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
+ UninstallableApexPlatformVariant: m.commonProperties.UninstallableApexPlatformVariant,
+ HideFromMake: m.commonProperties.HideFromMake,
+ SkipInstall: m.commonProperties.SkipInstall,
+ Host: m.Host(),
+ PrimaryLicensesProperty: m.primaryLicensesProperty,
+ Owner: m.module.Owner(),
+ SocSpecific: Bool(m.commonProperties.Soc_specific),
+ Vendor: Bool(m.commonProperties.Vendor),
+ Proprietary: Bool(m.commonProperties.Proprietary),
+ ProductSpecific: Bool(m.commonProperties.Product_specific),
+ SystemExtSpecific: Bool(m.commonProperties.System_ext_specific),
+ DeviceSpecific: Bool(m.commonProperties.Device_specific),
+ NoFullInstall: proptools.Bool(m.commonProperties.No_full_install),
+ InVendorRamdisk: m.InVendorRamdisk(),
+ ExemptFromRequiredApplicableLicensesProperty: exemptFromRequiredApplicableLicensesProperty(m.module),
+ RequiredModuleNames: m.module.RequiredModuleNames(ctx),
+ HostRequiredModuleNames: m.module.HostRequiredModuleNames(),
+ TargetRequiredModuleNames: m.module.TargetRequiredModuleNames(),
+ VintfFragmentModuleNames: m.module.VintfFragmentModuleNames(ctx),
+ Dists: m.Dists(),
+ ExportedToMake: m.ExportedToMake(),
+ Team: m.Team(),
+ PartitionTag: m.PartitionTag(ctx.DeviceConfig()),
}
- if m.commonProperties.ForcedDisabled {
- commonData.Enabled = false
- } else {
- commonData.Enabled = m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
+ if mm, ok := m.module.(interface {
+ MinSdkVersion(ctx EarlyModuleContext) ApiLevel
+ }); ok {
+ ver := mm.MinSdkVersion(ctx)
+ commonData.MinSdkVersion.ApiLevel = &ver
+ } else if mm, ok := m.module.(interface{ MinSdkVersion() string }); ok {
+ ver := mm.MinSdkVersion()
+ // Compile against the current platform
+ if ver == "" {
+ commonData.MinSdkVersion.IsPlatform = true
+ } else {
+ api := ApiLevelFrom(ctx, ver)
+ commonData.MinSdkVersion.ApiLevel = &api
+ }
}
- am, ok := m.module.(ApexModule)
- commonData.CanHaveApexVariants = ok && am.CanHaveApexVariants()
- SetProvider(ctx, CommonModuleInfoKey, commonData)
+
+ if mm, ok := m.module.(interface {
+ SdkVersion(ctx EarlyModuleContext) ApiLevel
+ }); ok {
+ ver := mm.SdkVersion(ctx)
+ if !ver.IsNone() {
+ commonData.SdkVersion = ver.String()
+ }
+ } else if mm, ok := m.module.(interface{ SdkVersion() string }); ok {
+ commonData.SdkVersion = mm.SdkVersion()
+ }
+
+ if am, ok := m.module.(ApexModule); ok {
+ commonData.CanHaveApexVariants = am.CanHaveApexVariants()
+ commonData.NotAvailableForPlatform = am.NotAvailableForPlatform()
+ commonData.NotInPlatform = am.NotInPlatform()
+ commonData.MinSdkVersionSupported = am.MinSdkVersionSupported(ctx)
+ commonData.IsInstallableToApex = am.IsInstallableToApex()
+ commonData.IsApexModule = true
+ }
+
+ if _, ok := m.module.(ModuleWithMinSdkVersionCheck); ok {
+ commonData.ModuleWithMinSdkVersionCheck = true
+ }
+
+ if st, ok := m.module.(StubsAvailableModule); ok {
+ commonData.IsStubsModule = st.IsStubsModule()
+ }
+ if mm, ok := m.module.(interface{ BaseModuleName() string }); ok {
+ commonData.BaseModuleName = mm.BaseModuleName()
+ }
+ SetProvider(ctx, CommonModuleInfoProvider, &commonData)
if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
- SetProvider(ctx, PrebuiltModuleProviderKey, PrebuiltModuleProviderData{})
+ SetProvider(ctx, PrebuiltModuleInfoProvider, PrebuiltModuleInfo{
+ SourceExists: p.Prebuilt().SourceExists(),
+ UsePrebuilt: p.Prebuilt().UsePrebuilt(),
+ })
}
if h, ok := m.module.(HostToolProvider); ok {
- SetProvider(ctx, HostToolProviderKey, HostToolProviderData{
+ SetProvider(ctx, HostToolProviderInfoProvider, HostToolProviderInfo{
HostToolPath: h.HostToolPath()})
}
if p, ok := m.module.(AndroidMkProviderInfoProducer); ok && !commonData.SkipAndroidMkProcessing {
SetProvider(ctx, AndroidMkInfoProvider, p.PrepareAndroidMKProviderInfo(ctx.Config()))
}
+
+ if s, ok := m.module.(SourceFileGenerator); ok {
+ SetProvider(ctx, GeneratedSourceInfoProvider, GeneratedSourceInfo{
+ GeneratedSourceFiles: s.GeneratedSourceFiles(),
+ GeneratedHeaderDirs: s.GeneratedHeaderDirs(),
+ GeneratedDeps: s.GeneratedDeps(),
+ })
+ }
+
+ if m.Enabled(ctx) {
+ if v, ok := m.module.(ModuleMakeVarsProvider); ok {
+ SetProvider(ctx, ModuleMakeVarsInfoProvider, v.MakeVars(ctx))
+ }
+
+ if am, ok := m.module.(AndroidMkDataProvider); ok {
+ SetProvider(ctx, AndroidMkDataInfoProvider, AndroidMkDataInfo{
+ Class: am.AndroidMk().Class,
+ })
+ }
+ }
+
+ m.module.CleanupAfterBuildActions()
}
+func (m *ModuleBase) CleanupAfterBuildActions() {}
+
func SetJarJarPrefixHandler(handler func(ModuleContext)) {
if jarJarPrefixHandler != nil {
panic("jarJarPrefixHandler already set")
@@ -2183,7 +2428,7 @@
arches = slices.DeleteFunc(arches, func(target Target) bool {
return target.NativeBridge != ctx.Target().NativeBridge
})
- if len(arches) > 0 && ctx.Arch().ArchType != arches[0].Arch.ArchType {
+ if len(arches) > 0 && ctx.Arch().ArchType != arches[0].Arch.ArchType && ctx.Arch().ArchType != Common {
if ctx.Arch().ArchType.Multilib == "lib32" {
suffix = "_32"
} else {
@@ -2369,6 +2614,10 @@
return m.commonProperties.Overrides
}
+func (m *ModuleBase) UseGenericConfig() bool {
+ return proptools.Bool(m.commonProperties.Use_generic_config)
+}
+
type ConfigContext interface {
Config() Config
}
@@ -2436,11 +2685,15 @@
return proptools.ConfigurableValueBool(ctx.Config().BuildFromTextStub())
case "debuggable":
return proptools.ConfigurableValueBool(ctx.Config().Debuggable())
+ case "eng":
+ return proptools.ConfigurableValueBool(ctx.Config().Eng())
case "use_debug_art":
// TODO(b/234351700): Remove once ART does not have separated debug APEX
return proptools.ConfigurableValueBool(ctx.Config().UseDebugArt())
case "selinux_ignore_neverallows":
return proptools.ConfigurableValueBool(ctx.Config().SelinuxIgnoreNeverallows())
+ case "always_use_prebuilt_sdks":
+ return proptools.ConfigurableValueBool(ctx.Config().AlwaysUsePrebuiltSdks())
default:
// TODO(b/323382414): Might add these on a case-by-case basis
ctx.OtherModulePropertyErrorf(m, property, fmt.Sprintf("TODO(b/323382414): Product variable %q is not yet supported in selects", variable))
@@ -2465,6 +2718,13 @@
return proptools.ConfigurableValueString(v)
case "bool":
return proptools.ConfigurableValueBool(v == "true")
+ case "int":
+ i, err := strconv.ParseInt(v, 10, 64)
+ if err != nil {
+ ctx.OtherModulePropertyErrorf(m, property, "integer soong_config_variable was not an int: %q", v)
+ return proptools.ConfigurableValueUndefined()
+ }
+ return proptools.ConfigurableValueInt(i)
case "string_list":
return proptools.ConfigurableValueStringList(strings.Split(v, " "))
default:
@@ -2674,6 +2934,8 @@
// OutputFileForModule returns the output file paths with the given tag. On error, including if the
// module produced zero or multiple paths, it reports errors to the ctx and returns nil.
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
func OutputFileForModule(ctx PathContext, module Module, tag string) Path {
paths, err := outputFilesForModule(ctx, module, tag)
if err != nil {
@@ -2711,9 +2973,10 @@
OtherModuleProviderContext
Module() Module
GetOutputFiles() OutputFilesInfo
- EqualModules(m1, m2 Module) bool
}
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
func outputFilesForModule(ctx PathContext, module Module, tag string) (Paths, error) {
outputFilesFromProvider, err := outputFilesForModuleFromProvider(ctx, module, tag)
if outputFilesFromProvider != nil || err != OutputFilesProviderNotSet {
@@ -2721,11 +2984,12 @@
}
if octx, ok := ctx.(OutputFilesProviderModuleContext); ok {
- if octx.EqualModules(octx.Module(), module) {
+ if EqualModules(octx.Module(), module) {
+ // It is the current module, we can access the srcs through interface
if sourceFileProducer, ok := module.(SourceFileProducer); ok {
return sourceFileProducer.Srcs(), nil
}
- } else if sourceFiles, ok := OtherModuleProvider(octx, module, SourceFilesInfoKey); ok {
+ } else if sourceFiles, ok := OtherModuleProvider(octx, module, SourceFilesInfoProvider); ok {
if tag != "" {
return nil, fmt.Errorf("module %q is a SourceFileProducer, which does not support tag %q", pathContextName(ctx, module), tag)
}
@@ -2745,14 +3009,12 @@
// If a module doesn't have the OutputFilesProvider, nil is returned.
func outputFilesForModuleFromProvider(ctx PathContext, module Module, tag string) (Paths, error) {
var outputFiles OutputFilesInfo
- fromProperty := false
if mctx, isMctx := ctx.(OutputFilesProviderModuleContext); isMctx {
- if !mctx.EqualModules(mctx.Module(), module) {
+ if !EqualModules(mctx.Module(), module) {
outputFiles, _ = OtherModuleProvider(mctx, module, OutputFilesProvider)
} else {
outputFiles = mctx.GetOutputFiles()
- fromProperty = true
}
} else if cta, isCta := ctx.(*singletonContextAdaptor); isCta {
outputFiles, _ = OtherModuleProvider(cta, module, OutputFilesProvider)
@@ -2769,10 +3031,8 @@
} else if taggedOutputFiles, hasTag := outputFiles.TaggedOutputFiles[tag]; hasTag {
return taggedOutputFiles, nil
} else {
- if fromProperty {
- return nil, fmt.Errorf("unsupported tag %q for module getting its own output files", tag)
- } else {
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ return nil, UnsupportedOutputTagError{
+ tag: tag,
}
}
}
@@ -2791,8 +3051,24 @@
var OutputFilesProvider = blueprint.NewProvider[OutputFilesInfo]()
+type UnsupportedOutputTagError struct {
+ tag string
+}
+
+func (u UnsupportedOutputTagError) Error() string {
+ return fmt.Sprintf("unsupported output tag %q", u.tag)
+}
+
+func (u UnsupportedOutputTagError) Is(e error) bool {
+ _, ok := e.(UnsupportedOutputTagError)
+ return ok
+}
+
+var _ error = UnsupportedOutputTagError{}
+
// This is used to mark the case where OutputFilesProvider is not set on some modules.
var OutputFilesProviderNotSet = fmt.Errorf("No output files from provider")
+var ErrUnsupportedOutputTag = UnsupportedOutputTagError{}
// Modules can implement HostToolProvider and return a valid OptionalPath from HostToolPath() to
// specify that they can be used as a tool by a genrule module.
@@ -2849,14 +3125,17 @@
func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
var checkbuildDeps Paths
+ // Create a top level partialcompileclean target for modules to add dependencies to.
+ ctx.Phony("partialcompileclean")
+
mmTarget := func(dir string) string {
return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
}
modulesInDir := make(map[string]Paths)
- ctx.VisitAllModules(func(module Module) {
- info := OtherModuleProviderOrDefault(ctx, module, FinalModuleBuildTargetsProvider)
+ ctx.VisitAllModuleProxies(func(module ModuleProxy) {
+ info := OtherModuleProviderOrDefault(ctx, module, ModuleBuildTargetsProvider)
if info.CheckbuildTarget != nil {
checkbuildDeps = append(checkbuildDeps, info.CheckbuildTarget)
@@ -2938,14 +3217,6 @@
BaseModuleName() string
}
-// Extract the base module name from the Import name.
-// Often the Import name has a prefix "prebuilt_".
-// Remove the prefix explicitly if needed
-// until we find a better solution to get the Import name.
-type IDECustomizedModuleName interface {
- IDECustomizedModuleName() string
-}
-
// Collect information for opening IDE project files in java/jdeps.go.
type IdeInfo struct {
BaseModuleName string `json:"-"`
diff --git a/android/module_context.go b/android/module_context.go
index ae7b54f..0a23a74 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -24,6 +24,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/depset"
"github.com/google/blueprint/proptools"
+ "github.com/google/blueprint/uniquelist"
)
// BuildParameters describes the set of potential parameters to build a Ninja rule.
@@ -75,11 +76,13 @@
// Validations is a slice of output path for a validation action. Validation outputs imply lower
// non-blocking priority to building non-validation outputs.
Validations Paths
- // Whether to skip outputting a default target statement which will be built by Ninja when no
+ // Whether to output a default target statement which will be built by Ninja when no
// targets are specified on Ninja's command line.
Default bool
// Args is a key value mapping for replacements of variables within the Rule
Args map[string]string
+ // PhonyOutput marks this build as `phony_output = true`
+ PhonyOutput bool
}
type ModuleBuildParams BuildParams
@@ -230,6 +233,10 @@
// the module-info.json generated by Make, and Make will not generate its own data for this module.
ModuleInfoJSON() *ModuleInfoJSON
+ // Simiar to ModuleInfoJSON, ExtraModuleInfoJSON also returns a pointer to the ModuleInfoJSON struct.
+ // This should only be called by a module that generates multiple AndroidMkEntries struct.
+ ExtraModuleInfoJSON() *ModuleInfoJSON
+
// SetOutputFiles stores the outputFiles to outputFiles property, which is used
// to set the OutputFilesProvider later.
SetOutputFiles(outputFiles Paths, tag string)
@@ -250,6 +257,24 @@
setContainersInfo(info ContainersInfo)
setAconfigPaths(paths Paths)
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoal(goal string, paths ...Path)
+
+ // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when the specified
+ // goal is built.
+ DistForGoalWithFilename(goal string, path Path, filename string)
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoals(goals []string, paths ...Path)
+
+ // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when any of the
+ // specified goals are built.
+ DistForGoalsWithFilename(goals []string, path Path, filename string)
}
type moduleContext struct {
@@ -295,7 +320,7 @@
// moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
// be included in the final module-info.json produced by Make.
- moduleInfoJSON *ModuleInfoJSON
+ moduleInfoJSON []*ModuleInfoJSON
// containersInfo stores the information about the containers and the information of the
// apexes the module belongs to.
@@ -307,6 +332,8 @@
// complianceMetadataInfo is for different module types to dump metadata.
// See android.ModuleContext interface.
complianceMetadataInfo *ComplianceMetadataInfo
+
+ dists []dist
}
var _ ModuleContext = &moduleContext{}
@@ -343,7 +370,8 @@
OrderOnly: params.OrderOnly.Strings(),
Validations: params.Validations.Strings(),
Args: params.Args,
- Optional: !params.Default,
+ Default: params.Default,
+ PhonyOutput: params.PhonyOutput,
}
if params.Depfile != nil {
@@ -428,6 +456,11 @@
}
func (m *moduleContext) Phony(name string, deps ...Path) {
+ for _, dep := range deps {
+ if dep == nil {
+ panic("Phony dep cannot be nil")
+ }
+ }
m.phonies[name] = append(m.phonies[name], deps...)
}
@@ -440,10 +473,27 @@
}
func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
- if module, _ := m.getDirectDepInternal(name, tag); module != nil {
- return module.(Module)
+ deps := m.getDirectDepsInternal(name, tag)
+ if len(deps) == 1 {
+ return deps[0]
+ } else if len(deps) >= 2 {
+ panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
+ name, m.ModuleName()))
+ } else {
+ return nil
}
- return nil
+}
+
+func (m *moduleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
+ deps := m.getDirectDepsProxyInternal(name, tag)
+ if len(deps) == 1 {
+ return &deps[0]
+ } else if len(deps) >= 2 {
+ panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
+ name, m.ModuleName()))
+ } else {
+ return nil
+ }
}
func (m *moduleContext) ModuleSubDir() string {
@@ -569,11 +619,11 @@
func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
fullInstallPath := installPath.Join(m, name)
- return m.packageFile(fullInstallPath, srcPath, false)
+ return m.packageFile(fullInstallPath, srcPath, false, false)
}
-func (m *moduleContext) getAconfigPaths() *Paths {
- return &m.aconfigFilePaths
+func (m *moduleContext) getAconfigPaths() Paths {
+ return m.aconfigFilePaths
}
func (m *moduleContext) setAconfigPaths(paths Paths) {
@@ -593,7 +643,7 @@
return owner, overrides
}
-func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
+func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool, requiresFullInstall bool) PackagingSpec {
licenseFiles := m.Module().EffectiveLicenseFiles()
owner, overrides := m.getOwnerAndOverrides()
spec := PackagingSpec{
@@ -601,13 +651,16 @@
srcPath: srcPath,
symlinkTarget: "",
executable: executable,
- effectiveLicenseFiles: &licenseFiles,
+ effectiveLicenseFiles: uniquelist.Make(licenseFiles),
partition: fullInstallPath.partition,
skipInstall: m.skipInstall(),
- aconfigPaths: m.getAconfigPaths(),
+ aconfigPaths: uniquelist.Make(m.getAconfigPaths()),
archType: m.target.Arch.ArchType,
- overrides: &overrides,
+ overrides: uniquelist.Make(overrides),
owner: owner,
+ requiresFullInstall: requiresFullInstall,
+ fullInstallPath: fullInstallPath,
+ variation: m.ModuleSubDir(),
}
m.packagingSpecs = append(m.packagingSpecs, spec)
return spec
@@ -615,6 +668,9 @@
func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
executable bool, hooks bool, checkbuild bool, extraZip *extraFilesZip) InstallPath {
+ if _, ok := srcPath.(InstallPath); ok {
+ m.ModuleErrorf("Src path cannot be another installed file. Please use a path from source or intermediates instead.")
+ }
fullInstallPath := installPath.Join(m, name)
if hooks {
@@ -623,8 +679,10 @@
if m.requiresFullInstall() {
deps = append(deps, InstallPaths(m.TransitiveInstallFiles.ToList())...)
- deps = append(deps, m.installedInitRcPaths...)
- deps = append(deps, m.installedVintfFragmentsPaths...)
+ if m.config.KatiEnabled() {
+ deps = append(deps, m.installedInitRcPaths...)
+ deps = append(deps, m.installedVintfFragmentsPaths...)
+ }
var implicitDeps, orderOnlyDeps Paths
@@ -636,22 +694,24 @@
orderOnlyDeps = InstallPaths(deps).Paths()
}
- if m.Config().KatiEnabled() {
- // When creating the install rule in Soong but embedding in Make, write the rule to a
- // makefile instead of directly to the ninja file so that main.mk can add the
- // dependencies from the `required` property that are hard to resolve in Soong.
- m.katiInstalls = append(m.katiInstalls, katiInstall{
- from: srcPath,
- to: fullInstallPath,
- implicitDeps: implicitDeps,
- orderOnlyDeps: orderOnlyDeps,
- executable: executable,
- extraFiles: extraZip,
- })
- } else {
- rule := Cp
+ // When creating the install rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ // In soong-only builds, the katiInstall will still be created for semi-legacy code paths
+ // such as module-info.json or compliance, but it will not be used for actually installing
+ // the file.
+ m.katiInstalls = append(m.katiInstalls, katiInstall{
+ from: srcPath,
+ to: fullInstallPath,
+ implicitDeps: implicitDeps,
+ orderOnlyDeps: orderOnlyDeps,
+ executable: executable,
+ extraFiles: extraZip,
+ })
+ if !m.Config().KatiEnabled() {
+ rule := CpWithBash
if executable {
- rule = CpExecutable
+ rule = CpExecutableWithBash
}
extraCmds := ""
@@ -662,6 +722,17 @@
implicitDeps = append(implicitDeps, extraZip.zip)
}
+ var cpFlags = "-f"
+
+ // If this is a device file, copy while preserving timestamps. This is to support
+ // adb sync in soong-only builds. Because soong-only builds have 2 different staging
+ // directories, the out/target/product one and the out/soong/.intermediates one,
+ // we need to ensure the files in them have the same timestamps so that adb sync doesn't
+ // update the files on device.
+ if strings.Contains(fullInstallPath.String(), "target/product") {
+ cpFlags += " -p"
+ }
+
m.Build(pctx, BuildParams{
Rule: rule,
Description: "install " + fullInstallPath.Base(),
@@ -669,9 +740,9 @@
Input: srcPath,
Implicits: implicitDeps,
OrderOnly: orderOnlyDeps,
- Default: !m.Config().KatiEnabled(),
Args: map[string]string{
"extraCmds": extraCmds,
+ "cpFlags": cpFlags,
},
})
}
@@ -679,9 +750,12 @@
m.installFiles = append(m.installFiles, fullInstallPath)
}
- m.packageFile(fullInstallPath, srcPath, executable)
+ m.packageFile(fullInstallPath, srcPath, executable, m.requiresFullInstall())
if checkbuild {
+ if srcPath == nil {
+ panic("srcPath cannot be nil")
+ }
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
@@ -698,25 +772,26 @@
}
if m.requiresFullInstall() {
- if m.Config().KatiEnabled() {
- // When creating the symlink rule in Soong but embedding in Make, write the rule to a
- // makefile instead of directly to the ninja file so that main.mk can add the
- // dependencies from the `required` property that are hard to resolve in Soong.
- m.katiSymlinks = append(m.katiSymlinks, katiInstall{
- from: srcPath,
- to: fullInstallPath,
- })
- } else {
+ // When creating the symlink rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ // In soong-only builds, the katiInstall will still be created for semi-legacy code paths
+ // such as module-info.json or compliance, but it will not be used for actually installing
+ // the file.
+ m.katiSymlinks = append(m.katiSymlinks, katiInstall{
+ from: srcPath,
+ to: fullInstallPath,
+ })
+ if !m.Config().KatiEnabled() {
// The symlink doesn't need updating when the target is modified, but we sometimes
// have a dependency on a symlink to a binary instead of to the binary directly, and
// the mtime of the symlink must be updated when the binary is modified, so use a
// normal dependency here instead of an order-only dependency.
m.Build(pctx, BuildParams{
- Rule: Symlink,
+ Rule: SymlinkWithBash,
Description: "install symlink " + fullInstallPath.Base(),
Output: fullInstallPath,
Input: srcPath,
- Default: !m.Config().KatiEnabled(),
Args: map[string]string{
"fromPath": relPath,
},
@@ -728,16 +803,19 @@
owner, overrides := m.getOwnerAndOverrides()
m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
- relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
- srcPath: nil,
- symlinkTarget: relPath,
- executable: false,
- partition: fullInstallPath.partition,
- skipInstall: m.skipInstall(),
- aconfigPaths: m.getAconfigPaths(),
- archType: m.target.Arch.ArchType,
- overrides: &overrides,
- owner: owner,
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: relPath,
+ executable: false,
+ partition: fullInstallPath.partition,
+ skipInstall: m.skipInstall(),
+ aconfigPaths: uniquelist.Make(m.getAconfigPaths()),
+ archType: m.target.Arch.ArchType,
+ overrides: uniquelist.Make(overrides),
+ owner: owner,
+ requiresFullInstall: m.requiresFullInstall(),
+ fullInstallPath: fullInstallPath,
+ variation: m.ModuleSubDir(),
})
return fullInstallPath
@@ -750,20 +828,21 @@
m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
if m.requiresFullInstall() {
- if m.Config().KatiEnabled() {
- // When creating the symlink rule in Soong but embedding in Make, write the rule to a
- // makefile instead of directly to the ninja file so that main.mk can add the
- // dependencies from the `required` property that are hard to resolve in Soong.
- m.katiSymlinks = append(m.katiSymlinks, katiInstall{
- absFrom: absPath,
- to: fullInstallPath,
- })
- } else {
+ // When creating the symlink rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ // In soong-only builds, the katiInstall will still be created for semi-legacy code paths
+ // such as module-info.json or compliance, but it will not be used for actually installing
+ // the file.
+ m.katiSymlinks = append(m.katiSymlinks, katiInstall{
+ absFrom: absPath,
+ to: fullInstallPath,
+ })
+ if !m.Config().KatiEnabled() {
m.Build(pctx, BuildParams{
- Rule: Symlink,
+ Rule: SymlinkWithBash,
Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
Output: fullInstallPath,
- Default: !m.Config().KatiEnabled(),
Args: map[string]string{
"fromPath": absPath,
},
@@ -775,16 +854,19 @@
owner, overrides := m.getOwnerAndOverrides()
m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
- relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
- srcPath: nil,
- symlinkTarget: absPath,
- executable: false,
- partition: fullInstallPath.partition,
- skipInstall: m.skipInstall(),
- aconfigPaths: m.getAconfigPaths(),
- archType: m.target.Arch.ArchType,
- overrides: &overrides,
- owner: owner,
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: absPath,
+ executable: false,
+ partition: fullInstallPath.partition,
+ skipInstall: m.skipInstall(),
+ aconfigPaths: uniquelist.Make(m.getAconfigPaths()),
+ archType: m.target.Arch.ArchType,
+ overrides: uniquelist.Make(overrides),
+ owner: owner,
+ requiresFullInstall: m.requiresFullInstall(),
+ fullInstallPath: fullInstallPath,
+ variation: m.ModuleSubDir(),
})
return fullInstallPath
@@ -805,6 +887,11 @@
// CheckbuildFile specifies the output files that should be built by checkbuild.
func (m *moduleContext) CheckbuildFile(srcPaths ...Path) {
+ for _, srcPath := range srcPaths {
+ if srcPath == nil {
+ panic("CheckbuildFile() files cannot be nil")
+ }
+ }
m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...)
}
@@ -822,11 +909,20 @@
}
func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
- if moduleInfoJSON := m.moduleInfoJSON; moduleInfoJSON != nil {
- return moduleInfoJSON
+ if len(m.moduleInfoJSON) == 0 {
+ moduleInfoJSON := &ModuleInfoJSON{}
+ m.moduleInfoJSON = append(m.moduleInfoJSON, moduleInfoJSON)
}
+ return m.moduleInfoJSON[0]
+}
+
+func (m *moduleContext) ExtraModuleInfoJSON() *ModuleInfoJSON {
+ if len(m.moduleInfoJSON) == 0 {
+ panic("call ModuleInfoJSON() instead")
+ }
+
moduleInfoJSON := &ModuleInfoJSON{}
- m.moduleInfoJSON = moduleInfoJSON
+ m.moduleInfoJSON = append(m.moduleInfoJSON, moduleInfoJSON)
return moduleInfoJSON
}
@@ -913,3 +1009,32 @@
func (m *moduleContext) setContainersInfo(info ContainersInfo) {
m.containersInfo = info
}
+
+func (c *moduleContext) DistForGoal(goal string, paths ...Path) {
+ c.DistForGoals([]string{goal}, paths...)
+}
+
+func (c *moduleContext) DistForGoalWithFilename(goal string, path Path, filename string) {
+ c.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (c *moduleContext) DistForGoals(goals []string, paths ...Path) {
+ var copies distCopies
+ for _, path := range paths {
+ copies = append(copies, distCopy{
+ from: path,
+ dest: path.Base(),
+ })
+ }
+ c.dists = append(c.dists, dist{
+ goals: slices.Clone(goals),
+ paths: copies,
+ })
+}
+
+func (c *moduleContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+ c.dists = append(c.dists, dist{
+ goals: slices.Clone(goals),
+ paths: distCopies{{from: path, dest: filename}},
+ })
+}
diff --git a/android/module_info_json.go b/android/module_info_json.go
index d102dd2..50c961a 100644
--- a/android/module_info_json.go
+++ b/android/module_info_json.go
@@ -34,15 +34,23 @@
SrcJars []string `json:"srcjars,omitempty"` // $(sort $(ALL_MODULES.$(m).SRCJARS))
ClassesJar []string `json:"classes_jar,omitempty"` // $(sort $(ALL_MODULES.$(m).CLASSES_JAR))
TestMainlineModules []string `json:"test_mainline_modules,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES))
- IsUnitTest bool `json:"is_unit_test,omitempty"` // $(ALL_MODULES.$(m).IS_UNIT_TEST)
+ IsUnitTest string `json:"is_unit_test,omitempty"` // $(ALL_MODULES.$(m).IS_UNIT_TEST)
TestOptionsTags []string `json:"test_options_tags,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS))
RuntimeDependencies []string `json:"runtime_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES))
StaticDependencies []string `json:"static_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES))
DataDependencies []string `json:"data_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_DATA_BINS))
- CompatibilitySuites []string `json:"compatibility_suites,omitempty"` // $(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES))
- AutoTestConfig []string `json:"auto_test_config,omitempty"` // $(ALL_MODULES.$(m).auto_test_config)
- TestConfig []string `json:"test_config,omitempty"` // $(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)
+ CompatibilitySuites []string `json:"compatibility_suites,omitempty"` // $(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES))
+ AutoTestConfig []string `json:"auto_test_config,omitempty"` // $(ALL_MODULES.$(m).auto_test_config)
+ TestConfig []string `json:"test_config,omitempty"` // $(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)
+ TestModuleConfigBase string `json:"test_module_config_base,omitempty"`
+ ExtraRequired []string `json:"-"`
+ ExtraHostRequired []string `json:"-"`
+
+ SupportedVariantsOverride []string `json:"-"`
+ Disabled bool `json:"-"`
+ RegisterNameOverride string `json:"-"`
+ ModuleNameOverride string `json:"-"`
}
type ModuleInfoJSON struct {
@@ -127,4 +135,12 @@
return gobtools.CustomGobDecode[combinedModuleInfoJSON](data, m)
}
-var ModuleInfoJSONProvider = blueprint.NewProvider[*ModuleInfoJSON]()
+func (m *ModuleInfoJSON) GetInstalled() []string {
+ return m.core.Installed
+}
+
+func (m *ModuleInfoJSON) GetClass() []string {
+ return m.Class
+}
+
+var ModuleInfoJSONProvider = blueprint.NewProvider[[]*ModuleInfoJSON]()
diff --git a/android/module_proxy.go b/android/module_proxy.go
index 30459b9..81d90e9 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -11,6 +11,10 @@
var _ Module = (*ModuleProxy)(nil)
+func (m ModuleProxy) IsNil() bool {
+ return m.module.IsNil()
+}
+
func (m ModuleProxy) Name() string {
return m.module.Name()
}
@@ -23,6 +27,10 @@
panic("method is not implemented on ModuleProxy")
}
+func (m ModuleProxy) CleanupAfterBuildActions() {
+ panic("method is not implemented on ModuleProxy")
+}
+
func (m ModuleProxy) ComponentDepsMutator(ctx BottomUpMutatorContext) {
panic("method is not implemented on ModuleProxy")
}
@@ -160,10 +168,6 @@
panic("method is not implemented on ModuleProxy")
}
-func (m ModuleProxy) EffectiveLicenseKinds() []string {
- panic("method is not implemented on ModuleProxy")
-}
-
func (m ModuleProxy) EffectiveLicenseFiles() Paths {
panic("method is not implemented on ModuleProxy")
}
@@ -189,7 +193,7 @@
}
func (m ModuleProxy) String() string {
- return m.module.Name()
+ return m.module.String()
}
func (m ModuleProxy) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
@@ -231,3 +235,7 @@
func (m ModuleProxy) VintfFragments(ctx ConfigurableEvaluatorContext) []string {
panic("method is not implemented on ModuleProxy")
}
+
+func (m ModuleProxy) UseGenericConfig() bool {
+ panic("method is not implemented on ModuleProxy")
+}
diff --git a/android/module_test.go b/android/module_test.go
index d5bf941..5331e49 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -321,27 +321,27 @@
if host {
variant = result.Config.BuildOSCommonTarget.String()
}
- return result.ModuleForTests(name, variant)
+ return result.ModuleForTests(t, name, variant)
}
outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
installRule := func(name string) TestingBuildParams {
- return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system", name))
+ return module(name, false).Output(filepath.Join("out/target/product/test_device/system", name))
}
symlinkRule := func(name string) TestingBuildParams {
- return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system/symlinks", name))
+ return module(name, false).Output(filepath.Join("out/target/product/test_device/system/symlinks", name))
}
hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
hostInstallRule := func(name string) TestingBuildParams {
- return module(name, true).Output(filepath.Join("out/soong/host/linux-x86", name))
+ return module(name, true).Output(filepath.Join("out/host/linux-x86", name))
}
hostSymlinkRule := func(name string) TestingBuildParams {
- return module(name, true).Output(filepath.Join("out/soong/host/linux-x86/symlinks", name))
+ return module(name, true).Output(filepath.Join("out/host/linux-x86/symlinks", name))
}
assertInputs := func(params TestingBuildParams, inputs ...Path) {
@@ -434,11 +434,12 @@
rules := result.InstallMakeRulesForTesting(t)
module := func(name string, host bool) TestingModule {
+ t.Helper()
variant := "android_common"
if host {
variant = result.Config.BuildOSCommonTarget.String()
}
- return result.ModuleForTests(name, variant)
+ return result.ModuleForTests(t, name, variant)
}
outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
@@ -743,7 +744,7 @@
FixtureWithRootAndroidBp(tc.bp),
).RunTest(t)
- foo := result.ModuleForTests("foo", "").Module().base()
+ foo := result.ModuleForTests(t, "foo", "").Module().base()
AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
})
@@ -1078,7 +1079,7 @@
PathContext: PathContextForTesting(config),
OtherModuleProviderContext: result.TestContext.OtherModuleProviderAdaptor(),
}
- got := OutputFileForModule(ctx, result.ModuleForTests("test_module", "").Module(), tt.tag)
+ got := OutputFileForModule(ctx, result.ModuleForTests(t, "test_module", "").Module(), tt.tag)
AssertPathRelativeToTopEquals(t, "expected output path", tt.expected, got)
AssertArrayString(t, "expected missing deps", tt.missingDeps, ctx.missingDeps)
})
@@ -1110,3 +1111,14 @@
"Module .+ and Vintf_fragment .+ are installed to different partitions.")).
RunTestWithBp(t, bp)
}
+
+func TestInvalidModuleName(t *testing.T) {
+ bp := `
+ deps {
+ name: "fo o",
+ }
+ `
+ prepareForModuleTests.
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`should use a valid name`)).
+ RunTestWithBp(t, bp)
+}
diff --git a/android/mutator.go b/android/mutator.go
index fdd16a8..12861c0 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,9 +15,8 @@
package android
import (
- "sync"
-
"github.com/google/blueprint"
+ "github.com/google/blueprint/pool"
)
// Phases:
@@ -67,10 +66,10 @@
}
type RegisterMutatorsContext interface {
- TopDown(name string, m TopDownMutator) MutatorHandle
BottomUp(name string, m BottomUpMutator) MutatorHandle
BottomUpBlueprint(name string, m blueprint.BottomUpMutator) MutatorHandle
- Transition(name string, m TransitionMutator) TransitionMutatorHandle
+ Transition(name string, m VariationTransitionMutator) TransitionMutatorHandle
+ InfoBasedTransition(name string, m androidTransitionMutator) TransitionMutatorHandle
}
type RegisterMutatorFunc func(RegisterMutatorsContext)
@@ -158,6 +157,7 @@
var preDeps = []RegisterMutatorFunc{
registerArchMutator,
+ RegisterPrebuiltsPreDepsMutators,
}
var postDeps = []RegisterMutatorFunc{
@@ -193,17 +193,6 @@
finalDeps = append(finalDeps, f)
}
-type TopDownMutator func(TopDownMutatorContext)
-
-type TopDownMutatorContext interface {
- BaseModuleContext
-}
-
-type topDownMutatorContext struct {
- bp blueprint.TopDownMutatorContext
- baseModuleContext
-}
-
type BottomUpMutator func(BottomUpMutatorContext)
type BottomUpMutatorContext interface {
@@ -213,7 +202,7 @@
// dependency (some entries may be nil).
//
// This method will pause until the new dependencies have had the current mutator called on them.
- AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
+ AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []Module
// AddReverseDependency adds a dependency from the destination to the given module.
// Does not affect the ordering of the current mutator pass, but will be ordered
@@ -229,7 +218,7 @@
// all the non-local variations of the current module, plus the variations argument.
//
// This method will pause until the new dependencies have had the current mutator called on them.
- AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module
+ AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []Module
// AddReverseVariationDependency adds a dependency from the named module to the current
// module. The given variations will be added to the current module's varations, and then the
@@ -252,7 +241,7 @@
// dependency only needs to match the supplied variations.
//
// This method will pause until the new dependencies have had the current mutator called on them.
- AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module
+ AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []Module
// ReplaceDependencies finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module.
@@ -279,22 +268,12 @@
}
// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
-// for each transition mutator. bottomUpMutatorContext and topDownMutatorContext are created once for every module
-// for every BottomUp or TopDown mutator. Use a global pool for each to avoid reallocating every time.
+// for each transition mutator. bottomUpMutatorContext is created once for every module for every BottomUp mutator.
+// Use a global pool for each to avoid reallocating every time.
var (
- outgoingTransitionContextPool = sync.Pool{
- New: func() any { return &outgoingTransitionContextImpl{} },
- }
- incomingTransitionContextPool = sync.Pool{
- New: func() any { return &incomingTransitionContextImpl{} },
- }
- bottomUpMutatorContextPool = sync.Pool{
- New: func() any { return &bottomUpMutatorContext{} },
- }
-
- topDownMutatorContextPool = sync.Pool{
- New: func() any { return &topDownMutatorContext{} },
- }
+ outgoingTransitionContextPool = pool.New[outgoingTransitionContextImpl]()
+ incomingTransitionContextPool = pool.New[incomingTransitionContextImpl]()
+ bottomUpMutatorContextPool = pool.New[bottomUpMutatorContext]()
)
type bottomUpMutatorContext struct {
@@ -305,10 +284,10 @@
// callers must immediately follow the call to this function with defer bottomUpMutatorContextPool.Put(mctx).
func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
- finalPhase bool) BottomUpMutatorContext {
+ finalPhase bool) *bottomUpMutatorContext {
moduleContext := a.base().baseModuleContextFactory(ctx)
- mctx := bottomUpMutatorContextPool.Get().(*bottomUpMutatorContext)
+ mctx := bottomUpMutatorContextPool.Get()
*mctx = bottomUpMutatorContext{
bp: ctx,
baseModuleContext: moduleContext,
@@ -337,250 +316,22 @@
return mutator
}
-type IncomingTransitionContext interface {
- ArchModuleContext
- ModuleProviderContext
- ModuleErrorContext
-
- // Module returns the target of the dependency edge for which the transition
- // is being computed
- Module() Module
-
- // Config returns the configuration for the build.
- Config() Config
-
- DeviceConfig() DeviceConfig
-
- // IsAddingDependency returns true if the transition is being called while adding a dependency
- // after the transition mutator has already run, or false if it is being called when the transition
- // mutator is running. This should be used sparingly, all uses will have to be removed in order
- // to support creating variants on demand.
- IsAddingDependency() bool
-}
-
-type OutgoingTransitionContext interface {
- ArchModuleContext
- ModuleProviderContext
-
- // Module returns the target of the dependency edge for which the transition
- // is being computed
- Module() Module
-
- // DepTag() Returns the dependency tag through which this dependency is
- // reached
- DepTag() blueprint.DependencyTag
-
- // Config returns the configuration for the build.
- Config() Config
-
- DeviceConfig() DeviceConfig
-}
-
-// TransitionMutator implements a top-down mechanism where a module tells its
-// direct dependencies what variation they should be built in but the dependency
-// has the final say.
-//
-// When implementing a transition mutator, one needs to implement four methods:
-// - Split() that tells what variations a module has by itself
-// - OutgoingTransition() where a module tells what it wants from its
-// dependency
-// - IncomingTransition() where a module has the final say about its own
-// variation
-// - Mutate() that changes the state of a module depending on its variation
-//
-// That the effective variation of module B when depended on by module A is the
-// composition the outgoing transition of module A and the incoming transition
-// of module B.
-//
-// the outgoing transition should not take the properties of the dependency into
-// account, only those of the module that depends on it. For this reason, the
-// dependency is not even passed into it as an argument. Likewise, the incoming
-// transition should not take the properties of the depending module into
-// account and is thus not informed about it. This makes for a nice
-// decomposition of the decision logic.
-//
-// A given transition mutator only affects its own variation; other variations
-// stay unchanged along the dependency edges.
-//
-// Soong makes sure that all modules are created in the desired variations and
-// that dependency edges are set up correctly. This ensures that "missing
-// variation" errors do not happen and allows for more flexible changes in the
-// value of the variation among dependency edges (as oppposed to bottom-up
-// mutators where if module A in variation X depends on module B and module B
-// has that variation X, A must depend on variation X of B)
-//
-// The limited power of the context objects passed to individual mutators
-// methods also makes it more difficult to shoot oneself in the foot. Complete
-// safety is not guaranteed because no one prevents individual transition
-// mutators from mutating modules in illegal ways and for e.g. Split() or
-// Mutate() to run their own visitations of the transitive dependency of the
-// module and both of these are bad ideas, but it's better than no guardrails at
-// all.
-//
-// This model is pretty close to Bazel's configuration transitions. The mapping
-// between concepts in Soong and Bazel is as follows:
-// - Module == configured target
-// - Variant == configuration
-// - Variation name == configuration flag
-// - Variation == configuration flag value
-// - Outgoing transition == attribute transition
-// - Incoming transition == rule transition
-//
-// The Split() method does not have a Bazel equivalent and Bazel split
-// transitions do not have a Soong equivalent.
-//
-// Mutate() does not make sense in Bazel due to the different models of the
-// two systems: when creating new variations, Soong clones the old module and
-// thus some way is needed to change it state whereas Bazel creates each
-// configuration of a given configured target anew.
-type TransitionMutator interface {
- // Split returns the set of variations that should be created for a module no
- // matter who depends on it. Used when Make depends on a particular variation
- // or when the module knows its variations just based on information given to
- // it in the Blueprint file. This method should not mutate the module it is
- // called on.
- Split(ctx BaseModuleContext) []string
-
- // OutgoingTransition is called on a module to determine which variation it wants
- // from its direct dependencies. The dependency itself can override this decision.
- // This method should not mutate the module itself.
- OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string
-
- // IncomingTransition is called on a module to determine which variation it should
- // be in based on the variation modules that depend on it want. This gives the module
- // a final say about its own variations. This method should not mutate the module
- // itself.
- IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string
-
- // Mutate is called after a module was split into multiple variations on each variation.
- // It should not split the module any further but adding new dependencies is
- // fine. Unlike all the other methods on TransitionMutator, this method is
- // allowed to mutate the module.
- Mutate(ctx BottomUpMutatorContext, variation string)
-}
-
-type androidTransitionMutator struct {
- finalPhase bool
- mutator TransitionMutator
- name string
-}
-
-func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
- if a.finalPhase {
- panic("TransitionMutator not allowed in FinalDepsMutators")
+func (x *registerMutatorsContext) Transition(name string, m VariationTransitionMutator) TransitionMutatorHandle {
+ atm := &androidTransitionMutatorAdapter{
+ finalPhase: x.finalPhase,
+ mutator: variationTransitionMutatorAdapter{m},
+ name: name,
}
- if m, ok := ctx.Module().(Module); ok {
- moduleContext := m.base().baseModuleContextFactory(ctx)
- return a.mutator.Split(&moduleContext)
- } else {
- return []string{""}
+ mutator := &mutator{
+ name: name,
+ transitionMutator: atm,
}
+ x.mutators = append(x.mutators, mutator)
+ return mutator
}
-type outgoingTransitionContextImpl struct {
- archModuleContext
- bp blueprint.OutgoingTransitionContext
-}
-
-func (c *outgoingTransitionContextImpl) Module() Module {
- return c.bp.Module().(Module)
-}
-
-func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag {
- return c.bp.DepTag()
-}
-
-func (c *outgoingTransitionContextImpl) Config() Config {
- return c.bp.Config().(Config)
-}
-
-func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig {
- return DeviceConfig{c.bp.Config().(Config).deviceConfig}
-}
-
-func (c *outgoingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
- return c.bp.Provider(provider)
-}
-
-func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
- if m, ok := bpctx.Module().(Module); ok {
- ctx := outgoingTransitionContextPool.Get().(*outgoingTransitionContextImpl)
- defer outgoingTransitionContextPool.Put(ctx)
- *ctx = outgoingTransitionContextImpl{
- archModuleContext: m.base().archModuleContextFactory(bpctx),
- bp: bpctx,
- }
- return a.mutator.OutgoingTransition(ctx, sourceVariation)
- } else {
- return ""
- }
-}
-
-type incomingTransitionContextImpl struct {
- archModuleContext
- bp blueprint.IncomingTransitionContext
-}
-
-func (c *incomingTransitionContextImpl) Module() Module {
- return c.bp.Module().(Module)
-}
-
-func (c *incomingTransitionContextImpl) Config() Config {
- return c.bp.Config().(Config)
-}
-
-func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig {
- return DeviceConfig{c.bp.Config().(Config).deviceConfig}
-}
-
-func (c *incomingTransitionContextImpl) IsAddingDependency() bool {
- return c.bp.IsAddingDependency()
-}
-
-func (c *incomingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
- return c.bp.Provider(provider)
-}
-
-func (c *incomingTransitionContextImpl) ModuleErrorf(fmt string, args ...interface{}) {
- c.bp.ModuleErrorf(fmt, args)
-}
-
-func (c *incomingTransitionContextImpl) PropertyErrorf(property, fmt string, args ...interface{}) {
- c.bp.PropertyErrorf(property, fmt, args)
-}
-
-func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string {
- if m, ok := bpctx.Module().(Module); ok {
- ctx := incomingTransitionContextPool.Get().(*incomingTransitionContextImpl)
- defer incomingTransitionContextPool.Put(ctx)
- *ctx = incomingTransitionContextImpl{
- archModuleContext: m.base().archModuleContextFactory(bpctx),
- bp: bpctx,
- }
- return a.mutator.IncomingTransition(ctx, incomingVariation)
- } else {
- return ""
- }
-}
-
-func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
- if am, ok := ctx.Module().(Module); ok {
- if variation != "" {
- // TODO: this should really be checking whether the TransitionMutator affected this module, not
- // the empty variant, but TransitionMutator has no concept of skipping a module.
- base := am.base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
- }
-
- mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
- defer bottomUpMutatorContextPool.Put(mctx)
- a.mutator.Mutate(mctx, variation)
- }
-}
-
-func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) TransitionMutatorHandle {
- atm := &androidTransitionMutator{
+func (x *registerMutatorsContext) InfoBasedTransition(name string, m androidTransitionMutator) TransitionMutatorHandle {
+ atm := &androidTransitionMutatorAdapter{
finalPhase: x.finalPhase,
mutator: m,
name: name,
@@ -597,24 +348,6 @@
return name
}
-func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
- f := func(ctx blueprint.TopDownMutatorContext) {
- if a, ok := ctx.Module().(Module); ok {
- moduleContext := a.base().baseModuleContextFactory(ctx)
- actx := topDownMutatorContextPool.Get().(*topDownMutatorContext)
- defer topDownMutatorContextPool.Put(actx)
- *actx = topDownMutatorContext{
- bp: ctx,
- baseModuleContext: moduleContext,
- }
- m(actx)
- }
- }
- mutator := &mutator{name: x.mutatorName(name), topDownMutator: f}
- x.mutators = append(x.mutators, mutator)
- return mutator
-}
-
func (mutator *mutator) componentName() string {
return mutator.name
}
@@ -624,8 +357,6 @@
var handle blueprint.MutatorHandle
if mutator.bottomUpMutator != nil {
handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator)
- } else if mutator.topDownMutator != nil {
- handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator)
} else if mutator.transitionMutator != nil {
handle := blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator)
if mutator.neverFar {
@@ -755,22 +486,22 @@
ctx.BottomUp("deps", depsMutator).UsesReverseDependencies()
}
-// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
+// android.bottomUpMutatorContext either has to embed blueprint.BottomUpMutatorContext, in which case every method that
// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
-// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
+// ambiguous method errors, or it has to store a blueprint.BottomUpMutatorContext non-embedded, in which case every
// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following
-// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
+// methods forward to the identical blueprint versions for bottomUpMutatorContext.
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
b.Module().base().commonProperties.DebugName = name
}
-func (b *bottomUpMutatorContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module {
- return b.bp.CreateModule(factory, name, props...)
+func (b *bottomUpMutatorContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) Module {
+ return bpModuleToModule(b.bp.CreateModule(factory, name, props...))
}
-func (b *bottomUpMutatorContext) createModuleInDirectory(factory blueprint.ModuleFactory, name string, _ string, props ...interface{}) blueprint.Module {
+func (b *bottomUpMutatorContext) createModuleInDirectory(factory blueprint.ModuleFactory, name string, _ string, props ...interface{}) Module {
panic("createModuleInDirectory is not implemented for bottomUpMutatorContext")
}
@@ -778,11 +509,11 @@
return createModule(b, factory, "_bottomUpMutatorModule", doesNotSpecifyDirectory(), props...)
}
-func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module {
+func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []Module {
if b.baseModuleContext.checkedMissingDeps() {
panic("Adding deps not allowed after checking for missing deps")
}
- return b.bp.AddDependency(module, tag, name...)
+ return bpModulesToModules(b.bp.AddDependency(module, tag, name...))
}
func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) {
@@ -800,20 +531,20 @@
}
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
- names ...string) []blueprint.Module {
+ names ...string) []Module {
if b.baseModuleContext.checkedMissingDeps() {
panic("Adding deps not allowed after checking for missing deps")
}
- return b.bp.AddVariationDependencies(variations, tag, names...)
+ return bpModulesToModules(b.bp.AddVariationDependencies(variations, tag, names...))
}
func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
- tag blueprint.DependencyTag, names ...string) []blueprint.Module {
+ tag blueprint.DependencyTag, names ...string) []Module {
if b.baseModuleContext.checkedMissingDeps() {
panic("Adding deps not allowed after checking for missing deps")
}
- return b.bp.AddFarVariationDependencies(variations, tag, names...)
+ return bpModulesToModules(b.bp.AddFarVariationDependencies(variations, tag, names...))
}
func (b *bottomUpMutatorContext) ReplaceDependencies(name string) {
@@ -829,3 +560,18 @@
}
b.bp.ReplaceDependenciesIf(name, predicate)
}
+
+func bpModulesToModules(bpModules []blueprint.Module) []Module {
+ modules := make([]Module, len(bpModules))
+ for i, bpModule := range bpModules {
+ modules[i] = bpModuleToModule(bpModule)
+ }
+ return modules
+}
+
+func bpModuleToModule(bpModule blueprint.Module) Module {
+ if bpModule != nil {
+ return bpModule.(Module)
+ }
+ return nil
+}
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 1d5f890..f7ee7d8 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -54,7 +54,7 @@
ctx.AddDependency(ctx.Module(), nil, m.props.Deps_missing_deps...)
}
-func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
+func addMissingDependenciesMutator(ctx BottomUpMutatorContext) {
ctx.AddMissingDependencies(ctx.Module().(*mutatorTestModule).props.Mutator_missing_deps)
}
@@ -72,143 +72,17 @@
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
+ ctx.BottomUp("add_missing_dependencies", addMissingDependenciesMutator)
})
}),
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- foo := result.ModuleForTests("foo", "").Module().(*mutatorTestModule)
+ foo := result.ModuleForTests(t, "foo", "").Module().(*mutatorTestModule)
AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps)
}
-type testTransitionMutator struct {
- split func(ctx BaseModuleContext) []string
- outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string
- incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string
- mutate func(ctx BottomUpMutatorContext, variation string)
-}
-
-func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string {
- if t.split != nil {
- return t.split(ctx)
- }
- return []string{""}
-}
-
-func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
- if t.outgoingTransition != nil {
- return t.outgoingTransition(ctx, sourceVariation)
- }
- return sourceVariation
-}
-
-func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
- if t.incomingTransition != nil {
- return t.incomingTransition(ctx, incomingVariation)
- }
- return incomingVariation
-}
-
-func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
- if t.mutate != nil {
- t.mutate(ctx, variation)
- }
-}
-
-func TestModuleString(t *testing.T) {
- bp := `
- test {
- name: "foo",
- }
- `
-
- var moduleStrings []string
-
- GroupFixturePreparers(
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
-
- ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("pre_arch", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- return []string{"a", "b"}
- },
- })
- })
-
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("pre_deps", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- return []string{"c", "d"}
- },
- })
- })
-
- ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("post_deps", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- return []string{"e", "f"}
- },
- outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string {
- return ""
- },
- })
- ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed1")
- }).UsesRename()
- ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- })
- })
-
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- }),
- FixtureWithRootAndroidBp(bp),
- ).RunTest(t)
-
- want := []string{
- // Initial name.
- "foo{}",
-
- // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
- "foo{pre_arch:b}",
- "foo{pre_arch:a}",
-
- // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
- "foo{pre_arch:b,pre_deps:d}",
- "foo{pre_arch:b,pre_deps:c}",
- "foo{pre_arch:a,pre_deps:d}",
- "foo{pre_arch:a,pre_deps:c}",
-
- // After post_deps.
- "foo{pre_arch:a,pre_deps:c,post_deps:e}",
- "foo{pre_arch:a,pre_deps:c,post_deps:f}",
- "foo{pre_arch:a,pre_deps:d,post_deps:e}",
- "foo{pre_arch:a,pre_deps:d,post_deps:f}",
- "foo{pre_arch:b,pre_deps:c,post_deps:e}",
- "foo{pre_arch:b,pre_deps:c,post_deps:f}",
- "foo{pre_arch:b,pre_deps:d,post_deps:e}",
- "foo{pre_arch:b,pre_deps:d,post_deps:f}",
-
- // After rename_bottom_up.
- "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
- "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
- "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
- "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
- "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
- "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
- "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
- "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
- }
-
- AssertDeepEquals(t, "module String() values", want, moduleStrings)
-}
-
func TestFinalDepsPhase(t *testing.T) {
bp := `
test {
@@ -288,22 +162,3 @@
AssertDeepEquals(t, "final", finalWant, finalGotMap)
}
-
-func TestTransitionMutatorInFinalDeps(t *testing.T) {
- GroupFixturePreparers(
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("vars", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- return []string{"a", "b"}
- },
- })
- })
-
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- }),
- FixtureWithRootAndroidBp(`test {name: "foo"}`),
- ).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
- RunTest(t)
-}
diff --git a/android/namespace.go b/android/namespace.go
index c3ee20f..d0e90b0 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -335,7 +335,7 @@
if isAbs {
// if the user gave a fully-qualified name, we don't need to look for other
// modules that they might have been referring to
- return fmt.Errorf(text)
+ return fmt.Errorf("%s", text)
}
// determine which namespaces the module can be found in
@@ -371,7 +371,7 @@
text += fmt.Sprintf("\nOr did you mean %q?", guess)
}
- return fmt.Errorf(text)
+ return fmt.Errorf("%s", text)
}
func (r *NameResolver) GetNamespace(ctx blueprint.NamespaceContext) blueprint.Namespace {
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 0327e78..a183bbf 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -683,7 +683,7 @@
}
func getModule(result *TestResult, moduleName string) TestingModule {
- return result.ModuleForTests(moduleName, "")
+ return result.ModuleForTests(result.fixture.t, moduleName, "")
}
func findModuleById(result *TestResult, id string) (module TestingModule) {
@@ -691,7 +691,7 @@
testModule, ok := candidate.(*testModule)
if ok {
if testModule.properties.Id == id {
- module = newTestingModule(result.config, testModule)
+ module = newTestingModule(result.fixture.t, result.config, testModule)
}
}
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 3136a15..98b443e 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -60,11 +60,13 @@
AddNeverAllowRules(createCcStubsRule())
AddNeverAllowRules(createProhibitHeaderOnlyRule())
AddNeverAllowRules(createLimitNdkExportRule()...)
- AddNeverAllowRules(createLimitDirgroupRule()...)
+ AddNeverAllowRules(createLimitDirgroupRules()...)
+ AddNeverAllowRules(createLimitGenruleRules()...)
AddNeverAllowRules(createFilesystemIsAutoGeneratedRule())
AddNeverAllowRules(createKotlinPluginRule()...)
AddNeverAllowRules(createPrebuiltEtcBpDefineRule())
AddNeverAllowRules(createAutogenRroBpDefineRule())
+ AddNeverAllowRules(createNoSha1HashRule())
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -230,7 +232,7 @@
func createUncompressDexRules() []Rule {
return []Rule{
NeverAllow().
- NotIn("art").
+ NotIn("art", "cts/hostsidetests/compilation").
WithMatcher("uncompress_dex", isSetMatcherInstance).
Because("uncompress_dex is only allowed for certain jars for test in art."),
}
@@ -287,29 +289,49 @@
}
}
-func createLimitDirgroupRule() []Rule {
- reason := "dirgroup module and dir_srcs / keep_gendir property of genrule is allowed only to Trusty build rule."
+func createLimitDirgroupRules() []Rule {
+ reason := "The dirgroup module can only be used with Trusty visibility"
+ scriptsDirsList := []string{"//trusty/vendor/google/aosp/scripts", "//trusty/vendor/google/proprietary/scripts"}
return []Rule{
NeverAllow().
ModuleType("dirgroup").
- WithMatcher("visibility", NotInList([]string{"//trusty/vendor/google/aosp/scripts"})).Because(reason),
+ WithMatcher("visibility", NotInList(scriptsDirsList)).Because(reason),
NeverAllow().
ModuleType("dirgroup").
- Without("visibility", "//trusty/vendor/google/aosp/scripts").Because(reason),
+ WithoutMatcher("visibility", InAllowedList(scriptsDirsList)).Because(reason),
+ }
+}
+
+func createLimitGenruleRules() []Rule {
+ dirSrcsReason := "The `dir_srcs` property in a `genrule` module can only be used by Trusty"
+ keepGendirReason := "The `keep_gendir` property in a `genrule` module can only be used by Trusty"
+ allowedModuleNameList := []string{
+ // Trusty TEE target names
+ "trusty_tee_package_goog",
+ "trusty_tee_package",
+ // Trusty vm target names
+ "trusty_desktop_vm_arm64.bin",
+ "trusty_desktop_vm_x86_64.bin",
+ "trusty_desktop_test_vm_arm64.bin",
+ "trusty_desktop_test_vm_x86_64.bin",
+ "trusty_test_vm_arm64.bin",
+ "trusty_test_vm_x86_64.elf",
+ "trusty_test_vm_os_arm64.bin",
+ "trusty_test_vm_os_x86_64.elf",
+ "trusty_security_vm_arm64.bin",
+ "trusty_security_vm_x86_64.elf",
+ "trusty_widevine_vm_arm64.bin",
+ "trusty_widevine_vm_x86_64.elf",
+ }
+ return []Rule{
NeverAllow().
ModuleType("genrule").
- Without("name", "trusty-arm64.lk.elf.gen").
- Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen").
- Without("name", "trusty-x86_64.lk.elf.gen").
- Without("name", "trusty-x86_64-test.lk.elf.gen").
- WithMatcher("dir_srcs", isSetMatcherInstance).Because(reason),
+ WithoutMatcher("name", InAllowedList(allowedModuleNameList)).
+ WithMatcher("dir_srcs", isSetMatcherInstance).Because(dirSrcsReason),
NeverAllow().
ModuleType("genrule").
- Without("name", "trusty-arm64.lk.elf.gen").
- Without("name", "trusty-arm64-virt-test-debug.lk.elf.gen").
- Without("name", "trusty-x86_64.lk.elf.gen").
- Without("name", "trusty-x86_64-test.lk.elf.gen").
- With("keep_gendir", "true").Because(reason),
+ WithoutMatcher("name", InAllowedList(allowedModuleNameList)).
+ With("keep_gendir", "true").Because(keepGendirReason),
}
}
@@ -321,11 +343,16 @@
Because("is_auto_generated property is only allowed for filesystem modules in build/soong/fsgen directory")
}
+func createNoSha1HashRule() Rule {
+ return NeverAllow().
+ ModuleType("filesystem", "android_filesystem").
+ ModuleType("filesystem", "android_system_image").
+ With("avb_hash_algorithm", "sha1").
+ Because("sha1 is discouraged")
+}
+
func createKotlinPluginRule() []Rule {
kotlinPluginProjectsAllowedList := []string{
- // TODO: Migrate compose plugin to the bundled compiler plugin
- // Actual path prebuilts/sdk/current/androidx/m2repository/androidx/compose/compiler/compiler-hosted
- "prebuilts/sdk/current/androidx",
"external/kotlinc",
}
@@ -358,6 +385,10 @@
"prebuilt_sbin",
"prebuilt_system",
"prebuilt_first_stage_ramdisk",
+ "prebuilt_radio",
+ "prebuilt_gpu",
+ "prebuilt_vendor_overlay",
+ "prebuilt_tee",
).
DefinedInBpFile().
Because("module type not allowed to be defined in bp file")
@@ -389,7 +420,8 @@
continue
}
- if !n.appliesToModuleType(ctx.ModuleType()) {
+ modType := proptools.StringDefault(m.base().baseProperties.Soong_config_base_module_type, ctx.ModuleType())
+ if !n.appliesToModuleType(modType) {
continue
}
@@ -479,6 +511,18 @@
return ".not-in-list(" + strings.Join(m.allowed, ",") + ")"
}
+type InListMatcher struct {
+ allowed []string
+}
+
+func (m *InListMatcher) Test(value string) bool {
+ return InList(value, m.allowed)
+}
+
+func (m *InListMatcher) String() string {
+ return ".in-list(" + strings.Join(m.allowed, ",") + ")"
+}
+
type isSetMatcher struct{}
func (m *isSetMatcher) Test(value string) bool {
@@ -757,6 +801,10 @@
return ¬InListMatcher{allowed}
}
+func InAllowedList(allowed []string) ValueMatcher {
+ return &InListMatcher{allowed}
+}
+
// assorted utils
func cleanPaths(paths []string) []string {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index c74d5ff..3ccc883 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -388,6 +388,30 @@
`module type not allowed to be defined in bp file`,
},
},
+ // Test the a neverallowed module type can't be smuggled through a soong config module type
+ {
+ name: `smuggling module types through soong config modules`,
+ fs: map[string][]byte{
+ "a/b/Android.bp": []byte(`
+ soong_config_bool_variable {
+ name: "my_var",
+ }
+ soong_config_module_type {
+ name: "smuggled_prebuilt_usr_srec",
+ module_type: "prebuilt_usr_srec",
+ config_namespace: "ANDROID",
+ variables: ["my_var"],
+ properties: ["enabled"],
+ }
+ smuggled_prebuilt_usr_srec {
+ name: "foo",
+ }
+ `),
+ },
+ expectedErrors: []string{
+ `module type not allowed to be defined in bp file`,
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -399,6 +423,7 @@
ctx.RegisterModuleType("filesystem", newMockFilesystemModule)
ctx.RegisterModuleType("prebuilt_usr_srec", newMockPrebuiltUsrSrecModule)
}),
+ PrepareForTestWithSoongConfigModuleBuildComponents,
)
func TestNeverallow(t *testing.T) {
diff --git a/android/nothing.go b/android/nothing.go
new file mode 100644
index 0000000..18bf85b
--- /dev/null
+++ b/android/nothing.go
@@ -0,0 +1,34 @@
+// Copyright 2025 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
+
+func init() {
+ RegisterParallelSingletonType("nothing_singleton", nothingSingletonFactory)
+}
+
+func nothingSingletonFactory() Singleton {
+ return ¬hingSingleton{}
+}
+
+type nothingSingleton struct{}
+
+func (s *nothingSingleton) GenerateBuildActions(ctx SingletonContext) {
+ rule := NewRuleBuilder(pctx, ctx)
+ rule.SetPhonyOutput()
+ rule.Command().
+ Text("echo Successfully read the makefiles.").
+ ImplicitOutput(PathForPhony(ctx, "nothing"))
+ rule.Build("nothing", "nothing")
+}
diff --git a/android/notices.go b/android/notices.go
index 3c41d92..dc2290c 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -18,9 +18,11 @@
"fmt"
"path/filepath"
"strings"
+
+ "github.com/google/blueprint"
)
-func modulesOutputDirs(ctx BuilderContext, modules ...Module) []string {
+func modulesOutputDirs(ctx BuilderContext, modules ...ModuleProxy) []string {
dirs := make([]string, 0, len(modules))
for _, module := range modules {
paths, err := outputFilesForModule(ctx, module, "")
@@ -41,12 +43,12 @@
OtherModuleProviderContext
}
-func modulesLicenseMetadata(ctx OtherModuleProviderContext, modules ...Module) Paths {
+func modulesLicenseMetadata(ctx OtherModuleProviderContext, modules ...ModuleProxy) Paths {
result := make(Paths, 0, len(modules))
mctx, isMctx := ctx.(ModuleContext)
for _, module := range modules {
var mf Path
- if isMctx && mctx.Module() == module {
+ if isMctx && EqualModules(mctx.Module(), module) {
mf = mctx.LicenseMetadataFile()
} else {
mf = OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).LicenseMetadataFile
@@ -61,12 +63,12 @@
// buildNoticeOutputFromLicenseMetadata writes out a notice file.
func buildNoticeOutputFromLicenseMetadata(
ctx BuilderAndOtherModuleProviderContext, tool, ruleName string, outputFile WritablePath,
- libraryName string, stripPrefix []string, modules ...Module) {
+ libraryName string, stripPrefix []string, modules ...ModuleProxy) {
depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", "."))
rule := NewRuleBuilder(pctx, ctx)
if len(modules) == 0 {
if mctx, ok := ctx.(ModuleContext); ok {
- modules = []Module{mctx.Module()}
+ modules = []ModuleProxy{{blueprint.CreateModuleProxy(mctx.Module())}}
} else {
panic(fmt.Errorf("%s %q needs a module to generate the notice for", ruleName, libraryName))
}
@@ -97,7 +99,7 @@
// current context module if none given.
func BuildNoticeTextOutputFromLicenseMetadata(
ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string,
- stripPrefix []string, modules ...Module) {
+ stripPrefix []string, modules ...ModuleProxy) {
buildNoticeOutputFromLicenseMetadata(ctx, "textnotice", "text_notice_"+ruleName,
outputFile, libraryName, stripPrefix, modules...)
}
@@ -107,7 +109,7 @@
// current context module if none given.
func BuildNoticeHtmlOutputFromLicenseMetadata(
ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string,
- stripPrefix []string, modules ...Module) {
+ stripPrefix []string, modules ...ModuleProxy) {
buildNoticeOutputFromLicenseMetadata(ctx, "htmlnotice", "html_notice_"+ruleName,
outputFile, libraryName, stripPrefix, modules...)
}
@@ -117,7 +119,7 @@
// current context module if none given.
func BuildNoticeXmlOutputFromLicenseMetadata(
ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string,
- stripPrefix []string, modules ...Module) {
+ stripPrefix []string, modules ...ModuleProxy) {
buildNoticeOutputFromLicenseMetadata(ctx, "xmlnotice", "xml_notice_"+ruleName,
outputFile, libraryName, stripPrefix, modules...)
}
diff --git a/android/otatools_package_cert_zip.go b/android/otatools_package_cert_zip.go
new file mode 100644
index 0000000..3a654cf
--- /dev/null
+++ b/android/otatools_package_cert_zip.go
@@ -0,0 +1,62 @@
+// Copyright 2025 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 (
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterOtatoolsPackageBuildComponents(InitRegistrationContext)
+ pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+}
+
+func RegisterOtatoolsPackageBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("otatools_package_cert_files", OtatoolsPackageFactory)
+}
+
+type OtatoolsPackage struct {
+ ModuleBase
+}
+
+func OtatoolsPackageFactory() Module {
+ module := &OtatoolsPackage{}
+ InitAndroidModule(module)
+ return module
+}
+
+var (
+ otatoolsPackageCertRule = pctx.AndroidStaticRule("otatools_package_cert_files", blueprint.RuleParams{
+ Command: "echo '$out : ' $$(cat $in) > ${out}.d && ${SoongZipCmd} -o $out -l $in",
+ CommandDeps: []string{"${SoongZipCmd}"},
+ Depfile: "${out}.d",
+ Description: "Zip otatools-package cert files",
+ })
+)
+
+func (fg *OtatoolsPackage) GenerateAndroidBuildActions(ctx ModuleContext) {
+ if ctx.ModuleDir() != "build/make/tools/otatools_package" {
+ ctx.ModuleErrorf("There can only be one otatools_package_cert_files module in build/make/tools/otatools_package")
+ return
+ }
+ fileListFile := PathForArbitraryOutput(ctx, ".module_paths", "OtaToolsCertFiles.list")
+ otatoolsPackageCertZip := PathForModuleOut(ctx, "otatools_package_cert_files.zip")
+ ctx.Build(pctx, BuildParams{
+ Rule: otatoolsPackageCertRule,
+ Input: fileListFile,
+ Output: otatoolsPackageCertZip,
+ })
+ ctx.SetOutputFiles([]Path{otatoolsPackageCertZip}, "")
+}
diff --git a/android/override_module.go b/android/override_module.go
index 50ddc9b..96620ef 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -367,6 +367,7 @@
}
func overridableModuleDepsMutator(ctx BottomUpMutatorContext) {
+ ctx.Module().base().baseOverridablePropertiesDepsMutator(ctx)
if b, ok := ctx.Module().(OverridableModule); ok && b.Enabled(ctx) {
b.OverridablePropertiesDepsMutator(ctx)
}
diff --git a/android/package.go b/android/package.go
index eb76751..52bddf9 100644
--- a/android/package.go
+++ b/android/package.go
@@ -38,6 +38,12 @@
Default_team *string `android:"path"`
}
+type PackageInfo struct {
+ Properties packageProperties
+}
+
+var PackageInfoProvider = blueprint.NewProvider[PackageInfo]()
+
type packageModule struct {
ModuleBase
@@ -56,7 +62,14 @@
}
func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
- // Nothing to do.
+ ctx.SetProvider(CommonModuleInfoProvider, &CommonModuleInfo{
+ Enabled: true,
+ PrimaryLicensesProperty: p.primaryLicensesProperty,
+ })
+
+ ctx.SetProvider(PackageInfoProvider, PackageInfo{
+ Properties: p.properties,
+ })
}
func (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
diff --git a/android/packaging.go b/android/packaging.go
index d96cccd..bf18409 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -22,6 +22,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/gobtools"
"github.com/google/blueprint/proptools"
+ "github.com/google/blueprint/uniquelist"
)
// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
@@ -42,7 +43,7 @@
// Whether relPathInPackage should be marked as executable or not
executable bool
- effectiveLicenseFiles *Paths
+ effectiveLicenseFiles uniquelist.UniqueList[Path]
partition string
@@ -52,16 +53,28 @@
skipInstall bool
// Paths of aconfig files for the built artifact
- aconfigPaths *Paths
+ aconfigPaths uniquelist.UniqueList[Path]
// ArchType of the module which produced this packaging spec
archType ArchType
// List of module names that this packaging spec overrides
- overrides *[]string
+ overrides uniquelist.UniqueList[string]
// Name of the module where this packaging spec is output of
owner string
+
+ // If the ninja rule creating the FullInstallPath has already been emitted or not. Do not use,
+ // for the soong-only migration.
+ requiresFullInstall bool
+
+ // The path to the installed file in out/target/product. This is for legacy purposes, with
+ // tools that want to interact with these files outside of the build. You should not use it
+ // inside of the build. Will be nil if this module doesn't require a "full install".
+ fullInstallPath InstallPath
+
+ // String representation of the variation of the module where this packaging spec is output of
+ variation string
}
type packagingSpecGob struct {
@@ -69,13 +82,24 @@
SrcPath Path
SymlinkTarget string
Executable bool
- EffectiveLicenseFiles *Paths
+ EffectiveLicenseFiles Paths
Partition string
SkipInstall bool
- AconfigPaths *Paths
+ AconfigPaths Paths
ArchType ArchType
- Overrides *[]string
+ Overrides []string
Owner string
+ RequiresFullInstall bool
+ FullInstallPath InstallPath
+ Variation string
+}
+
+func (p *PackagingSpec) Owner() string {
+ return p.owner
+}
+
+func (p *PackagingSpec) Variation() string {
+ return p.variation
}
func (p *PackagingSpec) ToGob() *packagingSpecGob {
@@ -84,13 +108,16 @@
SrcPath: p.srcPath,
SymlinkTarget: p.symlinkTarget,
Executable: p.executable,
- EffectiveLicenseFiles: p.effectiveLicenseFiles,
+ EffectiveLicenseFiles: p.effectiveLicenseFiles.ToSlice(),
Partition: p.partition,
SkipInstall: p.skipInstall,
- AconfigPaths: p.aconfigPaths,
+ AconfigPaths: p.aconfigPaths.ToSlice(),
ArchType: p.archType,
- Overrides: p.overrides,
+ Overrides: p.overrides.ToSlice(),
Owner: p.owner,
+ RequiresFullInstall: p.requiresFullInstall,
+ FullInstallPath: p.fullInstallPath,
+ Variation: p.variation,
}
}
@@ -99,13 +126,16 @@
p.srcPath = data.SrcPath
p.symlinkTarget = data.SymlinkTarget
p.executable = data.Executable
- p.effectiveLicenseFiles = data.EffectiveLicenseFiles
+ p.effectiveLicenseFiles = uniquelist.Make(data.EffectiveLicenseFiles)
p.partition = data.Partition
p.skipInstall = data.SkipInstall
- p.aconfigPaths = data.AconfigPaths
+ p.aconfigPaths = uniquelist.Make(data.AconfigPaths)
p.archType = data.ArchType
- p.overrides = data.Overrides
+ p.overrides = uniquelist.Make(data.Overrides)
p.owner = data.Owner
+ p.requiresFullInstall = data.RequiresFullInstall
+ p.fullInstallPath = data.FullInstallPath
+ p.variation = data.Variation
}
func (p *PackagingSpec) GobEncode() ([]byte, error) {
@@ -154,10 +184,7 @@
}
func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
- if p.effectiveLicenseFiles == nil {
- return Paths{}
- }
- return *p.effectiveLicenseFiles
+ return p.effectiveLicenseFiles.ToSlice()
}
func (p *PackagingSpec) Partition() string {
@@ -174,7 +201,30 @@
// Paths of aconfig files for the built artifact
func (p *PackagingSpec) GetAconfigPaths() Paths {
- return *p.aconfigPaths
+ return p.aconfigPaths.ToSlice()
+}
+
+// The path to the installed file in out/target/product. This is for legacy purposes, with
+// tools that want to interact with these files outside of the build. You should not use it
+// inside of the build. Will be nil if this module doesn't require a "full install".
+func (p *PackagingSpec) FullInstallPath() InstallPath {
+ return p.fullInstallPath
+}
+
+// If the ninja rule creating the FullInstallPath has already been emitted or not. Do not use,
+// for the soong-only migration.
+func (p *PackagingSpec) RequiresFullInstall() bool {
+ return p.requiresFullInstall
+}
+
+// The source file to be copied to the FullInstallPath. Do not use, for the soong-only migration.
+func (p *PackagingSpec) SrcPath() Path {
+ return p.srcPath
+}
+
+// The symlink target of the PackagingSpec. Do not use, for the soong-only migration.
+func (p *PackagingSpec) SymlinkTarget() string {
+ return p.symlinkTarget
}
type PackageModule interface {
@@ -456,13 +506,11 @@
// all packaging specs gathered from the high priority deps.
var highPriorities []PackagingSpec
- // Name of the dependency which requested the packaging spec.
- // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
- // (the packaging spec might still be installed if there are some other deps which depend on it).
- var depNames []string
-
// list of module names overridden
- var overridden []string
+ overridden := make(map[string]bool)
+
+ // all installed modules which are not overridden.
+ modulesToInstall := make(map[string]bool)
var arches []ArchType
for _, target := range getSupportedTargets(ctx) {
@@ -479,6 +527,7 @@
return false
}
+ // find all overridden modules and packaging specs
ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
depTag := ctx.OtherModuleDependencyTag(child)
if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
@@ -506,22 +555,32 @@
regularPriorities = append(regularPriorities, ps)
}
- depNames = append(depNames, child.Name())
- if ps.overrides != nil {
- overridden = append(overridden, *ps.overrides...)
+ for o := range ps.overrides.Iter() {
+ overridden[o] = true
}
}
})
- filterOverridden := func(input []PackagingSpec) []PackagingSpec {
- // input minus packaging specs that are overridden
- var filtered []PackagingSpec
- for index, ps := range input {
- if ps.owner != "" && InList(ps.owner, overridden) {
- continue
+ // gather modules to install, skipping overridden modules
+ ctx.WalkDeps(func(child, parent Module) bool {
+ owner := ctx.OtherModuleName(child)
+ if o, ok := child.(OverridableModule); ok {
+ if overriddenBy := o.GetOverriddenBy(); overriddenBy != "" {
+ owner = overriddenBy
}
- // The dependency which requested this packaging spec has been overridden.
- if InList(depNames[index], overridden) {
+ }
+ if overridden[owner] {
+ return false
+ }
+ modulesToInstall[owner] = true
+ return true
+ })
+
+ filterOverridden := func(input []PackagingSpec) []PackagingSpec {
+ // input minus packaging specs that are not installed
+ var filtered []PackagingSpec
+ for _, ps := range input {
+ if !modulesToInstall[ps.owner] {
continue
}
filtered = append(filtered, ps)
@@ -575,12 +634,12 @@
func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
dirsToSpecs[dir] = specs
- return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
+ return p.CopySpecsToDirs(ctx, builder, dirsToSpecs, false)
}
// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into corresponding directories.
-func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
+func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec, preserveTimestamps bool) (entries []string) {
empty := true
for _, specs := range dirsToSpecs {
if len(specs) > 0 {
@@ -614,7 +673,11 @@
builder.Command().Textf("mkdir -p %s", destDir)
}
if ps.symlinkTarget == "" {
- builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
+ cmd := builder.Command().Text("cp")
+ if preserveTimestamps {
+ cmd.Flag("-p")
+ }
+ cmd.Input(ps.srcPath).Text(destPath)
} else {
builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
}
diff --git a/android/path_properties.go b/android/path_properties.go
index 55a4dc0..d769d58 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -54,12 +54,14 @@
var pathDeviceFirstPrefer32Properties []string
var pathDeviceCommonProperties []string
var pathCommonOsProperties []string
+ var pathHostCommonProperties []string
for _, ps := range props {
pathProperties = append(pathProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path")...)
pathDeviceFirstProperties = append(pathDeviceFirstProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first")...)
pathDeviceFirstPrefer32Properties = append(pathDeviceFirstPrefer32Properties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_prefer32")...)
pathDeviceCommonProperties = append(pathDeviceCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_common")...)
pathCommonOsProperties = append(pathCommonOsProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_common_os")...)
+ pathHostCommonProperties = append(pathHostCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_host_common")...)
}
// Remove duplicates to avoid multiple dependencies.
@@ -68,6 +70,7 @@
pathDeviceFirstPrefer32Properties = FirstUniqueStrings(pathDeviceFirstPrefer32Properties)
pathDeviceCommonProperties = FirstUniqueStrings(pathDeviceCommonProperties)
pathCommonOsProperties = FirstUniqueStrings(pathCommonOsProperties)
+ pathHostCommonProperties = FirstUniqueStrings(pathHostCommonProperties)
// Add dependencies to anything that is a module reference.
for _, s := range pathProperties {
@@ -108,6 +111,12 @@
ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m)
}
}
+ // properties tagged "path_host_common" get the host common variant
+ for _, s := range pathHostCommonProperties {
+ if m, t := SrcIsModuleWithTag(s); m != "" {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m)
+ }
+ }
// properties tagged "path_common_os" get the CommonOs variant
for _, s := range pathCommonOsProperties {
if m, t := SrcIsModuleWithTag(s); m != "" {
diff --git a/android/paths.go b/android/paths.go
index bbf10d1..a254717 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -209,6 +209,10 @@
var _ ModuleErrorfContext = blueprint.ModuleContext(nil)
+type AddMissingDependenciesContext interface {
+ AddMissingDependencies([]string)
+}
+
// reportPathError will register an error with the attached context. It
// attempts ctx.ModuleErrorf for a better error message first, then falls
// back to ctx.Errorf.
@@ -220,7 +224,9 @@
// attempts ctx.ModuleErrorf for a better error message first, then falls
// back to ctx.Errorf.
func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) {
- if mctx, ok := ctx.(ModuleErrorfContext); ok {
+ if mctx, ok := ctx.(AddMissingDependenciesContext); ok && ctx.Config().AllowMissingDependencies() {
+ mctx.AddMissingDependencies([]string{fmt.Sprintf(format, args...)})
+ } else if mctx, ok := ctx.(ModuleErrorfContext); ok {
mctx.ModuleErrorf(format, args...)
} else if ectx, ok := ctx.(errorfContext); ok {
ectx.Errorf(format, args...)
@@ -229,6 +235,8 @@
}
}
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
func pathContextName(ctx PathContext, module blueprint.Module) string {
if x, ok := ctx.(interface{ ModuleName(blueprint.Module) string }); ok {
return x.ModuleName(module)
@@ -675,7 +683,7 @@
if module == nil {
return nil, missingDependencyError{[]string{moduleName}}
}
- if !OtherModuleProviderOrDefault(ctx, *module, CommonModuleInfoKey).Enabled {
+ if !OtherModulePointerProviderOrDefault(ctx, *module, CommonModuleInfoProvider).Enabled {
return nil, missingDependencyError{[]string{moduleName}}
}
@@ -1378,7 +1386,7 @@
// PathForArbitraryOutput creates a path for the given components. Unlike PathForOutput,
// the path is relative to the root of the output folder, not the out/soong folder.
-func PathForArbitraryOutput(ctx PathContext, pathComponents ...string) Path {
+func PathForArbitraryOutput(ctx PathContext, pathComponents ...string) WritablePath {
path, err := validatePath(pathComponents...)
if err != nil {
reportPathError(ctx, err)
@@ -1487,33 +1495,6 @@
return p.withRel(path)
}
-// OverlayPath returns the overlay for `path' if it exists. This assumes that the
-// SourcePath is the path to a resource overlay directory.
-func (p SourcePath) OverlayPath(ctx ModuleMissingDepsPathContext, path Path) OptionalPath {
- var relDir string
- if srcPath, ok := path.(SourcePath); ok {
- relDir = srcPath.path
- } else {
- ReportPathErrorf(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
- // No need to put the error message into the returned path since it has been reported already.
- return OptionalPath{}
- }
- dir := filepath.Join(p.path, relDir)
- // Use Glob so that we are run again if the directory is added.
- if pathtools.IsGlob(dir) {
- ReportPathErrorf(ctx, "Path may not contain a glob: %s", dir)
- }
- paths, err := ctx.GlobWithDeps(dir, nil)
- if err != nil {
- ReportPathErrorf(ctx, "glob: %s", err.Error())
- return OptionalPath{}
- }
- if len(paths) == 0 {
- return InvalidOptionalPath(dir + " does not exist")
- }
- return OptionalPathForPath(PathForSource(ctx, paths[0]))
-}
-
// OutputPath is a Path representing an intermediates file path rooted from the build directory
type OutputPath struct {
basePath
@@ -2123,7 +2104,7 @@
var partitionPaths []string
if os.Class == Device {
- partitionPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
+ partitionPaths = []string{"target", "product", *ctx.Config().deviceNameToInstall, partition}
} else {
osName := os.String()
if os == Linux {
@@ -2153,7 +2134,7 @@
reportPathError(ctx, err)
}
- base := pathForPartitionInstallDir(ctx, partition, partitionPath, ctx.Config().KatiEnabled())
+ base := pathForPartitionInstallDir(ctx, partition, partitionPath, true)
return base.Join(ctx, pathComponents...)
}
diff --git a/android/paths_test.go b/android/paths_test.go
index 5e618f9..b125c4e 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -1269,7 +1269,7 @@
ExtendWithErrorHandler(errorHandler).
RunTest(t)
- m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
+ m := result.ModuleForTests(t, "foo", "").Module().(*pathForModuleSrcTestModule)
AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
@@ -1533,13 +1533,13 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
+ foo := result.ModuleForTests(t, "foo", "").Module().(*pathForModuleSrcTestModule)
AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
AssertStringEquals(t, "foo src", "", foo.src)
- bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
+ bar := result.ModuleForTests(t, "bar", "").Module().(*pathForModuleSrcTestModule)
AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
@@ -1561,7 +1561,7 @@
t.Run("install for soong", func(t *testing.T) {
p := PathForModuleInstall(ctx, "install/path")
- AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
+ AssertPathRelativeToTopEquals(t, "install path for soong", "out/target/product/test_device/system/install/path", p)
})
t.Run("install for make", func(t *testing.T) {
p := PathForModuleInstall(ctx, "install/path")
@@ -1584,7 +1584,7 @@
}
expected := []string{
- "out/soong/target/product/test_device/system/install/path",
+ "out/target/product/test_device/system/install/path",
"out/soong/output/path",
"source/path",
}
diff --git a/android/phony.go b/android/phony.go
index f8db88d..99ff0aa 100644
--- a/android/phony.go
+++ b/android/phony.go
@@ -15,6 +15,7 @@
package android
import (
+ "strings"
"sync"
"github.com/google/blueprint"
@@ -54,7 +55,7 @@
func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
p.phonyMap = getSingletonPhonyMap(ctx.Config())
- ctx.VisitAllModules(func(m Module) {
+ ctx.VisitAllModuleProxies(func(m ModuleProxy) {
if info, ok := OtherModuleProvider(ctx, m, ModulePhonyProvider); ok {
for k, v := range info.Phonies {
p.phonyMap[k] = append(p.phonyMap[k], v...)
@@ -68,13 +69,25 @@
}
if !ctx.Config().KatiEnabled() {
+ // In soong-only builds, the phonies can conflict with dist targets that will
+ // be generated in the packaging step. Instead of emitting a blueprint/ninja phony directly,
+ // create a makefile that defines the phonies that will be included in the packaging step.
+ // Make will dedup the phonies there.
+ var buildPhonyFileContents strings.Builder
for _, phony := range p.phonyList {
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Outputs: []WritablePath{PathForPhony(ctx, phony)},
- Implicits: p.phonyMap[phony],
- })
+ buildPhonyFileContents.WriteString(".PHONY: ")
+ buildPhonyFileContents.WriteString(phony)
+ buildPhonyFileContents.WriteString("\n")
+ buildPhonyFileContents.WriteString(phony)
+ buildPhonyFileContents.WriteString(":")
+ for _, dep := range p.phonyMap[phony] {
+ buildPhonyFileContents.WriteString(" ")
+ buildPhonyFileContents.WriteString(dep.String())
+ }
+ buildPhonyFileContents.WriteString("\n")
}
+ buildPhonyFile := PathForOutput(ctx, "soong_phony_targets.mk")
+ writeValueIfChanged(ctx, absolutePath(buildPhonyFile.String()), buildPhonyFileContents.String())
}
}
diff --git a/android/plugin.go b/android/plugin.go
index d62fc94..4348f14 100644
--- a/android/plugin.go
+++ b/android/plugin.go
@@ -135,6 +135,6 @@
disallowedPlugins[name] = true
})
if len(disallowedPlugins) > 0 {
- ctx.Errorf("New plugins are not supported; however %q were found. Please reach out to the build team or use BUILD_BROKEN_PLUGIN_VALIDATION (see Changes.md for more info).", SortedStringKeys(disallowedPlugins))
+ ctx.Errorf("New plugins are not supported; however %q were found. Please reach out to the build team or use BUILD_BROKEN_PLUGIN_VALIDATION (see Changes.md for more info).", SortedKeys(disallowedPlugins))
}
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 0ac67b3..1ff009b 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -28,6 +28,7 @@
func RegisterPrebuiltMutators(ctx RegistrationContext) {
ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators)
+ ctx.PreDepsMutators(RegisterPrebuiltsPreDepsMutators)
ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
}
@@ -195,6 +196,10 @@
return p.properties.UsePrebuilt
}
+func (p *Prebuilt) SetUsePrebuilt(use bool) {
+ p.properties.UsePrebuilt = use
+}
+
// Called to provide the srcs value for the prebuilt module.
//
// This can be called with a context for any module not just the prebuilt one itself. It can also be
@@ -352,6 +357,17 @@
return true
}
+func IsModulePreferredProxy(ctx OtherModuleProviderContext, module ModuleProxy) bool {
+ if OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt {
+ // A source module that has been replaced by a prebuilt counterpart.
+ return false
+ }
+ if p, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok {
+ return p.UsePrebuilt
+ }
+ return true
+}
+
// IsModulePrebuilt returns true if the module implements PrebuiltInterface and
// has been initialized as a prebuilt and so returns a non-nil value from the
// PrebuiltInterface.Prebuilt() method.
@@ -381,10 +397,10 @@
// the right module. This function is only safe to call after all TransitionMutators
// have run, e.g. in GenerateAndroidBuildActions.
func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
- if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt {
+ if !OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).ReplacedByPrebuilt {
return module
}
- if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleProviderKey); ok {
+ if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok {
// If we're given a prebuilt then assume there's no source module around.
return module
}
@@ -396,7 +412,7 @@
if prebuiltMod != nil {
return false
}
- if ctx.EqualModules(parent, ctx.Module()) {
+ if EqualModules(parent, ctx.Module()) {
// First level: Only recurse if the module is found as a direct dependency.
sourceModDepFound = child == module
return sourceModDepFound
@@ -422,9 +438,12 @@
ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).UsesRename()
}
-func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
+func RegisterPrebuiltsPreDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).UsesReverseDependencies()
ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator)
+}
+
+func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies()
}
@@ -468,7 +487,7 @@
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
if ctx.OtherModuleReverseDependencyVariantExists(name) {
- ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
+ ctx.AddReverseVariationDependency(nil, PrebuiltDepTag, name)
p.properties.SourceExists = true
}
}
@@ -588,11 +607,6 @@
if !moduleInFamily.ExportedToMake() {
continue
}
- // Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first.
- // This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case
- if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
- continue
- }
if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt {
if selectedPrebuilt == nil {
selectedPrebuilt = moduleInFamily
@@ -604,6 +618,13 @@
}
}
+func IsDontReplaceSourceWithPrebuiltTag(tag blueprint.DependencyTag) bool {
+ if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
+ return !t.ReplaceSourceWithPrebuilt()
+ }
+ return false
+}
+
// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the
// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not
// be used, disable installing it.
@@ -612,26 +633,10 @@
if p := GetEmbeddedPrebuilt(m); p != nil {
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
- psi := PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) {
- psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
- })
if p.properties.UsePrebuilt {
if p.properties.SourceExists {
ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
- if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
- // Do not replace deps to the top-level prebuilt java_sdk_library hook.
- // This hook has been special-cased in #isSelected to be _always_ active, even in next builds
- // for dexpreopt and hiddenapi processing.
- // If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs
- // will get prebuilt stubs
- // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
- if psi.IsSelected(name) {
- return false
- }
- }
-
if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
return t.ReplaceSourceWithPrebuilt()
}
@@ -653,23 +658,13 @@
// java_sdk_library_import is a macro that creates
// 1. top-level "impl" library
// 2. stub libraries (suffixed with .stubs...)
-//
-// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim
-// to provide the jar deapxed from the prebuilt apex
-//
-// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the
-// selection of the top-level "impl" library so that this hook can work
-//
-// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main
func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool {
if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
sln := proptools.String(sdkLibrary.SdkLibraryName())
// This is the top-level library
- // Do not supersede the existing prebuilts vs source selection mechanisms
- // TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() {
- return false
+ return psi.IsSelected(m.Name())
}
// Stub library created by java_sdk_library_import
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index 17b3230..7773bf8 100644
--- a/android/prebuilt_build_tool.go
+++ b/android/prebuilt_build_tool.go
@@ -84,13 +84,12 @@
t.toolPath = OptionalPathForPath(installedPath)
}
-func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) {
- if makeVar := String(t.properties.Export_to_make_var); makeVar != "" {
- if t.Target().Os != ctx.Config().BuildOS {
- return
- }
- ctx.StrictRaw(makeVar, t.toolPath.String())
+func (t *prebuiltBuildTool) MakeVars(ctx MakeVarsModuleContext) []ModuleMakeVarsValue {
+ if makeVar := String(t.properties.Export_to_make_var); makeVar != "" &&
+ t.Target().Os == ctx.Config().BuildOS {
+ return []ModuleMakeVarsValue{{makeVar, t.toolPath.String()}}
}
+ return nil
}
func (t *prebuiltBuildTool) HostToolPath() OptionalPath {
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index b90ef3b..d31fc4f 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -335,7 +335,7 @@
).RunTestWithBp(t, bp)
for _, variant := range result.ModuleVariantsForTests("foo") {
- foo := result.ModuleForTests("foo", variant)
+ foo := result.ModuleForTests(t, "foo", variant)
t.Run(foo.Module().Target().Os.String(), func(t *testing.T) {
var dependsOnSourceModule, dependsOnPrebuiltModule bool
result.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
@@ -551,6 +551,9 @@
}
func (s *sourceModule) Srcs() Paths {
+ if s.src == nil {
+ return nil
+ }
return Paths{s.src}
}
diff --git a/android/product_packages_file.go b/android/product_packages_file.go
new file mode 100644
index 0000000..c7c18a2
--- /dev/null
+++ b/android/product_packages_file.go
@@ -0,0 +1,39 @@
+// 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 (
+ "strings"
+)
+
+func init() {
+ RegisterParallelSingletonType("product_packages_file_singleton", productPackagesFileSingletonFactory)
+}
+
+func productPackagesFileSingletonFactory() Singleton {
+ return &productPackagesFileSingleton{}
+}
+
+type productPackagesFileSingleton struct{}
+
+func (s *productPackagesFileSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // There's no HasDeviceName() function, but the device name and device product should always
+ // both be present or not.
+ if ctx.Config().HasDeviceProduct() {
+ productPackages := ctx.Config().productVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages
+ output := PathForArbitraryOutput(ctx, "target", "product", ctx.Config().DeviceName(), "product_packages.txt")
+ WriteFileRule(ctx, output, strings.Join(productPackages, "\n"))
+ }
+}
diff --git a/android/proto.go b/android/proto.go
index 66faa20..91d6732 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -75,7 +75,7 @@
}
ctx.VisitDirectDepsProxyWithTag(ProtoPluginDepTag, func(dep ModuleProxy) {
- if h, ok := OtherModuleProvider(ctx, dep, HostToolProviderKey); !ok || !h.HostToolPath.Valid() {
+ if h, ok := OtherModuleProvider(ctx, dep, HostToolProviderInfoProvider); !ok || !h.HostToolPath.Valid() {
ctx.PropertyErrorf("proto.plugin", "module %q is not a host tool provider",
ctx.OtherModuleName(dep))
} else {
diff --git a/android/provider.go b/android/provider.go
index 81d17a1..aae93ef 100644
--- a/android/provider.go
+++ b/android/provider.go
@@ -4,8 +4,8 @@
"github.com/google/blueprint"
)
-// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext for use in OtherModuleProvider.
+// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
+// for use in OtherModuleProvider.
type OtherModuleProviderContext interface {
otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
}
@@ -13,16 +13,20 @@
var _ OtherModuleProviderContext = BaseModuleContext(nil)
var _ OtherModuleProviderContext = ModuleContext(nil)
var _ OtherModuleProviderContext = BottomUpMutatorContext(nil)
-var _ OtherModuleProviderContext = TopDownMutatorContext(nil)
var _ OtherModuleProviderContext = SingletonContext(nil)
var _ OtherModuleProviderContext = (*TestContext)(nil)
+// ConfigAndOtherModuleProviderContext is OtherModuleProviderContext + ConfigContext
+type ConfigAndOtherModuleProviderContext interface {
+ OtherModuleProviderContext
+ ConfigContext
+}
+
// OtherModuleProvider reads the provider for the given module. If the provider has been set the value is
// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
//
-// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext.
+// OtherModuleProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
value, ok := ctx.otherModuleProvider(getWrappedModule(module), provider)
if !ok {
@@ -37,8 +41,16 @@
return value
}
-// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext for use in ModuleProvider.
+func OtherModulePointerProviderOrDefault[K *T, T any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K {
+ if value, ok := OtherModuleProvider(ctx, module, provider); ok {
+ return value
+ }
+ var val T
+ return &val
+}
+
+// ModuleProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
+// for use in ModuleProvider.
type ModuleProviderContext interface {
provider(provider blueprint.AnyProviderKey) (any, bool)
}
@@ -46,14 +58,12 @@
var _ ModuleProviderContext = BaseModuleContext(nil)
var _ ModuleProviderContext = ModuleContext(nil)
var _ ModuleProviderContext = BottomUpMutatorContext(nil)
-var _ ModuleProviderContext = TopDownMutatorContext(nil)
// ModuleProvider reads the provider for the current module. If the provider has been set the value is
// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
//
-// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext.
+// ModuleProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
func ModuleProvider[K any](ctx ModuleProviderContext, provider blueprint.ProviderKey[K]) (K, bool) {
value, ok := ctx.provider(provider)
if !ok {
@@ -63,8 +73,8 @@
return value.(K), ok
}
-// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext for use in SetProvider.
+// SetProviderContext is a helper interface that is a subset of ModuleContext or BottomUpMutatorContext
+// for use in SetProvider.
type SetProviderContext interface {
setProvider(provider blueprint.AnyProviderKey, value any)
}
@@ -72,15 +82,13 @@
var _ SetProviderContext = BaseModuleContext(nil)
var _ SetProviderContext = ModuleContext(nil)
var _ SetProviderContext = BottomUpMutatorContext(nil)
-var _ SetProviderContext = TopDownMutatorContext(nil)
// SetProvider sets the value for a provider for the current module. It panics if not called
// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
// is not of the appropriate type, or if the value has already been set. The value should not
// be modified after being passed to SetProvider.
//
-// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
-// TopDownMutatorContext.
+// SetProviderContext is a helper interface that accepts ModuleContext or BottomUpMutatorContext.
func SetProvider[K any](ctx SetProviderContext, provider blueprint.ProviderKey[K], value K) {
ctx.setProvider(provider, value)
}
diff --git a/genrule/allowlists.go b/android/provider_keys.go
similarity index 67%
rename from genrule/allowlists.go
rename to android/provider_keys.go
index 45a7f72..60b383f 100644
--- a/genrule/allowlists.go
+++ b/android/provider_keys.go
@@ -1,4 +1,4 @@
-// Copyright 2023 Google Inc. All rights reserved.
+// Copyright 2025 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.
@@ -12,11 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package genrule
+package android
-var (
- SandboxingDenyModuleList = []string{
- // go/keep-sorted start
- // go/keep-sorted end
- }
-)
+import "github.com/google/blueprint"
+
+// Providers of package filesystem
+type AndroidDeviceInfo struct {
+ Main_device bool
+}
+
+var AndroidDeviceInfoProvider = blueprint.NewProvider[AndroidDeviceInfo]()
diff --git a/android/raw_files.go b/android/raw_files.go
index 9d7f5e8..ebba4d1 100644
--- a/android/raw_files.go
+++ b/android/raw_files.go
@@ -18,7 +18,6 @@
"crypto/sha1"
"encoding/hex"
"fmt"
- "github.com/google/blueprint"
"io"
"io/fs"
"os"
@@ -26,25 +25,28 @@
"strings"
"testing"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/syncmap"
+
"github.com/google/blueprint/proptools"
)
// WriteFileRule creates a ninja rule to write contents to a file by immediately writing the
// contents, plus a trailing newline, to a file in out/soong/raw-${TARGET_PRODUCT}, and then creating
// a ninja rule to copy the file into place.
-func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
- writeFileRule(ctx, outputFile, content, true, false)
+func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string, validations ...Path) {
+ writeFileRule(ctx, outputFile, content, true, false, validations)
}
// WriteFileRuleVerbatim creates a ninja rule to write contents to a file by immediately writing the
// contents to a file in out/soong/raw-${TARGET_PRODUCT}, and then creating a ninja rule to copy the file into place.
-func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- writeFileRule(ctx, outputFile, content, false, false)
+func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string, validations ...Path) {
+ writeFileRule(ctx, outputFile, content, false, false, validations)
}
// WriteExecutableFileRuleVerbatim is the same as WriteFileRuleVerbatim, but runs chmod +x on the result
-func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- writeFileRule(ctx, outputFile, content, false, true)
+func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string, validations ...Path) {
+ writeFileRule(ctx, outputFile, content, false, true, validations)
}
// tempFile provides a testable wrapper around a file in out/soong/.temp. It writes to a temporary file when
@@ -124,7 +126,7 @@
return tempFile, hex.EncodeToString(hash.Sum(nil))
}
-func writeFileRule(ctx BuilderContext, outputFile WritablePath, content string, newline bool, executable bool) {
+func writeFileRule(ctx BuilderContext, outputFile WritablePath, content string, newline bool, executable bool, validations Paths) {
// Write the contents to a temporary file while computing its hash.
tempFile, hash := writeContentToTempFileAndHash(ctx, content, newline)
@@ -186,6 +188,7 @@
Input: rawPath,
Output: outputFile,
Description: "raw " + outputFile.Base(),
+ Validations: validations,
})
}
@@ -211,10 +214,10 @@
var rawFileSetKey OnceKey = NewOnceKey("raw file set")
-func getRawFileSet(config Config) *SyncMap[string, rawFileInfo] {
+func getRawFileSet(config Config) *syncmap.SyncMap[string, rawFileInfo] {
return config.Once(rawFileSetKey, func() any {
- return &SyncMap[string, rawFileInfo]{}
- }).(*SyncMap[string, rawFileInfo])
+ return &syncmap.SyncMap[string, rawFileInfo]{}
+ }).(*syncmap.SyncMap[string, rawFileInfo])
}
// ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
diff --git a/android/recovery_build_prop.go b/android/recovery_build_prop.go
new file mode 100644
index 0000000..ac7d2ec
--- /dev/null
+++ b/android/recovery_build_prop.go
@@ -0,0 +1,113 @@
+// 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 "github.com/google/blueprint/proptools"
+
+func init() {
+ RegisterModuleType("recovery_build_prop", RecoveryBuildPropModuleFactory)
+}
+
+type recoveryBuildPropProperties struct {
+ // Path to the system build.prop file
+ System_build_prop *string `android:"path"`
+
+ // Path to the vendor build.prop file
+ Vendor_build_prop *string `android:"path"`
+
+ // Path to the odm build.prop file
+ Odm_build_prop *string `android:"path"`
+
+ // Path to the product build.prop file
+ Product_build_prop *string `android:"path"`
+
+ // Path to the system_ext build.prop file
+ System_ext_build_prop *string `android:"path"`
+}
+
+type recoveryBuildPropModule struct {
+ ModuleBase
+ properties recoveryBuildPropProperties
+
+ outputFilePath ModuleOutPath
+
+ installPath InstallPath
+}
+
+func RecoveryBuildPropModuleFactory() Module {
+ module := &recoveryBuildPropModule{}
+ module.AddProperties(&module.properties)
+ InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
+ return module
+}
+
+// Overrides ctx.Module().InstallInRoot().
+// recovery_build_prop module always installs in root so that the prop.default
+// file is installed in recovery/root instead of recovery/root/system
+func (r *recoveryBuildPropModule) InstallInRoot() bool {
+ return true
+}
+
+func (r *recoveryBuildPropModule) appendRecoveryUIProperties(ctx ModuleContext, rule *RuleBuilder) {
+ rule.Command().Text("echo '#' >>").Output(r.outputFilePath)
+ rule.Command().Text("echo '# RECOVERY UI BUILD PROPERTIES' >>").Output(r.outputFilePath)
+ rule.Command().Text("echo '#' >>").Output(r.outputFilePath)
+
+ for propName, val := range ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrivateRecoveryUiProperties {
+ if len(val) > 0 {
+ rule.Command().
+ Textf("echo ro.recovery.ui.%s=%s >>", propName, val).
+ Output(r.outputFilePath)
+ }
+ }
+}
+
+func (r *recoveryBuildPropModule) getBuildProps(ctx ModuleContext) Paths {
+ var buildProps Paths
+ for _, buildProp := range []*string{
+ r.properties.System_build_prop,
+ r.properties.Vendor_build_prop,
+ r.properties.Odm_build_prop,
+ r.properties.Product_build_prop,
+ r.properties.System_ext_build_prop,
+ } {
+ if buildProp != nil {
+ if buildPropPath := PathForModuleSrc(ctx, proptools.String(buildProp)); buildPropPath != nil {
+ buildProps = append(buildProps, buildPropPath)
+ }
+ }
+ }
+ return buildProps
+}
+
+func (r *recoveryBuildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ if !r.InstallInRecovery() {
+ ctx.ModuleErrorf("recovery_build_prop module must set `recovery` property to true")
+ }
+ r.outputFilePath = PathForModuleOut(ctx, ctx.ModuleName(), "prop.default")
+
+ // Replicates the logic in https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2733;drc=0585bb1bcf4c89065adaf709f48acc8b869fd3ce
+ rule := NewRuleBuilder(pctx, ctx)
+ rule.Command().Text("rm").FlagWithOutput("-f ", r.outputFilePath)
+ rule.Command().Text("cat").
+ Inputs(r.getBuildProps(ctx)).
+ Text(">>").
+ Output(r.outputFilePath)
+ r.appendRecoveryUIProperties(ctx, rule)
+
+ rule.Build(ctx.ModuleName(), "generating recovery prop.default")
+ r.installPath = PathForModuleInstall(ctx)
+ ctx.InstallFile(r.installPath, "prop.default", r.outputFilePath)
+}
diff --git a/android/register.go b/android/register.go
index 8d2f19e..10c9114 100644
--- a/android/register.go
+++ b/android/register.go
@@ -89,7 +89,6 @@
type mutator struct {
name string
bottomUpMutator blueprint.BottomUpMutator
- topDownMutator blueprint.TopDownMutator
transitionMutator blueprint.TransitionMutator
usesRename bool
@@ -192,6 +191,11 @@
func collateGloballyRegisteredSingletons() sortableComponents {
allSingletons := append(sortableComponents(nil), singletons...)
allSingletons = append(allSingletons,
+ // Soong only androidmk is registered later than other singletons in order to collect
+ // dist contributions from other singletons. This singleton is registered just before
+ // phony so that its phony rules can be collected by the phony singleton.
+ singleton{parallel: false, name: "soongonlyandroidmk", factory: soongOnlyAndroidMkSingletonFactory},
+
// Register phony just before makevars so it can write out its phony rules as Make rules
singleton{parallel: false, name: "phony", factory: phonySingletonFactory},
diff --git a/android/removed_package.go b/android/removed_package.go
new file mode 100644
index 0000000..aa54c2a
--- /dev/null
+++ b/android/removed_package.go
@@ -0,0 +1,60 @@
+package android
+
+import (
+ "fmt"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ InitRegistrationContext.RegisterModuleType("removed_package", removedPackageModuleFactory)
+}
+
+type removedPackageModuleProps struct {
+ // The error message to display when this module is built. This is optional, there is a
+ // reasonable default message.
+ Message *string
+}
+
+type removedPackageModule struct {
+ ModuleBase
+ properties removedPackageModuleProps
+}
+
+// removed_package will cause a build failure when it's included in PRODUCT_PACKAGES. It's needed
+// because currently you can add non-existent packages to PRODUCT_PACKAGES, and the build will
+// not notice/complain, unless you opt-into enforcement via $(call enforce-product-packages-exist).
+// Opting into the enforcement is difficult in some cases, because a package exists on some source
+// trees but not on others. removed_package is an intermediate solution that allows you to remove
+// a package and still get an error if it remains in PRODUCT_PACKAGES somewhere.
+func removedPackageModuleFactory() Module {
+ m := &removedPackageModule{}
+ InitAndroidModule(m)
+ m.AddProperties(&m.properties)
+ return m
+}
+
+var removedPackageRule = pctx.AndroidStaticRule("removed_package", blueprint.RuleParams{
+ Command: "echo $message && false",
+}, "message")
+
+func (m *removedPackageModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ // Unchecked module so that checkbuild doesn't fail
+ ctx.UncheckedModule()
+
+ out := PathForModuleOut(ctx, "out.txt")
+ message := fmt.Sprintf("%s has been removed, and can no longer be used.", ctx.ModuleName())
+ if m.properties.Message != nil {
+ message = *m.properties.Message
+ }
+ ctx.Build(pctx, BuildParams{
+ Rule: removedPackageRule,
+ Output: out,
+ Args: map[string]string{
+ "message": proptools.ShellEscape(message),
+ },
+ })
+
+ ctx.InstallFile(PathForModuleInstall(ctx, "removed_module"), ctx.ModuleName(), out)
+}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index db56c3f..01fe6d8 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -660,12 +660,17 @@
}
for _, c := range r.commands {
for _, tool := range c.packagedTools {
- command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
- From: proto.String(tool.srcPath.String()),
- To: proto.String(sboxPathForPackagedToolRel(tool)),
- Executable: proto.Bool(tool.executable),
- })
- tools = append(tools, tool.srcPath)
+ if tool.srcPath != nil {
+ command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+ From: proto.String(tool.srcPath.String()),
+ To: proto.String(sboxPathForPackagedToolRel(tool)),
+ Executable: proto.Bool(tool.executable),
+ })
+ tools = append(tools, tool.srcPath)
+ } else if tool.SymlinkTarget() == "" {
+ // We ignore symlinks for now, could be added later if needed
+ panic("Expected tool packagingSpec to either be a file or symlink")
+ }
}
}
}
@@ -1187,7 +1192,11 @@
// Textf adds the specified formatted text to the command line. The text should not contain input or output paths or
// the rule will not have them listed in its dependencies or outputs.
func (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand {
- return c.Text(fmt.Sprintf(format, a...))
+ if c.buf.Len() > 0 {
+ c.buf.WriteByte(' ')
+ }
+ fmt.Fprintf(&c.buf, format, a...)
+ return c
}
// Flag adds the specified raw text to the command line. The text should not contain input or output paths or the
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index e1a1e08..5f3b9be 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -358,7 +358,7 @@
"command3 input3 out_local/soong/module/output2 out_local/soong/module/output3 input3 out_local/soong/module/output2",
}
- wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
+ wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
"out_local/soong/module/DepFile out_local/soong/module/depfile out_local/soong/module/ImplicitDepFile out_local/soong/module/depfile2"
AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
@@ -388,7 +388,7 @@
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
- wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
+ wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
@@ -651,7 +651,7 @@
outFile := "out/soong/.intermediates/foo/gen/foo"
rspFile := "out/soong/.intermediates/foo/rsp"
rspFile2 := "out/soong/.intermediates/foo/rsp2"
- module := result.ModuleForTests("foo", "")
+ module := result.ModuleForTests(t, "foo", "")
check(t, module.Rule("rule"), module.Output(rspFile2),
"cp in "+outFile+" @"+rspFile+" @"+rspFile2,
outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
@@ -664,11 +664,11 @@
rspFile := filepath.Join(outDir, "rsp")
rspFile2 := filepath.Join(outDir, "rsp2")
manifest := filepath.Join(outDir, "sbox.textproto")
- sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
+ sbox := filepath.Join("out", "host", result.Config.PrebuiltOS(), "bin/sbox")
sandboxPath := shared.TempDirForOutDir("out/soong")
cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
- module := result.ModuleForTests("foo_sbox", "")
+ module := result.ModuleForTests(t, "foo_sbox", "")
check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
})
@@ -680,12 +680,12 @@
rspFile := filepath.Join(outDir, "rsp")
rspFile2 := filepath.Join(outDir, "rsp2")
manifest := filepath.Join(outDir, "sbox.textproto")
- sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
+ sbox := filepath.Join("out", "host", result.Config.PrebuiltOS(), "bin/sbox")
sandboxPath := shared.TempDirForOutDir("out/soong")
cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
- module := result.ModuleForTests("foo_sbox_inputs", "")
+ module := result.ModuleForTests(t, "foo_sbox_inputs", "")
check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
})
@@ -693,7 +693,7 @@
outFile := filepath.Join("out/soong/singleton/gen/baz")
rspFile := filepath.Join("out/soong/singleton/rsp")
rspFile2 := filepath.Join("out/soong/singleton/rsp2")
- singleton := result.SingletonForTests("rule_builder_test")
+ singleton := result.SingletonForTests(t, "rule_builder_test")
check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
"cp in "+outFile+" @"+rspFile+" @"+rspFile2,
outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
@@ -756,14 +756,14 @@
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
t.Run("sbox", func(t *testing.T) {
- gen := result.ModuleForTests(test.name+"_sbox", "")
+ gen := result.ModuleForTests(t, test.name+"_sbox", "")
manifest := RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("sbox.textproto"))
hash := manifest.Commands[0].GetInputHash()
AssertStringEquals(t, "hash", test.expectedHash, hash)
})
t.Run("", func(t *testing.T) {
- gen := result.ModuleForTests(test.name+"", "")
+ gen := result.ModuleForTests(t, test.name+"", "")
command := gen.Output("gen/" + test.name).RuleParams.Command
if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
t.Errorf("Expected command line to end with %q, got %q", w, g)
diff --git a/android/sbom.go b/android/sbom.go
index f2b9c0f..fc61c41 100644
--- a/android/sbom.go
+++ b/android/sbom.go
@@ -84,12 +84,6 @@
Inputs: []Path{this.sbomFile},
Output: PathForPhony(ctx, "sbom"),
})
- }
-}
-
-func (this *sbomSingleton) MakeVars(ctx MakeVarsContext) {
- // When building SBOM of products
- if !ctx.Config().UnbundledBuildApps() {
ctx.DistForGoalWithFilename("droid", this.sbomFile, "sbom/sbom.spdx.json")
}
}
diff --git a/android/sdk_version.go b/android/sdk_version.go
index a9b88fb..fa3abaa 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -123,6 +123,31 @@
}
}
+func JavaLibraryNameToSdkKind(name string) (SdkKind, bool) {
+ if name == SdkPublic.DefaultJavaLibraryName() {
+ return SdkPublic, true
+ }
+ if name == SdkSystem.DefaultJavaLibraryName() {
+ return SdkSystem, true
+ }
+ if name == SdkTest.DefaultJavaLibraryName() {
+ return SdkTest, true
+ }
+ if name == SdkTestFrameworksCore.DefaultJavaLibraryName() {
+ return SdkTestFrameworksCore, true
+ }
+ if name == SdkCore.DefaultJavaLibraryName() {
+ return SdkCore, true
+ }
+ if name == SdkModule.DefaultJavaLibraryName() {
+ return SdkModule, true
+ }
+ if name == SdkSystemServer.DefaultJavaLibraryName() {
+ return SdkSystemServer, true
+ }
+ return SdkInvalid, false
+}
+
func (k SdkKind) DefaultExportableJavaLibraryName() string {
switch k {
case SdkPublic, SdkSystem, SdkTest, SdkModule, SdkSystemServer:
diff --git a/android/selects_test.go b/android/selects_test.go
index 1397ed8..8e469f8 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -666,6 +666,81 @@
},
},
{
+ name: "Select on integer soong config variable",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+ 34: "34",
+ default: "other",
+ }),
+ }
+ `,
+ vendorVars: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "34",
+ },
+ },
+ vendorVarTypes: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "int",
+ },
+ },
+ provider: selectsTestProvider{
+ my_string: proptools.StringPtr("34"),
+ },
+ },
+ {
+ name: "Select on integer soong config variable default",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_string: select(soong_config_variable("my_namespace", "my_variable"), {
+ 34: "34",
+ default: "other",
+ }),
+ }
+ `,
+ vendorVars: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "5",
+ },
+ },
+ vendorVarTypes: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "int",
+ },
+ },
+ provider: selectsTestProvider{
+ my_string: proptools.StringPtr("other"),
+ },
+ },
+ {
+ name: "Assign to integer property",
+ bp: `
+ my_module_type {
+ name: "foo",
+ my_int64: select(soong_config_variable("my_namespace", "my_variable"), {
+ any @ val: val,
+ default: "other",
+ }),
+ }
+ `,
+ vendorVars: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "5",
+ },
+ },
+ vendorVarTypes: map[string]map[string]string{
+ "my_namespace": {
+ "my_variable": "int",
+ },
+ },
+ provider: selectsTestProvider{
+ my_int64: proptools.Int64Ptr(5),
+ },
+ },
+ {
name: "Mismatched condition types",
bp: `
my_module_type {
@@ -1118,7 +1193,7 @@
for moduleName := range tc.providers {
expected := tc.providers[moduleName]
- m := result.ModuleForTests(moduleName, "android_arm64_armv8-a")
+ m := result.ModuleForTests(t, moduleName, "android_arm64_armv8-a")
p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey)
if !reflect.DeepEqual(p, expected) {
t.Errorf("Expected:\n %q\ngot:\n %q", expected.String(), p.String())
@@ -1132,6 +1207,7 @@
type selectsTestProvider struct {
my_bool *bool
my_string *string
+ my_int64 *int64
my_string_list *[]string
my_paths *[]string
replacing_string_list *[]string
@@ -1181,6 +1257,7 @@
type selectsMockModuleProperties struct {
My_bool proptools.Configurable[bool]
+ My_int64 proptools.Configurable[int64]
My_string proptools.Configurable[string]
My_string_list proptools.Configurable[[]string]
My_paths proptools.Configurable[[]string] `android:"path"`
@@ -1213,6 +1290,7 @@
SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{
my_bool: optionalToPtr(p.properties.My_bool.Get(ctx)),
my_string: optionalToPtr(p.properties.My_string.Get(ctx)),
+ my_int64: optionalToPtr(p.properties.My_int64.Get(ctx)),
my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)),
my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)),
replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)),
diff --git a/android/singleton.go b/android/singleton.go
index 0754b0c..e5f2684 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -15,6 +15,9 @@
package android
import (
+ "slices"
+ "sync"
+
"github.com/google/blueprint"
)
@@ -33,7 +36,7 @@
// ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer` enforcing visibility rules.
// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
- ModuleVariantsFromName(referer Module, name string) []Module
+ ModuleVariantsFromName(referer ModuleProxy, name string) []ModuleProxy
otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
@@ -81,6 +84,9 @@
VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy))
PrimaryModule(module Module) Module
+
+ PrimaryModuleProxy(module ModuleProxy) ModuleProxy
+
IsFinalModule(module Module) bool
AddNinjaFileDeps(deps ...string)
@@ -97,6 +103,24 @@
// HasMutatorFinished returns true if the given mutator has finished running.
// It will panic if given an invalid mutator name.
HasMutatorFinished(mutatorName string) bool
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoal(goal string, paths ...Path)
+
+ // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when the specified
+ // goal is built.
+ DistForGoalWithFilename(goal string, path Path, filename string)
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoals(goals []string, paths ...Path)
+
+ // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when any of the
+ // specified goals are built.
+ DistForGoalsWithFilename(goals []string, path Path, filename string)
}
type singletonAdaptor struct {
@@ -118,6 +142,13 @@
s.buildParams = sctx.buildParams
s.ruleParams = sctx.ruleParams
+
+ if len(sctx.dists) > 0 {
+ dists := getSingletonDists(sctx.Config())
+ dists.lock.Lock()
+ defer dists.lock.Unlock()
+ dists.dists = append(dists.dists, sctx.dists...)
+ }
}
func (s *singletonAdaptor) BuildParamsForTests() []BuildParams {
@@ -128,6 +159,19 @@
return s.ruleParams
}
+var singletonDistsKey = NewOnceKey("singletonDistsKey")
+
+type singletonDistsAndLock struct {
+ dists []dist
+ lock sync.Mutex
+}
+
+func getSingletonDists(config Config) *singletonDistsAndLock {
+ return config.Once(singletonDistsKey, func() interface{} {
+ return &singletonDistsAndLock{}
+ }).(*singletonDistsAndLock)
+}
+
type Singleton interface {
GenerateBuildActions(SingletonContext)
}
@@ -137,6 +181,7 @@
buildParams []BuildParams
ruleParams map[blueprint.Rule]blueprint.RuleParams
+ dists []dist
}
func (s *singletonContextAdaptor) blueprintSingletonContext() blueprint.SingletonContext {
@@ -229,6 +274,26 @@
}
}
+func (s *singletonContextAdaptor) ModuleName(module blueprint.Module) string {
+ return s.SingletonContext.ModuleName(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) ModuleDir(module blueprint.Module) string {
+ return s.SingletonContext.ModuleDir(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) ModuleSubDir(module blueprint.Module) string {
+ return s.SingletonContext.ModuleSubDir(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) ModuleType(module blueprint.Module) string {
+ return s.SingletonContext.ModuleType(getWrappedModule(module))
+}
+
+func (s *singletonContextAdaptor) BlueprintFile(module blueprint.Module) string {
+ return s.SingletonContext.BlueprintFile(getWrappedModule(module))
+}
+
func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
s.SingletonContext.VisitAllModules(visit)
}
@@ -266,40 +331,42 @@
}
func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) {
- s.SingletonContext.VisitAllModuleVariantProxies(module, visitProxyAdaptor(visit))
+ s.SingletonContext.VisitAllModuleVariantProxies(getWrappedModule(module), visitProxyAdaptor(visit))
}
func (s *singletonContextAdaptor) PrimaryModule(module Module) Module {
return s.SingletonContext.PrimaryModule(module).(Module)
}
-func (s *singletonContextAdaptor) IsFinalModule(module Module) bool {
- return s.SingletonContext.IsFinalModule(module)
+func (s *singletonContextAdaptor) PrimaryModuleProxy(module ModuleProxy) ModuleProxy {
+ return ModuleProxy{s.SingletonContext.PrimaryModuleProxy(module.module)}
}
-func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module {
- // get module reference for visibility enforcement
- qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), referer)
+func (s *singletonContextAdaptor) IsFinalModule(module Module) bool {
+ return s.SingletonContext.IsFinalModule(getWrappedModule(module))
+}
- modules := s.SingletonContext.ModuleVariantsFromName(referer, name)
- result := make([]Module, 0, len(modules))
- for _, m := range modules {
- if module, ok := m.(Module); ok {
- // enforce visibility
- depName := s.ModuleName(module)
- depDir := s.ModuleDir(module)
- depQualified := qualifiedModuleName{depDir, depName}
- // Targets are always visible to other targets in their own package.
- if depQualified.pkg != qualified.name.pkg {
- rule := effectiveVisibilityRules(s.Config(), depQualified)
- if !rule.matches(qualified) {
- s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility",
- referer.Name(), depQualified, "//"+s.ModuleDir(referer))
- continue
- }
+func (s *singletonContextAdaptor) ModuleVariantsFromName(referer ModuleProxy, name string) []ModuleProxy {
+ // get module reference for visibility enforcement
+ qualified := createVisibilityModuleProxyReference(s, s.ModuleName(referer), s.ModuleDir(referer), referer)
+
+ modules := s.SingletonContext.ModuleVariantsFromName(referer.module, name)
+ result := make([]ModuleProxy, 0, len(modules))
+ for _, module := range modules {
+ // enforce visibility
+ depName := s.ModuleName(module)
+ depDir := s.ModuleDir(module)
+ depQualified := qualifiedModuleName{depDir, depName}
+ // Targets are always visible to other targets in their own package.
+ if depQualified.pkg != qualified.name.pkg {
+ rule := effectiveVisibilityRules(s.Config(), depQualified)
+ if !rule.matches(qualified) {
+ s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility",
+ referer.Name(), depQualified, "//"+s.ModuleDir(referer))
+ continue
}
- result = append(result, module)
}
+ result = append(result, ModuleProxy{module})
}
return result
}
@@ -315,3 +382,31 @@
func (s *singletonContextAdaptor) HasMutatorFinished(mutatorName string) bool {
return s.blueprintSingletonContext().HasMutatorFinished(mutatorName)
}
+func (s *singletonContextAdaptor) DistForGoal(goal string, paths ...Path) {
+ s.DistForGoals([]string{goal}, paths...)
+}
+
+func (s *singletonContextAdaptor) DistForGoalWithFilename(goal string, path Path, filename string) {
+ s.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (s *singletonContextAdaptor) DistForGoals(goals []string, paths ...Path) {
+ var copies distCopies
+ for _, path := range paths {
+ copies = append(copies, distCopy{
+ from: path,
+ dest: path.Base(),
+ })
+ }
+ s.dists = append(s.dists, dist{
+ goals: slices.Clone(goals),
+ paths: copies,
+ })
+}
+
+func (s *singletonContextAdaptor) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+ s.dists = append(s.dists, dist{
+ goals: slices.Clone(goals),
+ paths: distCopies{{from: path, dest: filename}},
+ })
+}
diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go
index 3b8c6b2..6f61a3b 100644
--- a/android/singleton_module_test.go
+++ b/android/singleton_module_test.go
@@ -61,7 +61,7 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- ops := result.ModuleForTests("test_singleton_module", "").Module().(*testSingletonModule).ops
+ ops := result.ModuleForTests(t, "test_singleton_module", "").Module().(*testSingletonModule).ops
wantOps := []string{"GenerateAndroidBuildActions", "GenerateSingletonBuildActions", "MakeVars"}
AssertDeepEquals(t, "operations", wantOps, ops)
}
@@ -88,7 +88,7 @@
prepareForSingletonModuleTest,
).RunTest(t)
- singleton := result.SingletonForTests("test_singleton_module").Singleton()
+ singleton := result.SingletonForTests(t, "test_singleton_module").Singleton()
sm := singleton.(*singletonModuleSingletonAdaptor).sm
ops := sm.(*testSingletonModule).ops
if ops != nil {
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index e0b1d7c..a61c9d3 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -506,6 +506,10 @@
conditionalProps := proptools.CloneEmptyProperties(conditionalFactoryProps)
props = append(props, conditionalProps.Interface())
+ if m, ok := module.(Module); ok {
+ m.base().baseProperties.Soong_config_base_module_type = &moduleType.BaseModuleType
+ }
+
// Regular Soong operation wraps the existing module factory with a
// conditional on Soong config variables by reading the product
// config variables from Make.
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 04aafde..f98e02b 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -321,10 +321,10 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- foo := result.ModuleForTests("foo", "").Module().(*soongConfigTestModule)
+ foo := result.ModuleForTests(t, "foo", "").Module().(*soongConfigTestModule)
AssertDeepEquals(t, "foo cflags", tc.fooExpectedFlags, foo.props.Cflags)
- fooDefaults := result.ModuleForTests("foo_with_defaults", "").Module().(*soongConfigTestModule)
+ fooDefaults := result.ModuleForTests(t, "foo_with_defaults", "").Module().(*soongConfigTestModule)
AssertDeepEquals(t, "foo_with_defaults cflags", tc.fooDefaultsExpectedFlags, fooDefaults.props.Cflags)
})
}
@@ -499,8 +499,8 @@
).RunTest(t)
// Make sure that the singleton was created.
- result.SingletonForTests("test_singleton")
- m := result.ModuleForTests("wiley", "").module.(*soongConfigTestSingletonModule)
+ result.SingletonForTests(t, "test_singleton")
+ m := result.ModuleForTests(t, "wiley", "").module.(*soongConfigTestSingletonModule)
AssertStringEquals(t, "fragments", test.expectedFragments, fmt.Sprintf("%+v", m.props.Fragments))
})
}
diff --git a/android/team.go b/android/team.go
index c273dc6..ad37f28 100644
--- a/android/team.go
+++ b/android/team.go
@@ -32,6 +32,12 @@
Trendy_team_id *string `json:"trendy_team_id"`
}
+type TeamInfo struct {
+ Properties teamProperties
+}
+
+var TeamInfoProvider = blueprint.NewProvider[TeamInfo]()
+
type teamModule struct {
ModuleBase
DefaultableModuleBase
@@ -48,7 +54,11 @@
// Real work is done for the module that depends on us.
// If needed, the team can serialize the config to json/proto file as well.
-func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
+func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ SetProvider(ctx, TeamInfoProvider, TeamInfo{
+ Properties: t.properties,
+ })
+}
func (t *teamModule) TrendyTeamId(ctx ModuleContext) string {
return *t.properties.Trendy_team_id
diff --git a/android/team_proto/OWNERS b/android/team_proto/OWNERS
index 2beb4f4..1eb820b 100644
--- a/android/team_proto/OWNERS
+++ b/android/team_proto/OWNERS
@@ -1,5 +1,4 @@
dariofreni@google.com
joeo@google.com
ronish@google.com
-caditya@google.com
rbraunstein@google.com
diff --git a/android/team_test.go b/android/team_test.go
index ccfcaaa..dcc1c99 100644
--- a/android/team_test.go
+++ b/android/team_test.go
@@ -61,9 +61,9 @@
`)
// Assert the rule from GenerateAndroidBuildActions exists.
- m := ctx.ModuleForTests("main_test", "")
+ m := ctx.ModuleForTests(t, "main_test", "")
AssertStringEquals(t, "msg", m.Module().base().Team(), "someteam")
- m = ctx.ModuleForTests("tool", "")
+ m = ctx.ModuleForTests(t, "tool", "")
AssertStringEquals(t, "msg", m.Module().base().Team(), "team2")
}
diff --git a/android/test_asserts.go b/android/test_asserts.go
index c33ade5..22472c5 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -33,6 +33,23 @@
}
}
+// AssertSame checks if the expected and actual values are equal and if they are not then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func AssertSameArray[T comparable](t *testing.T, message string, expected []T, actual []T) {
+ t.Helper()
+ if len(actual) != len(expected) {
+ t.Errorf("%s: expected %d (%v), actual (%d) %v", message, len(expected), expected, len(actual), actual)
+ return
+ }
+ for i := range actual {
+ if actual[i] != expected[i] {
+ t.Errorf("%s: expected %d-th, %v (%v), actual %v (%v)",
+ message, i, expected[i], expected, actual[i], actual)
+ return
+ }
+ }
+}
+
// AssertBoolEquals checks if the expected and actual values are equal and if they are not then it
// reports an error prefixed with the supplied message and including a reason for why it failed.
func AssertBoolEquals(t *testing.T, message string, expected bool, actual bool) {
diff --git a/android/test_config.go b/android/test_config.go
index 3609e6b..5d79df0 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -23,8 +23,7 @@
"github.com/google/blueprint/proptools"
)
-// TestConfig returns a Config object for testing.
-func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
+func initTestConfig(buildDir string, env map[string]string) *config {
envCopy := make(map[string]string)
for k, v := range env {
envCopy[k] = v
@@ -58,6 +57,7 @@
soongOutDir: filepath.Join(buildDir, "soong"),
captureBuild: true,
env: envCopy,
+ OncePer: &OncePer{},
// Set testAllowNonExistentPaths so that test contexts don't need to specify every path
// passed to PathForSource or PathForModuleSrc.
@@ -69,10 +69,21 @@
config: config,
}
config.TestProductVariables = &config.productVariables
+ config.deviceNameToInstall = config.TestProductVariables.DeviceName
+
+ determineBuildOS(config)
+
+ return config
+}
+
+// TestConfig returns a Config object for testing.
+func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
+ config := initTestConfig(buildDir, env)
config.mockFileSystem(bp, fs)
- determineBuildOS(config)
+ config.genericConfig = initTestConfig(buildDir, env)
+ overrideGenericConfig(config)
return Config{config}
}
diff --git a/android/test_mapping_zip.go b/android/test_mapping_zip.go
new file mode 100644
index 0000000..8dc70d7
--- /dev/null
+++ b/android/test_mapping_zip.go
@@ -0,0 +1,49 @@
+// Copyright 2025 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
+
+func init() {
+ InitRegistrationContext.RegisterSingletonType("test_mapping_zip_singleton", testMappingZipSingletonFactory)
+}
+
+func testMappingZipSingletonFactory() Singleton {
+ return &testMappingZipSingleton{}
+}
+
+type testMappingZipSingleton struct{}
+
+func (s *testMappingZipSingleton) GenerateBuildActions(ctx SingletonContext) {
+ fileListFile := PathForArbitraryOutput(ctx, ".module_paths", "TEST_MAPPING.list")
+ out := PathForOutput(ctx, "test_mappings.zip")
+ dep := PathForOutput(ctx, "test_mappings.zip.d")
+
+ // disabled-presubmit-tests used to be filled out based on modules that set
+ // LOCAL_PRESUBMIT_DISABLED. But that's no longer used and there was never a soong equivalent
+ // anyways, so just always create an empty file.
+ disabledPresubmitTestsFile := PathForOutput(ctx, "disabled-presubmit-tests")
+ WriteFileRule(ctx, disabledPresubmitTestsFile, "")
+
+ builder := NewRuleBuilder(pctx, ctx)
+ builder.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", out).
+ FlagWithInput("-l ", fileListFile).
+ FlagWithArg("-e ", "disabled-presubmit-tests").
+ FlagWithInput("-f ", disabledPresubmitTestsFile)
+ builder.Command().Textf("echo '%s : ' $(cat %s) > ", out, fileListFile).DepFile(dep)
+ builder.Build("test_mappings_zip", "build TEST_MAPPING zip")
+
+ ctx.Phony("test_mapping", out)
+ ctx.DistForGoals([]string{"dist_files", "test_mapping"}, out)
+}
diff --git a/android/test_suites.go b/android/test_suites.go
index 936d2b6..dbcd48c 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -17,6 +17,8 @@
import (
"path/filepath"
"strings"
+
+ "github.com/google/blueprint"
)
func init() {
@@ -27,51 +29,57 @@
return &testSuiteFiles{}
}
-type testSuiteFiles struct {
- robolectric []Path
- ravenwood []Path
-}
+type testSuiteFiles struct{}
type TestSuiteModule interface {
Module
TestSuites() []string
}
+type TestSuiteInfo struct {
+ TestSuites []string
+}
+
+var TestSuiteInfoProvider = blueprint.NewProvider[TestSuiteInfo]()
+
+type SupportFilesInfo struct {
+ SupportFiles InstallPaths
+}
+
+var SupportFilesInfoProvider = blueprint.NewProvider[SupportFilesInfo]()
+
func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) {
files := make(map[string]map[string]InstallPaths)
- ctx.VisitAllModules(func(m Module) {
- if tsm, ok := m.(TestSuiteModule); ok {
- for _, testSuite := range tsm.TestSuites() {
+ ctx.VisitAllModuleProxies(func(m ModuleProxy) {
+ if tsm, ok := OtherModuleProvider(ctx, m, TestSuiteInfoProvider); ok {
+ for _, testSuite := range tsm.TestSuites {
if files[testSuite] == nil {
files[testSuite] = make(map[string]InstallPaths)
}
name := ctx.ModuleName(m)
files[testSuite][name] = append(files[testSuite][name],
- OtherModuleProviderOrDefault(ctx, tsm, InstallFilesProvider).InstallFiles...)
+ OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider).InstallFiles...)
}
}
})
- t.robolectric = robolectricTestSuite(ctx, files["robolectric-tests"])
- ctx.Phony("robolectric-tests", t.robolectric...)
+ robolectricZip, robolectrictListZip := buildTestSuite(ctx, "robolectric-tests", files["robolectric-tests"])
+ ctx.Phony("robolectric-tests", robolectricZip, robolectrictListZip)
+ ctx.DistForGoal("robolectric-tests", robolectricZip, robolectrictListZip)
- t.ravenwood = ravenwoodTestSuite(ctx, files["ravenwood-tests"])
- ctx.Phony("ravenwood-tests", t.ravenwood...)
+ ravenwoodZip, ravenwoodListZip := buildTestSuite(ctx, "ravenwood-tests", files["ravenwood-tests"])
+ ctx.Phony("ravenwood-tests", ravenwoodZip, ravenwoodListZip)
+ ctx.DistForGoal("ravenwood-tests", ravenwoodZip, ravenwoodListZip)
}
-func (t *testSuiteFiles) MakeVars(ctx MakeVarsContext) {
- ctx.DistForGoal("robolectric-tests", t.robolectric...)
- ctx.DistForGoal("ravenwood-tests", t.ravenwood...)
-}
-
-func robolectricTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path {
+func buildTestSuite(ctx SingletonContext, suiteName string, files map[string]InstallPaths) (Path, Path) {
var installedPaths InstallPaths
for _, module := range SortedKeys(files) {
installedPaths = append(installedPaths, files[module]...)
}
- outputFile := pathForPackaging(ctx, "robolectric-tests.zip")
+ outputFile := pathForPackaging(ctx, suiteName+".zip")
rule := NewRuleBuilder(pctx, ctx)
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", outputFile).
@@ -80,8 +88,8 @@
FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
Flag("-sha256") // necessary to save cas_uploader's time
- testList := buildTestList(ctx, "robolectric-tests_list", installedPaths)
- testListZipOutputFile := pathForPackaging(ctx, "robolectric-tests_list.zip")
+ testList := buildTestList(ctx, suiteName+"_list", installedPaths)
+ testListZipOutputFile := pathForPackaging(ctx, suiteName+"_list.zip")
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", testListZipOutputFile).
@@ -89,38 +97,9 @@
FlagWithInput("-f ", testList).
Flag("-sha256")
- rule.Build("robolectric_tests_zip", "robolectric-tests.zip")
+ rule.Build(strings.ReplaceAll(suiteName, "-", "_")+"_zip", suiteName+".zip")
- return []Path{outputFile, testListZipOutputFile}
-}
-
-func ravenwoodTestSuite(ctx SingletonContext, files map[string]InstallPaths) []Path {
- var installedPaths InstallPaths
- for _, module := range SortedKeys(files) {
- installedPaths = append(installedPaths, files[module]...)
- }
-
- outputFile := pathForPackaging(ctx, "ravenwood-tests.zip")
- rule := NewRuleBuilder(pctx, ctx)
- rule.Command().BuiltTool("soong_zip").
- FlagWithOutput("-o ", outputFile).
- FlagWithArg("-P ", "host/testcases").
- FlagWithArg("-C ", pathForTestCases(ctx).String()).
- FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
- Flag("-sha256") // necessary to save cas_uploader's time
-
- testList := buildTestList(ctx, "ravenwood-tests_list", installedPaths)
- testListZipOutputFile := pathForPackaging(ctx, "ravenwood-tests_list.zip")
-
- rule.Command().BuiltTool("soong_zip").
- FlagWithOutput("-o ", testListZipOutputFile).
- FlagWithArg("-C ", pathForPackaging(ctx).String()).
- FlagWithInput("-f ", testList).
- Flag("-sha256")
-
- rule.Build("ravenwood_tests_zip", "ravenwood-tests.zip")
-
- return []Path{outputFile, testListZipOutputFile}
+ return outputFile, testListZipOutputFile
}
func buildTestList(ctx SingletonContext, listFile string, installedPaths InstallPaths) Path {
diff --git a/android/test_suites_test.go b/android/test_suites_test.go
index db9a34d..03aa424 100644
--- a/android/test_suites_test.go
+++ b/android/test_suites_test.go
@@ -52,7 +52,7 @@
}
`)
- config := ctx.SingletonForTests("testsuites")
+ config := ctx.SingletonForTests(t, "testsuites")
allOutputs := config.AllOutputs()
wantContents := map[string]string{
@@ -108,8 +108,13 @@
func (f *fake_module) GenerateAndroidBuildActions(ctx ModuleContext) {
for _, output := range f.props.Outputs {
- ctx.InstallFile(pathForTestCases(ctx), output, nil)
+ f := PathForModuleOut(ctx, output)
+ ctx.InstallFile(pathForTestCases(ctx), output, f)
}
+
+ SetProvider(ctx, TestSuiteInfoProvider, TestSuiteInfo{
+ TestSuites: f.TestSuites(),
+ })
}
func (f *fake_module) TestSuites() []string {
diff --git a/android/testing.go b/android/testing.go
index 765839f..d2949ec 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -530,7 +530,8 @@
// both have the same value. Both the module and the map are allowed to have
// extra variations that the other doesn't have. Panics if not exactly one
// module variant matches.
-func (ctx *TestContext) ModuleVariantForTests(name string, matchVariations map[string]string) TestingModule {
+func (ctx *TestContext) ModuleVariantForTests(t *testing.T, name string, matchVariations map[string]string) TestingModule {
+ t.Helper()
modules := []Module{}
ctx.VisitAllModules(func(m blueprint.Module) {
if ctx.ModuleName(m) == name {
@@ -562,12 +563,12 @@
})
if len(allVariants) == 0 {
- panic(fmt.Errorf("failed to find module %q. All modules:\n %s",
- name, strings.Join(SortedUniqueStrings(allModuleNames), "\n ")))
+ t.Fatalf("failed to find module %q. All modules:\n %s",
+ name, strings.Join(SortedUniqueStrings(allModuleNames), "\n "))
} else {
sort.Strings(allVariants)
- panic(fmt.Errorf("failed to find module %q matching %v. All variants:\n %s",
- name, matchVariations, strings.Join(allVariants, "\n ")))
+ t.Fatalf("failed to find module %q matching %v. All variants:\n %s",
+ name, matchVariations, strings.Join(allVariants, "\n "))
}
}
@@ -577,14 +578,15 @@
moduleStrings = append(moduleStrings, m.String())
}
sort.Strings(moduleStrings)
- panic(fmt.Errorf("module %q has more than one variant that match %v:\n %s",
- name, matchVariations, strings.Join(moduleStrings, "\n ")))
+ t.Fatalf("module %q has more than one variant that match %v:\n %s",
+ name, matchVariations, strings.Join(moduleStrings, "\n "))
}
- return newTestingModule(ctx.config, modules[0])
+ return newTestingModule(t, ctx.config, modules[0])
}
-func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
+func (ctx *TestContext) ModuleForTests(t *testing.T, name, variant string) TestingModule {
+ t.Helper()
var module Module
ctx.VisitAllModules(func(m blueprint.Module) {
if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant {
@@ -605,15 +607,15 @@
sort.Strings(allVariants)
if len(allVariants) == 0 {
- panic(fmt.Errorf("failed to find module %q. All modules:\n %s",
- name, strings.Join(SortedUniqueStrings(allModuleNames), "\n ")))
+ t.Fatalf("failed to find module %q. All modules:\n %s",
+ name, strings.Join(SortedUniqueStrings(allModuleNames), "\n "))
} else {
- panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n %s",
- name, variant, strings.Join(allVariants, "\n ")))
+ t.Fatalf("failed to find module %q variant %q. All variants:\n %s",
+ name, variant, strings.Join(allVariants, "\n "))
}
}
- return newTestingModule(ctx.config, module)
+ return newTestingModule(t, ctx.config, module)
}
func (ctx *TestContext) ModuleVariantsForTests(name string) []string {
@@ -627,21 +629,24 @@
}
// SingletonForTests returns a TestingSingleton for the singleton registered with the given name.
-func (ctx *TestContext) SingletonForTests(name string) TestingSingleton {
+func (ctx *TestContext) SingletonForTests(t *testing.T, name string) TestingSingleton {
+ t.Helper()
allSingletonNames := []string{}
for _, s := range ctx.Singletons() {
n := ctx.SingletonName(s)
if n == name {
return TestingSingleton{
- baseTestingComponent: newBaseTestingComponent(ctx.config, s.(testBuildProvider)),
+ baseTestingComponent: newBaseTestingComponent(t, ctx.config, s.(testBuildProvider)),
singleton: s.(*singletonAdaptor).Singleton,
}
}
allSingletonNames = append(allSingletonNames, n)
}
- panic(fmt.Errorf("failed to find singleton %q."+
- "\nall singletons: %v", name, allSingletonNames))
+ t.Fatalf("failed to find singleton %q."+
+ "\nall singletons: %v", name, allSingletonNames)
+
+ return TestingSingleton{}
}
type InstallMakeRule struct {
@@ -651,6 +656,7 @@
}
func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []InstallMakeRule {
+ t.Helper()
var rules []InstallMakeRule
for _, node := range nodes {
if mkParserRule, ok := node.(*mkparser.Rule); ok {
@@ -688,7 +694,8 @@
}
func (ctx *TestContext) InstallMakeRulesForTesting(t *testing.T) []InstallMakeRule {
- installs := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting
+ t.Helper()
+ installs := ctx.SingletonForTests(t, "makevars").Singleton().(*makeVarsSingleton).installsForTesting
buf := bytes.NewBuffer(append([]byte(nil), installs...))
parser := mkparser.NewParser("makevars", buf)
@@ -728,8 +735,9 @@
//
// It is necessary to use PrepareForTestAccessingMakeVars in tests that want to call this function.
// Along with any other preparers needed to add the make vars.
-func (ctx *TestContext) MakeVarsForTesting(filter func(variable MakeVarVariable) bool) []MakeVarVariable {
- vars := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).varsForTesting
+func (ctx *TestContext) MakeVarsForTesting(t *testing.T, filter func(variable MakeVarVariable) bool) []MakeVarVariable {
+ t.Helper()
+ vars := ctx.SingletonForTests(t, "makevars").Singleton().(*makeVarsSingleton).varsForTesting
result := make([]MakeVarVariable, 0, len(vars))
for _, v := range vars {
if filter(v) {
@@ -846,12 +854,13 @@
// baseTestingComponent provides functionality common to both TestingModule and TestingSingleton.
type baseTestingComponent struct {
+ t *testing.T
config Config
provider testBuildProvider
}
-func newBaseTestingComponent(config Config, provider testBuildProvider) baseTestingComponent {
- return baseTestingComponent{config, provider}
+func newBaseTestingComponent(t *testing.T, config Config, provider testBuildProvider) baseTestingComponent {
+ return baseTestingComponent{t, config, provider}
}
// A function that will normalize a string containing paths, e.g. ninja command, by replacing
@@ -922,9 +931,10 @@
}
func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
+ b.t.Helper()
p, searchRules := b.maybeBuildParamsFromRule(rule)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n")))
+ b.t.Fatalf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n"))
}
return p
}
@@ -941,9 +951,10 @@
}
func (b baseTestingComponent) buildParamsFromDescription(desc string) TestingBuildParams {
+ b.t.Helper()
p, searchedDescriptions := b.maybeBuildParamsFromDescription(desc)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find description %q\nall descriptions:\n%s", desc, strings.Join(searchedDescriptions, "\n")))
+ b.t.Fatalf("couldn't find description %q\nall descriptions:\n%s", desc, strings.Join(searchedDescriptions, "\n"))
}
return p
}
@@ -974,10 +985,11 @@
}
func (b baseTestingComponent) buildParamsFromOutput(file string) TestingBuildParams {
+ b.t.Helper()
p, searchedOutputs := b.maybeBuildParamsFromOutput(file)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find output %q.\nall outputs:\n %s\n",
- file, strings.Join(searchedOutputs, "\n ")))
+ b.t.Fatalf("couldn't find output %q.\nall outputs:\n %s\n",
+ file, strings.Join(searchedOutputs, "\n "))
}
return p
}
@@ -999,6 +1011,7 @@
// Rule finds a call to ctx.Build with BuildParams.Rule set to a rule with the given name. Panics if no rule is found.
func (b baseTestingComponent) Rule(rule string) TestingBuildParams {
+ b.t.Helper()
return b.buildParamsFromRule(rule)
}
@@ -1012,6 +1025,7 @@
// Description finds a call to ctx.Build with BuildParams.Description set to a the given string. Panics if no rule is
// found.
func (b baseTestingComponent) Description(desc string) TestingBuildParams {
+ b.t.Helper()
return b.buildParamsFromDescription(desc)
}
@@ -1025,6 +1039,7 @@
// Output finds a call to ctx.Build with a BuildParams.Output or BuildParams.Outputs whose String() or Rel()
// value matches the provided string. Panics if no rule is found.
func (b baseTestingComponent) Output(file string) TestingBuildParams {
+ b.t.Helper()
return b.buildParamsFromOutput(file)
}
@@ -1040,9 +1055,9 @@
module Module
}
-func newTestingModule(config Config, module Module) TestingModule {
+func newTestingModule(t *testing.T, config Config, module Module) TestingModule {
return TestingModule{
- newBaseTestingComponent(config, module),
+ newBaseTestingComponent(t, config, module),
module,
}
}
@@ -1152,24 +1167,24 @@
config.katiEnabled = true
}
-func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
+func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod Module) []AndroidMkEntries {
t.Helper()
var p AndroidMkEntriesProvider
var ok bool
if p, ok = mod.(AndroidMkEntriesProvider); !ok {
- t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name())
+ t.Error("module does not implement AndroidMkEntriesProvider: " + mod.Name())
}
entriesList := p.AndroidMkEntries()
- aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
+ aconfigUpdateAndroidMkEntries(ctx, mod, &entriesList)
for i := range entriesList {
entriesList[i].fillInEntries(ctx, mod)
}
return entriesList
}
-func AndroidMkInfoForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) *AndroidMkProviderInfo {
- if runtime.GOOS == "darwin" && mod.(Module).base().Os() != Darwin {
+func AndroidMkInfoForTest(t *testing.T, ctx *TestContext, mod Module) *AndroidMkProviderInfo {
+ if runtime.GOOS == "darwin" && mod.base().Os() != Darwin {
// The AndroidMkInfo provider is not set in this case.
t.Skip("AndroidMkInfo provider is not set on darwin")
}
@@ -1177,31 +1192,32 @@
t.Helper()
var ok bool
if _, ok = mod.(AndroidMkProviderInfoProducer); !ok {
- t.Errorf("module does not implement AndroidMkProviderInfoProducer: " + mod.Name())
+ t.Error("module does not implement AndroidMkProviderInfoProducer: " + mod.Name())
}
info := OtherModuleProviderOrDefault(ctx, mod, AndroidMkInfoProvider)
- aconfigUpdateAndroidMkInfos(ctx, mod.(Module), info)
- info.PrimaryInfo.fillInEntries(ctx, mod)
+ aconfigUpdateAndroidMkInfos(ctx, mod, info)
+ commonInfo := OtherModulePointerProviderOrDefault(ctx, mod, CommonModuleInfoProvider)
+ info.PrimaryInfo.fillInEntries(ctx, mod, commonInfo)
if len(info.ExtraInfo) > 0 {
for _, ei := range info.ExtraInfo {
- ei.fillInEntries(ctx, mod)
+ ei.fillInEntries(ctx, mod, commonInfo)
}
}
return info
}
-func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
+func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod Module) AndroidMkData {
t.Helper()
var p AndroidMkDataProvider
var ok bool
if p, ok = mod.(AndroidMkDataProvider); !ok {
- t.Fatalf("module does not implement AndroidMkDataProvider: " + mod.Name())
+ t.Fatal("module does not implement AndroidMkDataProvider: " + mod.Name())
}
data := p.AndroidMk()
data.fillInData(ctx, mod)
- aconfigUpdateAndroidMkData(ctx, mod.(Module), &data)
+ aconfigUpdateAndroidMkData(ctx, mod, &data)
return data
}
diff --git a/android/transition.go b/android/transition.go
new file mode 100644
index 0000000..0677ca1
--- /dev/null
+++ b/android/transition.go
@@ -0,0 +1,410 @@
+// 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 "github.com/google/blueprint"
+
+// TransitionMutator implements a top-down mechanism where a module tells its
+// direct dependencies what variation they should be built in but the dependency
+// has the final say.
+//
+// When implementing a transition mutator, one needs to implement four methods:
+// - Split() that tells what variations a module has by itself
+// - OutgoingTransition() where a module tells what it wants from its
+// dependency
+// - IncomingTransition() where a module has the final say about its own
+// variation
+// - Mutate() that changes the state of a module depending on its variation
+//
+// That the effective variation of module B when depended on by module A is the
+// composition the outgoing transition of module A and the incoming transition
+// of module B.
+//
+// the outgoing transition should not take the properties of the dependency into
+// account, only those of the module that depends on it. For this reason, the
+// dependency is not even passed into it as an argument. Likewise, the incoming
+// transition should not take the properties of the depending module into
+// account and is thus not informed about it. This makes for a nice
+// decomposition of the decision logic.
+//
+// A given transition mutator only affects its own variation; other variations
+// stay unchanged along the dependency edges.
+//
+// Soong makes sure that all modules are created in the desired variations and
+// that dependency edges are set up correctly. This ensures that "missing
+// variation" errors do not happen and allows for more flexible changes in the
+// value of the variation among dependency edges (as oppposed to bottom-up
+// mutators where if module A in variation X depends on module B and module B
+// has that variation X, A must depend on variation X of B)
+//
+// The limited power of the context objects passed to individual mutators
+// methods also makes it more difficult to shoot oneself in the foot. Complete
+// safety is not guaranteed because no one prevents individual transition
+// mutators from mutating modules in illegal ways and for e.g. Split() or
+// Mutate() to run their own visitations of the transitive dependency of the
+// module and both of these are bad ideas, but it's better than no guardrails at
+// all.
+//
+// This model is pretty close to Bazel's configuration transitions. The mapping
+// between concepts in Soong and Bazel is as follows:
+// - Module == configured target
+// - Variant == configuration
+// - Variation name == configuration flag
+// - Variation == configuration flag value
+// - Outgoing transition == attribute transition
+// - Incoming transition == rule transition
+//
+// The Split() method does not have a Bazel equivalent and Bazel split
+// transitions do not have a Soong equivalent.
+//
+// Mutate() does not make sense in Bazel due to the different models of the
+// two systems: when creating new variations, Soong clones the old module and
+// thus some way is needed to change it state whereas Bazel creates each
+// configuration of a given configured target anew.
+type TransitionMutator[T blueprint.TransitionInfo] interface {
+ // Split returns the set of variations that should be created for a module no
+ // matter who depends on it. Used when Make depends on a particular variation
+ // or when the module knows its variations just based on information given to
+ // it in the Blueprint file. This method should not mutate the module it is
+ // called on.
+ Split(ctx BaseModuleContext) []T
+
+ // OutgoingTransition is called on a module to determine which variation it wants
+ // from its direct dependencies. The dependency itself can override this decision.
+ // This method should not mutate the module itself.
+ OutgoingTransition(ctx OutgoingTransitionContext, sourceTransitionInfo T) T
+
+ // IncomingTransition is called on a module to determine which variation it should
+ // be in based on the variation modules that depend on it want. This gives the module
+ // a final say about its own variations. This method should not mutate the module
+ // itself.
+ IncomingTransition(ctx IncomingTransitionContext, incomingTransitionInfo T) T
+
+ // Mutate is called after a module was split into multiple variations on each variation.
+ // It should not split the module any further but adding new dependencies is
+ // fine. Unlike all the other methods on TransitionMutator, this method is
+ // allowed to mutate the module.
+ Mutate(ctx BottomUpMutatorContext, transitionInfo T)
+
+ // TransitionInfoFromVariation is called when adding dependencies with an explicit variation after the
+ // TransitionMutator has already run. It takes a variation name and returns a TransitionInfo for that
+ // variation. It may not be possible for some TransitionMutators to generate an appropriate TransitionInfo
+ // if the variation does not contain all the information from the TransitionInfo, in which case the
+ // TransitionMutator can panic in TransitionInfoFromVariation, and adding dependencies with explicit variations
+ // for this TransitionMutator is not supported.
+ TransitionInfoFromVariation(variation string) T
+}
+
+// androidTransitionMutator is a copy of blueprint.TransitionMutator with the context argument types changed
+// from blueprint.BaseModuleContext to BaseModuleContext, etc.
+type androidTransitionMutator interface {
+ Split(ctx BaseModuleContext) []blueprint.TransitionInfo
+ OutgoingTransition(ctx OutgoingTransitionContext, sourceTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo
+ IncomingTransition(ctx IncomingTransitionContext, incomingTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo
+ Mutate(ctx BottomUpMutatorContext, transitionInfo blueprint.TransitionInfo)
+ TransitionInfoFromVariation(variation string) blueprint.TransitionInfo
+}
+
+// VariationTransitionMutator is a simpler version of androidTransitionMutator that passes variation strings instead
+// of a blueprint.TransitionInfo object.
+type VariationTransitionMutator interface {
+ Split(ctx BaseModuleContext) []string
+ OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string
+ IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string
+ Mutate(ctx BottomUpMutatorContext, variation string)
+}
+
+type IncomingTransitionContext interface {
+ ArchModuleContext
+ ModuleProviderContext
+ ModuleErrorContext
+
+ // Module returns the target of the dependency edge for which the transition
+ // is being computed
+ Module() Module
+
+ // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when
+ // the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename.
+ ModuleName() string
+
+ // DepTag() Returns the dependency tag through which this dependency is
+ // reached
+ DepTag() blueprint.DependencyTag
+
+ // Config returns the configuration for the build.
+ Config() Config
+
+ DeviceConfig() DeviceConfig
+
+ // IsAddingDependency returns true if the transition is being called while adding a dependency
+ // after the transition mutator has already run, or false if it is being called when the transition
+ // mutator is running. This should be used sparingly, all uses will have to be removed in order
+ // to support creating variants on demand.
+ IsAddingDependency() bool
+}
+
+type OutgoingTransitionContext interface {
+ ArchModuleContext
+ ModuleProviderContext
+
+ // Module returns the target of the dependency edge for which the transition
+ // is being computed
+ Module() Module
+
+ // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when
+ // the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename.
+ ModuleName() string
+
+ // DepTag() Returns the dependency tag through which this dependency is
+ // reached
+ DepTag() blueprint.DependencyTag
+
+ // Config returns the configuration for the build.
+ Config() Config
+
+ DeviceConfig() DeviceConfig
+}
+
+// androidTransitionMutatorAdapter wraps an androidTransitionMutator to convert it to a blueprint.TransitionInfo
+// by converting the blueprint.*Context objects into android.*Context objects.
+type androidTransitionMutatorAdapter struct {
+ finalPhase bool
+ mutator androidTransitionMutator
+ name string
+}
+
+func (a *androidTransitionMutatorAdapter) Split(ctx blueprint.BaseModuleContext) []blueprint.TransitionInfo {
+ if a.finalPhase {
+ panic("TransitionMutator not allowed in FinalDepsMutators")
+ }
+ m := ctx.Module().(Module)
+ moduleContext := m.base().baseModuleContextFactory(ctx)
+ return a.mutator.Split(&moduleContext)
+}
+
+func (a *androidTransitionMutatorAdapter) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext,
+ sourceTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo {
+ m := bpctx.Module().(Module)
+ ctx := outgoingTransitionContextPool.Get()
+ defer outgoingTransitionContextPool.Put(ctx)
+ *ctx = outgoingTransitionContextImpl{
+ archModuleContext: m.base().archModuleContextFactory(bpctx),
+ bp: bpctx,
+ }
+ return a.mutator.OutgoingTransition(ctx, sourceTransitionInfo)
+}
+
+func (a *androidTransitionMutatorAdapter) IncomingTransition(bpctx blueprint.IncomingTransitionContext,
+ incomingTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo {
+ m := bpctx.Module().(Module)
+ ctx := incomingTransitionContextPool.Get()
+ defer incomingTransitionContextPool.Put(ctx)
+ *ctx = incomingTransitionContextImpl{
+ archModuleContext: m.base().archModuleContextFactory(bpctx),
+ bp: bpctx,
+ }
+ return a.mutator.IncomingTransition(ctx, incomingTransitionInfo)
+}
+
+func (a *androidTransitionMutatorAdapter) Mutate(ctx blueprint.BottomUpMutatorContext, transitionInfo blueprint.TransitionInfo) {
+ am := ctx.Module().(Module)
+ variation := transitionInfo.Variation()
+ if variation != "" {
+ // TODO: this should really be checking whether the TransitionMutator affected this module, not
+ // the empty variant, but TransitionMutator has no concept of skipping a module.
+ base := am.base()
+ base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
+ base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
+ }
+
+ mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
+ defer bottomUpMutatorContextPool.Put(mctx)
+ a.mutator.Mutate(mctx, transitionInfo)
+}
+
+func (a *androidTransitionMutatorAdapter) TransitionInfoFromVariation(variation string) blueprint.TransitionInfo {
+ return a.mutator.TransitionInfoFromVariation(variation)
+}
+
+// variationTransitionMutatorAdapter wraps a VariationTransitionMutator to convert it to an androidTransitionMutator
+// by wrapping the string info object used by VariationTransitionMutator with variationTransitionInfo to convert it into
+// blueprint.TransitionInfo.
+type variationTransitionMutatorAdapter struct {
+ m VariationTransitionMutator
+}
+
+func (v variationTransitionMutatorAdapter) Split(ctx BaseModuleContext) []blueprint.TransitionInfo {
+ variations := v.m.Split(ctx)
+ transitionInfos := make([]blueprint.TransitionInfo, 0, len(variations))
+ for _, variation := range variations {
+ transitionInfos = append(transitionInfos, variationTransitionInfo{variation})
+ }
+ return transitionInfos
+}
+
+func (v variationTransitionMutatorAdapter) OutgoingTransition(ctx OutgoingTransitionContext,
+ sourceTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo {
+
+ sourceVariationTransitionInfo, _ := sourceTransitionInfo.(variationTransitionInfo)
+ outgoingVariation := v.m.OutgoingTransition(ctx, sourceVariationTransitionInfo.variation)
+ return variationTransitionInfo{outgoingVariation}
+}
+
+func (v variationTransitionMutatorAdapter) IncomingTransition(ctx IncomingTransitionContext,
+ incomingTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo {
+
+ incomingVariationTransitionInfo, _ := incomingTransitionInfo.(variationTransitionInfo)
+ variation := v.m.IncomingTransition(ctx, incomingVariationTransitionInfo.variation)
+ return variationTransitionInfo{variation}
+}
+
+func (v variationTransitionMutatorAdapter) Mutate(ctx BottomUpMutatorContext, transitionInfo blueprint.TransitionInfo) {
+ variationTransitionInfo, _ := transitionInfo.(variationTransitionInfo)
+ v.m.Mutate(ctx, variationTransitionInfo.variation)
+}
+
+func (v variationTransitionMutatorAdapter) TransitionInfoFromVariation(variation string) blueprint.TransitionInfo {
+ return variationTransitionInfo{variation}
+}
+
+// variationTransitionInfo is a blueprint.TransitionInfo that contains a single variation string.
+type variationTransitionInfo struct {
+ variation string
+}
+
+func (v variationTransitionInfo) Variation() string {
+ return v.variation
+}
+
+// genericTransitionMutatorAdapter wraps a TransitionMutator to convert it to an androidTransitionMutator
+type genericTransitionMutatorAdapter[T blueprint.TransitionInfo] struct {
+ m TransitionMutator[T]
+}
+
+// NewGenericTransitionMutatorAdapter is used to convert a generic TransitionMutator[T] into an androidTransitionMutator
+// that can be passed to RegisterMutatorsContext.InfoBasedTransition.
+func NewGenericTransitionMutatorAdapter[T blueprint.TransitionInfo](m TransitionMutator[T]) androidTransitionMutator {
+ return &genericTransitionMutatorAdapter[T]{m}
+}
+
+func (g *genericTransitionMutatorAdapter[T]) convertTransitionInfoToT(transitionInfo blueprint.TransitionInfo) T {
+ if transitionInfo == nil {
+ var zero T
+ return zero
+ }
+ return transitionInfo.(T)
+}
+
+func (g *genericTransitionMutatorAdapter[T]) Split(ctx BaseModuleContext) []blueprint.TransitionInfo {
+ transitionInfos := g.m.Split(ctx)
+ bpTransitionInfos := make([]blueprint.TransitionInfo, 0, len(transitionInfos))
+ for _, transitionInfo := range transitionInfos {
+ bpTransitionInfos = append(bpTransitionInfos, transitionInfo)
+ }
+ return bpTransitionInfos
+}
+
+func (g *genericTransitionMutatorAdapter[T]) OutgoingTransition(ctx OutgoingTransitionContext, sourceTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo {
+ sourceTransitionInfoT := g.convertTransitionInfoToT(sourceTransitionInfo)
+ return g.m.OutgoingTransition(ctx, sourceTransitionInfoT)
+}
+
+func (g *genericTransitionMutatorAdapter[T]) IncomingTransition(ctx IncomingTransitionContext, incomingTransitionInfo blueprint.TransitionInfo) blueprint.TransitionInfo {
+ incomingTransitionInfoT := g.convertTransitionInfoToT(incomingTransitionInfo)
+ return g.m.IncomingTransition(ctx, incomingTransitionInfoT)
+}
+
+func (g *genericTransitionMutatorAdapter[T]) Mutate(ctx BottomUpMutatorContext, transitionInfo blueprint.TransitionInfo) {
+ transitionInfoT := g.convertTransitionInfoToT(transitionInfo)
+ g.m.Mutate(ctx, transitionInfoT)
+}
+
+func (g *genericTransitionMutatorAdapter[T]) TransitionInfoFromVariation(variation string) blueprint.TransitionInfo {
+ return g.m.TransitionInfoFromVariation(variation)
+}
+
+// incomingTransitionContextImpl wraps a blueprint.IncomingTransitionContext to convert it to an
+// IncomingTransitionContext.
+type incomingTransitionContextImpl struct {
+ archModuleContext
+ bp blueprint.IncomingTransitionContext
+}
+
+func (c *incomingTransitionContextImpl) Module() Module {
+ return c.bp.Module().(Module)
+}
+
+func (c *incomingTransitionContextImpl) ModuleName() string {
+ return c.bp.ModuleName()
+}
+
+func (c *incomingTransitionContextImpl) DepTag() blueprint.DependencyTag {
+ return c.bp.DepTag()
+}
+
+func (c *incomingTransitionContextImpl) Config() Config {
+ return c.bp.Config().(Config)
+}
+
+func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig {
+ return DeviceConfig{c.bp.Config().(Config).deviceConfig}
+}
+
+func (c *incomingTransitionContextImpl) IsAddingDependency() bool {
+ return c.bp.IsAddingDependency()
+}
+
+func (c *incomingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
+ return c.bp.Provider(provider)
+}
+
+func (c *incomingTransitionContextImpl) ModuleErrorf(fmt string, args ...interface{}) {
+ c.bp.ModuleErrorf(fmt, args)
+}
+
+func (c *incomingTransitionContextImpl) PropertyErrorf(property, fmt string, args ...interface{}) {
+ c.bp.PropertyErrorf(property, fmt, args)
+}
+
+// outgoingTransitionContextImpl wraps a blueprint.OutgoingTransitionContext to convert it to an
+// OutgoingTransitionContext.
+type outgoingTransitionContextImpl struct {
+ archModuleContext
+ bp blueprint.OutgoingTransitionContext
+}
+
+func (c *outgoingTransitionContextImpl) Module() Module {
+ return c.bp.Module().(Module)
+}
+
+func (c *outgoingTransitionContextImpl) ModuleName() string {
+ return c.bp.ModuleName()
+}
+
+func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag {
+ return c.bp.DepTag()
+}
+
+func (c *outgoingTransitionContextImpl) Config() Config {
+ return c.bp.Config().(Config)
+}
+
+func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig {
+ return DeviceConfig{c.bp.Config().(Config).deviceConfig}
+}
+
+func (c *outgoingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
+ return c.bp.Provider(provider)
+}
diff --git a/android/transition_test.go b/android/transition_test.go
new file mode 100644
index 0000000..f7618f3
--- /dev/null
+++ b/android/transition_test.go
@@ -0,0 +1,162 @@
+// 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 "testing"
+
+type testTransitionMutator struct {
+ split func(ctx BaseModuleContext) []string
+ outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string
+ incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string
+ mutate func(ctx BottomUpMutatorContext, variation string)
+}
+
+func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string {
+ if t.split != nil {
+ return t.split(ctx)
+ }
+ return []string{""}
+}
+
+func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ if t.outgoingTransition != nil {
+ return t.outgoingTransition(ctx, sourceVariation)
+ }
+ return sourceVariation
+}
+
+func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ if t.incomingTransition != nil {
+ return t.incomingTransition(ctx, incomingVariation)
+ }
+ return incomingVariation
+}
+
+func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ if t.mutate != nil {
+ t.mutate(ctx, variation)
+ }
+}
+
+func TestModuleString(t *testing.T) {
+ bp := `
+ test {
+ name: "foo",
+ }
+ `
+
+ var moduleStrings []string
+
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+
+ ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("pre_arch", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"a", "b"}
+ },
+ })
+ })
+
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("pre_deps", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"c", "d"}
+ },
+ })
+ })
+
+ ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("post_deps", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"e", "f"}
+ },
+ outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return ""
+ },
+ })
+ ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+ }).UsesRename()
+ ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ })
+ })
+
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ want := []string{
+ // Initial name.
+ "foo{}",
+
+ // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
+ "foo{pre_arch:b}",
+ "foo{pre_arch:a}",
+
+ // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
+ "foo{pre_arch:b,pre_deps:d}",
+ "foo{pre_arch:b,pre_deps:c}",
+ "foo{pre_arch:a,pre_deps:d}",
+ "foo{pre_arch:a,pre_deps:c}",
+
+ // After post_deps.
+ "foo{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:f}",
+
+ // After rename_bottom_up.
+ "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
+ }
+
+ AssertDeepEquals(t, "module String() values", want, moduleStrings)
+}
+
+func TestTransitionMutatorInFinalDeps(t *testing.T) {
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("vars", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
+ })
+ })
+
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(`test {name: "foo"}`),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
+ RunTest(t)
+}
diff --git a/android/util.go b/android/util.go
index 3fc4608..4520f40 100644
--- a/android/util.go
+++ b/android/util.go
@@ -23,7 +23,6 @@
"runtime"
"sort"
"strings"
- "sync"
"github.com/google/blueprint/proptools"
)
@@ -102,13 +101,6 @@
return buf.String()
}
-// SortedStringKeys returns the keys of the given map in the ascending order.
-//
-// Deprecated: Use SortedKeys instead.
-func SortedStringKeys[V any](m map[string]V) []string {
- return SortedKeys(m)
-}
-
// SortedKeys returns the keys of the given map in the ascending order.
func SortedKeys[T cmp.Ordered, V any](m map[T]V) []T {
if len(m) == 0 {
@@ -213,21 +205,23 @@
}
// ListSetDifference checks if the two lists contain the same elements. It returns
-// a boolean which is true if there is a difference, and then returns lists of elements
+// a boolean which is true if there is a difference, and then returns lists of unique elements
// that are in l1 but not l2, and l2 but not l1.
func ListSetDifference[T comparable](l1, l2 []T) (bool, []T, []T) {
listsDiffer := false
+ l1 = firstUnique(l1)
+ l2 = firstUnique(l2)
diff1 := []T{}
diff2 := []T{}
m1 := setFromList(l1)
m2 := setFromList(l2)
- for t := range m1 {
+ for _, t := range l1 {
if _, ok := m2[t]; !ok {
diff1 = append(diff1, t)
listsDiffer = true
}
}
- for t := range m2 {
+ for _, t := range l2 {
if _, ok := m1[t]; !ok {
diff2 = append(diff2, t)
listsDiffer = true
@@ -238,8 +232,13 @@
// Returns true if the two lists have common elements.
func HasIntersection[T comparable](l1, l2 []T) bool {
- _, a, b := ListSetDifference(l1, l2)
- return len(a)+len(b) < len(setFromList(l1))+len(setFromList(l2))
+ m1 := setFromList(l1)
+ for _, x := range l2 {
+ if _, ok := m1[x]; ok {
+ return true
+ }
+ }
+ return false
}
// Returns true if the given string s is prefixed with any string in the given prefix list.
@@ -308,6 +307,20 @@
return
}
+// FilterListByPrefixes performs the same splitting as FilterList does, but treats the passed
+// filters as prefixes
+func FilterListByPrefix(list []string, filter []string) (remainder []string, filtered []string) {
+ for _, l := range list {
+ if HasAnyPrefix(l, filter) {
+ filtered = append(filtered, l)
+ } else {
+ remainder = append(remainder, l)
+ }
+ }
+
+ return
+}
+
// FilterListPred returns the elements of the given list for which the predicate
// returns true. Order is kept.
func FilterListPred(list []string, pred func(s string) bool) (filtered []string) {
@@ -632,35 +645,6 @@
}
}
-// SyncMap is a wrapper around sync.Map that provides type safety via generics.
-type SyncMap[K comparable, V any] struct {
- sync.Map
-}
-
-// Load returns the value stored in the map for a key, or the zero value if no
-// value is present.
-// The ok result indicates whether value was found in the map.
-func (m *SyncMap[K, V]) Load(key K) (value V, ok bool) {
- v, ok := m.Map.Load(key)
- if !ok {
- return *new(V), false
- }
- return v.(V), true
-}
-
-// Store sets the value for a key.
-func (m *SyncMap[K, V]) Store(key K, value V) {
- m.Map.Store(key, value)
-}
-
-// LoadOrStore returns the existing value for the key if present.
-// Otherwise, it stores and returns the given value.
-// The loaded result is true if the value was loaded, false if stored.
-func (m *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
- v, loaded := m.Map.LoadOrStore(key, value)
- return v.(V), loaded
-}
-
// AppendIfNotZero append the given value to the slice if it is not the zero value
// for its type.
func AppendIfNotZero[T comparable](slice []T, value T) []T {
diff --git a/android/variable.go b/android/variable.go
index e012103..f00dd13 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -65,12 +65,6 @@
Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
} `android:"arch_variant"`
- // similar to `Unbundled_build`, but `Always_use_prebuilt_sdks` means that it uses prebuilt
- // sdk specifically.
- Always_use_prebuilt_sdks struct {
- Enabled proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
- } `android:"arch_variant"`
-
Malloc_low_memory struct {
Cflags []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
@@ -162,6 +156,7 @@
Optimize struct {
Enabled *bool
}
+ Aaptflags []string
}
Uml struct {
@@ -215,7 +210,7 @@
Platform_display_version_name *string `json:",omitempty"`
Platform_version_name *string `json:",omitempty"`
Platform_sdk_version *int `json:",omitempty"`
- Platform_sdk_minor_version *int `json:",omitempty"`
+ Platform_sdk_version_full *string `json:",omitempty"`
Platform_sdk_codename *string `json:",omitempty"`
Platform_sdk_version_or_codename *string `json:",omitempty"`
Platform_sdk_final *bool `json:",omitempty"`
@@ -230,8 +225,8 @@
Platform_version_last_stable *string `json:",omitempty"`
Platform_version_known_codenames *string `json:",omitempty"`
- DeviceName *string `json:",omitempty"`
- DeviceProduct *string `json:",omitempty"`
+ DeviceName *string `json:",omitempty" generic:"generic"`
+ DeviceProduct *string `json:",omitempty" generic:"generic"`
DeviceArch *string `json:",omitempty"`
DeviceArchVariant *string `json:",omitempty"`
DeviceCpuVariant *string `json:",omitempty"`
@@ -533,7 +528,8 @@
OdmPropFiles []string `json:",omitempty"`
VendorPropFiles []string `json:",omitempty"`
- EnableUffdGc *string `json:",omitempty"`
+ EnableUffdGc *string `json:",omitempty"`
+ BoardKernelVersion *string `json:",omitempty"`
BoardAvbEnable *bool `json:",omitempty"`
BoardAvbSystemAddHashtreeFooterArgs []string `json:",omitempty"`
@@ -542,8 +538,6 @@
PartitionVarsForSoongMigrationOnlyDoNotUse PartitionVariables
- ExtraAllowedDepsTxt *string `json:",omitempty"`
-
AdbKeys *string `json:",omitempty"`
DeviceMatrixFile []string `json:",omitempty"`
@@ -552,10 +546,15 @@
SystemExtManifestFiles []string `json:",omitempty"`
DeviceManifestFiles []string `json:",omitempty"`
OdmManifestFiles []string `json:",omitempty"`
+
+ UseSoongNoticeXML *bool `json:",omitempty"`
+
+ StripByDefault *bool `json:",omitempty"`
}
type PartitionQualifiedVariablesType struct {
BuildingImage bool `json:",omitempty"`
+ PrebuiltImage bool `json:",omitempty"`
BoardErofsCompressor string `json:",omitempty"`
BoardErofsCompressHints string `json:",omitempty"`
BoardErofsPclusterSize string `json:",omitempty"`
@@ -618,39 +617,55 @@
ProductUseDynamicPartitionSize bool `json:",omitempty"`
CopyImagesForTargetFilesZip bool `json:",omitempty"`
- VendorSecurityPatch string `json:",omitempty"`
+ VendorSecurityPatch string `json:",omitempty"`
+ OdmSecurityPatch string `json:",omitempty"`
+ SystemDlkmSecurityPatch string `json:",omitempty"`
+ VendorDlkmSecurityPatch string `json:",omitempty"`
+ OdmDlkmSecurityPatch string `json:",omitempty"`
+
+ BuildingSystemOtherImage bool `json:",omitempty"`
// Boot image stuff
- BuildingRamdiskImage bool `json:",omitempty"`
- ProductBuildBootImage bool `json:",omitempty"`
- ProductBuildVendorBootImage string `json:",omitempty"`
- ProductBuildInitBootImage bool `json:",omitempty"`
- BoardUsesRecoveryAsBoot bool `json:",omitempty"`
- BoardPrebuiltBootimage string `json:",omitempty"`
- BoardPrebuiltInitBootimage string `json:",omitempty"`
- BoardBootimagePartitionSize string `json:",omitempty"`
- BoardInitBootimagePartitionSize string `json:",omitempty"`
- BoardBootHeaderVersion string `json:",omitempty"`
- TargetKernelPath string `json:",omitempty"`
- BoardUsesGenericKernelImage bool `json:",omitempty"`
- BootSecurityPatch string `json:",omitempty"`
- InitBootSecurityPatch string `json:",omitempty"`
- BoardIncludeDtbInBootimg bool `json:",omitempty"`
- InternalKernelCmdline []string `json:",omitempty"`
- InternalBootconfig []string `json:",omitempty"`
- InternalBootconfigFile string `json:",omitempty"`
+ BuildingRamdiskImage bool `json:",omitempty"`
+ ProductBuildBootImage bool `json:",omitempty"`
+ ProductBuildVendorBootImage string `json:",omitempty"`
+ ProductBuildInitBootImage bool `json:",omitempty"`
+ BoardUsesRecoveryAsBoot bool `json:",omitempty"`
+ BoardPrebuiltBootimage string `json:",omitempty"`
+ BoardPrebuiltInitBootimage string `json:",omitempty"`
+ BoardBootimagePartitionSize string `json:",omitempty"`
+ BoardVendorBootimagePartitionSize string `json:",omitempty"`
+ BoardInitBootimagePartitionSize string `json:",omitempty"`
+ BoardBootHeaderVersion string `json:",omitempty"`
+ TargetKernelPath string `json:",omitempty"`
+ BoardUsesGenericKernelImage bool `json:",omitempty"`
+ BootSecurityPatch string `json:",omitempty"`
+ InitBootSecurityPatch string `json:",omitempty"`
+ BoardIncludeDtbInBootimg bool `json:",omitempty"`
+ InternalKernelCmdline []string `json:",omitempty"`
+ InternalBootconfig []string `json:",omitempty"`
+ InternalBootconfigFile string `json:",omitempty"`
// Super image stuff
ProductUseDynamicPartitions bool `json:",omitempty"`
ProductRetrofitDynamicPartitions bool `json:",omitempty"`
ProductBuildSuperPartition bool `json:",omitempty"`
+ BuildingSuperEmptyImage bool `json:",omitempty"`
BoardSuperPartitionSize string `json:",omitempty"`
BoardSuperPartitionMetadataDevice string `json:",omitempty"`
BoardSuperPartitionBlockDevices []string `json:",omitempty"`
BoardSuperPartitionGroups map[string]BoardSuperPartitionGroupProps `json:",omitempty"`
ProductVirtualAbOta bool `json:",omitempty"`
ProductVirtualAbOtaRetrofit bool `json:",omitempty"`
+ ProductVirtualAbCompression bool `json:",omitempty"`
+ ProductVirtualAbCompressionMethod string `json:",omitempty"`
+ ProductVirtualAbCompressionFactor string `json:",omitempty"`
+ ProductVirtualAbCowVersion string `json:",omitempty"`
AbOtaUpdater bool `json:",omitempty"`
+ AbOtaPartitions []string `json:",omitempty"`
+ AbOtaKeys []string `json:",omitempty"`
+ AbOtaPostInstallConfig []string `json:",omitempty"`
+ BoardSuperImageInUpdatePackage bool `json:",omitempty"`
// Avb (android verified boot) stuff
BoardAvbEnable bool `json:",omitempty"`
@@ -689,6 +704,22 @@
ProductFsverityGenerateMetadata bool `json:",omitempty"`
TargetScreenDensity string `json:",omitempty"`
+
+ PrivateRecoveryUiProperties map[string]string `json:",omitempty"`
+
+ PrebuiltBootloader string `json:",omitempty"`
+
+ ProductFsCasefold string `json:",omitempty"`
+ ProductQuotaProjid string `json:",omitempty"`
+ ProductFsCompression string `json:",omitempty"`
+
+ ReleaseToolsExtensionDir string `json:",omitempty"`
+
+ BoardPartialOtaUpdatePartitionsList []string `json:",omitempty"`
+ BoardFlashBlockSize string `json:",omitempty"`
+ BootloaderInUpdatePackage bool `json:",omitempty"`
+
+ BoardFastbootInfoFile string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/android/variable_test.go b/android/variable_test.go
index 73dc052..1d928f2 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -299,7 +299,7 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- foo := result.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
+ foo := result.ModuleForTests(t, "foo", "").Module().(*productVariablesDefaultsTestModule)
want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
AssertDeepEquals(t, "foo", want, foo.properties.Foo)
@@ -360,7 +360,7 @@
FixtureWithRootAndroidBp(bp),
).RunTest(t)
- foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*productVariablesDefaultsTestModule)
+ foo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Module().(*productVariablesDefaultsTestModule)
want := []string{"module", "arm64"}
AssertDeepEquals(t, "foo", want, foo.properties.Foo)
diff --git a/android/vendor_api_levels.go b/android/vendor_api_levels.go
index 4d364fd..d32bc56 100644
--- a/android/vendor_api_levels.go
+++ b/android/vendor_api_levels.go
@@ -27,6 +27,8 @@
sdkVersion = 35
case 202504:
sdkVersion = 36
+ case 202604:
+ sdkVersion = 37
default:
ok = false
}
diff --git a/android/vintf_data.go b/android/vintf_data.go
index 401f4d2..2909817 100644
--- a/android/vintf_data.go
+++ b/android/vintf_data.go
@@ -140,6 +140,7 @@
// Process vintf fragment source file with assemble_vintf tool
builder.Command().
+ Implicits(inputPaths).
Flags(assembleVintfEnvs).
BuiltTool("assemble_vintf").
FlagWithArg("-i ", strings.Join(inputPaths.Strings(), ":")).
diff --git a/android/vintf_fragment.go b/android/vintf_fragment.go
index a3343fd..4a29fee 100644
--- a/android/vintf_fragment.go
+++ b/android/vintf_fragment.go
@@ -14,13 +14,16 @@
package android
+import "github.com/google/blueprint"
+
type vintfFragmentProperties struct {
// Vintf fragment XML file.
Src string `android:"path"`
}
-type vintfFragmentModule struct {
+type VintfFragmentModule struct {
ModuleBase
+ ApexModuleBase
properties vintfFragmentProperties
@@ -36,11 +39,17 @@
ctx.RegisterModuleType("vintf_fragment", vintfLibraryFactory)
}
+type VintfFragmentInfo struct {
+ OutputFile Path
+}
+
+var VintfFragmentInfoProvider = blueprint.NewProvider[VintfFragmentInfo]()
+
// vintf_fragment module processes vintf fragment file and installs under etc/vintf/manifest.
// Vintf fragment files formerly listed in vintf_fragment property would be transformed into
// this module type.
func vintfLibraryFactory() Module {
- m := &vintfFragmentModule{}
+ m := &VintfFragmentModule{}
m.AddProperties(
&m.properties,
)
@@ -49,7 +58,7 @@
return m
}
-func (m *vintfFragmentModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+func (m *VintfFragmentModule) GenerateAndroidBuildActions(ctx ModuleContext) {
builder := NewRuleBuilder(pctx, ctx)
srcVintfFragment := PathForModuleSrc(ctx, m.properties.Src)
processedVintfFragment := PathForModuleOut(ctx, srcVintfFragment.Base())
@@ -67,10 +76,18 @@
m.outputFilePath = processedVintfFragment
ctx.InstallFile(m.installDirPath, processedVintfFragment.Base(), processedVintfFragment)
+
+ SetProvider(ctx, VintfFragmentInfoProvider, VintfFragmentInfo{
+ OutputFile: m.OutputFile(),
+ })
+}
+
+func (m *VintfFragmentModule) OutputFile() Path {
+ return m.outputFilePath
}
// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files
-func (m *vintfFragmentModule) AndroidMkEntries() []AndroidMkEntries {
+func (m *VintfFragmentModule) AndroidMkEntries() []AndroidMkEntries {
return []AndroidMkEntries{{
Class: "ETC",
OutputFile: OptionalPathForPath(m.outputFilePath),
@@ -82,3 +99,10 @@
},
}}
}
+
+var _ ApexModule = (*VintfFragmentModule)(nil)
+
+// Implements android.ApexModule
+func (m *VintfFragmentModule) MinSdkVersionSupported(ctx BaseModuleContext) ApiLevel {
+ return MinApiLevel
+}
diff --git a/android/vintf_fragment_test.go b/android/vintf_fragment_test.go
index cd90b98..7f0078c 100644
--- a/android/vintf_fragment_test.go
+++ b/android/vintf_fragment_test.go
@@ -29,8 +29,8 @@
testResult := PrepareForTestWithAndroidBuildComponents.RunTestWithBp(t, bp)
- vintfFragmentBuild := testResult.TestContext.ModuleForTests("test_vintf_fragment", "android_common").Rule("assemble_vintf")
+ vintfFragmentBuild := testResult.TestContext.ModuleForTests(t, "test_vintf_fragment", "android_common").Rule("assemble_vintf")
if !strings.Contains(vintfFragmentBuild.RuleParams.Command, "assemble_vintf") {
- t.Errorf("Vintf_manifest build command does not process with assemble_vintf : " + vintfFragmentBuild.RuleParams.Command)
+ t.Error("Vintf_manifest build command does not process with assemble_vintf : " + vintfFragmentBuild.RuleParams.Command)
}
}
diff --git a/android/visibility.go b/android/visibility.go
index cee465e..9153687 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -58,15 +58,29 @@
var visibilityRuleRegexp = regexp.MustCompile(visibilityRulePattern)
type visibilityModuleReference struct {
- name qualifiedModuleName
- module Module
+ name qualifiedModuleName
+ partitionType *string
}
func createVisibilityModuleReference(name, dir string, module Module) visibilityModuleReference {
- return visibilityModuleReference{
- name: createQualifiedModuleName(name, dir),
- module: module,
+ vis := visibilityModuleReference{
+ name: createQualifiedModuleName(name, dir),
}
+ if m, ok := module.(PartitionTypeInterface); ok {
+ pt := m.PartitionType()
+ vis.partitionType = &pt
+ }
+ return vis
+}
+
+func createVisibilityModuleProxyReference(ctx OtherModuleProviderContext, name, dir string, module ModuleProxy) visibilityModuleReference {
+ vis := visibilityModuleReference{
+ name: createQualifiedModuleName(name, dir),
+ }
+ if m, ok := OtherModuleProvider(ctx, module, PartitionTypeInfoProvider); ok {
+ vis.partitionType = &m.PartitionType
+ }
+ return vis
}
// A visibility rule is associated with a module and determines which other modules it is visible
@@ -222,9 +236,17 @@
PartitionType() string
}
+type PartitionTypeInfo struct {
+ // 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.
+ PartitionType string
+}
+
+var PartitionTypeInfoProvider = blueprint.NewProvider[PartitionTypeInfo]()
+
func (r anyPartitionRule) matches(m visibilityModuleReference) bool {
- if m2, ok := m.module.(PartitionTypeInterface); ok {
- return m2.PartitionType() == r.partitionType
+ if m.partitionType != nil {
+ return *m.partitionType == r.partitionType
}
return false
}
@@ -647,42 +669,6 @@
return v.rules
}
-// Get the effective visibility rules, i.e. the actual rules that affect the visibility of the
-// property irrespective of where they are defined.
-//
-// Includes visibility rules specified by package default_visibility and/or on defaults.
-// Short hand forms, e.g. //:__subpackages__ are replaced with their full form, e.g.
-// //package/containing/rule:__subpackages__.
-func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) VisibilityRuleSet {
- moduleName := ctx.OtherModuleName(module)
- dir := ctx.OtherModuleDir(module)
- qualified := qualifiedModuleName{dir, moduleName}
-
- rule := effectiveVisibilityRules(ctx.Config(), qualified)
-
- 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
- // explicitly.
- if !rule.matches(currentModule) {
- if len(rule) == 1 {
- if _, ok := rule[0].(privateRule); ok {
- // If the rule is //visibility:private we can't append another
- // visibility to it. Semantically we need to convert it to a package
- // visibility rule for the location where the result is used, but since
- // modules are implicitly visible within the package we get the same
- // result without any rule at all, so just make it an empty list to be
- // appended below.
- rule = nil
- }
- }
- rule = append(rule, packageRule{dir})
- }
-
- return &visibilityRuleSet{rule.Strings()}
-}
-
// Clear the default visibility properties so they can be replaced.
func clearVisibilityProperties(module Module) {
module.base().visibilityPropertyInfo = nil
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 277be0f..4acaa02 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -2112,7 +2112,10 @@
ctx.AddVariationDependencies(nil, dependencyTag{name: "mockdeps"}, j.properties.Deps...)
}
-func (p *mockFilesystemModule) GenerateAndroidBuildActions(ModuleContext) {
+func (p *mockFilesystemModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ SetProvider(ctx, PartitionTypeInfoProvider, PartitionTypeInfo{
+ PartitionType: p.PartitionType(),
+ })
}
func (p *mockFilesystemModule) PartitionType() string {
diff --git a/android_sdk/sdk_repo_host_test.go b/android_sdk/sdk_repo_host_test.go
index 0688921..ce84204 100644
--- a/android_sdk/sdk_repo_host_test.go
+++ b/android_sdk/sdk_repo_host_test.go
@@ -44,7 +44,7 @@
`)
// produces "sdk-repo-{OS}-platform-tools.zip"
- result.ModuleForTests("platform-tools", "linux_glibc_common").Output("sdk-repo-linux-platform-tools.zip")
+ result.ModuleForTests(t, "platform-tools", "linux_glibc_common").Output("sdk-repo-linux-platform-tools.zip")
}
func TestRemapPackageSpecs(t *testing.T) {
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 18c97b5..e723abd 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -103,25 +103,26 @@
func init() {
addStandardProperties(bpparser.StringType,
map[string]string{
- "LOCAL_MODULE": "name",
- "LOCAL_CXX_STL": "stl",
- "LOCAL_MULTILIB": "compile_multilib",
- "LOCAL_ARM_MODE_HACK": "instruction_set",
- "LOCAL_SDK_VERSION": "sdk_version",
- "LOCAL_MIN_SDK_VERSION": "min_sdk_version",
- "LOCAL_TARGET_SDK_VERSION": "target_sdk_version",
- "LOCAL_NDK_STL_VARIANT": "stl",
- "LOCAL_JAR_MANIFEST": "manifest",
- "LOCAL_CERTIFICATE": "certificate",
- "LOCAL_CERTIFICATE_LINEAGE": "lineage",
- "LOCAL_PACKAGE_NAME": "name",
- "LOCAL_MODULE_RELATIVE_PATH": "relative_install_path",
- "LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
- "LOCAL_MODULE_OWNER": "owner",
- "LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
- "LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
- "LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
- "LOCAL_MANIFEST_FILE": "manifest",
+ "LOCAL_MODULE": "name",
+ "LOCAL_CXX_STL": "stl",
+ "LOCAL_MULTILIB": "compile_multilib",
+ "LOCAL_ARM_MODE_HACK": "instruction_set",
+ "LOCAL_SDK_VERSION": "sdk_version",
+ "LOCAL_MIN_SDK_VERSION": "min_sdk_version",
+ "LOCAL_ROTATION_MIN_SDK_VERSION": "rotationMinSdkVersion",
+ "LOCAL_TARGET_SDK_VERSION": "target_sdk_version",
+ "LOCAL_NDK_STL_VARIANT": "stl",
+ "LOCAL_JAR_MANIFEST": "manifest",
+ "LOCAL_CERTIFICATE": "certificate",
+ "LOCAL_CERTIFICATE_LINEAGE": "lineage",
+ "LOCAL_PACKAGE_NAME": "name",
+ "LOCAL_MODULE_RELATIVE_PATH": "relative_install_path",
+ "LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
+ "LOCAL_MODULE_OWNER": "owner",
+ "LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
+ "LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
+ "LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
+ "LOCAL_MANIFEST_FILE": "manifest",
"LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile",
"LOCAL_TEST_CONFIG": "test_config",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index ec5ca15..0a5644a 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -75,7 +75,7 @@
// populated by Soong for unconverted APEXes, or Bazel in mixed mode. Use
// apexFile#isBazelPrebuilt to differentiate.
func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir string,
- apexAndroidMkData android.AndroidMkData) []string {
+ apexAndroidMkData android.AndroidMkData) (archSpecificModuleNames []string, moduleNames []string) {
// apexBundleName comes from the 'name' property or soong module.
// apexName comes from 'name' property of apex_manifest.
@@ -84,11 +84,12 @@
// However, symbol files for apex files are installed under /apex/<apexBundleName> to avoid
// conflicts between two apexes with the same apexName.
- moduleNames := []string{}
-
for _, fi := range a.filesInfo {
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
moduleName := a.fullModuleName(apexBundleName, linkToSystemLib, &fi)
+ if !android.InList(moduleName, moduleNames) {
+ moduleNames = append(moduleNames, moduleName)
+ }
// This name will be added to LOCAL_REQUIRED_MODULES of the APEX. We need to be
// arch-specific otherwise we will end up installing both ABIs even when only
@@ -100,8 +101,8 @@
case "lib64":
aName = aName + ":64"
}
- if !android.InList(aName, moduleNames) {
- moduleNames = append(moduleNames, aName)
+ if !android.InList(aName, archSpecificModuleNames) {
+ archSpecificModuleNames = append(archSpecificModuleNames, aName)
}
if linkToSystemLib {
@@ -216,7 +217,7 @@
fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
}
}
- return moduleNames
+ return
}
func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) {
@@ -226,11 +227,6 @@
required = append(required, a.required...)
targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...)
hostRequired = append(hostRequired, a.HostRequiredModuleNames()...)
- for _, fi := range a.filesInfo {
- required = append(required, fi.requiredModuleNames...)
- targetRequired = append(targetRequired, fi.targetRequiredModuleNames...)
- hostRequired = append(hostRequired, fi.hostRequiredModuleNames...)
- }
android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", moduleNames, a.makeModulesToInstall, required)
android.AndroidMkEmitAssignList(w, "LOCAL_TARGET_REQUIRED_MODULES", targetRequired)
android.AndroidMkEmitAssignList(w, "LOCAL_HOST_REQUIRED_MODULES", hostRequired)
@@ -240,9 +236,10 @@
return android.AndroidMkData{
// While we do not provide a value for `Extra`, AconfigUpdateAndroidMkData may add some, which we must honor.
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ archSpecificModuleNames := []string{}
moduleNames := []string{}
if a.installable() {
- moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
+ archSpecificModuleNames, moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
}
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle")
@@ -261,6 +258,7 @@
fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_SYMLINKS := ", strings.Join(a.compatSymlinks.Strings(), " "))
+ fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS +=", a.extraInstalledPairs.String())
}
fmt.Fprintln(w, "LOCAL_APEX_KEY_PATH := ", a.apexKeysPath.String())
@@ -278,7 +276,7 @@
}
android.AndroidMkEmitAssignList(w, "LOCAL_OVERRIDES_MODULES", a.overridableProperties.Overrides)
- a.writeRequiredModules(w, moduleNames)
+ a.writeRequiredModules(w, archSpecificModuleNames)
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
for _, extra := range data.Extra {
extra(w, a.outputFile)
@@ -300,6 +298,9 @@
fmt.Fprintln(w, dist)
}
+ fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).SYMBOLIC_OUTPUT_PATH))\n", strings.Join(moduleNames, " "))
+ fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).ELF_SYMBOL_MAPPING_PATH))\n", strings.Join(moduleNames, " "))
+
distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
distCoverageFiles(w, "ndk_apis_backedby_apex", a.nativeApisBackedByModuleFile.String())
distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
diff --git a/apex/apex.go b/apex/apex.go
index 9fdb2a2..a726098 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -18,6 +18,7 @@
import (
"fmt"
+ "path"
"path/filepath"
"regexp"
"slices"
@@ -61,12 +62,11 @@
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_info", apexInfoMutator)
ctx.BottomUp("apex_unique", apexUniqueVariationsMutator)
// Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether
// it should create a platform variant.
ctx.BottomUp("mark_platform_availability", markPlatformAvailability)
- ctx.Transition("apex", &apexTransitionMutator{})
+ ctx.InfoBasedTransition("apex", android.NewGenericTransitionMutatorAdapter(&apexTransitionMutator{}))
}
type apexBundleProperties struct {
@@ -83,10 +83,6 @@
// /system/sepolicy/apex/<module_name>_file_contexts.
File_contexts *string `android:"path"`
- // By default, file_contexts is amended by force-labelling / and /apex_manifest.pb as system_file
- // to avoid mistakes. When set as true, no force-labelling.
- Use_file_contexts_as_is *bool
-
// Path to the canned fs config file for customizing file's
// uid/gid/mod/capabilities. The content of this file is appended to the
// default config, so that the custom entries are preferred. The format is
@@ -415,6 +411,30 @@
Min_sdk_version *string
}
+// installPair stores a path to a built object and its install location. It is used for holding
+// the installation location of the dexpreopt artifacts for system server jars in apexes that need
+// to be installed when the apex is installed.
+type installPair struct {
+ from android.Path
+ to android.InstallPath
+}
+
+type installPairs []installPair
+
+// String converts a list of installPair structs to the form accepted by LOCAL_SOONG_INSTALL_PAIRS.
+func (p installPairs) String() string {
+ sb := &strings.Builder{}
+ for i, pair := range p {
+ if i != 0 {
+ sb.WriteByte(' ')
+ }
+ sb.WriteString(pair.from.String())
+ sb.WriteByte(':')
+ sb.WriteString(pair.to.String())
+ }
+ return sb.String()
+}
+
type apexBundle struct {
// Inherited structs
android.ModuleBase
@@ -496,6 +516,12 @@
// Path where this APEX was installed.
installedFile android.InstallPath
+ // Extra files that are installed alongside this APEX.
+ extraInstalledFiles android.InstallPaths
+
+ // The source and install locations for extraInstalledFiles for use in LOCAL_SOONG_INSTALL_PAIRS.
+ extraInstalledPairs installPairs
+
// fragment for this apex for apexkeys.txt
apexKeysPath android.WritablePath
@@ -524,6 +550,9 @@
// Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk
required []string
+
+ // appinfo of the apk-in-apex of this module
+ appInfos java.AppInfos
}
// apexFileClass represents a type of file that can be included in APEX.
@@ -540,19 +569,6 @@
shBinary
)
-var (
- classes = map[string]apexFileClass{
- "app": app,
- "appSet": appSet,
- "etc": etc,
- "javaSharedLib": javaSharedLib,
- "nativeExecutable": nativeExecutable,
- "nativeSharedLib": nativeSharedLib,
- "nativeTest": nativeTest,
- "shBinary": shBinary,
- }
-)
-
// apexFile represents a file in an APEX bundle. This is created during the first half of
// GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half
// of the function, this is used to create commands that copies the files into a staging directory,
@@ -570,13 +586,15 @@
// Info for Android.mk Module name of `module` in AndroidMk. Note the generated AndroidMk
// module for apexFile is named something like <AndroidMk module name>.<apex name>[<apex
// suffix>]
- androidMkModuleName string // becomes LOCAL_MODULE
- class apexFileClass // becomes LOCAL_MODULE_CLASS
- moduleDir string // becomes LOCAL_PATH
- requiredModuleNames []string // becomes LOCAL_REQUIRED_MODULES
- targetRequiredModuleNames []string // becomes LOCAL_TARGET_REQUIRED_MODULES
- hostRequiredModuleNames []string // becomes LOCAL_HOST_REQUIRED_MODULES
- dataPaths []android.DataPath // becomes LOCAL_TEST_DATA
+ androidMkModuleName string // becomes LOCAL_MODULE
+ class apexFileClass // becomes LOCAL_MODULE_CLASS
+ moduleDir string // becomes LOCAL_PATH
+ dataPaths []android.DataPath // becomes LOCAL_TEST_DATA
+
+ // systemServerDexpreoptInstalls stores the list of dexpreopt artifacts for a system server jar.
+ systemServerDexpreoptInstalls []java.DexpreopterInstall
+ // systemServerDexJars stores the list of dexjars for a system server jar.
+ systemServerDexJars android.Paths
jacocoReportClassesFile android.Path // only for javalibs and apps
lintInfo *java.LintInfo // only for javalibs and apps
@@ -593,7 +611,8 @@
}
// TODO(jiyong): shorten the arglist using an option struct
-func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile {
+func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string,
+ installDir string, class apexFileClass, module android.Module) apexFile {
ret := apexFile{
builtFile: builtFile,
installDir: installDir,
@@ -736,6 +755,17 @@
shBinaryTag = &dependencyTag{name: "shBinary", payload: true}
)
+type fragmentInApexDepTag struct {
+ blueprint.BaseDependencyTag
+ android.FragmentInApexTag
+}
+
+func (fragmentInApexDepTag) ExcludeFromVisibilityEnforcement() {}
+
+// fragmentInApexTag is used by apex modules to depend on their fragments. Java bootclasspath
+// modules can traverse from the apex to the fragment using android.IsFragmentInApexTag.
+var fragmentInApexTag = fragmentInApexDepTag{}
+
// TODO(jiyong): shorten this function signature
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ResolvedApexNativeDependencies, target android.Target, imageVariation string) {
binVariations := target.Variations()
@@ -884,12 +914,31 @@
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...)
ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments.GetOrDefault(ctx, nil)...)
+ ctx.AddFarVariationDependencies(commonVariation, fragmentInApexTag, a.properties.Bootclasspath_fragments.GetOrDefault(ctx, nil)...)
ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments.GetOrDefault(ctx, nil)...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
+
+ // Add a reverse dependency to all_apex_certs singleton module.
+ // all_apex_certs will use this dependency to collect the certificate of this apex.
+ ctx.AddReverseDependency(ctx.Module(), allApexCertsDepTag, "all_apex_certs")
+
+ // TODO: When all branches contain this singleton module, make this strict
+ // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module
+ if ctx.OtherModuleExists("all_apex_contributions") {
+ ctx.AddDependency(ctx.Module(), android.AcDepTag, "all_apex_contributions")
+ }
}
+type allApexCertsDependencyTag struct {
+ blueprint.DependencyTag
+}
+
+func (_ allApexCertsDependencyTag) ExcludeFromVisibilityEnforcement() {}
+
+var allApexCertsDepTag = allApexCertsDependencyTag{}
+
// DepsMutator for the overridden properties.
func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
if a.overridableProperties.Allowed_files != nil {
@@ -934,58 +983,29 @@
}
}
-var _ ApexInfoMutator = (*apexBundle)(nil)
+var _ ApexTransitionMutator = (*apexBundle)(nil)
func (a *apexBundle) ApexVariationName() string {
return a.properties.ApexVariationName
}
-// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
-// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
-// indirect) dependencies are collected. But a few types of modules that shouldn't be included in
-// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended
-// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles.
-//
-// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex
-// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list.
-// The apexMutator uses that list to create module variants for the apexes to which it belongs.
-// The relationship between module variants and apexes is not one-to-one as variants will be
-// shared between compatible apexes.
-func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
+type generateApexInfoContext interface {
+ android.MinSdkVersionFromValueContext
+ Module() android.Module
+ ModuleName() string
+}
+// generateApexInfo returns an android.ApexInfo configuration that should be used for dependencies of this apex.
+func (a *apexBundle) generateApexInfo(ctx generateApexInfoContext) android.ApexInfo {
// The VNDK APEX is special. For the APEX, the membership is described in a very different
// way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK
// libraries are self-identified by their vndk.enabled properties. There is no need to run
- // this mutator for the APEX as nothing will be collected. So, let's return fast.
+ // this mutator for the APEX as nothing will be collected so return an empty ApexInfo.
if a.vndkApex {
- return
+ return android.ApexInfo{}
}
- continueApexDepsWalk := func(child, parent android.Module) bool {
- am, ok := child.(android.ApexModule)
- if !ok || !am.CanHaveApexVariants() {
- return false
- }
- depTag := mctx.OtherModuleDependencyTag(child)
-
- // Check to see if the tag always requires that the child module has an apex variant for every
- // apex variant of the parent module. If it does not then it is still possible for something
- // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required.
- if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() {
- return true
- }
- if !android.IsDepInSameApex(mctx, parent, child) {
- return false
- }
-
- // By default, all the transitive dependencies are collected, unless filtered out
- // above.
- return true
- }
-
- android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
-
- minSdkVersion := a.minSdkVersion(mctx)
+ minSdkVersion := a.minSdkVersion(ctx)
// When min_sdk_version is not set, the apex is built against FutureApiLevel.
if minSdkVersion.IsNone() {
minSdkVersion = android.FutureApiLevel
@@ -994,61 +1014,45 @@
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
- apexVariationName := mctx.ModuleName() // could be com.android.foo
- if overridable, ok := mctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
+ apexVariationName := ctx.ModuleName() // could be com.android.foo
+ if a.GetOverriddenBy() != "" {
// use the overridden name com.mycompany.android.foo
- apexVariationName = overridable.GetOverriddenBy()
+ apexVariationName = a.GetOverriddenBy()
}
- a.properties.ApexVariationName = apexVariationName
- testApexes := []string{}
- if a.testApex {
- testApexes = []string{apexVariationName}
- }
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
MinSdkVersion: minSdkVersion,
Updatable: a.Updatable(),
UsePlatformApis: a.UsePlatformApis(),
- InApexVariants: []string{apexVariationName},
- TestApexes: testApexes,
- BaseApexName: mctx.ModuleName(),
+ BaseApexName: ctx.ModuleName(),
ApexAvailableName: proptools.String(a.properties.Apex_available_name),
}
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if !continueApexDepsWalk(child, parent) {
- return false
- }
- child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark!
- return true
- })
+ return apexInfo
}
-type ApexInfoMutator interface {
- // ApexVariationName returns the name of the APEX variation to use in the apex
- // mutator etc. It is the same name as ApexInfo.ApexVariationName.
- ApexVariationName() string
-
- // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
- // depended upon by an apex and which require an apex specific variant.
- ApexInfoMutator(android.TopDownMutatorContext)
+func (a *apexBundle) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{a.generateApexInfo(ctx)}
}
-// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex
-// specific variant to modules that support the ApexInfoMutator.
-// It also propagates updatable=true to apps of updatable apexes
-func apexInfoMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
+func (a *apexBundle) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
- if a, ok := mctx.Module().(ApexInfoMutator); ok {
- a.ApexInfoMutator(mctx)
- }
+func (a *apexBundle) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return a.generateApexInfo(ctx)
+}
- if am, ok := mctx.Module().(android.ApexModule); ok {
- android.ApexInfoMutator(mctx, am)
- }
+func (a *apexBundle) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
+ a.properties.ApexVariationName = info.ApexVariationName
+}
+
+type ApexTransitionMutator interface {
+ ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo
+ ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo
+ ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo
+ ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo)
}
// TODO: b/215736885 Whittle the denylist
@@ -1062,7 +1066,7 @@
"com.android.appsearch",
"com.android.art",
"com.android.art.debug",
- "com.android.btservices",
+ "com.android.bt",
"com.android.cellbroadcast",
"com.android.configinfrastructure",
"com.android.conscrypt",
@@ -1111,6 +1115,9 @@
}
if am, ok := mctx.Module().(android.ApexModule); ok {
android.UpdateUniqueApexVariationsForDeps(mctx, am)
+ android.SetProvider(mctx, android.DepInSameApexInfoProvider, android.DepInSameApexInfo{
+ Checker: am.GetDepInSameApexChecker(),
+ })
}
}
@@ -1163,53 +1170,35 @@
type apexTransitionMutator struct{}
-func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
- // apexBundle itself is mutated so that it and its dependencies have the same apex variant.
- if ai, ok := ctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
- if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
- return []string{overridable.GetOverriddenBy()}
- }
- return []string{ai.ApexVariationName()}
- } else if _, ok := ctx.Module().(*OverrideApex); ok {
- return []string{ctx.ModuleName()}
+func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorSplit(ctx)
}
- return []string{""}
+ return []android.ApexInfo{{}}
}
-func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
- return sourceVariation
-}
-
-func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
- if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- return android.IncomingApexTransition(ctx, incomingVariation)
- } else if ai, ok := ctx.Module().(ApexInfoMutator); ok {
- if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
- return overridable.GetOverriddenBy()
- }
- return ai.ApexVariationName()
- } else if _, ok := ctx.Module().(*OverrideApex); ok {
- return ctx.Module().Name()
+func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorOutgoing(ctx, sourceInfo)
}
-
- return ""
+ return android.ApexInfo{}
}
-func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
- if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- android.MutateApexTransition(ctx, variation)
+func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorIncoming(ctx, outgoingInfo)
+ }
+ return android.ApexInfo{}
+}
+
+func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ ai.ApexTransitionMutatorMutate(ctx, info)
}
}
-// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
-// variant.
-func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
- if a, ok := module.(*apexBundle); ok {
- // TODO(jiyong): document the reason why the VNDK APEX is an exception here.
- return !a.vndkApex
- }
-
- return true
+func (a *apexTransitionMutator) TransitionInfoFromVariation(variation string) android.ApexInfo {
+ panic(fmt.Errorf("adding dependencies on explicit apex variations is not supported"))
}
const (
@@ -1225,15 +1214,6 @@
erofsFsType = "erofs"
)
-var _ android.DepIsInSameApex = (*apexBundle)(nil)
-
-// Implements android.DepInInSameApex
-func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
- // direct deps of an APEX bundle are all part of the APEX bundle
- // TODO(jiyong): shouldn't we look into the payload field of the dependencyTag?
- return true
-}
-
func (a *apexBundle) Exportable() bool {
return true
}
@@ -1383,24 +1363,29 @@
}
}
+func setDirInApexForNativeBridge(commonInfo *android.CommonModuleInfo, dir *string) {
+ if commonInfo.Target.NativeBridge == android.NativeBridgeEnabled {
+ *dir = filepath.Join(*dir, commonInfo.Target.NativeBridgeRelativePath)
+ }
+}
+
// apexFileFor<Type> functions below create an apexFile struct for a given Soong module. The
// returned apexFile saves information about the Soong module that will be used for creating the
// build rules.
-func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile {
+func apexFileForNativeLibrary(ctx android.BaseModuleContext, module android.Module,
+ commonInfo *android.CommonModuleInfo, ccMod *cc.LinkableInfo, handleSpecialLibs bool) apexFile {
// Decide the APEX-local directory by the multilib of the library In the future, we may
// query this to the module.
// TODO(jiyong): use the new PackagingSpec
var dirInApex string
- switch ccMod.Arch().ArchType.Multilib {
+ switch ccMod.Multilib {
case "lib32":
dirInApex = "lib"
case "lib64":
dirInApex = "lib64"
}
- if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
- dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
- }
- if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
+ setDirInApexForNativeBridge(commonInfo, &dirInApex)
+ if handleSpecialLibs && cc.InstallToBootstrap(commonInfo.BaseModuleName, ctx.Config()) {
// Special case for Bionic libs and other libs installed with them. This is to
// prevent those libs from being included in the search path
// /apex/com.android.runtime/${LIB}. This exclusion is required because those libs
@@ -1415,79 +1400,68 @@
// This needs to go after the runtime APEX handling because otherwise we would get
// weird paths like lib64/rel_install_path/bionic rather than
// lib64/bionic/rel_install_path.
- dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
+ dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath)
- fileToCopy := android.OutputFileForModule(ctx, ccMod, "")
- androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName
- return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod)
+ fileToCopy := android.OutputFileForModule(ctx, module, "")
+ androidMkModuleName := commonInfo.BaseModuleName + ccMod.SubName
+ return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, module)
}
-func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
+func apexFileForExecutable(ctx android.BaseModuleContext, module android.Module,
+ commonInfo *android.CommonModuleInfo, ccInfo *cc.CcInfo) apexFile {
+ linkableInfo := android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoProvider)
dirInApex := "bin"
- if cc.Target().NativeBridge == android.NativeBridgeEnabled {
- dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
- }
- dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
- fileToCopy := android.OutputFileForModule(ctx, cc, "")
- androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName
- af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc)
- af.symlinks = cc.Symlinks()
- af.dataPaths = cc.DataPaths()
+ setDirInApexForNativeBridge(commonInfo, &dirInApex)
+ dirInApex = filepath.Join(dirInApex, linkableInfo.RelativeInstallPath)
+ fileToCopy := android.OutputFileForModule(ctx, module, "")
+ androidMkModuleName := commonInfo.BaseModuleName + linkableInfo.SubName
+ af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, module)
+ af.symlinks = linkableInfo.Symlinks
+ af.dataPaths = ccInfo.DataPaths
return af
}
-func apexFileForRustExecutable(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
+func apexFileForRustExecutable(ctx android.BaseModuleContext, module android.Module,
+ commonInfo *android.CommonModuleInfo) apexFile {
+ linkableInfo := android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoProvider)
dirInApex := "bin"
- if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
- dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
- }
- dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath())
- fileToCopy := android.OutputFileForModule(ctx, rustm, "")
- androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
- af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm)
+ setDirInApexForNativeBridge(commonInfo, &dirInApex)
+ dirInApex = filepath.Join(dirInApex, linkableInfo.RelativeInstallPath)
+ fileToCopy := android.OutputFileForModule(ctx, module, "")
+ androidMkModuleName := commonInfo.BaseModuleName + linkableInfo.SubName
+ af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, module)
return af
}
-func apexFileForRustLibrary(ctx android.BaseModuleContext, rustm *rust.Module) apexFile {
- // Decide the APEX-local directory by the multilib of the library
- // In the future, we may query this to the module.
- var dirInApex string
- switch rustm.Arch().ArchType.Multilib {
- case "lib32":
- dirInApex = "lib"
- case "lib64":
- dirInApex = "lib64"
- }
- if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
- dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
- }
- dirInApex = filepath.Join(dirInApex, rustm.RelativeInstallPath())
- fileToCopy := android.OutputFileForModule(ctx, rustm, "")
- androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
- return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
-}
-
-func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
- dirInApex := filepath.Join("bin", sh.SubDir())
- if sh.Target().NativeBridge == android.NativeBridgeEnabled {
- dirInApex = filepath.Join(dirInApex, sh.Target().NativeBridgeRelativePath)
- }
- fileToCopy := sh.OutputFile()
- af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh)
- af.symlinks = sh.Symlinks()
+func apexFileForShBinary(ctx android.BaseModuleContext, module android.Module,
+ commonInfo *android.CommonModuleInfo, sh *sh.ShBinaryInfo) apexFile {
+ dirInApex := filepath.Join("bin", sh.SubDir)
+ setDirInApexForNativeBridge(commonInfo, &dirInApex)
+ fileToCopy := sh.OutputFile
+ af := newApexFile(ctx, fileToCopy, commonInfo.BaseModuleName, dirInApex, shBinary, module)
+ af.symlinks = sh.Symlinks
return af
}
-func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
- dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, module android.Module,
+ prebuilt *prebuilt_etc.PrebuiltEtcInfo, outputFile android.Path) apexFile {
+ dirInApex := filepath.Join(prebuilt.BaseDir, prebuilt.SubDir)
makeModuleName := strings.ReplaceAll(filepath.Join(dirInApex, outputFile.Base()), "/", "_")
- return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, prebuilt)
+ return newApexFile(ctx, outputFile, makeModuleName, dirInApex, etc, module)
}
-func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
- dirInApex := filepath.Join("etc", config.SubDir())
- fileToCopy := config.CompatConfig()
- return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config)
+func apexFileForCompatConfig(ctx android.BaseModuleContext, module android.Module,
+ config *java.PlatformCompatConfigInfo, depName string) apexFile {
+ dirInApex := filepath.Join("etc", config.SubDir)
+ fileToCopy := config.CompatConfig
+ return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, module)
+}
+
+func apexFileForVintfFragment(ctx android.BaseModuleContext, module android.Module,
+ commonInfo *android.CommonModuleInfo, vf *android.VintfFragmentInfo) apexFile {
+ dirInApex := filepath.Join("etc", "vintf")
+
+ return newApexFile(ctx, vf.OutputFile, commonInfo.BaseModuleName, dirInApex, etc, module)
}
// javaModule is an interface to handle all Java modules (java_library, dex_import, etc) in the same
@@ -1507,61 +1481,42 @@
var _ javaModule = (*java.SdkLibraryImport)(nil)
// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
-func apexFileForJavaModule(ctx android.ModuleContext, module javaModule) apexFile {
- return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath(ctx).PathOrNil())
+func apexFileForJavaModule(ctx android.ModuleContext, module android.Module, javaInfo *java.JavaInfo) apexFile {
+ return apexFileForJavaModuleWithFile(ctx, module, javaInfo, javaInfo.DexJarBuildPath.PathOrNil())
}
// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.
-func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module javaModule, dexImplementationJar android.Path) apexFile {
+func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module android.Module,
+ javaInfo *java.JavaInfo, dexImplementationJar android.Path) apexFile {
dirInApex := "javalib"
- af := newApexFile(ctx, dexImplementationJar, module.BaseModuleName(), dirInApex, javaSharedLib, module)
- af.jacocoReportClassesFile = module.JacocoReportClassesFile()
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ af := newApexFile(ctx, dexImplementationJar, commonInfo.BaseModuleName, dirInApex, javaSharedLib, module)
+ af.jacocoReportClassesFile = javaInfo.JacocoReportClassesFile
if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok {
af.lintInfo = lintInfo
}
- af.customStem = module.Stem() + ".jar"
+ af.customStem = javaInfo.Stem + ".jar"
+ // Collect any system server dex jars and dexpreopt artifacts for installation alongside the apex.
// TODO: b/338641779 - Remove special casing of sdkLibrary once bcpf and sscpf depends
// on the implementation library
- if sdkLib, ok := module.(*java.SdkLibrary); ok {
- for _, install := range sdkLib.BuiltInstalledForApex() {
- af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
- }
- } else if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
- for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() {
- af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
- }
+ if javaInfo.DexpreopterInfo != nil {
+ af.systemServerDexpreoptInstalls = append(af.systemServerDexpreoptInstalls, javaInfo.DexpreopterInfo.ApexSystemServerDexpreoptInstalls...)
+ af.systemServerDexJars = append(af.systemServerDexJars, javaInfo.DexpreopterInfo.ApexSystemServerDexJars...)
}
return af
}
-func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile {
- if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
- if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil {
- dirInApex := "javalib"
- af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil)
- af.customStem = module.Stem() + ".jar.prof"
- return &af
- }
+func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, commonInfo *android.CommonModuleInfo,
+ javaInfo *java.JavaInfo) *apexFile {
+ if profilePathOnHost := javaInfo.DexpreopterInfo.OutputProfilePathOnHost; profilePathOnHost != nil {
+ dirInApex := "javalib"
+ af := newApexFile(ctx, profilePathOnHost, commonInfo.BaseModuleName+"-profile", dirInApex, etc, nil)
+ af.customStem = javaInfo.Stem + ".jar.prof"
+ return &af
}
return nil
}
-// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in
-// the same way.
-type androidApp interface {
- android.Module
- Privileged() bool
- InstallApkName() string
- OutputFile() android.Path
- JacocoReportClassesFile() android.Path
- Certificate() java.Certificate
- BaseModuleName() string
- PrivAppAllowlist() android.OptionalPath
-}
-
-var _ androidApp = (*java.AndroidApp)(nil)
-var _ androidApp = (*java.AndroidAppImport)(nil)
-
func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string {
buildId := ctx.Config().BuildId()
@@ -1577,36 +1532,35 @@
return buildId
}
-func apexFilesForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) []apexFile {
+func apexFilesForAndroidApp(ctx android.BaseModuleContext, module android.Module,
+ commonInfo *android.CommonModuleInfo, aapp *java.AppInfo) []apexFile {
appDir := "app"
- if aapp.Privileged() {
+ if aapp.Privileged {
appDir = "priv-app"
}
// TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed
// so that PackageManager correctly invalidates the existing installed apk
// in favour of the new APK-in-APEX. See bugs for more information.
- dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+sanitizedBuildIdForPath(ctx))
- fileToCopy := aapp.OutputFile()
+ dirInApex := filepath.Join(appDir, aapp.InstallApkName+"@"+sanitizedBuildIdForPath(ctx))
+ fileToCopy := aapp.OutputFile
- af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
- af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
- if lintInfo, ok := android.OtherModuleProvider(ctx, aapp, java.LintProvider); ok {
+ af := newApexFile(ctx, fileToCopy, commonInfo.BaseModuleName, dirInApex, app, module)
+ af.jacocoReportClassesFile = aapp.JacocoReportClassesFile
+ if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok {
af.lintInfo = lintInfo
}
- af.certificate = aapp.Certificate()
+ af.certificate = aapp.Certificate
- if app, ok := aapp.(interface {
- OverriddenManifestPackageName() string
- }); ok {
- af.overriddenPackageName = app.OverriddenManifestPackageName()
+ if aapp.OverriddenManifestPackageName != nil {
+ af.overriddenPackageName = *aapp.OverriddenManifestPackageName
}
apexFiles := []apexFile{}
- if allowlist := aapp.PrivAppAllowlist(); allowlist.Valid() {
+ if allowlist := aapp.PrivAppAllowlist; allowlist.Valid() {
dirInApex := filepath.Join("etc", "permissions")
- privAppAllowlist := newApexFile(ctx, allowlist.Path(), aapp.BaseModuleName()+"_privapp", dirInApex, etc, aapp)
+ privAppAllowlist := newApexFile(ctx, allowlist.Path(), commonInfo.BaseModuleName+"_privapp", dirInApex, etc, module)
apexFiles = append(apexFiles, privAppAllowlist)
}
@@ -1615,29 +1569,24 @@
return apexFiles
}
-func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile {
+func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, module android.Module, rro java.RuntimeResourceOverlayInfo) apexFile {
rroDir := "overlay"
- dirInApex := filepath.Join(rroDir, rro.Theme())
- fileToCopy := rro.OutputFile()
- af := newApexFile(ctx, fileToCopy, rro.Name(), dirInApex, app, rro)
- af.certificate = rro.Certificate()
+ dirInApex := filepath.Join(rroDir, rro.Theme)
+ fileToCopy := rro.OutputFile
+ af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, app, module)
+ af.certificate = rro.Certificate
- if a, ok := rro.(interface {
- OverriddenManifestPackageName() string
- }); ok {
- af.overriddenPackageName = a.OverriddenManifestPackageName()
- }
return af
}
-func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile {
+func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram android.Module) apexFile {
dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
}
-func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile {
+func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, module android.Module) apexFile {
dirInApex := filepath.Join("etc", "fs")
- return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs)
+ return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, module)
}
// WalkPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the
@@ -1645,36 +1594,8 @@
// to the child modules. Returning false makes the visit to continue in the sibling or the parent
// modules. This is used in check* functions below.
func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
- ctx.WalkDeps(func(child, parent android.Module) bool {
- am, ok := child.(android.ApexModule)
- if !ok || !am.CanHaveApexVariants() {
- return false
- }
-
- // Filter-out unwanted depedendencies
- depTag := ctx.OtherModuleDependencyTag(child)
- if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
- return false
- }
- 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)
-
- // Visit actually
- return do(ctx, parent, am, externalDep)
- })
-}
-
-func (a *apexBundle) WalkPayloadDepsProxy(ctx android.BaseModuleContext,
- do func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool) {
ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
- if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).CanHaveApexVariants {
+ if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).CanHaveApexVariants {
return false
}
// Filter-out unwanted depedendencies
@@ -1689,8 +1610,7 @@
return false
}
- ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
+ externalDep := !android.IsDepInSameApex(ctx, parent, child)
// Visit actually
return do(ctx, parent, child, externalDep)
@@ -1888,11 +1808,12 @@
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
return false
}
- if !child.Enabled(ctx) {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider)
+ if !commonInfo.Enabled {
return false
}
depName := ctx.OtherModuleName(child)
- if _, isDirectDep := parent.(*apexBundle); isDirectDep {
+ if android.EqualModules(parent, ctx.Module()) {
switch depTag {
case sharedLibTag, jniLibTag:
isJniLib := depTag == jniLibTag
@@ -1900,58 +1821,54 @@
if isJniLib {
propertyName = "jni_libs"
}
- switch ch := child.(type) {
- case *cc.Module:
- if ch.IsStubs() {
+
+ if ch, ok := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider); ok {
+ if ch.IsStubs {
ctx.PropertyErrorf(propertyName, "%q is a stub. Remove it from the list.", depName)
}
- fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
+ fi := apexFileForNativeLibrary(ctx, child, commonInfo, ch, vctx.handleSpecialLibs)
fi.isJniLib = isJniLib
vctx.filesInfo = append(vctx.filesInfo, fi)
// Collect the list of stub-providing libs except:
// - VNDK libs are only for vendors
// - bootstrap bionic libs are treated as provided by system
- if ch.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(ch.BaseModuleName(), ctx.Config()) {
+ if ch.HasStubsVariants && !a.vndkApex && !cc.InstallToBootstrap(commonInfo.BaseModuleName, ctx.Config()) {
vctx.provideNativeLibs = append(vctx.provideNativeLibs, fi.stem())
}
return true // track transitive dependencies
- case *rust.Module:
- fi := apexFileForRustLibrary(ctx, ch)
- fi.isJniLib = isJniLib
- vctx.filesInfo = append(vctx.filesInfo, fi)
- return true // track transitive dependencies
- default:
- ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
+ } else {
+ ctx.PropertyErrorf(propertyName,
+ "%q is not a VersionLinkableInterface (e.g. cc_library or rust_ffi module)", depName)
}
+
case executableTag:
- switch ch := child.(type) {
- case *cc.Module:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
+ if ccInfo, ok := android.OtherModuleProvider(ctx, child, cc.CcInfoProvider); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, child, commonInfo, ccInfo))
return true // track transitive dependencies
- case *rust.Module:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
+ }
+ if _, ok := android.OtherModuleProvider(ctx, child, rust.RustInfoProvider); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, child, commonInfo))
return true // track transitive dependencies
- default:
+ } else {
ctx.PropertyErrorf("binaries",
"%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName)
}
case shBinaryTag:
- if csh, ok := child.(*sh.ShBinary); ok {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, csh))
+ if csh, ok := android.OtherModuleProvider(ctx, child, sh.ShBinaryInfoProvider); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, child, commonInfo, &csh))
} else {
ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
}
case bcpfTag:
- _, ok := child.(*java.BootclasspathFragmentModule)
+ _, ok := android.OtherModuleProvider(ctx, child, java.BootclasspathFragmentInfoProvider)
if !ok {
ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
return false
}
-
vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...)
return true
case sscpfTag:
- if _, ok := child.(*java.SystemServerClasspathModule); !ok {
+ if _, ok := android.OtherModuleProvider(ctx, child, java.LibraryNameToPartitionInfoProvider); !ok {
ctx.PropertyErrorf("systemserverclasspath_fragments",
"%q is not a systemserverclasspath_fragment module", depName)
return false
@@ -1961,98 +1878,104 @@
}
return true
case javaLibTag:
- switch child.(type) {
- case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
- af := apexFileForJavaModule(ctx, child.(javaModule))
+ if ctx.OtherModuleHasProvider(child, java.JavaLibraryInfoProvider) ||
+ ctx.OtherModuleHasProvider(child, java.JavaDexImportInfoProvider) ||
+ ctx.OtherModuleHasProvider(child, java.SdkLibraryInfoProvider) {
+ javaInfo := android.OtherModuleProviderOrDefault(ctx, child, java.JavaInfoProvider)
+ af := apexFileForJavaModule(ctx, child, javaInfo)
if !af.ok() {
ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
return true // track transitive dependencies
- default:
+ } else {
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
case androidAppTag:
- switch ap := child.(type) {
- case *java.AndroidApp:
- vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
- return true // track transitive dependencies
- case *java.AndroidAppImport:
- vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
- case *java.AndroidTestHelperApp:
- vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
- case *java.AndroidAppSet:
- appDir := "app"
- if ap.Privileged() {
- appDir = "priv-app"
+ if appInfo, ok := android.OtherModuleProvider(ctx, child, java.AppInfoProvider); ok {
+ a.appInfos = append(a.appInfos, *appInfo)
+ if appInfo.AppSet {
+ appDir := "app"
+ if appInfo.Privileged {
+ appDir = "priv-app"
+ }
+ // TODO(b/224589412, b/226559955): Ensure that the dirname is
+ // suffixed so that PackageManager correctly invalidates the
+ // existing installed apk in favour of the new APK-in-APEX.
+ // See bugs for more information.
+ appDirName := filepath.Join(appDir, commonInfo.BaseModuleName+"@"+sanitizedBuildIdForPath(ctx))
+ af := newApexFile(ctx, appInfo.OutputFile, commonInfo.BaseModuleName, appDirName, appSet, child)
+ af.certificate = java.PresignedCertificate
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ } else {
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, child, commonInfo, appInfo)...)
+ if !appInfo.Prebuilt && !appInfo.TestHelperApp {
+ return true // track transitive dependencies
+ }
}
- // TODO(b/224589412, b/226559955): Ensure that the dirname is
- // suffixed so that PackageManager correctly invalidates the
- // existing installed apk in favour of the new APK-in-APEX.
- // See bugs for more information.
- appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx))
- af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
- af.certificate = java.PresignedCertificate
- vctx.filesInfo = append(vctx.filesInfo, af)
- default:
+ } else {
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
case rroTag:
- if rro, ok := child.(java.RuntimeResourceOverlayModule); ok {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro))
+ if rro, ok := android.OtherModuleProvider(ctx, child, java.RuntimeResourceOverlayInfoProvider); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, child, rro))
} else {
ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
}
case bpfTag:
- if bpfProgram, ok := child.(bpf.BpfModule); ok {
- filesToCopy := android.OutputFilesForModule(ctx, bpfProgram, "")
- apex_sub_dir := bpfProgram.SubDir()
+ if bpfProgram, ok := android.OtherModuleProvider(ctx, child, bpf.BpfInfoProvider); ok {
+ filesToCopy := android.OutputFilesForModule(ctx, child, "")
+ apex_sub_dir := bpfProgram.SubDir
for _, bpfFile := range filesToCopy {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, child))
}
} else {
ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
}
case fsTag:
- if fs, ok := child.(filesystem.Filesystem); ok {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
+ if fs, ok := android.OtherModuleProvider(ctx, child, filesystem.FilesystemProvider); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.Output, child))
} else {
ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
}
case prebuiltTag:
- if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
- filesToCopy := android.OutputFilesForModule(ctx, prebuilt, "")
+ if prebuilt, ok := android.OtherModuleProvider(ctx, child, prebuilt_etc.PrebuiltEtcInfoProvider); ok {
+ filesToCopy := android.OutputFilesForModule(ctx, child, "")
for _, etcFile := range filesToCopy {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, child, &prebuilt, etcFile))
}
} else {
ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
}
case compatConfigTag:
- if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
+ if compatConfig, ok := android.OtherModuleProvider(ctx, child, java.PlatformCompatConfigInfoProvider); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, child, &compatConfig, depName))
} else {
ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName)
}
case testTag:
- if ccTest, ok := child.(*cc.Module); ok {
- af := apexFileForExecutable(ctx, ccTest)
- af.class = nativeTest
+ if ccInfo, ok := android.OtherModuleProvider(ctx, child, cc.CcInfoProvider); ok {
+ af := apexFileForExecutable(ctx, child, commonInfo, ccInfo)
+ // We make this a nativeExecutable instead of a nativeTest because we don't want
+ // the androidmk modules generated in AndroidMkForFiles to be treated as real
+ // tests that are then packaged into suites. Our AndroidMkForFiles does not
+ // implement enough functionality to support real tests.
+ af.class = nativeExecutable
vctx.filesInfo = append(vctx.filesInfo, af)
return true // track transitive dependencies
} else {
ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
}
case keyTag:
- if key, ok := child.(*apexKey); ok {
- a.privateKeyFile = key.privateKeyFile
- a.publicKeyFile = key.publicKeyFile
+ if key, ok := android.OtherModuleProvider(ctx, child, ApexKeyInfoProvider); ok {
+ a.privateKeyFile = key.PrivateKeyFile
+ a.publicKeyFile = key.PublicKeyFile
} else {
ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
}
case certificateTag:
- if dep, ok := child.(*java.AndroidAppCertificate); ok {
+ if dep, ok := android.OtherModuleProvider(ctx, child, java.AndroidAppCertificateInfoProvider); ok {
a.containerCertificateFile = dep.Certificate.Pem
a.containerPrivateKeyFile = dep.Certificate.Key
} else {
@@ -2067,18 +1990,17 @@
}
// indirect dependencies
- am, ok := child.(android.ApexModule)
- if !ok {
+ if !commonInfo.IsApexModule {
return false
}
// We cannot use a switch statement on `depTag` here as the checked
// tags used below are private (e.g. `cc.sharedDepTag`).
if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
- if ch, ok := child.(*cc.Module); ok {
- af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
+ if ch, ok := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider); ok {
+ af := apexFileForNativeLibrary(ctx, child, commonInfo, ch, vctx.handleSpecialLibs)
af.transitiveDep = true
- if ch.IsStubs() || ch.HasStubsVariants() {
+ if ch.IsStubs || ch.HasStubsVariants {
// If the dependency is a stubs lib, don't include it in this APEX,
// but make sure that the lib is installed on the device.
// In case no APEX is having the lib, the lib is installed to the system
@@ -2089,9 +2011,10 @@
//
// Skip the dependency in unbundled builds where the device image is not
// being built.
- if ch.IsStubsImplementationRequired() && !am.NotInPlatform() && !ctx.Config().UnbundledBuild() {
+ if ch.IsStubsImplementationRequired &&
+ !commonInfo.NotInPlatform && !ctx.Config().UnbundledBuild() {
// we need a module name for Make
- name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName
+ name := ch.ImplementationModuleNameForMake + ch.SubName
if !android.InList(name, a.makeModulesToInstall) {
a.makeModulesToInstall = append(a.makeModulesToInstall, name)
}
@@ -2110,43 +2033,33 @@
// like to record requiredNativeLibs even when
// DepIsInSameAPex is false. We also shouldn't do
// this for host.
- //
- // TODO(jiyong): explain why the same module is passed in twice.
- // Switching the first am to parent breaks lots of tests.
- if !android.IsDepInSameApex(ctx, am, am) {
+ if !android.IsDepInSameApex(ctx, parent, child) {
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
return true // track transitive dependencies
- } else if rm, ok := child.(*rust.Module); ok {
- if !android.IsDepInSameApex(ctx, am, am) {
- return false
- }
-
- af := apexFileForRustLibrary(ctx, rm)
- af.transitiveDep = true
- vctx.filesInfo = append(vctx.filesInfo, af)
- return true // track transitive dependencies
}
} else if cc.IsHeaderDepTag(depTag) {
// nothing
} else if java.IsJniDepTag(depTag) {
// 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 {
- filesToCopy := android.OutputFilesForModule(ctx, prebuilt, "")
+ if prebuilt, ok := android.OtherModuleProvider(ctx, child, prebuilt_etc.PrebuiltEtcInfoProvider); ok {
+ filesToCopy := android.OutputFilesForModule(ctx, child, "")
for _, etcFile := range filesToCopy {
- vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, child, &prebuilt, etcFile))
}
}
} else if rust.IsDylibDepTag(depTag) {
- if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
- if !android.IsDepInSameApex(ctx, am, am) {
+ if _, ok := android.OtherModuleProvider(ctx, child, rust.RustInfoProvider); ok &&
+ commonInfo.IsInstallableToApex {
+ if !android.IsDepInSameApex(ctx, parent, child) {
return false
}
- af := apexFileForRustLibrary(ctx, rustm)
+ linkableInfo := android.OtherModuleProviderOrDefault(ctx, child, cc.LinkableInfoProvider)
+ af := apexFileForNativeLibrary(ctx, child, commonInfo, linkableInfo, vctx.handleSpecialLibs)
af.transitiveDep = true
vctx.filesInfo = append(vctx.filesInfo, af)
return true // track transitive dependencies
@@ -2157,10 +2070,9 @@
return true
} else if java.IsBootclasspathFragmentContentDepTag(depTag) {
// Add the contents of the bootclasspath fragment to the apex.
- switch child.(type) {
- case *java.Library, *java.SdkLibrary:
- javaModule := child.(javaModule)
- af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule)
+ if ctx.OtherModuleHasProvider(child, java.JavaLibraryInfoProvider) ||
+ ctx.OtherModuleHasProvider(child, java.SdkLibraryInfoProvider) {
+ af := apexFileForBootclasspathFragmentContentModule(ctx, parent, child)
if !af.ok() {
ctx.PropertyErrorf("bootclasspath_fragments",
"bootclasspath_fragment content %q is not configured to be compiled into dex", depName)
@@ -2168,21 +2080,22 @@
}
vctx.filesInfo = append(vctx.filesInfo, af)
return true // track transitive dependencies
- default:
+ } else {
ctx.PropertyErrorf("bootclasspath_fragments",
"bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
} else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
// Add the contents of the systemserverclasspath fragment to the apex.
- switch child.(type) {
- case *java.Library, *java.SdkLibrary:
- af := apexFileForJavaModule(ctx, child.(javaModule))
+ if ctx.OtherModuleHasProvider(child, java.JavaLibraryInfoProvider) ||
+ ctx.OtherModuleHasProvider(child, java.SdkLibraryInfoProvider) {
+ javaInfo := android.OtherModuleProviderOrDefault(ctx, child, java.JavaInfoProvider)
+ af := apexFileForJavaModule(ctx, child, javaInfo)
vctx.filesInfo = append(vctx.filesInfo, af)
- if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil {
+ if profileAf := apexFileForJavaModuleProfile(ctx, commonInfo, javaInfo); profileAf != nil {
vctx.filesInfo = append(vctx.filesInfo, *profileAf)
}
return true // track transitive dependencies
- default:
+ } else {
ctx.PropertyErrorf("systemserverclasspath_fragments",
"systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
}
@@ -2190,9 +2103,15 @@
// nothing
} else if depTag == android.RequiredDepTag {
// nothing
- } else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
+ } else if commonInfo.IsInstallableToApex {
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
+ } else if android.IsVintfDepTag(depTag) {
+ if vf, ok := android.OtherModuleProvider(ctx, child, android.VintfFragmentInfoProvider); ok {
+ apexFile := apexFileForVintfFragment(ctx, child, commonInfo, &vf)
+ vctx.filesInfo = append(vctx.filesInfo, apexFile)
+ }
}
+
return false
}
@@ -2291,6 +2210,7 @@
////////////////////////////////////////////////////////////////////////////////////////////
// 4) generate the build rules to create the APEX. This is done in builder.go.
a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs)
+ a.installApexSystemServerFiles(ctx)
a.buildApex(ctx)
a.buildApexDependencyInfo(ctx)
a.buildLintReports(ctx)
@@ -2307,6 +2227,16 @@
a.enforcePartitionTagOnApexSystemServerJar(ctx)
a.verifyNativeImplementationLibs(ctx)
+ a.enforceNoVintfInUpdatable(ctx)
+
+ android.SetProvider(ctx, android.ApexBundleDepsDataProvider, android.ApexBundleDepsData{
+ FlatListPath: a.FlatListPath(),
+ Updatable: a.Updatable(),
+ })
+
+ android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{a.apexKeysPath})
+
+ android.SetProvider(ctx, java.AppInfosProvider, a.appInfos)
}
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
@@ -2356,8 +2286,8 @@
// checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
mctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
if appInfo, ok := android.OtherModuleProvider(mctx, module, java.AppInfoProvider); ok {
- // ignore android_test_app
- if !appInfo.TestHelperApp && !appInfo.Updatable {
+ // ignore android_test_app and android_app_import
+ if !appInfo.TestHelperApp && !appInfo.Prebuilt && !appInfo.Updatable {
mctx.ModuleErrorf("app dependency %s must have updatable: true", mctx.OtherModuleName(module))
}
}
@@ -2367,7 +2297,7 @@
// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
// the bootclasspath_fragment contributes to the apex.
-func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile {
+func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module android.Module) []apexFile {
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, module, java.BootclasspathFragmentApexContentInfoProvider)
var filesToAdd []apexFile
@@ -2416,7 +2346,7 @@
// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that
// the module contributes to the apex; or nil if the proto config was not generated.
-func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile {
+func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module android.Module) *apexFile {
info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
if !info.ClasspathFragmentProtoGenerated {
return nil
@@ -2428,7 +2358,7 @@
// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
// content module, i.e. a library that is part of the bootclasspath.
-func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile {
+func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule, javaModule android.Module) apexFile {
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragmentModule, java.BootclasspathFragmentApexContentInfoProvider)
// Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
@@ -2440,7 +2370,8 @@
// Create an apexFile as for a normal java module but with the dex boot jar provided by the
// bootclasspath_fragment.
- af := apexFileForJavaModuleWithFile(ctx, javaModule, dexBootJar)
+ javaInfo := android.OtherModuleProviderOrDefault(ctx, javaModule, java.JavaInfoProvider)
+ af := apexFileForJavaModuleWithFile(ctx, javaModule, javaInfo, dexBootJar)
return af
}
@@ -2550,7 +2481,7 @@
}
// Returns apex's min_sdk_version string value, honoring overrides
-func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string {
+func (a *apexBundle) minSdkVersionValue(ctx android.MinSdkVersionFromValueContext) string {
// Only override the minSdkVersion value on Apexes which already specify
// a min_sdk_version (it's optional for non-updatable apexes), and that its
// min_sdk_version value is lower than the one to override with.
@@ -2574,7 +2505,7 @@
}
// Returns apex's min_sdk_version ApiLevel, honoring overrides
-func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (a *apexBundle) minSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel {
return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
}
@@ -2590,8 +2521,8 @@
librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true
})
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
- if ccInfo, ok := android.OtherModuleProvider(ctx, to, cc.CcInfoProvider); ok {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ if info, ok := android.OtherModuleProvider(ctx, to, cc.LinkableInfoProvider); ok {
// If `to` is not actually in the same APEX as `from` then it does not need
// apex_available and neither do any of its dependencies.
if externalDep {
@@ -2603,7 +2534,7 @@
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
- // The dynamic linker and crash_dump tool in the runtime APEX is the only
+ // The dynamic linker and crash_dump tool in the runtime APEX is an
// exception to this rule. It can't make the static dependencies dynamic
// because it can't do the dynamic linking for itself.
// Same rule should be applied to linkerconfig, because it should be executed
@@ -2612,7 +2543,16 @@
return false
}
- isStubLibraryFromOtherApex := ccInfo.HasStubsVariants && !librariesDirectlyInApex[toName]
+ // b/389067742 adds libz as an exception to this check. Although libz is
+ // a part of NDK and thus provides a stable interface, it never was the
+ // intention because the upstream zlib provides neither ABI- nor behavior-
+ // stability. Therefore, we want to allow portable components like APEXes to
+ // bundle libz by statically linking to it.
+ if toName == "libz" {
+ return false
+ }
+
+ isStubLibraryFromOtherApex := info.HasStubsVariants && !librariesDirectlyInApex[toName]
if isStubLibraryFromOtherApex && !externalDep {
ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+
"It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false))
@@ -2695,7 +2635,7 @@
return
}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
if externalDep {
return false
@@ -2712,17 +2652,8 @@
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
- // If `to` is not actually in the same APEX as `from` then it does not need
- // apex_available and neither do any of its dependencies.
- //
- // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
- if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
- // As soon as the dependency graph crosses the APEX boundary, don't go
- // further.
- return false
- }
-
- if to.AvailableFor(apexName) {
+ if android.CheckAvailableForApex(apexName,
+ android.OtherModuleProviderOrDefault(ctx, to, android.ApexAvailableInfoProvider).ApexAvailableFor) {
return true
}
@@ -2752,7 +2683,7 @@
return
}
- if android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoKey).StaticExecutable {
+ if android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoProvider).StaticExecutable {
apex := a.ApexVariationName()
exec := ctx.OtherModuleName(module)
if isStaticExecutableAllowed(apex, exec) {
@@ -2927,14 +2858,14 @@
if !inApex && !inApkInApex {
ctx.ModuleErrorf("library in apex transitively linked against implementation library %q not in apex", lib)
var depPath []android.Module
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
if depPath != nil {
return false
}
tag := ctx.OtherModuleDependencyTag(child)
- if parent == ctx.Module() {
+ if android.EqualModules(parent, ctx.Module()) {
if !checkApexTag(tag) {
return false
}
@@ -2959,3 +2890,16 @@
}
}
}
+
+// TODO(b/399527905) libvintf is not forward compatible.
+func (a *apexBundle) enforceNoVintfInUpdatable(ctx android.ModuleContext) {
+ if !a.Updatable() {
+ return
+ }
+ for _, fi := range a.filesInfo {
+ if match, _ := path.Match("etc/vintf/*", fi.path()); match {
+ ctx.ModuleErrorf("VINTF fragment (%s) is not supported in updatable APEX.", fi.path())
+ break
+ }
+ }
+}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index d46104e..797f47b 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -59,9 +59,9 @@
// Diff two given lists while ignoring comments in the allowed deps file.
diffAllowedApexDepsInfoRule = pctx.AndroidStaticRule("diffAllowedApexDepsInfoRule", blueprint.RuleParams{
- Description: "Diff ${allowed_deps_list} and ${new_allowed_deps}",
+ Description: "Diff ${allowed_deps} and ${new_allowed_deps}",
Command: `
- if grep -v -h '^#' ${allowed_deps_list} | sort -u -f| diff -B -u - ${new_allowed_deps}; then
+ if grep -v '^#' ${allowed_deps} | diff -B - ${new_allowed_deps}; then
touch ${out};
else
echo;
@@ -85,62 +85,54 @@
exit 1;
fi;
`,
- }, "allowed_deps_list", "new_allowed_deps")
+ }, "allowed_deps", "new_allowed_deps")
)
func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- allowedDepsSources := []android.OptionalPath{android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")}
- extraAllowedDepsPath := ctx.Config().ExtraAllowedDepsTxt()
- if extraAllowedDepsPath != "" {
- allowedDepsSources = append(allowedDepsSources, android.ExistentPathForSource(ctx, extraAllowedDepsPath))
- }
updatableFlatLists := android.Paths{}
- ctx.VisitAllModules(func(module android.Module) {
- if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if binaryInfo, ok := android.OtherModuleProvider(ctx, module, android.ApexBundleDepsDataProvider); ok {
apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
- if path := binaryInfo.FlatListPath(); path != nil {
- if binaryInfo.Updatable() || apexInfo.Updatable {
- updatableFlatLists = append(updatableFlatLists, path)
+ if path := binaryInfo.FlatListPath; path != nil {
+ if binaryInfo.Updatable || apexInfo.Updatable {
+ if strings.HasPrefix(module.String(), "com.android.") {
+ updatableFlatLists = append(updatableFlatLists, path)
+ }
}
}
}
})
+
+ allowedDepsSource := android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")
newAllowedDeps := android.PathForOutput(ctx, "apex", "depsinfo", "new-allowed-deps.txt")
s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check")
- hasOneValidDepsPath := false
- for _, allowedDepsSource := range allowedDepsSources {
- if allowedDepsSource.Valid() {
- hasOneValidDepsPath = true
- updatableFlatLists = append(updatableFlatLists, allowedDepsSource.Path())
- }
- }
- allowedDepsStrList := make([]string, len(allowedDepsSources))
- for _, value := range allowedDepsSources {
- allowedDepsStrList = append(allowedDepsStrList, value.String())
- }
- allowedDepsListString := strings.Join(allowedDepsStrList, " ")
- if !hasOneValidDepsPath {
+
+ if !allowedDepsSource.Valid() {
// Unbundled projects may not have packages/modules/common/ checked out; ignore those.
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
Output: s.allowedApexDepsInfoCheckResult,
})
} else {
+ allowedDeps := allowedDepsSource.Path()
+
ctx.Build(pctx, android.BuildParams{
Rule: generateApexDepsInfoFilesRule,
- Inputs: updatableFlatLists,
+ Inputs: append(updatableFlatLists, allowedDeps),
Output: newAllowedDeps,
})
+
ctx.Build(pctx, android.BuildParams{
Rule: diffAllowedApexDepsInfoRule,
Input: newAllowedDeps,
Output: s.allowedApexDepsInfoCheckResult,
Args: map[string]string{
- "allowed_deps_list": allowedDepsListString,
- "new_allowed_deps": newAllowedDeps.String(),
+ "allowed_deps": allowedDeps.String(),
+ "new_allowed_deps": newAllowedDeps.String(),
},
})
}
+
ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult)
}
@@ -168,11 +160,11 @@
func (a *apexPrebuiltInfo) GenerateBuildActions(ctx android.SingletonContext) {
prebuiltInfos := []android.PrebuiltInfo{}
- ctx.VisitAllModules(func(m android.Module) {
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
prebuiltInfo, exists := android.OtherModuleProvider(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() {
+ if exists && !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).HideFromMake {
prebuiltInfos = append(prebuiltInfos, prebuiltInfo)
}
})
@@ -183,8 +175,5 @@
}
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 dd55152..327e018 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -20,7 +20,6 @@
"path/filepath"
"reflect"
"regexp"
- "slices"
"sort"
"strconv"
"strings"
@@ -29,7 +28,6 @@
"android/soong/aconfig/codegen"
"github.com/google/blueprint"
- "github.com/google/blueprint/bpmodify"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -507,10 +505,10 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
// Make sure that Android.mk is created
- ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, ab)
var builder strings.Builder
data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
@@ -587,14 +585,14 @@
}
fullDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex", "android_common_myapex").Output("depsinfo/fulllist.txt")), "\n")
+ ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("depsinfo/fulllist.txt")), "\n")
ensureListContains(t, fullDepsInfo, " myjar(minSdkVersion:(no version)) <- myapex")
ensureListContains(t, fullDepsInfo, " mylib2(minSdkVersion:(no version)) <- mylib")
ensureListContains(t, fullDepsInfo, " myotherjar(minSdkVersion:(no version)) <- myjar")
ensureListContains(t, fullDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
flatDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex", "android_common_myapex").Output("depsinfo/flatlist.txt")), "\n")
+ ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("depsinfo/flatlist.txt")), "\n")
ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))")
@@ -701,7 +699,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
args := module.Rule("apexRule").Args
if manifest := args["manifest"]; manifest != module.Output("apex_manifest.pb").Output.String() {
t.Error("manifest should be apex_manifest.pb, but " + manifest)
@@ -773,7 +771,7 @@
},
}
for _, tc := range testCases {
- module := ctx.ModuleForTests(tc.module, "android_common_"+tc.module)
+ module := ctx.ModuleForTests(t, tc.module, "android_common_"+tc.module)
args := module.Rule("apexRule").Args
optFlags := args["opt_flags"]
if !strings.Contains(optFlags, "--min_sdk_version "+tc.minSdkVersion) {
@@ -847,7 +845,7 @@
},
}
for _, tc := range testCases {
- module := ctx.ModuleForTests(tc.module, "android_common_"+tc.module)
+ module := ctx.ModuleForTests(t, tc.module, "android_common_"+tc.module)
args := module.Rule("apexRule").Args
optFlags := args["opt_flags"]
if !strings.Contains(optFlags, "--min_sdk_version "+tc.minSdkVersion) {
@@ -878,7 +876,7 @@
}
`)
- rule := ctx.ModuleForTests("myapex", "android_common_myapex").Output("file_contexts")
+ rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("file_contexts")
if vendor {
android.AssertStringDoesContain(t, "should force-label as vendor_apex_metadata_file",
rule.RuleParams.Command,
@@ -897,7 +895,11 @@
apex {
name: "myapex",
key: "myapex.key",
- native_shared_libs: ["mylib", "mylib3"],
+ native_shared_libs: [
+ "mylib",
+ "mylib3",
+ "libmylib3_rs",
+ ],
binaries: ["foo.rust"],
updatable: false,
}
@@ -911,7 +913,14 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
- shared_libs: ["mylib2", "mylib3#impl", "my_prebuilt_platform_lib", "my_prebuilt_platform_stub_only_lib"],
+ shared_libs: [
+ "mylib2",
+ "mylib3#impl",
+ "libmylib2_rs",
+ "libmylib3_rs#impl",
+ "my_prebuilt_platform_lib",
+ "my_prebuilt_platform_stub_only_lib",
+ ],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
@@ -929,6 +938,16 @@
},
}
+ rust_ffi {
+ name: "libmylib2_rs",
+ crate_name: "mylib2",
+ srcs: ["mylib.rs"],
+ stubs: {
+ symbol_file: "mylib2.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+
cc_library {
name: "mylib3",
srcs: ["mylib.cpp"],
@@ -942,6 +961,18 @@
apex_available: [ "myapex" ],
}
+ rust_ffi {
+ name: "libmylib3_rs",
+ crate_name: "mylib3",
+ srcs: ["mylib.rs"],
+ shared_libs: ["mylib4.from_rust"],
+ stubs: {
+ symbol_file: "mylib3.map.txt",
+ versions: ["10", "11", "12"],
+ },
+ apex_available: [ "myapex" ],
+ }
+
cc_library {
name: "mylib4",
srcs: ["mylib.cpp"],
@@ -950,6 +981,14 @@
apex_available: [ "myapex" ],
}
+ cc_library {
+ name: "mylib4.from_rust",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
cc_prebuilt_library_shared {
name: "my_prebuilt_platform_lib",
stubs: {
@@ -971,7 +1010,10 @@
rust_binary {
name: "foo.rust",
srcs: ["foo.rs"],
- shared_libs: ["libfoo.shared_from_rust"],
+ shared_libs: [
+ "libfoo.shared_from_rust",
+ "libfoo_rs.shared_from_rust",
+ ],
prefer_rlib: true,
apex_available: ["myapex"],
}
@@ -986,9 +1028,18 @@
},
}
+ rust_ffi {
+ name: "libfoo_rs.shared_from_rust",
+ crate_name: "foo_rs",
+ srcs: ["mylib.rs"],
+ stubs: {
+ versions: ["10", "11", "12"],
+ },
+ }
+
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -996,21 +1047,27 @@
// Ensure that indirect stubs dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib2_rs.so")
// Ensure that direct stubs dep is included
ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libmylib3_rs.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with the latest version of stubs for mylib2
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
+ ensureContains(t, mylibLdFlags, "libmylib2_rs/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rs.so")
// ... and not linking to the non-stub (impl) variant of mylib2
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
+ ensureNotContains(t, mylibLdFlags, "libmylib2_rs/android_arm64_armv8-a_shared/unstripped/libmylib2_rs.so")
// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because the dependency is added with mylib3#impl)
ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex10000/mylib3.so")
+ ensureContains(t, mylibLdFlags, "libmylib3_rs/android_arm64_armv8-a_shared_apex10000/unstripped/libmylib3_rs.so")
// .. and not linking to the stubs variant of mylib3
ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12/mylib3.so")
+ ensureNotContains(t, mylibLdFlags, "libmylib3_rs/android_arm64_armv8-a_shared_12/unstripped/mylib3.so")
// Comment out this test. Now it fails after the optimization of sharing "cflags" in cc/cc.go
// is replaced by sharing of "cFlags" in cc/builder.go.
@@ -1021,46 +1078,54 @@
// including the original cflags's "-include mylib.h".
//
// Ensure that stubs libs are built without -include flags
- // mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ // mylib2Cflags := ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
// ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub for platform-provided lib is invoked with --systemapi
- ensureContains(t, ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
+ ensureContains(t, ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
+ ensureContains(t, ctx.ModuleForTests(t, "libmylib2_rs", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
// Ensure that genstub for apex-provided lib is invoked with --apex
- ensureContains(t, ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_shared_12").Rule("genStubSrc").Args["flags"], "--apex")
+ ensureContains(t, ctx.ModuleForTests(t, "mylib3", "android_arm64_armv8-a_shared_12").Rule("genStubSrc").Args["flags"], "--apex")
+ ensureContains(t, ctx.ModuleForTests(t, "libmylib3_rs", "android_arm64_armv8-a_shared_12").Rule("genStubSrc").Args["flags"], "--apex")
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"lib64/mylib.so",
"lib64/mylib3.so",
+ "lib64/libmylib3_rs.so",
"lib64/mylib4.so",
+ "lib64/mylib4.from_rust.so",
"bin/foo.rust",
- "lib64/libc++.so", // by the implicit dependency from foo.rust
- "lib64/liblog.so", // by the implicit dependency from foo.rust
+
+ "lib64/libstd.dylib.so", // implicit rust ffi dep
})
// Ensure that stub dependency from a rust module is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo_rs.shared_from_rust.so")
// The rust module is linked to the stub cc library
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
+ rustDeps := ctx.ModuleForTests(t, "foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
+ ensureContains(t, rustDeps, "libfoo_rs.shared_from_rust/android_arm64_armv8-a_shared_current/unstripped/libfoo_rs.shared_from_rust.so")
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
+ ensureNotContains(t, rustDeps, "libfoo_rs.shared_from_rust/android_arm64_armv8-a_shared/unstripped/libfoo_rs.shared_from_rust.so")
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
+ ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo_rs.shared_from_rust.so")
// Ensure that mylib is linking with the latest version of stubs for my_prebuilt_platform_lib
ensureContains(t, mylibLdFlags, "my_prebuilt_platform_lib/android_arm64_armv8-a_shared_current/my_prebuilt_platform_lib.so")
// ... and not linking to the non-stub (impl) variant of my_prebuilt_platform_lib
ensureNotContains(t, mylibLdFlags, "my_prebuilt_platform_lib/android_arm64_armv8-a_shared/my_prebuilt_platform_lib.so")
// Ensure that genstub for platform-provided lib is invoked with --systemapi
- ensureContains(t, ctx.ModuleForTests("my_prebuilt_platform_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
+ ensureContains(t, ctx.ModuleForTests(t, "my_prebuilt_platform_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
// Ensure that mylib is linking with the latest version of stubs for my_prebuilt_platform_lib
ensureContains(t, mylibLdFlags, "my_prebuilt_platform_stub_only_lib/android_arm64_armv8-a_shared_current/my_prebuilt_platform_stub_only_lib.so")
// ... and not linking to the non-stub (impl) variant of my_prebuilt_platform_lib
ensureNotContains(t, mylibLdFlags, "my_prebuilt_platform_stub_only_lib/android_arm64_armv8-a_shared/my_prebuilt_platform_stub_only_lib.so")
// Ensure that genstub for platform-provided lib is invoked with --systemapi
- ensureContains(t, ctx.ModuleForTests("my_prebuilt_platform_stub_only_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
+ ensureContains(t, ctx.ModuleForTests(t, "my_prebuilt_platform_stub_only_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
}
func TestApexShouldNotEmbedStubVariant(t *testing.T) {
@@ -1111,7 +1176,10 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
- shared_libs: ["mylib2"],
+ shared_libs: [
+ "mylib2",
+ "libmylib2_rust"
+ ],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
@@ -1128,10 +1196,22 @@
},
}
+ rust_ffi {
+ name: "libmylib2_rust",
+ crate_name: "mylib2_rust",
+ srcs: ["mylib.rs"],
+ stubs: {
+ versions: ["1", "2", "3"],
+ },
+ }
+
rust_binary {
name: "foo.rust",
srcs: ["foo.rs"],
- shared_libs: ["libfoo.shared_from_rust"],
+ shared_libs: [
+ "libfoo.shared_from_rust",
+ "libmylib_rust.shared_from_rust"
+ ],
prefer_rlib: true,
apex_available: ["myapex"],
}
@@ -1145,23 +1225,38 @@
versions: ["10", "11", "12"],
},
}
+ rust_ffi {
+ name: "libmylib_rust.shared_from_rust",
+ crate_name: "mylib_rust",
+ srcs: ["mylib.rs"],
+ stubs: {
+ versions: ["1", "2", "3"],
+ },
+ }
+
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that indirect stubs dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib_rust.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib_rust.shared_from_rust.so")
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
// Ensure that we are using non-stub variants of mylib2 and libfoo.shared_from_rust (because
// of the platform_apis: true)
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000_p").Rule("ld").Args["libFlags"]
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
+ ensureNotContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rust.so")
+ ensureContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared/unstripped/libmylib2_rust.so")
+ rustDeps := ctx.ModuleForTests(t, "foo.rust", "android_arm64_armv8-a_apex10000_p").Rule("rustc").Args["linkFlags"]
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
+ ensureNotContains(t, rustDeps, "libmylib_rust.shared_from_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib_rust.shared_from_rust.so")
+ ensureContains(t, rustDeps, "libmylib_rust.shared_from_rust/android_arm64_armv8-a_shared/unstripped/libmylib_rust.shared_from_rust.so")
}
func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
@@ -1170,7 +1265,11 @@
apex {
name: "myapex",
key: "myapex.key",
- native_shared_libs: ["mylib", "mylib3"],
+ native_shared_libs: [
+ "mylib",
+ "mylib3",
+ "libmylib3_rust",
+ ],
min_sdk_version: "29",
}
@@ -1183,7 +1282,12 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
- shared_libs: ["mylib2", "mylib3#impl"],
+ shared_libs: [
+ "mylib2",
+ "mylib3#impl",
+ "libmylib2_rust",
+ "libmylib3_rust#impl",
+ ],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
@@ -1203,6 +1307,17 @@
min_sdk_version: "28",
}
+ rust_ffi {
+ name: "libmylib2_rust",
+ crate_name: "mylib2_rust",
+ srcs: ["mylib.rs"],
+ stubs: {
+ symbol_file: "mylib2.map.txt",
+ versions: ["28", "29", "30", "current"],
+ },
+ min_sdk_version: "28",
+ }
+
cc_library {
name: "mylib3",
srcs: ["mylib.cpp"],
@@ -1217,6 +1332,19 @@
min_sdk_version: "28",
}
+ rust_ffi {
+ name: "libmylib3_rust",
+ crate_name: "mylib3_rust",
+ srcs: ["mylib.rs"],
+ shared_libs: ["libmylib4.from_rust"],
+ stubs: {
+ symbol_file: "mylib3.map.txt",
+ versions: ["28", "29", "30", "current"],
+ },
+ apex_available: [ "myapex" ],
+ min_sdk_version: "28",
+ }
+
cc_library {
name: "mylib4",
srcs: ["mylib.cpp"],
@@ -1225,43 +1353,63 @@
apex_available: [ "myapex" ],
min_sdk_version: "28",
}
+
+ rust_ffi {
+ name: "libmylib4.from_rust",
+ crate_name: "mylib4",
+ srcs: ["mylib.rs"],
+ apex_available: [ "myapex" ],
+ min_sdk_version: "28",
+ }
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libmylib3_rust.so")
// Ensure that indirect stubs dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib2_rust.so")
// Ensure that direct stubs dep is included
ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with the latest version of stub for mylib2
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
+ ensureContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rust.so")
// ... and not linking to the non-stub (impl) variant of mylib2
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
+ ensureNotContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared/unstripped/libmylib2_rust.so")
// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because the dependency is added with mylib3#impl)
ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex29/mylib3.so")
+ ensureContains(t, mylibLdFlags, "libmylib3_rust/android_arm64_armv8-a_shared_apex29/unstripped/libmylib3_rust.so")
// .. and not linking to the stubs variant of mylib3
ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_29/mylib3.so")
+ ensureNotContains(t, mylibLdFlags, "libmylib3_rust/android_arm64_armv8-a_shared_29/unstripped/libmylib3_rust.so")
// Ensure that stubs libs are built without -include flags
- mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("cc").Args["cFlags"]
+ mylib2Cflags := ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_shared_29").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylib2Cflags, "-include ")
// Ensure that genstub is invoked with --systemapi
- ensureContains(t, ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("genStubSrc").Args["flags"], "--systemapi")
+ ensureContains(t, ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_shared_29").Rule("genStubSrc").Args["flags"], "--systemapi")
+ ensureContains(t, ctx.ModuleForTests(t, "libmylib2_rust", "android_arm64_armv8-a_shared_29").Rule("cc.genStubSrc").Args["flags"], "--systemapi")
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"lib64/mylib.so",
"lib64/mylib3.so",
+ "lib64/libmylib3_rust.so",
"lib64/mylib4.so",
+ "lib64/libmylib4.from_rust.so",
+
+ "lib64/libstd.dylib.so", // by the implicit dependency from foo.rust
})
}
@@ -1286,7 +1434,10 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
- shared_libs: ["libstub"],
+ shared_libs: [
+ "libstub",
+ "libstub_rust",
+ ],
apex_available: ["myapex"],
min_sdk_version: "Z",
}
@@ -1300,7 +1451,10 @@
apex {
name: "otherapex",
key: "myapex.key",
- native_shared_libs: ["libstub"],
+ native_shared_libs: [
+ "libstub",
+ "libstub_rust",
+ ],
min_sdk_version: "29",
}
@@ -1314,11 +1468,25 @@
min_sdk_version: "29",
}
+ rust_ffi {
+ name: "libstub_rust",
+ crate_name: "stub_rust",
+ srcs: ["mylib.rs"],
+ stubs: {
+ versions: ["29", "Z", "current"],
+ },
+ apex_available: ["otherapex"],
+ min_sdk_version: "29",
+ }
+
// platform module depending on libstub from otherapex should use the latest stub("current")
cc_library {
name: "libplatform",
srcs: ["mylib.cpp"],
- shared_libs: ["libstub"],
+ shared_libs: [
+ "libstub",
+ "libstub_rust",
+ ],
}
`,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -1329,16 +1497,22 @@
)
// Ensure that mylib from myapex is built against the latest stub (current)
- mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
+ mylibCflags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=10000 ")
- mylibLdflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ // rust stubs do not emit -D__LIBFOO_API__ flags as this is deprecated behavior for cc stubs
+
+ mylibLdflags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
+ ensureContains(t, mylibLdflags, "libstub_rust/android_arm64_armv8-a_shared_current/unstripped/libstub_rust.so ")
// Ensure that libplatform is built against latest stub ("current") of mylib3 from the apex
- libplatformCflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ libplatformCflags := ctx.ModuleForTests(t, "libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureContains(t, libplatformCflags, "-D__LIBSTUB_API__=10000 ") // "current" maps to 10000
- libplatformLdflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
+ // rust stubs do not emit -D__LIBFOO_API__ flags as this is deprecated behavior for cc stubs
+
+ libplatformLdflags := ctx.ModuleForTests(t, "libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
ensureContains(t, libplatformLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
+ ensureContains(t, libplatformLdflags, "libstub_rust/android_arm64_armv8-a_shared_current/unstripped/libstub_rust.so ")
}
func TestApexWithExplicitStubsDependency(t *testing.T) {
@@ -1360,7 +1534,10 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
- shared_libs: ["libfoo#10"],
+ shared_libs: [
+ "libfoo#10",
+ "libfoo_rust#10"
+ ],
static_libs: ["libbaz"],
system_shared_libs: [],
stl: "none",
@@ -1378,6 +1555,16 @@
},
}
+ rust_ffi {
+ name: "libfoo_rust",
+ crate_name: "foo_rust",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libbar.from_rust"],
+ stubs: {
+ versions: ["10", "20", "30"],
+ },
+ }
+
cc_library {
name: "libbar",
srcs: ["mylib.cpp"],
@@ -1385,6 +1572,13 @@
stl: "none",
}
+ cc_library {
+ name: "libbar.from_rust",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
cc_library_static {
name: "libbaz",
srcs: ["mylib.cpp"],
@@ -1395,7 +1589,7 @@
`)
- apexRule := ctx.ModuleForTests("myapex2", "android_common_myapex2").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex2", "android_common_myapex2").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -1403,28 +1597,34 @@
// Ensure that indirect stubs dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo_rust.so")
// Ensure that dependency of stubs is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.from_rust.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with version 10 of libfoo
ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
+ ensureContains(t, mylibLdFlags, "libfoo_rust/android_arm64_armv8-a_shared_10/unstripped/libfoo_rust.so")
// ... and not linking to the non-stub (impl) variant of libfoo
ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared/libfoo.so")
+ ensureNotContains(t, mylibLdFlags, "libfoo_rust/android_arm64_armv8-a_shared/unstripped/libfoo_rust.so")
- libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
+ libFooStubsLdFlags := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
+ libFooRustStubsLdFlags := ctx.ModuleForTests(t, "libfoo_rust", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
+ ensureNotContains(t, libFooRustStubsLdFlags, "libbar.from_rust.so")
fullDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex2", "android_common_myapex2").Output("depsinfo/fulllist.txt")), "\n")
+ ctx.ModuleForTests(t, "myapex2", "android_common_myapex2").Output("depsinfo/fulllist.txt")), "\n")
ensureListContains(t, fullDepsInfo, " libfoo(minSdkVersion:(no version)) (external) <- mylib")
flatDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex2", "android_common_myapex2").Output("depsinfo/flatlist.txt")), "\n")
+ ctx.ModuleForTests(t, "myapex2", "android_common_myapex2").Output("depsinfo/flatlist.txt")), "\n")
ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)")
}
@@ -1457,7 +1657,11 @@
srcs: ["mylib.cpp"],
static_libs: ["libstatic"],
shared_libs: ["libshared"],
- runtime_libs: ["libfoo", "libbar"],
+ runtime_libs: [
+ "libfoo",
+ "libbar",
+ "libfoo_rs",
+ ],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
@@ -1473,6 +1677,15 @@
},
}
+ rust_ffi {
+ name: "libfoo_rs",
+ crate_name: "foo_rs",
+ srcs: ["mylib.rs"],
+ stubs: {
+ versions: ["10", "20", "30"],
+ },
+ }
+
cc_library {
name: "libbar",
srcs: ["mylib.cpp"],
@@ -1516,7 +1729,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -1524,6 +1737,7 @@
// Ensure that indirect stubs dep is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo_rs.so")
// Ensure that runtime_libs dep in included
ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
@@ -1532,9 +1746,10 @@
ensureNotContains(t, copyCmds, "image.apex/lib64/libstatic_to_runtime.so")
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.so")
+ ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo_rs.so")
}
var prepareForTestOfRuntimeApexWithHwasan = android.GroupFixturePreparers(
@@ -1601,7 +1816,7 @@
"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
})
- hwasan := ctx.ModuleForTests("libclang_rt.hwasan", "android_arm64_armv8-a_shared")
+ hwasan := ctx.ModuleForTests(t, "libclang_rt.hwasan", "android_arm64_armv8-a_shared")
installed := hwasan.Description("install libclang_rt.hwasan")
ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
@@ -1657,7 +1872,7 @@
"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
})
- hwasan := ctx.ModuleForTests("libclang_rt.hwasan", "android_arm64_armv8-a_shared")
+ hwasan := ctx.ModuleForTests(t, "libclang_rt.hwasan", "android_arm64_armv8-a_shared")
installed := hwasan.Description("install libclang_rt.hwasan")
ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
@@ -1740,17 +1955,17 @@
})
// Ensure that LLNDK dep is required
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
+ mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
ensureContains(t, mylibLdFlags, "libbar/android_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
for _, ver := range tc.shouldNotLink {
ensureNotContains(t, mylibLdFlags, "libbar/android_arm64_armv8-a_shared_"+ver+"/libbar.so")
}
- mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
+ mylibCFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
ver := tc.shouldLink
if tc.shouldLink == "current" {
ver = strconv.Itoa(android.FutureApiLevelInt)
@@ -1766,7 +1981,7 @@
apex {
name: "myapex",
key: "myapex.key",
- native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
+ native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm", "libmylib_rs"],
updatable: false,
}
@@ -1785,6 +2000,14 @@
apex_available: [ "myapex" ],
}
+ rust_ffi {
+ name: "libmylib_rs",
+ crate_name: "mylib_rs",
+ shared_libs: ["libvers#27", "libm#impl"],
+ srcs: ["mylib.rs"],
+ apex_available: [ "myapex" ],
+ }
+
cc_library_shared {
name: "mylib_shared",
srcs: ["mylib.cpp"],
@@ -1799,22 +2022,40 @@
stl: "none",
bootstrap: true,
}
+
+ rust_ffi {
+ name: "libbootstrap_rs",
+ srcs: ["mylib.cpp"],
+ crate_name: "bootstrap_rs",
+ bootstrap: true,
+ }
+
+ cc_library {
+ name: "libvers",
+ srcs: ["mylib.cpp"],
+ stl: "none",
+ stubs: { versions: ["27","30"] },
+ }
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
- // Ensure that mylib, libm, libdl are included.
+ // Ensure that mylib, libmylib_rs, libm, libdl, libstd.dylib.so (from Rust) are included.
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libmylib_rs.so")
ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.so")
ensureContains(t, copyCmds, "image.apex/lib64/bionic/libdl.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/libstd.dylib.so")
- // Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
+ // Ensure that libc and liblog (from Rust) is not included (since it has stubs and not listed in native_shared_libs)
ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/liblog.so")
- mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
- mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
- mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_apex10000").Rule("cc").Args["cFlags"]
+ mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ mylibRsFlags := ctx.ModuleForTests(t, "libmylib_rs", "android_arm64_armv8-a_shared_apex10000").Rule("rustc").Args["linkFlags"]
+ mylibCFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
+ mylibSharedCFlags := ctx.ModuleForTests(t, "mylib_shared", "android_arm64_armv8-a_shared_apex10000").Rule("cc").Args["cFlags"]
// For dependency to libc
// Ensure that mylib is linking with the latest version of stubs
@@ -1846,11 +2087,42 @@
ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
+ // Rust checks
+ // For dependency to libc, liblog
+ // Ensure that libmylib_rs is linking with the latest versions of stubs
+ ensureContains(t, mylibRsFlags, "libc/android_arm64_armv8-a_shared_current/libc.so")
+ ensureContains(t, mylibRsFlags, "liblog/android_arm64_armv8-a_shared_current/liblog.so")
+ // ... and not linking to the non-stub (impl) variants
+ ensureNotContains(t, mylibRsFlags, "libc/android_arm64_armv8-a_shared/libc.so")
+ ensureNotContains(t, mylibRsFlags, "liblog/android_arm64_armv8-a_shared/liblog.so")
+
+ // For libm dependency (explicit)
+ // Ensure that mylib is linking with the non-stub (impl) variant
+ ensureContains(t, mylibRsFlags, "libm/android_arm64_armv8-a_shared_apex10000/libm.so")
+ // ... and not linking to the stub variant
+ ensureNotContains(t, mylibRsFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
+
+ // For dependency to libvers
+ // (We do not use libdl#27 as Rust links the system libs implicitly and does
+ // not currently have a system_shared_libs equivalent to prevent this)
+ // Ensure that mylib is linking with the specified version of stubs
+ ensureContains(t, mylibRsFlags, "libvers/android_arm64_armv8-a_shared_27/libvers.so")
+ // ... and not linking to the other versions of stubs
+ ensureNotContains(t, mylibRsFlags, "libvers/android_arm64_armv8-a_shared_30/libvers.so")
+ // ... and not linking to the non-stub (impl) variant
+ ensureNotContains(t, mylibRsFlags, "libvers/android_arm64_armv8-a_shared_apex10000/libvers.so")
+
// Ensure that libBootstrap is depending on the platform variant of bionic libs
- libFlags := ctx.ModuleForTests("libBootstrap", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
+ libFlags := ctx.ModuleForTests(t, "libBootstrap", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
ensureContains(t, libFlags, "libc/android_arm64_armv8-a_shared/libc.so")
ensureContains(t, libFlags, "libm/android_arm64_armv8-a_shared/libm.so")
ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
+
+ // Ensure that libbootstrap_rs is depending on the platform variant of bionic libs
+ libRsFlags := ctx.ModuleForTests(t, "libbootstrap_rs", "android_arm64_armv8-a_shared").Rule("rustc").Args["linkFlags"]
+ ensureContains(t, libRsFlags, "libc/android_arm64_armv8-a_shared/libc.so")
+ ensureContains(t, libRsFlags, "libm/android_arm64_armv8-a_shared/libm.so")
+ ensureContains(t, libRsFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
}
func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
@@ -1900,7 +2172,7 @@
cc_library {
name: "liba",
- shared_libs: ["libz"],
+ shared_libs: ["libz", "libz_rs"],
system_shared_libs: [],
stl: "none",
apex_available: [
@@ -1918,28 +2190,46 @@
versions: ["28", "30"],
},
}
+
+ rust_ffi {
+ name: "libz_rs",
+ crate_name: "z_rs",
+ srcs: ["foo.rs"],
+ stubs: {
+ versions: ["28", "30"],
+ },
+ }
`)
expectLink := func(from, from_variant, to, to_variant string) {
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectNoLink := func(from, from_variant, to, to_variant string) {
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
// platform liba is linked to non-stub version
expectLink("liba", "shared", "libz", "shared")
+ expectLink("liba", "shared", "unstripped/libz_rs", "shared")
// liba in myapex is linked to current
expectLink("liba", "shared_apex29", "libz", "shared_current")
expectNoLink("liba", "shared_apex29", "libz", "shared_30")
expectNoLink("liba", "shared_apex29", "libz", "shared_28")
expectNoLink("liba", "shared_apex29", "libz", "shared")
+ expectLink("liba", "shared_apex29", "unstripped/libz_rs", "shared_current")
+ expectNoLink("liba", "shared_apex29", "unstripped/libz_rs", "shared_30")
+ expectNoLink("liba", "shared_apex29", "unstripped/libz_rs", "shared_28")
+ expectNoLink("liba", "shared_apex29", "unstripped/libz_rs", "shared")
// liba in otherapex is linked to current
expectLink("liba", "shared_apex30", "libz", "shared_current")
expectNoLink("liba", "shared_apex30", "libz", "shared_30")
expectNoLink("liba", "shared_apex30", "libz", "shared_28")
expectNoLink("liba", "shared_apex30", "libz", "shared")
+ expectLink("liba", "shared_apex30", "unstripped/libz_rs", "shared_current")
+ expectNoLink("liba", "shared_apex30", "unstripped/libz_rs", "shared_30")
+ expectNoLink("liba", "shared_apex30", "unstripped/libz_rs", "shared_28")
+ expectNoLink("liba", "shared_apex30", "unstripped/libz_rs", "shared")
}
func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
@@ -1982,11 +2272,11 @@
)
expectLink := func(from, from_variant, to, to_variant string) {
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectNoLink := func(from, from_variant, to, to_variant string) {
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectLink("libx", "shared_apex10000", "libz", "shared_current")
@@ -2062,11 +2352,11 @@
`)
expectLink := func(from, from_variant, to, to_variant string) {
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectNoLink := func(from, from_variant, to, to_variant string) {
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectLink("libx", "shared_apex10000", "libz", "shared_current")
@@ -2110,14 +2400,14 @@
vendorVariant := "android_vendor_arm64_armv8-a"
- mylib := ctx.ModuleForTests("mylib", vendorVariant+"_shared_apex29")
+ mylib := ctx.ModuleForTests(t, "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/libbar.so")
// Ensure that mylib is targeting 29
- ccRule := ctx.ModuleForTests("mylib", vendorVariant+"_static_apex29").Output("obj/mylib.o")
+ ccRule := ctx.ModuleForTests(t, "mylib", vendorVariant+"_static_apex29").Output("obj/mylib.o")
ensureContains(t, ccRule.Args["cFlags"], "-target aarch64-linux-android29")
// Ensure that the correct variant of crtbegin_so is used.
@@ -2125,11 +2415,91 @@
ensureContains(t, crtBegin, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"crtbegin_so/"+vendorVariant+"_apex29/crtbegin_so.o")
// Ensure that the crtbegin_so used by the APEX is targeting 29
- cflags := ctx.ModuleForTests("crtbegin_so", vendorVariant+"_apex29").Rule("cc").Args["cFlags"]
+ cflags := ctx.ModuleForTests(t, "crtbegin_so", vendorVariant+"_apex29").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "cflags", cflags, "-target aarch64-linux-android29")
}
-func TestTrackAllowedDeps(t *testing.T) {
+func TestTrackAllowedDepsForAndroidApex(t *testing.T) {
+ t.Parallel()
+ ctx := testApex(t, `
+ apex {
+ name: "com.android.myapex",
+ key: "myapex.key",
+ updatable: true,
+ native_shared_libs: [
+ "mylib",
+ "yourlib",
+ ],
+ min_sdk_version: "29",
+ }
+
+ apex {
+ name: "myapex2",
+ key: "myapex.key",
+ updatable: false,
+ native_shared_libs: ["yourlib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libbar", "libbar_rs"],
+ min_sdk_version: "29",
+ apex_available: ["com.android.myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stubs: { versions: ["29", "30"] },
+ }
+
+ rust_ffi {
+ name: "libbar_rs",
+ crate_name: "bar_rs",
+ srcs: ["bar.rs"],
+ stubs: { versions: ["29", "30"] },
+ }
+
+ cc_library {
+ name: "yourlib",
+ srcs: ["mylib.cpp"],
+ min_sdk_version: "29",
+ apex_available: ["com.android.myapex", "myapex2", "//apex_available:platform"],
+ }
+ `, withFiles(android.MockFS{
+ "packages/modules/common/build/allowed_deps.txt": nil,
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.android.myapex-file_contexts": nil,
+ }))
+
+ depsinfo := ctx.SingletonForTests(t, "apex_depsinfo_singleton")
+ inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
+ android.AssertStringListContains(t, "updatable com.android.myapex should generate depsinfo file", inputs,
+ "out/soong/.intermediates/com.android.myapex/android_common_com.android.myapex/depsinfo/flatlist.txt")
+ android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
+
+ myapex := ctx.ModuleForTests(t, "com.android.myapex", "android_common_com.android.myapex")
+ flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ myapex.Output("depsinfo/flatlist.txt")), "\n")
+ android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+ flatlist, "libbar(minSdkVersion:(no version)) (external)")
+ android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+ flatlist, "libbar_rs(minSdkVersion:(no version)) (external)")
+ android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+ flatlist, "mylib:(minSdkVersion:29)")
+ android.AssertStringListContains(t, "track platform-available lib",
+ flatlist, "yourlib(minSdkVersion:29)")
+}
+
+func TestNotTrackAllowedDepsForNonAndroidApex(t *testing.T) {
t.Parallel()
ctx := testApex(t, `
apex {
@@ -2179,176 +2549,19 @@
"packages/modules/common/build/allowed_deps.txt": nil,
}))
- depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+ depsinfo := ctx.SingletonForTests(t, "apex_depsinfo_singleton")
inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
- android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
+ android.AssertStringListDoesNotContain(t, "updatable myapex should generate depsinfo file", inputs,
"out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
-
- myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
- flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- myapex.Output("depsinfo/flatlist.txt")), "\n")
- android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
- flatlist, "libbar(minSdkVersion:(no version)) (external)")
- android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
- flatlist, "mylib:(minSdkVersion:29)")
- android.AssertStringListContains(t, "track platform-available lib",
- flatlist, "yourlib(minSdkVersion:29)")
-}
-
-func TestTrackCustomAllowedDepsInvalidDefaultTxt(t *testing.T) {
- t.Parallel()
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- updatable: true,
- native_shared_libs: [
- "mylib",
- "yourlib",
- ],
- min_sdk_version: "29",
- }
-
- apex {
- name: "myapex2",
- key: "myapex.key",
- updatable: false,
- native_shared_libs: ["yourlib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- shared_libs: ["libbar"],
- min_sdk_version: "29",
- apex_available: ["myapex"],
- }
-
- cc_library {
- name: "libbar",
- stubs: { versions: ["29", "30"] },
- }
-
- cc_library {
- name: "yourlib",
- srcs: ["mylib.cpp"],
- min_sdk_version: "29",
- apex_available: ["myapex", "myapex2", "//apex_available:platform"],
- }
- `, withFiles(android.MockFS{
- "packages/modules/common/build/custom_allowed_deps.txt": nil,
- }),
- android.FixtureModifyProductVariables(
- func(variables android.FixtureProductVariables) {
- variables.ExtraAllowedDepsTxt = proptools.StringPtr("packages/modules/common/build/custom_allowed_deps.txt")
- },
- ))
-
- depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
- inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
- android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
- "out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
- android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
- "out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
-
- myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
- flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- myapex.Output("depsinfo/flatlist.txt")), "\n")
- android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
- flatlist, "libbar(minSdkVersion:(no version)) (external)")
- android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
- flatlist, "mylib:(minSdkVersion:29)")
- android.AssertStringListContains(t, "track platform-available lib",
- flatlist, "yourlib(minSdkVersion:29)")
-}
-
-func TestTrackCustomAllowedDepsWithDefaultTxt(t *testing.T) {
- t.Parallel()
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- updatable: true,
- native_shared_libs: [
- "mylib",
- "yourlib",
- ],
- min_sdk_version: "29",
- }
-
- apex {
- name: "myapex2",
- key: "myapex.key",
- updatable: false,
- native_shared_libs: ["yourlib"],
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- shared_libs: ["libbar"],
- min_sdk_version: "29",
- apex_available: ["myapex"],
- }
-
- cc_library {
- name: "libbar",
- stubs: { versions: ["29", "30"] },
- }
-
- cc_library {
- name: "yourlib",
- srcs: ["mylib.cpp"],
- min_sdk_version: "29",
- apex_available: ["myapex", "myapex2", "//apex_available:platform"],
- }
- `, withFiles(android.MockFS{
- "packages/modules/common/build/custom_allowed_deps.txt": nil,
- "packages/modules/common/build/allowed_deps.txt": nil,
- }),
- android.FixtureModifyProductVariables(
- func(variables android.FixtureProductVariables) {
- variables.ExtraAllowedDepsTxt = proptools.StringPtr("packages/modules/common/build/custom_allowed_deps.txt")
- },
- ))
-
- depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
- inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
- android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
- "out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
- android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
- "out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
-
- myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
- flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
- myapex.Output("depsinfo/flatlist.txt")), "\n")
- android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
- flatlist, "libbar(minSdkVersion:(no version)) (external)")
- android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
- flatlist, "mylib:(minSdkVersion:29)")
- android.AssertStringListContains(t, "track platform-available lib",
- flatlist, "yourlib(minSdkVersion:29)")
}
func TestTrackAllowedDeps_SkipWithoutAllowedDepsTxt(t *testing.T) {
t.Parallel()
ctx := testApex(t, `
apex {
- name: "myapex",
+ name: "com.android.myapex",
key: "myapex.key",
updatable: true,
min_sdk_version: "29",
@@ -2359,8 +2572,11 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
- `)
- depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+ `,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.android.myapex-file_contexts": nil,
+ }))
+ depsinfo := ctx.SingletonForTests(t, "apex_depsinfo_singleton")
if nil != depsinfo.MaybeRule("generateApexDepsInfoFilesRule").Output {
t.Error("apex_depsinfo_singleton shouldn't run when allowed_deps.txt doesn't exist")
}
@@ -2372,7 +2588,7 @@
apex {
name: "myapex",
key: "myapex.key",
- native_shared_libs: ["libx"],
+ native_shared_libs: ["libx", "libx_rs"],
updatable: false,
}
@@ -2392,9 +2608,19 @@
},
}
+ rust_ffi {
+ name: "libx_rs",
+ crate_name: "x_rs",
+ srcs: ["x.rs"],
+ apex_available: [ "myapex" ],
+ stubs: {
+ versions: ["1", "2"],
+ },
+ }
+
cc_library {
name: "libz",
- shared_libs: ["libx"],
+ shared_libs: ["libx", "libx_rs",],
system_shared_libs: [],
stl: "none",
}
@@ -2402,16 +2628,18 @@
expectLink := func(from, from_variant, to, to_variant string) {
t.Helper()
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectNoLink := func(from, from_variant, to, to_variant string) {
t.Helper()
- ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
+ ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectLink("libz", "shared", "libx", "shared_current")
expectNoLink("libz", "shared", "libx", "shared_2")
+ expectLink("libz", "shared", "unstripped/libx_rs", "shared_current")
+ expectNoLink("libz", "shared", "unstripped/libx_rs", "shared_2")
expectNoLink("libz", "shared", "libz", "shared_1")
expectNoLink("libz", "shared", "libz", "shared")
}
@@ -2440,11 +2668,18 @@
cc_library {
name: "libx",
- shared_libs: ["libbar"],
+ shared_libs: ["libbar", "libbar_rs"],
apex_available: [ "myapex" ],
min_sdk_version: "29",
}
+ rust_ffi {
+ name: "libbar_rs",
+ crate_name: "bar_rs",
+ srcs: ["bar.rs"],
+ stubs: { versions: ["29", "30"] },
+ }
+
cc_library {
name: "libbar",
stubs: {
@@ -2455,11 +2690,12 @@
prepareForTestWithSantitizeHwaddress,
)
expectLink := func(from, from_variant, to, to_variant string) {
- ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
+ ld := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_current")
+ expectLink("libx", "shared_hwasan_apex29", "unstripped/libbar_rs", "shared_current")
}
func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
@@ -2486,10 +2722,10 @@
`)
// ensure apex variant of c++ is linked with static unwinder
- cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_apex29").Module().(*cc.Module)
+ cm := ctx.ModuleForTests(t, "libc++", "android_arm64_armv8-a_shared_apex29").Module().(*cc.Module)
ensureListContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
// note that platform variant is not.
- cm = ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ cm = ctx.ModuleForTests(t, "libc++", "android_arm64_armv8-a_shared").Module().(*cc.Module)
ensureListNotContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
}
@@ -2982,7 +3218,7 @@
}
`)
expectLink := func(from, from_variant, to, to_variant string) {
- ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
+ ld := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
@@ -3057,7 +3293,7 @@
`, withSAsActiveCodeNames)
// ensure libfoo is linked with current version of libbar stub
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared_apex10000")
libFlags := libfoo.Rule("ld").Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_shared_current/libbar.so")
}
@@ -3113,7 +3349,7 @@
}
`)
- generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("generateFsConfig")
+ generateFsRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("generateFsConfig")
cmd := generateFsRule.RuleParams.Command
// Ensure that the subdirectories are all listed
@@ -3227,7 +3463,7 @@
"lib64/libc++.so",
})
- apexBundle := result.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := result.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, result.TestContext, apexBundle)
name := apexBundle.BaseModuleName()
prefix := "TARGET_"
@@ -3237,7 +3473,7 @@
installPath := "out/target/product/test_device/vendor/apex"
ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
- apexManifestRule := result.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := result.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
ensureListNotContains(t, requireNativeLibs, ":vndk")
}
@@ -3268,7 +3504,7 @@
`)
cflags := strings.Fields(
- ctx.ModuleForTests("foo", "android_product_arm64_armv8-a_apex10000").Rule("cc").Args["cFlags"])
+ ctx.ModuleForTests(t, "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__")
@@ -3337,7 +3573,7 @@
}
`)
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
name := apexBundle.BaseModuleName()
prefix := "TARGET_"
@@ -3366,7 +3602,7 @@
}
`)
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
name := apexBundle.BaseModuleName()
prefix := "TARGET_"
@@ -3404,20 +3640,31 @@
apex_available: ["myapex"],
}
+ rust_ffi {
+ name: "libmylib_rs",
+ crate_name: "mylib_rs",
+ srcs: ["mylib.rs"],
+ stubs: {
+ versions: ["1", "2", "3"],
+ },
+ apex_available: ["myapex"],
+ }
+
cc_binary {
name: "not_in_apex",
srcs: ["mylib.cpp"],
- static_libs: ["mylib"],
+ static_libs: ["mylib", "libmylib_rs"],
static_executable: true,
system_shared_libs: [],
stl: "none",
}
`)
- ldFlags := ctx.ModuleForTests("not_in_apex", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
+ ldFlags := ctx.ModuleForTests(t, "not_in_apex", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
// Ensure that not_in_apex is linking with the static variant of mylib
ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_static/mylib.a")
+ ensureContains(t, ldFlags, "generated_rust_staticlib/librustlibs.a")
}
func TestKeys(t *testing.T) {
@@ -3459,7 +3706,7 @@
`)
// check the APEX keys
- keys := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
+ keys := ctx.ModuleForTests(t, "myapex.key", "android_common").Module().(*apexKey)
if keys.publicKeyFile.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
t.Errorf("public key %q is not %q", keys.publicKeyFile.String(),
@@ -3471,7 +3718,7 @@
}
// check the APK certs. It should be overridden to myapex.certificate.override
- certs := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk").Args["certificates"]
+ certs := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk").Args["certificates"]
if certs != "testkey.override.x509.pem testkey.override.pk8" {
t.Errorf("cert and private key %q are not %q", certs,
"testkey.override.509.pem testkey.override.pk8")
@@ -3493,7 +3740,7 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}`)
- rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk")
+ rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk")
expected := "vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8"
if actual := rule.Args["certificates"]; actual != expected {
t.Errorf("certificates should be %q, not %q", expected, actual)
@@ -3517,7 +3764,7 @@
name: "myapex.certificate.override",
certificate: "testkey.override",
}`)
- rule := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
+ rule := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
expected := "testkey.override.x509.pem testkey.override.pk8"
if actual := rule.Args["certificates"]; actual != expected {
t.Errorf("certificates should be %q, not %q", expected, actual)
@@ -3541,7 +3788,7 @@
name: "myapex.certificate",
certificate: "testkey",
}`)
- rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk")
+ rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk")
expected := "testkey.x509.pem testkey.pk8"
if actual := rule.Args["certificates"]; actual != expected {
t.Errorf("certificates should be %q, not %q", expected, actual)
@@ -3566,7 +3813,7 @@
name: "myapex.certificate.override",
certificate: "testkey.override",
}`)
- rule := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
+ rule := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
expected := "testkey.override.x509.pem testkey.override.pk8"
if actual := rule.Args["certificates"]; actual != expected {
t.Errorf("certificates should be %q, not %q", expected, actual)
@@ -3585,8 +3832,12 @@
name: "myapex.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
- }`)
- rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk")
+ }`,
+ android.MockFS{
+ "vendor/foo/devkeys/testkey.x509.pem": nil,
+ }.AddToFixture(),
+ )
+ rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk")
expected := "vendor/foo/devkeys/testkey.x509.pem vendor/foo/devkeys/testkey.pk8"
if actual := rule.Args["certificates"]; actual != expected {
t.Errorf("certificates should be %q, not %q", expected, actual)
@@ -3611,7 +3862,7 @@
name: "myapex.certificate.override",
certificate: "testkey.override",
}`)
- rule := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
+ rule := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
expected := "testkey.override.x509.pem testkey.override.pk8"
if actual := rule.Args["certificates"]; actual != expected {
t.Errorf("certificates should be %q, not %q", expected, actual)
@@ -3682,34 +3933,34 @@
`)
// non-APEX variant does not have __ANDROID_APEX__ defined
- mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ mylibCFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX__ defined
- mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX__ defined
- mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
// When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
// each variant defines additional macros to distinguish which apex variant it is built for
// non-APEX variant does not have __ANDROID_APEX__ defined
- mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests(t, "mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
// recovery variant does not set __ANDROID_APEX__
- mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests(t, "mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
// non-APEX variant does not have __ANDROID_APEX__ defined
- mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
// recovery variant does not set __ANDROID_APEX__
- mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ mylibCFlags = ctx.ModuleForTests(t, "mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
}
@@ -3759,7 +4010,7 @@
}
`)
- cFlags := ctx.ModuleForTests("otherlib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ cFlags := ctx.ModuleForTests(t, "otherlib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
// Ensure that the include path of the header lib is exported to 'otherlib'
ensureContains(t, cFlags, "-Imy_include")
@@ -3791,7 +4042,7 @@
func getFiles(t *testing.T, ctx *android.TestContext, moduleName, variant string) []fileInApex {
t.Helper()
- module := ctx.ModuleForTests(moduleName, variant)
+ module := ctx.ModuleForTests(t, moduleName, variant)
apexRule := module.MaybeRule("apexRule")
apexDir := "/image.apex/"
copyCmds := apexRule.Args["copy_commands"]
@@ -3882,7 +4133,7 @@
}
func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) {
- deapexer := ctx.ModuleForTests(moduleName, variant).Description("deapex")
+ deapexer := ctx.ModuleForTests(t, moduleName, variant).Description("deapex")
outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
if deapexer.Output != nil {
outputs = append(outputs, deapexer.Output.String())
@@ -4011,7 +4262,7 @@
}`+vndkLibrariesTxtFiles("28", "29"))
assertApexName := func(expected, moduleName string) {
- module := ctx.ModuleForTests(moduleName, "android_common")
+ module := ctx.ModuleForTests(t, moduleName, "android_common")
apexManifestRule := module.Rule("apexManifestRule")
ensureContains(t, apexManifestRule.Args["opt"], "-v name "+expected)
}
@@ -4239,25 +4490,25 @@
var apexManifestRule android.TestingBuildParams
var provideNativeLibs, requireNativeLibs []string
- apexManifestRule = ctx.ModuleForTests("myapex_nodep", "android_common_myapex_nodep").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests(t, "myapex_nodep", "android_common_myapex_nodep").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
ensureListEmpty(t, requireNativeLibs)
- apexManifestRule = ctx.ModuleForTests("myapex_dep", "android_common_myapex_dep").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests(t, "myapex_dep", "android_common_myapex_dep").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
ensureListContains(t, requireNativeLibs, "libfoo.so")
- apexManifestRule = ctx.ModuleForTests("myapex_provider", "android_common_myapex_provider").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests(t, "myapex_provider", "android_common_myapex_provider").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListContains(t, provideNativeLibs, "libfoo.so")
ensureListEmpty(t, requireNativeLibs)
- apexManifestRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained").Rule("apexManifestRule")
+ apexManifestRule = ctx.ModuleForTests(t, "myapex_selfcontained", "android_common_myapex_selfcontained").Rule("apexManifestRule")
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
ensureListContains(t, provideNativeLibs, "libbar.so")
@@ -4294,7 +4545,7 @@
"OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
}))
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexManifestRule := module.Rule("apexManifestRule")
ensureContains(t, apexManifestRule.Args["default_version"], "1234")
}
@@ -4358,7 +4609,7 @@
}
`, testCase.compileMultiLibProp),
)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
for _, containedLib := range testCase.containedLibs {
@@ -4398,7 +4649,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -4418,7 +4669,7 @@
// Ensure that the platform variant ends with _shared
ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared")
- if !ctx.ModuleForTests("mylib_common", "android_arm64_armv8-a_shared_apex10000").Module().(*cc.Module).InAnyApex() {
+ if !ctx.ModuleForTests(t, "mylib_common", "android_arm64_armv8-a_shared_apex10000").Module().(*cc.Module).InAnyApex() {
t.Log("Found mylib_common not in any apex!")
t.Fail()
}
@@ -4453,7 +4704,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -4527,7 +4778,7 @@
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
"bin/mybin",
})
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
android.AssertStringEquals(t, "should require libz", apexManifestRule.Args["requireNativeLibs"], "libz.so")
}
// libz doesn't provide stubs for vendor variant.
@@ -4536,7 +4787,7 @@
"bin/mybin",
"lib64/libz.so",
})
- apexManifestRule := ctx.ModuleForTests("myvendorapex", "android_common_myvendorapex").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests(t, "myvendorapex", "android_common_myvendorapex").Rule("apexManifestRule")
android.AssertStringEquals(t, "should not require libz", apexManifestRule.Args["requireNativeLibs"], "")
}
}
@@ -4611,7 +4862,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that main rule creates an output
@@ -4696,7 +4947,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that apex variant is created for the direct dep
@@ -4734,7 +4985,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
@@ -4770,8 +5021,8 @@
}
`)
- apex := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
- expected := "out/soong/target/product/test_device/" + tc.partition + "/apex"
+ apex := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
+ expected := "out/target/product/test_device/" + tc.partition + "/apex"
actual := apex.installDir.RelativeToTop().String()
if actual != expected {
t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
@@ -4795,7 +5046,7 @@
private_key: "testkey.pem",
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
rule := module.Output("file_contexts")
ensureContains(t, rule.RuleParams.Command, "cat system/sepolicy/apex/myapex-file_contexts")
}
@@ -4855,7 +5106,7 @@
`, withFiles(map[string][]byte{
"product_specific_file_contexts": nil,
}))
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
rule := module.Output("file_contexts")
ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
}
@@ -4884,7 +5135,7 @@
`, withFiles(map[string][]byte{
"product_specific_file_contexts": nil,
}))
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
rule := module.Output("file_contexts")
ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
}
@@ -4910,7 +5161,7 @@
}
`)
- apex_key := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
+ apex_key := ctx.ModuleForTests(t, "myapex.key", "android_common").Module().(*apexKey)
expected_pubkey := "testkey2.avbpubkey"
actual_pubkey := apex_key.publicKeyFile.String()
if actual_pubkey != expected_pubkey {
@@ -4939,7 +5190,7 @@
}
`)
- testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ testingModule := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
prebuilt := testingModule.Module().(*Prebuilt)
expectedInput := "myapex-arm64.apex"
@@ -4960,7 +5211,7 @@
func TestPrebuiltMissingSrc(t *testing.T) {
t.Parallel()
- testApexError(t, `module "myapex" variant "android_common_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
+ testApexError(t, `module "myapex" variant "android_common_prebuilt_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
prebuilt_apex {
name: "myapex",
}
@@ -4977,7 +5228,7 @@
}
`)
- testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ testingModule := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
p := testingModule.Module().(*Prebuilt)
expected := "notmyapex.apex"
@@ -5000,7 +5251,7 @@
set: "company-myapex.apks",
filename: "com.company.android.myapex.apex"
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApex(t, `
apex_set {
@@ -5009,7 +5260,7 @@
set: "company-myapex.apks",
filename: "com.company.android.myapex.capex"
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApexError(t, `filename should end in .apex or .capex for apex_set`, `
apex_set {
@@ -5033,7 +5284,7 @@
}
`)
- testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt")
+ testingModule := ctx.ModuleForTests(t, "myapex.prebuilt", "android_common_prebuilt_myapex.prebuilt")
p := testingModule.Module().(*Prebuilt)
expected := []string{"myapex"}
@@ -5056,7 +5307,7 @@
apex_name: "com.android.myapex",
src: "company-myapex-arm.apex",
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApex(t, `
apex_set {
@@ -5064,7 +5315,7 @@
apex_name: "com.android.myapex",
set: "company-myapex.apks",
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
}
func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
@@ -5090,6 +5341,12 @@
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+ prebuilt_apex {
+ name: "com.android.art",
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
prebuilt_bootclasspath_fragment {
name: "art-bootclasspath-fragment",
image_name: "art",
@@ -5143,7 +5400,7 @@
checkHiddenAPIIndexFromClassesInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
t.Helper()
- platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ platformBootclasspath := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common")
var rule android.TestingBuildParams
rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv")
@@ -5152,7 +5409,7 @@
checkHiddenAPIIndexFromFlagsInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
t.Helper()
- platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ platformBootclasspath := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common")
var rule android.TestingBuildParams
rule = platformBootclasspath.Output("hiddenapi-index.csv")
@@ -5222,7 +5479,7 @@
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
- out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
})
@@ -5295,10 +5552,10 @@
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
- out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
- myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
+ myApex := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex").Module()
overrideNames := []string{
"",
@@ -5382,7 +5639,7 @@
// prebuilt_apex module always depends on the prebuilt, and so it doesn't
// find the dex boot jar in it. We either need to disable the source libfoo
// or make the prebuilt libfoo preferred.
- testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer, fragment)
+ testDexpreoptWithApexes(t, bp, `module "platform-bootclasspath" variant ".*": module libfoo{.*} does not provide a dex jar`, preparer, fragment)
// dexbootjar check is skipped if AllowMissingDependencies is true
preparerAllowMissingDeps := android.GroupFixturePreparers(
preparer,
@@ -5418,6 +5675,7 @@
prebuilt_apex {
name: "myapex",
+ prefer: true,
arch: {
arm64: {
src: "myapex-arm64.apex",
@@ -5490,7 +5748,7 @@
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
- out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
})
@@ -5589,7 +5847,7 @@
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/modular-hiddenapi/index.csv
- out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
})
@@ -5701,7 +5959,7 @@
checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
- out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
+ out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
})
@@ -5818,7 +6076,6 @@
relative_install_path: "test",
shared_libs: ["mylib"],
system_shared_libs: [],
- static_executable: true,
stl: "none",
data: [":fg"],
}
@@ -5838,7 +6095,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that test dep (and their transitive dependencies) are copied into apex.
@@ -5850,7 +6107,7 @@
ensureContains(t, copyCmds, "image.apex/bin/test/bar/baz")
// Ensure the module is correctly translated.
- bundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ bundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, bundle)
name := bundle.BaseModuleName()
prefix := "TARGET_"
@@ -5932,7 +6189,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
ensureContains(t, copyCmds, "image.apex/javalib/myjavaimport.jar")
@@ -5998,7 +6255,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -6006,14 +6263,14 @@
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@TEST.BUILD_ID/AppFooPriv.apk")
ensureContains(t, copyCmds, "image.apex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
- appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
+ appZipRule := ctx.ModuleForTests(t, "AppFoo", "android_common_apex10000").Description("zip jni libs")
// JNI libraries are uncompressed
if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
t.Errorf("jni libs are not uncompressed for AppFoo")
}
// JNI libraries including transitive deps are
for _, jni := range []string{"libjni", "libfoo"} {
- jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToTop()
+ jniOutput := ctx.ModuleForTests(t, jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToTop()
// ... embedded inside APK (jnilibs.zip)
ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
// ... and not directly inside the APEX
@@ -6106,7 +6363,7 @@
}
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -6184,7 +6441,7 @@
`)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -6682,14 +6939,14 @@
}
`)
- fooManifestRule := result.ModuleForTests("foo", "android_common_foo").Rule("apexManifestRule")
+ fooManifestRule := result.ModuleForTests(t, "foo", "android_common_foo").Rule("apexManifestRule")
fooExpectedDefaultVersion := testDefaultUpdatableModuleVersion
fooActualDefaultVersion := fooManifestRule.Args["default_version"]
if fooActualDefaultVersion != fooExpectedDefaultVersion {
t.Errorf("expected to find defaultVersion %q; got %q", fooExpectedDefaultVersion, fooActualDefaultVersion)
}
- barManifestRule := result.ModuleForTests("bar", "android_common_bar").Rule("apexManifestRule")
+ barManifestRule := result.ModuleForTests(t, "bar", "android_common_bar").Rule("apexManifestRule")
defaultVersionInt, _ := strconv.Atoi(testDefaultUpdatableModuleVersion)
barExpectedDefaultVersion := fmt.Sprint(defaultVersionInt + 3)
barActualDefaultVersion := barManifestRule.Args["default_version"]
@@ -6697,7 +6954,7 @@
t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
}
- overrideBarManifestRule := result.ModuleForTests("bar", "android_common_myoverrideapex_myoverrideapex").Rule("apexManifestRule")
+ overrideBarManifestRule := result.ModuleForTests(t, "bar", "android_common_myoverrideapex_myoverrideapex").Rule("apexManifestRule")
overrideBarActualDefaultVersion := overrideBarManifestRule.Args["default_version"]
if overrideBarActualDefaultVersion != barExpectedDefaultVersion {
t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
@@ -6937,14 +7194,14 @@
// libfoo shouldn't be available to platform even though it has "//apex_available:platform",
// because it depends on libbar which isn't available to platform
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
if libfoo.NotAvailableForPlatform() != true {
t.Errorf("%q shouldn't be available to platform", libfoo.String())
}
// libfoo2 however can be available to platform because it depends on libbaz which provides
// stubs
- libfoo2 := ctx.ModuleForTests("libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ libfoo2 := ctx.ModuleForTests(t, "libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
if libfoo2.NotAvailableForPlatform() == true {
t.Errorf("%q should be available to platform", libfoo2.String())
}
@@ -6976,11 +7233,11 @@
},
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
if libfooShared.NotAvailableForPlatform() != true {
t.Errorf("%q shouldn't be available to platform", libfooShared.String())
}
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
if libfooStatic.NotAvailableForPlatform() != false {
t.Errorf("%q should be available to platform", libfooStatic.String())
}
@@ -7081,6 +7338,34 @@
`)
}
+func TestApexValidation_UsesProperPartitionTag(t *testing.T) {
+ t.Parallel()
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ vendor: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // vendor path should not affect "partition tag"
+ variables.VendorPath = proptools.StringPtr("system/vendor")
+ }))
+
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
+ android.AssertStringEquals(t, "partition tag for host_apex_verifier",
+ "vendor",
+ module.Output("host_apex_verifier.timestamp").Args["partition_tag"])
+ android.AssertStringEquals(t, "partition tag for apex_sepolicy_tests",
+ "vendor",
+ module.Output("apex_sepolicy_tests.timestamp").Args["partition_tag"])
+}
+
func TestApexValidation_TestApexCanSkipInitRcCheck(t *testing.T) {
t.Parallel()
ctx := testApex(t, `
@@ -7099,7 +7384,7 @@
}
`)
- validations := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
+ validations := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
if android.SuffixInList(validations, "host_apex_verifier.timestamp") {
t.Error("should not run host_apex_verifier")
}
@@ -7120,7 +7405,7 @@
}
`)
- validations := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
+ validations := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
if !android.SuffixInList(validations, "host_apex_verifier.timestamp") {
t.Error("should run host_apex_verifier")
}
@@ -7224,8 +7509,8 @@
}
`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
- originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(android.OverridableModule)
- overriddenVariant := ctx.ModuleForTests("myapex", "android_common_override_myapex_override_myapex").Module().(android.OverridableModule)
+ originalVariant := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(android.OverridableModule)
+ overriddenVariant := ctx.ModuleForTests(t, "myapex", "android_common_override_myapex_override_myapex").Module().(android.OverridableModule)
if originalVariant.GetOverriddenBy() != "" {
t.Errorf("GetOverriddenBy should be empty, but was %q", originalVariant.GetOverriddenBy())
}
@@ -7233,7 +7518,7 @@
t.Errorf("GetOverriddenBy should be \"override_myapex\", but was %q", overriddenVariant.GetOverriddenBy())
}
- module := ctx.ModuleForTests("myapex", "android_common_override_myapex_override_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_override_myapex_override_myapex")
apexRule := module.Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
@@ -7324,7 +7609,7 @@
`, withApexGlobalMinSdkVersionOverride(&minSdkOverride31))
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -7384,7 +7669,7 @@
`, withApexGlobalMinSdkVersionOverride(&minSdkOverride29))
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
copyCmds := apexRule.Args["copy_commands"]
// Ensure that direct non-stubs dep is always included
@@ -7423,7 +7708,7 @@
}
`, withUnbundledBuild)
- module := ctx.ModuleForTests("myapex", "android_common_myapex")
+ module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
args := module.Rule("apexRule").Args
ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
@@ -7432,8 +7717,8 @@
// the dependency names directly here but for some reason the names are blank in
// this test.
for _, lib := range []string{"libc++", "mylib"} {
- apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_apex29").Rule("ld").Implicits
- nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
+ apexImplicits := ctx.ModuleForTests(t, lib, "android_arm64_armv8-a_shared_apex29").Rule("ld").Implicits
+ nonApexImplicits := ctx.ModuleForTests(t, lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
if len(apexImplicits) != len(nonApexImplicits)+1 {
t.Errorf("%q missing unwinder dep", lib)
}
@@ -7492,7 +7777,7 @@
"etc/permissions/foo.xml",
})
// Permission XML should point to the activated path of impl jar of java_sdk_library
- sdkLibrary := ctx.ModuleForTests("foo.xml", "android_common_myapex").Output("foo.xml")
+ sdkLibrary := ctx.ModuleForTests(t, "foo.xml", "android_common_myapex").Output("foo.xml")
contents := android.ContentFromFileRuleForTests(t, ctx, sdkLibrary)
ensureMatches(t, contents, "<library\\n\\s+name=\\\"foo\\\"\\n\\s+file=\\\"/apex/myapex/javalib/foo.jar\\\"")
}
@@ -7533,7 +7818,7 @@
// Permission XML should point to the activated path of impl jar of java_sdk_library.
// Since override variants (com.mycompany.android.foo) are installed in the same package as the overridden variant
// (com.android.foo), the filepath should not contain override apex name.
- sdkLibrary := ctx.ModuleForTests("foo.xml", "android_common_mycompanyapex").Output("foo.xml")
+ sdkLibrary := ctx.ModuleForTests(t, "foo.xml", "android_common_mycompanyapex").Output("foo.xml")
contents := android.ContentFromFileRuleForTests(t, ctx, sdkLibrary)
ensureMatches(t, contents, "<library\\n\\s+name=\\\"foo\\\"\\n\\s+file=\\\"/apex/myapex/javalib/foo.jar\\\"")
}
@@ -7588,8 +7873,8 @@
})
// The bar library should depend on the implementation jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
- if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ barLibrary := ctx.ModuleForTests(t, "bar", "android_common_apex10000").Rule("javac")
+ if expected, actual := `^-classpath [^:]*/turbine/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -7640,8 +7925,8 @@
})
// The bar library should depend on the stubs jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac")
- if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ barLibrary := ctx.ModuleForTests(t, "bar", "android_common").Rule("javac")
+ if expected, actual := `^-classpath [^:]*/foo\.stubs\.from-text/foo\.stubs\.from-text\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -7734,8 +8019,8 @@
})
// The bar library should depend on the implementation jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
- if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ barLibrary := ctx.ModuleForTests(t, "bar", "android_common_apex10000").Rule("javac")
+ if expected, actual := `^-classpath [^:]*/turbine/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -8113,7 +8398,7 @@
}
`)
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
var builder strings.Builder
data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
@@ -8199,7 +8484,7 @@
`)
- rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
// Notice mylib2.so (transitive dep) is not added as a jni_lib
ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so mylib3.so")
ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
@@ -8208,39 +8493,12 @@
"lib64/mylib2.so",
"lib64/mylib3.so",
"lib64/libfoo.rust.so",
- "lib64/libc++.so", // auto-added to libfoo.rust by Soong
- "lib64/liblog.so", // auto-added to libfoo.rust by Soong
})
// b/220397949
ensureListContains(t, names(rule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
}
-func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
- t.Parallel()
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- updatable: false,
- }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- `,
- android.FixtureModifyConfig(func(config android.Config) {
- delete(config.Targets, android.Android)
- config.AndroidCommonTarget = android.Target{}
- }),
- )
-
- if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
- t.Errorf("Expected variants: %v, but got: %v", expected, got)
- }
-}
-
func TestAppBundle(t *testing.T) {
t.Parallel()
ctx := testApex(t, `
@@ -8266,7 +8524,7 @@
}
`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
- bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex").Output("bundle_config.json")
+ bundleConfigRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("bundle_config.json")
content := android.ContentFromFileRuleForTests(t, ctx, bundleConfigRule)
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
@@ -8293,7 +8551,7 @@
name: "AppSet",
set: "AppSet.apks",
}`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
bundleConfigRule := mod.Output("bundle_config.json")
content := android.ContentFromFileRuleForTests(t, ctx, bundleConfigRule)
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
@@ -8327,16 +8585,16 @@
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
- extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
// Ditto for the apex.
- m = ctx.ModuleForTests("myapex", "android_common_myapex")
- copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_myapex/foo_v2.apex")
+ m = ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
+ copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_prebuilt_myapex/foo_v2.apex")
android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
}
@@ -8355,10 +8613,10 @@
}
`)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -8747,7 +9005,7 @@
}),
)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -8762,7 +9020,7 @@
t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
}
- m = ctx.ModuleForTests("myapex", "android_common_myapex")
+ m = ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
a := m.Module().(*ApexSet)
expectedOverrides := []string{"foo"}
actualOverrides := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
@@ -8789,7 +9047,7 @@
}),
)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -8851,7 +9109,7 @@
}
`)
- myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+ myapex := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
content := android.ContentFromFileRuleForTests(t, ctx, myapex.Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
}
@@ -8894,10 +9152,10 @@
`)
content := android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex", "android_common_myapex").Output("apexkeys.txt"))
+ ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
content = android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex_set", "android_common_myapex_set").Output("apexkeys.txt"))
+ ctx.ModuleForTests(t, "myapex_set", "android_common_prebuilt_myapex_set").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
}
@@ -8947,12 +9205,12 @@
`),
}))
- rule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("diffApexContentRule")
+ rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("diffApexContentRule")
if expected, actual := "allowed.txt", rule.Args["allowed_files_file"]; expected != actual {
t.Errorf("allowed_files_file: expected %q but got %q", expected, actual)
}
- rule2 := ctx.ModuleForTests("myapex", "android_common_override_myapex_override_myapex").Rule("diffApexContentRule")
+ rule2 := ctx.ModuleForTests(t, "myapex", "android_common_override_myapex_override_myapex").Rule("diffApexContentRule")
if expected, actual := "sub/allowed.txt", rule2.Args["allowed_files_file"]; expected != actual {
t.Errorf("allowed_files_file: expected %q but got %q", expected, actual)
}
@@ -9015,14 +9273,14 @@
}),
)
- compressRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("compressRule")
+ compressRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("compressRule")
ensureContains(t, compressRule.Output.String(), "myapex.capex.unsigned")
- signApkRule := ctx.ModuleForTests("myapex", "android_common_myapex").Description("sign compressedApex")
+ signApkRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Description("sign compressedApex")
ensureEquals(t, signApkRule.Input.String(), compressRule.Output.String())
// Make sure output of bundle is .capex
- ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
ensureContains(t, ab.outputFile.String(), "myapex.capex")
// Verify android.mk rules
@@ -9054,7 +9312,7 @@
}),
)
- compressRule := ctx.ModuleForTests("myapex", "android_common_myapex").MaybeRule("compressRule")
+ compressRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").MaybeRule("compressRule")
if compressRule.Rule != nil {
t.Error("erofs apex should not be compressed")
}
@@ -9076,7 +9334,7 @@
}),
)
- build := ctx.ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex").Output("com.company.android.myapex.apex")
+ build := ctx.ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex").Output("com.company.android.myapex.apex")
if compressionEnabled {
ensureEquals(t, build.Rule.String(), "android/soong/android.Cp")
} else {
@@ -9128,7 +9386,7 @@
}
`)
- ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, ab)
var builder strings.Builder
data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
@@ -9178,15 +9436,15 @@
`)
// Check if mylib is linked to mylib2 for the non-apex target
- ldFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
+ ldFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
ensureContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
// Make sure that the link doesn't occur for the apex target
- ldFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+ ldFlags = ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
ensureNotContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared_apex10000/mylib2.so")
// It shouldn't appear in the copy cmd as well.
- copyCmds := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule").Args["copy_commands"]
+ copyCmds := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule").Args["copy_commands"]
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
}
@@ -9302,7 +9560,7 @@
if !strings.HasPrefix(variant, "android_arm64_armv8-a_shared") {
continue
}
- mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module)
+ mod := ctx.ModuleForTests(t, modName, variant).Module().(*cc.Module)
if !mod.Enabled(android.PanickingConfigAndErrorContext(ctx)) || mod.IsHideFromMake() {
continue
}
@@ -9425,13 +9683,13 @@
).RunTest(t)
// Make sure jacoco ran on both mylib and mybootclasspathlib
- if result.ModuleForTests("mylib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
+ if result.ModuleForTests(t, "mylib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
t.Errorf("Failed to find jacoco rule for mylib")
}
- if result.ModuleForTests("mybootclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
+ if result.ModuleForTests(t, "mybootclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
t.Errorf("Failed to find jacoco rule for mybootclasspathlib")
}
- if result.ModuleForTests("mysystemserverclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
+ if result.ModuleForTests(t, "mysystemserverclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
t.Errorf("Failed to find jacoco rule for mysystemserverclasspathlib")
}
}
@@ -9514,12 +9772,21 @@
dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
)
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
var builder strings.Builder
data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
androidMk := builder.String()
- ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := foo.myapex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex\n")
+ out := ctx.Config().OutDir()
+ ensureContains(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS += "+
+ filepath.Join(out, "soong/.intermediates/foo/android_common_apex10000/dexpreopt/foo/oat/arm64/javalib.odex")+
+ ":"+
+ filepath.Join(out, "target/product/test_device/system/framework/oat/arm64/apex@myapex@javalib@foo.jar@classes.odex")+
+ " "+
+ filepath.Join(out, "soong/.intermediates/foo/android_common_apex10000/dexpreopt/foo/oat/arm64/javalib.vdex")+
+ ":"+
+ filepath.Join(out, "target/product/test_device/system/framework/oat/arm64/apex@myapex@javalib@foo.jar@classes.vdex")+
+ "\n")
}
func TestAndroidMk_RequiredModules(t *testing.T) {
@@ -9554,7 +9821,7 @@
}
`)
- apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, apexBundle)
var builder strings.Builder
data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
@@ -9578,7 +9845,7 @@
}
`)
- bundle := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ bundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
bundle.makeModulesToInstall = append(bundle.makeModulesToInstall, "foo")
data := android.AndroidMkDataForTest(t, ctx, bundle)
var builder strings.Builder
@@ -9630,7 +9897,7 @@
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.CompressedApex = proptools.BoolPtr(true)
}))
- javaTest := ctx.ModuleForTests(tc.name, "android_common").Module().(*java.Test)
+ javaTest := ctx.ModuleForTests(t, tc.name, "android_common").Module().(*java.Test)
data := android.AndroidMkEntriesForTest(t, ctx, javaTest)[0].EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
android.AssertStringPathsRelativeToTopEquals(t, "data", ctx.Config(), tc.expected_data, data)
})
@@ -9833,7 +10100,7 @@
// Verifies that the APEX depends on all the Make modules in the list.
func ensureContainsRequiredDeps(t *testing.T, ctx *android.TestContext, moduleName, variant string, deps []string) {
- a := ctx.ModuleForTests(moduleName, variant).Module().(*apexBundle)
+ a := ctx.ModuleForTests(t, moduleName, variant).Module().(*apexBundle)
for _, dep := range deps {
android.AssertStringListContains(t, "", a.makeModulesToInstall, dep)
}
@@ -9841,7 +10108,7 @@
// Verifies that the APEX does not depend on any of the Make modules in the list.
func ensureDoesNotContainRequiredDeps(t *testing.T, ctx *android.TestContext, moduleName, variant string, deps []string) {
- a := ctx.ModuleForTests(moduleName, variant).Module().(*apexBundle)
+ a := ctx.ModuleForTests(t, moduleName, variant).Module().(*apexBundle)
for _, dep := range deps {
android.AssertStringListDoesNotContain(t, "", a.makeModulesToInstall, dep)
}
@@ -9949,8 +10216,8 @@
}
}
- myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
- apex := result.ModuleForTests("myapex", "android_common_myapex")
+ myjavalib := result.ModuleForTests(t, "myjavalib", "android_common_apex29")
+ apex := result.ModuleForTests(t, "myapex", "android_common_myapex")
apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp")
javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp")
@@ -9999,7 +10266,7 @@
}
result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
- apex := result.ModuleForTests("myapex", "android_common_myapex")
+ apex := result.ModuleForTests(t, "myapex", "android_common_myapex")
apexStrictUpdatabilityCheck := apex.Output("lint_strict_updatability_check.stamp")
android.AssertStringDoesContain(t, "strict updatability check rule for myapex",
apexStrictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi")
@@ -10051,7 +10318,7 @@
android.FixtureMergeMockFs(fs),
).RunTestWithBp(t, bp)
- myapex := result.ModuleForTests("myapex", "android_common_myapex")
+ myapex := result.ModuleForTests(t, "myapex", "android_common_myapex")
lintReportInputs := strings.Join(myapex.Output("lint-report-xml.zip").Inputs.Strings(), " ")
android.AssertStringDoesContain(t,
"myapex lint report expected to contain that of the sdk library impl lib as an input",
@@ -10103,7 +10370,7 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
generateFsRule := mod.Rule("generateFsConfig")
cmd := generateFsRule.RuleParams.Command
@@ -10125,7 +10392,7 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
generateFsRule := mod.Rule("generateFsConfig")
cmd := generateFsRule.RuleParams.Command
@@ -10159,9 +10426,9 @@
expectedError: "Stub libraries should have a single apex_available.*myapex.*otherapex",
},
{
- desc: "stub library can be available to a core apex and a test apex",
+ desc: "stub library can be available to a core apex and a test apex using apex_available_name",
hasStubs: true,
- apexAvailable: `["myapex", "test_myapex"]`,
+ apexAvailable: `["myapex"]`,
},
}
bpTemplate := `
@@ -10186,25 +10453,28 @@
key: "apex.key",
updatable: false,
native_shared_libs: ["libfoo"],
+ apex_available_name: "myapex",
}
apex_key {
name: "apex.key",
}
`
for _, tc := range testCases {
- stubs := ""
- if tc.hasStubs {
- stubs = `stubs: {symbol_file: "libfoo.map.txt"},`
- }
- bp := fmt.Sprintf(bpTemplate, stubs, tc.apexAvailable)
- mockFsFixturePreparer := android.FixtureModifyMockFS(func(fs android.MockFS) {
- fs["system/sepolicy/apex/test_myapex-file_contexts"] = nil
+ t.Run(tc.desc, func(t *testing.T) {
+ stubs := ""
+ if tc.hasStubs {
+ stubs = `stubs: {symbol_file: "libfoo.map.txt"},`
+ }
+ bp := fmt.Sprintf(bpTemplate, stubs, tc.apexAvailable)
+ mockFsFixturePreparer := android.FixtureModifyMockFS(func(fs android.MockFS) {
+ fs["system/sepolicy/apex/test_myapex-file_contexts"] = nil
+ })
+ if tc.expectedError == "" {
+ testApex(t, bp, mockFsFixturePreparer)
+ } else {
+ testApexError(t, tc.expectedError, bp, mockFsFixturePreparer)
+ }
})
- if tc.expectedError == "" {
- testApex(t, bp, mockFsFixturePreparer)
- } else {
- testApexError(t, tc.expectedError, bp, mockFsFixturePreparer)
- }
}
}
@@ -10257,7 +10527,7 @@
}
`)
- inputs := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img").Implicits
+ inputs := result.ModuleForTests(t, "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")
@@ -10351,7 +10621,7 @@
}
`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
if len(copyCmds) != 14 {
@@ -10490,7 +10760,7 @@
}
`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
if len(copyCmds) != 18 {
@@ -10536,15 +10806,6 @@
}
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"],
@@ -10661,11 +10922,11 @@
}
`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 38 {
- t.Fatalf("Expected 38 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 32 {
+ t.Fatalf("Expected 32 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
@@ -10777,7 +11038,7 @@
}
`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
s := " " + combineAconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
@@ -10857,7 +11118,7 @@
}
`)
- mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
s := " " + combineAconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
@@ -10880,7 +11141,7 @@
t.Parallel()
checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
t.Helper()
- s := ctx.ModuleForTests("dex_bootjars", "android_common")
+ s := ctx.ModuleForTests(t, "dex_bootjars", "android_common")
foundLibfooJar := false
base := stem + ".jar"
for _, output := range s.AllOutputs() {
@@ -10898,14 +11159,14 @@
// Check that the boot jars of the selected apex are run through boot_jars_package_check
// This validates that the jars on the bootclasspath do not contain packages outside an allowlist
checkBootJarsPackageCheck := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
- platformBcp := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ platformBcp := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common")
bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
android.AssertStringMatches(t, "Could not find the correct boot dex jar in package check rule", bootJarsCheckRule.RuleParams.Command, "build/soong/scripts/check_boot_jars/package_allowed_list.txt.*"+expectedBootJar)
}
// Check that the boot jars used to generate the monolithic hiddenapi flags come from the selected apex
checkBootJarsForMonolithicHiddenapi := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
- monolithicHiddenapiFlagsCmd := ctx.ModuleForTests("platform-bootclasspath", "android_common").Output("out/soong/hiddenapi/hiddenapi-stub-flags.txt").RuleParams.Command
+ monolithicHiddenapiFlagsCmd := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common").Output("out/soong/hiddenapi/hiddenapi-stub-flags.txt").RuleParams.Command
android.AssertStringMatches(t, "Could not find the correct boot dex jar in monolithic hiddenapi flags generation command", monolithicHiddenapiFlagsCmd, "--boot-dex="+expectedBootJar)
}
@@ -11015,17 +11276,17 @@
{
desc: "Source apex com.android.foo is selected, bootjar should come from source java library",
selectedApexContributions: "foo.source.contributions",
- expectedBootJar: "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_apex10000/hiddenapi-modular/encoded/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_com.android.foo/hiddenapi-modular/encoded/framework-foo.jar",
},
{
desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.contributions",
- expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
},
{
desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.v2.contributions",
- expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
},
}
@@ -11070,18 +11331,18 @@
// for a mainline module family, check that only the flagged soong module is visible to make
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
- ret := "android_common_com.android.foo"
+ ret := "android_common_prebuilt_com.android.foo"
if moduleName == "com.google.android.foo" {
- ret = "android_common_com.google.android.foo_com.google.android.foo"
+ ret = "android_common_com.google.android.foo"
}
return ret
}
- visibleModule := ctx.ModuleForTests(visibleModuleName, variation(visibleModuleName)).Module()
+ visibleModule := ctx.ModuleForTests(t, visibleModuleName, variation(visibleModuleName)).Module()
android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
for _, hiddenModuleName := range hiddenModuleNames {
- hiddenModule := ctx.ModuleForTests(hiddenModuleName, variation(hiddenModuleName)).Module()
+ hiddenModule := ctx.ModuleForTests(t, hiddenModuleName, variation(hiddenModuleName)).Module()
android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
}
@@ -11207,6 +11468,16 @@
// 1. The contents of the selected apex_contributions are visible to make
// 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make
checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames)
+
+ // Check that source_apex_name is written as LOCAL_MODULE for make packaging
+ if tc.expectedVisibleModuleName == "prebuilt_com.google.android.foo.v2" {
+ apex := ctx.ModuleForTests(t, "prebuilt_com.google.android.foo.v2", "android_common_prebuilt_com.android.foo").Module()
+ entries := android.AndroidMkEntriesForTest(t, ctx, apex)[0]
+
+ expected := "com.google.android.foo"
+ actual := entries.EntryMap["LOCAL_MODULE"][0]
+ android.AssertStringEquals(t, "LOCAL_MODULE", expected, actual)
+ }
}
}
@@ -11217,19 +11488,19 @@
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleNames []string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
ret := "android_common_com.android.adservices"
- if moduleName == "com.google.android.foo" {
- ret = "android_common_com.google.android.foo_com.google.android.foo"
+ if moduleName == "com.google.android.adservices" || moduleName == "com.google.android.adservices.v2" {
+ ret = "android_common_prebuilt_com.android.adservices"
}
return ret
}
for _, visibleModuleName := range visibleModuleNames {
- visibleModule := ctx.ModuleForTests(visibleModuleName, variation(visibleModuleName)).Module()
+ visibleModule := ctx.ModuleForTests(t, visibleModuleName, variation(visibleModuleName)).Module()
android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
}
for _, hiddenModuleName := range hiddenModuleNames {
- hiddenModule := ctx.ModuleForTests(hiddenModuleName, variation(hiddenModuleName)).Module()
+ hiddenModule := ctx.ModuleForTests(t, hiddenModuleName, variation(hiddenModuleName)).Module()
android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
}
@@ -11293,13 +11564,13 @@
expectedHiddenModuleNames: []string{"com.google.android.adservices", "com.google.android.adservices.v2"},
},
{
- desc: "Prebuilt apex prebuilt_com.android.foo is selected",
+ desc: "Prebuilt apex prebuilt_com.android.adservices is selected",
selectedApexContributions: "adservices.prebuilt.contributions",
expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices"},
expectedHiddenModuleNames: []string{"com.google.android.adservices.v2"},
},
{
- desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected",
+ desc: "Prebuilt apex prebuilt_com.android.adservices.v2 is selected",
selectedApexContributions: "adservices.prebuilt.v2.contributions",
expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices.v2"},
expectedHiddenModuleNames: []string{"com.google.android.adservices"},
@@ -11401,12 +11672,12 @@
}
`+aconfigDeclarationLibraryString([]string{"bar", "baz", "qux", "quux"}))
- m := result.ModuleForTests("foo.stubs.source", "android_common")
+ m := result.ModuleForTests(t, "foo.stubs.source", "android_common")
outDir := "out/soong/.intermediates"
// Arguments passed to aconfig to retrieve the state of the flags defined in the
// textproto files
- aconfigFlagArgs := m.Output("released-flagged-apis-exportable.txt").Args["flags_path"]
+ aconfigFlagArgs := m.Output("released-flags-exportable.pb").Args["flags_path"]
// "bar-lib" is a static_lib of "foo" and is passed to metalava as classpath. Thus the
// cache file provided by the associated aconfig_declarations module "bar" should be passed
@@ -11466,7 +11737,7 @@
"packages/modules/common/build/allowed_deps.txt": nil,
}))
- ab := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*apexBundle)
+ ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
data := android.AndroidMkDataForTest(t, ctx, ab)
var builder strings.Builder
data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
@@ -11538,18 +11809,18 @@
}),
)
- baseModule := ctx.ModuleForTests("com.android.apex30", "android_common_com.android.apex30")
+ baseModule := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.android.apex30")
checkMinSdkVersion(t, baseModule, "30")
// Override module, but uses same min_sdk_version
- overridingModuleSameMinSdkVersion := ctx.ModuleForTests("com.android.apex30", "android_common_com.mycompany.android.apex30_com.mycompany.android.apex30")
- javalibApex30Variant := ctx.ModuleForTests("javalib", "android_common_apex30")
+ overridingModuleSameMinSdkVersion := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.mycompany.android.apex30_com.mycompany.android.apex30")
+ javalibApex30Variant := ctx.ModuleForTests(t, "javalib", "android_common_apex30")
checkMinSdkVersion(t, overridingModuleSameMinSdkVersion, "30")
checkHasDep(t, ctx, overridingModuleSameMinSdkVersion.Module(), javalibApex30Variant.Module())
// Override module, uses different min_sdk_version
- overridingModuleDifferentMinSdkVersion := ctx.ModuleForTests("com.android.apex30", "android_common_com.mycompany.android.apex31_com.mycompany.android.apex31")
- javalibApex31Variant := ctx.ModuleForTests("javalib", "android_common_apex31")
+ overridingModuleDifferentMinSdkVersion := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.mycompany.android.apex31_com.mycompany.android.apex31")
+ javalibApex31Variant := ctx.ModuleForTests(t, "javalib", "android_common_apex31")
checkMinSdkVersion(t, overridingModuleDifferentMinSdkVersion, "31")
checkHasDep(t, ctx, overridingModuleDifferentMinSdkVersion.Module(), javalibApex31Variant.Module())
}
@@ -11587,7 +11858,7 @@
}
`)
- java.CheckModuleHasDependency(t, res.TestContext, "myoverrideapex", "android_common_myoverrideapex_myoverrideapex", "foo")
+ java.CheckModuleHasDependency(t, res.TestContext, "myoverrideapex", "android_common_myoverrideapex", "foo")
}
func TestUpdatableApexMinSdkVersionCurrent(t *testing.T) {
@@ -11618,7 +11889,7 @@
android.FixtureMergeMockFs(fs),
).RunTest(t)
- ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
+ ldRule := result.ModuleForTests(t, "installedlib", "android_arm64_armv8-a_shared").Rule("ld")
android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared_current/libfoo.so")
installRules := result.InstallMakeRulesForTesting(t)
@@ -11919,400 +12190,66 @@
}
`, filesystem.PrepareForTestWithFilesystemBuildComponents)
- partition := result.ModuleForTests("myfilesystem", "android_common")
+ partition := result.ModuleForTests(t, "myfilesystem", "android_common")
fileList := android.ContentFromFileRuleForTests(t, result, partition.Output("fileList"))
android.AssertDeepEquals(t, "filesystem with apex", "apex/myapex.apex\n", fileList)
}
-func TestApexVerifyNativeImplementationLibs(t *testing.T) {
+func TestVintfFragmentInApex(t *testing.T) {
t.Parallel()
-
- extractDepenencyPathFromErrors := func(errs []error) []string {
- i := slices.IndexFunc(errs, func(err error) bool {
- return strings.Contains(err.Error(), "dependency path:")
- })
- if i < 0 {
- return nil
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ binaries: [ "mybin" ],
+ updatable: false,
}
- var dependencyPath []string
- for _, err := range errs[i+1:] {
- s := err.Error()
- lastSpace := strings.LastIndexByte(s, ' ')
- if lastSpace >= 0 {
- dependencyPath = append(dependencyPath, s[lastSpace+1:])
- }
+
+ cc_binary {
+ name: "mybin",
+ srcs: ["mybin.cpp"],
+ vintf_fragment_modules: ["my_vintf_fragment.xml"],
+ apex_available: [ "myapex" ],
}
- return dependencyPath
- }
- checkErrors := func(wantDependencyPath []string) func(t *testing.T, result *android.TestResult) {
- return func(t *testing.T, result *android.TestResult) {
- t.Helper()
- if len(result.Errs) == 0 {
- t.Fatalf("expected errors")
- }
- t.Log("found errors:")
- for _, err := range result.Errs {
- t.Log(err)
- }
- if g, w := result.Errs[0].Error(), "library in apex transitively linked against implementation library"; !strings.Contains(g, w) {
- t.Fatalf("expected error %q, got %q", w, g)
- }
- dependencyPath := extractDepenencyPathFromErrors(result.Errs)
- if g, w := dependencyPath, wantDependencyPath; !slices.Equal(g, w) {
- t.Errorf("expected dependency path %q, got %q", w, g)
- }
+ vintf_fragment {
+ name: "my_vintf_fragment.xml",
+ src: "my_vintf_fragment.xml",
}
- }
+ `)
- addToSharedLibs := func(module, lib string) func(bp *bpmodify.Blueprint) {
- return func(bp *bpmodify.Blueprint) {
- m := bp.ModulesByName(module)
- props, err := m.GetOrCreateProperty(bpmodify.List, "shared_libs")
- if err != nil {
- panic(err)
- }
- props.AddStringToList(lib)
+ generateFsRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+
+ // Ensure that vintf fragment file is being installed
+ ensureContains(t, cmd, "/etc/vintf/my_vintf_fragment.xml ")
+}
+
+func TestNoVintfFragmentInUpdatableApex(t *testing.T) {
+ t.Parallel()
+ testApexError(t, `VINTF fragment .* is not supported in updatable APEX`, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ key: "myapex.key",
+ binaries: [ "mybin" ],
+ updatable: true,
+ min_sdk_version: "29",
}
- }
- bpTemplate := `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["mylib"],
- rust_dyn_libs: ["libmyrust"],
- binaries: ["mybin", "myrustbin"],
- jni_libs: ["libjni"],
- apps: ["myapp"],
- updatable: false,
- }
+ cc_binary {
+ name: "mybin",
+ srcs: ["mybin.cpp"],
+ vintf_fragment_modules: ["my_vintf_fragment.xml"],
+ apex_available: [ "myapex" ],
+ min_sdk_version: "29",
+ }
- apex {
- name: "otherapex",
- key: "myapex.key",
- native_shared_libs: ["libotherapex"],
- updatable: false,
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["foo.cpp"],
- apex_available: ["myapex"],
- }
-
- cc_binary {
- name: "mybin",
- srcs: ["foo.cpp"],
- apex_available: ["myapex"],
- }
-
- rust_library {
- name: "libmyrust",
- crate_name: "myrust",
- srcs: ["src/lib.rs"],
- rustlibs: ["libmyrust_transitive_dylib"],
- rlibs: ["libmyrust_transitive_rlib"],
- apex_available: ["myapex"],
- }
-
- rust_library{
- name: "libmyrust_transitive_dylib",
- crate_name: "myrust_transitive_dylib",
- srcs: ["src/lib.rs"],
- apex_available: ["myapex"],
- }
-
- rust_library {
- name: "libmyrust_transitive_rlib",
- crate_name: "myrust_transitive_rlib",
- srcs: ["src/lib.rs"],
- apex_available: ["myapex"],
- }
-
- rust_binary {
- name: "myrustbin",
- srcs: ["src/main.rs"],
- apex_available: ["myapex"],
- }
-
- cc_library {
- name: "libbar",
- sdk_version: "current",
- srcs: ["bar.cpp"],
- apex_available: ["myapex"],
- stl: "none",
- }
-
- android_app {
- name: "myapp",
- jni_libs: ["libembeddedjni"],
- use_embedded_native_libs: true,
- sdk_version: "current",
- apex_available: ["myapex"],
- }
-
- cc_library {
- name: "libembeddedjni",
- sdk_version: "current",
- srcs: ["bar.cpp"],
- apex_available: ["myapex"],
- stl: "none",
- }
-
- cc_library {
- name: "libjni",
- sdk_version: "current",
- srcs: ["bar.cpp"],
- apex_available: ["myapex"],
- stl: "none",
- }
-
- cc_library {
- name: "libotherapex",
- sdk_version: "current",
- srcs: ["otherapex.cpp"],
- apex_available: ["otherapex"],
- stubs: {
- symbol_file: "libotherapex.map.txt",
- versions: ["1", "2", "3"],
- },
- stl: "none",
- }
-
- cc_library {
- name: "libplatform",
- sdk_version: "current",
- srcs: ["libplatform.cpp"],
- stubs: {
- symbol_file: "libplatform.map.txt",
- versions: ["1", "2", "3"],
- },
- stl: "none",
- system_shared_libs: [],
- }
- `
-
- testCases := []struct {
- name string
- bpModifier func(bp *bpmodify.Blueprint)
- dependencyPath []string
- }{
- {
- name: "library dependency in other apex",
- bpModifier: addToSharedLibs("mylib", "libotherapex#impl"),
- dependencyPath: []string{"myapex", "mylib", "libotherapex"},
- },
- {
- name: "transitive library dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("mylib", "libbar")(bp)
- addToSharedLibs("libbar", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "mylib", "libbar", "libotherapex"},
- },
- {
- name: "library dependency in platform",
- bpModifier: addToSharedLibs("mylib", "libplatform#impl"),
- dependencyPath: []string{"myapex", "mylib", "libplatform"},
- },
- {
- name: "jni library dependency in other apex",
- bpModifier: addToSharedLibs("libjni", "libotherapex#impl"),
- dependencyPath: []string{"myapex", "libjni", "libotherapex"},
- },
- {
- name: "transitive jni library dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libjni", "libbar")(bp)
- addToSharedLibs("libbar", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libjni", "libbar", "libotherapex"},
- },
- {
- name: "jni library dependency in platform",
- bpModifier: addToSharedLibs("libjni", "libplatform#impl"),
- dependencyPath: []string{"myapex", "libjni", "libplatform"},
- },
- {
- name: "transitive jni library dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libjni", "libbar")(bp)
- addToSharedLibs("libbar", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libjni", "libbar", "libplatform"},
- },
- {
- name: "app jni library dependency in other apex",
- bpModifier: addToSharedLibs("libembeddedjni", "libotherapex#impl"),
- dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libotherapex"},
- },
- {
- name: "transitive app jni library dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libembeddedjni", "libbar")(bp)
- addToSharedLibs("libbar", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libotherapex"},
- },
- {
- name: "app jni library dependency in platform",
- bpModifier: addToSharedLibs("libembeddedjni", "libplatform#impl"),
- dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libplatform"},
- },
- {
- name: "transitive app jni library dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libembeddedjni", "libbar")(bp)
- addToSharedLibs("libbar", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "myapp", "libembeddedjni", "libbar", "libplatform"},
- },
- {
- name: "binary dependency in other apex",
- bpModifier: addToSharedLibs("mybin", "libotherapex#impl"),
- dependencyPath: []string{"myapex", "mybin", "libotherapex"},
- },
- {
- name: "transitive binary dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("mybin", "libbar")(bp)
- addToSharedLibs("libbar", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "mybin", "libbar", "libotherapex"},
- },
- {
- name: "binary dependency in platform",
- bpModifier: addToSharedLibs("mybin", "libplatform#impl"),
- dependencyPath: []string{"myapex", "mybin", "libplatform"},
- },
- {
- name: "transitive binary dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("mybin", "libbar")(bp)
- addToSharedLibs("libbar", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "mybin", "libbar", "libplatform"},
- },
-
- {
- name: "rust library dependency in other apex",
- bpModifier: addToSharedLibs("libmyrust", "libotherapex#impl"),
- dependencyPath: []string{"myapex", "libmyrust", "libotherapex"},
- },
- {
- name: "transitive rust library dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libmyrust", "libbar")(bp)
- addToSharedLibs("libbar", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libmyrust", "libbar", "libotherapex"},
- },
- {
- name: "rust library dependency in platform",
- bpModifier: addToSharedLibs("libmyrust", "libplatform#impl"),
- dependencyPath: []string{"myapex", "libmyrust", "libplatform"},
- },
- {
- name: "transitive rust library dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libmyrust", "libbar")(bp)
- addToSharedLibs("libbar", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libmyrust", "libbar", "libplatform"},
- },
- {
- name: "transitive rust library dylib dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libmyrust_transitive_dylib", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_dylib", "libotherapex"},
- },
- {
- name: "transitive rust library dylib dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libmyrust_transitive_dylib", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_dylib", "libplatform"},
- },
- {
- name: "transitive rust library rlib dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libmyrust_transitive_rlib", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_rlib", "libotherapex"},
- },
- {
- name: "transitive rust library rlib dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("libmyrust_transitive_rlib", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "libmyrust", "libmyrust_transitive_rlib", "libplatform"},
- },
- {
- name: "rust binary dependency in other apex",
- bpModifier: addToSharedLibs("myrustbin", "libotherapex#impl"),
- dependencyPath: []string{"myapex", "myrustbin", "libotherapex"},
- },
- {
- name: "transitive rust binary dependency in other apex",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("myrustbin", "libbar")(bp)
- addToSharedLibs("libbar", "libotherapex#impl")(bp)
- },
- dependencyPath: []string{"myapex", "myrustbin", "libbar", "libotherapex"},
- },
- {
- name: "rust binary dependency in platform",
- bpModifier: addToSharedLibs("myrustbin", "libplatform#impl"),
- dependencyPath: []string{"myapex", "myrustbin", "libplatform"},
- },
- {
- name: "transitive rust binary dependency in platform",
- bpModifier: func(bp *bpmodify.Blueprint) {
- addToSharedLibs("myrustbin", "libbar")(bp)
- addToSharedLibs("libbar", "libplatform#impl")(bp)
- },
- dependencyPath: []string{"myapex", "myrustbin", "libbar", "libplatform"},
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- t.Parallel()
- bp, err := bpmodify.NewBlueprint("", []byte(bpTemplate))
- if err != nil {
- t.Fatal(err)
- }
- if testCase.bpModifier != nil {
- func() {
- defer func() {
- if r := recover(); r != nil {
- t.Fatalf("panic in bpModifier: %v", r)
- }
- }()
- testCase.bpModifier(bp)
- }()
- }
- android.GroupFixturePreparers(
- android.PrepareForTestWithAndroidBuildComponents,
- cc.PrepareForTestWithCcBuildComponents,
- java.PrepareForTestWithDexpreopt,
- rust.PrepareForTestWithRustDefaultModules,
- PrepareForTestWithApexBuildComponents,
- prepareForTestWithMyapex,
- prepareForTestWithOtherapex,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
- }),
- ).ExtendWithErrorHandler(android.FixtureCustomErrorHandler(checkErrors(testCase.dependencyPath))).
- RunTestWithBp(t, bp.String())
- })
- }
+ vintf_fragment {
+ name: "my_vintf_fragment.xml",
+ src: "my_vintf_fragment.xml",
+ }
+ `)
}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 71a8246..97644e6 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -242,6 +242,7 @@
apex_available: [
"com.android.art",
],
+ min_sdk_version: "33",
}
`, content)
}
@@ -291,6 +292,7 @@
apex_available: [
"com.android.art",
],
+ min_sdk_version: "33",
compile_dex: true,
}
`, content, prefer)
@@ -320,6 +322,7 @@
})
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ `all_apex_contributions`,
`art-bootclasspath-fragment`,
`com.android.art.key`,
`dex2oatd`,
@@ -327,7 +330,7 @@
// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
- module := result.ModuleForTests("dex_bootjars", "android_common")
+ module := result.ModuleForTests(t, "dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
@@ -418,22 +421,24 @@
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
- ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_com.android.art", []string{
+ ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_prebuilt_com.android.art", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
})
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ `all_apex_contributions`,
`art-bootclasspath-fragment`,
`com.android.art.key`,
`dex2oatd`,
+ `prebuilt_art-bootclasspath-fragment`,
`prebuilt_com.android.art`,
})
// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
- module := result.ModuleForTests("dex_bootjars", "android_common")
+ module := result.ModuleForTests(t, "dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
@@ -586,20 +591,20 @@
t.Parallel()
result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
- java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_prebuilt_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
})
- java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_prebuilt_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- module := result.ModuleForTests("dex_bootjars", "android_common")
+ module := result.ModuleForTests(t, "dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
}
@@ -698,17 +703,18 @@
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`myapex.key`,
`mybootclasspathfragment`,
})
- apex := result.ModuleForTests("myapex", "android_common_myapex")
+ apex := result.ModuleForTests(t, "myapex", "android_common_myapex")
apexRule := apex.Rule("apexRule")
copyCommands := apexRule.Args["copy_commands"]
// Make sure that the fragment provides the hidden API encoded dex jars to the APEX.
- fragment := result.Module("mybootclasspathfragment", "android_common_apex10000")
+ fragment := result.Module("mybootclasspathfragment", "android_common_myapex")
info, _ := android.OtherModuleProvider(result, fragment, java.BootclasspathFragmentApexContentInfoProvider)
@@ -724,8 +730,8 @@
android.AssertStringDoesContain(t, name+" apex copy command", copyCommands, expectedCopyCommand)
}
- checkFragmentExportedDexJar("foo", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/foo.jar")
- checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/bar.jar")
+ checkFragmentExportedDexJar("foo", "out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/hiddenapi-modular/encoded/foo.jar")
+ checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/hiddenapi-modular/encoded/bar.jar")
}
func getDexJarPath(result *android.TestResult, name string) string {
@@ -856,10 +862,10 @@
}
`)
- java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -871,7 +877,7 @@
quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.exportable.module_lib")
// Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags.
- fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+ fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common_myapex")
rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
command := rule.RuleParams.Command
@@ -1029,14 +1035,14 @@
}
`)
- java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
"android-non-updatable.stubs",
"android-non-updatable.stubs.module_lib",
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1048,7 +1054,7 @@
// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
// API flags.
- fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+ fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common_myapex")
rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
command := rule.RuleParams.Command
@@ -1203,14 +1209,14 @@
}
`)
- java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
"android-non-updatable.stubs",
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
"android-non-updatable.stubs.test_module_lib",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1219,7 +1225,7 @@
// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
// API flags.
- fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+ fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common_myapex")
rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
command := rule.RuleParams.Command
@@ -1358,10 +1364,10 @@
}
`)
- java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
"prebuilt_sdk_module-lib_current_android-non-updatable",
@@ -1377,7 +1383,7 @@
// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
// API flags.
- fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+ fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common_myapex")
rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
command := rule.RuleParams.Command
@@ -1460,7 +1466,7 @@
}
`)
- fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+ fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common_myapex")
classPathProtoContent := android.ContentFromFileRuleForTests(t, result.TestContext, fragment.Output("bootclasspath.pb.textproto"))
// foo
ensureContains(t, classPathProtoContent, `jars {
diff --git a/apex/builder.go b/apex/builder.go
index 41e2511..23c2ed8 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -20,12 +20,14 @@
"path"
"path/filepath"
"runtime"
+ "slices"
"sort"
"strconv"
"strings"
"android/soong/aconfig"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/java"
"github.com/google/blueprint"
@@ -70,9 +72,10 @@
pctx.HostBinToolVariable("extract_apks", "extract_apks")
pctx.HostBinToolVariable("make_f2fs", "make_f2fs")
pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
- pctx.HostBinToolVariable("make_erofs", "make_erofs")
+ pctx.HostBinToolVariable("make_erofs", "mkfs.erofs")
pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
pctx.HostBinToolVariable("dexdeps", "dexdeps")
+ pctx.HostBinToolVariable("apex_ls", "apex-ls")
pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests")
pctx.HostBinToolVariable("deapexer", "deapexer")
pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
@@ -210,11 +213,11 @@
}, "image_dir", "readelf")
apexSepolicyTestsRule = pctx.StaticRule("apexSepolicyTestsRule", blueprint.RuleParams{
- Command: `${deapexer} --debugfs_path ${debugfs_static} list -Z ${in} > ${out}.fc` +
- ` && ${apex_sepolicy_tests} -f ${out}.fc && touch ${out}`,
- CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
+ Command: `${apex_ls} -Z ${in} > ${out}.fc` +
+ ` && ${apex_sepolicy_tests} -f ${out}.fc --partition ${partition_tag} && touch ${out}`,
+ CommandDeps: []string{"${apex_sepolicy_tests}", "${apex_ls}"},
Description: "run apex_sepolicy_tests",
- })
+ }, "partition_tag")
apexLinkerconfigValidationRule = pctx.StaticRule("apexLinkerconfigValidationRule", blueprint.RuleParams{
Command: `${conv_linker_config} validate --type apex ${image_dir} && touch ${out}`,
@@ -275,6 +278,12 @@
})
files = append(files, newApexFile(ctx, apexAconfigFile, "aconfig_flags", "etc", etc, nil))
+ // To enable fingerprint, we need to have v2 storage files. The default version is 1.
+ storageFilesVersion := 1
+ if ctx.Config().ReleaseFingerprintAconfigPackages() {
+ storageFilesVersion = 2
+ }
+
for _, info := range createStorageInfo {
outputFile := android.PathForModuleOut(ctx, info.Output_file)
ctx.Build(pctx, android.BuildParams{
@@ -286,6 +295,7 @@
"container": ctx.ModuleName(),
"file_type": info.File_type,
"cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "),
+ "version": strconv.Itoa(storageFilesVersion),
},
})
files = append(files, newApexFile(ctx, outputFile, info.File_type, "etc", etc, nil))
@@ -337,8 +347,8 @@
if err != nil {
ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to be an int, but got %s", defaultVersion)
}
- if defaultVersionInt%10 != 0 {
- ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to end in a zero, but got %s", defaultVersion)
+ if defaultVersionInt%10 != 0 && defaultVersionInt%10 != 9 {
+ ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to end in a zero or a nine, but got %s", defaultVersion)
}
variantVersion := []rune(*a.properties.Variant_version)
if len(variantVersion) != 1 || variantVersion[0] < '0' || variantVersion[0] > '9' {
@@ -418,8 +428,6 @@
ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", fileContexts.String())
}
- useFileContextsAsIs := proptools.Bool(a.properties.Use_file_contexts_as_is)
-
output := android.PathForModuleOut(ctx, "file_contexts")
rule := android.NewRuleBuilder(pctx, ctx)
@@ -436,11 +444,9 @@
rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
// new line
rule.Command().Text("echo").Text(">>").Output(output)
- if !useFileContextsAsIs {
- // force-label /apex_manifest.pb and /
- rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(labelForManifest).Text(">>").Output(output)
- rule.Command().Text("echo").Text("/").Text(labelForRoot).Text(">>").Output(output)
- }
+ // force-label /apex_manifest.pb and /
+ rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(labelForManifest).Text(">>").Output(output)
+ rule.Command().Text("echo").Text("/").Text(labelForRoot).Text(">>").Output(output)
rule.Build("file_contexts."+a.Name(), "Generate file_contexts")
return output
@@ -518,9 +524,10 @@
})
}
-func isVintfFragment(fi apexFile) bool {
+func shouldApplyAssembleVintf(fi apexFile) bool {
isVintfFragment, _ := path.Match("etc/vintf/*", fi.path())
- return isVintfFragment
+ _, fromVintfFragmentModule := fi.module.(*android.VintfFragmentModule)
+ return isVintfFragment && !fromVintfFragmentModule
}
func runAssembleVintf(ctx android.ModuleContext, vintfFragment android.Path) android.Path {
@@ -534,6 +541,65 @@
return processed
}
+// installApexSystemServerFiles installs dexpreopt and dexjar files for system server classpath entries
+// provided by the apex. They are installed here instead of in library module because there may be multiple
+// variants of the library, generally one for the "main" apex and another with a different min_sdk_version
+// for the Android Go version of the apex. Both variants would attempt to install to the same locations,
+// and the library variants cannot determine which one should. The apex module is better equipped to determine
+// if it is "selected".
+// This assumes that the jars produced by different min_sdk_version values are identical, which is currently
+// true but may not be true if the min_sdk_version difference between the variants spans version that changed
+// the dex format.
+func (a *apexBundle) installApexSystemServerFiles(ctx android.ModuleContext) {
+ // If performInstalls is set this module is responsible for creating the install rules.
+ performInstalls := a.GetOverriddenBy() == "" && !a.testApex && a.installable()
+ // TODO(b/234351700): Remove once ART does not have separated debug APEX, or make the selection
+ // explicit in the ART Android.bp files.
+ if ctx.Config().UseDebugArt() {
+ if ctx.ModuleName() == "com.android.art" {
+ performInstalls = false
+ }
+ } else {
+ if ctx.ModuleName() == "com.android.art.debug" {
+ performInstalls = false
+ }
+ }
+
+ psi := android.PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDeps(func(am android.Module) {
+ if info, exists := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); exists {
+ psi = info
+ }
+ })
+
+ if len(psi.GetSelectedModulesForApiDomain(ctx.ModuleName())) > 0 {
+ performInstalls = false
+ }
+
+ for _, fi := range a.filesInfo {
+ for _, install := range fi.systemServerDexpreoptInstalls {
+ var installedFile android.InstallPath
+ if performInstalls {
+ installedFile = ctx.InstallFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
+ } else {
+ // Another module created the install rules, but this module should still depend on
+ // the installed locations.
+ installedFile = install.InstallDirOnDevice.Join(ctx, install.InstallFileOnDevice)
+ }
+ a.extraInstalledFiles = append(a.extraInstalledFiles, installedFile)
+ a.extraInstalledPairs = append(a.extraInstalledPairs, installPair{install.OutputPathOnHost, installedFile})
+ ctx.PackageFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
+ }
+ if performInstalls {
+ for _, dexJar := range fi.systemServerDexJars {
+ // Copy the system server dex jar to a predefined location where dex2oat will find it.
+ android.CopyFileRule(ctx, dexJar,
+ android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJar.Base()))
+ }
+ }
+ }
+}
+
// buildApex creates build rules to build an APEX using apexer.
func (a *apexBundle) buildApex(ctx android.ModuleContext) {
suffix := imageApexSuffix
@@ -544,7 +610,7 @@
imageDir := android.PathForModuleOut(ctx, "image"+suffix)
- installSymbolFiles := (!ctx.Config().KatiEnabled() || a.ExportedToMake()) && a.installable()
+ installSymbolFiles := a.ExportedToMake() && a.installable()
// set of dependency module:location mappings
installMapSet := make(map[string]bool)
@@ -571,7 +637,7 @@
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
// Copy the file into APEX
- if !a.testApex && isVintfFragment(fi) {
+ if !a.testApex && shouldApplyAssembleVintf(fi) {
// copy the output of assemble_vintf instead of the original
vintfFragment := runAssembleVintf(ctx, fi.builtFile)
copyCommands = append(copyCommands, "cp -f "+vintfFragment.String()+" "+destPath)
@@ -595,7 +661,7 @@
} else {
if installSymbolFiles {
// store installedPath. symlinks might be created if required.
- installedPath = apexDir.Join(ctx, fi.installDir, fi.stem())
+ installedPath = ctx.InstallFile(apexDir.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
}
}
@@ -911,9 +977,8 @@
}
var validations android.Paths
validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile, imageDir))
- // TODO(b/279688635) deapexer supports [ext4]
- if !a.skipValidation(apexSepolicyTests) && suffix == imageApexSuffix && ext4 == a.payloadFsType {
- validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile))
+ if !a.skipValidation(apexSepolicyTests) && android.InList(a.payloadFsType, []fsType{ext4, erofs}) {
+ validations = append(validations, runApexSepolicyTests(ctx, a, unsignedOutputFile))
}
if !a.testApex && len(a.properties.Unwanted_transitive_deps) > 0 {
validations = append(validations,
@@ -978,9 +1043,9 @@
a.SkipInstall()
}
+ installDeps := slices.Concat(a.compatSymlinks, a.extraInstalledFiles)
// Install to $OUT/soong/{target,host}/.../apex.
- a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
- a.compatSymlinks...)
+ a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile, installDeps...)
// installed-files.txt is dist'ed
a.installedFilesFile = a.buildInstalledFilesFile(ctx, a.outputFile, imageDir)
@@ -1037,7 +1102,7 @@
}
depInfos := android.DepNameToDepInfoMap{}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this.
// As soon as the dependency graph crosses the APEX boundary, don't go further.
@@ -1046,7 +1111,7 @@
// Skip dependencies that are only available to APEXes; they are developed with updatability
// in mind and don't need manual approval.
- if to.(android.ApexModule).NotAvailableForPlatform() {
+ if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform {
return !externalDep
}
@@ -1064,18 +1129,9 @@
depInfos[to.Name()] = info
} else {
toMinSdkVersion := "(no version)"
- if m, ok := to.(interface {
- MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
- }); ok {
- if v := m.MinSdkVersion(ctx); !v.IsNone() {
- toMinSdkVersion = v.String()
- }
- } else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
- // TODO(b/175678607) eliminate the use of MinSdkVersion returning
- // string
- if v := m.MinSdkVersion(); v != "" {
- toMinSdkVersion = v
- }
+ if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok &&
+ !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil {
+ toMinSdkVersion = info.MinSdkVersion.ApiLevel.String()
}
depInfos[to.Name()] = android.ApexModuleDepInfo{
To: to.Name(),
@@ -1203,16 +1259,35 @@
return timestamp
}
+// Can't use PartitionTag() because PartitionTag() returns the partition this module is actually
+// installed (e.g. PartitionTag() may return "system" for vendor apex when vendor is linked to /system/vendor)
+func (a *apexBundle) partition() string {
+ if a.SocSpecific() {
+ return "vendor"
+ } else if a.DeviceSpecific() {
+ return "odm"
+ } else if a.ProductSpecific() {
+ return "product"
+ } else if a.SystemExtSpecific() {
+ return "system_ext"
+ } else {
+ return "system"
+ }
+}
+
// Runs apex_sepolicy_tests
//
-// $ deapexer list -Z {apex_file} > {file_contexts}
+// $ apex-ls -Z {apex_file} > {file_contexts}
// $ apex_sepolicy_tests -f {file_contexts}
-func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.Path) android.Path {
+func runApexSepolicyTests(ctx android.ModuleContext, a *apexBundle, apexFile android.Path) android.Path {
timestamp := android.PathForModuleOut(ctx, "apex_sepolicy_tests.timestamp")
ctx.Build(pctx, android.BuildParams{
Rule: apexSepolicyTestsRule,
Input: apexFile,
Output: timestamp,
+ Args: map[string]string{
+ "partition_tag": a.partition(),
+ },
})
return timestamp
}
@@ -1238,7 +1313,7 @@
Input: apexFile,
Output: timestamp,
Args: map[string]string{
- "partition_tag": a.PartitionTag(ctx.DeviceConfig()),
+ "partition_tag": a.partition(),
},
})
return timestamp
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index f367174..c2f2fc5 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -198,15 +198,13 @@
result := preparer.RunTest(t)
- artFragment := result.Module("art-bootclasspath-fragment", "android_common_apex10000")
+ artFragment := result.Module("art-bootclasspath-fragment", "android_common_com.android.art")
artBaz := result.Module("baz", "android_common_apex10000")
artQuuz := result.Module("quuz", "android_common_apex10000")
- myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
+ myFragment := result.Module("mybootclasspath-fragment", "android_common_myapex")
myBar := result.Module("bar", "android_common_apex10000")
- other := result.Module("othersdklibrary", "android_common_apex10000")
-
otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
platformFoo := result.Module("quuz", "android_common")
@@ -240,7 +238,11 @@
t.Run("art:baz, art:quuz, my:bar, foo", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, artQuuz, myBar, platformFoo}, []android.Module{artFragment, myFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, artQuuz, myBar, platformFoo},
+ []android.Module{artFragment, myFragment},
+ map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectFragmentElement(myFragment, myBar),
@@ -249,32 +251,16 @@
assertElementsEquals(t, "elements", expectedElements, elements)
})
- // Verify that CreateClasspathElements detects when an apex has multiple fragments.
- t.Run("multiple fragments for same apex", func(t *testing.T) {
- t.Parallel()
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{artFragment, artFragment})
- android.FailIfNoMatchingErrors(t, "apex com.android.art has multiple fragments, art-bootclasspath-fragment{.*} and art-bootclasspath-fragment{.*}", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
-
- // Verify that CreateClasspathElements detects when a library is in multiple fragments.
- t.Run("library from multiple fragments", func(t *testing.T) {
- t.Parallel()
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{other}, []android.Module{artFragment, myFragment})
- android.FailIfNoMatchingErrors(t, "library othersdklibrary{.*} is in two separate fragments, art-bootclasspath-fragment{.*} and mybootclasspath-fragment{.*}", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
-
// Verify that CreateClasspathElements detects when a fragment's contents are not contiguous and
// are separated by a library from another fragment.
t.Run("discontiguous separated by fragment", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, myBar, artQuuz, platformFoo}, []android.Module{artFragment, myFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, myBar, artQuuz, platformFoo},
+ []android.Module{artFragment, myFragment},
+ map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectFragmentElement(myFragment, myBar),
@@ -289,7 +275,11 @@
t.Run("discontiguous separated by library", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, platformFoo, artQuuz, myBar}, []android.Module{artFragment, myFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, platformFoo, artQuuz, myBar},
+ []android.Module{artFragment, myFragment},
+ map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectLibraryElement(platformFoo),
@@ -305,7 +295,11 @@
t.Run("no fragment for apex", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, otherApexLibrary}, []android.Module{artFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, otherApexLibrary},
+ []android.Module{artFragment},
+ map[android.Module]string{artBaz: "com.android.art", otherApexLibrary: "otherapex"},
+ map[string]android.Module{"com.android.art": artFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz),
}
diff --git a/apex/container_test.go b/apex/container_test.go
index 395793f..b19e050 100644
--- a/apex/container_test.go
+++ b/apex/container_test.go
@@ -29,6 +29,7 @@
func TestApexDepsContainers(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -156,7 +157,7 @@
}
for _, c := range testcases {
- m := result.ModuleForTests(c.moduleName, c.variant)
+ m := result.ModuleForTests(t, c.moduleName, c.variant)
containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider)
belongingContainers := containers.BelongingContainers()
checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
@@ -166,6 +167,7 @@
func TestNonUpdatableApexDepsContainers(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -271,7 +273,7 @@
}
for _, c := range testcases {
- m := result.ModuleForTests(c.moduleName, c.variant)
+ m := result.ModuleForTests(t, c.moduleName, c.variant)
containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider)
belongingContainers := containers.BelongingContainers()
checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
@@ -281,6 +283,7 @@
func TestUpdatableAndNonUpdatableApexesIdenticalMinSdkVersion(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -334,7 +337,7 @@
}
`)
- fooApexVariant := result.ModuleForTests("foo", "android_common_apex30")
+ fooApexVariant := result.ModuleForTests(t, "foo", "android_common_apex30")
containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), fooApexVariant.Module(), android.ContainersInfoProvider)
belongingContainers := containers.BelongingContainers()
checkContainerMatch(t, "foo", "system", true, android.InList(android.SystemContainer, belongingContainers))
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index b51bb36..2c7c459 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -151,7 +151,7 @@
}
result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
- dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
+ dexBootJars := result.ModuleForTests(t, "dex_bootjars", "android_common")
rule := dexBootJars.Output(ruleFile)
inputs := rule.Implicits.Strings()
@@ -176,7 +176,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+ "out/soong/.intermediates/art-bootclasspath-fragment/android_common_com.android.art/art-bootclasspath-fragment/boot.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
}
@@ -215,7 +215,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ "out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
}
@@ -396,17 +396,17 @@
{
desc: "Source apex com.android.art is selected, profile should come from source java library",
selectedArtApexContributions: "art.source.contributions",
- expectedProfile: "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+ expectedProfile: "out/soong/.intermediates/art-bootclasspath-fragment/android_common_com.android.art/art-bootclasspath-fragment/boot.prof",
},
{
desc: "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.contributions",
- expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
},
{
desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.v2.contributions",
- expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
},
}
for _, tc := range testCases {
@@ -419,7 +419,7 @@
android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", tc.selectedArtApexContributions),
).RunTestWithBp(t, bp)
- dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
+ dexBootJars := result.ModuleForTests(t, "dex_bootjars", "android_common")
rule := dexBootJars.Output(ruleFile)
inputs := rule.Implicits.Strings()
diff --git a/apex/key.go b/apex/key.go
index e4214f0..cc66a13 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -18,6 +18,7 @@
"fmt"
"android/soong/android"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -29,8 +30,16 @@
func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+ ctx.RegisterParallelSingletonModuleType("all_apex_certs", allApexCertsFactory)
}
+type ApexKeyInfo struct {
+ PublicKeyFile android.Path
+ PrivateKeyFile android.Path
+}
+
+var ApexKeyInfoProvider = blueprint.NewProvider[ApexKeyInfo]()
+
type apexKey struct {
android.ModuleBase
@@ -93,6 +102,11 @@
m.publicKeyFile.String(), pubKeyName, m.privateKeyFile, privKeyName)
return
}
+
+ android.SetProvider(ctx, ApexKeyInfoProvider, ApexKeyInfo{
+ PublicKeyFile: m.publicKeyFile,
+ PrivateKeyFile: m.privateKeyFile,
+ })
}
type apexKeyEntry struct {
@@ -155,3 +169,64 @@
android.WriteFileRuleVerbatim(ctx, path, entry.String())
return path
}
+
+var (
+ pemToDer = pctx.AndroidStaticRule("pem_to_der",
+ blueprint.RuleParams{
+ Command: `openssl x509 -inform PEM -outform DER -in $in -out $out`,
+ Description: "Convert certificate from PEM to DER format",
+ },
+ )
+)
+
+// all_apex_certs is a singleton module that collects the certs of all apexes in the tree.
+// It provides two types of output files
+// 1. .pem: This is usually the checked-in x509 certificate in PEM format
+// 2. .der: This is DER format of the certificate, and is generated from the PEM certificate using `openssl x509`
+func allApexCertsFactory() android.SingletonModule {
+ m := &allApexCerts{}
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ return m
+}
+
+type allApexCerts struct {
+ android.SingletonModuleBase
+}
+
+func (_ *allApexCerts) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var avbpubkeys android.Paths
+ var certificatesPem android.Paths
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if apex, ok := m.(*apexBundle); ok {
+ pem, _ := apex.getCertificateAndPrivateKey(ctx)
+ if !android.ExistentPathForSource(ctx, pem.String()).Valid() {
+ if ctx.Config().AllowMissingDependencies() {
+ return
+ } else {
+ ctx.ModuleErrorf("Path %s is not valid\n", pem.String())
+ }
+ }
+ certificatesPem = append(certificatesPem, pem)
+ // avbpubkey for signing the apex payload
+ avbpubkeys = append(avbpubkeys, apex.publicKeyFile)
+ }
+ })
+ certificatesPem = android.SortedUniquePaths(certificatesPem) // For hermiticity
+ avbpubkeys = android.SortedUniquePaths(avbpubkeys) // For hermiticity
+ var certificatesDer android.Paths
+ for index, certificatePem := range certificatesPem {
+ certificateDer := android.PathForModuleOut(ctx, fmt.Sprintf("x509.%v.der", index))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: pemToDer,
+ Input: certificatePem,
+ Output: certificateDer,
+ })
+ certificatesDer = append(certificatesDer, certificateDer)
+ }
+ ctx.SetOutputFiles(certificatesPem, ".pem")
+ ctx.SetOutputFiles(certificatesDer, ".der")
+ ctx.SetOutputFiles(avbpubkeys, ".avbpubkey")
+}
+
+func (_ *allApexCerts) GenerateSingletonBuildActions(ctx android.SingletonContext) {
+}
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 9f9b0b4..d79af86 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -23,7 +23,6 @@
"android/soong/dexpreopt"
"android/soong/java"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -165,12 +164,12 @@
android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
}
- android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
- android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
- android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/index.csv"}, info.IndexPaths)
+ android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
+ android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
+ android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/index.csv"}, info.IndexPaths)
- android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/filtered-stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
- android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/bar-fragment/android_common_apex30/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
}
// TestPlatformBootclasspath_LegacyPrebuiltFragment verifies that the
@@ -240,8 +239,8 @@
pbcp := result.Module("myplatform-bootclasspath", "android_common")
info, _ := android.OtherModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
- android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
- android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
}
func TestPlatformBootclasspathDependencies(t *testing.T) {
@@ -388,7 +387,7 @@
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
- CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
// source vs prebuilt selection metadata module
`platform:all_apex_contributions`,
@@ -401,17 +400,17 @@
// Needed for generating the boot image.
`platform:dex2oatd`,
- // The configured contents of BootJars.
- `com.android.art:baz`,
- `com.android.art:quuz`,
+ // The configured contents of BootJars, via their apexes if necessary.
+ `platform:com.android.art`,
+ `platform:com.android.art`,
`platform:foo`,
- // The configured contents of ApexBootJars.
- `myapex:bar`,
+ // The configured contents of ApexBootJars, via their apex.
+ `platform:myapex`,
- // The fragments.
- `com.android.art:art-bootclasspath-fragment`,
- `myapex:my-bootclasspath-fragment`,
+ // The fragments via their apexes.
+ `platform:com.android.art`,
+ `platform:myapex`,
// Impl lib of sdk_library for transitive srcjar generation
`platform:foo.impl`,
@@ -429,7 +428,7 @@
// of AlwaysUsePrebuiltsSdk(). The second is a normal library that is unaffected. The order
// matters, so that the dependencies resolved by the platform_bootclasspath matches the
// configured list.
- java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
+ java.FixtureConfigureApexBootJars("myapex:foo"),
java.PrepareForTestWithJavaSdkLibraryFiles,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
@@ -479,6 +478,7 @@
name: "myapex",
src: "myapex.apex",
exported_bootclasspath_fragments: ["mybootclasspath-fragment"],
+ prefer: true,
}
// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
@@ -544,12 +544,11 @@
java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
// The configured contents of BootJars.
- "myapex:prebuilt_foo",
- "myapex:bar",
+ "prebuilt_myapex:prebuilt_foo",
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
- CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
// source vs prebuilt selection metadata module
`platform:all_apex_contributions`,
@@ -561,39 +560,17 @@
// Not a prebuilt as no prebuilt existed when it was added.
"platform:legacy.core.platform.api.stubs.exportable",
- // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
- // modules when available as it does not know which one will be preferred.
- "myapex:foo",
- "myapex:prebuilt_foo",
+ // The prebuilt library via the apex.
+ "platform:prebuilt_myapex",
- // Only a source module exists.
- "myapex:bar",
-
- // The fragments.
- "myapex:mybootclasspath-fragment",
- "myapex:prebuilt_mybootclasspath-fragment",
+ // The fragments via the apex.
+ "platform:prebuilt_myapex",
// Impl lib of sdk_library for transitive srcjar generation
"platform:foo.impl",
})
}
-// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
-//
-// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
-// name of the apex, or platform is it is not part of an apex and <module> is the module name.
-func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
- t.Helper()
- module := ctx.ModuleForTests(name, variant).Module()
- modules := []android.Module{}
- ctx.VisitDirectDeps(module, func(m blueprint.Module) {
- modules = append(modules, m.(android.Module))
- })
-
- pairs := java.ApexNamePairsFromModules(ctx, modules)
- android.AssertDeepEquals(t, "module dependencies", expected, pairs)
-}
-
// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
// by setting generate_classpaths_proto property to false.
@@ -653,7 +630,7 @@
true, // proto should be generated
"myapex:foo", // apex doesn't generate its own config, so must be in platform_bootclasspath
"bootclasspath.pb",
- "out/soong/target/product/test_device/system/etc/classpaths",
+ "out/target/product/test_device/system/etc/classpaths",
)
}
@@ -665,7 +642,7 @@
prepareForTestWithMyapex,
java.FixtureConfigureApexBootJars("myapex:foo"),
).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- `dependency "foo" of "myplatform-bootclasspath" missing variant`)).
+ `module "myplatform-bootclasspath" variant ".*": failed to find module "foo" in apex "myapex"`)).
RunTestWithBp(t, `
apex {
name: "myapex",
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index f93eada..fdd9a75 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -15,11 +15,15 @@
package apex
import (
+ "fmt"
+ "slices"
+ "sort"
"strconv"
"strings"
"android/soong/android"
"android/soong/dexpreopt"
+ "android/soong/filesystem"
"android/soong/java"
"android/soong/provenance"
@@ -59,10 +63,12 @@
// Properties common to both prebuilt_apex and apex_set.
prebuiltCommonProperties *PrebuiltCommonProperties
- installDir android.InstallPath
- installFilename string
- installedFile android.InstallPath
- outputApex android.WritablePath
+ installDir android.InstallPath
+ installFilename string
+ installedFile android.InstallPath
+ extraInstalledFiles android.InstallPaths
+ extraInstalledPairs installPairs
+ outputApex android.WritablePath
// fragment for this apex for apexkeys.txt
apexKeysPath android.WritablePath
@@ -70,8 +76,16 @@
// Installed locations of symlinks for backward compatibility.
compatSymlinks android.InstallPaths
- hostRequired []string
- requiredModuleNames []string
+ // systemServerDexpreoptInstalls stores the list of dexpreopt artifacts for a system server jar.
+ systemServerDexpreoptInstalls []java.DexpreopterInstall
+
+ // systemServerDexJars stores the list of dexjars for system server jars in the prebuilt for use when
+ // dexpreopting system server jars that are later in the system server classpath.
+ systemServerDexJars android.Paths
+
+ // Certificate information of any apk packaged inside the prebuilt apex.
+ // This will be nil if the prebuilt apex does not contain any apk.
+ apkCertsFile android.WritablePath
}
type sanitizedPrebuilt interface {
@@ -188,9 +202,8 @@
// initApexFilesForAndroidMk initializes the prebuiltCommon.requiredModuleNames field with the install only deps of the prebuilt apex
func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) {
// If this apex contains a system server jar, then the dexpreopt artifacts should be added as required
- for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
- p.requiredModuleNames = append(p.requiredModuleNames, install.FullModuleName())
- }
+ p.systemServerDexpreoptInstalls = append(p.systemServerDexpreoptInstalls, p.Dexpreopter.ApexSystemServerDexpreoptInstalls()...)
+ p.systemServerDexJars = append(p.systemServerDexJars, p.Dexpreopter.ApexSystemServerDexJars()...)
}
// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex
@@ -218,38 +231,63 @@
}
}
-func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) {
- entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...)
+// installApexSystemServerFiles installs dexpreopt files for system server classpath entries
+// provided by the apex. They are installed here instead of in library module because there may be multiple
+// variants of the library, generally one for the "main" apex and another with a different min_sdk_version
+// for the Android Go version of the apex. Both variants would attempt to install to the same locations,
+// and the library variants cannot determine which one should. The apex module is better equipped to determine
+// if it is "selected".
+// This assumes that the jars produced by different min_sdk_version values are identical, which is currently
+// true but may not be true if the min_sdk_version difference between the variants spans version that changed
+// the dex format.
+func (p *prebuiltCommon) installApexSystemServerFiles(ctx android.ModuleContext) {
+ performInstalls := android.IsModulePreferred(ctx.Module())
+
+ for _, install := range p.systemServerDexpreoptInstalls {
+ var installedFile android.InstallPath
+ if performInstalls {
+ installedFile = ctx.InstallFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
+ } else {
+ installedFile = install.InstallDirOnDevice.Join(ctx, install.InstallFileOnDevice)
+ }
+ p.extraInstalledFiles = append(p.extraInstalledFiles, installedFile)
+ p.extraInstalledPairs = append(p.extraInstalledPairs, installPair{install.OutputPathOnHost, installedFile})
+ ctx.PackageFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost)
+ }
+
+ for _, dexJar := range p.systemServerDexJars {
+ // Copy the system server dex jar to a predefined location where dex2oat will find it.
+ android.CopyFileRule(ctx, dexJar,
+ android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJar.Base()))
+ }
}
func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
entriesList := []android.AndroidMkEntries{
{
- Class: "ETC",
- OutputFile: android.OptionalPathForPath(p.outputApex),
- Include: "$(BUILD_PREBUILT)",
- Host_required: p.hostRequired,
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(p.outputApex),
+ Include: "$(BUILD_PREBUILT)",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_PATH", p.installDir.String())
entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
entries.SetPath("LOCAL_SOONG_INSTALLED_MODULE", p.installedFile)
- entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", p.outputApex.String()+":"+p.installedFile.String())
+ installPairs := append(installPairs{{p.outputApex, p.installedFile}}, p.extraInstalledPairs...)
+ entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", installPairs.String())
entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...)
entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String())
- p.addRequiredModules(entries)
+ if p.apkCertsFile != nil {
+ entries.SetString("LOCAL_APKCERTS_FILE", p.apkCertsFile.String())
+ }
+
},
},
},
}
- // Add the dexpreopt artifacts to androidmk
- for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
- entriesList = append(entriesList, install.ToMakeEntries())
- }
-
return entriesList
}
@@ -258,6 +296,14 @@
len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0
}
+type appInPrebuiltApexDepTag struct {
+ blueprint.BaseDependencyTag
+}
+
+func (appInPrebuiltApexDepTag) ExcludeFromVisibilityEnforcement() {}
+
+var appInPrebuiltApexTag = appInPrebuiltApexDepTag{}
+
// prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents.
func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
@@ -265,6 +311,7 @@
for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
prebuiltDep := android.PrebuiltNameFromSource(dep)
ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep)
+ ctx.AddDependency(module, fragmentInApexTag, prebuiltDep)
}
for _, dep := range p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments {
@@ -274,95 +321,47 @@
}
// Implements android.DepInInSameApex
-func (p *prebuiltCommon) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- tag := ctx.OtherModuleDependencyTag(dep)
+func (m *prebuiltCommon) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return ApexPrebuiltDepInSameApexChecker{}
+}
+
+type ApexPrebuiltDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m ApexPrebuiltDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
_, ok := tag.(exportedDependencyTag)
return ok
}
-// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
-// specific variant and checks that they are supported.
-//
-// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are
-// associated with the apex specific variant using the ApexInfoProvider for later retrieval.
-//
-// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
-// across prebuilt_apex modules. That is because there is no way to determine whether two
-// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
-// been built from different source at different times or they could have been built with different
-// build options that affect the libraries.
-//
-// While it may be possible to provide sufficient information to determine whether two prebuilt_apex
-// modules were compatible it would be a lot of work and would not provide much benefit for a couple
-// of reasons:
-// - The number of prebuilt_apex modules that will be exporting files for the same module will be
-// low as the prebuilt_apex only exports files for the direct dependencies that require it and
-// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
-// few com.android.art* apex files that contain the same contents and could export files for the
-// same modules but only one of them needs to do so. Contrast that with source apex modules which
-// need apex specific variants for every module that contributes code to the apex, whether direct
-// or indirect.
-// - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
-// extra copying of files. Contrast that with source apex modules that has to build each variant
-// from source.
-func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
- // Collect the list of dependencies.
- var dependencies []android.ApexModule
- mctx.WalkDeps(func(child, parent android.Module) bool {
- // If the child is not in the same apex as the parent then exit immediately and do not visit
- // any of the child's dependencies.
- if !android.IsDepInSameApex(mctx, parent, child) {
- return false
- }
-
- tag := mctx.OtherModuleDependencyTag(child)
- depName := mctx.OtherModuleName(child)
+func (p *prebuiltCommon) checkExportedDependenciesArePrebuilts(ctx android.ModuleContext) {
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ tag := ctx.OtherModuleDependencyTag(dep)
+ depName := ctx.OtherModuleName(dep)
if exportedTag, ok := tag.(exportedDependencyTag); ok {
propertyName := exportedTag.name
// It is an error if the other module is not a prebuilt.
- if !android.IsModulePrebuilt(child) {
- mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
- return false
+ if !android.IsModulePrebuilt(dep) {
+ ctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
}
// It is an error if the other module is not an ApexModule.
- if _, ok := child.(android.ApexModule); !ok {
- mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
- return false
+ if _, ok := dep.(android.ApexModule); !ok {
+ ctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
}
}
- // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific
- // variant.
- if _, ok := child.(android.ApexModule); !ok {
- return false
- }
-
- // Strip off the prebuilt_ prefix if present before storing content to ensure consistent
- // behavior whether there is a corresponding source module present or not.
- depName = android.RemoveOptionalPrebuiltPrefix(depName)
-
- // Add the module to the list of dependencies that need to have an APEX variant.
- dependencies = append(dependencies, child.(android.ApexModule))
-
- return true
})
+}
- android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
-
- // Create an ApexInfo for the prebuilt_apex.
- apexVariationName := p.ApexVariationName()
- apexInfo := android.ApexInfo{
- ApexVariationName: apexVariationName,
- InApexVariants: []string{apexVariationName},
+// generateApexInfo returns an android.ApexInfo configuration suitable for dependencies of this apex.
+func (p *prebuiltCommon) generateApexInfo(ctx generateApexInfoContext) android.ApexInfo {
+ return android.ApexInfo{
+ ApexVariationName: "prebuilt_" + p.ApexVariationName(),
+ BaseApexName: p.ApexVariationName(),
ForPrebuiltApex: true,
}
-
- // Mark the dependencies of this module as requiring a variant for this module.
- for _, am := range dependencies {
- am.BuildForApex(apexInfo)
- }
}
type Prebuilt struct {
@@ -451,6 +450,12 @@
ApexFileProperties
PrebuiltCommonProperties
+
+ // List of apps that are bundled inside this prebuilt apex.
+ // This will be used to create the certificate info of those apps for apkcerts.txt
+ // This dependency will only be used for apkcerts.txt processing.
+ // Notably, building the prebuilt apex will not build the source app.
+ Apps []string
}
func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool {
@@ -564,12 +569,27 @@
func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
p.prebuiltApexContentsDeps(ctx)
+ for _, app := range p.properties.Apps {
+ ctx.AddDependency(p, appInPrebuiltApexTag, app)
+ }
}
-var _ ApexInfoMutator = (*Prebuilt)(nil)
+var _ ApexTransitionMutator = (*Prebuilt)(nil)
-func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
- p.apexInfoMutator(mctx)
+func (p *Prebuilt) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{p.generateApexInfo(ctx)}
+}
+
+func (p *Prebuilt) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
+
+func (p *Prebuilt) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return p.generateApexInfo(ctx)
+}
+
+func (p *Prebuilt) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
}
// creates the build rules to deapex the prebuilt, and returns a deapexerInfo
@@ -635,6 +655,8 @@
validateApexClasspathFragments(ctx)
}
+ p.checkExportedDependenciesArePrebuilts(ctx)
+
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module()))
@@ -676,27 +698,69 @@
}
if p.installable() {
- p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...)
+ p.installApexSystemServerFiles(ctx)
+ installDeps := slices.Concat(p.compatSymlinks, p.extraInstalledFiles)
+ p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, installDeps...)
p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
}
+ p.addApkCertsInfo(ctx)
+
ctx.SetOutputFiles(android.Paths{p.outputApex}, "")
+
+ android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{p.apexKeysPath})
+}
+
+// `addApkCertsInfo` sets a provider that will be used to create apkcerts.txt
+func (p *Prebuilt) addApkCertsInfo(ctx android.ModuleContext) {
+ formatLine := func(cert java.Certificate, name, partition string) string {
+ pem := cert.AndroidMkString()
+ var key string
+ if cert.Key == nil {
+ key = ""
+ } else {
+ key = cert.Key.String()
+ }
+ return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
+ }
+
+ // Determine if this prebuilt_apex contains any .apks
+ var appInfos java.AppInfos
+ ctx.VisitDirectDepsProxyWithTag(appInPrebuiltApexTag, func(app android.ModuleProxy) {
+ if appInfo, ok := android.OtherModuleProvider(ctx, app, java.AppInfoProvider); ok {
+ appInfos = append(appInfos, *appInfo)
+ } else {
+ ctx.ModuleErrorf("App %s does not set AppInfoProvider\n", app.Name())
+ }
+ })
+ sort.Slice(appInfos, func(i, j int) bool {
+ return appInfos[i].InstallApkName < appInfos[j].InstallApkName
+ })
+
+ if len(appInfos) == 0 {
+ return
+ }
+
+ // Set a provider for use by `android_device`.
+ // `android_device` will create an apkcerts.txt with the list of installed apps for that device.
+ android.SetProvider(ctx, java.AppInfosProvider, appInfos)
+
+ // Set a Make variable for legacy apkcerts.txt creation
+ // p.apkCertsFile will become `LOCAL_APKCERTS_FILE`
+ var lines []string
+ for _, appInfo := range appInfos {
+ lines = append(lines, formatLine(appInfo.Certificate, appInfo.InstallApkName+".apk", p.PartitionTag(ctx.DeviceConfig())))
+ }
+ if len(lines) > 0 {
+ p.apkCertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
+ android.WriteFileRule(ctx, p.apkCertsFile, strings.Join(lines, "\n"))
+ }
}
func (p *Prebuilt) ProvenanceMetaDataFile() android.Path {
return p.provenanceMetaDataFile
}
-// prebuiltApexExtractorModule is a private module type that is only created by the prebuilt_apex
-// module. It extracts the correct apex to use and makes it available for use by apex_set.
-type prebuiltApexExtractorModule struct {
- android.ModuleBase
-
- properties ApexExtractorProperties
-
- extractedApex android.WritablePath
-}
-
// extract registers the build actions to extract an apex from .apks file
// returns the path of the extracted apex
func extract(ctx android.ModuleContext, apexSet android.Path, prerelease *bool) android.Path {
@@ -803,10 +867,22 @@
a.prebuiltApexContentsDeps(ctx)
}
-var _ ApexInfoMutator = (*ApexSet)(nil)
+var _ ApexTransitionMutator = (*ApexSet)(nil)
-func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) {
- a.apexInfoMutator(mctx)
+func (a *ApexSet) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{a.generateApexInfo(ctx)}
+}
+
+func (a *ApexSet) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
+
+func (a *ApexSet) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return a.generateApexInfo(ctx)
+}
+
+func (a *ApexSet) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
}
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -863,7 +939,8 @@
a.installDir = android.PathForModuleInstall(ctx, "apex")
if a.installable() {
- a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex)
+ a.installApexSystemServerFiles(ctx)
+ a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex, a.extraInstalledFiles...)
}
// in case that apex_set replaces source apex (using prefer: prop)
@@ -874,12 +951,6 @@
}
ctx.SetOutputFiles(android.Paths{a.outputApex}, "")
-}
-type systemExtContext struct {
- android.ModuleContext
-}
-
-func (*systemExtContext) SystemExtSpecific() bool {
- return true
+ android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{a.apexKeysPath})
}
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index 7dbac5f..61f79d6 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -108,6 +108,7 @@
})
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`myapex.key`,
`mysystemserverclasspathfragment`,
@@ -166,6 +167,7 @@
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`myapex.key`,
`mysystemserverclasspathfragment`,
@@ -278,19 +280,19 @@
ctx := result.TestContext
- java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_mysystemserverclasspathfragment`,
})
- java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -438,13 +440,13 @@
ctx := result.TestContext
- java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -455,7 +457,7 @@
}
func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
- dexpreopt := ctx.ModuleForTests(moduleName, variant).Rule("dexpreopt")
+ dexpreopt := ctx.ModuleForTests(t, moduleName, variant).Rule("dexpreopt")
actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
if expected != actual {
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
@@ -463,9 +465,126 @@
}
func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) {
- dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName)
+ dexpreopt := ctx.ModuleForTests(t, apexName, "android_common_prebuilt_"+apexName).Rule("dexpreopt." + moduleName)
actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
if expected != actual {
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
}
}
+
+func TestCheckSystemServerOrderWithArtApex(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ java.PrepareForTestWithDexpreopt,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithArtApex,
+ java.FixtureConfigureBootJars("com.android.art:framework-art"),
+ dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-apex1", "com.android.art:service-art"),
+ java.FixtureWithLastReleaseApis("baz"),
+ )
+
+ // Creates a com.android.art apex with a bootclasspath fragment and a systemserverclasspath fragment, and a
+ // com.android.apex1 prebuilt whose bootclasspath fragment depends on the com.android.art bootclasspath fragment.
+ // Verifies that the checkSystemServerOrder doesn't get confused by the bootclasspath dependencies and report
+ // that service-apex1 depends on service-art.
+ result := preparers.RunTestWithBp(t, `
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ systemserverclasspath_fragments: ["art-systemserverclasspath-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["framework-art"],
+ apex_available: [
+ "com.android.art",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ java_library {
+ name: "framework-art",
+ apex_available: ["com.android.art"],
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+
+ systemserverclasspath_fragment {
+ name: "art-systemserverclasspath-fragment",
+ apex_available: ["com.android.art"],
+ contents: ["service-art"],
+ }
+
+ java_library {
+ name: "service-art",
+ srcs: ["a.java"],
+ apex_available: ["com.android.art"],
+ compile_dex: true,
+ }
+
+ prebuilt_apex {
+ name: "com.android.apex1",
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ exported_bootclasspath_fragments: ["com.android.apex1-bootclasspath-fragment"],
+ exported_systemserverclasspath_fragments: ["com.android.apex1-systemserverclasspath-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "com.android.apex1-bootclasspath-fragment",
+ visibility: ["//visibility:public"],
+ apex_available: ["com.android.apex1"],
+ contents: ["framework-apex1"],
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ hidden_api: {
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ stub_flags: "hiddenapi/stub-flags.csv",
+ all_flags: "hiddenapi/all-flags.csv",
+ },
+ }
+
+ java_import {
+ name: "framework-apex1",
+ apex_available: ["com.android.apex1"],
+ }
+
+ prebuilt_systemserverclasspath_fragment {
+ name: "com.android.apex1-systemserverclasspath-fragment",
+ apex_available: ["com.android.apex1"],
+ contents: ["service-apex1"],
+ }
+
+ java_import {
+ name: "service-apex1",
+ installable: true,
+ apex_available: ["com.android.apex1"],
+ sdk_version: "current",
+ }`)
+
+ _ = result
+}
diff --git a/apex/testing.go b/apex/testing.go
index 63c5b69..a22f640 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -22,6 +22,9 @@
android.FixtureRegisterWithContext(registerApexBuildComponents),
android.FixtureRegisterWithContext(registerApexKeyBuildComponents),
android.FixtureRegisterWithContext(registerApexDepsInfoComponents),
+ android.FixtureAddTextFile("all_apex_certs/Android.bp", `
+ all_apex_certs { name: "all_apex_certs" }
+ `),
// Additional files needed in tests that disallow non-existent source files.
// This includes files that are needed by all, or at least most, instances of an apex module type.
android.MockFS{
@@ -30,6 +33,8 @@
"build/soong/scripts/gen_ndk_backedby_apex.sh": nil,
// Needed by prebuilt_apex.
"build/soong/scripts/unpack-prebuilt-apex.sh": nil,
+ // Needed by all_apex_certs
+ "build/make/target/product/security/testkey.x509.pem": nil,
}.AddToFixture(),
android.PrepareForTestWithBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", testDefaultUpdatableModuleVersion),
)
diff --git a/bin/get_build_vars b/bin/get_build_vars
new file mode 100755
index 0000000..aa887c7
--- /dev/null
+++ b/bin/get_build_vars
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# 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.
+
+# Get the value of build variables. The values are printed in a format suitable
+# for use in the import_build_vars function in build/make/shell_utils.sh
+#
+# For absolute variables, prefix the variable name with a '/'
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+$TOP/build/soong/soong_ui.bash --dumpvars-mode \
+ --vars="$(printf '%s\n' "$@" | grep -v '^/')" \
+ --abs-vars="$(printf '%s\n' "$@" | grep '^/' | sed 's:^/::')" \
+ --var-prefix= \
+ --abs-var-prefix=
+
+exit $?
diff --git a/bin/mm b/bin/mm
index 6461b1e..6f1c934 100755
--- a/bin/mm
+++ b/bin/mm
@@ -19,6 +19,6 @@
require_top
-_wrap_build "$TOP/build/soong/soong_ui.bash" --build-mode --modules-in-a-dir-no-deps --dir="$(pwd)" "$@"
+_wrap_build "$TOP/build/soong/soong_ui.bash" --build-mode --modules-in-a-dir --dir="$(pwd)" "$@"
exit $?
diff --git a/bin/mmm b/bin/mmm
index ab3a632..d9190e5 100755
--- a/bin/mmm
+++ b/bin/mmm
@@ -19,6 +19,6 @@
require_top
-_wrap_build "$TOP/build/soong/soong_ui.bash" --build-mode --modules-in-dirs-no-deps --dir="$(pwd)" "$@"
+_wrap_build "$TOP/build/soong/soong_ui.bash" --build-mode --modules-in-dirs --dir="$(pwd)" "$@"
exit $?
diff --git a/bin/soongdbg b/bin/soongdbg
index 0807291..dad5137 100755
--- a/bin/soongdbg
+++ b/bin/soongdbg
@@ -450,13 +450,17 @@
def main():
+ global SOONG_DEBUG_DATA_FILENAME
parser = argparse.ArgumentParser()
+ parser.add_argument("-f", "--debug-file", nargs=1, help="location of the debug info file",
+ default=[SOONG_DEBUG_DATA_FILENAME])
subparsers = parser.add_subparsers(required=True, dest="command")
for name in sorted(COMMANDS.keys()):
command = COMMANDS[name]
subparser = subparsers.add_parser(name, help=command.help)
command.args(subparser)
args = parser.parse_args()
+ SOONG_DEBUG_DATA_FILENAME = args.debug_file[0]
COMMANDS[args.command].run(args)
sys.exit(0)
diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go
index 8ecea98..d78a907 100644
--- a/bloaty/bloaty.go
+++ b/bloaty/bloaty.go
@@ -84,8 +84,8 @@
func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var deps android.Paths
- ctx.VisitAllModules(func(m android.Module) {
- if !m.ExportedToMake() {
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
+ if !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).ExportedToMake {
return
}
filePaths, ok := android.OtherModuleProvider(ctx, m, fileSizeMeasurerKey)
@@ -105,13 +105,11 @@
}
})
+ protoFilenamePath := android.PathForOutput(ctx, protoFilename)
ctx.Build(pctx, android.BuildParams{
Rule: bloatyMerger,
Inputs: android.SortedUniquePaths(deps),
- Output: android.PathForOutput(ctx, protoFilename),
+ Output: protoFilenamePath,
})
-}
-
-func (singleton *sizesSingleton) MakeVars(ctx android.MakeVarsContext) {
- ctx.DistForGoalWithFilename("checkbuild", android.PathForOutput(ctx, protoFilename), protoFilename)
+ ctx.DistForGoalWithFilename("checkbuild", protoFilenamePath, protoFilename)
}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 3b7073e..deb465d 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -60,6 +60,12 @@
ctx.RegisterModuleType("bpf", BpfFactory)
}
+type BpfInfo struct {
+ SubDir string
+}
+
+var BpfInfoProvider = blueprint.NewProvider[BpfInfo]()
+
var PrepareForTestWithBpf = android.FixtureRegisterWithContext(registerBpfBuildComponents)
// BpfModule interface is used by the apex package to gather information from a bpf module.
@@ -230,7 +236,9 @@
ctx.PackageFile(installDir, obj.Base(), obj)
}
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
+ android.SetProvider(ctx, BpfInfoProvider, BpfInfo{
+ SubDir: bpf.SubDir(),
+ })
ctx.SetOutputFiles(bpf.objs, "")
}
diff --git a/bpf/libbpf/libbpf_prog.go b/bpf/libbpf/libbpf_prog.go
index 3b26d46..44013e5 100644
--- a/bpf/libbpf/libbpf_prog.go
+++ b/bpf/libbpf/libbpf_prog.go
@@ -239,8 +239,6 @@
ctx.PackageFile(installDir, obj.Base(), obj)
}
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
-
ctx.SetOutputFiles(libbpf.objs, "")
}
diff --git a/cc/Android.bp b/cc/Android.bp
index 3b29ae8..1ac5a4a 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -36,6 +36,7 @@
"linkable.go",
"lto.go",
"makevars.go",
+ "misc_disted_files.go",
"orderfile.go",
"prebuilt.go",
"proto.go",
diff --git a/cc/afdo.go b/cc/afdo.go
index 14d105e..9be3918 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -65,8 +65,8 @@
}
func getFdoProfilePathFromDep(ctx ModuleContext) string {
- fdoProfileDeps := ctx.GetDirectDepsWithTag(FdoProfileTag)
- if len(fdoProfileDeps) > 0 && fdoProfileDeps[0] != nil {
+ fdoProfileDeps := ctx.GetDirectDepsProxyWithTag(FdoProfileTag)
+ if len(fdoProfileDeps) > 0 {
if info, ok := android.OtherModuleProvider(ctx, fdoProfileDeps[0], FdoProfileProvider); ok {
return info.Path.String()
}
@@ -96,13 +96,20 @@
flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
// Flags for Flow Sensitive AutoFDO
flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
+ flags.Local.LdFlags = append([]string{"-Wl,-mllvm,-enable-fs-discriminator=true"}, flags.Local.LdFlags...)
// TODO(b/266595187): Remove the following feature once it is enabled in LLVM by default.
flags.Local.CFlags = append([]string{"-mllvm", "-improved-fs-discriminator=true"}, flags.Local.CFlags...)
+ flags.Local.LdFlags = append([]string{"-Wl,-mllvm,-improved-fs-discriminator=true"}, flags.Local.LdFlags...)
}
if fdoProfilePath := getFdoProfilePathFromDep(ctx); fdoProfilePath != "" {
// The flags are prepended to allow overriding.
profileUseFlag := fmt.Sprintf(afdoFlagsFormat, fdoProfilePath)
flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
+ // Salvage stale profile by fuzzy matching and use the remapped location for sample profile query.
+ flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile=true"}, flags.Local.CFlags...)
+ flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile-max-callsites=2000"}, flags.Local.CFlags...)
+ // Salvage stale profile by fuzzy matching renamed functions.
+ flags.Local.CFlags = append([]string{"-mllvm", "--salvage-unused-profile=true"}, flags.Local.CFlags...)
flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
@@ -163,7 +170,7 @@
}
// TODO(b/324141705): this is designed to prevent propagating AFDO from static libraries that have afdo: true set, but
- // it should be m.static() && !m.staticBinary() so that static binaries use AFDO variants of dependencies.
+ // it should be m.staticLibrary() so that static binaries use AFDO variants of dependencies.
if m.static() {
return ""
}
@@ -188,7 +195,7 @@
if variation == "" {
// The empty variation is either a module that has enabled AFDO for itself, or the non-AFDO
// variant of a dependency.
- if m.afdo.afdoEnabled() && !(m.static() && !m.staticBinary()) && !m.Host() {
+ if m.afdo.afdoEnabled() && !m.staticLibrary() && !m.Host() {
m.afdo.addDep(ctx, ctx.ModuleName())
}
} else {
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index 0679d13..d2d5584 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -94,9 +94,9 @@
afdoLtoLdFlag := "-Wl,-plugin-opt,-import-instr-limit=40"
noAfdoLtoLdFlag := "-Wl,-plugin-opt,-import-instr-limit=5"
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
- libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
- libBarAfdoVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariant := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libBarAfdoVariant := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static_afdo-libTest")
// Check cFlags of afdo-enabled module and the afdo-variant of its static deps
cFlags := libTest.Rule("cc").Args["cFlags"]
@@ -138,8 +138,8 @@
}
// Verify non-afdo variant exists and doesn't contain afdo
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, profileSampleCFlag) {
@@ -166,9 +166,9 @@
}
// Verify that the arm variant does not have FDO since the fdo_profile module only has a profile for arm64
- libTest32 := result.ModuleForTests("libTest", "android_arm_armv7-a-neon_shared")
- libFooAfdoVariant32 := result.ModuleForTests("libFoo", "android_arm_armv7-a-neon_static_afdo-libTest_lto-thin")
- libBarAfdoVariant32 := result.ModuleForTests("libBar", "android_arm_armv7-a-neon_static_afdo-libTest_lto-thin")
+ libTest32 := result.ModuleForTests(t, "libTest", "android_arm_armv7-a-neon_shared")
+ libFooAfdoVariant32 := result.ModuleForTests(t, "libFoo", "android_arm_armv7-a-neon_static_afdo-libTest_lto-thin")
+ libBarAfdoVariant32 := result.ModuleForTests(t, "libBar", "android_arm_armv7-a-neon_static_afdo-libTest_lto-thin")
cFlags = libTest32.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, profileSampleCFlag) {
@@ -215,9 +215,9 @@
}
// Verify that the host variants don't enable afdo
- libTestHost := result.ModuleForTests("libTest", result.Config.BuildOSTarget.String()+"_shared")
- libFooHost := result.ModuleForTests("libFoo", result.Config.BuildOSTarget.String()+"_static_lto-thin")
- libBarHost := result.ModuleForTests("libBar", result.Config.BuildOSTarget.String()+"_static_lto-thin")
+ libTestHost := result.ModuleForTests(t, "libTest", result.Config.BuildOSTarget.String()+"_shared")
+ libFooHost := result.ModuleForTests(t, "libFoo", result.Config.BuildOSTarget.String()+"_static_lto-thin")
+ libBarHost := result.ModuleForTests(t, "libBar", result.Config.BuildOSTarget.String()+"_static_lto-thin")
cFlags = libTestHost.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, profileSampleCFlag) {
@@ -301,9 +301,9 @@
}.AddToFixture(),
).RunTestWithBp(t, bp)
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static").Module()
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared").Module()
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static").Module()
if !hasDirectDep(result, libTest, libFoo.Module()) {
t.Errorf("libTest missing dependency on non-afdo variant of libFoo")
@@ -412,13 +412,13 @@
}.AddToFixture(),
).RunTestWithBp(t, bp)
- fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
+ fooArm := result.ModuleForTests(t, "foo", "android_arm_armv7-a-neon_shared")
fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
}
- fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
+ fooArm64 := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_shared")
fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
@@ -476,11 +476,11 @@
expectedCFlagLibTest := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
expectedCFlagLibBar := "-fprofile-sample-use=afdo_profiles_package/libBar.afdo"
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
- libFooAfdoVariantWithLibTest := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariantWithLibTest := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static_afdo-libTest")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
- libFooAfdoVariantWithLibBar := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_shared")
+ libFooAfdoVariantWithLibBar := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static_afdo-libBar")
// Check cFlags of afdo-enabled module and the afdo-variant of its static deps
cFlags := libTest.Rule("cc").Args["cFlags"]
@@ -543,9 +543,9 @@
// -funique-internal-linkage-names.
expectedCFlag := "-funique-internal-linkage-names"
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
- libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
- libBarAfdoVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariant := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libBarAfdoVariant := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static_afdo-libTest")
// Check cFlags of afdo-enabled module and the afdo-variant of its static deps
cFlags := libTest.Rule("cc").Args["cFlags"]
@@ -572,8 +572,8 @@
}
// Verify non-afdo variant exists and doesn't contain afdo
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 8037272..b016788 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -231,7 +231,7 @@
} else if library.shared() {
entries.Class = "SHARED_LIBRARIES"
entries.SetString("LOCAL_SOONG_TOC", library.toc().String())
- if !library.buildStubs() && library.unstrippedOutputFile != nil {
+ if !library.BuildStubs() && library.unstrippedOutputFile != nil {
entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String())
}
if len(library.Properties.Overrides) > 0 {
@@ -244,10 +244,6 @@
entries.Class = "HEADER_LIBRARIES"
}
- if library.distFile != nil {
- entries.DistFiles = android.MakeDefaultDistFiles(library.distFile)
- }
-
library.androidMkWriteExportedFlags(entries)
library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
@@ -260,16 +256,16 @@
entries.SetString("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputFile.String())
}
- if library.shared() && !library.buildStubs() {
+ if library.shared() && !library.BuildStubs() {
ctx.subAndroidMk(config, entries, library.baseInstaller)
} else {
- if library.buildStubs() && library.stubsVersion() != "" {
- entries.SubName = "." + library.stubsVersion()
+ if library.BuildStubs() && library.StubsVersion() != "" {
+ entries.SubName = "." + library.StubsVersion()
}
// library.makeUninstallable() depends on this to bypass HideFromMake() for
// static libraries.
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- if library.buildStubs() {
+ if library.BuildStubs() {
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
}
}
@@ -281,10 +277,10 @@
// very early stage in the boot process).
if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.NotInPlatform() &&
!ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.InVendorOrProduct() && !ctx.static() {
- if library.buildStubs() && library.isLatestStubVersion() {
+ if library.BuildStubs() && library.isLatestStubVersion() {
entries.SubName = ""
}
- if !library.buildStubs() {
+ if !library.BuildStubs() {
entries.SubName = ".bootstrap"
}
}
@@ -336,7 +332,6 @@
ctx.subAndroidMk(config, entries, binary.baseInstaller)
entries.Class = "EXECUTABLES"
- entries.DistFiles = binary.distFiles
entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile.String())
if len(binary.symlinks) > 0 {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", binary.symlinks...)
@@ -423,7 +418,7 @@
entries.SubName = ndkLibrarySuffix + "." + c.apiLevel.String()
entries.Class = "SHARED_LIBRARIES"
- if !c.buildStubs() {
+ if !c.BuildStubs() {
entries.Disabled = true
return
}
diff --git a/cc/api_level.go b/cc/api_level.go
index 7dc0213..fa8dfaf 100644
--- a/cc/api_level.go
+++ b/cc/api_level.go
@@ -51,7 +51,7 @@
return apiLevel
}
-func nativeApiLevelFromUser(ctx android.BaseModuleContext,
+func NativeApiLevelFromUser(ctx android.BaseModuleContext,
raw string) (android.ApiLevel, error) {
if raw == "minimum" {
@@ -69,7 +69,7 @@
func nativeApiLevelOrPanic(ctx android.BaseModuleContext,
raw string) android.ApiLevel {
- value, err := nativeApiLevelFromUser(ctx, raw)
+ value, err := NativeApiLevelFromUser(ctx, raw)
if err != nil {
panic(err.Error())
}
diff --git a/cc/binary.go b/cc/binary.go
index 4b77bea..608251a 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -104,8 +104,8 @@
// Output archive of gcno coverage information
coverageOutputFile android.OptionalPath
- // Location of the files that should be copied to dist dir when requested
- distFiles android.TaggedDistFiles
+ // Location of the file that should be copied to dist dir when no explicit tag is requested
+ defaultDistFile android.Path
// Action command lines to run directly after the binary is installed. For example,
// may be used to symlink runtime dependencies (such as bionic) alongside installation.
@@ -385,11 +385,11 @@
// When dist'ing a library or binary that has use_version_lib set, always
// distribute the stamped version, even for the device.
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
- binary.distFiles = android.MakeDefaultDistFiles(versionedOutputFile)
+ binary.defaultDistFile = versionedOutputFile
if binary.stripper.NeedsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
- binary.distFiles = android.MakeDefaultDistFiles(out)
+ binary.defaultDistFile = out
binary.stripper.StripExecutableOrSharedLib(ctx, versionedOutputFile, out, stripFlags)
}
@@ -426,7 +426,7 @@
validations = append(validations, objs.tidyDepFiles...)
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
- if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
+ if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
deps.StaticLibs = append(deps.StaticLibs, generatedLib)
}
@@ -551,6 +551,10 @@
binary.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
}
+func (binary *binaryDecorator) testSuiteInfo(ctx ModuleContext) {
+ // not a test
+}
+
var _ overridable = (*binaryDecorator)(nil)
func init() {
@@ -575,3 +579,10 @@
},
})
}
+
+func (binary *binaryDecorator) defaultDistFiles() []android.Path {
+ if binary.defaultDistFile == nil {
+ return nil
+ }
+ return []android.Path{binary.defaultDistFile}
+}
diff --git a/cc/binary_test.go b/cc/binary_test.go
index 3e18940..4f001d7 100644
--- a/cc/binary_test.go
+++ b/cc/binary_test.go
@@ -29,7 +29,7 @@
linker_scripts: ["foo.ld", "bar.ld"],
}`)
- binFoo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("ld")
+ binFoo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Rule("ld")
android.AssertStringListContains(t, "missing dependency on linker_scripts",
binFoo.Implicits.Strings(), "foo.ld")
diff --git a/cc/builder.go b/cc/builder.go
index b98bef9..f4f8596 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -472,15 +472,25 @@
}
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
-func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs, timeoutTidySrcs android.Paths,
- flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
+func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, noTidySrcs, timeoutTidySrcs android.Paths,
+ flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths, sharedFlags *SharedFlags) Objects {
+
+ // Not all source files produce a .o; a Rust source provider
+ // may provide both a .c and a .rs file (e.g. rust_bindgen).
+ srcObjFiles := android.Paths{}
+ for _, src := range srcFiles {
+ if src.Ext() != ".rs" {
+ srcObjFiles = append(srcObjFiles, src)
+ }
+ }
+
// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
- objFiles := make(android.Paths, len(srcFiles))
+ objFiles := make(android.Paths, len(srcObjFiles))
var tidyFiles android.Paths
noTidySrcsMap := make(map[string]bool)
var tidyVars string
if flags.tidy {
- tidyFiles = make(android.Paths, 0, len(srcFiles))
+ tidyFiles = make(android.Paths, 0, len(srcObjFiles))
for _, path := range noTidySrcs {
noTidySrcsMap[path.String()] = true
}
@@ -495,11 +505,11 @@
}
var coverageFiles android.Paths
if flags.gcovCoverage {
- coverageFiles = make(android.Paths, 0, len(srcFiles))
+ coverageFiles = make(android.Paths, 0, len(srcObjFiles))
}
var kytheFiles android.Paths
if flags.emitXrefs && ctx.Module() == ctx.PrimaryModule() {
- kytheFiles = make(android.Paths, 0, len(srcFiles))
+ kytheFiles = make(android.Paths, 0, len(srcObjFiles))
}
// Produce fully expanded flags for use by C tools, C compiles, C++ tools, C++ compiles, and asm compiles
@@ -548,16 +558,14 @@
var sAbiDumpFiles android.Paths
if flags.sAbiDump {
- sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
+ sAbiDumpFiles = make(android.Paths, 0, len(srcObjFiles))
}
// Multiple source files have build rules usually share the same cFlags or tidyFlags.
- // Define only one version in this module and share it in multiple build rules.
- // To simplify the code, the shared variables are all named as $flags<nnn>.
- shared := ctx.getSharedFlags()
-
+ // SharedFlags provides one version for this module and shares it in multiple build rules.
+ // To simplify the code, the SharedFlags variables are all named as $flags<nnn>.
// Share flags only when there are multiple files or tidy rules.
- var hasMultipleRules = len(srcFiles) > 1 || flags.tidy
+ var hasMultipleRules = len(srcObjFiles) > 1 || flags.tidy
var shareFlags = func(kind string, flags string) string {
if !hasMultipleRules || len(flags) < 60 {
@@ -566,17 +574,17 @@
return flags
}
mapKey := kind + flags
- n, ok := shared.flagsMap[mapKey]
+ n, ok := sharedFlags.FlagsMap[mapKey]
if !ok {
- shared.numSharedFlags += 1
- n = strconv.Itoa(shared.numSharedFlags)
- shared.flagsMap[mapKey] = n
+ sharedFlags.NumSharedFlags += 1
+ n = strconv.Itoa(sharedFlags.NumSharedFlags)
+ sharedFlags.FlagsMap[mapKey] = n
ctx.Variable(pctx, kind+n, flags)
}
return "$" + kind + n
}
- for i, srcFile := range srcFiles {
+ for i, srcFile := range srcObjFiles {
objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
objFiles[i] = objFile
@@ -809,7 +817,7 @@
}
// Generate a Rust staticlib from a list of rlibDeps. Returns nil if TransformRlibstoStaticlib is nil or rlibDeps is empty.
-func generateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
+func GenerateRustStaticlib(ctx android.ModuleContext, rlibDeps []RustRlibDep) android.Path {
if TransformRlibstoStaticlib == nil && len(rlibDeps) > 0 {
// This should only be reachable if a module defines Rust deps in static_libs and
// soong-rust hasn't been loaded alongside soong-cc (e.g. in soong-cc tests).
@@ -853,6 +861,27 @@
return strings.Join(lines, "\n")
}
+func BuildRustStubs(ctx android.ModuleContext, outputFile android.ModuleOutPath,
+ stubObjs Objects, ccFlags Flags) {
+
+ // Instantiate paths
+ sharedLibs := android.Paths{}
+ staticLibs := android.Paths{}
+ lateStaticLibs := android.Paths{}
+ wholeStaticLibs := android.Paths{}
+ deps := android.Paths{}
+ implicitOutputs := android.WritablePaths{}
+ validations := android.Paths{}
+ crtBegin := android.Paths{}
+ crtEnd := android.Paths{}
+ groupLate := false
+
+ builderFlags := flagsToBuilderFlags(ccFlags)
+ transformObjToDynamicBinary(ctx, stubObjs.objFiles, sharedLibs, staticLibs,
+ lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd,
+ groupLate, builderFlags, outputFile, implicitOutputs, validations)
+}
+
// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
// and shared libraries, to a shared library (.so) or dynamic executable
func transformObjToDynamicBinary(ctx android.ModuleContext,
@@ -945,13 +974,18 @@
func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath,
excludedSymbolVersions, excludedSymbolTags, includedSymbolTags []string,
- api string) android.Path {
+ api string, commonGlobalIncludes bool) android.Path {
outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
implicits := android.Paths{soFile}
symbolFilterStr := "-so " + soFile.String()
exportedHeaderFlags := android.JoinWithPrefix(exportedIncludeDirs, "-I")
+ // If this library does not export any include directory, do not append the flags
+ // so that the ABI tool dumps everything without filtering by the include directories.
+ if commonGlobalIncludes && len(exportedIncludeDirs) > 0 {
+ exportedHeaderFlags += " ${config.CommonGlobalIncludes}"
+ }
if symbolFile.Valid() {
implicits = append(implicits, symbolFile.Path())
diff --git a/cc/cc.go b/cc/cc.go
index 6b4e0dc..3e0444d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -34,7 +34,6 @@
"android/soong/android"
"android/soong/cc/config"
"android/soong/fuzz"
- "android/soong/genrule"
)
type CcMakeVarsInfo struct {
@@ -46,26 +45,178 @@
var CcMakeVarsInfoProvider = blueprint.NewProvider[*CcMakeVarsInfo]()
type CcObjectInfo struct {
- objFiles android.Paths
- tidyFiles android.Paths
- kytheFiles android.Paths
+ ObjFiles android.Paths
+ TidyFiles android.Paths
+ KytheFiles android.Paths
}
var CcObjectInfoProvider = blueprint.NewProvider[CcObjectInfo]()
-// Common info about the cc module.
-type CcInfo struct {
- HasStubsVariants bool
+type AidlInterfaceInfo struct {
+ // list of aidl_interface sources
+ Sources []string
+ // root directory of AIDL sources
+ AidlRoot string
+ // AIDL backend language (e.g. "cpp", "ndk")
+ Lang string
+ // list of flags passed to AIDL generator
+ Flags []string
}
-var CcInfoProvider = blueprint.NewProvider[CcInfo]()
+type CompilerInfo struct {
+ Srcs android.Paths
+ // list of module-specific flags that will be used for C and C++ compiles.
+ Cflags []string
+ AidlInterfaceInfo AidlInterfaceInfo
+ LibraryDecoratorInfo *LibraryDecoratorInfo
+}
+
+type LinkerInfo struct {
+ WholeStaticLibs []string
+ // list of modules that should be statically linked into this module.
+ StaticLibs []string
+ // list of modules that should be dynamically linked into this module.
+ SharedLibs []string
+ // list of modules that should only provide headers for this module.
+ HeaderLibs []string
+ ImplementationModuleName *string
+
+ BinaryDecoratorInfo *BinaryDecoratorInfo
+ LibraryDecoratorInfo *LibraryDecoratorInfo
+ TestBinaryInfo *TestBinaryInfo
+ BenchmarkDecoratorInfo *BenchmarkDecoratorInfo
+ ObjectLinkerInfo *ObjectLinkerInfo
+ StubDecoratorInfo *StubDecoratorInfo
+ PrebuiltLibraryLinkerInfo *PrebuiltLibraryLinkerInfo
+}
+
+type BinaryDecoratorInfo struct{}
+type LibraryDecoratorInfo struct {
+ ExportIncludeDirs []string
+ InjectBsslHash bool
+ // Location of the static library in the sysroot. Empty if the library is
+ // not included in the NDK.
+ NdkSysrootPath android.Path
+ VndkFileName string
+}
+
+type SnapshotInfo struct {
+ SnapshotAndroidMkSuffix string
+}
+
+type TestBinaryInfo struct {
+ Gtest bool
+}
+type BenchmarkDecoratorInfo struct{}
+
+type StubDecoratorInfo struct {
+ AbiDumpPath android.OutputPath
+ HasAbiDump bool
+ AbiDiffPaths android.Paths
+ InstallPath android.Path
+}
+
+type ObjectLinkerInfo struct {
+ // Location of the object in the sysroot. Empty if the object is not
+ // included in the NDK.
+ NdkSysrootPath android.Path
+}
+
+type PrebuiltLibraryLinkerInfo struct {
+ VndkFileName string
+}
+
+type LibraryInfo struct {
+ BuildStubs bool
+}
+
+type InstallerInfo struct {
+ StubDecoratorInfo *StubDecoratorInfo
+}
+
+type LocalOrGlobalFlagsInfo struct {
+ CommonFlags []string // Flags that apply to C, C++, and assembly source files
+ CFlags []string // Flags that apply to C and C++ source files
+ ConlyFlags []string // Flags that apply to C source files
+ CppFlags []string // Flags that apply to C++ source files
+}
+
+// Common info about the cc module.
+type CcInfo struct {
+ IsPrebuilt bool
+ CmakeSnapshotSupported bool
+ HasLlndkStubs bool
+ DataPaths []android.DataPath
+ CompilerInfo *CompilerInfo
+ LinkerInfo *LinkerInfo
+ SnapshotInfo *SnapshotInfo
+ LibraryInfo *LibraryInfo
+ InstallerInfo *InstallerInfo
+}
+
+var CcInfoProvider = blueprint.NewProvider[*CcInfo]()
type LinkableInfo struct {
// StaticExecutable returns true if this is a binary module with "static_executable: true".
- StaticExecutable bool
+ StaticExecutable bool
+ Static bool
+ Shared bool
+ Header bool
+ HasStubsVariants bool
+ StubsVersion string
+ IsStubs bool
+ UnstrippedOutputFile android.Path
+ OutputFile android.OptionalPath
+ CoverageFiles android.Paths
+ // CoverageOutputFile returns the output archive of gcno coverage information files.
+ CoverageOutputFile android.OptionalPath
+ SAbiDumpFiles android.Paths
+ // Partition returns the partition string for this module.
+ Partition string
+ CcLibrary bool
+ CcLibraryInterface bool
+ RustLibraryInterface bool
+ // CrateName returns the crateName for a Rust library
+ CrateName string
+ // DepFlags returns a slice of Rustc string flags
+ ExportedCrateLinkDirs []string
+ HasNonSystemVariants bool
+ IsLlndk bool
+ // True if the library is in the configs known NDK list.
+ IsNdk bool
+ InVendorOrProduct bool
+ // SubName returns the modules SubName, used for image and NDK/SDK variations.
+ SubName string
+ InRamdisk bool
+ OnlyInRamdisk bool
+ InVendorRamdisk bool
+ OnlyInVendorRamdisk bool
+ InRecovery bool
+ OnlyInRecovery bool
+ InVendor bool
+ Installable *bool
+ // RelativeInstallPath returns the relative install path for this module.
+ RelativeInstallPath string
+ // TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
+ RustApexExclude bool
+ // Bootstrap tests if this module is allowed to use non-APEX version of libraries.
+ Bootstrap bool
+ Multilib string
+ ImplementationModuleNameForMake string
+ IsStubsImplementationRequired bool
+ // Symlinks returns a list of symlinks that should be created for this module.
+ Symlinks []string
+ APIListCoverageXMLPath android.ModuleOutPath
+ // FuzzSharedLibraries returns the shared library dependencies for this module.
+ // Expects that IsFuzzModule returns true.
+ FuzzSharedLibraries android.RuleBuilderInstalls
+ IsVndkPrebuiltLibrary bool
+ HasLLNDKStubs bool
+ IsLLNDKMovedToApex bool
+ ImplementationModuleName string
}
-var LinkableInfoKey = blueprint.NewProvider[LinkableInfo]()
+var LinkableInfoProvider = blueprint.NewProvider[*LinkableInfo]()
func init() {
RegisterCCBuildComponents(android.InitRegistrationContext)
@@ -519,13 +670,13 @@
type ModuleContextIntf interface {
static() bool
staticBinary() bool
+ staticLibrary() bool
testBinary() bool
testLibrary() bool
header() bool
binary() bool
object() bool
toolchain() config.Toolchain
- canUseSdk() bool
useSdk() bool
sdkVersion() string
minSdkVersion() string
@@ -549,9 +700,7 @@
isFuzzer() bool
isNDKStubLibrary() bool
useClangLld(actx ModuleContext) bool
- isForPlatform() bool
apexVariationName() string
- apexSdkVersion() android.ApiLevel
bootstrap() bool
nativeCoverage() bool
isPreventInstall() bool
@@ -563,8 +712,8 @@
}
type SharedFlags struct {
- numSharedFlags int
- flagsMap map[string]string
+ NumSharedFlags int
+ FlagsMap map[string]string
}
type ModuleContext interface {
@@ -643,7 +792,13 @@
// Get the deps that have been explicitly specified in the properties.
linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps
+ // Gets a list of files that will be disted when using the dist property without specifying
+ // an output file tag.
+ defaultDistFiles() []android.Path
+
moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
+
+ testSuiteInfo(ctx ModuleContext)
}
// specifiedDeps is a tuple struct representing dependencies of a linked binary owned by the linker.
@@ -734,6 +889,7 @@
reexportFlags bool
explicitlyVersioned bool
+ explicitlyImpl bool
dataLib bool
ndk bool
@@ -822,13 +978,18 @@
dataLibDepTag = dependencyTag{name: "data lib"}
dataBinDepTag = dependencyTag{name: "data bin"}
runtimeDepTag = installDependencyTag{name: "runtime lib"}
- stubImplDepTag = dependencyTag{name: "stub_impl"}
+ StubImplDepTag = dependencyTag{name: "stub_impl"}
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
FdoProfileTag = dependencyTag{name: "fdo_profile"}
aidlLibraryTag = dependencyTag{name: "aidl_library"}
llndkHeaderLibTag = dependencyTag{name: "llndk_header_lib"}
)
+func IsExplicitImplSharedDepTag(depTag blueprint.DependencyTag) bool {
+ ccLibDepTag, ok := depTag.(libraryDependencyTag)
+ return ok && ccLibDepTag.shared() && ccLibDepTag.explicitlyImpl
+}
+
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
ccLibDepTag, ok := depTag.(libraryDependencyTag)
return ok && ccLibDepTag.shared()
@@ -848,6 +1009,11 @@
return depTag == runtimeDepTag
}
+func ExcludeInApexDepTag(depTag blueprint.DependencyTag) bool {
+ ccLibDepTag, ok := depTag.(libraryDependencyTag)
+ return ok && ccLibDepTag.excludeInApex
+}
+
// Module contains the properties and members used by all C/C++ module types, and implements
// the blueprint.Module interface. It delegates to compiler, linker, and installer interfaces
// to construct the output file. Behavior can be customized with a Customizer, or "decorator",
@@ -1071,7 +1237,21 @@
return String(c.Properties.Min_sdk_version)
}
-func (c *Module) isCrt() bool {
+func (c *Module) SetSdkVersion(s string) {
+ c.Properties.Sdk_version = StringPtr(s)
+}
+
+func (c *Module) SetMinSdkVersion(s string) {
+ c.Properties.Min_sdk_version = StringPtr(s)
+}
+
+func (c *Module) SetStl(s string) {
+ if c.stl != nil {
+ c.stl.Properties.Stl = StringPtr(s)
+ }
+}
+
+func (c *Module) IsCrt() bool {
if linker, ok := c.linker.(*objectLinker); ok {
return linker.isCrt()
}
@@ -1079,7 +1259,7 @@
}
func (c *Module) SplitPerApiLevel() bool {
- return c.canUseSdk() && c.isCrt()
+ return CanUseSdk(c) && c.IsCrt()
}
func (c *Module) AlwaysSdk() bool {
@@ -1099,7 +1279,7 @@
}
func (c *Module) CcLibraryInterface() bool {
- if _, ok := c.linker.(libraryInterface); ok {
+ if c.library != nil {
return true
}
return false
@@ -1193,11 +1373,6 @@
return false
}
-func (c *Module) IsRustFFI() bool {
- // cc modules are not Rust modules
- return false
-}
-
func (c *Module) Module() android.Module {
return c
}
@@ -1217,6 +1392,13 @@
var _ LinkableInterface = (*Module)(nil)
+func (c *Module) VersionedInterface() VersionedInterface {
+ if c.library != nil {
+ return c.library
+ }
+ return nil
+}
+
func (c *Module) UnstrippedOutputFile() android.Path {
if c.linker != nil {
return c.linker.unstrippedOutputFilePath()
@@ -1301,13 +1483,13 @@
return c.Properties.VndkVersion != ""
}
-func (c *Module) canUseSdk() bool {
- return c.Os() == android.Android && c.Target().NativeBridge == android.NativeBridgeDisabled &&
+func CanUseSdk(c LinkableInterface) bool {
+ return c.Module().Target().Os == android.Android && c.Target().NativeBridge == android.NativeBridgeDisabled &&
!c.InVendorOrProduct() && !c.InRamdisk() && !c.InRecovery() && !c.InVendorRamdisk()
}
func (c *Module) UseSdk() bool {
- if c.canUseSdk() {
+ if CanUseSdk(c) {
return String(c.Properties.Sdk_version) != ""
}
return false
@@ -1326,13 +1508,13 @@
}
func (m *Module) NeedsLlndkVariants() bool {
- lib := moduleLibraryInterface(m)
- return lib != nil && (lib.hasLLNDKStubs() || lib.hasLLNDKHeaders())
+ lib := moduleVersionedInterface(m)
+ return lib != nil && (lib.HasLLNDKStubs() || lib.HasLLNDKHeaders())
}
func (m *Module) NeedsVendorPublicLibraryVariants() bool {
- lib := moduleLibraryInterface(m)
- return lib != nil && (lib.hasVendorPublicLibrary())
+ lib := moduleVersionedInterface(m)
+ return lib != nil && (lib.HasVendorPublicLibrary())
}
// IsVendorPublicLibrary returns true for vendor public libraries.
@@ -1352,13 +1534,13 @@
}
func (c *Module) HasLlndkStubs() bool {
- lib := moduleLibraryInterface(c)
- return lib != nil && lib.hasLLNDKStubs()
+ lib := moduleVersionedInterface(c)
+ return lib != nil && lib.HasLLNDKStubs()
}
func (c *Module) StubsVersion() string {
- if lib, ok := c.linker.(versionedInterface); ok {
- return lib.stubsVersion()
+ if lib, ok := c.linker.(VersionedInterface); ok {
+ return lib.StubsVersion()
}
panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", c.BaseModuleName()))
}
@@ -1367,7 +1549,7 @@
// and does not set llndk.vendor_available: false.
func (c *Module) isImplementationForLLNDKPublic() bool {
library, _ := c.library.(*libraryDecorator)
- return library != nil && library.hasLLNDKStubs() &&
+ return library != nil && library.HasLLNDKStubs() &&
!Bool(library.Properties.Llndk.Private)
}
@@ -1406,21 +1588,25 @@
func (c *Module) IsStubs() bool {
if lib := c.library; lib != nil {
- return lib.buildStubs()
+ return lib.BuildStubs()
}
return false
}
func (c *Module) HasStubsVariants() bool {
if lib := c.library; lib != nil {
- return lib.hasStubsVariants()
+ return lib.HasStubsVariants()
}
return false
}
+func (c *Module) RustApexExclude() bool {
+ return false
+}
+
func (c *Module) IsStubsImplementationRequired() bool {
if lib := c.library; lib != nil {
- return lib.isStubsImplementationRequired()
+ return lib.IsStubsImplementationRequired()
}
return false
}
@@ -1429,21 +1615,21 @@
// the implementation. If it is an implementation library it returns its own name.
func (c *Module) ImplementationModuleName(ctx android.BaseModuleContext) string {
name := ctx.OtherModuleName(c)
- if versioned, ok := c.linker.(versionedInterface); ok {
- name = versioned.implementationModuleName(name)
+ if versioned, ok := c.linker.(VersionedInterface); ok {
+ name = versioned.ImplementationModuleName(name)
}
return name
}
-// Similar to ImplementationModuleName, but uses the Make variant of the module
+// Similar to ImplementationModuleNameByCtx, but uses the Make variant of the module
// name as base name, for use in AndroidMk output. E.g. for a prebuilt module
// where the Soong name is prebuilt_foo, this returns foo (which works in Make
// under the premise that the prebuilt module overrides its source counterpart
// if it is exposed to Make).
-func (c *Module) ImplementationModuleNameForMake(ctx android.BaseModuleContext) string {
+func (c *Module) ImplementationModuleNameForMake() string {
name := c.BaseModuleName()
- if versioned, ok := c.linker.(versionedInterface); ok {
- name = versioned.implementationModuleName(name)
+ if versioned, ok := c.linker.(VersionedInterface); ok {
+ name = versioned.ImplementationModuleName(name)
}
return name
}
@@ -1523,6 +1709,10 @@
return ctx.mod.staticBinary()
}
+func (ctx *moduleContextImpl) staticLibrary() bool {
+ return ctx.mod.staticLibrary()
+}
+
func (ctx *moduleContextImpl) testBinary() bool {
return ctx.mod.testBinary()
}
@@ -1547,10 +1737,6 @@
return ctx.mod.OptimizeForSize()
}
-func (ctx *moduleContextImpl) canUseSdk() bool {
- return ctx.mod.canUseSdk()
-}
-
func (ctx *moduleContextImpl) useSdk() bool {
return ctx.mod.UseSdk()
}
@@ -1562,21 +1748,23 @@
return ""
}
-func (ctx *moduleContextImpl) minSdkVersion() string {
- ver := ctx.mod.MinSdkVersion()
- if ver == "apex_inherit" && !ctx.isForPlatform() {
- ver = ctx.apexSdkVersion().String()
+func MinSdkVersion(mod VersionedLinkableInterface, ctxIsForPlatform bool, device bool,
+ platformSdkVersion string) string {
+
+ ver := mod.MinSdkVersion()
+ if ver == "apex_inherit" && !ctxIsForPlatform {
+ ver = mod.ApexSdkVersion().String()
}
if ver == "apex_inherit" || ver == "" {
- ver = ctx.sdkVersion()
+ ver = mod.SdkVersion()
}
- if ctx.ctx.Device() {
+ if device {
// When building for vendor/product, use the latest _stable_ API as "current".
// This is passed to clang/aidl compilers so that compiled/generated code works
// with the system.
- if (ctx.inVendor() || ctx.inProduct()) && (ver == "" || ver == "current") {
- ver = ctx.ctx.Config().PlatformSdkVersion().String()
+ if (mod.InVendor() || mod.InProduct()) && (ver == "" || ver == "current") {
+ ver = platformSdkVersion
}
}
@@ -1590,19 +1778,19 @@
// support such an old version. The version is set to the later version in case when the
// non-sdk variant is for the platform, or the min_sdk_version of the containing APEX if
// it's for an APEX.
- if ctx.mod.isCrt() && !ctx.isSdkVariant() {
- if ctx.isForPlatform() {
+ if mod.IsCrt() && !mod.IsSdkVariant() {
+ if ctxIsForPlatform {
ver = strconv.Itoa(android.FutureApiLevelInt)
} else { // for apex
- ver = ctx.apexSdkVersion().String()
+ ver = mod.ApexSdkVersion().String()
if ver == "" { // in case when min_sdk_version was not set by the APEX
- ver = ctx.sdkVersion()
+ ver = mod.SdkVersion()
}
}
}
// Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers
- sdkVersionInt, err := strconv.Atoi(ctx.sdkVersion())
+ sdkVersionInt, err := strconv.Atoi(mod.SdkVersion())
minSdkVersionInt, err2 := strconv.Atoi(ver)
if err == nil && err2 == nil {
if sdkVersionInt < minSdkVersionInt {
@@ -1612,6 +1800,14 @@
return ver
}
+func (ctx *moduleContextImpl) minSdkVersion() string {
+ platformSdkVersion := ""
+ if ctx.ctx.Device() {
+ platformSdkVersion = ctx.ctx.Config().PlatformSdkVersion().String()
+ }
+ return MinSdkVersion(ctx.mod, CtxIsForPlatform(ctx.ctx), ctx.ctx.Device(), platformSdkVersion)
+}
+
func (ctx *moduleContextImpl) isSdkVariant() bool {
return ctx.mod.IsSdkVariant()
}
@@ -1675,8 +1871,8 @@
return ctx.mod.BaseModuleName()
}
-func (ctx *moduleContextImpl) isForPlatform() bool {
- apexInfo, _ := android.ModuleProvider(ctx.ctx, android.ApexInfoProvider)
+func CtxIsForPlatform(ctx android.BaseModuleContext) bool {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return apexInfo.IsForPlatform()
}
@@ -1685,10 +1881,6 @@
return apexInfo.ApexVariationName
}
-func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel {
- return ctx.mod.apexSdkVersion
-}
-
func (ctx *moduleContextImpl) bootstrap() bool {
return ctx.mod.Bootstrap()
}
@@ -1703,9 +1895,9 @@
func (ctx *moduleContextImpl) getSharedFlags() *SharedFlags {
shared := &ctx.mod.sharedFlags
- if shared.flagsMap == nil {
- shared.numSharedFlags = 0
- shared.flagsMap = make(map[string]string)
+ if shared.FlagsMap == nil {
+ shared.NumSharedFlags = 0
+ shared.FlagsMap = make(map[string]string)
}
return shared
}
@@ -1769,6 +1961,14 @@
return name
}
+func (c *Module) Multilib() string {
+ return c.Arch().ArchType.Multilib
+}
+
+func (c *Module) ApexSdkVersion() android.ApiLevel {
+ return c.apexSdkVersion
+}
+
func (c *Module) Symlinks() []string {
if p, ok := c.installer.(interface {
symlinkList() []string
@@ -1899,13 +2099,13 @@
return false
}
- _, aaWithoutTestApexes, _ := android.ListSetDifference(c.ApexAvailable(), c.TestApexes())
// Stub libraries should not have more than one apex_available
- if len(aaWithoutTestApexes) > 1 {
+ apexAvailable := android.FirstUniqueStrings(c.ApexAvailable())
+ if len(apexAvailable) > 1 {
return true
}
// Stub libraries should not use the wildcard
- if aaWithoutTestApexes[0] == android.AvailableToAnyApex {
+ if apexAvailable[0] == android.AvailableToAnyApex {
return true
}
// Default: no violation
@@ -2064,8 +2264,6 @@
})
}
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()})
-
if Bool(c.Properties.Cmake_snapshot_supported) {
android.SetProvider(ctx, cmakeSnapshotSourcesProvider, android.GlobFiles(ctx, ctx.ModuleDir()+"/**/*", nil))
}
@@ -2117,23 +2315,121 @@
}
ccObjectInfo := CcObjectInfo{
- kytheFiles: objs.kytheFiles,
+ KytheFiles: objs.kytheFiles,
}
if !ctx.Config().KatiEnabled() || !android.ShouldSkipAndroidMkProcessing(ctx, c) {
- ccObjectInfo.objFiles = objs.objFiles
- ccObjectInfo.tidyFiles = objs.tidyFiles
+ ccObjectInfo.ObjFiles = objs.objFiles
+ ccObjectInfo.TidyFiles = objs.tidyFiles
}
- if len(ccObjectInfo.kytheFiles)+len(ccObjectInfo.objFiles)+len(ccObjectInfo.tidyFiles) > 0 {
+ if len(ccObjectInfo.KytheFiles)+len(ccObjectInfo.ObjFiles)+len(ccObjectInfo.TidyFiles) > 0 {
android.SetProvider(ctx, CcObjectInfoProvider, ccObjectInfo)
}
- android.SetProvider(ctx, LinkableInfoKey, LinkableInfo{
- StaticExecutable: c.StaticExecutable(),
- })
+ linkableInfo := CreateCommonLinkableInfo(ctx, c)
+ if lib, ok := c.linker.(VersionedInterface); ok {
+ linkableInfo.StubsVersion = lib.StubsVersion()
+ }
+ if c.linker != nil {
+ if library, ok := c.linker.(libraryInterface); ok {
+ linkableInfo.Static = library.static()
+ linkableInfo.Shared = library.shared()
+ linkableInfo.CoverageFiles = library.objs().coverageFiles
+ linkableInfo.SAbiDumpFiles = library.objs().sAbiDumpFiles
+ }
+ }
+ android.SetProvider(ctx, LinkableInfoProvider, linkableInfo)
- android.SetProvider(ctx, CcInfoProvider, CcInfo{
- HasStubsVariants: c.HasStubsVariants(),
- })
+ ccInfo := CcInfo{
+ IsPrebuilt: c.IsPrebuilt(),
+ CmakeSnapshotSupported: proptools.Bool(c.Properties.Cmake_snapshot_supported),
+ HasLlndkStubs: c.HasLlndkStubs(),
+ DataPaths: c.DataPaths(),
+ }
+ if c.compiler != nil {
+ cflags := c.compiler.baseCompilerProps().Cflags
+ ccInfo.CompilerInfo = &CompilerInfo{
+ Srcs: c.compiler.(CompiledInterface).Srcs(),
+ Cflags: cflags.GetOrDefault(ctx, nil),
+ AidlInterfaceInfo: AidlInterfaceInfo{
+ Sources: c.compiler.baseCompilerProps().AidlInterface.Sources,
+ AidlRoot: c.compiler.baseCompilerProps().AidlInterface.AidlRoot,
+ Lang: c.compiler.baseCompilerProps().AidlInterface.Lang,
+ Flags: c.compiler.baseCompilerProps().AidlInterface.Flags,
+ },
+ }
+ switch decorator := c.compiler.(type) {
+ case *libraryDecorator:
+ ccInfo.CompilerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{
+ ExportIncludeDirs: decorator.flagExporter.Properties.Export_include_dirs.GetOrDefault(ctx, nil),
+ }
+ }
+ }
+ if c.linker != nil {
+ baseLinkerProps := c.linker.baseLinkerProps()
+ ccInfo.LinkerInfo = &LinkerInfo{
+ WholeStaticLibs: baseLinkerProps.Whole_static_libs.GetOrDefault(ctx, nil),
+ StaticLibs: baseLinkerProps.Static_libs.GetOrDefault(ctx, nil),
+ SharedLibs: baseLinkerProps.Shared_libs.GetOrDefault(ctx, nil),
+ HeaderLibs: baseLinkerProps.Header_libs.GetOrDefault(ctx, nil),
+ }
+ switch decorator := c.linker.(type) {
+ case *binaryDecorator:
+ ccInfo.LinkerInfo.BinaryDecoratorInfo = &BinaryDecoratorInfo{}
+ case *libraryDecorator:
+ lk := c.linker.(*libraryDecorator)
+ ccInfo.LinkerInfo.LibraryDecoratorInfo = &LibraryDecoratorInfo{
+ InjectBsslHash: Bool(lk.Properties.Inject_bssl_hash),
+ NdkSysrootPath: lk.ndkSysrootPath,
+ VndkFileName: lk.getLibNameHelper(c.BaseModuleName(), true, false) + ".so",
+ }
+ case *testBinary:
+ ccInfo.LinkerInfo.TestBinaryInfo = &TestBinaryInfo{
+ Gtest: decorator.testDecorator.gtest(),
+ }
+ case *benchmarkDecorator:
+ ccInfo.LinkerInfo.BenchmarkDecoratorInfo = &BenchmarkDecoratorInfo{}
+ case *objectLinker:
+ ccInfo.LinkerInfo.ObjectLinkerInfo = &ObjectLinkerInfo{
+ NdkSysrootPath: c.linker.(*objectLinker).ndkSysrootPath,
+ }
+ case *stubDecorator:
+ ccInfo.LinkerInfo.StubDecoratorInfo = &StubDecoratorInfo{}
+ case *prebuiltLibraryLinker:
+ ccInfo.LinkerInfo.PrebuiltLibraryLinkerInfo = &PrebuiltLibraryLinkerInfo{
+ VndkFileName: c.linker.(*prebuiltLibraryLinker).getLibNameHelper(
+ c.BaseModuleName(), true, false) + ".so",
+ }
+ }
+
+ if s, ok := c.linker.(SnapshotInterface); ok {
+ ccInfo.SnapshotInfo = &SnapshotInfo{
+ SnapshotAndroidMkSuffix: s.SnapshotAndroidMkSuffix(),
+ }
+ }
+ if v, ok := c.linker.(VersionedInterface); ok {
+ name := v.ImplementationModuleName(ctx.OtherModuleName(c))
+ ccInfo.LinkerInfo.ImplementationModuleName = &name
+ }
+
+ c.linker.testSuiteInfo(ctx)
+ }
+ if c.library != nil {
+ ccInfo.LibraryInfo = &LibraryInfo{
+ BuildStubs: c.library.BuildStubs(),
+ }
+ }
+ if c.installer != nil {
+ ccInfo.InstallerInfo = &InstallerInfo{}
+ if installer, ok := c.installer.(*stubDecorator); ok {
+ ccInfo.InstallerInfo.StubDecoratorInfo = &StubDecoratorInfo{
+ HasAbiDump: installer.hasAbiDump,
+ AbiDumpPath: installer.abiDumpPath,
+ AbiDiffPaths: installer.abiDiffPaths,
+ InstallPath: installer.installPath,
+ }
+ }
+ }
+ android.SetProvider(ctx, CcInfoProvider, &ccInfo)
c.setOutputFiles(ctx)
@@ -2142,10 +2438,79 @@
}
}
-func setOutputFilesIfNotEmpty(ctx ModuleContext, files android.Paths, tag string) {
- if len(files) > 0 {
- ctx.SetOutputFiles(files, tag)
+func (c *Module) CleanupAfterBuildActions() {
+ // Clear as much of Module as possible to reduce memory usage.
+ c.generators = nil
+ c.compiler = nil
+ c.installer = nil
+ c.features = nil
+ c.coverage = nil
+ c.fuzzer = nil
+ c.sabi = nil
+ c.lto = nil
+ c.afdo = nil
+ c.orderfile = nil
+
+ // TODO: these can be cleared after nativeBinaryInfoProperties and nativeLibInfoProperties are switched to
+ // using providers.
+ // c.linker = nil
+ // c.stl = nil
+ // c.sanitize = nil
+ // c.library = nil
+}
+
+func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableInterface) *LinkableInfo {
+ info := &LinkableInfo{
+ StaticExecutable: mod.StaticExecutable(),
+ HasStubsVariants: mod.HasStubsVariants(),
+ OutputFile: mod.OutputFile(),
+ UnstrippedOutputFile: mod.UnstrippedOutputFile(),
+ CoverageOutputFile: mod.CoverageOutputFile(),
+ Partition: mod.Partition(),
+ IsStubs: mod.IsStubs(),
+ CcLibrary: mod.CcLibrary(),
+ CcLibraryInterface: mod.CcLibraryInterface(),
+ RustLibraryInterface: mod.RustLibraryInterface(),
+ IsLlndk: mod.IsLlndk(),
+ IsNdk: mod.IsNdk(ctx.Config()),
+ HasNonSystemVariants: mod.HasNonSystemVariants(),
+ SubName: mod.SubName(),
+ InVendorOrProduct: mod.InVendorOrProduct(),
+ InRamdisk: mod.InRamdisk(),
+ OnlyInRamdisk: mod.OnlyInRamdisk(),
+ InVendorRamdisk: mod.InVendorRamdisk(),
+ OnlyInVendorRamdisk: mod.OnlyInVendorRamdisk(),
+ InRecovery: mod.InRecovery(),
+ OnlyInRecovery: mod.OnlyInRecovery(),
+ InVendor: mod.InVendor(),
+ Installable: mod.Installable(),
+ RelativeInstallPath: mod.RelativeInstallPath(),
+ // TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
+ RustApexExclude: mod.RustApexExclude(),
+ Bootstrap: mod.Bootstrap(),
+ Multilib: mod.Multilib(),
+ ImplementationModuleNameForMake: mod.ImplementationModuleNameForMake(),
+ Symlinks: mod.Symlinks(),
+ Header: mod.Header(),
+ IsVndkPrebuiltLibrary: mod.IsVndkPrebuiltLibrary(),
}
+
+ vi := mod.VersionedInterface()
+ if vi != nil {
+ info.IsStubsImplementationRequired = vi.IsStubsImplementationRequired()
+ info.APIListCoverageXMLPath = vi.GetAPIListCoverageXMLPath()
+ info.HasLLNDKStubs = vi.HasLLNDKStubs()
+ info.IsLLNDKMovedToApex = vi.IsLLNDKMovedToApex()
+ info.ImplementationModuleName = vi.ImplementationModuleName(mod.BaseModuleName())
+ }
+
+ if !mod.PreventInstall() && fuzz.IsValid(ctx, mod.FuzzModuleStruct()) && mod.IsFuzzModule() {
+ info.FuzzSharedLibraries = mod.FuzzSharedLibraries()
+ fm := mod.FuzzPackagedModule()
+ fuzz.SetFuzzPackagedModuleInfo(ctx, &fm)
+ }
+
+ return info
}
func (c *Module) setOutputFiles(ctx ModuleContext) {
@@ -2157,31 +2522,52 @@
if c.linker != nil {
ctx.SetOutputFiles(android.PathsIfNonNil(c.linker.unstrippedOutputFilePath()), "unstripped")
ctx.SetOutputFiles(android.PathsIfNonNil(c.linker.strippedAllOutputFilePath()), "stripped_all")
+ defaultDistFiles := c.linker.defaultDistFiles()
+ if len(defaultDistFiles) > 0 {
+ ctx.SetOutputFiles(defaultDistFiles, android.DefaultDistTag)
+ }
}
}
func buildComplianceMetadataInfo(ctx ModuleContext, c *Module, deps PathDeps) {
// Dump metadata that can not be done in android/compliance-metadata.go
complianceMetadataInfo := ctx.ComplianceMetadataInfo()
- complianceMetadataInfo.SetStringValue(android.ComplianceMetadataProp.IS_STATIC_LIB, strconv.FormatBool(ctx.static()))
+ complianceMetadataInfo.SetStringValue(android.ComplianceMetadataProp.IS_STATIC_LIB, strconv.FormatBool(ctx.static() || ctx.ModuleType() == "cc_object"))
complianceMetadataInfo.SetStringValue(android.ComplianceMetadataProp.BUILT_FILES, c.outputFile.String())
// Static deps
- staticDeps := ctx.GetDirectDepsWithTag(StaticDepTag(false))
+ staticDeps := ctx.GetDirectDepsProxyWithTag(StaticDepTag(false))
staticDepNames := make([]string, 0, len(staticDeps))
for _, dep := range staticDeps {
staticDepNames = append(staticDepNames, dep.Name())
}
+ // Process CrtBegin and CrtEnd as static libs
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
+ depName := ctx.OtherModuleName(dep)
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ switch depTag {
+ case CrtBeginDepTag:
+ staticDepNames = append(staticDepNames, depName)
+ case CrtEndDepTag:
+ staticDepNames = append(staticDepNames, depName)
+ }
+ })
- staticDepPaths := make([]string, 0, len(deps.StaticLibs))
+ staticDepPaths := make([]string, 0, len(deps.StaticLibs)+len(deps.CrtBegin)+len(deps.CrtEnd))
for _, dep := range deps.StaticLibs {
staticDepPaths = append(staticDepPaths, dep.String())
}
+ for _, dep := range deps.CrtBegin {
+ staticDepPaths = append(staticDepPaths, dep.String())
+ }
+ for _, dep := range deps.CrtEnd {
+ staticDepPaths = append(staticDepPaths, dep.String())
+ }
complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.FirstUniqueStrings(staticDepNames))
complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.FirstUniqueStrings(staticDepPaths))
// Whole static deps
- wholeStaticDeps := ctx.GetDirectDepsWithTag(StaticDepTag(true))
+ wholeStaticDeps := ctx.GetDirectDepsProxyWithTag(StaticDepTag(true))
wholeStaticDepNames := make([]string, 0, len(wholeStaticDeps))
for _, dep := range wholeStaticDeps {
wholeStaticDepNames = append(wholeStaticDepNames, dep.Name())
@@ -2193,6 +2579,14 @@
}
complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.WHOLE_STATIC_DEPS, android.FirstUniqueStrings(wholeStaticDepNames))
complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.WHOLE_STATIC_DEP_FILES, android.FirstUniqueStrings(wholeStaticDepPaths))
+
+ // Header libs
+ headerLibDeps := ctx.GetDirectDepsProxyWithTag(HeaderDepTag())
+ headerLibDepNames := make([]string, 0, len(headerLibDeps))
+ for _, dep := range headerLibDeps {
+ headerLibDepNames = append(headerLibDepNames, dep.Name())
+ }
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.HEADER_LIBS, android.FirstUniqueStrings(headerLibDepNames))
}
func (c *Module) maybeUnhideFromMake() {
@@ -2272,7 +2666,7 @@
c.orderfile.begin(ctx)
}
if ctx.useSdk() && c.IsSdkVariant() {
- version, err := nativeApiLevelFromUser(ctx, ctx.sdkVersion())
+ version, err := NativeApiLevelFromUser(ctx, ctx.sdkVersion())
if err != nil {
ctx.PropertyErrorf("sdk_version", err.Error())
c.Properties.Sdk_version = nil
@@ -2428,6 +2822,9 @@
variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
if tag, ok := depTag.(libraryDependencyTag); ok {
tag.explicitlyVersioned = true
+ if version == "" {
+ tag.explicitlyImpl = true
+ }
// depTag is an interface that contains a concrete non-pointer struct. That makes the local
// tag variable a copy of the contents of depTag, and updating it doesn't change depTag. Reassign
// the modified copy to depTag.
@@ -2803,6 +3200,7 @@
// Recovery code is not NDK
return
}
+ // Change this to LinkableInterface if Rust gets NDK support, which stubDecorators are for
if c, ok := to.(*Module); ok {
if c.StubDecorator() {
// These aren't real libraries, but are the stub shared libraries that are included in
@@ -2909,7 +3307,7 @@
if depTag == staticVariantTag {
return false
}
- if depTag == stubImplDepTag {
+ if depTag == StubImplDepTag {
return false
}
if depTag == android.RequiredDepTag {
@@ -2940,7 +3338,7 @@
}
if module, ok := ctx.Module().(*Module); ok {
if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
- if lib.hasLLNDKStubs() {
+ if lib.HasLLNDKStubs() {
ctx.WalkDeps(check)
}
}
@@ -2984,7 +3382,7 @@
skipModuleList := map[string]bool{}
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
@@ -2993,8 +3391,17 @@
return
}
+ var ccInfo *CcInfo
+ v, hasCcInfo := android.OtherModuleProvider(ctx, dep, CcInfoProvider)
+ if hasCcInfo {
+ ccInfo = v
+ }
+ linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, LinkableInfoProvider)
if depTag == android.DarwinUniversalVariantTag {
- depPaths.DarwinSecondArchOutput = dep.(*Module).OutputFile()
+ if !hasCcInfo {
+ panic(fmt.Errorf("dep is not a cc module: %s", dep.String()))
+ }
+ depPaths.DarwinSecondArchOutput = linkableInfo.OutputFile
return
}
@@ -3007,34 +3414,32 @@
}
}
- ccDep, ok := dep.(LinkableInterface)
- if !ok {
-
+ if !hasLinkableInfo {
// handling for a few module types that aren't cc Module but that are also supported
+ genRule, ok := android.OtherModuleProvider(ctx, dep, android.GeneratedSourceInfoProvider)
switch depTag {
case genSourceDepTag:
- if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
+ if ok {
depPaths.GeneratedSources = append(depPaths.GeneratedSources,
- genRule.GeneratedSourceFiles()...)
+ genRule.GeneratedSourceFiles...)
} else {
ctx.ModuleErrorf("module %q is not a gensrcs or genrule", depName)
}
// Support exported headers from a generated_sources dependency
fallthrough
case genHeaderDepTag, genHeaderExportDepTag:
- if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
+ if ok {
depPaths.GeneratedDeps = append(depPaths.GeneratedDeps,
- genRule.GeneratedDeps()...)
- dirs := genRule.GeneratedHeaderDirs()
+ genRule.GeneratedDeps...)
+ dirs := genRule.GeneratedHeaderDirs
depPaths.IncludeDirs = append(depPaths.IncludeDirs, dirs...)
if depTag == genHeaderExportDepTag {
depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, dirs...)
depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders,
- genRule.GeneratedSourceFiles()...)
- depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, genRule.GeneratedDeps()...)
+ genRule.GeneratedSourceFiles...)
+ depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, genRule.GeneratedDeps...)
// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
c.sabi.Properties.ReexportedIncludes = append(c.sabi.Properties.ReexportedIncludes, dirs.Strings()...)
-
}
} else {
ctx.ModuleErrorf("module %q is not a genrule", depName)
@@ -3055,13 +3460,14 @@
return
}
- if dep.Target().Os != ctx.Os() {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
+ if commonInfo.Target.Os != ctx.Os() {
ctx.ModuleErrorf("OS mismatch between %q (%s) and %q (%s)", ctx.ModuleName(), ctx.Os().Name, depName, dep.Target().Os.Name)
return
}
- if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
+ if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType {
ctx.ModuleErrorf("Arch mismatch between %q(%v) and %q(%v)",
- ctx.ModuleName(), ctx.Arch().ArchType, depName, dep.Target().Arch.ArchType)
+ ctx.ModuleName(), ctx.Arch().ArchType, depName, commonInfo.Target.Arch.ArchType)
return
}
@@ -3070,7 +3476,7 @@
// The reuseObjTag dependency still exists because the LinkageMutator runs before the
// version mutator, so the stubs variant is created from the shared variant that
// already has the reuseObjTag dependency on the static variant.
- if !c.library.buildStubs() {
+ if !c.library.BuildStubs() {
staticAnalogue, _ := android.OtherModuleProvider(ctx, dep, StaticLibraryInfoProvider)
objs := staticAnalogue.ReuseObjects
depPaths.Objs = depPaths.Objs.Append(objs)
@@ -3086,7 +3492,7 @@
depPaths.LlndkSystemIncludeDirs = append(depPaths.LlndkSystemIncludeDirs, depExporterInfo.SystemIncludeDirs...)
}
- linkFile := ccDep.OutputFile()
+ linkFile := linkableInfo.OutputFile
if libDepTag, ok := depTag.(libraryDependencyTag); ok {
// Only use static unwinder for legacy (min_sdk_version = 29) apexes (b/144430859)
@@ -3141,9 +3547,12 @@
depFile = sharedLibraryInfo.TableOfContents
if !sharedLibraryInfo.IsStubs {
- depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
- if info, ok := android.OtherModuleProvider(ctx, dep, ImplementationDepInfoProvider); ok {
- depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ // TODO(b/362509506): remove this additional check once all apex_exclude uses are switched to stubs.
+ if !linkableInfo.RustApexExclude {
+ depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
+ if info, ok := android.OtherModuleProvider(ctx, dep, ImplementationDepInfoProvider); ok {
+ depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ }
}
}
@@ -3164,8 +3573,8 @@
}
case libDepTag.static():
- if ccDep.RustLibraryInterface() {
- rlibDep := RustRlibDep{LibPath: linkFile.Path(), CrateName: ccDep.CrateName(), LinkDirs: ccDep.ExportedCrateLinkDirs()}
+ if linkableInfo.RustLibraryInterface {
+ rlibDep := RustRlibDep{LibPath: linkFile.Path(), CrateName: linkableInfo.CrateName, LinkDirs: linkableInfo.ExportedCrateLinkDirs}
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, rlibDep)
depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...)
if libDepTag.wholeStatic {
@@ -3242,8 +3651,8 @@
}
}
- if libDepTag.static() && !libDepTag.wholeStatic && !ccDep.RustLibraryInterface() {
- if !ccDep.CcLibraryInterface() || !ccDep.Static() {
+ if libDepTag.static() && !libDepTag.wholeStatic && !linkableInfo.RustLibraryInterface {
+ if !linkableInfo.CcLibraryInterface || !linkableInfo.Static {
ctx.ModuleErrorf("module %q not a static library", depName)
return
}
@@ -3251,16 +3660,15 @@
// When combining coverage files for shared libraries and executables, coverage files
// in static libraries act as if they were whole static libraries. The same goes for
// source based Abi dump files.
- if c, ok := ccDep.(*Module); ok {
- staticLib := c.linker.(libraryInterface)
+ if hasCcInfo {
depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
- staticLib.objs().coverageFiles...)
+ linkableInfo.CoverageFiles...)
depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles,
- staticLib.objs().sAbiDumpFiles...)
+ linkableInfo.SAbiDumpFiles...)
} else {
// Handle non-CC modules here
depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles,
- ccDep.CoverageFiles()...)
+ linkableInfo.CoverageFiles...)
}
}
@@ -3306,7 +3714,7 @@
c.sabi.Properties.ReexportedSystemIncludes, depExporterInfo.SystemIncludeDirs.Strings()...)
}
- makeLibName := MakeLibName(ctx, c, ccDep, ccDep.BaseModuleName()) + libDepTag.makeSuffix
+ makeLibName := MakeLibName(ccInfo, linkableInfo, commonInfo, commonInfo.BaseModuleName) + libDepTag.makeSuffix
switch {
case libDepTag.header():
c.Properties.AndroidMkHeaderLibs = append(
@@ -3317,7 +3725,7 @@
c.Properties.AndroidMkSharedLibs = append(
c.Properties.AndroidMkSharedLibs, makeLibName)
case libDepTag.static():
- if !ccDep.RustLibraryInterface() {
+ if !linkableInfo.RustLibraryInterface {
if libDepTag.wholeStatic {
c.Properties.AndroidMkWholeStaticLibs = append(
c.Properties.AndroidMkWholeStaticLibs, makeLibName)
@@ -3333,7 +3741,8 @@
switch depTag {
case runtimeDepTag:
c.Properties.AndroidMkRuntimeLibs = append(
- c.Properties.AndroidMkRuntimeLibs, MakeLibName(ctx, c, ccDep, ccDep.BaseModuleName())+libDepTag.makeSuffix)
+ c.Properties.AndroidMkRuntimeLibs, MakeLibName(ccInfo, linkableInfo, commonInfo,
+ commonInfo.BaseModuleName)+libDepTag.makeSuffix)
case objDepTag:
depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path())
case CrtBeginDepTag:
@@ -3373,21 +3782,30 @@
return depPaths
}
-func ShouldUseStubForApex(ctx android.ModuleContext, parent, dep android.Module) bool {
+func ShouldUseStubForApex(ctx android.ModuleContext, parent android.Module, dep android.ModuleProxy) bool {
inVendorOrProduct := false
bootstrap := false
- if linkable, ok := parent.(LinkableInterface); !ok {
- ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
+ if android.EqualModules(ctx.Module(), parent) {
+ if linkable, ok := parent.(LinkableInterface); !ok {
+ ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
+ } else {
+ inVendorOrProduct = linkable.InVendorOrProduct()
+ bootstrap = linkable.Bootstrap()
+ }
} else {
- inVendorOrProduct = linkable.InVendorOrProduct()
- bootstrap = linkable.Bootstrap()
+ if linkable, ok := android.OtherModuleProvider(ctx, parent, LinkableInfoProvider); !ok {
+ ctx.ModuleErrorf("Not a Linkable module: %q", ctx.ModuleName())
+ } else {
+ inVendorOrProduct = linkable.InVendorOrProduct
+ bootstrap = linkable.Bootstrap
+ }
}
apexInfo, _ := android.OtherModuleProvider(ctx, parent, android.ApexInfoProvider)
useStubs := false
- if lib := moduleLibraryInterface(dep); lib.buildStubs() && inVendorOrProduct { // LLNDK
+ if android.OtherModuleProviderOrDefault(ctx, dep, LinkableInfoProvider).IsStubs && inVendorOrProduct { // LLNDK
if !apexInfo.IsForPlatform() {
// For platform libraries, use current version of LLNDK
// If this is for use_vendor apex we will apply the same rules
@@ -3399,7 +3817,7 @@
// platform APIs, use stubs only when it is from an APEX (and not from
// platform) However, for host, ramdisk, vendor_ramdisk, recovery or
// bootstrap modules, always link to non-stub variant
- isNotInPlatform := dep.(android.ApexModule).NotInPlatform()
+ isNotInPlatform := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider).NotInPlatform
useStubs = isNotInPlatform && !bootstrap
} else {
@@ -3417,7 +3835,7 @@
// library bar which provides stable interface and exists in the platform, foo uses the stub variant
// of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
// same APEX as foo, the non-stub variant of bar is used.
-func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
+func ChooseStubOrImpl(ctx android.ModuleContext, dep android.ModuleProxy) (SharedLibraryInfo, FlagExporterInfo) {
depTag := ctx.OtherModuleDependencyTag(dep)
libDepTag, ok := depTag.(libraryDependencyTag)
if !ok || !libDepTag.shared() {
@@ -3478,32 +3896,29 @@
return libName
}
-func MakeLibName(ctx android.ModuleContext, c LinkableInterface, ccDep LinkableInterface, depName string) string {
+func MakeLibName(ccInfo *CcInfo, linkableInfo *LinkableInfo, commonInfo *android.CommonModuleInfo, depName string) string {
libName := BaseLibName(depName)
- ccDepModule, _ := ccDep.(*Module)
- isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
- nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
+ isLLndk := ccInfo != nil && linkableInfo.IsLlndk
+ nonSystemVariantsExist := linkableInfo.HasNonSystemVariants || isLLndk
- if ccDepModule != nil {
+ if ccInfo != nil {
// Use base module name for snapshots when exporting to Makefile.
- if snapshotPrebuilt, ok := ccDepModule.linker.(SnapshotInterface); ok {
- baseName := ccDepModule.BaseModuleName()
-
- return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix()
+ if ccInfo.SnapshotInfo != nil {
+ return commonInfo.BaseModuleName + ccInfo.SnapshotInfo.SnapshotAndroidMkSuffix
}
}
- if ccDep.InVendorOrProduct() && nonSystemVariantsExist {
+ if linkableInfo.InVendorOrProduct && nonSystemVariantsExist {
// The vendor and product modules in Make will have been renamed to not conflict with the
// core module, so update the dependency name here accordingly.
- return libName + ccDep.SubName()
- } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
+ return libName + linkableInfo.SubName
+ } else if linkableInfo.InRamdisk && !linkableInfo.OnlyInRamdisk {
return libName + RamdiskSuffix
- } else if ccDep.InVendorRamdisk() && !ccDep.OnlyInVendorRamdisk() {
+ } else if linkableInfo.InVendorRamdisk && !linkableInfo.OnlyInVendorRamdisk {
return libName + VendorRamdiskSuffix
- } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
+ } else if linkableInfo.InRecovery && !linkableInfo.OnlyInRecovery {
return libName + RecoverySuffix
- } else if ccDep.Target().NativeBridge == android.NativeBridgeEnabled {
+ } else if commonInfo.Target.NativeBridge == android.NativeBridgeEnabled {
return libName + NativeBridgeSuffix
} else {
return libName
@@ -3567,6 +3982,15 @@
return false
}
+func (c *Module) staticLibrary() bool {
+ if static, ok := c.linker.(interface {
+ staticLibrary() bool
+ }); ok {
+ return static.staticLibrary()
+ }
+ return false
+}
+
func (c *Module) staticBinary() bool {
if static, ok := c.linker.(interface {
staticBinary() bool
@@ -3631,6 +4055,10 @@
return false
}
+func (c *Module) ForceDisableSanitizers() {
+ c.sanitize.Properties.ForceDisable = true
+}
+
func (c *Module) StaticExecutable() bool {
if b, ok := c.linker.(*binaryDecorator); ok {
return b.static()
@@ -3686,19 +4114,24 @@
if lib := c.library; lib != nil {
// Stub libs and prebuilt libs in a versioned SDK are not
// installable to APEX even though they are shared libs.
- return lib.shared() && !lib.buildStubs()
+ return lib.shared() && !lib.BuildStubs()
}
return false
}
func (c *Module) AvailableFor(what string) bool {
+ return android.CheckAvailableForApex(what, c.ApexAvailableFor())
+}
+
+func (c *Module) ApexAvailableFor() []string {
+ list := c.ApexModuleBase.ApexAvailable()
if linker, ok := c.linker.(interface {
- availableFor(string) bool
+ apexAvailable() []string
}); ok {
- return c.ApexModuleBase.AvailableFor(what) || linker.availableFor(what)
- } else {
- return c.ApexModuleBase.AvailableFor(what)
+ list = append(list, linker.apexAvailable()...)
}
+
+ return android.FirstUniqueStrings(list)
}
func (c *Module) EverInstallable() bool {
@@ -3733,15 +4166,6 @@
return ret
}
- // Special case for modules that are configured to be installed to /data, which includes
- // test modules. For these modules, both APEX and non-APEX variants are considered as
- // installable. This is because even the APEX variants won't be included in the APEX, but
- // will anyway be installed to /data/*.
- // See b/146995717
- if c.InstallInData() {
- return ret
- }
-
return false
}
@@ -3756,36 +4180,24 @@
var _ android.ApexModule = (*Module)(nil)
// Implements android.ApexModule
-func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- depTag := ctx.OtherModuleDependencyTag(dep)
- libDepTag, isLibDepTag := depTag.(libraryDependencyTag)
-
- if cc, ok := dep.(*Module); ok {
- if cc.HasStubsVariants() {
- if isLibDepTag && libDepTag.shared() {
- // dynamic dep to a stubs lib crosses APEX boundary
- return false
- }
- if IsRuntimeDepTag(depTag) {
- // runtime dep to a stubs lib also crosses APEX boundary
- return false
- }
- }
- if cc.IsLlndk() {
- return false
- }
- if isLibDepTag && c.static() && libDepTag.shared() {
- // shared_lib dependency from a static lib is considered as crossing
- // the APEX boundary because the dependency doesn't actually is
- // linked; the dependency is used only during the compilation phase.
- return false
- }
-
- if isLibDepTag && libDepTag.excludeInApex {
- return false
- }
+func (c *Module) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return CcDepInSameApexChecker{
+ Static: c.static(),
+ HasStubsVariants: c.HasStubsVariants(),
+ IsLlndk: c.IsLlndk(),
+ Host: c.Host(),
}
- if depTag == stubImplDepTag {
+}
+
+type CcDepInSameApexChecker struct {
+ Static bool
+ HasStubsVariants bool
+ IsLlndk bool
+ Host bool
+}
+
+func (c CcDepInSameApexChecker) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if depTag == StubImplDepTag {
// We don't track from an implementation library to its stubs.
return false
}
@@ -3795,24 +4207,60 @@
// APEX.
return false
}
+
+ libDepTag, isLibDepTag := depTag.(libraryDependencyTag)
+ if isLibDepTag && c.Static && libDepTag.shared() {
+ // shared_lib dependency from a static lib is considered as crossing
+ // the APEX boundary because the dependency doesn't actually is
+ // linked; the dependency is used only during the compilation phase.
+ return false
+ }
+
+ if isLibDepTag && libDepTag.excludeInApex {
+ return false
+ }
+
+ return true
+}
+
+func (c CcDepInSameApexChecker) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if c.Host {
+ return false
+ }
+ if c.HasStubsVariants {
+ if IsSharedDepTag(depTag) && !IsExplicitImplSharedDepTag(depTag) {
+ // dynamic dep to a stubs lib crosses APEX boundary
+ return false
+ }
+ if IsRuntimeDepTag(depTag) {
+ // runtime dep to a stubs lib also crosses APEX boundary
+ return false
+ }
+ if IsHeaderDepTag(depTag) {
+ return false
+ }
+ }
+ if c.IsLlndk {
+ return false
+ }
+
return true
}
// Implements android.ApexModule
-func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
+func (c *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
// We ignore libclang_rt.* prebuilt libs since they declare sdk_version: 14(b/121358700)
if strings.HasPrefix(ctx.OtherModuleName(c), "libclang_rt") {
- return nil
+ return android.MinApiLevel
}
// We don't check for prebuilt modules
if _, ok := c.linker.(prebuiltLinkerInterface); ok {
- return nil
+ return android.MinApiLevel
}
minSdkVersion := c.MinSdkVersion()
if minSdkVersion == "apex_inherit" {
- return nil
+ return android.MinApiLevel
}
if minSdkVersion == "" {
// JNI libs within APK-in-APEX fall into here
@@ -3821,14 +4269,16 @@
// non-SDK variant resets sdk_version, which works too.
minSdkVersion = c.SdkVersion()
}
+
if minSdkVersion == "" {
- return fmt.Errorf("neither min_sdk_version nor sdk_version specificed")
+ return android.NoneApiLevel
}
+
// Not using nativeApiLevelFromUser because the context here is not
// necessarily a native context.
- ver, err := android.ApiLevelFromUser(ctx, minSdkVersion)
+ ver, err := android.ApiLevelFromUserWithConfig(ctx.Config(), minSdkVersion)
if err != nil {
- return err
+ return android.NoneApiLevel
}
// A dependency only needs to support a min_sdk_version at least
@@ -3836,15 +4286,14 @@
// This allows introducing new architectures in the platform that
// need to be included in apexes that normally require an older
// min_sdk_version.
- minApiForArch := MinApiForArch(ctx, c.Target().Arch.ArchType)
- if sdkVersion.LessThan(minApiForArch) {
- sdkVersion = minApiForArch
+ if c.Enabled(ctx) {
+ minApiForArch := MinApiForArch(ctx, c.Target().Arch.ArchType)
+ if ver.LessThanOrEqualTo(minApiForArch) {
+ ver = android.MinApiLevel
+ }
}
- if ver.GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", ver)
- }
- return nil
+ return ver
}
// Implements android.ApexModule
@@ -3918,7 +4367,6 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
- android.ApexModuleBase
}
// cc_defaults provides a set of properties that can be inherited by other cc
@@ -3985,7 +4433,7 @@
func (ks *kytheExtractAllSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var xrefTargets android.Paths
ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
- files := android.OtherModuleProviderOrDefault(ctx, module, CcObjectInfoProvider).kytheFiles
+ files := android.OtherModuleProviderOrDefault(ctx, module, CcObjectInfoProvider).KytheFiles
if len(files) > 0 {
xrefTargets = append(xrefTargets, files...)
}
diff --git a/cc/cc_preprocess_no_configuration_test.go b/cc/cc_preprocess_no_configuration_test.go
index c6eae4c..f09c44a 100644
--- a/cc/cc_preprocess_no_configuration_test.go
+++ b/cc/cc_preprocess_no_configuration_test.go
@@ -36,7 +36,7 @@
result := fixture.RunTest(t)
- foo := result.ModuleForTests("foo", "")
+ foo := result.ModuleForTests(t, "foo", "")
actual := foo.Rule("cc").Args["cFlags"]
expected := "-E -DANDROID -Ifoo/bar"
android.AssertStringEquals(t, "cflags should be correct", expected, actual)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 98af7b6..7240ea5 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -160,7 +160,7 @@
}
`)
- ld := ctx.ModuleForTests("libTest", vendorVariant).Rule("ld")
+ ld := ctx.ModuleForTests(t, "libTest", vendorVariant).Rule("ld")
var objs []string
for _, o := range ld.Inputs {
objs = append(objs, o.Base())
@@ -171,7 +171,7 @@
}
func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) {
- mod := ctx.ModuleForTests(name, variant).Module().(*Module)
+ mod := ctx.ModuleForTests(t, name, variant).Module().(*Module)
partitionDefined := false
checkPartition := func(specific bool, partition string) {
if specific {
@@ -311,7 +311,7 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
ctx := testCcWithConfig(t, config)
- testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
+ testingModule := ctx.ModuleForTests(t, "main_test", "android_arm_armv7-a-neon")
testBinary := testingModule.Module().(*Module).linker.(*testBinary)
outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
@@ -363,7 +363,7 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
ctx := testCcWithConfig(t, config)
- testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
+ testingModule := ctx.ModuleForTests(t, "main_test", "android_arm_armv7-a-neon")
module := testingModule.Module()
testBinary := module.(*Module).linker.(*testBinary)
outputFiles := testingModule.OutputFiles(ctx, t, "")
@@ -405,7 +405,7 @@
`
ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
- module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
+ module := ctx.ModuleForTests(t, "main_test", "android_arm_armv7-a-neon").Module()
entries := android.AndroidMkInfoForTest(t, ctx, module).PrimaryInfo
compatEntries := entries.EntryMap["LOCAL_COMPATIBILITY_SUITE"]
@@ -437,7 +437,7 @@
`
ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
- module := ctx.ModuleForTests("main_test_lib", "android_arm_armv7-a-neon_shared").Module()
+ module := ctx.ModuleForTests(t, "main_test_lib", "android_arm_armv7-a-neon_shared").Module()
entries := android.AndroidMkInfoForTest(t, ctx, module).PrimaryInfo
compatEntries := entries.EntryMap["LOCAL_COMPATIBILITY_SUITE"]
@@ -668,7 +668,7 @@
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- module := ctx.ModuleForTests(test.name, test.variant).Module().(*Module)
+ module := ctx.ModuleForTests(t, test.name, test.variant).Module().(*Module)
assertString(t, module.makeLinkType, test.expected)
})
}
@@ -861,10 +861,10 @@
`)
variant := "android_arm64_armv8-a_static"
- moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
+ moduleA := ctx.ModuleForTests(t, "a", variant).Module().(*Module)
staticLibInfo, _ := android.OtherModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
- expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
+ expected := GetOutputPaths(t, ctx, variant, []string{"a", "c", "b", "d"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings were not propagated correctly"+
@@ -897,10 +897,10 @@
`)
variant := "android_arm64_armv8-a_static"
- moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
+ moduleA := ctx.ModuleForTests(t, "a", variant).Module().(*Module)
staticLibInfo, _ := android.OtherModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
- expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b"})
+ expected := GetOutputPaths(t, ctx, variant, []string{"a", "c", "b"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings did not account for shared libs"+
@@ -1004,12 +1004,12 @@
}
android.AssertArrayString(t, "variants for llndk stubs", expected, actual)
- params := result.ModuleForTests("libllndk", "android_vendor_arm_armv7-a-neon_shared").Description("generate stub")
+ params := result.ModuleForTests(t, "libllndk", "android_vendor_arm_armv7-a-neon_shared").Description("generate stub")
android.AssertSame(t, "use Vendor API level for default stubs", "35", params.Args["apiLevel"])
checkExportedIncludeDirs := func(module, variant string, expectedSystemDirs []string, expectedDirs ...string) {
t.Helper()
- m := result.ModuleForTests(module, variant).Module()
+ m := result.ModuleForTests(t, module, variant).Module()
f, _ := android.OtherModuleProvider(result, m, FlagExporterInfoProvider)
android.AssertPathsRelativeToTopEquals(t, "exported include dirs for "+module+"["+variant+"]",
expectedDirs, f.IncludeDirs)
@@ -1030,14 +1030,14 @@
checkAbiLinkerIncludeDirs := func(module string) {
t.Helper()
- coreModule := result.ModuleForTests(module, coreVariant)
+ coreModule := result.ModuleForTests(t, module, coreVariant)
abiCheckFlags := ""
for _, output := range coreModule.AllOutputs() {
if strings.HasSuffix(output, ".so.llndk.lsdump") {
abiCheckFlags = coreModule.Output(output).Args["exportedHeaderFlags"]
}
}
- vendorModule := result.ModuleForTests(module, vendorVariant).Module()
+ vendorModule := result.ModuleForTests(t, module, vendorVariant).Module()
vendorInfo, _ := android.OtherModuleProvider(result, vendorModule, FlagExporterInfoProvider)
vendorDirs := android.Concat(vendorInfo.IncludeDirs, vendorInfo.SystemIncludeDirs)
android.AssertStringEquals(t, module+" has different exported include dirs for vendor variant and ABI check",
@@ -1078,7 +1078,7 @@
`)
// _static variant is used since _shared reuses *.o from the static variant
- cc := ctx.ModuleForTests("libvendor", "android_vendor_arm_armv7-a-neon_static").Rule("cc")
+ cc := ctx.ModuleForTests(t, "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)
@@ -1189,33 +1189,33 @@
// runtime_libs for core variants use the module names without suffixes.
variant := "android_arm64_armv8-a_shared"
- module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+ module := ctx.ModuleForTests(t, "libvendor_available1", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available"}, module)
- module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libproduct_available1", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available"}, module)
- module = ctx.ModuleForTests("libcore", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libcore", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available"}, module)
// runtime_libs for vendor variants have '.vendor' suffixes if the modules have both core
// and vendor variants.
variant = "android_vendor_arm64_armv8-a_shared"
- module = ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libvendor_available1", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available.vendor"}, module)
- module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libvendor2", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available.vendor", "libvendor1", "libproduct_vendor.vendor"}, module)
// runtime_libs for product variants have '.product' suffixes if the modules have both core
// and product variants.
variant = "android_product_arm64_armv8-a_shared"
- module = ctx.ModuleForTests("libproduct_available1", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libproduct_available1", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available.product"}, module)
- module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libproduct2", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available.product", "libproduct1", "libproduct_vendor"}, module)
}
@@ -1224,11 +1224,11 @@
ctx := testCc(t, runtimeLibAndroidBp)
variant := "android_arm64_armv8-a_shared"
- module := ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
+ module := ctx.ModuleForTests(t, "libvendor_available2", variant).Module().(*Module)
checkRuntimeLibs(t, []string{"liball_available"}, module)
variant = "android_vendor_arm64_armv8-a_shared"
- module = ctx.ModuleForTests("libvendor_available2", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "libvendor_available2", variant).Module().(*Module)
checkRuntimeLibs(t, nil, module)
}
@@ -1261,12 +1261,12 @@
// Check the shared version of lib2.
variant := "android_arm64_armv8-a_shared"
- module := ctx.ModuleForTests("lib2", variant).Module().(*Module)
+ module := ctx.ModuleForTests(t, "lib2", variant).Module().(*Module)
checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins"}, module)
// Check the static version of lib2.
variant = "android_arm64_armv8-a_static"
- module = ctx.ModuleForTests("lib2", variant).Module().(*Module)
+ module = ctx.ModuleForTests(t, "lib2", variant).Module().(*Module)
// libc++_static is linked additionally.
checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins"}, module)
}
@@ -1387,7 +1387,7 @@
t.Errorf("multilib was set to 32 for librecovery32, but its variants has %s.", arm64)
}
- recoveryModule := ctx.ModuleForTests("libHalInRecovery", recoveryVariant).Module().(*Module)
+ recoveryModule := ctx.ModuleForTests(t, "libHalInRecovery", recoveryVariant).Module().(*Module)
if !recoveryModule.Platform() {
t.Errorf("recovery variant of libHalInRecovery must not specific to device, soc, or product")
}
@@ -1412,7 +1412,7 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
ctx := testCcWithConfig(t, config)
- testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
+ testingModule := ctx.ModuleForTests(t, "main_test", "android_arm_armv7-a-neon")
module := testingModule.Module()
testBinary := module.(*Module).linker.(*testBinary)
outputFiles := testingModule.OutputFiles(ctx, t, "")
@@ -1487,14 +1487,14 @@
}
}
- libBarLinkRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_shared").Rule("ld")
+ libBarLinkRule := ctx.ModuleForTests(t, "libBar", "android_arm64_armv8-a_shared").Rule("ld")
libFlags := libBarLinkRule.Args["libFlags"]
libFoo1StubPath := "libFoo/android_arm64_armv8-a_shared_1/libFoo.so"
if !strings.Contains(libFlags, libFoo1StubPath) {
t.Errorf("%q is not found in %q", libFoo1StubPath, libFlags)
}
- libBarCompileRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_shared").Rule("cc")
+ libBarCompileRule := ctx.ModuleForTests(t, "libBar", "android_arm64_armv8-a_shared").Rule("cc")
cFlags := libBarCompileRule.Args["cFlags"]
libFoo1VersioningMacro := "-D__LIBFOO_API__=1"
if !strings.Contains(cFlags, libFoo1VersioningMacro) {
@@ -1550,7 +1550,7 @@
}`)
variant := "android_arm64_armv8-a_static"
- arRule := ctx.ModuleForTests("baz", variant).Rule("ar")
+ arRule := ctx.ModuleForTests(t, "baz", variant).Rule("ar")
// For static libraries, the object files of a whole static dep are included in the archive
// directly
@@ -1591,7 +1591,7 @@
}`)
variant := "android_arm64_armv8-a_shared"
- linkRule := ctx.ModuleForTests("baz", variant).Rule("ld")
+ linkRule := ctx.ModuleForTests(t, "baz", variant).Rule("ld")
libFlags := linkRule.Args["libFlags"]
// When dynamically linking, we expect static dependencies to be found on the command line
if expected := "foo.a"; !strings.Contains(libFlags, expected) {
@@ -1623,7 +1623,7 @@
}`)
variant := "android_arm64_armv8-a"
- binModuleRule := ctx.ModuleForTests("static_test", variant).Rule("ld")
+ binModuleRule := ctx.ModuleForTests(t, "static_test", variant).Rule("ld")
libFlags := binModuleRule.Args["libFlags"]
systemStaticLibs := []string{"libc.a", "libm.a"}
for _, lib := range systemStaticLibs {
@@ -1666,9 +1666,9 @@
},
}`)
- mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Rule("ld")
+ mybin := ctx.ModuleForTests(t, "mybin", "android_arm64_armv8-a").Rule("ld")
actual := mybin.Implicits[:2]
- expected := GetOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
+ expected := GetOutputPaths(t, ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings were not propagated correctly"+
@@ -1775,7 +1775,7 @@
checkPcGuardFlag := func(
modName string, variantName string, shouldHave bool) {
- cc := ctx.ModuleForTests(modName, variantName).Rule("cc")
+ cc := ctx.ModuleForTests(t, modName, variantName).Rule("cc")
cFlags, ok := cc.Args["cFlags"]
if !ok {
@@ -1802,9 +1802,9 @@
checkPcGuardFlag(moduleName, variant+"_static", false)
checkPcGuardFlag(moduleName, variant+"_static_fuzzer_afl", true)
- ctx.ModuleForTests("afl_fuzz_shared_lib",
+ ctx.ModuleForTests(t, "afl_fuzz_shared_lib",
"android_arm64_armv8-a_shared").Rule("cc")
- ctx.ModuleForTests("afl_fuzz_shared_lib",
+ ctx.ModuleForTests(t, "afl_fuzz_shared_lib",
"android_arm64_armv8-a_shared_fuzzer").Rule("cc")
}
@@ -1833,7 +1833,7 @@
}`)
variant := "android_arm64_armv8-a_fuzzer"
- ctx.ModuleForTests("fuzz_smoke_test", variant).Rule("cc")
+ ctx.ModuleForTests(t, "fuzz_smoke_test", variant).Rule("cc")
}
func assertString(t *testing.T, got, expected string) {
@@ -1897,24 +1897,24 @@
defaults: ["defaults"],
}`)
- shared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Rule("ld")
+ shared := ctx.ModuleForTests(t, "libshared", "android_arm64_armv8-a_shared").Rule("ld")
if g, w := pathsToBase(shared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
t.Errorf("libshared ld rule wanted %q, got %q", w, g)
}
- bothShared := ctx.ModuleForTests("libboth", "android_arm64_armv8-a_shared").Rule("ld")
+ bothShared := ctx.ModuleForTests(t, "libboth", "android_arm64_armv8-a_shared").Rule("ld")
if g, w := pathsToBase(bothShared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
t.Errorf("libboth ld rule wanted %q, got %q", w, g)
}
- binary := ctx.ModuleForTests("binary", "android_arm64_armv8-a").Rule("ld")
+ binary := ctx.ModuleForTests(t, "binary", "android_arm64_armv8-a").Rule("ld")
if g, w := pathsToBase(binary.Inputs), []string{"foo.o"}; !reflect.DeepEqual(w, g) {
t.Errorf("binary ld rule wanted %q, got %q", w, g)
}
- static := ctx.ModuleForTests("libstatic", "android_arm64_armv8-a_static").Rule("ar")
+ static := ctx.ModuleForTests(t, "libstatic", "android_arm64_armv8-a_static").Rule("ar")
if g, w := pathsToBase(static.Inputs), []string{"foo.o", "bar.o"}; !reflect.DeepEqual(w, g) {
t.Errorf("libstatic ar rule wanted %q, got %q", w, g)
}
- bothStatic := ctx.ModuleForTests("libboth", "android_arm64_armv8-a_static").Rule("ar")
+ bothStatic := ctx.ModuleForTests(t, "libboth", "android_arm64_armv8-a_static").Rule("ar")
if g, w := pathsToBase(bothStatic.Inputs), []string{"foo.o", "bar.o"}; !reflect.DeepEqual(w, g) {
t.Errorf("libboth ar rule wanted %q, got %q", w, g)
}
@@ -1973,12 +1973,12 @@
android.PrepareForTestWithAllowMissingDependencies,
).RunTestWithBp(t, bp)
- libbar := result.ModuleForTests("libbar", "android_arm64_armv8-a_static").Output("libbar.a")
+ libbar := result.ModuleForTests(t, "libbar", "android_arm64_armv8-a_static").Output("libbar.a")
android.AssertDeepEquals(t, "libbar rule", android.ErrorRule, libbar.Rule)
android.AssertStringDoesContain(t, "libbar error", libbar.Args["error"], "missing dependencies: libmissing")
- libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Output("libfoo.a")
+ libfoo := result.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static").Output("libfoo.a")
android.AssertStringListContains(t, "libfoo.a dependencies", libfoo.Inputs.Strings(), libbar.Output.String())
}
@@ -2025,11 +2025,11 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
ctx := testCcWithConfig(t, config)
- hostBin := ctx.ModuleForTests("bin", config.BuildOSTarget.String()).Description("install")
- hostShared := ctx.ModuleForTests("libshared", config.BuildOSTarget.String()+"_shared").Description("install")
- hostRuntime := ctx.ModuleForTests("libruntime", config.BuildOSTarget.String()+"_shared").Description("install")
- hostTransitive := ctx.ModuleForTests("libtransitive", config.BuildOSTarget.String()+"_shared").Description("install")
- hostTool := ctx.ModuleForTests("tool", config.BuildOSTarget.String()).Description("install")
+ hostBin := ctx.ModuleForTests(t, "bin", config.BuildOSTarget.String()).Description("install")
+ hostShared := ctx.ModuleForTests(t, "libshared", config.BuildOSTarget.String()+"_shared").Description("install")
+ hostRuntime := ctx.ModuleForTests(t, "libruntime", config.BuildOSTarget.String()+"_shared").Description("install")
+ hostTransitive := ctx.ModuleForTests(t, "libtransitive", config.BuildOSTarget.String()+"_shared").Description("install")
+ hostTool := ctx.ModuleForTests(t, "tool", config.BuildOSTarget.String()).Description("install")
if g, w := hostBin.Implicits.Strings(), hostShared.Output.String(); !android.InList(w, g) {
t.Errorf("expected host bin dependency %q, got %q", w, g)
@@ -2051,10 +2051,10 @@
t.Errorf("expected no host bin dependency %q, got %q", w, g)
}
- deviceBin := ctx.ModuleForTests("bin", "android_arm64_armv8-a").Description("install")
- deviceShared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Description("install")
- deviceTransitive := ctx.ModuleForTests("libtransitive", "android_arm64_armv8-a_shared").Description("install")
- deviceRuntime := ctx.ModuleForTests("libruntime", "android_arm64_armv8-a_shared").Description("install")
+ deviceBin := ctx.ModuleForTests(t, "bin", "android_arm64_armv8-a").Description("install")
+ deviceShared := ctx.ModuleForTests(t, "libshared", "android_arm64_armv8-a_shared").Description("install")
+ deviceTransitive := ctx.ModuleForTests(t, "libtransitive", "android_arm64_armv8-a_shared").Description("install")
+ deviceRuntime := ctx.ModuleForTests(t, "libruntime", "android_arm64_armv8-a_shared").Description("install")
if g, w := deviceBin.OrderOnly.Strings(), deviceShared.Output.String(); !android.InList(w, g) {
t.Errorf("expected device bin dependency %q, got %q", w, g)
@@ -2104,7 +2104,7 @@
srcs: ["foo.c"],
}`)
- cFlags := ctx.ModuleForTests("libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+ cFlags := ctx.ModuleForTests(t, "libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, "-Iinclude/libbar") {
t.Errorf("expected %q in cflags, got %q", "-Iinclude/libbar", cFlags)
@@ -2144,7 +2144,7 @@
}.AddToFixture(),
).RunTest(t).TestContext
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static")
android.AssertPathsRelativeToTopEquals(
t,
@@ -2192,7 +2192,7 @@
}
`)
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static")
manifest := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, libfoo.Output("aidl.sbox.textproto"))
aidlCommand := manifest.Commands[0].GetCommand()
expectedAidlFlag := "-Werror"
@@ -2243,7 +2243,7 @@
`+tc.sdkVersion+`
}
`)
- libfoo := ctx.ModuleForTests("libfoo", tc.variant)
+ libfoo := ctx.ModuleForTests(t, "libfoo", tc.variant)
manifest := android.RuleBuilderSboxProtoForTests(t, ctx, libfoo.Output("aidl.sbox.textproto"))
aidlCommand := manifest.Commands[0].GetCommand()
expectedAidlFlag := "--min_sdk_version=" + tc.expected
@@ -2312,7 +2312,7 @@
min_sdk_version: "29",
}`)
- cFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+ cFlags := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android29")
}
@@ -2332,7 +2332,7 @@
}),
).RunTestWithBp(t, bp)
ctx := result.TestContext
- cFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+ cFlags := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android31")
}
@@ -2439,7 +2439,7 @@
export_generated_headers: ["genrule_bar"],
}
`)
- foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
foo/standard
@@ -2450,7 +2450,7 @@
expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
)
- bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
+ bar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, bar,
expectedIncludeDirs(`
bar/standard
@@ -2483,7 +2483,7 @@
export_generated_headers: ["genrule_bar"],
}
`)
- foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
foo/standard
@@ -2494,7 +2494,7 @@
expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
)
- bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
+ bar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, bar,
expectedIncludeDirs(`
bar/standard
@@ -2540,7 +2540,7 @@
}
}
`).TestContext
- foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl
@@ -2580,7 +2580,7 @@
}
}
`)
- foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto
@@ -2607,7 +2607,7 @@
],
}
`)
- foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include
@@ -2689,7 +2689,7 @@
cppOnly := []string{"-fPIC", "${config.CommonGlobalCppflags}", "${config.DeviceGlobalCppflags}", "${config.ArmCppflags}"}
cflags := []string{"-Werror", "-std=candcpp"}
- cstd := []string{"-std=gnu17", "-std=conly"}
+ cstd := []string{"-std=gnu23", "-std=conly"}
cppstd := []string{"-std=gnu++20", "-std=cpp", "-fno-rtti"}
lastNDKFlags := []string{
@@ -2877,7 +2877,7 @@
PrepareForIntegrationTestWithCc,
android.FixtureAddTextFile("external/foo/Android.bp", bp),
).RunTest(t)
- cflags := ctx.ModuleForTests("libfoo", variant).Output("obj/external/foo/foo.o").Args["cFlags"]
+ cflags := ctx.ModuleForTests(t, "libfoo", variant).Output("obj/external/foo/foo.o").Args["cFlags"]
var includes []string
flags := strings.Split(cflags, " ")
@@ -2931,7 +2931,7 @@
srcs: ["foo.c"],
}`)
- cFlags := ctx.ModuleForTests("libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+ cFlags := ctx.ModuleForTests(t, "libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, "${config.NoOverride64GlobalCflags}") {
t.Errorf("expected %q in cflags, got %q", "${config.NoOverride64GlobalCflags}", cFlags)
@@ -3095,7 +3095,7 @@
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
ctx := testCcWithConfig(t, config)
- testingModule := ctx.ModuleForTests("test_lib", "android_arm_armv7-a-neon_shared")
+ testingModule := ctx.ModuleForTests(t, "test_lib", "android_arm_armv7-a-neon_shared")
outputFile := testingModule.OutputFiles(ctx, t, "stripped_all")
if !strings.HasSuffix(outputFile.Strings()[0], "/stripped_all/test_lib.so") {
t.Errorf("Unexpected output file: %s", outputFile.Strings()[0])
@@ -3140,8 +3140,8 @@
if imageVariant != "core" {
imageVariantStr = "_" + imageVariant
}
- binFooModule := ctx.ModuleForTests("binfoo", "android"+imageVariantStr+"_arm64_armv8-a").Module()
- libBarModule := ctx.ModuleForTests("libbar", "android"+imageVariantStr+"_arm64_armv8-a_shared").Module()
+ binFooModule := ctx.ModuleForTests(t, "binfoo", "android"+imageVariantStr+"_arm64_armv8-a").Module()
+ libBarModule := ctx.ModuleForTests(t, "libbar", "android"+imageVariantStr+"_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, "binfoo should have dependency on libbar with image variant "+imageVariant, true, hasDep(binFooModule, libBarModule))
}
@@ -3172,7 +3172,7 @@
ctx := prepareForCcTest.RunTestWithBp(t, bp)
testSdkVersionFlag := func(module, variant, version string) {
- flags := ctx.ModuleForTests(module, "android_"+variant+"_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ flags := ctx.ModuleForTests(t, module, "android_"+variant+"_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "target SDK version", flags, "-target aarch64-linux-android"+version)
}
@@ -3199,14 +3199,14 @@
}
`)
- module := ctx.ModuleForTests("lib_no_clang_verify", "android_arm64_armv8-a_shared")
+ module := ctx.ModuleForTests(t, "lib_no_clang_verify", "android_arm64_armv8-a_shared")
cFlags_no_cv := module.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags_no_cv, "-Xclang") || strings.Contains(cFlags_no_cv, "-verify") {
t.Errorf("expected %q not in cflags, got %q", "-Xclang -verify", cFlags_no_cv)
}
- cFlags_cv := ctx.ModuleForTests("lib_clang_verify", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+ cFlags_cv := ctx.ModuleForTests(t, "lib_clang_verify", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
if strings.Contains(cFlags_cv, "-Xclang") && strings.Contains(cFlags_cv, "-verify") {
t.Errorf("expected %q in cflags, got %q", "-Xclang -verify", cFlags_cv)
}
diff --git a/cc/cc_test_only_property_test.go b/cc/cc_test_only_property_test.go
index 972e86b..a178cad 100644
--- a/cc/cc_test_only_property_test.go
+++ b/cc/cc_test_only_property_test.go
@@ -173,7 +173,7 @@
func getTeamProtoOutput(t *testing.T, ctx *android.TestResult) *team_proto.AllTeams {
teams := new(team_proto.AllTeams)
- config := ctx.SingletonForTests("all_teams")
+ config := ctx.SingletonForTests(t, "all_teams")
allOutputs := config.AllOutputs()
protoPath := allOutputs[0]
diff --git a/cc/ccdeps.go b/cc/ccdeps.go
index 469fe31..4247778 100644
--- a/cc/ccdeps.go
+++ b/cc/ccdeps.go
@@ -41,8 +41,6 @@
outputPath android.Path
}
-var _ android.SingletonMakeVarsProvider = (*ccdepsGeneratorSingleton)(nil)
-
const (
ccdepsJsonFileName = "module_bp_cc_deps.json"
cClang = "clang"
@@ -114,13 +112,6 @@
Rule: android.Touch,
Output: ccfpath,
})
-}
-
-func (c *ccdepsGeneratorSingleton) MakeVars(ctx android.MakeVarsContext) {
- if c.outputPath == nil {
- return
- }
-
ctx.DistForGoal("general-tests", c.outputPath)
}
diff --git a/cc/cmake_module_aidl.txt b/cc/cmake_module_aidl.txt
index 84755a3..3622648 100644
--- a/cc/cmake_module_aidl.txt
+++ b/cc/cmake_module_aidl.txt
@@ -1,11 +1,11 @@
# <<.M.Name>>
-<<setList .M.Name "_SRCS" "" (getAidlSources .M)>>
+<<setList .M.Name "_SRCS" "" (getAidlSources .CcInfo)>>
-<<setList .M.Name "_AIDLFLAGS" "" (getCompilerProperties .M).AidlInterface.Flags>>
+<<setList .M.Name "_AIDLFLAGS" "" (getAidlInterface .CcInfo).Flags>>
-add_aidl_library(<<.M.Name>> <<(getCompilerProperties .M).AidlInterface.Lang>>
- "${ANDROID_BUILD_TOP}/<<.Ctx.OtherModuleDir .M>>/<<(getCompilerProperties .M).AidlInterface.AidlRoot>>"
+add_aidl_library(<<.M.Name>> <<(getAidlInterface .CcInfo).Lang>>
+ "${ANDROID_BUILD_TOP}/<<.Ctx.OtherModuleDir .M>>/<<(getAidlInterface .CcInfo).AidlRoot>>"
"${<<.M.Name>>_SRCS}"
"${<<.M.Name>>_AIDLFLAGS}")
add_library(android::<<.M.Name>> ALIAS <<.M.Name>>)
diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt
index 0f6e62f..a57e053 100644
--- a/cc/cmake_module_cc.txt
+++ b/cc/cmake_module_cc.txt
@@ -1,14 +1,14 @@
-<<$srcs := getSources .M>>
-<<$includeDirs := getIncludeDirs .Ctx .M>>
-<<$cflags := getCflagsProperty .Ctx .M>>
+<<$srcs := getSources .Ctx .CcInfo>>
+<<$includeDirs := getIncludeDirs .Ctx .M .CcInfo>>
+<<$cflags := getCflagsProperty .Ctx .CcInfo>>
<<$deps := mapLibraries .Ctx .M (concat5
-(getWholeStaticLibsProperty .Ctx .M)
-(getStaticLibsProperty .Ctx .M)
-(getSharedLibsProperty .Ctx .M)
-(getHeaderLibsProperty .Ctx .M)
-(getExtraLibs .M)
+(getWholeStaticLibsProperty .Ctx .CcInfo)
+(getStaticLibsProperty .Ctx .CcInfo)
+(getSharedLibsProperty .Ctx .CcInfo)
+(getHeaderLibsProperty .Ctx .CcInfo)
+(getExtraLibs .CcInfo)
) .Pprop.LibraryMapping>>
-<<$moduleType := getModuleType .M>>
+<<$moduleType := getModuleType .CcInfo>>
<<$moduleTypeCmake := "executable">>
<<if eq $moduleType "library">>
<<$moduleTypeCmake = "library">>
diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go
index f553f27..3f6a01d 100644
--- a/cc/cmake_snapshot.go
+++ b/cc/cmake_snapshot.go
@@ -196,39 +196,31 @@
return list.String()
},
- "getSources": func(m *Module) android.Paths {
- return m.compiler.(CompiledInterface).Srcs()
+ "getSources": func(ctx android.ModuleContext, info *CcInfo) android.Paths {
+ return info.CompilerInfo.Srcs
},
"getModuleType": getModuleType,
- "getCompilerProperties": func(m *Module) BaseCompilerProperties {
- return m.compiler.baseCompilerProps()
+ "getAidlInterface": func(info *CcInfo) AidlInterfaceInfo {
+ return info.CompilerInfo.AidlInterfaceInfo
},
- "getCflagsProperty": func(ctx android.ModuleContext, m *Module) []string {
- prop := m.compiler.baseCompilerProps().Cflags
- return prop.GetOrDefault(ctx, nil)
+ "getCflagsProperty": func(ctx android.ModuleContext, info *CcInfo) []string {
+ return info.CompilerInfo.Cflags
},
- "getLinkerProperties": func(m *Module) BaseLinkerProperties {
- return m.linker.baseLinkerProps()
+ "getWholeStaticLibsProperty": func(ctx android.ModuleContext, info *CcInfo) []string {
+ return info.LinkerInfo.WholeStaticLibs
},
- "getWholeStaticLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
- prop := m.linker.baseLinkerProps().Whole_static_libs
- return prop.GetOrDefault(ctx, nil)
+ "getStaticLibsProperty": func(ctx android.ModuleContext, info *CcInfo) []string {
+ return info.LinkerInfo.StaticLibs
},
- "getStaticLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
- prop := m.linker.baseLinkerProps().Static_libs
- return prop.GetOrDefault(ctx, nil)
+ "getSharedLibsProperty": func(ctx android.ModuleContext, info *CcInfo) []string {
+ return info.LinkerInfo.SharedLibs
},
- "getSharedLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
- prop := m.linker.baseLinkerProps().Shared_libs
- return prop.GetOrDefault(ctx, nil)
- },
- "getHeaderLibsProperty": func(ctx android.ModuleContext, m *Module) []string {
- prop := m.linker.baseLinkerProps().Header_libs
- return prop.GetOrDefault(ctx, nil)
+ "getHeaderLibsProperty": func(ctx android.ModuleContext, info *CcInfo) []string {
+ return info.LinkerInfo.HeaderLibs
},
"getExtraLibs": getExtraLibs,
"getIncludeDirs": getIncludeDirs,
- "mapLibraries": func(ctx android.ModuleContext, m *Module, libs []string, mapping map[string]LibraryMappingProperty) []string {
+ "mapLibraries": func(ctx android.ModuleContext, m android.ModuleProxy, libs []string, mapping map[string]LibraryMappingProperty) []string {
var mappedLibs []string
for _, lib := range libs {
mappedLib, exists := mapping[lib]
@@ -249,8 +241,8 @@
mappedLibs = slices.Compact(mappedLibs)
return mappedLibs
},
- "getAidlSources": func(m *Module) []string {
- aidlInterface := m.compiler.baseCompilerProps().AidlInterface
+ "getAidlSources": func(info *CcInfo) []string {
+ aidlInterface := info.CompilerInfo.AidlInterfaceInfo
aidlRoot := aidlInterface.AidlRoot + string(filepath.Separator)
if aidlInterface.AidlRoot == "" {
aidlRoot = ""
@@ -340,14 +332,14 @@
moduleDirs := map[string][]string{}
sourceFiles := map[string]android.Path{}
visitedModules := map[string]bool{}
- var pregeneratedModules []*Module
- ctx.WalkDeps(func(dep_a android.Module, parent android.Module) bool {
- moduleName := ctx.OtherModuleName(dep_a)
+ var pregeneratedModules []android.ModuleProxy
+ ctx.WalkDepsProxy(func(dep, parent android.ModuleProxy) bool {
+ moduleName := ctx.OtherModuleName(dep)
if visited := visitedModules[moduleName]; visited {
return false // visit only once
}
visitedModules[moduleName] = true
- dep, ok := dep_a.(*Module)
+ ccInfo, ok := android.OtherModuleProvider(ctx, dep, CcInfoProvider)
if !ok {
return false // not a cc module
}
@@ -363,15 +355,15 @@
if slices.Contains(ignoredSystemLibs, moduleName) {
return false // system libs built in-tree for Android
}
- if dep.IsPrebuilt() {
+ if ccInfo.IsPrebuilt {
return false // prebuilts are not supported
}
- if dep.compiler == nil {
+ if ccInfo.CompilerInfo == nil {
return false // unsupported module type
}
- isAidlModule := dep.compiler.baseCompilerProps().AidlInterface.Lang != ""
+ isAidlModule := ccInfo.CompilerInfo.AidlInterfaceInfo.Lang != ""
- if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) {
+ if !ccInfo.CmakeSnapshotSupported {
ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported",
"CMake snapshots not supported, despite being a dependency for %s",
ctx.OtherModuleName(parent))
@@ -389,12 +381,14 @@
}
moduleFragment := executeTemplate(templateToUse, &templateBuffer, struct {
Ctx *android.ModuleContext
- M *Module
+ M android.ModuleProxy
+ CcInfo *CcInfo
Snapshot *CmakeSnapshot
Pprop *cmakeProcessedProperties
}{
&ctx,
dep,
+ ccInfo,
m,
&pprop,
})
@@ -415,7 +409,7 @@
// Enumerate sources for pregenerated modules
if m.Properties.Include_sources {
for _, dep := range pregeneratedModules {
- if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) {
+ if !android.OtherModuleProviderOrDefault(ctx, dep, CcInfoProvider).CmakeSnapshotSupported {
ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported",
"Pregenerated CMake snapshots not supported, despite being requested for %s",
ctx.ModuleName())
@@ -491,7 +485,7 @@
if len(m.Properties.Prebuilts) > 0 {
var prebuiltsList android.Paths
- ctx.VisitDirectDepsWithTag(cmakeSnapshotPrebuiltTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(cmakeSnapshotPrebuiltTag, func(dep android.ModuleProxy) {
for _, file := range android.OtherModuleProviderOrDefault(
ctx, dep, android.InstallFilesProvider).InstallFiles {
prebuiltsList = append(prebuiltsList, file)
@@ -523,42 +517,37 @@
}}
}
-func getModuleType(m *Module) string {
- switch m.linker.(type) {
- case *binaryDecorator:
+func getModuleType(info *CcInfo) string {
+ if info.LinkerInfo.BinaryDecoratorInfo != nil {
return "executable"
- case *libraryDecorator:
+ } else if info.LinkerInfo.LibraryDecoratorInfo != nil {
return "library"
- case *testBinary:
+ } else if info.LinkerInfo.TestBinaryInfo != nil || info.LinkerInfo.BenchmarkDecoratorInfo != nil {
return "test"
- case *benchmarkDecorator:
- return "test"
- case *objectLinker:
+ } else if info.LinkerInfo.ObjectLinkerInfo != nil {
return "object"
}
- panic(fmt.Sprintf("Unexpected module type: %T", m.linker))
+ panic(fmt.Sprintf("Unexpected module type for LinkerInfo"))
}
-func getExtraLibs(m *Module) []string {
- switch decorator := m.linker.(type) {
- case *testBinary:
- if decorator.testDecorator.gtest() {
+func getExtraLibs(info *CcInfo) []string {
+ if info.LinkerInfo.TestBinaryInfo != nil {
+ if info.LinkerInfo.TestBinaryInfo.Gtest {
return []string{
"libgtest",
"libgtest_main",
}
}
- case *benchmarkDecorator:
+ } else if info.LinkerInfo.BenchmarkDecoratorInfo != nil {
return []string{"libgoogle-benchmark"}
}
return nil
}
-func getIncludeDirs(ctx android.ModuleContext, m *Module) []string {
+func getIncludeDirs(ctx android.ModuleContext, m android.ModuleProxy, info *CcInfo) []string {
moduleDir := ctx.OtherModuleDir(m) + string(filepath.Separator)
- switch decorator := m.compiler.(type) {
- case *libraryDecorator:
- return sliceWithPrefix(moduleDir, decorator.flagExporter.Properties.Export_include_dirs.GetOrDefault(ctx, nil))
+ if info.CompilerInfo.LibraryDecoratorInfo != nil {
+ return sliceWithPrefix(moduleDir, info.CompilerInfo.LibraryDecoratorInfo.ExportIncludeDirs)
}
return nil
}
diff --git a/cc/cmake_snapshot_test.go b/cc/cmake_snapshot_test.go
index b6f4369..d08096a 100644
--- a/cc/cmake_snapshot_test.go
+++ b/cc/cmake_snapshot_test.go
@@ -49,7 +49,7 @@
t.Skip("CMake snapshots are only supported on Linux")
}
- snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64")
+ snapshotModule := result.ModuleForTests(t, "foo", "linux_glibc_x86_64")
wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy")
wasGenerated(t, &snapshotModule, "foo.zip", "")
@@ -77,7 +77,7 @@
t.Skip("CMake snapshots are only supported on Linux")
}
- snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64")
+ snapshotModule := result.ModuleForTests(t, "foo", "linux_glibc_x86_64")
wasGenerated(t, &snapshotModule, "some/module/CMakeLists.txt", "rawFileCopy")
}
@@ -110,7 +110,7 @@
t.Skip("CMake snapshots are only supported on Linux")
}
- snapshotModule := result.ModuleForTests("foo", "linux_glibc_x86_64")
+ snapshotModule := result.ModuleForTests(t, "foo", "linux_glibc_x86_64")
wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy")
wasGenerated(t, &snapshotModule, "foo.zip", "")
diff --git a/cc/compdb.go b/cc/compdb.go
index 4132e09..3818e9c 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -193,7 +193,7 @@
}
builds[src.String()] = compDbEntry{
Directory: android.AbsSrcDirForExistingUseCases(),
- Arguments: getArguments(src, ctx, ccModule, ccPath, cxxPath),
+ Arguments: args,
File: src.String(),
}
}
diff --git a/cc/compiler.go b/cc/compiler.go
index 91f107c..949603e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -324,6 +324,10 @@
getNamedMapForConfig(ctx.Config(), key).Store(module, true)
}
+func requiresGlobalIncludes(ctx ModuleContext) bool {
+ return !(ctx.useSdk() || ctx.InVendorOrProduct()) || ctx.Host()
+}
+
func useGnuExtensions(gnuExtensions *bool) bool {
return proptools.BoolDefault(gnuExtensions, true)
}
@@ -360,6 +364,29 @@
}
}
+func AddTargetFlags(ctx android.ModuleContext, flags Flags, tc config.Toolchain, version string, bpf bool) Flags {
+ target := "-target " + tc.ClangTriple()
+ if ctx.Os().Class == android.Device {
+ if version == "" || version == "current" {
+ target += strconv.Itoa(android.FutureApiLevelInt)
+ } else {
+ apiLevel := nativeApiLevelOrPanic(ctx, version)
+ target += strconv.Itoa(apiLevel.FinalOrFutureInt())
+ }
+ }
+
+ // bpf targets don't need the default target triple. b/308826679
+ if bpf {
+ target = "--target=bpf"
+ }
+
+ flags.Global.CFlags = append(flags.Global.CFlags, target)
+ flags.Global.AsFlags = append(flags.Global.AsFlags, target)
+ flags.Global.LdFlags = append(flags.Global.LdFlags, target)
+
+ return flags
+}
+
// Create a Flags struct that collects the compile flags from global values,
// per-target values, module type values, and per-module Blueprints properties
func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
@@ -367,7 +394,7 @@
modulePath := ctx.ModuleDir()
reuseObjs := false
- if len(ctx.GetDirectDepsWithTag(reuseObjTag)) > 0 {
+ if len(ctx.GetDirectDepsProxyWithTag(reuseObjTag)) > 0 {
reuseObjs = true
}
@@ -429,7 +456,7 @@
flags.Local.YasmFlags = append(flags.Local.YasmFlags, "-I"+modulePath)
}
- if !(ctx.useSdk() || ctx.InVendorOrProduct()) || ctx.Host() {
+ if requiresGlobalIncludes(ctx) {
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
"${config.CommonGlobalIncludes}",
tc.IncludeFlags())
@@ -513,25 +540,7 @@
flags.Local.ConlyFlags = config.ClangFilterUnknownCflags(flags.Local.ConlyFlags)
flags.Local.LdFlags = config.ClangFilterUnknownCflags(flags.Local.LdFlags)
- target := "-target " + tc.ClangTriple()
- if ctx.Os().Class == android.Device {
- version := ctx.minSdkVersion()
- if version == "" || version == "current" {
- target += strconv.Itoa(android.FutureApiLevelInt)
- } else {
- apiLevel := nativeApiLevelOrPanic(ctx, version)
- target += strconv.Itoa(apiLevel.FinalOrFutureInt())
- }
- }
-
- // bpf targets don't need the default target triple. b/308826679
- if proptools.Bool(compiler.Properties.Bpf_target) {
- target = "--target=bpf"
- }
-
- flags.Global.CFlags = append(flags.Global.CFlags, target)
- flags.Global.AsFlags = append(flags.Global.AsFlags, target)
- flags.Global.LdFlags = append(flags.Global.LdFlags, target)
+ flags = AddTargetFlags(ctx, flags, tc, ctx.minSdkVersion(), Bool(compiler.Properties.Bpf_target))
hod := "Host"
if ctx.Os().Class == android.Device {
@@ -785,7 +794,7 @@
objs := compileObjs(ctx, buildFlags, "", srcs,
append(android.PathsForModuleSrc(ctx, compiler.Properties.Tidy_disabled_srcs), compiler.generatedSources...),
android.PathsForModuleSrc(ctx, compiler.Properties.Tidy_timeout_srcs),
- pathDeps, compiler.cFlagsDeps)
+ pathDeps, compiler.cFlagsDeps, ctx.getSharedFlags())
if ctx.Failed() {
return Objects{}
@@ -795,10 +804,12 @@
}
// Compile a list of source files into objects a specified subdirectory
-func compileObjs(ctx ModuleContext, flags builderFlags, subdir string,
- srcFiles, noTidySrcs, timeoutTidySrcs, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
+func compileObjs(ctx android.ModuleContext, flags builderFlags, subdir string,
+ srcFiles, noTidySrcs, timeoutTidySrcs, pathDeps android.Paths, cFlagsDeps android.Paths,
+ sharedFlags *SharedFlags) Objects {
- return transformSourceToObj(ctx, subdir, srcFiles, noTidySrcs, timeoutTidySrcs, flags, pathDeps, cFlagsDeps)
+ return transformSourceToObj(ctx, subdir, srcFiles, noTidySrcs, timeoutTidySrcs, flags, pathDeps, cFlagsDeps,
+ sharedFlags)
}
// Properties for rust_bindgen related to generating rust bindings.
diff --git a/cc/config/OWNERS b/cc/config/OWNERS
index c78b6d5..2668fdd 100644
--- a/cc/config/OWNERS
+++ b/cc/config/OWNERS
@@ -1,3 +1,2 @@
per-file vndk.go = smoreland@google.com, victoryang@google.com
-per-file clang.go,global.go,tidy.go = appujee@google.com, pirama@google.com, srhines@google.com, yabinc@google.com, yikong@google.com, zijunzhao@google.com
-
+per-file clang.go,global.go,tidy.go = appujee@google.com, pirama@google.com, srhines@google.com, yabinc@google.com, yikong@google.com, rprichard@google.com, sharjeelkhan@google.com
\ No newline at end of file
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 0dcf2cf..25edb79 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -44,7 +44,7 @@
// On ARMv9 and later, Pointer Authentication Codes (PAC) are mandatory,
// so -fstack-protector is unnecessary.
"armv9-a": []string{
- "-march=armv8.2-a+dotprod",
+ "-march=armv9-a",
"-mbranch-protection=standard",
"-fno-stack-protector",
},
@@ -53,6 +53,16 @@
"-mbranch-protection=standard",
"-fno-stack-protector",
},
+ "armv9-3a": []string{
+ "-march=armv9.3-a",
+ "-mbranch-protection=standard",
+ "-fno-stack-protector",
+ },
+ "armv9-4a": []string{
+ "-march=armv9.4-a",
+ "-mbranch-protection=standard",
+ "-fno-stack-protector",
+ },
}
arm64Ldflags = []string{
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 1783f49..716965a 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -54,6 +54,7 @@
"12",
"13",
"14",
+ "15",
}
darwinAvailableLibraries = append(
diff --git a/cc/config/global.go b/cc/config/global.go
index b19682d..e81ac0d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -290,11 +290,8 @@
// New warnings to be fixed after clang-r468909
"-Wno-error=deprecated-builtins", // http://b/241601211
"-Wno-error=deprecated", // in external/googletest/googletest
- // Disabling until the warning is fixed in libc++abi header files b/366180429
- "-Wno-deprecated-dynamic-exception-spec",
// New warnings to be fixed after clang-r522817
"-Wno-error=invalid-offsetof",
- "-Wno-error=thread-safety-reference-return",
// Allow using VLA CXX extension.
"-Wno-vla-cxx-extension",
@@ -366,8 +363,6 @@
"-Wno-array-parameter",
"-Wno-gnu-offsetof-extensions",
"-Wno-pessimizing-move",
- // TODO: Enable this warning http://b/315245071
- "-Wno-fortify-source",
}
llvmNextExtraCommonGlobalCflags = []string{
@@ -378,17 +373,20 @@
// Flags that must not appear in any command line.
IllegalFlags = []string{
"-w",
+ "-pedantic",
+ "-pedantic-errors",
+ "-Werror=pedantic",
}
- CStdVersion = "gnu17"
+ CStdVersion = "gnu23"
CppStdVersion = "gnu++20"
ExperimentalCStdVersion = "gnu2x"
ExperimentalCppStdVersion = "gnu++2b"
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r536225"
- ClangDefaultShortVersion = "19"
+ ClangDefaultVersion = "clang-r547379"
+ ClangDefaultShortVersion = "20"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index ddc86c2..d2f88ef 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -28,7 +28,7 @@
"-fno-omit-frame-pointer",
"-U_FORTIFY_SOURCE",
- "-D_FORTIFY_SOURCE=2",
+ "-D_FORTIFY_SOURCE=3",
"-fstack-protector-strong",
// From x86_64_device
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 287967c..c3f25aa 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -29,7 +29,7 @@
"-fno-omit-frame-pointer",
"-U_FORTIFY_SOURCE",
- "-D_FORTIFY_SOURCE=2",
+ "-D_FORTIFY_SOURCE=3",
"-fstack-protector",
"--gcc-toolchain=${LinuxGccRoot}",
@@ -41,7 +41,6 @@
}
linuxMuslCflags = []string{
- "-D_LIBCPP_HAS_MUSL_LIBC",
"-DANDROID_HOST_MUSL",
"-nostdlibinc",
"--sysroot /dev/null",
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index a4d43b9..505ddfa 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -106,10 +106,13 @@
}
windowsAvailableLibraries = addPrefix([]string{
+ "bcrypt",
+ "dbghelp",
"gdi32",
"imagehlp",
"iphlpapi",
"netapi32",
+ "ntdll",
"oleaut32",
"ole32",
"opengl32",
diff --git a/cc/coverage.go b/cc/coverage.go
index a7618dd..757641c 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -145,7 +145,7 @@
// Even if we don't have coverage enabled, if any of our object files were compiled
// with coverage, then we need to add --coverage to our ldflags.
if !cov.linkCoverage {
- if ctx.static() && !ctx.staticBinary() {
+ if ctx.staticLibrary() {
// For static libraries, the only thing that changes our object files
// are included whole static libraries, so check to see if any of
// those have coverage enabled.
@@ -273,8 +273,6 @@
type coverageTransitionMutator struct{}
-var _ android.TransitionMutator = (*coverageTransitionMutator)(nil)
-
func (c coverageTransitionMutator) Split(ctx android.BaseModuleContext) []string {
if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
if c.coverage.Properties.NeedCoverageVariant {
@@ -354,10 +352,10 @@
}
}
-func parseSymbolFileForAPICoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
+func ParseSymbolFileForAPICoverage(ctx android.ModuleContext, symbolFile string) android.ModuleOutPath {
apiLevelsJson := android.GetApiLevelsJson(ctx)
symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
- outputFile := ctx.baseModuleName() + ".xml"
+ outputFile := ctx.Module().(LinkableInterface).BaseModuleName() + ".xml"
parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFile)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go
index 1a33957..c79ea10 100644
--- a/cc/fdo_profile.go
+++ b/cc/fdo_profile.go
@@ -17,6 +17,8 @@
import (
"android/soong/android"
"github.com/google/blueprint"
+
+ "github.com/google/blueprint/proptools"
)
func init() {
@@ -34,7 +36,7 @@
}
type fdoProfileProperties struct {
- Profile *string `android:"arch_variant"`
+ Profile proptools.Configurable[string] `android:"arch_variant,replace_instead_of_append"`
}
// FdoProfileInfo is provided by FdoProfileProvider
@@ -47,8 +49,9 @@
// GenerateAndroidBuildActions of fdo_profile does not have any build actions
func (fp *fdoProfile) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if fp.properties.Profile != nil {
- path := android.PathForModuleSrc(ctx, *fp.properties.Profile)
+ profile := fp.properties.Profile.GetOrDefault(ctx, "")
+ if profile != "" {
+ path := android.PathForModuleSrc(ctx, profile)
android.SetProvider(ctx, FdoProfileProvider, FdoProfileInfo{
Path: path,
})
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 8a974c0..79874fc 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -211,29 +211,30 @@
moduleInfoJSON.Class = []string{"EXECUTABLES"}
}
-// IsValidSharedDependency takes a module and determines if it is a unique shared library
+// isValidSharedDependency takes a module and determines if it is a unique shared library
// that should be installed in the fuzz target output directories. This function
// returns true, unless:
// - The module is not an installable shared library, or
// - The module is a header or stub, or
// - The module is a prebuilt and its source is available, or
// - The module is a versioned member of an SDK snapshot.
-func IsValidSharedDependency(dependency android.Module) bool {
+func isValidSharedDependency(ctx android.ModuleContext, dependency android.ModuleProxy) bool {
// TODO(b/144090547): We should be parsing these modules using
// ModuleDependencyTag instead of the current brute-force checking.
- linkable, ok := dependency.(LinkableInterface)
- if !ok || !linkable.CcLibraryInterface() {
+ linkable, ok := android.OtherModuleProvider(ctx, dependency, LinkableInfoProvider)
+ if !ok || !linkable.CcLibraryInterface {
// Discard non-linkables.
return false
}
- if !linkable.Shared() {
+ if !linkable.Shared {
// Discard static libs.
return false
}
- if lib := moduleLibraryInterface(dependency); lib != nil && lib.buildStubs() && linkable.CcLibrary() {
+ ccInfo, hasCcInfo := android.OtherModuleProvider(ctx, dependency, CcInfoProvider)
+ if hasCcInfo && ccInfo.LibraryInfo != nil && ccInfo.LibraryInfo.BuildStubs && linkable.CcLibrary {
// Discard stubs libs (only CCLibrary variants). Prebuilt libraries should not
// be excluded on the basis of they're not CCLibrary()'s.
return false
@@ -242,13 +243,13 @@
// We discarded module stubs libraries above, but the LLNDK prebuilts stubs
// libraries must be handled differently - by looking for the stubDecorator.
// Discard LLNDK prebuilts stubs as well.
- if ccLibrary, isCcLibrary := dependency.(*Module); isCcLibrary {
- if _, isLLndkStubLibrary := ccLibrary.linker.(*stubDecorator); isLLndkStubLibrary {
+ if hasCcInfo {
+ if ccInfo.LinkerInfo != nil && ccInfo.LinkerInfo.StubDecoratorInfo != nil {
return false
}
// Discard installable:false libraries because they are expected to be absent
// in runtime.
- if !proptools.BoolDefault(ccLibrary.Installable(), true) {
+ if !proptools.BoolDefault(linkable.Installable, true) {
return false
}
}
@@ -256,7 +257,7 @@
// If the same library is present both as source and a prebuilt we must pick
// only one to avoid a conflict. Always prefer the source since the prebuilt
// probably won't be built with sanitizers enabled.
- if prebuilt := android.GetEmbeddedPrebuilt(dependency); prebuilt != nil && prebuilt.SourceExists() {
+ if prebuilt, ok := android.OtherModuleProvider(ctx, dependency, android.PrebuiltModuleInfoProvider); ok && prebuilt.SourceExists {
return false
}
@@ -288,7 +289,7 @@
}
func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
- fuzzBin.fuzzPackagedModule = PackageFuzzModule(ctx, fuzzBin.fuzzPackagedModule, pctx)
+ fuzzBin.fuzzPackagedModule = PackageFuzzModule(ctx, fuzzBin.fuzzPackagedModule)
installBase := "fuzz"
@@ -345,11 +346,14 @@
fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
}
-func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule, pctx android.PackageContext) fuzz.FuzzPackagedModule {
+func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule) fuzz.FuzzPackagedModule {
fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Corpus)
fuzzPackagedModule.Corpus = append(fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
+ fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_data)...)
+ fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_first_data)...)
+ fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Host_common_data)...)
if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
@@ -466,43 +470,37 @@
// multiple fuzzers that depend on the same shared library.
sharedLibraryInstalled := make(map[string]bool)
- ctx.VisitAllModules(func(module android.Module) {
- ccModule, ok := module.(LinkableInterface)
- if !ok || ccModule.PreventInstall() {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ ccModule, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider)
+ if !ok {
return
}
// Discard non-fuzz targets.
- if ok := fuzz.IsValid(ctx, ccModule.FuzzModuleStruct()); !ok {
+ fuzzInfo, ok := android.OtherModuleProvider(ctx, module, fuzz.FuzzPackagedModuleInfoProvider)
+ if !ok {
return
}
sharedLibsInstallDirPrefix := "lib"
- if ccModule.InVendor() {
+ if ccModule.InVendor {
sharedLibsInstallDirPrefix = "lib/vendor"
}
- if !ccModule.IsFuzzModule() {
- return
- }
-
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ isHost := commonInfo.Target.Os.Class == android.Host
hostOrTargetString := "target"
- if ccModule.Target().HostCross {
+ if commonInfo.Target.HostCross {
hostOrTargetString = "host_cross"
- } else if ccModule.Host() {
+ } else if isHost {
hostOrTargetString = "host"
}
if s.onlyIncludePresubmits == true {
hostOrTargetString = "presubmit-" + hostOrTargetString
}
- fpm := fuzz.FuzzPackagedModule{}
- if ok {
- fpm = ccModule.FuzzPackagedModule()
- }
-
intermediatePath := "fuzz"
- archString := ccModule.Target().Arch.ArchType.String()
+ archString := commonInfo.Target.Arch.ArchType.String()
archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
@@ -510,23 +508,24 @@
builder := android.NewRuleBuilder(pctx, ctx)
// Package the corpus, data, dict and config into a zipfile.
- files = s.PackageArtifacts(ctx, module, fpm, archDir, builder)
+ files = s.PackageArtifacts(ctx, module, &fuzzInfo, archDir, builder)
// Package shared libraries
- files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries(), ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
+ files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries, isHost, ccModule.InVendor, &s.FuzzPackager,
+ archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
// The executable.
- files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, ccModule, "unstripped")})
+ files = append(files, fuzz.FileToZip{SourceFilePath: android.OutputFileForModule(ctx, module, "unstripped")})
if s.onlyIncludePresubmits == true {
- if fpm.FuzzProperties.Fuzz_config == nil {
+ if fuzzInfo.FuzzConfig == nil {
return
}
- if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false) {
+ if !fuzzInfo.FuzzConfig.UseForPresubmit {
return
}
}
- archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
+ archDirs[archOs], ok = s.BuildZipFile(ctx, module, &fuzzInfo, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
return
}
@@ -555,7 +554,8 @@
// GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for
// packaging.
-func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, module LinkableInterface, s *fuzz.FuzzPackager, archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
+func GetSharedLibsToZip(sharedLibraries android.RuleBuilderInstalls, isHost bool, inVendor bool, s *fuzz.FuzzPackager,
+ archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
var files []fuzz.FileToZip
fuzzDir := "fuzz"
@@ -573,7 +573,7 @@
// install it to the output directory. Setup the install destination here,
// which will be used by $(copy-many-files) in the Make backend.
installDestination := SharedLibraryInstallLocation(
- install, module.Host(), module.InVendor(), fuzzDir, archString)
+ install, isHost, inVendor, fuzzDir, archString)
if (*sharedLibraryInstalled)[installDestination] {
continue
}
@@ -590,8 +590,8 @@
// dir. Symbolized DSO's are always installed to the device when fuzzing, but
// we want symbolization tools (like `stack`) to be able to find the symbols
// in $ANDROID_PRODUCT_OUT/symbols automagically.
- if !module.Host() {
- symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, module.InVendor(), fuzzDir, archString)
+ if !isHost {
+ symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, inVendor, fuzzDir, archString)
symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
library.String()+":"+symbolsInstallDestination)
@@ -605,17 +605,17 @@
// VisitDirectDeps is used first to avoid incorrectly using the core libraries (sanitizer
// runtimes, libc, libdl, etc.) from a dependency. This may cause issues when dependencies
// have explicit sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
-func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilderInstalls, []android.Module) {
+func CollectAllSharedDependencies(ctx android.ModuleContext) (android.RuleBuilderInstalls, []android.ModuleProxy) {
seen := make(map[string]bool)
recursed := make(map[string]bool)
- deps := []android.Module{}
+ deps := []android.ModuleProxy{}
var sharedLibraries android.RuleBuilderInstalls
// Enumerate the first level of dependencies, as we discard all non-library
// modules in the BFS loop below.
- ctx.VisitDirectDeps(func(dep android.Module) {
- if !IsValidSharedDependency(dep) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
+ if !isValidSharedDependency(ctx, dep) {
return
}
sharedLibraryInfo, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, SharedLibraryInfoProvider)
@@ -633,19 +633,21 @@
sharedLibraries = append(sharedLibraries, ruleBuilderInstall)
})
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool {
// If this is a Rust module which is not rust_ffi_shared, we still want to bundle any transitive
- // shared dependencies (even for rust_ffi_rlib or rust_ffi_static)
- if rustmod, ok := child.(LinkableInterface); ok && rustmod.RustLibraryInterface() && !rustmod.Shared() {
- if recursed[ctx.OtherModuleName(child)] {
- return false
+ // shared dependencies (even for rust_ffi_static)
+ if info, ok := android.OtherModuleProvider(ctx, child, LinkableInfoProvider); ok {
+ if info.RustLibraryInterface && !info.Shared {
+ if recursed[ctx.OtherModuleName(child)] {
+ return false
+ }
+ recursed[ctx.OtherModuleName(child)] = true
+ return true
}
- recursed[ctx.OtherModuleName(child)] = true
- return true
}
- if !IsValidSharedDependency(child) {
+ if !isValidSharedDependency(ctx, child) {
return false
}
sharedLibraryInfo, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, child, SharedLibraryInfoProvider)
diff --git a/cc/gen_test.go b/cc/gen_test.go
index 439f0a9..dde0dcf 100644
--- a/cc/gen_test.go
+++ b/cc/gen_test.go
@@ -33,8 +33,8 @@
],
}`)
- aidl := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("aidl")
- libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
+ aidl := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("aidl")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
expected := "-I" + filepath.Dir(aidl.Output.String())
actual := android.StringsRelativeToTop(ctx.Config(), libfoo.flags.Local.CommonFlags)
@@ -59,9 +59,9 @@
],
}`)
- aidl := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("aidl")
- aidlManifest := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Output("aidl.sbox.textproto")
- libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
+ aidl := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("aidl")
+ aidlManifest := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Output("aidl.sbox.textproto")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
if !inList("-I"+filepath.Dir(aidl.Output.String()), android.StringsRelativeToTop(ctx.Config(), libfoo.flags.Local.CommonFlags)) {
t.Errorf("missing aidl includes in global flags")
@@ -84,7 +84,7 @@
}`)
outDir := "out/soong/.intermediates/libsysprop/android_arm64_armv8-a_static/gen"
- syspropBuildParams := ctx.ModuleForTests("libsysprop", "android_arm64_armv8-a_static").Rule("sysprop")
+ syspropBuildParams := ctx.ModuleForTests(t, "libsysprop", "android_arm64_armv8-a_static").Rule("sysprop")
android.AssertStringEquals(t, "header output directory does not match", outDir+"/sysprop/include/path/to", syspropBuildParams.Args["headerOutDir"])
android.AssertStringEquals(t, "public output directory does not match", outDir+"/sysprop/public/include/path/to", syspropBuildParams.Args["publicOutDir"])
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index 9a8049b..4e700a2 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -17,6 +17,7 @@
import (
"reflect"
"slices"
+ "strings"
"testing"
"android/soong/android"
@@ -64,13 +65,13 @@
t.Fatal(errs)
}
- gen := ctx.ModuleForTests("gen", "android_arm_armv7-a-neon").Output("out_arm")
+ gen := ctx.ModuleForTests(t, "gen", "android_arm_armv7-a-neon").Output("out_arm")
expected := []string{"foo"}
if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
}
- gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm")
+ gen = ctx.ModuleForTests(t, "gen", "android_arm64_armv8-a").Output("out_arm")
expected = []string{"bar"}
if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Implicits.Strings())
@@ -105,7 +106,7 @@
`
ctx := testCc(t, bp)
- gen := ctx.ModuleForTests("gen", "android_arm_armv7-a-neon").Output("out")
+ gen := ctx.ModuleForTests(t, "gen", "android_arm_armv7-a-neon").Output("out")
expected := []string{"libboth.so", "libshared.so", "libstatic.a"}
var got []string
for _, input := range gen.Implicits {
@@ -178,7 +179,7 @@
PrepareForIntegrationTestWithCc,
android.OptionalFixturePreparer(tt.preparer),
).RunTestWithBp(t, bp)
- gen := result.ModuleForTests("gen", tt.variant)
+ gen := result.ModuleForTests(t, "gen", tt.variant)
sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
cmd := *sboxProto.Commands[0].Command
android.AssertStringDoesContain(t, "incorrect CC_ARCH", cmd, "CC_ARCH="+tt.arch+" ")
@@ -236,7 +237,7 @@
}
`
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
- gen_32bit := result.ModuleForTests("gen", "android_arm_armv7-a-neon").OutputFiles(result.TestContext, t, "")
+ gen_32bit := result.ModuleForTests(t, "gen", "android_arm_armv7-a-neon").OutputFiles(result.TestContext, t, "")
android.AssertPathsEndWith(t,
"genrule_out",
[]string{
@@ -245,7 +246,7 @@
gen_32bit,
)
- gen_64bit := result.ModuleForTests("gen", "android_arm64_armv8-a").OutputFiles(result.TestContext, t, "")
+ gen_64bit := result.ModuleForTests(t, "gen", "android_arm64_armv8-a").OutputFiles(result.TestContext, t, "")
android.AssertPathsEndWith(t,
"genrule_out",
[]string{
@@ -254,3 +255,42 @@
gen_64bit,
)
}
+
+// Test that a genrule can depend on a tool with symlinks. The symlinks are ignored, but
+// at least it doesn't cause errors.
+func TestGenruleToolWithSymlinks(t *testing.T) {
+ bp := `
+ genrule {
+ name: "gen",
+ tools: ["tool_with_symlinks"],
+ cmd: "$(location tool_with_symlinks) $(in) $(out)",
+ out: ["out"],
+ }
+
+ cc_binary_host {
+ name: "tool_with_symlinks",
+ symlinks: ["symlink1", "symlink2"],
+ }
+ `
+ ctx := PrepareForIntegrationTestWithCc.
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, bp)
+ gen := ctx.ModuleForTests(t, "gen", "").Output("out")
+ toolFound := false
+ symlinkFound := false
+ for _, dep := range gen.RuleParams.CommandDeps {
+ if strings.HasSuffix(dep, "/tool_with_symlinks") {
+ toolFound = true
+ }
+ if strings.HasSuffix(dep, "/symlink1") || strings.HasSuffix(dep, "/symlink2") {
+ symlinkFound = true
+ }
+ }
+ if !toolFound {
+ t.Errorf("Tool not found")
+ }
+ // We may want to change genrules to include symlinks later
+ if symlinkFound {
+ t.Errorf("Symlinks found")
+ }
+}
diff --git a/cc/installer.go b/cc/installer.go
index 30f9612..d7d8c6d 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -107,6 +107,10 @@
installer.installDeps = append(installer.installDeps, installedData...)
}
+func (installer *baseInstaller) installStandaloneTestDep(ctx ModuleContext, standaloneTestDep android.PackagingSpec) {
+ installer.installTestData(ctx, []android.DataPath{{SrcPath: standaloneTestDep.ToGob().SrcPath, RelativeInstallPath: "standalone-libs"}})
+}
+
func (installer *baseInstaller) everInstallable() bool {
// Most cc modules are installable.
return true
diff --git a/cc/library.go b/cc/library.go
index ef3ccd2..7b85486 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -25,6 +25,7 @@
"sync"
"android/soong/android"
+ "android/soong/cc/config"
"github.com/google/blueprint"
"github.com/google/blueprint/depset"
@@ -34,6 +35,8 @@
// LibraryProperties is a collection of properties shared by cc library rules/cc.
type LibraryProperties struct {
+ // local file name to pass to the linker as -exported_symbols_list
+ Exported_symbols_list *string `android:"path,arch_variant"`
// local file name to pass to the linker as -unexported_symbols_list
Unexported_symbols_list *string `android:"path,arch_variant"`
// local file name to pass to the linker as -force_symbols_not_weak_list
@@ -62,21 +65,7 @@
Static_ndk_lib *bool
// Generate stubs to make this library accessible to APEXes.
- Stubs struct {
- // Relative path to the symbol map. The symbol map provides the list of
- // symbols that are exported for stubs variant of this library.
- Symbol_file *string `android:"path,arch_variant"`
-
- // List versions to generate stubs libs for. The version name "current" is always
- // implicitly added.
- Versions []string
-
- // Whether to not require the implementation of the library to be installed if a
- // client of the stubs is installed. Defaults to true; set to false if the
- // implementation is made available by some other means, e.g. in a Microdroid
- // virtual machine.
- Implementation_installable *bool
- } `android:"arch_variant"`
+ Stubs StubsProperties `android:"arch_variant"`
// set the name of the output
Stem *string `android:"arch_variant"`
@@ -125,6 +114,22 @@
Vendor_public_library vendorPublicLibraryProperties
}
+type StubsProperties struct {
+ // Relative path to the symbol map. The symbol map provides the list of
+ // symbols that are exported for stubs variant of this library.
+ Symbol_file *string `android:"path,arch_variant"`
+
+ // List versions to generate stubs libs for. The version name "current" is always
+ // implicitly added.
+ Versions []string
+
+ // Whether to not require the implementation of the library to be installed if a
+ // client of the stubs is installed. Defaults to true; set to false if the
+ // implementation is made available by some other means, e.g. in a Microdroid
+ // virtual machine.
+ Implementation_installable *bool
+}
+
// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a
// library module.
type StaticProperties struct {
@@ -218,6 +223,7 @@
func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_library_static", LibraryStaticFactory)
+ ctx.RegisterModuleType("cc_rustlibs_for_make", LibraryMakeRustlibsFactory)
ctx.RegisterModuleType("cc_library_shared", LibrarySharedFactory)
ctx.RegisterModuleType("cc_library", LibraryFactory)
ctx.RegisterModuleType("cc_library_host_static", LibraryHostStaticFactory)
@@ -247,6 +253,19 @@
return module.Init()
}
+// cc_rustlibs_for_make creates a static library which bundles together rust_ffi_static
+// deps for Make. This should not be depended on in Soong, and is probably not the
+// module you need unless you are sure of what you're doing. These should only
+// be declared as dependencies in Make. To ensure inclusion, rust_ffi_static modules
+// should be declared in the whole_static_libs property.
+func LibraryMakeRustlibsFactory() android.Module {
+ module, library := NewLibrary(android.HostAndDeviceSupported)
+ library.BuildOnlyStatic()
+ library.wideStaticlibForMake = true
+ module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
+ return module.Init()
+}
+
// cc_library_shared creates a shared library for a device and/or host.
func LibrarySharedFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
@@ -421,8 +440,8 @@
// Location of the linked, stripped library for shared libraries, strip: "all"
strippedAllOutputFile android.Path
- // Location of the file that should be copied to dist dir when requested
- distFile android.Path
+ // Location of the file that should be copied to dist dir when no explicit tag is requested
+ defaultDistFile android.Path
versionScriptPath android.OptionalPath
@@ -439,6 +458,10 @@
// Path to the file containing the APIs exported by this library
stubsSymbolFilePath android.Path
+
+ // Forces production of the generated Rust staticlib for cc_library_static.
+ // Intended to be used to provide these generated staticlibs for Make.
+ wideStaticlibForMake bool
}
// linkerProps returns the list of properties structs relevant for this library. (For example, if
@@ -462,11 +485,15 @@
return props
}
-// linkerFlags takes a Flags struct and augments it to contain linker flags that are defined by this
-// library, or that are implied by attributes of this library (such as whether this library is a
-// shared library).
-func (library *libraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- flags = library.baseLinker.linkerFlags(ctx, flags)
+func CommonLibraryLinkerFlags(ctx android.ModuleContext, flags Flags,
+ toolchain config.Toolchain, libName string) Flags {
+
+ mod, ok := ctx.Module().(LinkableInterface)
+
+ if !ok {
+ ctx.ModuleErrorf("trying to add linker flags to a non-LinkableInterface module.")
+ return flags
+ }
// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
// all code is position independent, and then those warnings get promoted to
@@ -474,27 +501,18 @@
if !ctx.Windows() {
flags.Global.CFlags = append(flags.Global.CFlags, "-fPIC")
}
-
- if library.static() {
- flags.Local.CFlags = append(flags.Local.CFlags, library.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)...)
- } else if library.shared() {
- flags.Local.CFlags = append(flags.Local.CFlags, library.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)...)
- }
-
- if library.shared() {
- libName := library.getLibName(ctx)
+ if mod.Shared() {
var f []string
- if ctx.toolchain().Bionic() {
+ if toolchain.Bionic() {
f = append(f,
"-nostdlib",
"-Wl,--gc-sections",
)
}
-
if ctx.Darwin() {
f = append(f,
"-dynamiclib",
- "-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
+ "-install_name @rpath/"+libName+toolchain.ShlibSuffix(),
)
if ctx.Arch().ArchType == android.X86 {
f = append(f,
@@ -504,16 +522,30 @@
} else {
f = append(f, "-shared")
if !ctx.Windows() {
- f = append(f, "-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix())
+ f = append(f, "-Wl,-soname,"+libName+toolchain.ShlibSuffix())
}
}
-
flags.Global.LdFlags = append(flags.Global.LdFlags, f...)
}
return flags
}
+// linkerFlags takes a Flags struct and augments it to contain linker flags that are defined by this
+// library, or that are implied by attributes of this library (such as whether this library is a
+// shared library).
+func (library *libraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ flags = library.baseLinker.linkerFlags(ctx, flags)
+ flags = CommonLibraryLinkerFlags(ctx, flags, ctx.toolchain(), library.getLibName(ctx))
+ if library.static() {
+ flags.Local.CFlags = append(flags.Local.CFlags, library.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)...)
+ } else if library.shared() {
+ flags.Local.CFlags = append(flags.Local.CFlags, library.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)...)
+ }
+
+ return flags
+}
+
// compilerFlags takes a Flags and augments it to contain compile flags from global values,
// per-target values, module type values, per-module Blueprints properties, extra flags from
// `flags`, and generated sources from `deps`.
@@ -532,7 +564,7 @@
// Wipe all the module-local properties, leaving only the global properties.
flags.Local = LocalOrGlobalFlags{}
}
- if library.buildStubs() {
+ if library.BuildStubs() {
// Remove -include <file> when compiling stubs. Otherwise, the force included
// headers might cause conflicting types error with the symbols in the
// generated stubs source code. e.g.
@@ -551,7 +583,7 @@
flags.Local.CommonFlags = removeInclude(flags.Local.CommonFlags)
flags.Local.CFlags = removeInclude(flags.Local.CFlags)
- flags = addStubLibraryCompilerFlags(flags)
+ flags = AddStubLibraryCompilerFlags(flags)
}
return flags
}
@@ -572,6 +604,8 @@
}
func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
+ sharedFlags := ctx.getSharedFlags()
+
if ctx.IsLlndk() {
// Get the matching SDK version for the vendor API level.
version, err := android.GetSdkVersionForVendorApiLevel(ctx.Config().VendorApiLevel())
@@ -579,28 +613,40 @@
panic(err)
}
+ llndkFlag := "--llndk"
+ if ctx.baseModuleName() == "libbinder_ndk" && ctx.inProduct() {
+ // This is a special case only for the libbinder_ndk. As the product partition is in the
+ // framework side along with system and system_ext partitions in Treble, libbinder_ndk
+ // provides different binder interfaces between product and vendor modules.
+ // In libbinder_ndk, 'llndk' annotation is for the vendor APIs; while 'systemapi'
+ // annotation is for the product APIs.
+ // Use '--systemapi' flag for building the llndk stub of product variant for the
+ // libbinder_ndk.
+ llndkFlag = "--systemapi"
+ }
+
// This is the vendor variant of an LLNDK library, build the LLNDK stubs.
- nativeAbiResult := parseNativeAbiDefinition(ctx,
+ nativeAbiResult := ParseNativeAbiDefinition(ctx,
String(library.Properties.Llndk.Symbol_file),
- nativeClampedApiLevel(ctx, version), "--llndk")
- objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
+ nativeClampedApiLevel(ctx, version), llndkFlag)
+ objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, sharedFlags)
if !Bool(library.Properties.Llndk.Unversioned) {
library.versionScriptPath = android.OptionalPathForPath(
- nativeAbiResult.versionScript)
+ nativeAbiResult.VersionScript)
}
return objs
}
if ctx.IsVendorPublicLibrary() {
- nativeAbiResult := parseNativeAbiDefinition(ctx,
+ nativeAbiResult := ParseNativeAbiDefinition(ctx,
String(library.Properties.Vendor_public_library.Symbol_file),
android.FutureApiLevel, "")
- objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
+ objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, sharedFlags)
if !Bool(library.Properties.Vendor_public_library.Unversioned) {
- library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.versionScript)
+ library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.VersionScript)
}
return objs
}
- if library.buildStubs() {
+ if library.BuildStubs() {
return library.compileModuleLibApiStubs(ctx, flags, deps)
}
@@ -621,10 +667,17 @@
}
if library.sabi.shouldCreateSourceAbiDump() {
dirs := library.exportedIncludeDirsForAbiCheck(ctx)
- flags.SAbiFlags = make([]string, 0, len(dirs))
+ flags.SAbiFlags = make([]string, 0, len(dirs)+1)
for _, dir := range dirs {
flags.SAbiFlags = append(flags.SAbiFlags, "-I"+dir)
}
+ // If this library does not export any include directory, do not append the flags
+ // so that the ABI tool dumps everything without filtering by the include directories.
+ // requiresGlobalIncludes returns whether this library can include CommonGlobalIncludes.
+ // If the library cannot include them, it cannot export them.
+ if len(dirs) > 0 && requiresGlobalIncludes(ctx) {
+ flags.SAbiFlags = append(flags.SAbiFlags, "${config.CommonGlobalIncludes}")
+ }
totalLength := len(srcs) + len(deps.GeneratedSources) +
len(sharedSrcs) + len(staticSrcs)
if totalLength > 0 {
@@ -640,18 +693,65 @@
objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceStaticLibrary, srcs,
android.PathsForModuleSrc(ctx, library.StaticProperties.Static.Tidy_disabled_srcs),
android.PathsForModuleSrc(ctx, library.StaticProperties.Static.Tidy_timeout_srcs),
- library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
+ library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps, sharedFlags))
} else if library.shared() {
srcs := android.PathsForModuleSrc(ctx, sharedSrcs)
objs = objs.Append(compileObjs(ctx, buildFlags, android.DeviceSharedLibrary, srcs,
android.PathsForModuleSrc(ctx, library.SharedProperties.Shared.Tidy_disabled_srcs),
android.PathsForModuleSrc(ctx, library.SharedProperties.Shared.Tidy_timeout_srcs),
- library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps))
+ library.baseCompiler.pathDeps, library.baseCompiler.cFlagsDeps, sharedFlags))
}
return objs
}
+type ApiStubsParams struct {
+ NotInPlatform bool
+ IsNdk bool
+ BaseModuleName string
+ ModuleName string
+}
+
+// GetApiStubsFlags calculates the genstubFlags string to pass to ParseNativeAbiDefinition
+func GetApiStubsFlags(api ApiStubsParams) string {
+ var flag string
+
+ // b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
+ // systemapi, respectively. The former is for symbols defined in platform libraries
+ // and the latter is for symbols defined in APEXes.
+ // A single library can contain either # apex or # systemapi, but not both.
+ // The stub generator (ndkstubgen) is additive, so passing _both_ of these to it should be a no-op.
+ // However, having this distinction helps guard accidental
+ // promotion or demotion of API and also helps the API review process b/191371676
+ if api.NotInPlatform {
+ flag = "--apex"
+ } else {
+ flag = "--systemapi"
+ }
+
+ // b/184712170, unless the lib is an NDK library, exclude all public symbols from
+ // the stub so that it is mandated that all symbols are explicitly marked with
+ // either apex or systemapi.
+ if !api.IsNdk &&
+ // the symbol files of libclang libs are autogenerated and do not contain systemapi tags
+ // TODO (spandandas): Update mapfile.py to include #systemapi tag on all symbols
+ !strings.Contains(api.ModuleName, "libclang_rt") {
+ flag = flag + " --no-ndk"
+ }
+
+ // TODO(b/361303067): Remove this special case if bionic/ projects are added to ART development branches.
+ if isBionic(api.BaseModuleName) {
+ // set the flags explicitly for bionic libs.
+ // this is necessary for development in minimal branches which does not contain bionic/*.
+ // In such minimal branches, e.g. on the prebuilt libc stubs
+ // 1. IsNdk will return false (since the ndk_library definition for libc does not exist)
+ // 2. NotInPlatform will return true (since the source com.android.runtime does not exist)
+ flag = "--apex"
+ }
+
+ return flag
+}
+
// Compile stubs for the API surface between platform and apex
// This method will be used by source and prebuilt cc module types.
func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
@@ -659,56 +759,34 @@
if library.Properties.Stubs.Symbol_file == nil {
return Objects{}
}
+
symbolFile := String(library.Properties.Stubs.Symbol_file)
library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile)
- // b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
- // systemapi, respectively. The former is for symbols defined in platform libraries
- // and the latter is for symbols defined in APEXes.
- // A single library can contain either # apex or # systemapi, but not both.
- // The stub generator (ndkstubgen) is additive, so passing _both_ of these to it should be a no-op.
- // However, having this distinction helps guard accidental
- // promotion or demotion of API and also helps the API review process b/191371676
- var flag string
- if ctx.notInPlatform() {
- flag = "--apex"
- } else {
- flag = "--systemapi"
+
+ apiParams := ApiStubsParams{
+ NotInPlatform: ctx.notInPlatform(),
+ IsNdk: ctx.Module().(*Module).IsNdk(ctx.Config()),
+ BaseModuleName: ctx.baseModuleName(),
+ ModuleName: ctx.ModuleName(),
}
- // b/184712170, unless the lib is an NDK library, exclude all public symbols from
- // the stub so that it is mandated that all symbols are explicitly marked with
- // either apex or systemapi.
- if !ctx.Module().(*Module).IsNdk(ctx.Config()) &&
- // the symbol files of libclang libs are autogenerated and do not contain systemapi tags
- // TODO (spandandas): Update mapfile.py to include #systemapi tag on all symbols
- !strings.Contains(ctx.ModuleName(), "libclang_rt") {
- flag = flag + " --no-ndk"
- }
- // TODO(b/361303067): Remove this special case if bionic/ projects are added to ART development branches.
- if isBionic(ctx.baseModuleName()) {
- // set the flags explicitly for bionic libs.
- // this is necessary for development in minimal branches which does not contain bionic/*.
- // In such minimal branches, e.g. on the prebuilt libc stubs
- // 1. IsNdk will return false (since the ndk_library definition for libc does not exist)
- // 2. NotInPlatform will return true (since the source com.android.runtime does not exist)
- flag = "--apex"
- }
- nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
+ flag := GetApiStubsFlags(apiParams)
+
+ nativeAbiResult := ParseNativeAbiDefinition(ctx, symbolFile,
android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
- objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
+ objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, ctx.getSharedFlags())
library.versionScriptPath = android.OptionalPathForPath(
- nativeAbiResult.versionScript)
-
+ nativeAbiResult.VersionScript)
// Parse symbol file to get API list for coverage
- if library.stubsVersion() == "current" && ctx.PrimaryArch() && !ctx.inRecovery() && !ctx.inProduct() && !ctx.inVendor() {
- library.apiListCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
+ if library.StubsVersion() == "current" && ctx.PrimaryArch() && !ctx.inRecovery() && !ctx.inProduct() && !ctx.inVendor() {
+ library.apiListCoverageXmlPath = ParseSymbolFileForAPICoverage(ctx, symbolFile)
}
return objs
}
type libraryInterface interface {
- versionedInterface
+ VersionedInterface
static() bool
shared() bool
@@ -730,34 +808,51 @@
// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
- availableFor(string) bool
+ apexAvailable() []string
- getAPIListCoverageXMLPath() android.ModuleOutPath
+ setAPIListCoverageXMLPath(out android.ModuleOutPath)
+ symbolsFile() *string
+ setSymbolFilePath(path android.Path)
+ setVersionScriptPath(path android.OptionalPath)
installable() *bool
}
-type versionedInterface interface {
- buildStubs() bool
- setBuildStubs(isLatest bool)
- hasStubsVariants() bool
- isStubsImplementationRequired() bool
- setStubsVersion(string)
- stubsVersion() string
+func (library *libraryDecorator) symbolsFile() *string {
+ return library.Properties.Stubs.Symbol_file
+}
- stubsVersions(ctx android.BaseModuleContext) []string
- setAllStubsVersions([]string)
- allStubsVersions() []string
+func (library *libraryDecorator) setSymbolFilePath(path android.Path) {
+ library.stubsSymbolFilePath = path
+}
- implementationModuleName(name string) string
- hasLLNDKStubs() bool
- hasLLNDKHeaders() bool
- hasVendorPublicLibrary() bool
- isLLNDKMovedToApex() bool
+func (library *libraryDecorator) setVersionScriptPath(path android.OptionalPath) {
+ library.versionScriptPath = path
+}
+
+type VersionedInterface interface {
+ BuildStubs() bool
+ SetBuildStubs(isLatest bool)
+ HasStubsVariants() bool
+ IsStubsImplementationRequired() bool
+ SetStubsVersion(string)
+ StubsVersion() string
+
+ StubsVersions(ctx android.BaseModuleContext) []string
+ SetAllStubsVersions([]string)
+ AllStubsVersions() []string
+
+ ImplementationModuleName(name string) string
+ HasLLNDKStubs() bool
+ HasLLNDKHeaders() bool
+ HasVendorPublicLibrary() bool
+ IsLLNDKMovedToApex() bool
+
+ GetAPIListCoverageXMLPath() android.ModuleOutPath
}
var _ libraryInterface = (*libraryDecorator)(nil)
-var _ versionedInterface = (*libraryDecorator)(nil)
+var _ VersionedInterface = (*libraryDecorator)(nil)
func (library *libraryDecorator) getLibNameHelper(baseModuleName string, inVendor bool, inProduct bool) string {
name := library.libName
@@ -806,9 +901,9 @@
library.baseLinker.linkerInit(ctx)
// Let baseLinker know whether this variant is for stubs or not, so that
// it can omit things that are not required for linking stubs.
- library.baseLinker.dynamicProperties.BuildStubs = library.buildStubs()
+ library.baseLinker.dynamicProperties.BuildStubs = library.BuildStubs()
- if library.buildStubs() {
+ if library.BuildStubs() {
macroNames := versioningMacroNamesList(ctx.Config())
myName := versioningMacroName(ctx.ModuleName())
versioningMacroNamesListMutex.Lock()
@@ -967,8 +1062,8 @@
moduleInfoJSON.Uninstallable = true
}
- if library.buildStubs() && library.stubsVersion() != "" {
- moduleInfoJSON.SubName += "." + library.stubsVersion()
+ if library.BuildStubs() && library.StubsVersion() != "" {
+ moduleInfoJSON.SubName += "." + library.StubsVersion()
}
// If a library providing a stub is included in an APEX, the private APIs of the library
@@ -979,10 +1074,10 @@
// very early stage in the boot process).
if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.notInPlatform() &&
!ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && !ctx.useVndk() && !ctx.static() {
- if library.buildStubs() && library.isLatestStubVersion() {
+ if library.BuildStubs() && library.isLatestStubVersion() {
moduleInfoJSON.SubName = ""
}
- if !library.buildStubs() {
+ if !library.BuildStubs() {
moduleInfoJSON.SubName = ".bootstrap"
}
}
@@ -990,6 +1085,10 @@
library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
}
+func (library *libraryDecorator) testSuiteInfo(ctx ModuleContext) {
+ // not a test
+}
+
func (library *libraryDecorator) linkStatic(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
@@ -997,6 +1096,16 @@
library.objects = library.objects.Append(objs)
library.wholeStaticLibsFromPrebuilts = android.CopyOfPaths(deps.WholeStaticLibsFromPrebuilts)
+ if library.wideStaticlibForMake {
+ if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil {
+ // WholeStaticLibsFromPrebuilts are .a files that get included whole into the resulting staticlib
+ // so reuse that here for our Rust staticlibs because we don't have individual object files for
+ // these.
+ deps.WholeStaticLibsFromPrebuilts = append(deps.WholeStaticLibsFromPrebuilts, generatedLib)
+ }
+
+ }
+
fileName := ctx.ModuleName() + staticLibraryExtension
outputFile := android.PathForModuleOut(ctx, fileName)
builderFlags := flagsToBuilderFlags(flags)
@@ -1008,7 +1117,7 @@
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
- library.distFile = versionedOutputFile
+ library.defaultDistFile = versionedOutputFile
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
}
}
@@ -1056,10 +1165,14 @@
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
+ exportedSymbols := ctx.ExpandOptionalSource(library.Properties.Exported_symbols_list, "exported_symbols_list")
unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list")
forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list")
forceWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_weak_list, "force_symbols_weak_list")
if !ctx.Darwin() {
+ if exportedSymbols.Valid() {
+ ctx.PropertyErrorf("exported_symbols_list", "Only supported on Darwin")
+ }
if unexportedSymbols.Valid() {
ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
}
@@ -1070,6 +1183,10 @@
ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
}
} else {
+ if exportedSymbols.Valid() {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-exported_symbols_list,"+exportedSymbols.String())
+ linkerDeps = append(linkerDeps, exportedSymbols.Path())
+ }
if unexportedSymbols.Valid() {
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
linkerDeps = append(linkerDeps, unexportedSymbols.Path())
@@ -1117,7 +1234,7 @@
stripFlags := flagsToStripFlags(flags)
needsStrip := library.stripper.NeedsStrip(ctx)
- if library.buildStubs() {
+ if library.BuildStubs() {
// No need to strip stubs libraries
needsStrip = false
}
@@ -1140,11 +1257,11 @@
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
- library.distFile = versionedOutputFile
+ library.defaultDistFile = versionedOutputFile
if library.stripper.NeedsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
- library.distFile = out
+ library.defaultDistFile = out
library.stripper.StripExecutableOrSharedLib(ctx, versionedOutputFile, out, stripFlags)
}
@@ -1171,7 +1288,7 @@
linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
- if generatedLib := generateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.buildStubs() {
+ if generatedLib := GenerateRustStaticlib(ctx, deps.RustRlibDeps); generatedLib != nil && !library.BuildStubs() {
if ctx.Module().(*Module).WholeRustStaticlib {
deps.WholeStaticLibs = append(deps.WholeStaticLibs, generatedLib)
} else {
@@ -1192,7 +1309,7 @@
library.linkSAbiDumpFiles(ctx, deps, objs, fileName, unstrippedOutputFile)
var transitiveStaticLibrariesForOrdering depset.DepSet[android.Path]
- if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 {
+ if static := ctx.GetDirectDepsProxyWithTag(staticVariantTag); len(static) > 0 {
s, _ := android.OtherModuleProvider(ctx, static[0], StaticLibraryInfoProvider)
transitiveStaticLibrariesForOrdering = s.TransitiveStaticLibrariesForOrdering
}
@@ -1202,18 +1319,18 @@
SharedLibrary: unstrippedOutputFile,
TransitiveStaticLibrariesForOrdering: transitiveStaticLibrariesForOrdering,
Target: ctx.Target(),
- IsStubs: library.buildStubs(),
+ IsStubs: library.BuildStubs(),
})
- addStubDependencyProviders(ctx)
+ AddStubDependencyProviders(ctx)
return unstrippedOutputFile
}
// Visits the stub variants of the library and returns a struct containing the stub .so paths
-func addStubDependencyProviders(ctx ModuleContext) []SharedStubLibrary {
+func AddStubDependencyProviders(ctx android.BaseModuleContext) []SharedStubLibrary {
stubsInfo := []SharedStubLibrary{}
- stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
+ stubs := ctx.GetDirectDepsProxyWithTag(StubImplDepTag)
if len(stubs) > 0 {
for _, stub := range stubs {
stubInfo, ok := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
@@ -1222,8 +1339,11 @@
continue
}
flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
+ if _, ok = android.OtherModuleProvider(ctx, stub, CcInfoProvider); !ok {
+ panic(fmt.Errorf("stub is not a cc module %s", stub))
+ }
stubsInfo = append(stubsInfo, SharedStubLibrary{
- Version: moduleLibraryInterface(stub).stubsVersion(),
+ Version: android.OtherModuleProviderOrDefault(ctx, stub, LinkableInfoProvider).StubsVersion,
SharedLibraryInfo: stubInfo,
FlagExporterInfo: flagInfo,
})
@@ -1231,10 +1351,11 @@
if len(stubsInfo) > 0 {
android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
- IsLLNDK: ctx.IsLlndk(),
+ IsLLNDK: ctx.Module().(LinkableInterface).IsLlndk(),
})
}
}
+
return stubsInfo
}
@@ -1251,7 +1372,7 @@
}
func (library *libraryDecorator) nativeCoverage() bool {
- if library.header() || library.buildStubs() {
+ if library.header() || library.BuildStubs() {
return false
}
return true
@@ -1299,13 +1420,15 @@
deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string,
excludeSymbolVersions, excludeSymbolTags []string,
sdkVersionForVendorApiLevel string) android.Path {
+ // Though LLNDK is implemented in system, the callers in vendor cannot include CommonGlobalIncludes,
+ // so commonGlobalIncludes is false.
return transformDumpToLinkedDump(ctx,
sAbiDumpFiles, soFile, libFileName+".llndk",
library.llndkIncludeDirsForAbiCheck(ctx, deps),
android.OptionalPathForModuleSrc(ctx, library.Properties.Llndk.Symbol_file),
append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
append([]string{"platform-only"}, excludeSymbolTags...),
- []string{"llndk"}, sdkVersionForVendorApiLevel)
+ []string{"llndk"}, sdkVersionForVendorApiLevel, false /* commonGlobalIncludes */)
}
func (library *libraryDecorator) linkApexSAbiDumpFiles(ctx ModuleContext,
@@ -1318,7 +1441,7 @@
android.OptionalPathForModuleSrc(ctx, library.Properties.Stubs.Symbol_file),
append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...),
append([]string{"platform-only"}, excludeSymbolTags...),
- []string{"apex", "systemapi"}, sdkVersion)
+ []string{"apex", "systemapi"}, sdkVersion, requiresGlobalIncludes(ctx))
}
func getRefAbiDumpFile(ctx android.ModuleInstallPathContext,
@@ -1380,6 +1503,11 @@
extraFlags = append(extraFlags,
"-allow-unreferenced-changes",
"-allow-unreferenced-elf-symbol-changes")
+ // The functions in standard libraries are not always declared in the headers.
+ // Allow them to be added or removed without changing the symbols.
+ if isBionic(ctx.ModuleName()) {
+ extraFlags = append(extraFlags, "-allow-adding-removing-referenced-apis")
+ }
}
if isLlndk {
extraFlags = append(extraFlags, "-consider-opaque-types-different")
@@ -1456,7 +1584,7 @@
android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
headerAbiChecker.Exclude_symbol_versions,
headerAbiChecker.Exclude_symbol_tags,
- []string{} /* includeSymbolTags */, currSdkVersion)
+ []string{} /* includeSymbolTags */, currSdkVersion, requiresGlobalIncludes(ctx))
var llndkDump, apexVariantDump android.Path
tags := classifySourceAbiDump(ctx.Module().(*Module))
@@ -1716,9 +1844,9 @@
}
func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) {
- if library.buildStubs() && library.stubsVersion() != "" && !library.skipAPIDefine {
+ if library.BuildStubs() && library.StubsVersion() != "" && !library.skipAPIDefine {
name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx))
- apiLevel, err := android.ApiLevelFromUser(ctx, library.stubsVersion())
+ apiLevel, err := android.ApiLevelFromUser(ctx, library.StubsVersion())
if err != nil {
ctx.ModuleErrorf("Can't export version macro: %s", err.Error())
}
@@ -1770,8 +1898,8 @@
func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
if library.shared() {
translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
- if library.hasStubsVariants() && !ctx.Host() && !ctx.isSdkVariant() &&
- InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.buildStubs() &&
+ if library.HasStubsVariants() && !ctx.Host() && !ctx.isSdkVariant() &&
+ InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !library.BuildStubs() &&
!translatedArch && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() {
// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
// The original path becomes a symlink to the corresponding file in the
@@ -1788,7 +1916,7 @@
if Bool(library.Properties.Static_ndk_lib) && library.static() &&
!ctx.InVendorOrProduct() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
- ctx.isForPlatform() && !ctx.isPreventInstall() {
+ CtxIsForPlatform(ctx) && !ctx.isPreventInstall() {
installPath := getUnversionedLibraryInstallPath(ctx).Join(ctx, file.Base())
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
@@ -1808,12 +1936,17 @@
return library.shared() || library.static()
}
-// static returns true if this library is for a "static' variant.
+// static returns true if this library is for a "static" variant.
func (library *libraryDecorator) static() bool {
return library.MutatedProperties.VariantIsStatic
}
-// shared returns true if this library is for a "shared' variant.
+// staticLibrary returns true if this library is for a "static"" variant.
+func (library *libraryDecorator) staticLibrary() bool {
+ return library.static()
+}
+
+// shared returns true if this library is for a "shared" variant.
func (library *libraryDecorator) shared() bool {
return library.MutatedProperties.VariantIsShared
}
@@ -1853,32 +1986,32 @@
library.MutatedProperties.BuildStatic = false
}
-// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
-func (library *libraryDecorator) hasLLNDKStubs() bool {
+// HasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
+func (library *libraryDecorator) HasLLNDKStubs() bool {
return String(library.Properties.Llndk.Symbol_file) != ""
}
// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
-func (library *libraryDecorator) hasLLNDKHeaders() bool {
+func (library *libraryDecorator) HasLLNDKHeaders() bool {
return Bool(library.Properties.Llndk.Llndk_headers)
}
-// isLLNDKMovedToApex returns true if this cc_library module sets the llndk.moved_to_apex property.
-func (library *libraryDecorator) isLLNDKMovedToApex() bool {
+// IsLLNDKMovedToApex returns true if this cc_library module sets the llndk.moved_to_apex property.
+func (library *libraryDecorator) IsLLNDKMovedToApex() bool {
return Bool(library.Properties.Llndk.Moved_to_apex)
}
-// hasVendorPublicLibrary returns true if this cc_library module has a variant that will build
+// HasVendorPublicLibrary returns true if this cc_library module has a variant that will build
// vendor public library stubs.
-func (library *libraryDecorator) hasVendorPublicLibrary() bool {
+func (library *libraryDecorator) HasVendorPublicLibrary() bool {
return String(library.Properties.Vendor_public_library.Symbol_file) != ""
}
-func (library *libraryDecorator) implementationModuleName(name string) string {
+func (library *libraryDecorator) ImplementationModuleName(name string) string {
return name
}
-func (library *libraryDecorator) buildStubs() bool {
+func (library *libraryDecorator) BuildStubs() bool {
return library.MutatedProperties.BuildStubs
}
@@ -1886,7 +2019,7 @@
if props := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)); props.Symbol_file != nil {
return props.Symbol_file
}
- if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
+ 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.
@@ -1896,35 +2029,35 @@
return nil
}
-func (library *libraryDecorator) hasStubsVariants() bool {
+func (library *libraryDecorator) HasStubsVariants() bool {
// Just having stubs.symbol_file is enough to create a stub variant. In that case
// the stub for the future API level is created.
return library.Properties.Stubs.Symbol_file != nil ||
len(library.Properties.Stubs.Versions) > 0
}
-func (library *libraryDecorator) isStubsImplementationRequired() bool {
+func (library *libraryDecorator) IsStubsImplementationRequired() bool {
return BoolDefault(library.Properties.Stubs.Implementation_installable, true)
}
-func (library *libraryDecorator) stubsVersions(ctx android.BaseModuleContext) []string {
- if !library.hasStubsVariants() {
+func (library *libraryDecorator) StubsVersions(ctx android.BaseModuleContext) []string {
+ if !library.HasStubsVariants() {
return nil
}
- if library.hasLLNDKStubs() && ctx.Module().(*Module).InVendorOrProduct() {
+ if library.HasLLNDKStubs() && ctx.Module().(*Module).InVendorOrProduct() {
// 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
- versions := addCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
- normalizeVersions(ctx, versions)
+ versions := AddCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
+ NormalizeVersions(ctx, versions)
return versions
}
-func addCurrentVersionIfNotPresent(vers []string) []string {
+func AddCurrentVersionIfNotPresent(vers []string) []string {
if inList(android.FutureApiLevel.String(), vers) {
return vers
}
@@ -1937,24 +2070,24 @@
return append(vers, android.FutureApiLevel.String())
}
-func (library *libraryDecorator) setStubsVersion(version string) {
+func (library *libraryDecorator) SetStubsVersion(version string) {
library.MutatedProperties.StubsVersion = version
}
-func (library *libraryDecorator) stubsVersion() string {
+func (library *libraryDecorator) StubsVersion() string {
return library.MutatedProperties.StubsVersion
}
-func (library *libraryDecorator) setBuildStubs(isLatest bool) {
+func (library *libraryDecorator) SetBuildStubs(isLatest bool) {
library.MutatedProperties.BuildStubs = true
library.MutatedProperties.IsLatestVersion = isLatest
}
-func (library *libraryDecorator) setAllStubsVersions(versions []string) {
+func (library *libraryDecorator) SetAllStubsVersions(versions []string) {
library.MutatedProperties.AllStubsVersions = versions
}
-func (library *libraryDecorator) allStubsVersions() []string {
+func (library *libraryDecorator) AllStubsVersions() []string {
return library.MutatedProperties.AllStubsVersions
}
@@ -1962,17 +2095,15 @@
return library.MutatedProperties.IsLatestVersion
}
-func (library *libraryDecorator) availableFor(what string) bool {
+func (library *libraryDecorator) apexAvailable() []string {
var list []string
if library.static() {
list = library.StaticProperties.Static.Apex_available
} else if library.shared() {
list = library.SharedProperties.Shared.Apex_available
}
- if len(list) == 0 {
- return false
- }
- return android.CheckAvailableForApex(what, list)
+
+ return list
}
func (library *libraryDecorator) installable() *bool {
@@ -1985,7 +2116,7 @@
}
func (library *libraryDecorator) makeUninstallable(mod *Module) {
- if library.static() && library.buildStatic() && !library.buildStubs() {
+ if library.static() && library.buildStatic() && !library.BuildStubs() {
// If we're asked to make a static library uninstallable we don't do
// anything since AndroidMkEntries always sets LOCAL_UNINSTALLABLE_MODULE
// for these entries. This is done to still get the make targets for NOTICE
@@ -1999,14 +2130,25 @@
return library.path.Partition()
}
-func (library *libraryDecorator) getAPIListCoverageXMLPath() android.ModuleOutPath {
+func (library *libraryDecorator) GetAPIListCoverageXMLPath() android.ModuleOutPath {
return library.apiListCoverageXmlPath
}
+func (library *libraryDecorator) setAPIListCoverageXMLPath(xml android.ModuleOutPath) {
+ library.apiListCoverageXmlPath = xml
+}
+
func (library *libraryDecorator) overriddenModules() []string {
return library.Properties.Overrides
}
+func (library *libraryDecorator) defaultDistFiles() []android.Path {
+ if library.defaultDistFile == nil {
+ return nil
+ }
+ return []android.Path{library.defaultDistFile}
+}
+
var _ overridable = (*libraryDecorator)(nil)
var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
@@ -2117,7 +2259,7 @@
} else {
// Header only
}
- } else if library, ok := ctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface() || library.RustLibraryInterface()) {
+ } else if library, ok := ctx.Module().(LinkableInterface); ok && (library.CcLibraryInterface()) {
// Non-cc.Modules may need an empty variant for their mutators.
variations := []string{}
if library.NonCcVariants() {
@@ -2146,6 +2288,9 @@
}
func (linkageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
@@ -2172,7 +2317,7 @@
}
buildStatic := library.BuildStaticVariant() && !isLLNDK
buildShared := library.BuildSharedVariant()
- if library.BuildRlibVariant() && library.IsRustFFI() && !buildStatic && (incomingVariation == "static" || incomingVariation == "") {
+ if library.BuildRlibVariant() && !buildStatic && (incomingVariation == "static" || incomingVariation == "") {
// Rust modules do not build static libs, but rlibs are used as if they
// were via `static_libs`. Thus we need to alias the BuildRlibVariant
// to "static" for Rust FFI libraries.
@@ -2202,11 +2347,13 @@
library.setStatic()
if !library.buildStatic() {
library.disablePrebuilt()
+ ctx.Module().(*Module).Prebuilt().SetUsePrebuilt(false)
}
} else if variation == "shared" {
library.setShared()
if !library.buildShared() {
library.disablePrebuilt()
+ ctx.Module().(*Module).Prebuilt().SetUsePrebuilt(false)
}
}
} else if library, ok := ctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() {
@@ -2229,10 +2376,10 @@
}
}
-// normalizeVersions modifies `versions` in place, so that each raw version
+// NormalizeVersions modifies `versions` in place, so that each raw version
// string becomes its normalized canonical form.
// Validates that the versions in `versions` are specified in least to greatest order.
-func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
+func NormalizeVersions(ctx android.BaseModuleContext, versions []string) {
var previous android.ApiLevel
for i, v := range versions {
ver, err := android.ApiLevelFromUser(ctx, v)
@@ -2249,7 +2396,7 @@
}
func perApiVersionVariations(mctx android.BaseModuleContext, minSdkVersion string) []string {
- from, err := nativeApiLevelFromUser(mctx, minSdkVersion)
+ from, err := NativeApiLevelFromUser(mctx, minSdkVersion)
if err != nil {
mctx.PropertyErrorf("min_sdk_version", err.Error())
return []string{""}
@@ -2277,25 +2424,25 @@
module.CcLibraryInterface() && module.Shared()
}
-func moduleLibraryInterface(module blueprint.Module) libraryInterface {
- if m, ok := module.(*Module); ok {
- return m.library
+func moduleVersionedInterface(module blueprint.Module) VersionedInterface {
+ if m, ok := module.(VersionedLinkableInterface); ok {
+ return m.VersionedInterface()
}
return nil
}
// setStubsVersions normalizes the versions in the Stubs.Versions property into MutatedProperties.AllStubsVersions.
-func setStubsVersions(mctx android.BaseModuleContext, library libraryInterface, module *Module) {
- if !library.buildShared() || !canBeVersionVariant(module) {
+func setStubsVersions(mctx android.BaseModuleContext, module VersionedLinkableInterface) {
+ if !module.BuildSharedVariant() || !canBeVersionVariant(module) {
return
}
- versions := library.stubsVersions(mctx)
+ versions := module.VersionedInterface().StubsVersions(mctx)
if mctx.Failed() {
return
}
// Set the versions on the pre-mutated module so they can be read by any llndk modules that
// depend on the implementation library and haven't been mutated yet.
- library.setAllStubsVersions(versions)
+ module.VersionedInterface().SetAllStubsVersions(versions)
}
// versionTransitionMutator splits a module into the mandatory non-stubs variant
@@ -2306,20 +2453,22 @@
if ctx.Os() != android.Android {
return []string{""}
}
-
- m, ok := ctx.Module().(*Module)
- if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
- setStubsVersions(ctx, library, m)
-
- return append(slices.Clone(library.allStubsVersions()), "")
- } else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() {
- return perApiVersionVariations(ctx, m.MinSdkVersion())
+ if m, ok := ctx.Module().(VersionedLinkableInterface); ok {
+ if m.CcLibraryInterface() && canBeVersionVariant(m) {
+ setStubsVersions(ctx, m)
+ return append(slices.Clone(m.VersionedInterface().AllStubsVersions()), "")
+ } else if m.SplitPerApiLevel() && m.IsSdkVariant() {
+ return perApiVersionVariations(ctx, m.MinSdkVersion())
+ }
}
return []string{""}
}
func (versionTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
@@ -2327,11 +2476,11 @@
if ctx.Os() != android.Android {
return ""
}
- m, ok := ctx.Module().(*Module)
- if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
+ m, ok := ctx.Module().(VersionedLinkableInterface)
+ if library := moduleVersionedInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
if incomingVariation == "latest" {
latestVersion := ""
- versions := library.allStubsVersions()
+ versions := library.AllStubsVersions()
if len(versions) > 0 {
latestVersion = versions[len(versions)-1]
}
@@ -2356,39 +2505,39 @@
return
}
- m, ok := ctx.Module().(*Module)
- if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
+ m, ok := ctx.Module().(VersionedLinkableInterface)
+ if library := moduleVersionedInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
isLLNDK := m.IsLlndk()
isVendorPublicLibrary := m.IsVendorPublicLibrary()
if variation != "" || isLLNDK || isVendorPublicLibrary {
// A stubs or LLNDK stubs variant.
- if m.sanitize != nil {
- m.sanitize.Properties.ForceDisable = true
+ if sm, ok := ctx.Module().(PlatformSanitizeable); ok && sm.SanitizePropDefined() {
+ sm.ForceDisableSanitizers()
}
- if m.stl != nil {
- m.stl.Properties.Stl = StringPtr("none")
- }
- m.Properties.PreventInstall = true
- lib := moduleLibraryInterface(m)
- allStubsVersions := library.allStubsVersions()
+ m.SetStl("none")
+ m.SetPreventInstall()
+ allStubsVersions := m.VersionedInterface().AllStubsVersions()
isLatest := len(allStubsVersions) > 0 && variation == allStubsVersions[len(allStubsVersions)-1]
- lib.setBuildStubs(isLatest)
+ m.VersionedInterface().SetBuildStubs(isLatest)
}
if variation != "" {
// A non-LLNDK stubs module is hidden from make
- library.setStubsVersion(variation)
- m.Properties.HideFromMake = true
+ m.VersionedInterface().SetStubsVersion(variation)
+ m.SetHideFromMake()
} else {
// A non-LLNDK implementation module has a dependency to all stubs versions
- for _, version := range library.allStubsVersions() {
- ctx.AddVariationDependencies([]blueprint.Variation{{"version", version}},
- stubImplDepTag, ctx.ModuleName())
+ for _, version := range m.VersionedInterface().AllStubsVersions() {
+ ctx.AddVariationDependencies(
+ []blueprint.Variation{
+ {Mutator: "version", Variation: version},
+ {Mutator: "link", Variation: "shared"}},
+ StubImplDepTag, ctx.ModuleName())
}
}
} else if ok && m.SplitPerApiLevel() && m.IsSdkVariant() {
- m.Properties.Sdk_version = StringPtr(variation)
- m.Properties.Min_sdk_version = StringPtr(variation)
+ m.SetSdkVersion(variation)
+ m.SetMinSdkVersion(variation)
}
}
@@ -2400,13 +2549,12 @@
inject *bool, fileName string) android.ModuleOutPath {
// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
injectBoringSSLHash := Bool(inject)
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
if tag, ok := ctx.OtherModuleDependencyTag(dep).(libraryDependencyTag); ok && tag.static() {
- if cc, ok := dep.(*Module); ok {
- if library, ok := cc.linker.(*libraryDecorator); ok {
- if Bool(library.Properties.Inject_bssl_hash) {
- injectBoringSSLHash = true
- }
+ if ccInfo, ok := android.OtherModuleProvider(ctx, dep, CcInfoProvider); ok &&
+ ccInfo.LinkerInfo != nil && ccInfo.LinkerInfo.LibraryDecoratorInfo != nil {
+ if ccInfo.LinkerInfo.LibraryDecoratorInfo.InjectBsslHash {
+ injectBoringSSLHash = true
}
}
}
diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go
index 5a45767..88ccd43 100644
--- a/cc/library_headers_test.go
+++ b/cc/library_headers_test.go
@@ -41,11 +41,11 @@
ctx := testCc(t, fmt.Sprintf(bp, headerModule))
// test if header search paths are correctly added
- cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc")
+ cc := ctx.ModuleForTests(t, "lib", "android_arm64_armv8-a_static").Rule("cc")
android.AssertStringDoesContain(t, "cFlags for lib module", cc.Args["cFlags"], " -Imy_include ")
// Test that there's a valid AndroidMk entry.
- headers := ctx.ModuleForTests("headers", "android_arm64_armv8-a").Module()
+ headers := ctx.ModuleForTests(t, "headers", "android_arm64_armv8-a").Module()
e := android.AndroidMkInfoForTest(t, ctx, headers).PrimaryInfo
// This duplicates the tests done in AndroidMkEntries.write. It would be
@@ -80,9 +80,9 @@
for _, prebuiltPreferred := range []bool{false, true} {
t.Run(fmt.Sprintf("prebuilt prefer %t", prebuiltPreferred), func(t *testing.T) {
ctx := testCc(t, fmt.Sprintf(bp, prebuiltPreferred))
- lib := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static")
- sourceDep := ctx.ModuleForTests("headers", "android_arm64_armv8-a")
- prebuiltDep := ctx.ModuleForTests("prebuilt_headers", "android_arm64_armv8-a")
+ lib := ctx.ModuleForTests(t, "lib", "android_arm64_armv8-a_static")
+ sourceDep := ctx.ModuleForTests(t, "headers", "android_arm64_armv8-a")
+ prebuiltDep := ctx.ModuleForTests(t, "prebuilt_headers", "android_arm64_armv8-a")
hasSourceDep := false
hasPrebuiltDep := false
ctx.VisitDirectDeps(lib.Module(), func(dep blueprint.Module) {
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index af3658d..4629030 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -546,7 +546,7 @@
specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx.SdkModuleContext(), ccModule, specifiedDeps)
if lib := ccModule.library; lib != nil {
- if !lib.hasStubsVariants() {
+ if !lib.HasStubsVariants() {
// Propagate dynamic dependencies for implementation libs, but not stubs.
p.SharedLibs = specifiedDeps.sharedLibs
} else {
@@ -554,8 +554,8 @@
// ccModule.StubsVersion()) if the module is versioned. 2. Ensure that all
// the versioned stub libs are retained in the prebuilt tree; currently only
// the stub corresponding to ccModule.StubsVersion() is.
- p.StubsVersions = lib.allStubsVersions()
- if lib.buildStubs() && ccModule.stubsSymbolFilePath() == nil {
+ p.StubsVersions = lib.AllStubsVersions()
+ if lib.BuildStubs() && ccModule.stubsSymbolFilePath() == nil {
ctx.ModuleErrorf("Could not determine symbol_file")
} else {
p.StubsSymbolFilePath = ccModule.stubsSymbolFilePath()
@@ -573,9 +573,8 @@
func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path {
var path android.Path
- outputFile := ccModule.OutputFile()
- if outputFile.Valid() {
- path = outputFile.Path()
+ if info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), ccModule, LinkableInfoProvider); ok && info.OutputFile.Valid() {
+ path = info.OutputFile.Path()
} else {
ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", ccModule)
}
diff --git a/cc/library_test.go b/cc/library_test.go
index 2ed2d76..8b7fed2 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -30,8 +30,8 @@
srcs: ["foo.c", "baz.o"],
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
if len(libfooShared.Inputs) != 2 {
t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
@@ -59,8 +59,8 @@
},
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
if len(libfooShared.Inputs) != 1 {
t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
@@ -85,8 +85,8 @@
},
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
if len(libfooShared.Inputs) != 2 {
t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
@@ -111,8 +111,8 @@
},
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
if len(libfooShared.Inputs) != 1 {
t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
@@ -137,8 +137,8 @@
},
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
if len(libfooShared.Inputs) != 1 {
t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
@@ -168,8 +168,8 @@
},
}`)
- libfooShared := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libfooStatic := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
+ libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_static").Output("libfoo.a")
if len(libfooShared.Inputs) != 3 {
t.Fatalf("unexpected inputs to libfoo shared: %#v", libfooShared.Inputs.Strings())
@@ -183,7 +183,7 @@
t.Errorf("static objects not reused for shared library")
}
- libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
if !inList("-DGOOGLE_PROTOBUF_NO_RTTI", libfoo.flags.Local.CFlags) {
t.Errorf("missing protobuf cflags")
}
@@ -254,7 +254,7 @@
version_script: "foo.map.txt",
}`)
- libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
+ libfoo := result.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Rule("ld")
android.AssertStringListContains(t, "missing dependency on version_script",
libfoo.Implicits.Strings(), "foo.map.txt")
@@ -272,7 +272,7 @@
dynamic_list: "foo.dynamic.txt",
}`)
- libfoo := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
+ libfoo := result.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Rule("ld")
android.AssertStringListContains(t, "missing dependency on dynamic_list",
libfoo.Implicits.Strings(), "foo.dynamic.txt")
@@ -312,14 +312,14 @@
}
`)
- libdirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static").Rule("arWithLibs")
- libtransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static").Rule("arWithLibs")
+ libdirect := result.ModuleForTests(t, "libdirect", "android_arm64_armv8-a_static").Rule("arWithLibs")
+ libtransitive := result.ModuleForTests(t, "libtransitive", "android_arm64_armv8-a_static").Rule("arWithLibs")
- libdirectWithSrcs := result.ModuleForTests("libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs")
- libtransitiveWithSrcs := result.ModuleForTests("libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs")
+ libdirectWithSrcs := result.ModuleForTests(t, "libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs")
+ libtransitiveWithSrcs := result.ModuleForTests(t, "libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("arWithLibs")
- barObj := result.ModuleForTests("libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("cc")
- bazObj := result.ModuleForTests("libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("cc")
+ barObj := result.ModuleForTests(t, "libdirect_with_srcs", "android_arm64_armv8-a_static").Rule("cc")
+ bazObj := result.ModuleForTests(t, "libtransitive_with_srcs", "android_arm64_armv8-a_static").Rule("cc")
android.AssertStringListContains(t, "missing dependency on foo.a",
libdirect.Inputs.Strings(), "foo.a")
diff --git a/cc/linkable.go b/cc/linkable.go
index 1a9a9ab..f3aff15 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -53,6 +53,9 @@
// SanitizableDepTagChecker returns a SantizableDependencyTagChecker function type.
SanitizableDepTagChecker() SantizableDependencyTagChecker
+
+ // ForceDisableSanitizers sets the ForceDisable sanitize property
+ ForceDisableSanitizers()
}
// SantizableDependencyTagChecker functions check whether or not a dependency
@@ -63,6 +66,30 @@
// implementation should handle tags from both.
type SantizableDependencyTagChecker func(tag blueprint.DependencyTag) bool
+type VersionedLinkableInterface interface {
+ LinkableInterface
+ android.ApexModule
+
+ // VersionedInterface returns the VersionedInterface for this module
+ // (e.g. c.library), or nil if this is module is not a VersionedInterface.
+ VersionedInterface() VersionedInterface
+
+ // HasStubsVariants true if this module is a stub or has a sibling variant
+ // that is a stub.
+ HasStubsVariants() bool
+
+ // SetStl sets the stl property for CC modules. Does not panic if for other module types.
+ SetStl(string)
+ SetSdkVersion(string)
+ SetMinSdkVersion(version string)
+ ApexSdkVersion() android.ApiLevel
+ ImplementationModuleNameForMake() string
+
+ // RustApexExclude returns ApexExclude() for Rust modules; always returns false for all non-Rust modules.
+ // TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
+ RustApexExclude() bool
+}
+
// LinkableInterface is an interface for a type of module that is linkable in a C++ library.
type LinkableInterface interface {
android.Module
@@ -102,9 +129,6 @@
IsPrebuilt() bool
Toc() android.OptionalPath
- // IsRustFFI returns true if this is a Rust FFI library.
- IsRustFFI() bool
-
// IsFuzzModule returns true if this a *_fuzz module.
IsFuzzModule() bool
@@ -135,28 +159,18 @@
// IsNdk returns true if the library is in the configs known NDK list.
IsNdk(config android.Config) bool
- // HasStubsVariants true if this module is a stub or has a sibling variant
- // that is a stub.
- HasStubsVariants() bool
-
// IsStubs returns true if the this is a stubs library.
IsStubs() bool
// IsLlndk returns true for both LLNDK (public) and LLNDK-private libs.
IsLlndk() bool
- // HasLlndkStubs returns true if this library has a variant that will build LLNDK stubs.
- HasLlndkStubs() bool
-
// NeedsLlndkVariants returns true if this module has LLNDK stubs or provides LLNDK headers.
NeedsLlndkVariants() bool
// NeedsVendorPublicLibraryVariants returns true if this module has vendor public library stubs.
NeedsVendorPublicLibraryVariants() bool
- //StubsVersion returns the stubs version for this module.
- StubsVersion() string
-
// UseVndk returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64.
// "product" and "vendor" variant modules return true for this function.
// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true",
@@ -185,6 +199,7 @@
MinSdkVersion() string
AlwaysSdk() bool
IsSdkVariant() bool
+ Multilib() string
SplitPerApiLevel() bool
@@ -253,6 +268,7 @@
// FuzzModule returns the fuzz.FuzzModule associated with the module.
FuzzModuleStruct() fuzz.FuzzModule
+ IsCrt() bool
}
var (
diff --git a/cc/linker.go b/cc/linker.go
index b96d139..f854937 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -457,7 +457,7 @@
if ctx.minSdkVersion() == "current" {
return true
}
- parsedSdkVersion, err := nativeApiLevelFromUser(ctx, ctx.minSdkVersion())
+ parsedSdkVersion, err := NativeApiLevelFromUser(ctx, ctx.minSdkVersion())
if err != nil {
ctx.PropertyErrorf("min_sdk_version",
"Invalid min_sdk_version value (must be int or current): %q",
@@ -471,16 +471,77 @@
// ModuleContext extends BaseModuleContext
// BaseModuleContext should know if LLD is used?
-func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- toolchain := ctx.toolchain()
-
+func CommonLinkerFlags(ctx android.ModuleContext, flags Flags, useClangLld bool,
+ toolchain config.Toolchain, allow_undefined_symbols bool) Flags {
hod := "Host"
if ctx.Os().Class == android.Device {
hod = "Device"
}
- if linker.useClangLld(ctx) {
+ mod, ok := ctx.Module().(LinkableInterface)
+ if !ok {
+ ctx.ModuleErrorf("trying to add CommonLinkerFlags to non-LinkableInterface module.")
+ return flags
+ }
+ if useClangLld {
flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod))
+ } else {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
+ }
+
+ if allow_undefined_symbols {
+ if ctx.Darwin() {
+ // darwin defaults to treating undefined symbols as errors
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-undefined,dynamic_lookup")
+ }
+ } else if !ctx.Darwin() && !ctx.Windows() {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--no-undefined")
+ }
+
+ if useClangLld {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Lldflags())
+ } else {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Ldflags())
+ }
+
+ if !toolchain.Bionic() && ctx.Os() != android.LinuxMusl {
+ if !ctx.Windows() {
+ // Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
+ // builds
+ flags.Global.LdFlags = append(flags.Global.LdFlags,
+ "-ldl",
+ "-lpthread",
+ "-lm",
+ )
+ if !ctx.Darwin() {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, "-lrt")
+ }
+ }
+ }
+ staticLib := mod.CcLibraryInterface() && mod.Static()
+ if ctx.Host() && !ctx.Windows() && !staticLib {
+ flags.Global.LdFlags = append(flags.Global.LdFlags, RpathFlags(ctx)...)
+ }
+
+ flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ToolchainLdflags())
+ return flags
+}
+
+func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ toolchain := ctx.toolchain()
+ allow_undefined_symbols := Bool(linker.Properties.Allow_undefined_symbols)
+
+ flags = CommonLinkerFlags(ctx, flags, linker.useClangLld(ctx), toolchain,
+ allow_undefined_symbols)
+
+ if !toolchain.Bionic() && ctx.Os() != android.LinuxMusl {
+ CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, linker.Properties.Host_ldlibs...)
+ }
+
+ CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
+
+ if linker.useClangLld(ctx) {
if !BoolDefault(linker.Properties.Pack_relocations, packRelocationsDefault) {
flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=none")
} else if ctx.Device() {
@@ -498,53 +559,10 @@
flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android")
}
}
- } else {
- flags.Global.LdFlags = append(flags.Global.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod))
}
- if Bool(linker.Properties.Allow_undefined_symbols) {
- if ctx.Darwin() {
- // darwin defaults to treating undefined symbols as errors
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-undefined,dynamic_lookup")
- }
- } else if !ctx.Darwin() && !ctx.Windows() {
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--no-undefined")
- }
-
- if linker.useClangLld(ctx) {
- flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Lldflags())
- } else {
- flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Ldflags())
- }
-
- if !ctx.toolchain().Bionic() && ctx.Os() != android.LinuxMusl {
- CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
-
- flags.Local.LdFlags = append(flags.Local.LdFlags, linker.Properties.Host_ldlibs...)
-
- if !ctx.Windows() {
- // Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
- // builds
- flags.Global.LdFlags = append(flags.Global.LdFlags,
- "-ldl",
- "-lpthread",
- "-lm",
- )
- if !ctx.Darwin() {
- flags.Global.LdFlags = append(flags.Global.LdFlags, "-lrt")
- }
- }
- }
-
- CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags)
flags.Local.LdFlags = append(flags.Local.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...)
- if ctx.Host() && !ctx.Windows() && !ctx.static() {
- flags.Global.LdFlags = append(flags.Global.LdFlags, RpathFlags(ctx)...)
- }
-
- flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.ToolchainLdflags())
-
// Version_script is not needed when linking stubs lib where the version
// script is created from the symbol map file.
if !linker.dynamicProperties.BuildStubs {
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 162dd54..b119fda 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -63,23 +63,51 @@
}
func makeLlndkVars(ctx android.MakeVarsContext) {
- // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config.
- movedToApexLlndkLibraries := make(map[string]bool)
- ctx.VisitAllModules(func(module android.Module) {
- if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() {
- if library.isLLNDKMovedToApex() {
- name := library.implementationModuleName(module.(*Module).BaseModuleName())
- movedToApexLlndkLibraries[name] = true
- }
- }
- })
- ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
- strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " "))
}
func init() {
RegisterLlndkLibraryTxtType(android.InitRegistrationContext)
+ android.RegisterParallelSingletonType("movedToApexLlndkLibraries", movedToApexLlndkLibrariesFactory)
+}
+
+func movedToApexLlndkLibrariesFactory() android.Singleton {
+ return &movedToApexLlndkLibraries{}
+}
+
+type movedToApexLlndkLibraries struct {
+ movedToApexLlndkLibraries []string
+}
+
+func (s *movedToApexLlndkLibraries) GenerateBuildActions(ctx android.SingletonContext) {
+ // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config.
+ movedToApexLlndkLibrariesMap := make(map[string]bool)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if library, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok {
+ if library.HasLLNDKStubs && library.IsLLNDKMovedToApex {
+ movedToApexLlndkLibrariesMap[library.ImplementationModuleName] = true
+ }
+ }
+ })
+ s.movedToApexLlndkLibraries = android.SortedKeys(movedToApexLlndkLibrariesMap)
+
+ var sb strings.Builder
+ for i, l := range s.movedToApexLlndkLibraries {
+ if i > 0 {
+ sb.WriteRune(' ')
+ }
+ sb.WriteString(l)
+ sb.WriteString(".so")
+ }
+ android.WriteFileRule(ctx, MovedToApexLlndkLibrariesFile(ctx), sb.String())
+}
+
+func MovedToApexLlndkLibrariesFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForIntermediates(ctx, "moved_to_apex_llndk_libraries.txt")
+}
+
+func (s *movedToApexLlndkLibraries) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(s.movedToApexLlndkLibraries, " "))
}
func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) {
@@ -118,16 +146,20 @@
ctx.InstallFile(installPath, filename, txt.outputFile)
ctx.SetOutputFiles(android.Paths{txt.outputFile}, "")
+
+ etc.SetCommonPrebuiltEtcInfo(ctx, txt)
}
-func getVndkFileName(m *Module) (string, error) {
- if library, ok := m.linker.(*libraryDecorator); ok {
- return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
+func getVndkFileName(info *LinkerInfo) (string, error) {
+ if info != nil {
+ if info.LibraryDecoratorInfo != nil {
+ return info.LibraryDecoratorInfo.VndkFileName, nil
+ }
+ if info.PrebuiltLibraryLinkerInfo != nil {
+ return info.PrebuiltLibraryLinkerInfo.VndkFileName, nil
+ }
}
- if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok {
- return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
- }
- return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
+ return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", info)
}
func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) {
@@ -136,9 +168,17 @@
return
}
- ctx.VisitAllModules(func(m android.Module) {
- if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() {
- filename, err := getVndkFileName(c)
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
+ ccInfo, ok := android.OtherModuleProvider(ctx, m, CcInfoProvider)
+ if !ok {
+ return
+ }
+ linkableInfo, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider)
+ if !ok {
+ return
+ }
+ if linkableInfo.IsLlndk && !linkableInfo.Header && !linkableInfo.IsVndkPrebuiltLibrary {
+ filename, err := getVndkFileName(ccInfo.LinkerInfo)
if err != nil {
ctx.ModuleErrorf(m, "%s", err)
}
@@ -194,10 +234,10 @@
lib, isLib := m.linker.(*libraryDecorator)
prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
- if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() {
+ if m.InVendorOrProduct() && isLib && lib.HasLLNDKStubs() {
m.VendorProperties.IsLLNDK = true
}
- if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
+ if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.HasLLNDKStubs() {
m.VendorProperties.IsLLNDK = true
}
diff --git a/cc/lto_test.go b/cc/lto_test.go
index e4b5a3a..3fb1f3c 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -70,24 +70,24 @@
result := LTOPreparer.RunTestWithBp(t, bp)
- libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
+ libLto := result.ModuleForTests(t, "lto_enabled", "android_arm64_armv8-a_shared").Module()
- libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static").Module()
+ libFoo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_static").Module()
if !hasDep(result, libLto, libFoo) {
t.Errorf("'lto_enabled' missing dependency on the default variant of 'foo'")
}
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static").Module()
+ libBaz := result.ModuleForTests(t, "baz", "android_arm64_armv8-a_static").Module()
if !hasDep(result, libFoo, libBaz) {
t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
- libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static").Module()
+ libNeverLto := result.ModuleForTests(t, "lib_never_lto", "android_arm64_armv8-a_static").Module()
if !hasDep(result, libLto, libNeverLto) {
t.Errorf("'lto_enabled' missing dependency on the default variant of 'lib_never_lto'")
}
- libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
+ libBar := result.ModuleForTests(t, "bar", "android_arm64_armv8-a_shared").Module()
if !hasDep(result, libLto, libBar) {
t.Errorf("'lto_enabled' missing dependency on the default variant of 'bar'")
}
@@ -138,15 +138,15 @@
result := LTOPreparer.RunTestWithBp(t, bp)
- libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
- libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
+ libRoot := result.ModuleForTests(t, "root", "android_arm64_armv8-a_shared").Module()
+ libRootLtoNever := result.ModuleForTests(t, "root_no_lto", "android_arm64_armv8-a_shared").Module()
- libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_static")
if !hasDep(result, libRoot, libFoo.Module()) {
t.Errorf("'root' missing dependency on the default variant of 'foo'")
}
- libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none")
+ libFooNoLto := result.ModuleForTests(t, "foo", "android_arm64_armv8-a_static_lto-none")
if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) {
t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'")
}
@@ -156,7 +156,7 @@
t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
}
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static")
+ libBaz := result.ModuleForTests(t, "baz", "android_arm64_armv8-a_static")
if !hasDep(result, libFoo.Module(), libBaz.Module()) {
t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
@@ -187,8 +187,8 @@
}`
result := LTOPreparer.RunTestWithBp(t, bp)
- libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
+ libFooWithLto := result.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libFooWithoutLto := result.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Rule("ld")
android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it",
libFooWithLto.Args["ldFlags"], "-flto=thin")
@@ -215,8 +215,8 @@
result := LTOPreparer.RunTestWithBp(t, bp)
- libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
- libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libFoo := result.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libBar := result.ModuleForTests(t, "runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
libFoo.Args["ldFlags"], "-flto=thin")
diff --git a/cc/makevars.go b/cc/makevars.go
index 4cb98e7..9358755 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -100,15 +100,7 @@
// Filter vendor_public_library that are exported to make
var exportedVendorPublicLibraries []string
- var warningsAllowed []string
- var usingWnoErrors []string
- var missingProfiles []string
ctx.VisitAllModules(func(module android.Module) {
- if v, ok := android.OtherModuleProvider(ctx, module, CcMakeVarsInfoProvider); ok {
- warningsAllowed = android.AppendIfNotZero(warningsAllowed, v.WarningsAllowed)
- usingWnoErrors = android.AppendIfNotZero(usingWnoErrors, v.UsingWnoError)
- missingProfiles = android.AppendIfNotZero(missingProfiles, v.MissingProfile)
- }
if ccModule, ok := module.(*Module); ok {
baseName := ccModule.BaseModuleName()
if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() {
@@ -123,9 +115,6 @@
ctx.Strict("LSDUMP_PATHS", strings.Join(lsdumpPaths, " "))
ctx.Strict("ANDROID_WARNING_ALLOWED_PROJECTS", makeStringOfWarningAllowedProjects())
- ctx.Strict("SOONG_MODULES_WARNINGS_ALLOWED", makeVarsString(warningsAllowed))
- ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", makeVarsString(usingWnoErrors))
- ctx.Strict("SOONG_MODULES_MISSING_PGO_PROFILE_FILE", makeVarsString(missingProfiles))
ctx.Strict("CLANG_COVERAGE_CONFIG_CFLAGS", strings.Join(clangCoverageCFlags, " "))
ctx.Strict("CLANG_COVERAGE_CONFIG_COMMFLAGS", strings.Join(clangCoverageCommonFlags, " "))
@@ -175,19 +164,19 @@
sort.Strings(ndkKnownLibs)
ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " "))
- hostTargets := ctx.Config().Targets[ctx.Config().BuildOS]
- makeVarsToolchain(ctx, "", hostTargets[0])
- if len(hostTargets) > 1 {
- makeVarsToolchain(ctx, "2ND_", hostTargets[1])
+ if hostTargets := ctx.Config().Targets[ctx.Config().BuildOS]; len(hostTargets) > 0 {
+ makeVarsToolchain(ctx, "", hostTargets[0])
+ if len(hostTargets) > 1 {
+ makeVarsToolchain(ctx, "2ND_", hostTargets[1])
+ }
}
- deviceTargets := ctx.Config().Targets[android.Android]
- makeVarsToolchain(ctx, "", deviceTargets[0])
- if len(deviceTargets) > 1 {
- makeVarsToolchain(ctx, "2ND_", deviceTargets[1])
+ if deviceTargets := ctx.Config().Targets[android.Android]; len(deviceTargets) > 0 {
+ makeVarsToolchain(ctx, "", deviceTargets[0])
+ if len(deviceTargets) > 1 {
+ makeVarsToolchain(ctx, "2ND_", deviceTargets[1])
+ }
}
-
- makeLlndkVars(ctx)
}
func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
diff --git a/cc/misc_disted_files.go b/cc/misc_disted_files.go
new file mode 100644
index 0000000..4bdffaa
--- /dev/null
+++ b/cc/misc_disted_files.go
@@ -0,0 +1,89 @@
+// Copyright 2025 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"
+ "strings"
+)
+
+func init() {
+ android.InitRegistrationContext.RegisterSingletonType("cc_misc_disted_files", ccMiscDistedFilesSingletonFactory)
+}
+
+func ccMiscDistedFilesSingletonFactory() android.Singleton {
+ return &ccMiscDistedFilesSingleton{}
+}
+
+type ccMiscDistedFilesSingleton struct {
+ warningsAllowed []string
+ usingWnoErrors []string
+}
+
+func (s *ccMiscDistedFilesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var warningsAllowed []string
+ var usingWnoErrors []string
+ var missingProfiles []string
+ ctx.VisitAllModules(func(module android.Module) {
+ if v, ok := android.OtherModuleProvider(ctx, module, CcMakeVarsInfoProvider); ok {
+ warningsAllowed = android.AppendIfNotZero(warningsAllowed, v.WarningsAllowed)
+ usingWnoErrors = android.AppendIfNotZero(usingWnoErrors, v.UsingWnoError)
+ missingProfiles = android.AppendIfNotZero(missingProfiles, v.MissingProfile)
+ }
+ })
+
+ warningsAllowed = android.SortedUniqueStrings(warningsAllowed)
+ usingWnoErrors = android.SortedUniqueStrings(usingWnoErrors)
+ missingProfiles = android.SortedUniqueStrings(missingProfiles)
+
+ s.warningsAllowed = warningsAllowed
+ s.usingWnoErrors = usingWnoErrors
+
+ var sb strings.Builder
+ sb.WriteString("# Modules using -Wno-error\n")
+ for _, nwe := range usingWnoErrors {
+ sb.WriteString(nwe)
+ sb.WriteString("\n")
+ }
+ sb.WriteString("# Modules that allow warnings\n")
+ for _, wa := range warningsAllowed {
+ sb.WriteString(wa)
+ sb.WriteString("\n")
+ }
+ wallWerrFile := android.PathForOutput(ctx, "wall_werror.txt")
+ android.WriteFileRuleVerbatim(ctx, wallWerrFile, sb.String())
+
+ // Only dist this file in soong-only builds. In soong+make builds, it contains information
+ // from make modules, so we'll still rely on make to build and dist it.
+ if !ctx.Config().KatiEnabled() {
+ ctx.DistForGoal("droidcore-unbundled", wallWerrFile)
+ }
+
+ var sb2 strings.Builder
+ sb2.WriteString("# Modules missing PGO profile files\n")
+ for _, mp := range missingProfiles {
+ sb2.WriteString(mp)
+ sb2.WriteString("\n")
+ }
+ profileMissingFile := android.PathForOutput(ctx, "pgo_profile_file_missing.txt")
+ android.WriteFileRuleVerbatim(ctx, profileMissingFile, sb2.String())
+
+ ctx.DistForGoal("droidcore-unbundled", profileMissingFile)
+}
+
+func (s *ccMiscDistedFilesSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict("SOONG_MODULES_WARNINGS_ALLOWED", strings.Join(s.warningsAllowed, " "))
+ ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", strings.Join(s.usingWnoErrors, " "))
+}
diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go
index 2706261..b96a779 100644
--- a/cc/ndk_abi.go
+++ b/cc/ndk_abi.go
@@ -39,15 +39,15 @@
func (n *ndkAbiDumpSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var depPaths android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
- if m, ok := module.(*Module); ok {
- if installer, ok := m.installer.(*stubDecorator); ok {
- if installer.hasAbiDump {
- depPaths = append(depPaths, installer.abiDumpPath)
+ if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ if ccInfo.InstallerInfo != nil && ccInfo.InstallerInfo.StubDecoratorInfo != nil {
+ if ccInfo.InstallerInfo.StubDecoratorInfo.HasAbiDump {
+ depPaths = append(depPaths, ccInfo.InstallerInfo.StubDecoratorInfo.AbiDumpPath)
}
}
}
@@ -77,14 +77,14 @@
func (n *ndkAbiDiffSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var depPaths android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(android.Module); ok && !m.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
- if m, ok := module.(*Module); ok {
- if installer, ok := m.installer.(*stubDecorator); ok {
- depPaths = append(depPaths, installer.abiDiffPaths...)
+ if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ if ccInfo.InstallerInfo != nil && ccInfo.InstallerInfo.StubDecoratorInfo != nil {
+ depPaths = append(depPaths, ccInfo.InstallerInfo.StubDecoratorInfo.AbiDiffPaths...)
}
}
})
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 7481954..6e26d4c 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -80,6 +80,20 @@
licensePath android.Path
}
+type NdkHeaderInfo struct {
+ SrcPaths android.Paths
+ InstallPaths android.Paths
+ LicensePath android.Path
+ // Set to true if the headers installed by this module should skip
+ // verification. This step ensures that each header is self-contained (can
+ // be #included alone) and is valid C. This should not be disabled except in
+ // rare cases. Outside bionic and external, if you're using this option
+ // you've probably made a mistake.
+ SkipVerification bool
+}
+
+var NdkHeaderInfoProvider = blueprint.NewProvider[NdkHeaderInfo]()
+
func getHeaderInstallDir(ctx android.ModuleContext, header android.Path, from string,
to string) android.OutputPath {
// Output path is the sysroot base + "usr/include" + to directory + directory component
@@ -135,6 +149,13 @@
if len(m.installPaths) == 0 {
ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs)
}
+
+ android.SetProvider(ctx, NdkHeaderInfoProvider, NdkHeaderInfo{
+ SrcPaths: m.srcPaths,
+ InstallPaths: m.installPaths,
+ LicensePath: m.licensePath,
+ SkipVerification: Bool(m.properties.Skip_verification),
+ })
}
// ndk_headers installs the sets of ndk headers defined in the srcs property
@@ -203,6 +224,8 @@
licensePath android.Path
}
+var NdkPreprocessedHeaderInfoProvider = blueprint.NewProvider[NdkHeaderInfo]()
+
func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if String(m.properties.License) == "" {
ctx.PropertyErrorf("license", "field is required")
@@ -231,6 +254,13 @@
if len(m.installPaths) == 0 {
ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs)
}
+
+ android.SetProvider(ctx, NdkPreprocessedHeaderInfoProvider, NdkHeaderInfo{
+ SrcPaths: m.srcPaths,
+ InstallPaths: m.installPaths,
+ LicensePath: m.licensePath,
+ SkipVerification: Bool(m.properties.Skip_verification),
+ })
}
// preprocessed_ndk_headers preprocesses all the ndk headers listed in the srcs
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2411614..c21fe56 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -133,13 +133,13 @@
unversionedUntil android.ApiLevel
}
-var _ versionedInterface = (*stubDecorator)(nil)
+var _ VersionedInterface = (*stubDecorator)(nil)
func shouldUseVersionScript(ctx BaseModuleContext, stub *stubDecorator) bool {
return stub.apiLevel.GreaterThanOrEqualTo(stub.unversionedUntil)
}
-func (stub *stubDecorator) implementationModuleName(name string) string {
+func (stub *stubDecorator) ImplementationModuleName(name string) string {
return strings.TrimSuffix(name, ndkLibrarySuffix)
}
@@ -155,7 +155,7 @@
return versionStrs
}
-func (this *stubDecorator) stubsVersions(ctx android.BaseModuleContext) []string {
+func (this *stubDecorator) StubsVersions(ctx android.BaseModuleContext) []string {
if !ctx.Module().Enabled(ctx) {
return nil
}
@@ -163,7 +163,7 @@
ctx.Module().Disable()
return nil
}
- firstVersion, err := nativeApiLevelFromUser(ctx,
+ firstVersion, err := NativeApiLevelFromUser(ctx,
String(this.properties.First_version))
if err != nil {
ctx.PropertyErrorf("first_version", err.Error())
@@ -173,10 +173,10 @@
}
func (this *stubDecorator) initializeProperties(ctx BaseModuleContext) bool {
- this.apiLevel = nativeApiLevelOrPanic(ctx, this.stubsVersion())
+ this.apiLevel = nativeApiLevelOrPanic(ctx, this.StubsVersion())
var err error
- this.firstVersion, err = nativeApiLevelFromUser(ctx,
+ this.firstVersion, err = NativeApiLevelFromUser(ctx,
String(this.properties.First_version))
if err != nil {
ctx.PropertyErrorf("first_version", err.Error())
@@ -184,7 +184,7 @@
}
str := proptools.StringDefault(this.properties.Unversioned_until, "minimum")
- this.unversionedUntil, err = nativeApiLevelFromUser(ctx, str)
+ this.unversionedUntil, err = NativeApiLevelFromUser(ctx, str)
if err != nil {
ctx.PropertyErrorf("unversioned_until", err.Error())
return false
@@ -236,7 +236,7 @@
pctx.StaticVariable("StubLibraryCompilerFlags", strings.Join(stubLibraryCompilerFlags, " "))
}
-func addStubLibraryCompilerFlags(flags Flags) Flags {
+func AddStubLibraryCompilerFlags(flags Flags) Flags {
flags.Global.CFlags = append(flags.Global.CFlags, stubLibraryCompilerFlags...)
// All symbols in the stubs library should be visible.
if inList("-fvisibility=hidden", flags.Local.CFlags) {
@@ -247,17 +247,17 @@
func (stub *stubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
flags = stub.baseCompiler.compilerFlags(ctx, flags, deps)
- return addStubLibraryCompilerFlags(flags)
+ return AddStubLibraryCompilerFlags(flags)
}
-type ndkApiOutputs struct {
- stubSrc android.ModuleGenPath
- versionScript android.ModuleGenPath
+type NdkApiOutputs struct {
+ StubSrc android.ModuleGenPath
+ VersionScript android.ModuleGenPath
symbolList android.ModuleGenPath
}
-func parseNativeAbiDefinition(ctx ModuleContext, symbolFile string,
- apiLevel android.ApiLevel, genstubFlags string) ndkApiOutputs {
+func ParseNativeAbiDefinition(ctx android.ModuleContext, symbolFile string,
+ apiLevel android.ApiLevel, genstubFlags string) NdkApiOutputs {
stubSrcPath := android.PathForModuleGen(ctx, "stub.c")
versionScriptPath := android.PathForModuleGen(ctx, "stub.map")
@@ -279,37 +279,36 @@
},
})
- return ndkApiOutputs{
- stubSrc: stubSrcPath,
- versionScript: versionScriptPath,
+ return NdkApiOutputs{
+ StubSrc: stubSrcPath,
+ VersionScript: versionScriptPath,
symbolList: symbolListPath,
}
}
-func compileStubLibrary(ctx ModuleContext, flags Flags, src android.Path) Objects {
+func CompileStubLibrary(ctx android.ModuleContext, flags Flags, src android.Path, sharedFlags *SharedFlags) Objects {
// libc/libm stubs libraries end up mismatching with clang's internal definition of these
// functions (which have noreturn attributes and other things). Because we just want to create a
// stub with symbol definitions, and types aren't important in C, ignore the mismatch.
flags.Local.ConlyFlags = append(flags.Local.ConlyFlags, "-fno-builtin")
return compileObjs(ctx, flagsToBuilderFlags(flags), "",
- android.Paths{src}, nil, nil, nil, nil)
+ android.Paths{src}, nil, nil, nil, nil, sharedFlags)
}
func (this *stubDecorator) findImplementationLibrary(ctx ModuleContext) android.Path {
- dep := ctx.GetDirectDepWithTag(strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix),
+ dep := ctx.GetDirectDepProxyWithTag(strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix),
stubImplementation)
if dep == nil {
- ctx.ModuleErrorf("Could not find implementation for stub")
+ ctx.ModuleErrorf("Could not find implementation for stub: ")
return nil
}
- impl, ok := dep.(*Module)
- if !ok {
+ if _, ok := android.OtherModuleProvider(ctx, *dep, CcInfoProvider); !ok {
ctx.ModuleErrorf("Implementation for stub is not correct module type")
return nil
}
- output := impl.UnstrippedOutputFile()
+ output := android.OtherModuleProviderOrDefault(ctx, *dep, LinkableInfoProvider).UnstrippedOutputFile
if output == nil {
- ctx.ModuleErrorf("implementation module (%s) has no output", impl)
+ ctx.ModuleErrorf("implementation module (%s) has no output", *dep)
return nil
}
@@ -490,7 +489,7 @@
ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
}
- if !c.buildStubs() {
+ if !c.BuildStubs() {
// NDK libraries have no implementation variant, nothing to do
return Objects{}
}
@@ -501,9 +500,9 @@
}
symbolFile := String(c.properties.Symbol_file)
- nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, c.apiLevel, "")
- objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
- c.versionScriptPath = nativeAbiResult.versionScript
+ nativeAbiResult := ParseNativeAbiDefinition(ctx, symbolFile, c.apiLevel, "")
+ objs := CompileStubLibrary(ctx, flags, nativeAbiResult.StubSrc, ctx.getSharedFlags())
+ c.versionScriptPath = nativeAbiResult.VersionScript
if c.canDumpAbi(ctx) {
c.dumpAbi(ctx, nativeAbiResult.symbolList)
if c.canDiffAbi(ctx.Config()) {
@@ -511,7 +510,7 @@
}
}
if c.apiLevel.IsCurrent() && ctx.PrimaryArch() {
- c.parsedCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
+ c.parsedCoverageXmlPath = ParseSymbolFileForAPICoverage(ctx, symbolFile)
}
return objs
}
@@ -542,7 +541,7 @@
func (stub *stubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
objs Objects) android.Path {
- if !stub.buildStubs() {
+ if !stub.BuildStubs() {
// NDK libraries have no implementation variant, nothing to do
return nil
}
@@ -561,6 +560,10 @@
return false
}
+func (stub *stubDecorator) defaultDistFiles() []android.Path {
+ return nil
+}
+
// Returns the install path for unversioned NDK libraries (currently only static
// libraries).
func getUnversionedLibraryInstallPath(ctx ModuleContext) android.OutputPath {
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 92da172..1677862 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -53,11 +53,12 @@
// TODO(danalbert): Write `ndk_static_library` rule.
import (
- "android/soong/android"
"fmt"
"path/filepath"
"strings"
+ "android/soong/android"
+
"github.com/google/blueprint"
)
@@ -209,57 +210,61 @@
var headerCCompatVerificationTimestampPaths android.Paths
var installPaths android.Paths
var licensePaths android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(android.Module); ok && !m.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
- if m, ok := module.(*headerModule); ok {
- headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
- headerInstallPaths = append(headerInstallPaths, m.installPaths...)
- if !Bool(m.properties.Skip_verification) {
- for i, installPath := range m.installPaths {
+ if m, ok := android.OtherModuleProvider(ctx, module, NdkHeaderInfoProvider); ok {
+ headerSrcPaths = append(headerSrcPaths, m.SrcPaths...)
+ headerInstallPaths = append(headerInstallPaths, m.InstallPaths...)
+ if !m.SkipVerification {
+ for i, installPath := range m.InstallPaths {
headersToVerify = append(headersToVerify, srcDestPair{
- src: m.srcPaths[i],
+ src: m.SrcPaths[i],
dest: installPath,
})
}
}
- installPaths = append(installPaths, m.installPaths...)
- licensePaths = append(licensePaths, m.licensePath)
+ installPaths = append(installPaths, m.InstallPaths...)
+ licensePaths = append(licensePaths, m.LicensePath)
}
- if m, ok := module.(*preprocessedHeadersModule); ok {
- headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
- headerInstallPaths = append(headerInstallPaths, m.installPaths...)
- if !Bool(m.properties.Skip_verification) {
- for i, installPath := range m.installPaths {
+ if m, ok := android.OtherModuleProvider(ctx, module, NdkPreprocessedHeaderInfoProvider); ok {
+ headerSrcPaths = append(headerSrcPaths, m.SrcPaths...)
+ headerInstallPaths = append(headerInstallPaths, m.InstallPaths...)
+ if !m.SkipVerification {
+ for i, installPath := range m.InstallPaths {
headersToVerify = append(headersToVerify, srcDestPair{
- src: m.srcPaths[i],
+ src: m.SrcPaths[i],
dest: installPath,
})
}
}
- installPaths = append(installPaths, m.installPaths...)
- licensePaths = append(licensePaths, m.licensePath)
+ installPaths = append(installPaths, m.InstallPaths...)
+ licensePaths = append(licensePaths, m.LicensePath)
}
- if m, ok := module.(*Module); ok {
- if installer, ok := m.installer.(*stubDecorator); ok && m.library.buildStubs() {
- installPaths = append(installPaths, installer.installPath)
+ if ccInfo, ok := android.OtherModuleProvider(ctx, module, CcInfoProvider); ok {
+ if installer := ccInfo.InstallerInfo; installer != nil && installer.StubDecoratorInfo != nil &&
+ ccInfo.LibraryInfo != nil && ccInfo.LibraryInfo.BuildStubs {
+ installPaths = append(installPaths, installer.StubDecoratorInfo.InstallPath)
}
- if library, ok := m.linker.(*libraryDecorator); ok {
- if library.ndkSysrootPath != nil {
- staticLibInstallPaths = append(
- staticLibInstallPaths, library.ndkSysrootPath)
+ if ccInfo.LinkerInfo != nil {
+ if library := ccInfo.LinkerInfo.LibraryDecoratorInfo; library != nil {
+ if library.NdkSysrootPath != nil {
+ staticLibInstallPaths = append(
+ staticLibInstallPaths, library.NdkSysrootPath)
+ }
}
- }
- if object, ok := m.linker.(*objectLinker); ok {
- if object.ndkSysrootPath != nil {
- staticLibInstallPaths = append(
- staticLibInstallPaths, object.ndkSysrootPath)
+ if object := ccInfo.LinkerInfo.ObjectLinkerInfo; object != nil {
+ if object.NdkSysrootPath != nil {
+ staticLibInstallPaths = append(
+ staticLibInstallPaths, object.NdkSysrootPath)
+ }
}
}
}
diff --git a/cc/ndk_test.go b/cc/ndk_test.go
index f20d3c6..8574bf1 100644
--- a/cc/ndk_test.go
+++ b/cc/ndk_test.go
@@ -50,7 +50,7 @@
}
`
ctx := prepareForCcTest.RunTestWithBp(t, bp)
- libfoo := ctx.ModuleForTests("libfoo.ndk", "android_arm64_armv8-a_sdk_shared")
- libfoo_headers := ctx.ModuleForTests("libfoo_headers", "")
+ libfoo := ctx.ModuleForTests(t, "libfoo.ndk", "android_arm64_armv8-a_sdk_shared")
+ libfoo_headers := ctx.ModuleForTests(t, "libfoo_headers", "")
android.AssertBoolEquals(t, "Could not find headers of ndk_library", true, isDep(ctx, libfoo.Module(), libfoo_headers.Module()))
}
diff --git a/cc/object.go b/cc/object.go
index c89520a..ea3ed61 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -159,7 +159,7 @@
// isForPlatform is terribly named and actually means isNotApex.
if Bool(object.Properties.Crt) &&
!Bool(object.Properties.Exclude_from_ndk_sysroot) && ctx.useSdk() &&
- ctx.isSdkVariant() && ctx.isForPlatform() {
+ ctx.isSdkVariant() && CtxIsForPlatform(ctx) {
output = getVersionedLibraryInstallPath(ctx,
nativeApiLevelOrPanic(ctx, ctx.sdkVersion())).Join(ctx, outputName)
@@ -242,7 +242,15 @@
return Bool(object.Properties.Crt)
}
+func (object *objectLinker) defaultDistFiles() []android.Path {
+ return nil
+}
+
func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
}
+
+func (object *objectLinker) testSuiteInfo(ctx ModuleContext) {
+ // not a test
+}
diff --git a/cc/object_test.go b/cc/object_test.go
index 004dfd3..6d82265 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -46,13 +46,13 @@
ctx := prepareForCcTest.RunTestWithBp(t, bp)
for _, v := range variants {
- cflags := ctx.ModuleForTests("crt_foo", v.variant).Rule("cc").Args["cFlags"]
+ cflags := ctx.ModuleForTests(t, "crt_foo", v.variant).Rule("cc").Args["cFlags"]
expected := "-target aarch64-linux-android" + v.num + " "
android.AssertStringDoesContain(t, "cflag", cflags, expected)
}
ctx = prepareForCcTest.RunTestWithBp(t, bp)
android.AssertStringDoesContain(t, "cflag",
- ctx.ModuleForTests("crt_foo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"],
+ ctx.ModuleForTests(t, "crt_foo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"],
"-target aarch64-linux-android10000 ")
}
@@ -69,13 +69,13 @@
// Sdk variant uses the crt object of the matching min_sdk_version
variant := "android_arm64_armv8-a_sdk"
- crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
+ crt := ctx.ModuleForTests(t, "bin", variant).Rule("ld").Args["crtBegin"]
android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
"29/crtbegin_dynamic.o")
// platform variant uses the crt object built for platform
variant = "android_arm64_armv8-a"
- crt = ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
+ crt = ctx.ModuleForTests(t, "bin", variant).Rule("ld").Args["crtBegin"]
android.AssertStringDoesContain(t, "crt dep of platform variant", crt,
variant+"/crtbegin_dynamic.o")
}
@@ -147,7 +147,7 @@
ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
android.AssertPathRelativeToTopEquals(t, "expected output file foo.o",
fmt.Sprintf("out/soong/.intermediates/%s/android_arm64_armv8-a/foo.o", testcase.moduleName),
- ctx.ModuleForTests(testcase.moduleName, "android_arm64_armv8-a").Output("foo.o").Output)
+ ctx.ModuleForTests(t, testcase.moduleName, "android_arm64_armv8-a").Output("foo.o").Output)
})
}
diff --git a/cc/orderfile.go b/cc/orderfile.go
index 6e08da7..c07a098 100644
--- a/cc/orderfile.go
+++ b/cc/orderfile.go
@@ -153,7 +153,7 @@
}
// Currently, we are not enabling orderfiles to begin from static libraries
- if ctx.static() && !ctx.staticBinary() {
+ if ctx.staticLibrary() {
return
}
diff --git a/cc/orderfile_test.go b/cc/orderfile_test.go
index 3486f96..41253ad 100644
--- a/cc/orderfile_test.go
+++ b/cc/orderfile_test.go
@@ -41,7 +41,7 @@
expectedCFlag := "-forder-file-instrumentation"
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
// Check cFlags of orderfile-enabled module
cFlags := libTest.Rule("cc").Args["cFlags"]
@@ -77,7 +77,7 @@
expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile"
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
// Check ldFlags of orderfile-enabled module
ldFlags := libTest.Rule("ld").Args["ldFlags"]
@@ -106,7 +106,7 @@
expectedCFlag := "-forder-file-instrumentation"
- test := result.ModuleForTests("test", "android_arm64_armv8-a")
+ test := result.ModuleForTests(t, "test", "android_arm64_armv8-a")
// Check cFlags of orderfile-enabled module
cFlags := test.Rule("cc").Args["cFlags"]
@@ -142,7 +142,7 @@
expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
- test := result.ModuleForTests("test", "android_arm64_armv8-a")
+ test := result.ModuleForTests(t, "test", "android_arm64_armv8-a")
// Check ldFlags of orderfile-enabled module
ldFlags := test.Rule("ld").Args["ldFlags"]
@@ -185,7 +185,7 @@
expectedCFlag := "-forder-file-instrumentation"
// Check cFlags of orderfile-enabled module
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
cFlags := libTest.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlag) {
@@ -193,8 +193,8 @@
}
// Check cFlags of orderfile variant static libraries
- libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
- libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
+ libFooOfVariant := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static_orderfile")
+ libBarOfVariant := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static_orderfile")
cFlags = libFooOfVariant.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlag) {
@@ -216,8 +216,8 @@
}
// Check cFlags of the non-orderfile variant static libraries
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
@@ -274,15 +274,15 @@
expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile"
// Check ldFlags of orderfile-enabled module
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
ldFlags := libTest.Rule("ld").Args["ldFlags"]
if !strings.Contains(ldFlags, expectedCFlag) {
t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags)
}
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
@@ -343,7 +343,7 @@
expectedCFlag := "-forder-file-instrumentation"
// Check cFlags of orderfile-enabled module
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_shared")
cFlags := libTest.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlag) {
@@ -351,8 +351,8 @@
}
// Check cFlags of the static and shared libraries
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_shared")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
@@ -423,7 +423,7 @@
expectedCFlag := "-forder-file-instrumentation"
// Check cFlags of module
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static")
+ libTest := result.ModuleForTests(t, "libTest", "android_arm64_armv8-a_static")
cFlags := libTest.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
@@ -431,8 +431,8 @@
}
// Check cFlags of the static libraries
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests(t, "libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests(t, "libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 96a07bc..70ee5e3 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -114,10 +114,10 @@
// TODO(ccross): verify shared library dependencies
srcs := p.prebuiltSrcs(ctx)
- stubInfo := addStubDependencyProviders(ctx)
+ stubInfo := AddStubDependencyProviders(ctx)
// Stub variants will create a stub .so file from stub .c files
- if p.buildStubs() && objs.objFiles != nil {
+ if p.BuildStubs() && objs.objFiles != nil {
// TODO (b/275273834): Make objs.objFiles == nil a hard error when the symbol files have been added to module sdk.
return p.linkShared(ctx, flags, deps, objs)
}
@@ -204,7 +204,7 @@
Target: ctx.Target(),
TableOfContents: p.tocFile,
- IsStubs: p.buildStubs(),
+ IsStubs: p.BuildStubs(),
})
return outputFile
@@ -268,7 +268,7 @@
}
// Implements versionedInterface
-func (p *prebuiltLibraryLinker) implementationModuleName(name string) string {
+func (p *prebuiltLibraryLinker) ImplementationModuleName(name string) string {
return android.RemoveOptionalPrebuiltPrefix(name)
}
@@ -298,7 +298,7 @@
}
func (p *prebuiltLibraryLinker) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- if p.buildStubs() && p.stubsVersion() != "" {
+ if p.BuildStubs() && p.StubsVersion() != "" {
return p.compileModuleLibApiStubs(ctx, flags, deps)
}
return Objects{}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 3214fb4..af68ca6 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -116,21 +116,21 @@
})
// Verify that all the modules exist and that their dependencies were connected correctly
- liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
- libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
- libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
- libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
- libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
- libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
- crtx := ctx.ModuleForTests("crtx", "android_arm64_armv8-a").Module()
+ liba := ctx.ModuleForTests(t, "liba", "android_arm64_armv8-a_shared").Module()
+ libb := ctx.ModuleForTests(t, "libb", "android_arm64_armv8-a_static").Module()
+ libd := ctx.ModuleForTests(t, "libd", "android_arm64_armv8-a_shared").Module()
+ libe := ctx.ModuleForTests(t, "libe", "android_arm64_armv8-a_static").Module()
+ libfStatic := ctx.ModuleForTests(t, "libf", "android_arm64_armv8-a_static").Module()
+ libfShared := ctx.ModuleForTests(t, "libf", "android_arm64_armv8-a_shared").Module()
+ crtx := ctx.ModuleForTests(t, "crtx", "android_arm64_armv8-a").Module()
- prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
- prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
- prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
- prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
- prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
- prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
- prebuiltCrtx := ctx.ModuleForTests("prebuilt_crtx", "android_arm64_armv8-a").Module()
+ prebuiltLiba := ctx.ModuleForTests(t, "prebuilt_liba", "android_arm64_armv8-a_shared").Module()
+ prebuiltLibb := ctx.ModuleForTests(t, "prebuilt_libb", "android_arm64_armv8-a_static").Module()
+ prebuiltLibd := ctx.ModuleForTests(t, "prebuilt_libd", "android_arm64_armv8-a_shared").Module()
+ prebuiltLibe := ctx.ModuleForTests(t, "prebuilt_libe", "android_arm64_armv8-a_static").Module()
+ prebuiltLibfStatic := ctx.ModuleForTests(t, "prebuilt_libf", "android_arm64_armv8-a_static").Module()
+ prebuiltLibfShared := ctx.ModuleForTests(t, "prebuilt_libf", "android_arm64_armv8-a_shared").Module()
+ prebuiltCrtx := ctx.ModuleForTests(t, "prebuilt_crtx", "android_arm64_armv8-a").Module()
hasDep := func(m android.Module, wantDep android.Module) bool {
t.Helper()
@@ -190,7 +190,7 @@
"libf.so": nil,
})
- shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
+ shared := ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
}
@@ -204,7 +204,7 @@
"libf.a": nil,
})
- static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+ static := ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().Path().Base(), "libf.a")
}
@@ -227,10 +227,10 @@
"libf.so": nil,
})
- shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
+ shared := ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().Path().Base(), "libtest.so")
- static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+ static := ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().Path().Base(), "libf.a")
}
@@ -254,10 +254,10 @@
"libfoo.so": nil,
})
- static := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
+ static := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().Path().Base(), "libfoo.a")
- shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
+ shared := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
}
@@ -275,7 +275,7 @@
"libfoo.so": nil,
})
- shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
+ shared := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
}
@@ -312,7 +312,7 @@
"foo": nil,
})
- fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
+ fooRule := ctx.ModuleForTests(t, "foo", "linux_glibc_x86_64").Rule("Symlink")
assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
@@ -355,16 +355,16 @@
// Without SANITIZE_TARGET.
ctx := testPrebuilt(t, bp, fs)
- shared_rule := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
+ shared_rule := ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
assertString(t, shared_rule.Input.String(), "libf.so")
- static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
+ static := ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().Path().Base(), "libf.a")
- shared_rule2 := ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
+ shared_rule2 := ctx.ModuleForTests(t, "libtest_shared", "android_arm64_armv8-a_shared").Rule("android/soong/cc.strip")
assertString(t, shared_rule2.Input.String(), "libf.so")
- static2 := ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
+ static2 := ctx.ModuleForTests(t, "libtest_static", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static2.OutputFile().Path().Base(), "libf.a")
// With SANITIZE_TARGET=hwaddress
@@ -374,16 +374,16 @@
}),
)
- shared_rule = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
+ shared_rule = ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
assertString(t, shared_rule.Input.String(), "hwasan/libf.so")
- static = ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
+ static = ctx.ModuleForTests(t, "libtest", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
assertString(t, static.OutputFile().Path().Base(), "libf.hwasan.a")
- shared_rule2 = ctx.ModuleForTests("libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
+ shared_rule2 = ctx.ModuleForTests(t, "libtest_shared", "android_arm64_armv8-a_shared_hwasan").Rule("android/soong/cc.strip")
assertString(t, shared_rule2.Input.String(), "hwasan/libf.so")
- static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
+ static2 = ctx.ModuleForTests(t, "libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
}
@@ -394,7 +394,7 @@
srcs: [],
}`
ctx := testPrebuilt(t, bp, map[string][]byte{})
- mod := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
+ mod := ctx.ModuleForTests(t, "bintest", "android_arm64_armv8-a").Module().(*Module)
android.AssertBoolEquals(t, `expected no srcs to yield no output file`, false, mod.OutputFile().Valid())
}
@@ -484,8 +484,8 @@
"libbar.so": nil,
"crtx.o": nil,
}, preparer)
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
- expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
+ expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
// check that LOCAL_SHARED_LIBRARIES contains libbar and not libbar.v<N>
entries := android.AndroidMkInfoForTest(t, ctx, libfoo).PrimaryInfo
@@ -493,7 +493,7 @@
// check installation rules
// the selected soong module should be exported to make
- libbar := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
+ libbar := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, fmt.Sprintf("dependency %s should be exported to make\n", expectedDependency), true, !libbar.IsHideFromMake())
// check LOCAL_MODULE of the selected module name
@@ -585,8 +585,8 @@
if tc.expectedErr != "" {
return // the fixture will assert that the excepted err has been raised
}
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
- expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
+ expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
}
}
@@ -638,8 +638,8 @@
"libbar.so": nil,
"crtx.o": nil,
}, preparer)
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
- sourceLibBar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module()
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module()
+ sourceLibBar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_static").Module()
// Even though the prebuilt is listed in apex_contributions, the prebuilt does not have a static variant.
// Therefore source of libbar should be used.
android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from libfoo to source libbar"), true, hasDep(ctx, libfoo, sourceLibBar))
diff --git a/cc/proto_test.go b/cc/proto_test.go
index a905ea8..47b7e17 100644
--- a/cc/proto_test.go
+++ b/cc/proto_test.go
@@ -29,7 +29,7 @@
srcs: ["a.proto"],
}`)
- proto := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Output("proto/a.pb.cc")
+ proto := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Output("proto/a.pb.cc")
if cmd := proto.RuleParams.Command; !strings.Contains(cmd, "--cpp_out=") {
t.Errorf("expected '--cpp_out' in %q", cmd)
@@ -53,8 +53,8 @@
buildOS := ctx.Config().BuildOS.String()
- proto := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Output("proto/a.pb.cc")
- foobar := ctx.ModuleForTests("protoc-gen-foobar", buildOS+"_x86_64")
+ proto := ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_shared").Output("proto/a.pb.cc")
+ foobar := ctx.ModuleForTests(t, "protoc-gen-foobar", buildOS+"_x86_64")
cmd := proto.RuleParams.Command
if w := "--foobar_out="; !strings.Contains(cmd, w) {
@@ -85,8 +85,8 @@
buildOS := ctx.Config().BuildOS.String()
- proto := ctx.ModuleForTests("libgrpc", "android_arm_armv7-a-neon_shared").Output("proto/a.grpc.pb.cc")
- grpcCppPlugin := ctx.ModuleForTests("protoc-gen-grpc-cpp-plugin", buildOS+"_x86_64")
+ proto := ctx.ModuleForTests(t, "libgrpc", "android_arm_armv7-a-neon_shared").Output("proto/a.grpc.pb.cc")
+ grpcCppPlugin := ctx.ModuleForTests(t, "protoc-gen-grpc-cpp-plugin", buildOS+"_x86_64")
cmd := proto.RuleParams.Command
if w := "--grpc-cpp-plugin_out="; !strings.Contains(cmd, w) {
diff --git a/cc/sabi.go b/cc/sabi.go
index bc61b6c..06ab6ec 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -137,7 +137,7 @@
if m.isImplementationForLLNDKPublic() {
result = append(result, llndkLsdumpTag)
}
- if m.library.hasStubsVariants() {
+ if m.library.HasStubsVariants() {
result = append(result, apexLsdumpTag)
}
if headerAbiChecker.enabled() {
diff --git a/cc/sabi_test.go b/cc/sabi_test.go
index 6b8cc17..3d2a98c 100644
--- a/cc/sabi_test.go
+++ b/cc/sabi_test.go
@@ -48,16 +48,16 @@
PrepareForTestWithCcDefaultModules,
).RunTestWithBp(t, bp)
- libsabiStatic := result.ModuleForTests("libsabi", "android_arm64_armv8-a_static_sabi")
+ libsabiStatic := result.ModuleForTests(t, "libsabi", "android_arm64_armv8-a_static_sabi")
sabiObjSDump := libsabiStatic.Output("obj/sabi.sdump")
- libDirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static_sabi")
+ libDirect := result.ModuleForTests(t, "libdirect", "android_arm64_armv8-a_static_sabi")
directObjSDump := libDirect.Output("obj/direct.sdump")
- libTransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static_sabi")
+ libTransitive := result.ModuleForTests(t, "libtransitive", "android_arm64_armv8-a_static_sabi")
transitiveObjSDump := libTransitive.Output("obj/transitive.sdump")
- libsabiShared := result.ModuleForTests("libsabi", "android_arm64_armv8-a_shared")
+ libsabiShared := result.ModuleForTests(t, "libsabi", "android_arm64_armv8-a_shared")
sabiLink := libsabiShared.Rule("sAbiLink")
android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), sabiObjSDump.Output.String())
diff --git a/cc/sanitize.go b/cc/sanitize.go
index d8d8c7a..f0b0308 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -79,7 +79,7 @@
minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined"}
- memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
+ memtagStackCommonFlags = []string{"-Xclang -target-feature -Xclang +mte"}
memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
@@ -1422,6 +1422,7 @@
sanitizers = append(sanitizers,
"bool",
"integer-divide-by-zero",
+ "object-size",
"return",
"returns-nonnull-attribute",
"shift-exponent",
@@ -1438,10 +1439,6 @@
//"shift-base",
//"signed-integer-overflow",
)
-
- if mctx.Config().ReleaseBuildObjectSizeSanitizer() {
- sanitizers = append(sanitizers, "object-size")
- }
}
sanitizers = append(sanitizers, sanProps.Misc_undefined...)
}
@@ -1901,6 +1898,8 @@
ctx.SetOutputFiles(android.Paths{outputFile}, "")
txt.outputFile = outputFile
+
+ etc.SetCommonPrebuiltEtcInfo(ctx, txt)
}
func (txt *sanitizerLibrariesTxtModule) PrepareAndroidMKProviderInfo(config android.Config) *android.AndroidMkProviderInfo {
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index a1cfb5c..543e808 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -222,31 +222,31 @@
staticAsanVariant := staticVariant + "_asan"
// The binaries, one with asan and one without
- binWithAsan := result.ModuleForTests("bin_with_asan", asanVariant)
- binNoAsan := result.ModuleForTests("bin_no_asan", variant)
+ binWithAsan := result.ModuleForTests(t, "bin_with_asan", asanVariant)
+ binNoAsan := result.ModuleForTests(t, "bin_no_asan", variant)
// Shared libraries that don't request asan
- libShared := result.ModuleForTests("libshared", sharedVariant)
- libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
+ libShared := result.ModuleForTests(t, "libshared", sharedVariant)
+ libTransitive := result.ModuleForTests(t, "libtransitive", sharedVariant)
// Shared library that requests asan
- libAsan := result.ModuleForTests("libasan", sharedAsanVariant)
+ libAsan := result.ModuleForTests(t, "libasan", sharedAsanVariant)
// Static library that uses an asan variant for bin_with_asan and a non-asan variant
// for bin_no_asan.
- libStaticAsanVariant := result.ModuleForTests("libstatic", staticAsanVariant)
- libStaticNoAsanVariant := result.ModuleForTests("libstatic", staticVariant)
+ libStaticAsanVariant := result.ModuleForTests(t, "libstatic", staticAsanVariant)
+ libStaticNoAsanVariant := result.ModuleForTests(t, "libstatic", staticVariant)
// Static library that never uses asan.
- libNoAsan := result.ModuleForTests("libnoasan", staticVariant)
+ libNoAsan := result.ModuleForTests(t, "libnoasan", staticVariant)
// Static library that specifies asan
- libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
- libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
+ libStaticAsan := result.ModuleForTests(t, "libstatic_asan", staticAsanVariant)
+ libStaticAsanNoAsanVariant := result.ModuleForTests(t, "libstatic_asan", staticVariant)
- libAsanSharedRuntime := result.ModuleForTests("libclang_rt.asan", sharedVariant)
- libAsanStaticRuntime := result.ModuleForTests("libclang_rt.asan.static", staticVariant)
- libAsanStaticCxxRuntime := result.ModuleForTests("libclang_rt.asan_cxx.static", staticVariant)
+ libAsanSharedRuntime := result.ModuleForTests(t, "libclang_rt.asan", sharedVariant)
+ libAsanStaticRuntime := result.ModuleForTests(t, "libclang_rt.asan.static", staticVariant)
+ libAsanStaticCxxRuntime := result.ModuleForTests(t, "libclang_rt.asan_cxx.static", staticVariant)
expectSharedLinkDep(t, ctx, binWithAsan, libShared)
expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
@@ -386,15 +386,15 @@
sharedTsanVariant := sharedVariant + "_tsan"
// The binaries, one with tsan and one without
- binWithTsan := result.ModuleForTests("bin_with_tsan", tsanVariant)
- binNoTsan := result.ModuleForTests("bin_no_tsan", variant)
+ binWithTsan := result.ModuleForTests(t, "bin_with_tsan", tsanVariant)
+ binNoTsan := result.ModuleForTests(t, "bin_no_tsan", variant)
// Shared libraries that don't request tsan
- libShared := result.ModuleForTests("libshared", sharedVariant)
- libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
+ libShared := result.ModuleForTests(t, "libshared", sharedVariant)
+ libTransitive := result.ModuleForTests(t, "libtransitive", sharedVariant)
// Shared library that requests tsan
- libTsan := result.ModuleForTests("libtsan", sharedTsanVariant)
+ libTsan := result.ModuleForTests(t, "libtsan", sharedTsanVariant)
expectSharedLinkDep(t, ctx, binWithTsan, libShared)
expectSharedLinkDep(t, ctx, binWithTsan, libTsan)
@@ -479,16 +479,16 @@
staticVariant := variant + "_static"
// The binaries, one with ubsan and one without
- binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant)
- binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant)
+ binWithUbsan := result.ModuleForTests(t, "bin_with_ubsan", variant)
+ binNoUbsan := result.ModuleForTests(t, "bin_no_ubsan", variant)
// Static libraries that don't request ubsan
- libStatic := result.ModuleForTests("libstatic", staticVariant)
- libTransitive := result.ModuleForTests("libtransitive", staticVariant)
+ libStatic := result.ModuleForTests(t, "libstatic", staticVariant)
+ libTransitive := result.ModuleForTests(t, "libtransitive", staticVariant)
- libUbsan := result.ModuleForTests("libubsan", staticVariant)
+ libUbsan := result.ModuleForTests(t, "libubsan", staticVariant)
- libUbsanMinimal := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant)
+ libUbsanMinimal := result.ModuleForTests(t, "libclang_rt.ubsan_minimal", staticVariant)
expectStaticLinkDep(t, ctx, binWithUbsan, libStatic)
expectStaticLinkDep(t, ctx, binWithUbsan, libUbsan)
@@ -610,31 +610,31 @@
staticFuzzerVariant := staticVariant + "_fuzzer"
// The binaries, one with fuzzer and one without
- binWithFuzzer := result.ModuleForTests("bin_with_fuzzer", fuzzerVariant)
- binNoFuzzer := result.ModuleForTests("bin_no_fuzzer", variant)
+ binWithFuzzer := result.ModuleForTests(t, "bin_with_fuzzer", fuzzerVariant)
+ binNoFuzzer := result.ModuleForTests(t, "bin_no_fuzzer", variant)
// Shared libraries that don't request fuzzer
- libShared := result.ModuleForTests("libshared", sharedVariant)
- libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
+ libShared := result.ModuleForTests(t, "libshared", sharedVariant)
+ libTransitive := result.ModuleForTests(t, "libtransitive", sharedVariant)
// Shared libraries that don't request fuzzer
- libSharedFuzzer := result.ModuleForTests("libshared", sharedFuzzerVariant)
- libTransitiveFuzzer := result.ModuleForTests("libtransitive", sharedFuzzerVariant)
+ libSharedFuzzer := result.ModuleForTests(t, "libshared", sharedFuzzerVariant)
+ libTransitiveFuzzer := result.ModuleForTests(t, "libtransitive", sharedFuzzerVariant)
// Shared library that requests fuzzer
- libFuzzer := result.ModuleForTests("libfuzzer", sharedFuzzerVariant)
+ libFuzzer := result.ModuleForTests(t, "libfuzzer", sharedFuzzerVariant)
// Static library that uses an fuzzer variant for bin_with_fuzzer and a non-fuzzer variant
// for bin_no_fuzzer.
- libStaticFuzzerVariant := result.ModuleForTests("libstatic", staticFuzzerVariant)
- libStaticNoFuzzerVariant := result.ModuleForTests("libstatic", staticVariant)
+ libStaticFuzzerVariant := result.ModuleForTests(t, "libstatic", staticFuzzerVariant)
+ libStaticNoFuzzerVariant := result.ModuleForTests(t, "libstatic", staticVariant)
// Static library that never uses fuzzer.
- libNoFuzzer := result.ModuleForTests("libnofuzzer", staticVariant)
+ libNoFuzzer := result.ModuleForTests(t, "libnofuzzer", staticVariant)
// Static library that specifies fuzzer
- libStaticFuzzer := result.ModuleForTests("libstatic_fuzzer", staticFuzzerVariant)
- libStaticFuzzerNoFuzzerVariant := result.ModuleForTests("libstatic_fuzzer", staticVariant)
+ libStaticFuzzer := result.ModuleForTests(t, "libstatic_fuzzer", staticFuzzerVariant)
+ libStaticFuzzerNoFuzzerVariant := result.ModuleForTests(t, "libstatic_fuzzer", staticVariant)
expectSharedLinkDep(t, ctx, binWithFuzzer, libSharedFuzzer)
expectSharedLinkDep(t, ctx, binWithFuzzer, libFuzzer)
@@ -781,16 +781,16 @@
staticVariant := variant + "_static"
sharedVariant := variant + "_shared"
- minimalRuntime := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant)
- standaloneRuntime := result.ModuleForTests("libclang_rt.ubsan_standalone.static", staticVariant)
+ minimalRuntime := result.ModuleForTests(t, "libclang_rt.ubsan_minimal", staticVariant)
+ standaloneRuntime := result.ModuleForTests(t, "libclang_rt.ubsan_standalone.static", staticVariant)
// The binaries, one with ubsan and one without
- binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant)
- binDependsUbsan := result.ModuleForTests("bin_depends_ubsan_static", variant)
- libSharedUbsan := result.ModuleForTests("libsharedubsan", sharedVariant)
- binDependsUbsanShared := result.ModuleForTests("bin_depends_ubsan_shared", variant)
- binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant)
- staticBin := result.ModuleForTests("static_bin_with_ubsan_dep", variant)
+ binWithUbsan := result.ModuleForTests(t, "bin_with_ubsan", variant)
+ binDependsUbsan := result.ModuleForTests(t, "bin_depends_ubsan_static", variant)
+ libSharedUbsan := result.ModuleForTests(t, "libsharedubsan", sharedVariant)
+ binDependsUbsanShared := result.ModuleForTests(t, "bin_depends_ubsan_shared", variant)
+ binNoUbsan := result.ModuleForTests(t, "bin_no_ubsan", variant)
+ staticBin := result.ModuleForTests(t, "static_bin_with_ubsan_dep", variant)
android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_with_ubsan static libs",
strings.Split(binWithUbsan.Rule("ld").Args["libFlags"], " "),
@@ -979,67 +979,67 @@
).RunTest(t)
ctx := result.TestContext
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}
func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
@@ -1055,66 +1055,66 @@
).RunTest(t)
ctx := result.TestContext
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}
func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
@@ -1131,66 +1131,66 @@
).RunTest(t)
ctx := result.TestContext
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}
func TestCfi(t *testing.T) {
@@ -1250,14 +1250,14 @@
cfi_suffix := "_cfi"
static_suffix := "_static"
- sharedWithCfiLib := result.ModuleForTests("shared_with_cfi", buildOs+shared_suffix+cfi_suffix)
- sharedNoCfiLib := result.ModuleForTests("shared_no_cfi", buildOs+shared_suffix)
- staticWithCfiLib := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix)
- staticWithCfiLibCfiVariant := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix+cfi_suffix)
- staticNoCfiLib := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix)
- staticNoCfiLibCfiVariant := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix+cfi_suffix)
- sharedRdepNoCfi := result.ModuleForTests("shared_rdep_no_cfi", buildOs+shared_suffix)
- staticDepWithCfi2Lib := result.ModuleForTests("static_dep_with_cfi_2", buildOs+static_suffix)
+ sharedWithCfiLib := result.ModuleForTests(t, "shared_with_cfi", buildOs+shared_suffix+cfi_suffix)
+ sharedNoCfiLib := result.ModuleForTests(t, "shared_no_cfi", buildOs+shared_suffix)
+ staticWithCfiLib := result.ModuleForTests(t, "static_dep_with_cfi", buildOs+static_suffix)
+ staticWithCfiLibCfiVariant := result.ModuleForTests(t, "static_dep_with_cfi", buildOs+static_suffix+cfi_suffix)
+ staticNoCfiLib := result.ModuleForTests(t, "static_dep_no_cfi", buildOs+static_suffix)
+ staticNoCfiLibCfiVariant := result.ModuleForTests(t, "static_dep_no_cfi", buildOs+static_suffix+cfi_suffix)
+ sharedRdepNoCfi := result.ModuleForTests(t, "shared_rdep_no_cfi", buildOs+shared_suffix)
+ staticDepWithCfi2Lib := result.ModuleForTests(t, "static_dep_with_cfi_2", buildOs+static_suffix)
// Confirm assumptions about propagation of CFI enablement
expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticWithCfiLibCfiVariant)
diff --git a/cc/sdk_test.go b/cc/sdk_test.go
index 61925e3..664a7c6 100644
--- a/cc/sdk_test.go
+++ b/cc/sdk_test.go
@@ -81,16 +81,16 @@
ctx := testCc(t, bp)
- libsdkNDK := ctx.ModuleForTests("libsdk", "android_arm64_armv8-a_sdk_shared")
- libsdkPlatform := ctx.ModuleForTests("libsdk", "android_arm64_armv8-a_shared")
- libsdkdepNDK := ctx.ModuleForTests("libsdkdep", "android_arm64_armv8-a_sdk_shared")
- libsdkdepPlatform := ctx.ModuleForTests("libsdkdep", "android_arm64_armv8-a_shared")
- libplatform := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared")
- platformbinary := ctx.ModuleForTests("platformbinary", "android_arm64_armv8-a")
- sdkbinary := ctx.ModuleForTests("sdkbinary", "android_arm64_armv8-a_sdk")
+ libsdkNDK := ctx.ModuleForTests(t, "libsdk", "android_arm64_armv8-a_sdk_shared")
+ libsdkPlatform := ctx.ModuleForTests(t, "libsdk", "android_arm64_armv8-a_shared")
+ libsdkdepNDK := ctx.ModuleForTests(t, "libsdkdep", "android_arm64_armv8-a_sdk_shared")
+ libsdkdepPlatform := ctx.ModuleForTests(t, "libsdkdep", "android_arm64_armv8-a_shared")
+ libplatform := ctx.ModuleForTests(t, "libplatform", "android_arm64_armv8-a_shared")
+ platformbinary := ctx.ModuleForTests(t, "platformbinary", "android_arm64_armv8-a")
+ sdkbinary := ctx.ModuleForTests(t, "sdkbinary", "android_arm64_armv8-a_sdk")
- libcxxNDK := ctx.ModuleForTests("ndk_libc++_shared", "android_arm64_armv8-a_sdk_shared")
- libcxxPlatform := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared")
+ libcxxNDK := ctx.ModuleForTests(t, "ndk_libc++_shared", "android_arm64_armv8-a_sdk_shared")
+ libcxxPlatform := ctx.ModuleForTests(t, "libc++", "android_arm64_armv8-a_shared")
assertDep(t, libsdkNDK, libsdkdepNDK)
assertDep(t, libsdkPlatform, libsdkdepPlatform)
diff --git a/cc/strip.go b/cc/strip.go
index b1f34bb..42c9137 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -23,7 +23,6 @@
// StripProperties defines the type of stripping applied to the module.
type StripProperties struct {
Strip struct {
- // none forces all stripping to be disabled.
// Device modules default to stripping enabled leaving mini debuginfo.
// Host modules default to stripping disabled, but can be enabled by setting any other
// strip boolean property.
@@ -52,7 +51,8 @@
// NeedsStrip determines if stripping is required for a module.
func (stripper *Stripper) NeedsStrip(actx android.ModuleContext) bool {
forceDisable := Bool(stripper.StripProperties.Strip.None)
- defaultEnable := (!actx.Config().KatiEnabled() || actx.Device())
+ // Strip is enabled by default for device variants.
+ defaultEnable := actx.Device() || actx.Config().StripByDefault()
forceEnable := Bool(stripper.StripProperties.Strip.All) ||
Bool(stripper.StripProperties.Strip.Keep_symbols) ||
Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame)
diff --git a/cc/stub_library.go b/cc/stub_library.go
index e746a33..21ef139 100644
--- a/cc/stub_library.go
+++ b/cc/stub_library.go
@@ -26,22 +26,26 @@
android.RegisterParallelSingletonType("stublibraries", stubLibrariesSingleton)
}
+func stubLibrariesSingleton() android.Singleton {
+ return &stubLibraries{}
+}
+
type stubLibraries struct {
- stubLibraryMap map[string]bool
- stubVendorLibraryMap map[string]bool
+ stubLibraries []string
+ vendorStubLibraries []string
apiListCoverageXmlPaths []string
}
// Check if the module defines stub, or itself is stub
-func IsStubTarget(m *Module) bool {
- return m.IsStubs() || m.HasStubsVariants()
+func IsStubTarget(info *LinkableInfo) bool {
+ return info != nil && (info.IsStubs || info.HasStubsVariants)
}
// Get target file name to be installed from this module
-func getInstalledFileName(ctx android.SingletonContext, m *Module) string {
+func getInstalledFileName(ctx android.SingletonContext, m android.ModuleProxy) string {
for _, ps := range android.OtherModuleProviderOrDefault(
- ctx, m.Module(), android.InstallFilesProvider).PackagingSpecs {
+ ctx, m, android.InstallFilesProvider).PackagingSpecs {
if name := ps.FileName(); name != "" {
return name
}
@@ -51,36 +55,39 @@
func (s *stubLibraries) GenerateBuildActions(ctx android.SingletonContext) {
// Visit all generated soong modules and store stub library file names.
- ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(*Module); ok {
- if IsStubTarget(m) {
- if name := getInstalledFileName(ctx, m); name != "" {
- s.stubLibraryMap[name] = true
- if m.InVendor() {
- s.stubVendorLibraryMap[name] = true
+ stubLibraryMap := make(map[string]bool)
+ vendorStubLibraryMap := make(map[string]bool)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if linkableInfo, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok {
+ if IsStubTarget(linkableInfo) {
+ if name := getInstalledFileName(ctx, module); name != "" {
+ stubLibraryMap[name] = true
+ if linkableInfo.InVendor {
+ vendorStubLibraryMap[name] = true
}
}
}
- if m.library != nil && android.IsModulePreferred(m) {
- if p := m.library.getAPIListCoverageXMLPath().String(); p != "" {
+ if linkableInfo.CcLibraryInterface && android.IsModulePreferredProxy(ctx, module) {
+ if p := linkableInfo.APIListCoverageXMLPath.String(); p != "" {
s.apiListCoverageXmlPaths = append(s.apiListCoverageXmlPaths, p)
}
}
}
})
+ s.stubLibraries = android.SortedKeys(stubLibraryMap)
+ s.vendorStubLibraries = android.SortedKeys(vendorStubLibraryMap)
+
+ android.WriteFileRule(ctx, StubLibrariesFile(ctx), strings.Join(s.stubLibraries, " "))
}
-func stubLibrariesSingleton() android.Singleton {
- return &stubLibraries{
- stubLibraryMap: make(map[string]bool),
- stubVendorLibraryMap: make(map[string]bool),
- }
+func StubLibrariesFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForIntermediates(ctx, "stub_libraries.txt")
}
func (s *stubLibraries) MakeVars(ctx android.MakeVarsContext) {
// Convert stub library file names into Makefile variable.
- ctx.Strict("STUB_LIBRARIES", strings.Join(android.SortedKeys(s.stubLibraryMap), " "))
- ctx.Strict("SOONG_STUB_VENDOR_LIBRARIES", strings.Join(android.SortedKeys(s.stubVendorLibraryMap), " "))
+ ctx.Strict("STUB_LIBRARIES", strings.Join(s.stubLibraries, " "))
+ ctx.Strict("SOONG_STUB_VENDOR_LIBRARIES", strings.Join(s.vendorStubLibraries, " "))
// Export the list of API XML files to Make.
sort.Strings(s.apiListCoverageXmlPaths)
diff --git a/cc/test.go b/cc/test.go
index ae73886..9c276b8 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -18,6 +18,7 @@
"path/filepath"
"strconv"
+ "github.com/google/blueprint/depset"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -29,8 +30,8 @@
// if set, build against the gtest library. Defaults to true.
Gtest *bool
- // if set, use the isolated gtest runner. Defaults to true if gtest is also true and the arch is Windows, false
- // otherwise.
+ // if set, use the isolated gtest runner. Defaults to false.
+ // Isolation is not supported on Windows.
Isolated *bool
}
@@ -83,16 +84,21 @@
// the test
Data []string `android:"path,arch_variant"`
- // Same as data, but adds depedencies on modules using the device's os variant, and common
+ // Same as data, but adds dependencies on modules using the device's os variant, and common
// architecture's variant. Can be useful to add device-built apps to the data of a host
// test.
Device_common_data []string `android:"path_device_common"`
- // Same as data, but adds depedencies on modules using the device's os variant, and the device's
- // first architecture's variant. Can be useful to add device-built apps to the data of a host
- // test.
+ // Same as data, but adds dependencies on modules using the device's os variant, and the
+ // device's first architecture's variant. Can be useful to add device-built apps to the data
+ // of a host test.
Device_first_data []string `android:"path_device_first"`
+ // Same as data, but will add dependencies on modules using the host's os variation and
+ // the common arch variation. Useful for a device test that wants to depend on a host
+ // module, for example to include a custom Tradefed test runner.
+ Host_common_data []string `android:"path_host_common"`
+
// list of shared library modules that should be installed alongside the test
Data_libs []string `android:"arch_variant"`
@@ -128,6 +134,13 @@
// Install the test into a folder named for the module in all test suites.
Per_testcase_directory *bool
+
+ // Install the test's dependencies into a folder named standalone-libs relative to the
+ // test's installation path. ld-library-path will be set to this path in the test's
+ // auto-generated config. This way the dependencies can be used by the test without having
+ // to manually install them to the device. See more details in
+ // go/standalone-native-device-tests.
+ Standalone_test *bool
}
func init() {
@@ -198,8 +211,8 @@
return BoolDefault(test.LinkerProperties.Gtest, true)
}
-func (test *testDecorator) isolated(ctx android.EarlyModuleContext) bool {
- return BoolDefault(test.LinkerProperties.Isolated, false)
+func (test *testDecorator) isolated(ctx android.BaseModuleContext) bool {
+ return BoolDefault(test.LinkerProperties.Isolated, false) && !ctx.Windows()
}
// NOTE: Keep this in sync with cc/cc_test.bzl#gtest_copts
@@ -261,6 +274,12 @@
}
}
+func (test *testDecorator) testSuiteInfo(ctx ModuleContext) {
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: test.InstallerProperties.Test_suites,
+ })
+}
+
func NewTestInstaller() *baseInstaller {
return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
}
@@ -329,6 +348,10 @@
}
+func (test *testBinary) testSuiteInfo(ctx ModuleContext) {
+ test.testDecorator.testSuiteInfo(ctx)
+}
+
func (test *testBinary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -337,33 +360,34 @@
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...)
dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_first_data)...)
+ dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...)
for _, dataSrcPath := range dataSrcPaths {
test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
}
- ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataLibDepTag, func(dep android.ModuleProxy) {
depName := ctx.OtherModuleName(dep)
- linkableDep, ok := dep.(LinkableInterface)
+ linkableDep, ok := android.OtherModuleProvider(ctx, dep, LinkableInfoProvider)
if !ok {
ctx.ModuleErrorf("data_lib %q is not a LinkableInterface module", depName)
}
- if linkableDep.OutputFile().Valid() {
+ if linkableDep.OutputFile.Valid() {
test.data = append(test.data,
- android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
- RelativeInstallPath: linkableDep.RelativeInstallPath()})
+ android.DataPath{SrcPath: linkableDep.OutputFile.Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath})
}
})
- ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataBinDepTag, func(dep android.ModuleProxy) {
depName := ctx.OtherModuleName(dep)
- linkableDep, ok := dep.(LinkableInterface)
+ linkableDep, ok := android.OtherModuleProvider(ctx, dep, LinkableInfoProvider)
if !ok {
ctx.ModuleErrorf("data_bin %q is not a LinkableInterface module", depName)
}
- if linkableDep.OutputFile().Valid() {
+ if linkableDep.OutputFile.Valid() {
test.data = append(test.data,
- android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
- RelativeInstallPath: linkableDep.RelativeInstallPath()})
+ android.DataPath{SrcPath: linkableDep.OutputFile.Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath})
}
})
@@ -380,6 +404,7 @@
TestInstallBase: testInstallBase,
DeviceTemplate: "${NativeTestConfigTemplate}",
HostTemplate: "${NativeHostTestConfigTemplate}",
+ StandaloneTest: test.Properties.Standalone_test,
})
test.extraTestConfigs = android.PathsForModuleSrc(ctx, test.Properties.Test_options.Extra_test_configs)
@@ -397,8 +422,55 @@
test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
}
+ if !ctx.Config().KatiEnabled() { // TODO(spandandas): Remove the special case for kati
+ // Install the test config in testcases/ directory for atest.
+ c, ok := ctx.Module().(*Module)
+ if !ok {
+ ctx.ModuleErrorf("Not a cc_test module")
+ }
+ // Install configs in the root of $PRODUCT_OUT/testcases/$module
+ testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName()+c.SubName())
+ if ctx.PrimaryArch() {
+ if test.testConfig != nil {
+ ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
+ }
+ dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+ }
+ for _, extraTestConfig := range test.extraTestConfigs {
+ ctx.InstallFile(testCases, extraTestConfig.Base(), extraTestConfig)
+ }
+ }
+ // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
+ testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
+ ctx.InstallTestData(testCases, test.data)
+ ctx.InstallFile(testCases, file.Base(), file)
+ }
+
test.binaryDecorator.baseInstaller.installTestData(ctx, test.data)
test.binaryDecorator.baseInstaller.install(ctx, file)
+ if Bool(test.Properties.Standalone_test) {
+ packagingSpecsBuilder := depset.NewBuilder[android.PackagingSpec](depset.TOPOLOGICAL)
+
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ deps := android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider)
+ packagingSpecsBuilder.Transitive(deps.TransitivePackagingSpecs)
+ })
+
+ for _, standaloneTestDep := range packagingSpecsBuilder.Build().ToList() {
+ if standaloneTestDep.ToGob().SrcPath == nil {
+ continue
+ }
+ if standaloneTestDep.SkipInstall() {
+ continue
+ }
+ if standaloneTestDep.Partition() == "data" {
+ continue
+ }
+ test.binaryDecorator.baseInstaller.installStandaloneTestDep(ctx, standaloneTestDep)
+ }
+ }
}
func getTestInstallBase(useVendor bool) string {
@@ -516,6 +588,10 @@
test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
}
+func (test *testLibrary) testSuiteInfo(ctx ModuleContext) {
+ test.testDecorator.testSuiteInfo(ctx)
+}
+
func (test *testLibrary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -633,6 +709,12 @@
}
}
+func (benchmark *benchmarkDecorator) testSuiteInfo(ctx ModuleContext) {
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: benchmark.Properties.Test_suites,
+ })
+}
+
func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
module, binary := newBinary(hod)
module.multilib = android.MultilibBoth
diff --git a/cc/test_data_test.go b/cc/test_data_test.go
index a621166..2c03ca4 100644
--- a/cc/test_data_test.go
+++ b/cc/test_data_test.go
@@ -132,7 +132,7 @@
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- foo := ctx.ModuleForTests("foo", "")
+ foo := ctx.ModuleForTests(t, "foo", "")
got := foo.Module().(*testDataTest).data
if len(got) != len(test.data) {
diff --git a/cc/testing.go b/cc/testing.go
index 14a6b7a..69ae11d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -193,7 +193,7 @@
},
apex_available: [
"//apex_available:platform",
- "myapex"
+ "//apex_available:anyapex",
],
llndk: {
symbol_file: "libm.map.txt",
@@ -253,7 +253,7 @@
},
apex_available: [
"//apex_available:platform",
- "myapex"
+ "//apex_available:anyapex",
],
llndk: {
symbol_file: "libdl.map.txt",
@@ -708,7 +708,7 @@
func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
t.Helper()
- mod := ctx.ModuleForTests(moduleName, variant)
+ mod := ctx.ModuleForTests(t, moduleName, variant)
outputFiles := mod.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Errorf("%q must have single output\n", moduleName)
@@ -750,9 +750,10 @@
checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
}
-func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
+func GetOutputPaths(t *testing.T, ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
+ t.Helper()
for _, moduleName := range moduleNames {
- module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
+ module := ctx.ModuleForTests(t, moduleName, variant).Module().(*Module)
output := module.outputFile.Path().RelativeToTop()
paths = append(paths, output)
}
diff --git a/cc/tidy.go b/cc/tidy.go
index 6481b95..bf273e9 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -211,7 +211,7 @@
type tidyPhonySingleton struct{}
// Given a final module, add its tidy/obj phony targets to tidy/objModulesInDirGroup.
-func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Module,
+func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.ModuleProxy,
tidyModulesInDirGroup, objModulesInDirGroup map[string]map[string]android.Paths) {
allObjFileGroups := make(map[string]android.Paths) // variant group name => obj file Paths
allTidyFileGroups := make(map[string]android.Paths) // variant group name => tidy file Paths
@@ -220,10 +220,10 @@
// (1) Collect all obj/tidy files into OS-specific groups.
ctx.VisitAllModuleVariantProxies(module, func(variant android.ModuleProxy) {
- osName := android.OtherModuleProviderOrDefault(ctx, variant, android.CommonModuleInfoKey).CompileTarget.Os.Name
+ osName := android.OtherModulePointerProviderOrDefault(ctx, variant, android.CommonModuleInfoProvider).Target.Os.Name
info := android.OtherModuleProviderOrDefault(ctx, variant, CcObjectInfoProvider)
- addToOSGroup(osName, info.objFiles, allObjFileGroups, subsetObjFileGroups)
- addToOSGroup(osName, info.tidyFiles, allTidyFileGroups, subsetTidyFileGroups)
+ addToOSGroup(osName, info.ObjFiles, allObjFileGroups, subsetObjFileGroups)
+ addToOSGroup(osName, info.TidyFiles, allTidyFileGroups, subsetTidyFileGroups)
})
// (2) Add an all-OS group, with "" or "subset" name, to include all os-specific phony targets.
@@ -253,7 +253,7 @@
objModulesInDirGroup := make(map[string]map[string]android.Paths)
// Collect tidy/obj targets from the 'final' modules.
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
if ctx.IsFinalModule(module) {
collectTidyObjModuleTargets(ctx, module, tidyModulesInDirGroup, objModulesInDirGroup)
}
@@ -268,7 +268,7 @@
}
// The name for an obj/tidy module variant group phony target is Name_group-obj/tidy,
-func objTidyModuleGroupName(module android.Module, group string, suffix string) string {
+func objTidyModuleGroupName(module android.ModuleProxy, group string, suffix string) string {
if group == "" {
return module.Name() + "-" + suffix
}
@@ -327,7 +327,7 @@
}
// Add an all-OS group, with groupName, to include all os-specific phony targets.
-func addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) {
+func addAllOSGroup(ctx android.SingletonContext, module android.ModuleProxy, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) {
if len(phonyTargetGroups) > 0 {
var targets android.Paths
for group, _ := range phonyTargetGroups {
@@ -338,7 +338,7 @@
}
// Create one phony targets for each group and add them to the targetGroups.
-func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.Module, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) {
+func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.ModuleProxy, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) {
for group, files := range fileGroups {
groupName := objTidyModuleGroupName(module, group, objTidyName)
ctx.Phony(groupName, files...)
diff --git a/cc/tidy_test.go b/cc/tidy_test.go
index 9481778..afc12b8 100644
--- a/cc/tidy_test.go
+++ b/cc/tidy_test.go
@@ -83,7 +83,7 @@
variant := "android_arm64_armv8-a_shared"
ctx := testCc(t, test.bp)
t.Run("caseTidyFlags", func(t *testing.T) {
- flags := ctx.ModuleForTests(test.libName, variant).Rule("clangTidy").Args["tidyFlags"]
+ flags := ctx.ModuleForTests(t, test.libName, variant).Rule("clangTidy").Args["tidyFlags"]
for _, flag := range test.flags {
if !strings.Contains(flags, flag) {
t.Errorf("tidyFlags %v for %s does not contain %s.", flags, test.libName, flag)
@@ -143,7 +143,7 @@
variant := "android_arm64_armv8-a_shared"
for _, test := range testCases {
libName := fmt.Sprintf("libfoo_%d", test.libNumber)
- flags := ctx.ModuleForTests(libName, variant).Rule("clangTidy").Args["tidyFlags"]
+ flags := ctx.ModuleForTests(t, libName, variant).Rule("clangTidy").Args["tidyFlags"]
splitFlags := strings.Split(flags, " ")
foundCheckFlag := false
for _, flag := range splitFlags {
@@ -231,7 +231,7 @@
checkLibraryRule := func(foo, variant, ruleName string) {
libName := fmt.Sprintf("lib%s_%d", foo, n)
tidyFile := "out/soong/.intermediates/" + libName + "/" + variant + "/obj/" + foo + ".tidy"
- depFiles := ctx.ModuleForTests(libName, variant).Rule(ruleName).Validations.Strings()
+ depFiles := ctx.ModuleForTests(t, libName, variant).Rule(ruleName).Validations.Strings()
if test.needTidyFile[n] {
android.AssertStringListContains(t, libName+" needs .tidy file", depFiles, tidyFile)
} else {
@@ -262,7 +262,7 @@
ctx := android.GroupFixturePreparers(prepareForCcTest, android.FixtureMergeEnv(testEnv)).RunTestWithBp(t, bp)
t.Run("tidy should be only run for source code, not for generated code", func(t *testing.T) {
- depFiles := ctx.ModuleForTests("libfoo", variant).Rule("ld").Validations.Strings()
+ depFiles := ctx.ModuleForTests(t, "libfoo", variant).Rule("ld").Validations.Strings()
tidyFileForCpp := "out/soong/.intermediates/libfoo/" + variant + "/obj/foo_src.tidy"
diff --git a/cc/vendor_public_library_test.go b/cc/vendor_public_library_test.go
index 7385f2b..797bb25 100644
--- a/cc/vendor_public_library_test.go
+++ b/cc/vendor_public_library_test.go
@@ -70,32 +70,32 @@
// test if header search paths are correctly added
// _static variant is used since _shared reuses *.o from the static variant
- cc := ctx.ModuleForTests("libsystem", strings.Replace(coreVariant, "_shared", "_static", 1)).Rule("cc")
+ cc := ctx.ModuleForTests(t, "libsystem", strings.Replace(coreVariant, "_shared", "_static", 1)).Rule("cc")
cflags := cc.Args["cFlags"]
if !strings.Contains(cflags, "-Imy_include") {
t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags)
}
// test if libsystem is linked to the stub
- ld := ctx.ModuleForTests("libsystem", coreVariant).Rule("ld")
+ ld := ctx.ModuleForTests(t, "libsystem", coreVariant).Rule("ld")
libflags := ld.Args["libFlags"]
- stubPaths := GetOutputPaths(ctx, coreVariant, []string{"libvendorpublic"})
+ stubPaths := GetOutputPaths(t, ctx, coreVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libsystem must contain %#v, but was %#v", stubPaths[0], libflags)
}
// test if libsystem is linked to the stub
- ld = ctx.ModuleForTests("libproduct", productVariant).Rule("ld")
+ ld = ctx.ModuleForTests(t, "libproduct", productVariant).Rule("ld")
libflags = ld.Args["libFlags"]
- stubPaths = GetOutputPaths(ctx, productVariant, []string{"libvendorpublic"})
+ stubPaths = GetOutputPaths(t, ctx, productVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libproduct must contain %#v, but was %#v", stubPaths[0], libflags)
}
// test if libvendor is linked to the real shared lib
- ld = ctx.ModuleForTests("libvendor", vendorVariant).Rule("ld")
+ ld = ctx.ModuleForTests(t, "libvendor", vendorVariant).Rule("ld")
libflags = ld.Args["libFlags"]
- stubPaths = GetOutputPaths(ctx, vendorVariant, []string{"libvendorpublic"})
+ stubPaths = GetOutputPaths(t, ctx, vendorVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libvendor must contain %#v, but was %#v", stubPaths[0], libflags)
diff --git a/ci_tests/Android.bp b/ci_tests/Android.bp
new file mode 100644
index 0000000..181ded4
--- /dev/null
+++ b/ci_tests/Android.bp
@@ -0,0 +1,21 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-ci-tests",
+ pkgPath: "android/soong/ci_tests",
+ deps: [
+ "blueprint",
+ "blueprint-proptools",
+ "soong",
+ "soong-android",
+ ],
+ srcs: [
+ "ci_test_package_zip.go",
+ ],
+ testSrcs: [
+ ],
+ pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
+}
diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go
new file mode 100644
index 0000000..4cadffd
--- /dev/null
+++ b/ci_tests/ci_test_package_zip.go
@@ -0,0 +1,287 @@
+// Copyright (C) 2025 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 ci_tests
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ pctx.Import("android/soong/android")
+ registerTestPackageZipBuildComponents(android.InitRegistrationContext)
+}
+
+func registerTestPackageZipBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("test_package", TestPackageZipFactory)
+}
+
+type testPackageZip struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ properties CITestPackageProperties
+
+ output android.Path
+}
+
+type CITestPackageProperties struct {
+ // test modules will be added as dependencies using the device os and the common architecture's variant.
+ Tests proptools.Configurable[[]string] `android:"arch_variant"`
+ // test modules that will be added as dependencies based on the first supported arch variant and the device os variant
+ Device_first_tests proptools.Configurable[[]string] `android:"arch_variant"`
+ // test modules that will be added as dependencies based on both 32bit and 64bit arch variant and the device os variant
+ Device_both_tests proptools.Configurable[[]string] `android:"arch_variant"`
+ // test modules that will be added as dependencies based on host
+ Host_tests proptools.Configurable[[]string] `android:"arch_variant"`
+ // git-main only test modules. Will only be added as dependencies using the device os and the common architecture's variant if exists.
+ Tests_if_exist_common proptools.Configurable[[]string] `android:"arch_variant"`
+ // git-main only test modules. Will only be added as dependencies based on both 32bit and 64bit arch variant and the device os variant if exists.
+ Tests_if_exist_device_both proptools.Configurable[[]string] `android:"arch_variant"`
+}
+
+type testPackageZipDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var testPackageZipDepTag testPackageZipDepTagType
+
+var (
+ pctx = android.NewPackageContext("android/soong/ci_tests")
+ // test_package module type should only be used for the following modules.
+ // TODO: remove "_soong" from the module names inside when eliminating the corresponding make modules
+ moduleNamesAllowed = []string{"continuous_instrumentation_tests_soong", "continuous_instrumentation_metric_tests_soong", "continuous_native_tests_soong", "continuous_native_metric_tests_soong", "platform_tests"}
+)
+
+func (p *testPackageZip) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // adding tests property deps
+ for _, t := range p.properties.Tests.GetOrDefault(ctx, nil) {
+ ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), testPackageZipDepTag, t)
+ }
+
+ // adding device_first_tests property deps
+ for _, t := range p.properties.Device_first_tests.GetOrDefault(ctx, nil) {
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), testPackageZipDepTag, t)
+ }
+
+ // adding device_both_tests property deps
+ p.addDeviceBothDeps(ctx, false)
+
+ // adding host_tests property deps
+ for _, t := range p.properties.Host_tests.GetOrDefault(ctx, nil) {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), testPackageZipDepTag, t)
+ }
+
+ // adding Tests_if_exist_* property deps
+ for _, t := range p.properties.Tests_if_exist_common.GetOrDefault(ctx, nil) {
+ if ctx.OtherModuleExists(t) {
+ ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), testPackageZipDepTag, t)
+ }
+ }
+ p.addDeviceBothDeps(ctx, true)
+}
+
+func (p *testPackageZip) addDeviceBothDeps(ctx android.BottomUpMutatorContext, checkIfExist bool) {
+ android32TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib32")
+ android64TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib64")
+ if len(android32TargetList) > 0 {
+ maybeAndroid32Target := &android32TargetList[0]
+ if checkIfExist {
+ for _, t := range p.properties.Tests_if_exist_device_both.GetOrDefault(ctx, nil) {
+ if ctx.OtherModuleExists(t) {
+ ctx.AddFarVariationDependencies(maybeAndroid32Target.Variations(), testPackageZipDepTag, t)
+ }
+ }
+ } else {
+ ctx.AddFarVariationDependencies(maybeAndroid32Target.Variations(), testPackageZipDepTag, p.properties.Device_both_tests.GetOrDefault(ctx, nil)...)
+ }
+ }
+ if len(android64TargetList) > 0 {
+ maybeAndroid64Target := &android64TargetList[0]
+ if checkIfExist {
+ for _, t := range p.properties.Tests_if_exist_device_both.GetOrDefault(ctx, nil) {
+ if ctx.OtherModuleExists(t) {
+ ctx.AddFarVariationDependencies(maybeAndroid64Target.Variations(), testPackageZipDepTag, t)
+ }
+ }
+ } else {
+ ctx.AddFarVariationDependencies(maybeAndroid64Target.Variations(), testPackageZipDepTag, p.properties.Device_both_tests.GetOrDefault(ctx, nil)...)
+ }
+ }
+}
+
+func TestPackageZipFactory() android.Module {
+ module := &testPackageZip{}
+
+ module.AddProperties(&module.properties)
+
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
+ return module
+}
+
+func (p *testPackageZip) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Never install this test package, it's for disting only
+ p.SkipInstall()
+
+ if !android.InList(ctx.ModuleName(), moduleNamesAllowed) {
+ ctx.ModuleErrorf("%s is not allowed to use module type test_package")
+ }
+
+ p.output = createOutput(ctx, pctx)
+
+ ctx.SetOutputFiles(android.Paths{p.output}, "")
+}
+
+func createOutput(ctx android.ModuleContext, pctx android.PackageContext) android.ModuleOutPath {
+ productOut := filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName())
+ stagingDir := android.PathForModuleOut(ctx, "STAGING")
+ productVariables := ctx.Config().ProductVariables()
+ arch := proptools.String(productVariables.DeviceArch)
+ secondArch := proptools.String(productVariables.DeviceSecondaryArch)
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("rm").Flag("-rf").Text(stagingDir.String())
+ builder.Command().Text("mkdir").Flag("-p").Output(stagingDir)
+ builder.Temporary(stagingDir)
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if !child.Enabled(ctx) {
+ return false
+ }
+ if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == testPackageZipDepTag {
+ // handle direct deps
+ extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch)
+ return true
+ } else if !android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == android.RequiredDepTag {
+ // handle the "required" from deps
+ extendBuilderCommand(ctx, child, builder, stagingDir, productOut, arch, secondArch)
+ return true
+ } else {
+ return false
+ }
+ })
+
+ output := android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+ builder.Command().
+ BuiltTool("soong_zip").
+ Flag("-o").Output(output).
+ Flag("-C").Text(stagingDir.String()).
+ Flag("-D").Text(stagingDir.String())
+ builder.Command().Text("rm").Flag("-rf").Text(stagingDir.String())
+ builder.Build("test_package", fmt.Sprintf("build test_package for %s", ctx.ModuleName()))
+ return output
+}
+
+func extendBuilderCommand(ctx android.ModuleContext, m android.Module, builder *android.RuleBuilder, stagingDir android.ModuleOutPath, productOut, arch, secondArch string) {
+ info, ok := android.OtherModuleProvider(ctx, m, android.ModuleInfoJSONProvider)
+ if !ok {
+ ctx.OtherModuleErrorf(m, "doesn't set ModuleInfoJSON provider")
+ } else if len(info) != 1 {
+ ctx.OtherModuleErrorf(m, "doesn't provide exactly one ModuleInfoJSON")
+ }
+
+ classes := info[0].GetClass()
+ if len(info[0].Class) != 1 {
+ ctx.OtherModuleErrorf(m, "doesn't have exactly one class in its ModuleInfoJSON")
+ }
+ class := strings.ToLower(classes[0])
+ if class == "apps" {
+ class = "app"
+ } else if class == "java_libraries" {
+ class = "framework"
+ }
+
+ installedFilesInfo, ok := android.OtherModuleProvider(ctx, m, android.InstallFilesProvider)
+ if !ok {
+ ctx.ModuleErrorf("Module %s doesn't set InstallFilesProvider", m.Name())
+ }
+
+ for _, spec := range installedFilesInfo.PackagingSpecs {
+ if spec.SrcPath() == nil {
+ // Probably a symlink
+ continue
+ }
+ installedFile := spec.FullInstallPath()
+
+ ext := installedFile.Ext()
+ // there are additional installed files for some app-class modules, we only need the .apk, .odex and .vdex files in the test package
+ excludeInstalledFile := ext != ".apk" && ext != ".odex" && ext != ".vdex"
+ if class == "app" && excludeInstalledFile {
+ continue
+ }
+ // only .jar files should be included for a framework dep
+ if class == "framework" && ext != ".jar" {
+ continue
+ }
+ name := removeFileExtension(installedFile.Base())
+ // some apks have other apk as installed files, these additional files shouldn't be included
+ isAppOrFramework := class == "app" || class == "framework"
+ if isAppOrFramework && name != ctx.OtherModuleName(m) {
+ continue
+ }
+
+ f := strings.TrimPrefix(installedFile.String(), productOut+"/")
+ if strings.HasPrefix(f, "out") {
+ continue
+ }
+ if strings.HasPrefix(f, "system/") {
+ f = strings.Replace(f, "system/", "DATA/", 1)
+ }
+ f = strings.ReplaceAll(f, filepath.Join("testcases", name, arch), filepath.Join("DATA", class, name))
+ f = strings.ReplaceAll(f, filepath.Join("testcases", name, secondArch), filepath.Join("DATA", class, name))
+ if strings.HasPrefix(f, "testcases") {
+ f = strings.Replace(f, "testcases", filepath.Join("DATA", class), 1)
+ }
+ if strings.HasPrefix(f, "data/") {
+ f = strings.Replace(f, "data/", "DATA/", 1)
+ }
+ f = strings.ReplaceAll(f, "DATA_other", "system_other")
+ f = strings.ReplaceAll(f, "system_other/DATA", "system_other/system")
+ dir := filepath.Dir(f)
+
+ tempOut := android.PathForModuleOut(ctx, "STAGING", f)
+ builder.Command().Text("mkdir").Flag("-p").Text(filepath.Join(stagingDir.String(), dir))
+ // Copy srcPath instead of installedFile because some rules like target-files.zip
+ // are non-hermetic and would be affected if we built the installed files.
+ builder.Command().Text("cp").Flag("-Rf").Input(spec.SrcPath()).Output(tempOut)
+ builder.Temporary(tempOut)
+ }
+}
+
+func removeFileExtension(filename string) string {
+ return strings.TrimSuffix(filename, filepath.Ext(filename))
+}
+
+// The only purpose of this method is to make sure we can build the module directly
+// without adding suffix "-soong"
+func (p *testPackageZip) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{
+ android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(p.output),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ }},
+ },
+ }
+}
diff --git a/cmd/find_input_delta/find_input_delta/main.go b/cmd/find_input_delta/find_input_delta/main.go
index a864584..65ef881 100644
--- a/cmd/find_input_delta/find_input_delta/main.go
+++ b/cmd/find_input_delta/find_input_delta/main.go
@@ -17,11 +17,13 @@
import (
"flag"
"os"
- "strings"
+ "regexp"
fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib"
)
+var fileSepRegex = regexp.MustCompile("[^[:space:]]+")
+
func main() {
var top string
var prior_state_file string
@@ -46,6 +48,8 @@
if target == "" {
panic("must specify --target")
}
+ // Drop any extra file names that arrived in `target`.
+ target = fileSepRegex.FindString(target)
if prior_state_file == "" {
prior_state_file = target + ".pc_state"
}
@@ -63,7 +67,7 @@
if err != nil {
panic(err)
}
- inputs = append(inputs, strings.Split(string(data), "\n")...)
+ inputs = append(inputs, fileSepRegex.FindAllString(string(data), -1)...)
}
// Read the prior state
@@ -80,15 +84,16 @@
panic(err)
}
- file_list := *fid_lib.CompareInternalState(prior_state, new_state, target)
+ file_list := fid_lib.CompareInternalState(prior_state, new_state, target)
if err = file_list.Format(os.Stdout, template); err != nil {
panic(err)
}
- metrics_file := os.Getenv("SOONG_METRICS_AGGREGATION_FILE")
- if metrics_file != "" {
- if err = file_list.SendMetrics(metrics_file); err != nil {
+ metrics_dir := os.Getenv("SOONG_METRICS_AGGREGATION_DIR")
+ out_dir := os.Getenv("OUT_DIR")
+ if metrics_dir != "" {
+ if err = file_list.WriteMetrics(metrics_dir, out_dir); err != nil {
panic(err)
}
}
diff --git a/cmd/find_input_delta/find_input_delta_lib/file_list.go b/cmd/find_input_delta/find_input_delta_lib/file_list.go
index 01242a0..f1d588b 100644
--- a/cmd/find_input_delta/find_input_delta_lib/file_list.go
+++ b/cmd/find_input_delta/find_input_delta_lib/file_list.go
@@ -16,10 +16,11 @@
import (
"fmt"
+ "hash/fnv"
"io"
"os"
"path/filepath"
- "slices"
+ "strings"
"text/template"
fid_exp "android/soong/cmd/find_input_delta/find_input_delta_proto"
@@ -106,95 +107,75 @@
fl.ExtCountMap[ext].Changes += 1
}
-func (fl FileList) ToProto() (*fid_exp.FileList, error) {
- var count uint32
- return fl.toProto(&count)
-}
-
-func (fl FileList) toProto(count *uint32) (*fid_exp.FileList, error) {
- ret := &fid_exp.FileList{
- Name: proto.String(fl.Name),
+// Write a SoongExecutionMetrics FileList proto to `dir`.
+//
+// Path
+// Prune any paths that
+// begin with `pruneDir` (usually ${OUT_DIR}). The file is only written if any
+// non-pruned changes are present.
+func (fl *FileList) WriteMetrics(dir, pruneDir string) (err error) {
+ if dir == "" {
+ return fmt.Errorf("No directory given")
}
+ var needed bool
+
+ if !strings.HasSuffix(pruneDir, "/") {
+ pruneDir += "/"
+ }
+
+ // Hash the dir and `fl.Name` to simplify scanning the metrics
+ // aggregation directory.
+ h := fnv.New128()
+ h.Write([]byte(dir + " " + fl.Name + ".FileList"))
+ path := fmt.Sprintf("%x.pb", h.Sum([]byte{}))
+ path = filepath.Join(dir, path[0:2], path[2:])
+
+ var msg = &fid_exp.FileList{Name: proto.String(fl.Name)}
for _, a := range fl.Additions {
- if *count >= MaxFilesRecorded {
- break
+ if strings.HasPrefix(a, pruneDir) {
+ continue
}
- ret.Additions = append(ret.Additions, a)
- *count += 1
+ msg.Additions = append(msg.Additions, a)
+ needed = true
}
for _, ch := range fl.Changes {
- if *count >= MaxFilesRecorded {
- break
- } else {
- // Pre-increment to limit what the call adds.
- *count += 1
- change, err := ch.toProto(count)
- if err != nil {
- return nil, err
- }
- ret.Changes = append(ret.Changes, change)
+ if strings.HasPrefix(ch.Name, pruneDir) {
+ continue
}
+ msg.Changes = append(msg.Changes, ch.Name)
+ needed = true
}
for _, d := range fl.Deletions {
- if *count >= MaxFilesRecorded {
- break
+ if strings.HasPrefix(d, pruneDir) {
+ continue
}
- ret.Deletions = append(ret.Deletions, d)
+ msg.Deletions = append(msg.Deletions, d)
+ needed = true
}
- ret.TotalDelta = proto.Uint32(*count)
- exts := []string{}
- for k := range fl.ExtCountMap {
- exts = append(exts, k)
+ if !needed {
+ return nil
}
- slices.Sort(exts)
- for _, k := range exts {
- v := fl.ExtCountMap[k]
- ret.Counts = append(ret.Counts, &fid_exp.FileCount{
- Extension: proto.String(k),
- Additions: proto.Uint32(v.Additions),
- Deletions: proto.Uint32(v.Deletions),
- Modifications: proto.Uint32(v.Changes),
- })
- }
- return ret, nil
-}
-
-func (fl FileList) SendMetrics(path string) error {
- if path == "" {
- return fmt.Errorf("No path given")
- }
- message, err := fl.ToProto()
- if err != nil {
- return err
- }
-
- // Marshal the message wrapped in SoongCombinedMetrics.
data := protowire.AppendVarint(
[]byte{},
protowire.EncodeTag(
protowire.Number(fid_exp.FieldNumbers_FIELD_NUMBERS_FILE_LIST),
protowire.BytesType))
- size := uint64(proto.Size(message))
+ size := uint64(proto.Size(msg))
data = protowire.AppendVarint(data, size)
- data, err = proto.MarshalOptions{UseCachedSize: true}.MarshalAppend(data, message)
+ data, err = proto.MarshalOptions{UseCachedSize: true}.MarshalAppend(data, msg)
if err != nil {
return err
}
- out, err := os.Create(path)
+ err = os.MkdirAll(filepath.Dir(path), 0777)
if err != nil {
return err
}
- defer func() {
- if err := out.Close(); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to close %s: %v\n", path, err)
- }
- }()
- _, err = out.Write(data)
- return err
+
+ return os.WriteFile(path, data, 0644)
}
-func (fl FileList) Format(wr io.Writer, format string) error {
+func (fl *FileList) Format(wr io.Writer, format string) error {
tmpl, err := template.New("filelist").Parse(format)
if err != nil {
return err
diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state.go b/cmd/find_input_delta/find_input_delta_lib/internal_state.go
index 2b8c395..0f88159 100644
--- a/cmd/find_input_delta/find_input_delta_lib/internal_state.go
+++ b/cmd/find_input_delta/find_input_delta_lib/internal_state.go
@@ -51,6 +51,9 @@
for _, input := range inputs {
stat, err := fs.Stat(fsys, input)
if err != nil {
+ if errors.Is(err, fs.ErrNotExist) {
+ continue
+ }
return ret, err
}
pci := &fid_proto.PartialCompileInput{
@@ -92,9 +95,14 @@
}
ret := []*fid_proto.PartialCompileInput{}
for _, v := range rc.File {
+ // Only include timestamp when there is no CRC.
+ timeNsec := proto.Int64(v.ModTime().UnixNano())
+ if v.CRC32 != 0 {
+ timeNsec = nil
+ }
pci := &fid_proto.PartialCompileInput{
Name: proto.String(v.Name),
- MtimeNsec: proto.Int64(v.ModTime().UnixNano()),
+ MtimeNsec: timeNsec,
Hash: proto.String(fmt.Sprintf("%08x", v.CRC32)),
}
ret = append(ret, pci)
diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go
index 745de2d..b6adc45 100644
--- a/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go
+++ b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go
@@ -96,20 +96,14 @@
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // The name of the file.
- // In the outermost message, this is the name of the Ninja target.
- // When used in `changes`, this is the name of the changed file.
+ // The name of the output file (Ninja target).
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// The added files.
Additions []string `protobuf:"bytes,2,rep,name=additions" json:"additions,omitempty"`
// The changed files.
- Changes []*FileList `protobuf:"bytes,3,rep,name=changes" json:"changes,omitempty"`
+ Changes []string `protobuf:"bytes,3,rep,name=changes" json:"changes,omitempty"`
// The deleted files.
Deletions []string `protobuf:"bytes,4,rep,name=deletions" json:"deletions,omitempty"`
- // Count of files added/changed/deleted.
- TotalDelta *uint32 `protobuf:"varint,5,opt,name=total_delta,json=totalDelta" json:"total_delta,omitempty"`
- // Counts by extension.
- Counts []*FileCount `protobuf:"bytes,6,rep,name=counts" json:"counts,omitempty"`
}
func (x *FileList) Reset() {
@@ -158,7 +152,7 @@
return nil
}
-func (x *FileList) GetChanges() []*FileList {
+func (x *FileList) GetChanges() []string {
if x != nil {
return x.Changes
}
@@ -172,135 +166,28 @@
return nil
}
-func (x *FileList) GetTotalDelta() uint32 {
- if x != nil && x.TotalDelta != nil {
- return *x.TotalDelta
- }
- return 0
-}
-
-func (x *FileList) GetCounts() []*FileCount {
- if x != nil {
- return x.Counts
- }
- return nil
-}
-
-type FileCount struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // The file extension
- Extension *string `protobuf:"bytes,1,opt,name=extension" json:"extension,omitempty"`
- // Number of added files with this extension.
- Additions *uint32 `protobuf:"varint,2,opt,name=additions" json:"additions,omitempty"`
- // Number of modified files with this extension.
- Modifications *uint32 `protobuf:"varint,3,opt,name=modifications" json:"modifications,omitempty"`
- // Number of deleted files with this extension.
- Deletions *uint32 `protobuf:"varint,4,opt,name=deletions" json:"deletions,omitempty"`
-}
-
-func (x *FileCount) Reset() {
- *x = FileCount{}
- if protoimpl.UnsafeEnabled {
- mi := &file_file_list_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *FileCount) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*FileCount) ProtoMessage() {}
-
-func (x *FileCount) ProtoReflect() protoreflect.Message {
- mi := &file_file_list_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use FileCount.ProtoReflect.Descriptor instead.
-func (*FileCount) Descriptor() ([]byte, []int) {
- return file_file_list_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *FileCount) GetExtension() string {
- if x != nil && x.Extension != nil {
- return *x.Extension
- }
- return ""
-}
-
-func (x *FileCount) GetAdditions() uint32 {
- if x != nil && x.Additions != nil {
- return *x.Additions
- }
- return 0
-}
-
-func (x *FileCount) GetModifications() uint32 {
- if x != nil && x.Modifications != nil {
- return *x.Modifications
- }
- return 0
-}
-
-func (x *FileCount) GetDeletions() uint32 {
- if x != nil && x.Deletions != nil {
- return *x.Deletions
- }
- return 0
-}
-
var File_file_list_proto protoreflect.FileDescriptor
var file_file_list_proto_rawDesc = []byte{
0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x22, 0x82, 0x02, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x42, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64,
- 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f,
- 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74,
- 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x65,
- 0x6c, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69,
- 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
- 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
- 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x2a, 0x4a, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x75, 0x6d,
- 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55,
- 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
- 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d,
- 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01,
- 0x42, 0x3b, 0x5a, 0x39, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74,
- 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75,
- 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x6f, 0x22, 0x74, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+ 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c,
+ 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65,
+ 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2a, 0x4a, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64,
+ 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x49, 0x45, 0x4c, 0x44,
+ 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+ 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f,
+ 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4c, 0x49, 0x53,
+ 0x54, 0x10, 0x01, 0x42, 0x3b, 0x5a, 0x39, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -316,20 +203,17 @@
}
var file_file_list_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_file_list_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_file_list_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_file_list_proto_goTypes = []interface{}{
(FieldNumbers)(0), // 0: android.find_input_delta_proto.FieldNumbers
(*FileList)(nil), // 1: android.find_input_delta_proto.FileList
- (*FileCount)(nil), // 2: android.find_input_delta_proto.FileCount
}
var file_file_list_proto_depIdxs = []int32{
- 1, // 0: android.find_input_delta_proto.FileList.changes:type_name -> android.find_input_delta_proto.FileList
- 2, // 1: android.find_input_delta_proto.FileList.counts:type_name -> android.find_input_delta_proto.FileCount
- 2, // [2:2] is the sub-list for method output_type
- 2, // [2:2] is the sub-list for method input_type
- 2, // [2:2] is the sub-list for extension type_name
- 2, // [2:2] is the sub-list for extension extendee
- 0, // [0:2] is the sub-list for field type_name
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
}
func init() { file_file_list_proto_init() }
@@ -350,18 +234,6 @@
return nil
}
}
- file_file_list_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FileCount); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -369,7 +241,7 @@
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_file_list_proto_rawDesc,
NumEnums: 1,
- NumMessages: 2,
+ NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.proto b/cmd/find_input_delta/find_input_delta_proto/file_list.proto
index 7180358..5309d66 100644
--- a/cmd/find_input_delta/find_input_delta_proto/file_list.proto
+++ b/cmd/find_input_delta/find_input_delta_proto/file_list.proto
@@ -23,37 +23,15 @@
}
message FileList {
- // The name of the file.
- // In the outermost message, this is the name of the Ninja target.
- // When used in `changes`, this is the name of the changed file.
+ // The name of the output file (Ninja target).
optional string name = 1;
// The added files.
repeated string additions = 2;
// The changed files.
- repeated FileList changes = 3;
+ repeated string changes = 3;
// The deleted files.
repeated string deletions = 4;
-
- // Count of files added/changed/deleted.
- optional uint32 total_delta = 5;
-
- // Counts by extension.
- repeated FileCount counts = 6;
-}
-
-message FileCount {
- // The file extension
- optional string extension = 1;
-
- // Number of added files with this extension.
- optional uint32 additions = 2;
-
- // Number of modified files with this extension.
- optional uint32 modifications = 3;
-
- // Number of deleted files with this extension.
- optional uint32 deletions = 4;
}
diff --git a/cmd/find_input_delta/find_input_delta_proto/regen.sh b/cmd/find_input_delta/find_input_delta_proto/regen.sh
old mode 100644
new mode 100755
diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh b/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh
old mode 100644
new mode 100755
diff --git a/cmd/javac_wrapper/javac_wrapper.go b/cmd/javac_wrapper/javac_wrapper.go
index 4679906..49bcedf 100644
--- a/cmd/javac_wrapper/javac_wrapper.go
+++ b/cmd/javac_wrapper/javac_wrapper.go
@@ -200,6 +200,9 @@
var warningFilters = []*regexp.Regexp{
regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
+ regexp.MustCompile(`source value 8 is obsolete and will be removed in a future release`),
+ regexp.MustCompile(`target value 8 is obsolete and will be removed in a future release`),
+ regexp.MustCompile(`To suppress warnings about obsolete options, use -Xlint:-options.`),
}
var filters = []*regexp.Regexp{
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index ad23001..5e26786 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -90,6 +90,15 @@
`,
out: "\n\x1b[1m\x1b[35mwarning:\x1b[0m\x1b[1m foo\x1b[0m\n1 warning\n",
},
+ {
+ in: `
+warning: [options] source value 8 is obsolete and will be removed in a future release
+warning: [options] target value 8 is obsolete and will be removed in a future release
+warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
+3 warnings
+`,
+ out: "\n",
+ },
}
func TestJavacColorize(t *testing.T) {
diff --git a/cmd/kotlinc_incremental/Android.bp b/cmd/kotlinc_incremental/Android.bp
new file mode 100644
index 0000000..7816553
--- /dev/null
+++ b/cmd/kotlinc_incremental/Android.bp
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2025 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 {
+ default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
+ default_applicable_licenses: [
+ "Android-Apache-2.0",
+ "Kotlin_Incremental_license",
+ ],
+}
+
+license {
+ name: "Kotlin_Incremental_license",
+ visibility: [":__subpackages__"],
+ license_kinds: ["legacy_proprietary"],
+}
+
+java_library_host {
+ name: "kotlin-incremental-client-lib",
+ srcs: [
+ "src/com/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-compiler-embeddable",
+ "kotlin-compiler-runner",
+ "kotlin-daemon-client",
+ ],
+
+ plugins: [],
+
+ kotlincflags: [
+ "-Werror",
+ ],
+}
+
+java_binary_host {
+ name: "kotlin-incremental-client",
+ manifest: "kotlin-incremental-client.mf",
+ static_libs: ["kotlin-incremental-client-lib"],
+}
+
+java_test_host {
+ name: "kotlin-incremental-client-tests",
+ srcs: [
+ "tests/src/com/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-incremental-client-lib",
+ "junit",
+ "truth",
+ ],
+}
diff --git a/cmd/kotlinc_incremental/kotlin-incremental-client.mf b/cmd/kotlinc_incremental/kotlin-incremental-client.mf
new file mode 100644
index 0000000..b84c86a
--- /dev/null
+++ b/cmd/kotlinc_incremental/kotlin-incremental-client.mf
@@ -0,0 +1 @@
+Main-Class: com.android.kotlin.compiler.client.MainKt
diff --git a/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt
new file mode 100644
index 0000000..4938641
--- /dev/null
+++ b/cmd/kotlinc_incremental/src/com/android/kotlin/compiler/client/Main.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2025 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 com.android.kotlin.compiler.client
+
+fun main(args: Array<String>) {
+ println("compiling")
+}
diff --git a/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/MainTest.kt b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/MainTest.kt
new file mode 100644
index 0000000..3354aa4
--- /dev/null
+++ b/cmd/kotlinc_incremental/tests/src/com/android/kotlin/compiler/client/MainTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2025 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 com.android.kotlin.compiler.client
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class MainTest {
+ @Test
+ fun testMain() {
+ assertThat(true).isTrue()
+ }
+}
\ No newline at end of file
diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go
index d06b2b7..7013d6b 100644
--- a/cmd/release_config/release_config/main.go
+++ b/cmd/release_config/release_config/main.go
@@ -95,7 +95,7 @@
if allMake {
// Write one makefile per release config, using the canonical release name.
for _, c := range configs.GetSortedReleaseConfigs() {
- if c.Name != targetRelease {
+ if c.Name != targetRelease && !c.DisallowLunchUse {
makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.varmk", product, c.Name))
err = config.WriteMakefile(makefilePath, c.Name, configs)
if err != nil {
diff --git a/cmd/release_config/release_config_lib/flag_artifact.go b/cmd/release_config/release_config_lib/flag_artifact.go
index cb13fdc..f493e1e 100644
--- a/cmd/release_config/release_config_lib/flag_artifact.go
+++ b/cmd/release_config/release_config_lib/flag_artifact.go
@@ -189,7 +189,7 @@
if redacted {
fa.Redact()
flagValue.proto.Value = fa.Value
- fmt.Printf("Redacting flag %s in %s\n", name, flagValue.path)
+ warnf("Redacting flag %s in %s\n", name, flagValue.path)
} else {
// If we are assigning a value, then the flag is no longer redacted.
fa.Redacted = false
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index 719ddc0..873f2fc 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -67,6 +67,9 @@
// overrides. Build flag value overrides are an error.
AconfigFlagsOnly bool
+ // True if this release config is not allowed as TARGET_RELEASE.
+ DisallowLunchUse bool
+
// Unmarshalled flag artifacts
FlagArtifacts FlagArtifacts
@@ -93,6 +96,11 @@
// If true, this is a proper release config that can be used in "lunch".
func (config *ReleaseConfig) isConfigListable() bool {
+ // Do not list disallowed release configs.
+ if config.DisallowLunchUse {
+ return false
+ }
+ // Logic based on ReleaseConfigType.
switch config.ReleaseConfigType {
case rc_proto.ReleaseConfigType_RELEASE_CONFIG:
return true
@@ -405,6 +413,7 @@
ValueDirectories: valueDirectories,
PriorStages: SortedMapKeys(config.PriorStagesMap),
ReleaseConfigType: config.ReleaseConfigType.Enum(),
+ DisallowLunchUse: proto.Bool(config.DisallowLunchUse),
}
config.compileInProgress = false
@@ -481,6 +490,9 @@
}
// As it stands this list is not per-product, but conceptually it is, and will be.
data += fmt.Sprintf("ALL_RELEASE_CONFIGS_FOR_PRODUCT :=$= %s\n", strings.Join(configs.GetAllReleaseNames(), " "))
+ if config.DisallowLunchUse {
+ data += fmt.Sprintf("_disallow_lunch_use :=$= true\n")
+ }
data += fmt.Sprintf("_used_files := %s\n", strings.Join(config.GetSortedFileList(), " "))
data += fmt.Sprintf("_ALL_RELEASE_FLAGS :=$= %s\n", strings.Join(names, " "))
for _, pName := range pNames {
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index 4f621c7..dd98bca 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -314,6 +314,9 @@
}
}
}
+ if flagDeclaration.Namespace == nil {
+ return fmt.Errorf("Flag declaration %s has no namespace.", path)
+ }
m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration)
name := *flagDeclaration.Name
@@ -378,6 +381,7 @@
return fmt.Errorf("%s mismatching ReleaseConfigType value %s", path, *releaseConfigType)
}
config.FilesUsedMap[path] = true
+ config.DisallowLunchUse = config.DisallowLunchUse || releaseConfigContribution.proto.GetDisallowLunchUse()
inheritNames := make(map[string]bool)
for _, inh := range config.InheritNames {
inheritNames[inh] = true
diff --git a/cmd/release_config/release_config_proto/build_flags_common.pb.go b/cmd/release_config/release_config_proto/build_flags_common.pb.go
index f8ad38f..7b52b07 100644
--- a/cmd/release_config/release_config_proto/build_flags_common.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_common.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: build_flags_common.proto
diff --git a/cmd/release_config/release_config_proto/build_flags_declarations.pb.go b/cmd/release_config/release_config_proto/build_flags_declarations.pb.go
index 1df246c..0029f99 100644
--- a/cmd/release_config/release_config_proto/build_flags_declarations.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_declarations.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: build_flags_declarations.proto
diff --git a/cmd/release_config/release_config_proto/build_flags_out.pb.go b/cmd/release_config/release_config_proto/build_flags_out.pb.go
index ec07415..21a37a9 100644
--- a/cmd/release_config/release_config_proto/build_flags_out.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_out.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: build_flags_out.proto
@@ -237,6 +237,10 @@
ValueDirectories []string `protobuf:"bytes,8,rep,name=value_directories,json=valueDirectories" json:"value_directories,omitempty"`
// The ReleaseConfigType of this release config.
ReleaseConfigType *ReleaseConfigType `protobuf:"varint,9,opt,name=release_config_type,json=releaseConfigType,enum=android.release_config_proto.ReleaseConfigType" json:"release_config_type,omitempty"`
+ // Whether to disallow this release config as TARGET_RELEASE.
+ // If true, this release config can only be inherited, it cannot be used
+ // directly in a build.
+ DisallowLunchUse *bool `protobuf:"varint,10,opt,name=disallow_lunch_use,json=disallowLunchUse" json:"disallow_lunch_use,omitempty"`
}
func (x *ReleaseConfigArtifact) Reset() {
@@ -334,6 +338,13 @@
return ReleaseConfigType_CONFIG_TYPE_UNSPECIFIED
}
+func (x *ReleaseConfigArtifact) GetDisallowLunchUse() bool {
+ if x != nil && x.DisallowLunchUse != nil {
+ return *x.DisallowLunchUse
+ }
+ return false
+}
+
type ReleaseConfigsArtifact struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -434,7 +445,7 @@
0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66,
0x61, 0x63, 0x74, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x0e, 0x66, 0x6c, 0x61, 0x67,
- 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xbb, 0x03, 0x0a, 0x15, 0x52,
+ 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xe9, 0x03, 0x0a, 0x15, 0x52,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x72, 0x74, 0x69,
0x66, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x74, 0x68, 0x65,
@@ -461,41 +472,44 @@
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61,
- 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xde, 0x03, 0x0a, 0x16, 0x52, 0x65, 0x6c,
- 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66,
- 0x61, 0x63, 0x74, 0x12, 0x5a, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63,
- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
- 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
- 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
- 0x67, 0x0a, 0x15, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
- 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33,
- 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
- 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
- 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66,
- 0x61, 0x63, 0x74, 0x52, 0x13, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73,
- 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x17, 0x72, 0x65, 0x6c,
- 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x73,
- 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4e, 0x2e, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73,
- 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
- 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61,
- 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x6c, 0x65,
- 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70,
- 0x1a, 0x77, 0x0a, 0x19, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
- 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
- 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e,
- 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
- 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
- 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x52, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61,
- 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
- 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x69, 0x73, 0x61,
+ 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6c, 0x75, 0x6e, 0x63, 0x68, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x0a,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x64, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x75,
+ 0x6e, 0x63, 0x68, 0x55, 0x73, 0x65, 0x52, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74,
+ 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xde, 0x03, 0x0a, 0x16, 0x52, 0x65, 0x6c, 0x65, 0x61,
+ 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+ 0x74, 0x12, 0x5a, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x0d,
+ 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x67, 0x0a,
+ 0x15, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65,
+ 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+ 0x74, 0x52, 0x13, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x17, 0x72, 0x65, 0x6c, 0x65, 0x61,
+ 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x5f, 0x6d,
+ 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4e, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52,
+ 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73,
+ 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
+ 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x1a, 0x77,
+ 0x0a, 0x19, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d,
+ 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65,
+ 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x52, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
diff --git a/cmd/release_config/release_config_proto/build_flags_out.proto b/cmd/release_config/release_config_proto/build_flags_out.proto
index 55c848e..8b53464 100644
--- a/cmd/release_config/release_config_proto/build_flags_out.proto
+++ b/cmd/release_config/release_config_proto/build_flags_out.proto
@@ -99,6 +99,11 @@
// The ReleaseConfigType of this release config.
optional ReleaseConfigType release_config_type = 9;
+
+ // Whether to disallow this release config as TARGET_RELEASE.
+ // If true, this release config can only be inherited, it cannot be used
+ // directly in a build.
+ optional bool disallow_lunch_use = 10;
}
message ReleaseConfigsArtifact {
diff --git a/cmd/release_config/release_config_proto/build_flags_src.pb.go b/cmd/release_config/release_config_proto/build_flags_src.pb.go
index c48c323..9fc4ea4 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.pb.go
+++ b/cmd/release_config/release_config_proto/build_flags_src.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: build_flags_src.proto
@@ -410,6 +410,10 @@
PriorStages []string `protobuf:"bytes,5,rep,name=prior_stages,json=priorStages" json:"prior_stages,omitempty"`
// The ReleaseConfigType of this release config.
ReleaseConfigType *ReleaseConfigType `protobuf:"varint,6,opt,name=release_config_type,json=releaseConfigType,enum=android.release_config_proto.ReleaseConfigType" json:"release_config_type,omitempty"`
+ // Whether to disallow this release config as TARGET_RELEASE.
+ // If true, this release config can only be inherited, it cannot be used
+ // directly in a build.
+ DisallowLunchUse *bool `protobuf:"varint,7,opt,name=disallow_lunch_use,json=disallowLunchUse" json:"disallow_lunch_use,omitempty"`
}
func (x *ReleaseConfig) Reset() {
@@ -486,6 +490,13 @@
return ReleaseConfigType_CONFIG_TYPE_UNSPECIFIED
}
+func (x *ReleaseConfig) GetDisallowLunchUse() bool {
+ if x != nil && x.DisallowLunchUse != nil {
+ return *x.DisallowLunchUse
+ }
+ return false
+}
+
// Any aliases. These are used for continuous integration builder config.
type ReleaseAlias struct {
state protoimpl.MessageState
@@ -655,7 +666,7 @@
0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x08, 0x72, 0x65,
0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72,
- 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x22, 0x9f, 0x02, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x65,
+ 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x22, 0xcd, 0x02, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x65,
0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a,
0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
@@ -673,32 +684,35 @@
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43,
- 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x0a, 0x0c, 0x52, 0x65, 0x6c,
- 0x65, 0x61, 0x73, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a,
- 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74,
- 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xa9, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73,
- 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x12, 0x44, 0x0a, 0x07, 0x61, 0x6c,
- 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
- 0x73, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73,
- 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f,
- 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11,
- 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
- 0x73, 0x2a, 0x78, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47,
- 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
- 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x43,
- 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x58, 0x50, 0x4c, 0x49,
- 0x43, 0x49, 0x54, 0x5f, 0x49, 0x4e, 0x48, 0x45, 0x52, 0x49, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f,
- 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x42, 0x55, 0x49, 0x4c,
- 0x44, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x4e, 0x54, 0x10, 0x03, 0x42, 0x33, 0x5a, 0x31, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c,
- 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65,
- 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x69, 0x73,
+ 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x6c, 0x75, 0x6e, 0x63, 0x68, 0x5f, 0x75, 0x73, 0x65, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x64, 0x69, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c,
+ 0x75, 0x6e, 0x63, 0x68, 0x55, 0x73, 0x65, 0x22, 0x3a, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x65, 0x61,
+ 0x73, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x22, 0xa9, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x12, 0x44, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61,
+ 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x41, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x20,
+ 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65,
+ 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2a,
+ 0x78, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x54,
+ 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+ 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x4e,
+ 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x45, 0x58, 0x50, 0x4c, 0x49, 0x43, 0x49,
+ 0x54, 0x5f, 0x49, 0x4e, 0x48, 0x45, 0x52, 0x49, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f,
+ 0x4e, 0x46, 0x49, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f,
+ 0x56, 0x41, 0x52, 0x49, 0x41, 0x4e, 0x54, 0x10, 0x03, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61,
+ 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73,
+ 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
diff --git a/cmd/release_config/release_config_proto/build_flags_src.proto b/cmd/release_config/release_config_proto/build_flags_src.proto
index e42ac31..2cc1a84 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.proto
+++ b/cmd/release_config/release_config_proto/build_flags_src.proto
@@ -138,6 +138,11 @@
// The ReleaseConfigType of this release config.
optional ReleaseConfigType release_config_type = 6;
+
+ // Whether to disallow this release config as TARGET_RELEASE.
+ // If true, this release config can only be inherited, it cannot be used
+ // directly in a build.
+ optional bool disallow_lunch_use = 7;
}
// Any aliases. These are used for continuous integration builder config.
diff --git a/cmd/release_config/release_config_proto/release_configs_contributions.pb.go b/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
index 54854f1..339e4ba 100644
--- a/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
+++ b/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
@@ -15,7 +15,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: release_configs_contributions.proto
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 6642023..cd4e9bd 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -64,6 +64,7 @@
flag.StringVar(&usedEnvFile, "used_env", "", "File containing used environment variables")
flag.StringVar(&cmdlineArgs.OutDir, "out", "", "the ninja builddir directory")
flag.StringVar(&cmdlineArgs.ModuleListFile, "l", "", "file that lists filepaths to parse")
+ flag.StringVar(&cmdlineArgs.KatiSuffix, "kati_suffix", "", "the suffix for kati and ninja files, so that different configurations don't clobber each other")
// Debug flags
flag.StringVar(&delveListen, "delve_listen", "", "Delve port to listen on for debugging")
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index c7134d7..584cc04 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -27,6 +27,7 @@
"android/soong/shared"
"android/soong/ui/build"
+ "android/soong/ui/execution_metrics"
"android/soong/ui/logger"
"android/soong/ui/metrics"
"android/soong/ui/signal"
@@ -170,14 +171,16 @@
stat.Finish()
})
criticalPath := status.NewCriticalPath()
+ emet := execution_metrics.NewExecutionMetrics(log)
buildCtx := build.Context{ContextImpl: &build.ContextImpl{
- Context: ctx,
- Logger: log,
- Metrics: met,
- Tracer: trace,
- Writer: output,
- Status: stat,
- CriticalPath: criticalPath,
+ Context: ctx,
+ Logger: log,
+ Metrics: met,
+ ExecutionMetrics: emet,
+ Tracer: trace,
+ Writer: output,
+ Status: stat,
+ CriticalPath: criticalPath,
}}
freshConfig := func() build.Config {
@@ -194,6 +197,7 @@
rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
soongBuildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_build_metrics.pb")
buildTraceFile := filepath.Join(logsDir, c.logsPrefix+"build.trace.gz")
+ executionMetricsFile := filepath.Join(logsDir, c.logsPrefix+"execution_metrics.pb")
metricsFiles := []string{
buildErrorFile, // build error strings
@@ -204,9 +208,15 @@
}
defer func() {
+ emet.Finish(buildCtx)
stat.Finish()
criticalPath.WriteToMetrics(met)
met.Dump(soongMetricsFile)
+ emet.Dump(executionMetricsFile, args)
+ // If there are execution metrics, upload them.
+ if _, err := os.Stat(executionMetricsFile); err == nil {
+ metricsFiles = append(metricsFiles, executionMetricsFile)
+ }
if !config.SkipMetricsUpload() {
build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, metricsFiles...)
}
@@ -323,12 +333,12 @@
varName := flags.Arg(0)
if varName == "report_config" {
- varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
+ varData, err := build.DumpMakeVars(ctx, config, nil, append(build.BannerVars, "PRODUCT_SOONG_ONLY"))
if err != nil {
ctx.Fatal(err)
}
- fmt.Println(build.Banner(varData))
+ fmt.Println(build.Banner(config, varData))
} else {
varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
if err != nil {
@@ -390,7 +400,7 @@
if i := indexList("report_config", allVars); i != -1 {
allVars = append(allVars[:i], allVars[i+1:]...)
- allVars = append(allVars, build.BannerVars...)
+ allVars = append(allVars, append(build.BannerVars, "PRODUCT_SOONG_ONLY")...)
}
if len(allVars) == 0 {
@@ -404,7 +414,7 @@
for _, name := range vars {
if name == "report_config" {
- fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
+ fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(config, varData))
} else {
fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
}
@@ -461,20 +471,6 @@
description: "Build action: build from the top of the source tree.",
action: build.BUILD_MODULES,
}, {
- // This is redirecting to mma build command behaviour. Once it has soaked for a
- // while, the build command is deleted from here once it has been removed from the
- // envsetup.sh.
- name: "modules-in-a-dir-no-deps",
- description: "Build action: builds all of the modules in the current directory without their dependencies.",
- action: build.BUILD_MODULES_IN_A_DIRECTORY,
- }, {
- // This is redirecting to mmma build command behaviour. Once it has soaked for a
- // while, the build command is deleted from here once it has been removed from the
- // envsetup.sh.
- name: "modules-in-dirs-no-deps",
- description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
- action: build.BUILD_MODULES_IN_DIRECTORIES,
- }, {
name: "modules-in-a-dir",
description: "Build action: builds all of the modules in the current directory and their dependencies.",
action: build.BUILD_MODULES_IN_A_DIRECTORY,
diff --git a/genrule/allowlists.go b/cmd/source_tree_size/Android.bp
similarity index 63%
copy from genrule/allowlists.go
copy to cmd/source_tree_size/Android.bp
index 45a7f72..97d29c6 100644
--- a/genrule/allowlists.go
+++ b/cmd/source_tree_size/Android.bp
@@ -1,4 +1,4 @@
-// Copyright 2023 Google Inc. All rights reserved.
+// 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.
@@ -12,11 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package genrule
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
-var (
- SandboxingDenyModuleList = []string{
- // go/keep-sorted start
- // go/keep-sorted end
- }
-)
+blueprint_go_binary {
+ name: "source_tree_size",
+ srcs: [
+ "source_tree.pb.go",
+ "source_tree_size.go",
+ ],
+ deps: [
+ "golang-protobuf-runtime-protoimpl",
+ ],
+}
diff --git a/cmd/source_tree_size/regen.sh b/cmd/source_tree_size/regen.sh
new file mode 100755
index 0000000..b0f1c80
--- /dev/null
+++ b/cmd/source_tree_size/regen.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. source_tree.proto
+
diff --git a/cmd/source_tree_size/source_tree.pb.go b/cmd/source_tree_size/source_tree.pb.go
new file mode 100644
index 0000000..da8cba5
--- /dev/null
+++ b/cmd/source_tree_size/source_tree.pb.go
@@ -0,0 +1,230 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: source_tree.proto
+
+package main
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type SourceFile struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Path *string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"`
+ SizeBytes *int32 `protobuf:"varint,2,opt,name=size_bytes,json=sizeBytes" json:"size_bytes,omitempty"`
+}
+
+func (x *SourceFile) Reset() {
+ *x = SourceFile{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_source_tree_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SourceFile) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SourceFile) ProtoMessage() {}
+
+func (x *SourceFile) ProtoReflect() protoreflect.Message {
+ mi := &file_source_tree_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SourceFile.ProtoReflect.Descriptor instead.
+func (*SourceFile) Descriptor() ([]byte, []int) {
+ return file_source_tree_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *SourceFile) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *SourceFile) GetSizeBytes() int32 {
+ if x != nil && x.SizeBytes != nil {
+ return *x.SizeBytes
+ }
+ return 0
+}
+
+type SourceTree struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Files []*SourceFile `protobuf:"bytes,1,rep,name=files" json:"files,omitempty"`
+}
+
+func (x *SourceTree) Reset() {
+ *x = SourceTree{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_source_tree_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SourceTree) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SourceTree) ProtoMessage() {}
+
+func (x *SourceTree) ProtoReflect() protoreflect.Message {
+ mi := &file_source_tree_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SourceTree.ProtoReflect.Descriptor instead.
+func (*SourceTree) Descriptor() ([]byte, []int) {
+ return file_source_tree_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *SourceTree) GetFiles() []*SourceFile {
+ if x != nil {
+ return x.Files
+ }
+ return nil
+}
+
+var File_source_tree_proto protoreflect.FileDescriptor
+
+var file_source_tree_proto_rawDesc = []byte{
+ 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65,
+ 0x73, 0x22, 0x3f, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12,
+ 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70,
+ 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74,
+ 0x65, 0x73, 0x22, 0x3c, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65,
+ 0x12, 0x2e, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x18, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73,
+ 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x6d, 0x61, 0x69, 0x6e,
+}
+
+var (
+ file_source_tree_proto_rawDescOnce sync.Once
+ file_source_tree_proto_rawDescData = file_source_tree_proto_rawDesc
+)
+
+func file_source_tree_proto_rawDescGZIP() []byte {
+ file_source_tree_proto_rawDescOnce.Do(func() {
+ file_source_tree_proto_rawDescData = protoimpl.X.CompressGZIP(file_source_tree_proto_rawDescData)
+ })
+ return file_source_tree_proto_rawDescData
+}
+
+var file_source_tree_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_source_tree_proto_goTypes = []interface{}{
+ (*SourceFile)(nil), // 0: source_files.SourceFile
+ (*SourceTree)(nil), // 1: source_files.SourceTree
+}
+var file_source_tree_proto_depIdxs = []int32{
+ 0, // 0: source_files.SourceTree.files:type_name -> source_files.SourceFile
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_source_tree_proto_init() }
+func file_source_tree_proto_init() {
+ if File_source_tree_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_source_tree_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SourceFile); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_source_tree_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SourceTree); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_source_tree_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_source_tree_proto_goTypes,
+ DependencyIndexes: file_source_tree_proto_depIdxs,
+ MessageInfos: file_source_tree_proto_msgTypes,
+ }.Build()
+ File_source_tree_proto = out.File
+ file_source_tree_proto_rawDesc = nil
+ file_source_tree_proto_goTypes = nil
+ file_source_tree_proto_depIdxs = nil
+}
diff --git a/genrule/allowlists.go b/cmd/source_tree_size/source_tree.proto
similarity index 61%
copy from genrule/allowlists.go
copy to cmd/source_tree_size/source_tree.proto
index 45a7f72..1a5b89f 100644
--- a/genrule/allowlists.go
+++ b/cmd/source_tree_size/source_tree.proto
@@ -1,10 +1,10 @@
-// Copyright 2023 Google Inc. All rights reserved.
+// 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
+// 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,
@@ -12,11 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package genrule
+syntax = "proto2";
-var (
- SandboxingDenyModuleList = []string{
- // go/keep-sorted start
- // go/keep-sorted end
- }
-)
+package source_files;
+option go_package = "./main";
+
+message SourceFile {
+ optional string path = 1;
+ optional int32 size_bytes = 2;
+}
+
+message SourceTree {
+ repeated SourceFile files = 1;
+}
diff --git a/cmd/source_tree_size/source_tree_size.go b/cmd/source_tree_size/source_tree_size.go
new file mode 100644
index 0000000..8b2a4cf
--- /dev/null
+++ b/cmd/source_tree_size/source_tree_size.go
@@ -0,0 +1,126 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "path/filepath"
+ "sort"
+ "strings"
+ "sync"
+
+ "google.golang.org/protobuf/proto"
+)
+
+var root string
+var repo string
+var outDir string
+var channel chan SourceFile
+var waiter sync.WaitGroup
+var sourceTree SourceTree
+
+func normalizeOutDir(outDir, root string) string {
+ if len(outDir) == 0 {
+ return ""
+ }
+ if filepath.IsAbs(outDir) {
+ if strings.HasPrefix(outDir, root) {
+ // Absolute path inside root, use it
+ return outDir
+ } else {
+ // Not inside root, we don't care about it
+ return ""
+ }
+ } else {
+ // Relative path inside root, make it absolute
+ return root + outDir
+ }
+}
+
+func walkDir(dir string) {
+ defer waiter.Done()
+
+ visit := func(path string, info os.FileInfo, err error) error {
+ name := info.Name()
+
+ // Repo git projects are symlinks. A real directory called .git counts as checked in
+ // (and is very likely to be wasted space)
+ if info.Mode().Type()&os.ModeSymlink != 0 && name == ".git" {
+ return nil
+ }
+
+ // Skip .repo and out
+ if info.IsDir() && (path == repo || path == outDir) {
+ return filepath.SkipDir
+ }
+
+ if info.IsDir() && path != dir {
+ waiter.Add(1)
+ go walkDir(path)
+ return filepath.SkipDir
+ }
+
+ if !info.IsDir() {
+ sourcePath := strings.TrimPrefix(path, root)
+ file := SourceFile{
+ Path: proto.String(sourcePath),
+ SizeBytes: proto.Int32(42),
+ }
+ channel <- file
+ }
+ return nil
+
+ }
+ filepath.Walk(dir, visit)
+}
+
+func main() {
+ var outputFile string
+ flag.StringVar(&outputFile, "o", "", "The file to write")
+ flag.StringVar(&outDir, "out_dir", "out", "The out directory")
+ flag.Parse()
+
+ if outputFile == "" {
+ fmt.Fprintf(os.Stderr, "source_tree_size: Missing argument: -o\n")
+ os.Exit(1)
+ }
+
+ root, _ = os.Getwd()
+ if root[len(root)-1] != '/' {
+ root += "/"
+ }
+
+ outDir = normalizeOutDir(outDir, root)
+ repo = path.Join(root, ".repo")
+
+ // The parallel scanning reduces the run time by about a minute
+ channel = make(chan SourceFile)
+ waiter.Add(1)
+ go walkDir(root)
+ go func() {
+ waiter.Wait()
+ close(channel)
+ }()
+ for sourceFile := range channel {
+ sourceTree.Files = append(sourceTree.Files, &sourceFile)
+ }
+
+ // Sort the results, for a stable output
+ sort.Slice(sourceTree.Files, func(i, j int) bool {
+ return *sourceTree.Files[i].Path < *sourceTree.Files[j].Path
+ })
+
+ // Flatten and write
+ buf, err := proto.Marshal(&sourceTree)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Couldn't marshal protobuf\n")
+ os.Exit(1)
+ }
+ err = ioutil.WriteFile(outputFile, buf, 0644)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
+ os.Exit(1)
+ }
+}
diff --git a/cmd/symbols_map/symbols_map.go b/cmd/symbols_map/symbols_map.go
index c56cf93..3955c8a 100644
--- a/cmd/symbols_map/symbols_map.go
+++ b/cmd/symbols_map/symbols_map.go
@@ -72,6 +72,7 @@
elfFile := flags.String("elf", "", "extract identifier from an elf file")
r8File := flags.String("r8", "", "extract identifier from an r8 dictionary")
+ locationFlag := flags.String("location", "", "an override for the value of the location field in the proto. If not specified, the filename will be used")
merge := flags.String("merge", "", "merge multiple identifier protos")
writeIfChanged := flags.Bool("write_if_changed", false, "only write output file if it is modified")
@@ -134,6 +135,10 @@
panic("shouldn't get here")
}
+ if *locationFlag != "" {
+ location = *locationFlag
+ }
+
mapping := symbols_map_proto.Mapping{
Identifier: proto.String(identifier),
Location: proto.String(location),
diff --git a/cmd/symbols_map/symbols_map_proto/regen.sh b/cmd/symbols_map/symbols_map_proto/regen.sh
new file mode 100755
index 0000000..3c189d1
--- /dev/null
+++ b/cmd/symbols_map/symbols_map_proto/regen.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. symbols_map.proto
+
diff --git a/cmd/symbols_map/symbols_map_proto/symbols_map.pb.go b/cmd/symbols_map/symbols_map_proto/symbols_map.pb.go
index f9c0ce5..07f4b39 100644
--- a/cmd/symbols_map/symbols_map_proto/symbols_map.pb.go
+++ b/cmd/symbols_map/symbols_map_proto/symbols_map.pb.go
@@ -14,8 +14,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.27.1
-// protoc v3.9.1
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
// source: symbols_map.proto
package symbols_map_proto
@@ -93,6 +93,68 @@
return file_symbols_map_proto_rawDescGZIP(), []int{0, 0}
}
+// LocationType is the place where to look for the file with the given
+// identifier.
+type Mapping_LocationType int32
+
+const (
+ // ZIP denotes the file with the given identifier is in the distribuited
+ // symbols.zip or proguard_dict.zip files, or the local disc.
+ Mapping_ZIP Mapping_LocationType = 0
+ // AB denotes the file with the given identifier is in the AB artifacts but
+ // not in a symbols.zip or proguard_dict.zip.
+ Mapping_AB Mapping_LocationType = 1
+)
+
+// Enum value maps for Mapping_LocationType.
+var (
+ Mapping_LocationType_name = map[int32]string{
+ 0: "ZIP",
+ 1: "AB",
+ }
+ Mapping_LocationType_value = map[string]int32{
+ "ZIP": 0,
+ "AB": 1,
+ }
+)
+
+func (x Mapping_LocationType) Enum() *Mapping_LocationType {
+ p := new(Mapping_LocationType)
+ *p = x
+ return p
+}
+
+func (x Mapping_LocationType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (Mapping_LocationType) Descriptor() protoreflect.EnumDescriptor {
+ return file_symbols_map_proto_enumTypes[1].Descriptor()
+}
+
+func (Mapping_LocationType) Type() protoreflect.EnumType {
+ return &file_symbols_map_proto_enumTypes[1]
+}
+
+func (x Mapping_LocationType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *Mapping_LocationType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = Mapping_LocationType(num)
+ return nil
+}
+
+// Deprecated: Use Mapping_LocationType.Descriptor instead.
+func (Mapping_LocationType) EnumDescriptor() ([]byte, []int) {
+ return file_symbols_map_proto_rawDescGZIP(), []int{0, 1}
+}
+
type Mapping struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -107,6 +169,9 @@
Location *string `protobuf:"bytes,2,opt,name=location" json:"location,omitempty"`
// type is the type of the mapping, either ELF or R8.
Type *Mapping_Type `protobuf:"varint,3,opt,name=type,enum=symbols_map.Mapping_Type" json:"type,omitempty"`
+ // location_type is the Location Type that dictates where to search for the
+ // file with the given identifier. Defaults to ZIP if not present.
+ LocationType *Mapping_LocationType `protobuf:"varint,4,opt,name=location_type,json=locationType,enum=symbols_map.Mapping_LocationType" json:"location_type,omitempty"`
}
func (x *Mapping) Reset() {
@@ -162,6 +227,13 @@
return Mapping_ELF
}
+func (x *Mapping) GetLocationType() Mapping_LocationType {
+ if x != nil && x.LocationType != nil {
+ return *x.LocationType
+ }
+ return Mapping_ZIP
+}
+
type Mappings struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -214,23 +286,29 @@
var file_symbols_map_proto_rawDesc = []byte{
0x0a, 0x11, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6d, 0x61, 0x70,
- 0x22, 0x8d, 0x01, 0x0a, 0x07, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0a,
+ 0x22, 0xf6, 0x01, 0x0a, 0x07, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0a,
0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08,
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73,
0x5f, 0x6d, 0x61, 0x70, 0x2e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x79, 0x70,
- 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x17, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
- 0x07, 0x0a, 0x03, 0x45, 0x4c, 0x46, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x52, 0x38, 0x10, 0x01,
- 0x22, 0x3c, 0x0a, 0x08, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x08,
- 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14,
+ 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x46, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21,
0x2e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x2e, 0x4d, 0x61, 0x70,
- 0x70, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x31,
- 0x5a, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f,
- 0x63, 0x6d, 0x64, 0x2f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x2f,
- 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x74,
- 0x6f,
+ 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70,
+ 0x65, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22,
+ 0x17, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4c, 0x46, 0x10, 0x00,
+ 0x12, 0x06, 0x0a, 0x02, 0x52, 0x38, 0x10, 0x01, 0x22, 0x1f, 0x0a, 0x0c, 0x4c, 0x6f, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x5a, 0x49, 0x50, 0x10,
+ 0x00, 0x12, 0x06, 0x0a, 0x02, 0x41, 0x42, 0x10, 0x01, 0x22, 0x3c, 0x0a, 0x08, 0x4d, 0x61, 0x70,
+ 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
+ 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+ 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x2e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x6d,
+ 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x31, 0x5a, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x73, 0x79, 0x6d,
+ 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x2f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73,
+ 0x5f, 0x6d, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -245,21 +323,23 @@
return file_symbols_map_proto_rawDescData
}
-var file_symbols_map_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_symbols_map_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_symbols_map_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_symbols_map_proto_goTypes = []interface{}{
- (Mapping_Type)(0), // 0: symbols_map.Mapping.Type
- (*Mapping)(nil), // 1: symbols_map.Mapping
- (*Mappings)(nil), // 2: symbols_map.Mappings
+ (Mapping_Type)(0), // 0: symbols_map.Mapping.Type
+ (Mapping_LocationType)(0), // 1: symbols_map.Mapping.LocationType
+ (*Mapping)(nil), // 2: symbols_map.Mapping
+ (*Mappings)(nil), // 3: symbols_map.Mappings
}
var file_symbols_map_proto_depIdxs = []int32{
0, // 0: symbols_map.Mapping.type:type_name -> symbols_map.Mapping.Type
- 1, // 1: symbols_map.Mappings.mappings:type_name -> symbols_map.Mapping
- 2, // [2:2] is the sub-list for method output_type
- 2, // [2:2] is the sub-list for method input_type
- 2, // [2:2] is the sub-list for extension type_name
- 2, // [2:2] is the sub-list for extension extendee
- 0, // [0:2] is the sub-list for field type_name
+ 1, // 1: symbols_map.Mapping.location_type:type_name -> symbols_map.Mapping.LocationType
+ 2, // 2: symbols_map.Mappings.mappings:type_name -> symbols_map.Mapping
+ 3, // [3:3] is the sub-list for method output_type
+ 3, // [3:3] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
}
func init() { file_symbols_map_proto_init() }
@@ -298,7 +378,7 @@
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_symbols_map_proto_rawDesc,
- NumEnums: 1,
+ NumEnums: 2,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
diff --git a/cmd/symbols_map/symbols_map_proto/symbols_map.proto b/cmd/symbols_map/symbols_map_proto/symbols_map.proto
index a76d171..a52f75c 100644
--- a/cmd/symbols_map/symbols_map_proto/symbols_map.proto
+++ b/cmd/symbols_map/symbols_map_proto/symbols_map.proto
@@ -40,7 +40,7 @@
// LocationType is the place where to look for the file with the given
// identifier.
- Enum LocationType {
+ enum LocationType {
// ZIP denotes the file with the given identifier is in the distribuited
// symbols.zip or proguard_dict.zip files, or the local disc.
ZIP = 0;
@@ -56,4 +56,4 @@
message Mappings {
repeated Mapping mappings = 4;
-}
\ No newline at end of file
+}
diff --git a/compliance/Android.bp b/compliance/Android.bp
index 6662970..25f6f86 100644
--- a/compliance/Android.bp
+++ b/compliance/Android.bp
@@ -34,7 +34,41 @@
name: "notice_xml_system",
partition_name: "system",
visibility: [
- "//build/make/target/product/generic",
- "//build/make/target/product/gsi",
+ "//visibility:any_system_partition",
],
}
+
+notice_xml {
+ name: "notice_xml_system_ext",
+ partition_name: "system_ext",
+}
+
+notice_xml {
+ name: "notice_xml_system_dlkm",
+ partition_name: "system_dlkm",
+}
+
+notice_xml {
+ name: "notice_xml_product",
+ partition_name: "product",
+}
+
+notice_xml {
+ name: "notice_xml_odm",
+ partition_name: "odm",
+}
+
+notice_xml {
+ name: "notice_xml_odm_dlkm",
+ partition_name: "odm_dlkm",
+}
+
+notice_xml {
+ name: "notice_xml_vendor",
+ partition_name: "vendor",
+}
+
+notice_xml {
+ name: "notice_xml_vendor_dlkm",
+ partition_name: "vendor_dlkm",
+}
diff --git a/compliance/notice.go b/compliance/notice.go
index edd1b34..c5b0fbe 100644
--- a/compliance/notice.go
+++ b/compliance/notice.go
@@ -71,12 +71,17 @@
}
func (nx *NoticeXmlModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ prodVars := ctx.Config().ProductVariables()
+ buildFingerprintFile := android.PathForArbitraryOutput(ctx, "target", "product", android.String(prodVars.DeviceName), "build_fingerprint.txt")
+ implicits := []android.Path{buildFingerprintFile}
+
output := android.PathForModuleOut(ctx, "NOTICE.xml.gz")
metadataDb := android.PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "compliance-metadata.db")
ctx.Build(pctx, android.BuildParams{
- Rule: genNoticeXmlRule,
- Input: metadataDb,
- Output: output,
+ Rule: genNoticeXmlRule,
+ Input: metadataDb,
+ Implicits: implicits,
+ Output: output,
Args: map[string]string{
"productOut": filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()),
"soongOut": ctx.Config().SoongOutDir(),
@@ -86,8 +91,10 @@
nx.outputFile = output.OutputPath
- installPath := android.PathForModuleInPartitionInstall(ctx, nx.props.Partition_name, "etc")
- ctx.PackageFile(installPath, "NOTICE.xml.gz", nx.outputFile)
+ if android.Bool(ctx.Config().ProductVariables().UseSoongNoticeXML) {
+ installPath := android.PathForModuleInPartitionInstall(ctx, nx.props.Partition_name, "etc")
+ ctx.InstallFile(installPath, "NOTICE.xml.gz", nx.outputFile)
+ }
}
func (nx *NoticeXmlModule) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/dexpreopt/Android.bp b/dexpreopt/Android.bp
index 679d066..dbc1922 100644
--- a/dexpreopt/Android.bp
+++ b/dexpreopt/Android.bp
@@ -9,6 +9,8 @@
"class_loader_context.go",
"config.go",
"dexpreopt.go",
+ "dexpreopt_tools_zip.go",
+ "system_server_zip.go",
"testing.go",
],
testSrcs: [
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index af1d33d..7f50912 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -291,6 +291,11 @@
// For prebuilts, library should have the same name as the source module.
lib = android.RemoveOptionalPrebuiltPrefix(lib)
+ // Bootclasspath libraries should not be added to CLC.
+ if android.InList(lib, ctx.Config().BootJars()) {
+ return nil
+ }
+
devicePath := UnknownInstallLibraryPath
if installPath == nil {
if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index e3804e5..af09dbc 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -139,6 +139,11 @@
// Returns all jars that system_server loads.
func (g *GlobalConfig) AllSystemServerJars(ctx android.PathContext) *android.ConfiguredJarList {
+ // dexpreopt does not initialize the soong config.
+ // Initialize the OncePer here.
+ if ctx.Config().OncePer == nil {
+ ctx.Config().OncePer = &android.OncePer{}
+ }
return ctx.Config().Once(allSystemServerJarsKey, func() interface{} {
res := g.AllPlatformSystemServerJars(ctx).AppendList(g.AllApexSystemServerJars(ctx))
return &res
@@ -464,8 +469,8 @@
func (d dex2oatDependencyTag) AllowDisabledModuleDependencyProxy(
ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
- return android.OtherModuleProviderOrDefault(
- ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt
+ return android.OtherModulePointerProviderOrDefault(
+ ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt
}
// Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that
@@ -507,36 +512,37 @@
// final variants, while prebuilt_postdeps needs to run before many of the
// PostDeps mutators, like the APEX mutators). Hence we need to dig out the
// prebuilt explicitly here instead.
- var dex2oatModule android.Module
- ctx.WalkDeps(func(child, parent android.Module) bool {
- if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
+ var dex2oatModule android.ModuleProxy
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ prebuiltInfo, isPrebuilt := android.OtherModuleProvider(ctx, child, android.PrebuiltModuleInfoProvider)
+ if android.EqualModules(parent, ctx.Module()) && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
// Found the source module, or prebuilt module that has replaced the source.
dex2oatModule = child
- if android.IsModulePrebuilt(child) {
+ if isPrebuilt {
return false // If it's the prebuilt we're done.
} else {
return true // Recurse to check if the source has a prebuilt dependency.
}
}
- if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
- if p := android.GetEmbeddedPrebuilt(child); p != nil && p.UsePrebuilt() {
+ if android.EqualModules(parent, dex2oatModule) && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
+ if isPrebuilt && prebuiltInfo.UsePrebuilt {
dex2oatModule = child // Found a prebuilt that should be used.
}
}
return false
})
- if dex2oatModule == nil {
+ if dex2oatModule.IsNil() {
// If this happens there's probably a missing call to AddToolDeps in DepsMutator.
panic(fmt.Sprintf("Failed to lookup %s dependency", dex2oatBin))
}
- dex2oatPath := dex2oatModule.(android.HostToolProvider).HostToolPath()
- if !dex2oatPath.Valid() {
+ dex2oatPath, ok := android.OtherModuleProvider(ctx, dex2oatModule, android.HostToolProviderInfoProvider)
+ if !ok || !dex2oatPath.HostToolPath.Valid() {
panic(fmt.Sprintf("Failed to find host tool path in %s", dex2oatModule))
}
- return dex2oatPath.Path()
+ return dex2oatPath.HostToolPath.Path()
}
// createGlobalSoongConfig creates a GlobalSoongConfig from the current context.
@@ -716,8 +722,9 @@
} else if global.EnableUffdGc == "false" {
android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "")
} else if global.EnableUffdGc == "default" {
- // Generated by `build/make/core/Makefile`.
+ // Generated by build/make/core/Makefile, or the android_device module in soong-only builds.
kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
+
// Determine the UFFD GC flag by the kernel version file.
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 7a39fa1..699a675 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -46,13 +46,14 @@
const SystemPartition = "/system/"
const SystemOtherPartition = "/system_other/"
+const SystemServerDexjarsDir = "system_server_dexjars"
var DexpreoptRunningInSoong = false
// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
func GenerateDexpreoptRule(ctx android.BuilderContext, globalSoong *GlobalSoongConfig,
- global *GlobalConfig, module *ModuleConfig, productPackages android.Path, copyApexSystemServerJarDex bool) (
+ global *GlobalConfig, module *ModuleConfig, productPackages android.Path) (
rule *android.RuleBuilder, err error) {
defer func() {
@@ -83,7 +84,7 @@
if !dexpreoptDisabled(ctx, global, module) {
if valid, err := validateClassLoaderContext(module.ClassLoaderContexts); err != nil {
- android.ReportPathErrorf(ctx, err.Error())
+ android.ReportPathErrorf(ctx, "%s", err.Error())
} else if valid {
fixClassLoaderContext(module.ClassLoaderContexts)
@@ -94,7 +95,7 @@
for archIdx, _ := range module.Archs {
dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage,
- generateDM, productPackages, copyApexSystemServerJarDex)
+ generateDM, productPackages)
}
}
}
@@ -231,7 +232,7 @@
func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig,
global *GlobalConfig, module *ModuleConfig, rule *android.RuleBuilder, archIdx int,
- profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path, copyApexSystemServerJarDex bool) {
+ profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path) {
arch := module.Archs[archIdx]
@@ -279,25 +280,10 @@
clcTarget = append(clcTarget, GetSystemServerDexLocation(ctx, global, lib))
}
- if DexpreoptRunningInSoong && copyApexSystemServerJarDex {
- // Copy the system server jar to a predefined location where dex2oat will find it.
- dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
- rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
- rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost)
- } else {
- // For Make modules the copy rule is generated in the makefiles, not in dexpreopt.sh.
- // This is necessary to expose the rule to Ninja, otherwise it has rules that depend on
- // the jar (namely, dexpreopt commands for all subsequent system server jars that have
- // this one in their class loader context), but no rule that creates it (because Ninja
- // cannot see the rule in the generated dexpreopt.sh script).
- }
-
clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]"
clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]"
- if systemServerClasspathJars.ContainsJar(module.Name) {
- checkSystemServerOrder(ctx, jarIndex)
- } else {
+ if !systemServerClasspathJars.ContainsJar(module.Name) {
// Standalone jars are loaded by separate class loaders with SYSTEMSERVERCLASSPATH as the
// parent.
clcHostString = "PCL[];" + clcHostString
@@ -581,34 +567,11 @@
func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.OutputPath {
if DexpreoptRunningInSoong {
// Soong module, just use the default output directory $OUT/soong.
- return android.PathForOutput(ctx, "system_server_dexjars", jar+".jar")
+ return android.PathForOutput(ctx, SystemServerDexjarsDir, jar+".jar")
} else {
// Make module, default output directory is $OUT (passed via the "null config" created
// by dexpreopt_gen). Append Soong subdirectory to match Soong module paths.
- return android.PathForOutput(ctx, "soong", "system_server_dexjars", jar+".jar")
- }
-}
-
-// Check the order of jars on the system server classpath and give a warning/error if a jar precedes
-// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't
-// have the dependency jar in the class loader context, and it won't be able to resolve any
-// references to its classes and methods.
-func checkSystemServerOrder(ctx android.PathContext, jarIndex int) {
- mctx, isModule := ctx.(android.ModuleContext)
- if isModule {
- config := GetGlobalConfig(ctx)
- jars := config.AllSystemServerClasspathJars(ctx)
- mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
- depIndex := jars.IndexOfJar(dep.Name())
- if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
- jar := jars.Jar(jarIndex)
- dep := jars.Jar(depIndex)
- mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+
- " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+
- " references from '%s' to '%s'.\n", jar, dep, jar, dep)
- }
- return true
- })
+ return android.PathForOutput(ctx, "soong", SystemServerDexjarsDir, jar+".jar")
}
}
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index 7512005..8033b48 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -205,9 +205,8 @@
panic(err)
}
}
- cpApexSscpServerJar := false // dexpreopt_gen operates on make modules, and since sscp libraries are in soong, this should be a noop
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(
- ctx, globalSoong, global, module, android.PathForTesting(productPackagesPath), cpApexSscpServerJar)
+ ctx, globalSoong, global, module, android.PathForTesting(productPackagesPath))
if err != nil {
panic(err)
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 7b0f51f..500b2ff 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -15,9 +15,10 @@
package dexpreopt
import (
- "android/soong/android"
"fmt"
"testing"
+
+ "android/soong/android"
)
func testSystemModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
@@ -103,7 +104,7 @@
module := testSystemModuleConfig(ctx, "test")
productPackages := android.PathForTesting("product_packages.txt")
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -163,7 +164,7 @@
for _, test := range tests {
global.PatternsOnSystemOther = test.patterns
for _, mt := range test.moduleTests {
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -198,7 +199,7 @@
global.ApexSystemServerJars = android.CreateTestConfiguredJarList(
[]string{"com.android.apex1:service-A"})
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -210,15 +211,6 @@
android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
- android.AssertStringListContains(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar")
-
- // rule with apex sscp cp as false
- rule, err = GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, false)
- if err != nil {
- t.Fatal(err)
- }
- android.AssertStringListDoesNotContain(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar")
-
// cleanup the global variable for test
DexpreoptRunningInSoong = oldDexpreoptRunningInSoong
}
@@ -241,7 +233,7 @@
global.ApexSystemServerJars = android.CreateTestConfiguredJarList(
[]string{"com.android.apex1:service-A"})
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -253,15 +245,6 @@
android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
- android.AssertStringListContains(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar")
-
- // rule with apex sscp cp as false
- rule, err = GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, false)
- if err != nil {
- t.Fatal(err)
- }
- android.AssertStringListDoesNotContain(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar")
-
// cleanup the global variable for test
DexpreoptRunningInSoong = oldDexpreoptRunningInSoong
}
@@ -277,7 +260,7 @@
global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(
[]string{"platform:service-A"})
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -301,7 +284,7 @@
global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(
[]string{"system_ext:service-A"})
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -325,7 +308,7 @@
global.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList(
[]string{"com.android.apex1:service-A"})
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -348,7 +331,7 @@
module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile"))
- rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages)
if err != nil {
t.Fatal(err)
}
@@ -394,7 +377,7 @@
result := preparers.RunTest(t)
ctx := result.TestContext
- ctx.SingletonForTests("dexpreopt-soong-config").Output("out/soong/dexpreopt/uffd_gc_flag.txt")
+ ctx.SingletonForTests(t, "dexpreopt-soong-config").Output("out/soong/dexpreopt/uffd_gc_flag.txt")
})
}
}
@@ -403,6 +386,7 @@
preparers := android.GroupFixturePreparers(
PrepareForTestWithFakeDex2oatd,
PrepareForTestWithDexpreoptConfig,
+ android.FixtureModifyConfig(android.SetKatiEnabledForTests),
FixtureSetEnableUffdGc("default"),
)
@@ -410,7 +394,7 @@
ctx := result.TestContext
config := ctx.Config()
- rule := ctx.SingletonForTests("dexpreopt-soong-config").Rule("dexpreopt_uffd_gc_flag")
+ rule := ctx.SingletonForTests(t, "dexpreopt-soong-config").Rule("dexpreopt_uffd_gc_flag")
android.AssertStringDoesContain(t, "", rule.RuleParams.Command, "construct_uffd_gc_flag")
android.AssertStringPathsRelativeToTopEquals(t, "", config, []string{
diff --git a/dexpreopt/dexpreopt_tools_zip.go b/dexpreopt/dexpreopt_tools_zip.go
new file mode 100644
index 0000000..c7cf128
--- /dev/null
+++ b/dexpreopt/dexpreopt_tools_zip.go
@@ -0,0 +1,62 @@
+package dexpreopt
+
+import "android/soong/android"
+
+func init() {
+ android.InitRegistrationContext.RegisterSingletonType("dexpreopt_tools_zip_singleton", dexpreoptToolsZipSingletonFactory)
+}
+
+func dexpreoptToolsZipSingletonFactory() android.Singleton {
+ return &dexpreoptToolsZipSingleton{}
+}
+
+type dexpreoptToolsZipSingleton struct{}
+
+func (s *dexpreoptToolsZipSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // The mac build doesn't build dex2oat, so create the zip file only if the build OS is linux.
+ if !ctx.Config().BuildOS.Linux() {
+ return
+ }
+ global := GetGlobalConfig(ctx)
+ if global.DisablePreopt {
+ return
+ }
+ config := GetCachedGlobalSoongConfig(ctx)
+ if config == nil {
+ return
+ }
+
+ deps := android.Paths{
+ ctx.Config().HostToolPath(ctx, "dexpreopt_gen"),
+ ctx.Config().HostToolPath(ctx, "dexdump"),
+ ctx.Config().HostToolPath(ctx, "oatdump"),
+ config.Profman,
+ config.Dex2oat,
+ config.Aapt,
+ config.SoongZip,
+ config.Zip2zip,
+ config.ManifestCheck,
+ config.ConstructContext,
+ config.UffdGcFlag,
+ }
+
+ out := android.PathForOutput(ctx, "dexpreopt_tools.zip")
+ builder := android.NewRuleBuilder(pctx, ctx)
+
+ cmd := builder.Command().BuiltTool("soong_zip").
+ Flag("-d").
+ FlagWithOutput("-o ", out).
+ Flag("-j")
+
+ for _, dep := range deps {
+ cmd.FlagWithInput("-f ", dep)
+ }
+
+ // This reads through a symlink to include the file it points to. This isn't great for
+ // build reproducibility, will need to be revisited later.
+ cmd.Textf("-f $(realpath %s)", config.Dex2oat)
+
+ builder.Build("dexpreopt_tools_zip", "building dexpreopt_tools.zip")
+
+ ctx.DistForGoal("droidcore", out)
+}
diff --git a/dexpreopt/system_server_zip.go b/dexpreopt/system_server_zip.go
new file mode 100644
index 0000000..cef847b
--- /dev/null
+++ b/dexpreopt/system_server_zip.go
@@ -0,0 +1,49 @@
+package dexpreopt
+
+import "android/soong/android"
+
+func init() {
+ android.InitRegistrationContext.RegisterSingletonType("system_server_zip_singleton", systemServerZipSingletonFactory)
+}
+
+func systemServerZipSingletonFactory() android.Singleton {
+ return &systemServerZipSingleton{}
+}
+
+type systemServerZipSingleton struct{}
+
+func (s *systemServerZipSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ global := GetGlobalConfig(ctx)
+ if global.DisablePreopt || global.OnlyPreoptArtBootImage {
+ return
+ }
+
+ systemServerDexjarsDir := android.PathForOutput(ctx, SystemServerDexjarsDir)
+
+ out := android.PathForOutput(ctx, "system_server.zip")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", out).
+ FlagWithArg("-C ", systemServerDexjarsDir.String())
+
+ for i := 0; i < global.SystemServerJars.Len(); i++ {
+ jar := global.SystemServerJars.Jar(i) + ".jar"
+ cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar))
+ }
+ for i := 0; i < global.StandaloneSystemServerJars.Len(); i++ {
+ jar := global.StandaloneSystemServerJars.Jar(i) + ".jar"
+ cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar))
+ }
+ for i := 0; i < global.ApexSystemServerJars.Len(); i++ {
+ jar := global.ApexSystemServerJars.Jar(i) + ".jar"
+ cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar))
+ }
+ for i := 0; i < global.ApexStandaloneSystemServerJars.Len(); i++ {
+ jar := global.ApexStandaloneSystemServerJars.Jar(i) + ".jar"
+ cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar))
+ }
+
+ builder.Build("system_server_zip", "building system_server.zip")
+
+ ctx.DistForGoal("droidcore", out)
+}
diff --git a/etc/avbpubkey.go b/etc/avbpubkey.go
index 3f998d4..dc242ce 100644
--- a/etc/avbpubkey.go
+++ b/etc/avbpubkey.go
@@ -51,6 +51,7 @@
Command: `${avbtool} extract_public_key --key ${in} --output ${out}.tmp` +
` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
CommandDeps: []string{"${avbtool}"},
+ Restat: true,
Description: "Extracting system_other avb key",
})
diff --git a/etc/install_symlink_test.go b/etc/install_symlink_test.go
index c97d97c..dce6873 100644
--- a/etc/install_symlink_test.go
+++ b/etc/install_symlink_test.go
@@ -39,7 +39,7 @@
t.Fatalf("expected 1 variant, got %#v", foo_variants)
}
- foo := result.ModuleForTests("foo", "android_common").Module()
+ foo := result.ModuleForTests(t, "foo", "android_common").Module()
androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
if len(androidMkEntries) != 1 {
t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
@@ -70,7 +70,7 @@
t.Fatalf("expected 1 variant, got %#v", foo_variants)
}
- foo := result.ModuleForTests("foo", "android_common").Module()
+ foo := result.ModuleForTests(t, "foo", "android_common").Module()
androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
if len(androidMkEntries) != 1 {
t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries))
@@ -149,7 +149,7 @@
`)
buildOS := result.Config.BuildOS.String()
- foo := result.ModuleForTests("foo", buildOS+"_common").Module()
+ foo := result.ModuleForTests(t, "foo", buildOS+"_common").Module()
androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo)
if len(androidMkEntries) != 1 {
diff --git a/etc/otacerts_zip.go b/etc/otacerts_zip.go
index 8220cea..53ddc50 100644
--- a/etc/otacerts_zip.go
+++ b/etc/otacerts_zip.go
@@ -111,6 +111,10 @@
return proptools.StringDefault(m.properties.Filename, "otacerts.zip")
}
+func (m *otacertsZipModule) onlyInRecovery() bool {
+ return m.ModuleBase.InstallInRecovery()
+}
+
func (m *otacertsZipModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Read .x509.pem file defined in PRODUCT_DEFAULT_DEV_CERTIFICATE or the default test key.
pem, _ := ctx.Config().DefaultAppCertificate(ctx)
@@ -136,7 +140,7 @@
func (m *otacertsZipModule) AndroidMkEntries() []android.AndroidMkEntries {
nameSuffix := ""
- if m.InRecovery() {
+ if m.InRecovery() && !m.onlyInRecovery() {
nameSuffix = ".recovery"
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 3d1e242..7820047 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -32,6 +32,7 @@
"path/filepath"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -60,9 +61,11 @@
ctx.RegisterModuleType("prebuilt_usr_keychars", PrebuiltUserKeyCharsFactory)
ctx.RegisterModuleType("prebuilt_usr_idc", PrebuiltUserIdcFactory)
ctx.RegisterModuleType("prebuilt_usr_srec", PrebuiltUserSrecFactory)
+ ctx.RegisterModuleType("prebuilt_usr_odml", PrebuiltUserOdmlFactory)
ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
ctx.RegisterModuleType("prebuilt_overlay", PrebuiltOverlayFactory)
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
+ ctx.RegisterModuleType("prebuilt_gpu", PrebuiltGPUFactory)
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory)
ctx.RegisterModuleType("prebuilt_renderscript_bitcode", PrebuiltRenderScriptBitcodeFactory)
@@ -71,12 +74,15 @@
ctx.RegisterModuleType("prebuilt_bin", PrebuiltBinaryFactory)
ctx.RegisterModuleType("prebuilt_wallpaper", PrebuiltWallpaperFactory)
ctx.RegisterModuleType("prebuilt_priv_app", PrebuiltPrivAppFactory)
+ ctx.RegisterModuleType("prebuilt_radio", PrebuiltRadioFactory)
ctx.RegisterModuleType("prebuilt_rfs", PrebuiltRfsFactory)
ctx.RegisterModuleType("prebuilt_framework", PrebuiltFrameworkFactory)
ctx.RegisterModuleType("prebuilt_res", PrebuiltResFactory)
+ ctx.RegisterModuleType("prebuilt_tee", PrebuiltTeeFactory)
ctx.RegisterModuleType("prebuilt_wlc_upt", PrebuiltWlcUptFactory)
ctx.RegisterModuleType("prebuilt_odm", PrebuiltOdmFactory)
ctx.RegisterModuleType("prebuilt_vendor_dlkm", PrebuiltVendorDlkmFactory)
+ ctx.RegisterModuleType("prebuilt_vendor_overlay", PrebuiltVendorOverlayFactory)
ctx.RegisterModuleType("prebuilt_bt_firmware", PrebuiltBtFirmwareFactory)
ctx.RegisterModuleType("prebuilt_tvservice", PrebuiltTvServiceFactory)
ctx.RegisterModuleType("prebuilt_optee", PrebuiltOpteeFactory)
@@ -91,6 +97,15 @@
}
+type PrebuiltEtcInfo struct {
+ // Returns the base install directory, such as "etc", "usr/share".
+ BaseDir string
+ // Returns the sub install directory relative to BaseDir().
+ SubDir string
+}
+
+var PrebuiltEtcInfoProvider = blueprint.NewProvider[PrebuiltEtcInfo]()
+
var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
type PrebuiltEtcProperties struct {
@@ -510,7 +525,28 @@
ip.addInstallRules(ctx)
}
+ p.updateModuleInfoJSON(ctx)
+
ctx.SetOutputFiles(p.outputFilePaths.Paths(), "")
+
+ SetCommonPrebuiltEtcInfo(ctx, p)
+}
+
+func SetCommonPrebuiltEtcInfo(ctx android.ModuleContext, p PrebuiltEtcModule) {
+ android.SetProvider(ctx, PrebuiltEtcInfoProvider, PrebuiltEtcInfo{
+ BaseDir: p.BaseDir(),
+ SubDir: p.SubDir(),
+ })
+}
+
+func (p *PrebuiltEtc) updateModuleInfoJSON(ctx android.ModuleContext) {
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"ETC"}
+ if p.makeClass != "" {
+ moduleInfoJSON.Class = []string{p.makeClass}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+ moduleInfoJSON.Tags = []string{"optional"}
}
type installProperties struct {
@@ -782,6 +818,17 @@
return module
}
+// prebuilt_usr_odml is for a prebuilt artifact that is installed in
+// <partition>/usr/odml/<sub_dir> directory.
+func PrebuiltUserOdmlFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "usr/odml")
+ // 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{}
@@ -815,6 +862,15 @@
return module
}
+// prebuilt_gpu is for a prebuilt artifact in <partition>/gpu directory.
+func PrebuiltGPUFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "gpu")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
// prebuilt_dsp installs a DSP related file to <partition>/etc/dsp directory for system image.
// If soc_specific property is set to true, the DSP related file is installed to the
// vendor <partition>/dsp directory for vendor image.
@@ -855,6 +911,16 @@
return module
}
+// prebuilt_tee installs files in <partition>/tee directory.
+func PrebuiltTeeFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "tee")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_media installs media files in <partition>/media directory.
func PrebuiltMediaFactory() android.Module {
module := &PrebuiltEtc{}
@@ -905,6 +971,16 @@
return module
}
+// prebuilt_radio installs files in <partition>/radio directory.
+func PrebuiltRadioFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "radio")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_rfs installs files in <partition>/rfs directory.
func PrebuiltRfsFactory() android.Module {
module := &PrebuiltEtc{}
@@ -1015,6 +1091,16 @@
return module
}
+// prebuilt_vendor_overlay is for a prebuilt artifact in <partition>/vendor_overlay directory.
+func PrebuiltVendorOverlayFactory() android.Module {
+ module := &PrebuiltEtc{}
+ InitPrebuiltEtcModule(module, "vendor_overlay")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_sbin installs files in <partition>/sbin directory.
func PrebuiltSbinFactory() android.Module {
module := &PrebuiltEtc{}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 0fd04d8..eb722b4 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -133,8 +133,8 @@
android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base())
expectedPaths := [...]string{
- "out/soong/target/product/test_device/system/etc/foodir",
- "out/soong/target/product/test_device/system/etc/bardir/extradir",
+ "out/target/product/test_device/system/etc/foodir",
+ "out/target/product/test_device/system/etc/bardir/extradir",
}
android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0])
android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1])
@@ -155,8 +155,8 @@
android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base())
expectedPaths := [...]string{
- "out/soong/target/product/test_device/system/etc/somewhere/foodir",
- "out/soong/target/product/test_device/system/etc/somewhere/bardir/extradir",
+ "out/target/product/test_device/system/etc/somewhere/foodir",
+ "out/target/product/test_device/system/etc/somewhere/bardir/extradir",
}
android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0])
android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1])
@@ -271,7 +271,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/etc/bar"
+ expected := "out/target/product/test_device/system/etc/bar"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -324,7 +324,7 @@
`)
android.AssertStringEquals(t, "expected error rule", "android/soong/android.Error",
- result.ModuleForTests("foo.conf", "android_arm64_armv8-a").Output("foo.conf").Rule.String())
+ result.ModuleForTests(t, "foo.conf", "android_arm64_armv8-a").Output("foo.conf").Rule.String())
}
func TestPrebuiltRootInstallDirPath(t *testing.T) {
@@ -337,7 +337,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system"
+ expected := "out/target/product/test_device/system"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -362,7 +362,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/root/avb"
+ expected := "out/target/product/test_device/root/avb"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -386,7 +386,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/usr/share/bar"
+ expected := "out/target/product/test_device/system/usr/share/bar"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -401,7 +401,7 @@
buildOS := result.Config.BuildOS.String()
p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc)
- expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "usr", "share", "bar")
+ expected := filepath.Join("out/host", result.Config.PrebuiltOS(), "usr", "share", "bar")
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -415,7 +415,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar"
+ expected := "out/target/product/test_device/system/usr/hyphen-data/bar"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -429,7 +429,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/usr/keylayout/bar"
+ expected := "out/target/product/test_device/system/usr/keylayout/bar"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -443,7 +443,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/usr/keychars/bar"
+ expected := "out/target/product/test_device/system/usr/keychars/bar"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -457,7 +457,7 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/usr/idc/bar"
+ expected := "out/target/product/test_device/system/usr/idc/bar"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -470,7 +470,7 @@
`)
p := result.Module("foo.conf", "android_common").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/fonts"
+ expected := "out/target/product/test_device/system/fonts"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
@@ -483,12 +483,12 @@
`)
p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/system/overlay"
+ expected := "out/target/product/test_device/system/overlay"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
func TestPrebuiltFirmwareDirPath(t *testing.T) {
- targetPath := "out/soong/target/product/test_device"
+ targetPath := "out/target/product/test_device"
tests := []struct {
description string
config string
@@ -522,7 +522,7 @@
}
func TestPrebuiltDSPDirPath(t *testing.T) {
- targetPath := "out/soong/target/product/test_device"
+ targetPath := "out/target/product/test_device"
tests := []struct {
description string
config string
@@ -556,7 +556,7 @@
}
func TestPrebuiltRFSADirPath(t *testing.T) {
- targetPath := "out/soong/target/product/test_device"
+ targetPath := "out/target/product/test_device"
tests := []struct {
description string
config string
@@ -600,6 +600,6 @@
`)
p := result.Module("foo", "android_common").(*PrebuiltEtc)
- expected := "out/soong/target/product/test_device/product/media/alarms"
+ expected := "out/target/product/test_device/product/media/alarms"
android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0])
}
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 127faa7..cb76df2 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -17,6 +17,7 @@
srcs: [
"aconfig_files.go",
"android_device.go",
+ "android_device_product_out.go",
"avb_add_hash_footer.go",
"avb_gen_vbmeta_image.go",
"bootimg.go",
@@ -27,6 +28,7 @@
"raw_binary.go",
"super_image.go",
"system_image.go",
+ "system_other.go",
"vbmeta.go",
"testing.go",
],
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index c80ae03..20a1953 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -16,50 +16,127 @@
import (
"android/soong/android"
+ "strconv"
+ "strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
-func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, dir android.OutputPath) {
+func init() {
+ pctx.HostBinToolVariable("aconfig", "aconfig")
+}
+
+var (
+ aconfigCreateStorage = pctx.AndroidStaticRule("aconfig_create_storage", blueprint.RuleParams{
+ Command: `$aconfig create-storage --container $container --file $fileType --out $out --cache $in --version $version`,
+ CommandDeps: []string{"$aconfig"},
+ }, "container", "fileType", "version")
+
+ subPartitionsInPartition = map[string][]string{
+ "system": {"system_ext", "product", "vendor"},
+ "vendor": {"odm"},
+ }
+)
+
+func (f *filesystem) buildAconfigFlagsFiles(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ specs map[string]android.PackagingSpec,
+ dir android.OutputPath,
+ fullInstallPaths *[]FullInstallPathInfo,
+) {
if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) {
return
}
+ partition := f.PartitionType()
+ subPartitionsFound := map[string]bool{}
+ fullInstallPath := android.PathForModuleInPartitionInstall(ctx, partition)
+
+ for _, subPartition := range subPartitionsInPartition[partition] {
+ subPartitionsFound[subPartition] = false
+ }
+
var caches []android.Path
for _, ps := range specs {
caches = append(caches, ps.GetAconfigPaths()...)
+ for subPartition, found := range subPartitionsFound {
+ if !found && strings.HasPrefix(ps.RelPathInPackage(), subPartition+"/") {
+ subPartitionsFound[subPartition] = true
+ break
+ }
+ }
}
caches = android.SortedUniquePaths(caches)
- installAconfigFlagsPath := dir.Join(ctx, "etc", "aconfig_flags.pb")
- cmd := builder.Command().
- BuiltTool("aconfig").
- Text(" dump-cache --dedup --format protobuf --out").
- Output(installAconfigFlagsPath).
- Textf("--filter container:%s", f.PartitionType())
- for _, cache := range caches {
- cmd.FlagWithInput("--cache ", cache)
- }
- f.appendToEntry(ctx, installAconfigFlagsPath)
-
- installAconfigStorageDir := dir.Join(ctx, "etc", "aconfig")
- builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String())
-
- generatePartitionAconfigStorageFile := func(fileType, fileName string) {
- outputPath := installAconfigStorageDir.Join(ctx, fileName)
- builder.Command().
+ buildAconfigFlagsFiles := func(container string, dir android.OutputPath, fullInstallPath android.InstallPath) {
+ aconfigFlagsPb := android.PathForModuleOut(ctx, "aconfig", container, "aconfig_flags.pb")
+ aconfigFlagsPbBuilder := android.NewRuleBuilder(pctx, ctx)
+ cmd := aconfigFlagsPbBuilder.Command().
BuiltTool("aconfig").
- FlagWithArg("create-storage --container ", f.PartitionType()).
- FlagWithArg("--file ", fileType).
- FlagWithOutput("--out ", outputPath).
- FlagWithArg("--cache ", installAconfigFlagsPath.String())
- f.appendToEntry(ctx, outputPath)
+ Text(" dump-cache --dedup --format protobuf --out").
+ Output(aconfigFlagsPb).
+ Textf("--filter container:%s+state:ENABLED", container).
+ Textf("--filter container:%s+permission:READ_WRITE", container)
+ for _, cache := range caches {
+ cmd.FlagWithInput("--cache ", cache)
+ }
+ aconfigFlagsPbBuilder.Build(container+"_aconfig_flags_pb", "build aconfig_flags.pb")
+
+ installEtcDir := dir.Join(ctx, "etc")
+ installAconfigFlagsPath := installEtcDir.Join(ctx, "aconfig_flags.pb")
+ builder.Command().Text("mkdir -p ").Text(installEtcDir.String())
+ builder.Command().Text("cp").Input(aconfigFlagsPb).Text(installAconfigFlagsPath.String())
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig_flags.pb"),
+ SourcePath: aconfigFlagsPb,
+ })
+ f.appendToEntry(ctx, installAconfigFlagsPath)
+
+ // To enable fingerprint, we need to have v2 storage files. The default version is 1.
+ storageFilesVersion := 1
+ if ctx.Config().ReleaseFingerprintAconfigPackages() {
+ storageFilesVersion = 2
+ }
+
+ installAconfigStorageDir := installEtcDir.Join(ctx, "aconfig")
+ builder.Command().Text("mkdir -p").Text(installAconfigStorageDir.String())
+
+ generatePartitionAconfigStorageFile := func(fileType, fileName string) {
+ outPath := android.PathForModuleOut(ctx, "aconfig", container, fileName)
+ installPath := installAconfigStorageDir.Join(ctx, fileName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aconfigCreateStorage,
+ Input: aconfigFlagsPb,
+ Output: outPath,
+ Args: map[string]string{
+ "container": container,
+ "fileType": fileType,
+ "version": strconv.Itoa(storageFilesVersion),
+ },
+ })
+ builder.Command().
+ Text("cp").Input(outPath).Text(installPath.String())
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ SourcePath: outPath,
+ FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig", fileName),
+ })
+ f.appendToEntry(ctx, installPath)
+ }
+
+ if ctx.Config().ReleaseCreateAconfigStorageFile() {
+ generatePartitionAconfigStorageFile("package_map", "package.map")
+ generatePartitionAconfigStorageFile("flag_map", "flag.map")
+ generatePartitionAconfigStorageFile("flag_val", "flag.val")
+ generatePartitionAconfigStorageFile("flag_info", "flag.info")
+ }
}
- if ctx.Config().ReleaseCreateAconfigStorageFile() {
- generatePartitionAconfigStorageFile("package_map", "package.map")
- generatePartitionAconfigStorageFile("flag_map", "flag.map")
- generatePartitionAconfigStorageFile("flag_val", "flag.val")
- generatePartitionAconfigStorageFile("flag_info", "flag.info")
+ buildAconfigFlagsFiles(partition, dir, fullInstallPath)
+ for _, subPartition := range android.SortedKeys(subPartitionsFound) {
+ if subPartitionsFound[subPartition] {
+ buildAconfigFlagsFiles(subPartition, dir.Join(ctx, subPartition), fullInstallPath.Join(ctx, subPartition))
+ }
}
}
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index ab1b96e..8b6ea49 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -15,49 +15,138 @@
package filesystem
import (
+ "cmp"
+ "fmt"
+ "path/filepath"
+ "slices"
+ "sort"
+ "strings"
+ "sync/atomic"
+
"android/soong/android"
+ "android/soong/java"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
+var proguardDictToProto = pctx.AndroidStaticRule("proguard_dict_to_proto", blueprint.RuleParams{
+ Command: `${symbols_map} -r8 $in -location $location -write_if_changed $out`,
+ Restat: true,
+ CommandDeps: []string{"${symbols_map}"},
+}, "location")
+
type PartitionNameProperties struct {
- // Name of the Boot_partition_name partition filesystem module
+ // Name of the super partition filesystem module
+ Super_partition_name *string
+ // Name of the boot partition filesystem module
Boot_partition_name *string
- // Name of the System partition filesystem module
+ // Name of the vendor boot partition filesystem module
+ Vendor_boot_partition_name *string
+ // Name of the init boot partition filesystem module
+ Init_boot_partition_name *string
+ // Name of the system partition filesystem module
System_partition_name *string
- // Name of the System_ext partition filesystem module
+ // Name of the system_ext partition filesystem module
System_ext_partition_name *string
- // Name of the Product partition filesystem module
+ // Name of the product partition filesystem module
Product_partition_name *string
- // Name of the Vendor partition filesystem module
+ // Name of the vendor partition filesystem module
Vendor_partition_name *string
- // Name of the Odm partition filesystem module
+ // Name of the odm partition filesystem module
Odm_partition_name *string
+ // Name of the recovery partition filesystem module
+ Recovery_partition_name *string
// The vbmeta partition and its "chained" partitions
Vbmeta_partitions []string
- // Name of the Userdata partition filesystem module
+ // Name of the userdata partition filesystem module
Userdata_partition_name *string
+ // Name of the system_dlkm partition filesystem module
+ System_dlkm_partition_name *string
+ // Name of the vendor_dlkm partition filesystem module
+ Vendor_dlkm_partition_name *string
+ // Name of the odm_dlkm partition filesystem module
+ Odm_dlkm_partition_name *string
+}
+
+type DeviceProperties struct {
+ // Path to the prebuilt bootloader that would be copied to PRODUCT_OUT
+ Bootloader *string `android:"path"`
+ // Path to android-info.txt file containing board specific info.
+ Android_info *string `android:"path"`
+ // If this is the "main" android_device target for the build, i.e. the one that gets built
+ // when running a plain `m` command. Currently, this is the autogenerated android_device module
+ // in soong-only builds, but in the future when we check in android_device modules, the main
+ // one will be determined based on the lunch product. TODO: Figure out how to make this
+ // blueprint:"mutated" and still set it from filesystem_creator
+ Main_device *bool
+
+ Ab_ota_updater *bool
+ Ab_ota_partitions []string
+ Ab_ota_keys []string
+ Ab_ota_postinstall_config []string
+
+ Ramdisk_node_list *string `android:"path"`
+ Releasetools_extension *string `android:"path"`
+ FastbootInfo *string `android:"path"`
+
+ Partial_ota_update_partitions []string
+ Flash_block_size *string
+ Bootloader_in_update_package *bool
+
+ // The kernel version in the build. Will be verified against the actual kernel.
+ // If not provided, will attempt to extract it from the loose kernel or the kernel inside
+ // the boot image. The version is later used to decide whether or not to enable uffd_gc
+ // when dexpreopting apps. So setting this doesn't really do anything except enforce that the
+ // actual kernel version is as specified here.
+ Kernel_version *string
}
type androidDevice struct {
android.ModuleBase
partitionProps PartitionNameProperties
+
+ deviceProps DeviceProperties
+
+ allImagesZip android.Path
+
+ proguardDictZip android.Path
+ proguardDictMapping android.Path
+ proguardUsageZip android.Path
+ kernelConfig android.Path
+ kernelVersion android.Path
+ miscInfo android.Path
+ rootDirForFsConfig string
+ rootDirForFsConfigTimestamp android.Path
+ apkCertsInfo android.Path
+ targetFilesZip android.Path
+ updatePackage android.Path
}
func AndroidDeviceFactory() android.Module {
module := &androidDevice{}
- module.AddProperties(&module.partitionProps)
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ module.AddProperties(&module.partitionProps, &module.deviceProps)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibFirst)
return module
}
+var numMainAndroidDevicesOnceKey android.OnceKey = android.NewOnceKey("num_auto_generated_anroid_devices")
+
type partitionDepTagType struct {
blueprint.BaseDependencyTag
}
+type superPartitionDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+type targetFilesMetadataDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var superPartitionDepTag superPartitionDepTagType
var filesystemDepTag partitionDepTagType
+var targetFilesMetadataDepTag targetFilesMetadataDepTagType
func (a *androidDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
addDependencyIfDefined := func(dep *string) {
@@ -66,18 +155,1020 @@
}
}
+ if a.partitionProps.Super_partition_name != nil {
+ ctx.AddDependency(ctx.Module(), superPartitionDepTag, *a.partitionProps.Super_partition_name)
+ }
addDependencyIfDefined(a.partitionProps.Boot_partition_name)
+ addDependencyIfDefined(a.partitionProps.Init_boot_partition_name)
+ addDependencyIfDefined(a.partitionProps.Vendor_boot_partition_name)
addDependencyIfDefined(a.partitionProps.System_partition_name)
addDependencyIfDefined(a.partitionProps.System_ext_partition_name)
addDependencyIfDefined(a.partitionProps.Product_partition_name)
addDependencyIfDefined(a.partitionProps.Vendor_partition_name)
addDependencyIfDefined(a.partitionProps.Odm_partition_name)
addDependencyIfDefined(a.partitionProps.Userdata_partition_name)
+ addDependencyIfDefined(a.partitionProps.System_dlkm_partition_name)
+ addDependencyIfDefined(a.partitionProps.Vendor_dlkm_partition_name)
+ addDependencyIfDefined(a.partitionProps.Odm_dlkm_partition_name)
+ addDependencyIfDefined(a.partitionProps.Recovery_partition_name)
for _, vbmetaPartition := range a.partitionProps.Vbmeta_partitions {
ctx.AddDependency(ctx.Module(), filesystemDepTag, vbmetaPartition)
}
+ a.addDepsForTargetFilesMetadata(ctx)
+}
+
+func (a *androidDevice) addDepsForTargetFilesMetadata(ctx android.BottomUpMutatorContext) {
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), targetFilesMetadataDepTag, "liblz4") // host variant
}
func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if proptools.Bool(a.deviceProps.Main_device) {
+ numMainAndroidDevices := ctx.Config().Once(numMainAndroidDevicesOnceKey, func() interface{} {
+ return &atomic.Int32{}
+ }).(*atomic.Int32)
+ total := numMainAndroidDevices.Add(1)
+ if total > 1 {
+ // There should only be 1 main android_device module. That one will be
+ // made the default thing to build in soong-only builds.
+ ctx.ModuleErrorf("There cannot be more than 1 main android_device module")
+ }
+ }
+ allInstalledModules := a.allInstalledModules(ctx)
+
+ a.apkCertsInfo = a.buildApkCertsInfo(ctx, allInstalledModules)
+ a.kernelVersion, a.kernelConfig = a.extractKernelVersionAndConfigs(ctx)
+ a.miscInfo = a.addMiscInfo(ctx)
+ a.buildTargetFilesZip(ctx, allInstalledModules)
+ a.buildProguardZips(ctx, allInstalledModules)
+ a.buildUpdatePackage(ctx)
+
+ var deps []android.Path
+ if proptools.String(a.partitionProps.Super_partition_name) != "" {
+ superImage := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, superImage, SuperImageProvider); ok {
+ assertUnset := func(prop *string, propName string) {
+ if prop != nil && *prop != "" {
+ ctx.PropertyErrorf(propName, "Cannot be set because it's already part of the super image")
+ }
+ }
+ for _, subPartitionType := range android.SortedKeys(info.SubImageInfo) {
+ switch subPartitionType {
+ case "system":
+ assertUnset(a.partitionProps.System_partition_name, "system_partition_name")
+ case "system_ext":
+ assertUnset(a.partitionProps.System_ext_partition_name, "system_ext_partition_name")
+ case "system_dlkm":
+ assertUnset(a.partitionProps.System_dlkm_partition_name, "system_dlkm_partition_name")
+ case "system_other":
+ // TODO
+ case "product":
+ assertUnset(a.partitionProps.Product_partition_name, "product_partition_name")
+ case "vendor":
+ assertUnset(a.partitionProps.Vendor_partition_name, "vendor_partition_name")
+ case "vendor_dlkm":
+ assertUnset(a.partitionProps.Vendor_dlkm_partition_name, "vendor_dlkm_partition_name")
+ case "odm":
+ assertUnset(a.partitionProps.Odm_partition_name, "odm_partition_name")
+ case "odm_dlkm":
+ assertUnset(a.partitionProps.Odm_dlkm_partition_name, "odm_dlkm_partition_name")
+ default:
+ ctx.ModuleErrorf("Unsupported sub-partition of super partition: %q", subPartitionType)
+ }
+ }
+
+ deps = append(deps, info.SuperImage)
+ } else {
+ ctx.ModuleErrorf("Expected super image dep to provide SuperImageProvider")
+ }
+ }
+ ctx.VisitDirectDepsProxyWithTag(filesystemDepTag, func(m android.ModuleProxy) {
+ imageOutput, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider)
+ if !ok {
+ ctx.ModuleErrorf("Partition module %s doesn't set OutputfilesProvider", m.Name())
+ }
+ if len(imageOutput.DefaultOutputFiles) != 1 {
+ ctx.ModuleErrorf("Partition module %s should provide exact 1 output file", m.Name())
+ }
+ deps = append(deps, imageOutput.DefaultOutputFiles[0])
+ })
+
+ allImagesZip := android.PathForModuleOut(ctx, "all_images.zip")
+ allImagesZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ cmd := allImagesZipBuilder.Command().BuiltTool("soong_zip")
+ for _, dep := range deps {
+ cmd.FlagWithArg("-e ", dep.Base())
+ cmd.FlagWithInput("-f ", dep)
+ }
+ cmd.FlagWithOutput("-o ", allImagesZip)
+ allImagesZipBuilder.Build("soong_all_images_zip", "all_images.zip")
+ a.allImagesZip = allImagesZip
+
+ allImagesStamp := android.PathForModuleOut(ctx, "all_images_stamp")
+ var validations android.Paths
+ if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) {
+ // In soong-only builds, build this module by default.
+ // This is the analogue to this make code:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/main.mk;l=1396;drc=6595459cdd8164a6008335f6372c9f97b9094060
+ ctx.Phony("droidcore-unbundled", allImagesStamp)
+
+ deps = append(deps, a.copyFilesToProductOutForSoongOnly(ctx))
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: allImagesStamp,
+ Implicits: deps,
+ Validations: validations,
+ })
+
+ // Checkbuilding it causes soong to make a phony, so you can say `m <module name>`
+ ctx.CheckbuildFile(allImagesStamp)
+
+ a.setVbmetaPhonyTargets(ctx)
+
+ a.distFiles(ctx)
+
+ android.SetProvider(ctx, android.AndroidDeviceInfoProvider, android.AndroidDeviceInfo{
+ Main_device: android.Bool(a.deviceProps.Main_device),
+ })
+
+ if proptools.String(a.partitionProps.Super_partition_name) != "" {
+ buildComplianceMetadata(ctx, superPartitionDepTag, filesystemDepTag)
+ } else {
+ buildComplianceMetadata(ctx, filesystemDepTag)
+ }
+}
+
+func buildComplianceMetadata(ctx android.ModuleContext, tags ...blueprint.DependencyTag) {
+ // Collect metadata from deps
+ filesContained := make([]string, 0)
+ prebuiltFilesCopied := make([]string, 0)
+ for _, tag := range tags {
+ ctx.VisitDirectDepsProxyWithTag(tag, func(m android.ModuleProxy) {
+ if complianceMetadataInfo, ok := android.OtherModuleProvider(ctx, m, android.ComplianceMetadataProvider); ok {
+ filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...)
+ prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
+ }
+ })
+ }
+ // Merge to module's ComplianceMetadataInfo
+ complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+ filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...)
+ sort.Strings(filesContained)
+ complianceMetadataInfo.SetFilesContained(filesContained)
+
+ prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
+ sort.Strings(prebuiltFilesCopied)
+ complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied)
+}
+
+// Returns a list of modules that are installed, which are collected from the dependency
+// filesystem and super_image modules.
+func (a *androidDevice) allInstalledModules(ctx android.ModuleContext) []android.Module {
+ fsInfoMap := a.getFsInfos(ctx)
+ allOwners := make(map[string][]string)
+ for _, partition := range android.SortedKeys(fsInfoMap) {
+ fsInfo := fsInfoMap[partition]
+ for _, owner := range fsInfo.Owners {
+ allOwners[owner.Name] = append(allOwners[owner.Name], owner.Variation)
+ }
+ }
+
+ ret := []android.Module{}
+ ctx.WalkDepsProxy(func(mod, _ android.ModuleProxy) bool {
+ if variations, ok := allOwners[ctx.OtherModuleName(mod)]; ok && android.InList(ctx.OtherModuleSubDir(mod), variations) {
+ ret = append(ret, mod)
+ }
+ return true
+ })
+
+ // Remove duplicates
+ ret = android.FirstUniqueFunc(ret, func(a, b android.Module) bool {
+ return a.String() == b.String()
+ })
+
+ // Sort the modules by their names and variants
+ slices.SortFunc(ret, func(a, b android.Module) int {
+ return cmp.Compare(a.String(), b.String())
+ })
+ return ret
+}
+
+func insertBeforeExtension(file, insertion string) string {
+ ext := filepath.Ext(file)
+ return strings.TrimSuffix(file, ext) + insertion + ext
+}
+
+func (a *androidDevice) distInstalledFiles(ctx android.ModuleContext) {
+ distInstalledFilesJsonAndTxt := func(installedFiles InstalledFilesStruct) {
+ if installedFiles.Json != nil {
+ ctx.DistForGoal("droidcore-unbundled", installedFiles.Json)
+ }
+ if installedFiles.Txt != nil {
+ ctx.DistForGoal("droidcore-unbundled", installedFiles.Txt)
+ }
+ }
+
+ fsInfoMap := a.getFsInfos(ctx)
+ for _, partition := range android.SortedKeys(fsInfoMap) {
+ // installed-files-*{.txt | .json} is not disted for userdata partition
+ if partition == "userdata" {
+ continue
+ }
+ fsInfo := fsInfoMap[partition]
+ for _, installedFiles := range fsInfo.InstalledFilesDepSet.ToList() {
+ distInstalledFilesJsonAndTxt(installedFiles)
+ }
+ }
+}
+
+func (a *androidDevice) distFiles(ctx android.ModuleContext) {
+ if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) {
+ a.distInstalledFiles(ctx)
+
+ namePrefix := ""
+ if ctx.Config().HasDeviceProduct() {
+ namePrefix = ctx.Config().DeviceProduct() + "-"
+ }
+ ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictZip, namePrefix+insertBeforeExtension(a.proguardDictZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictMapping, namePrefix+insertBeforeExtension(a.proguardDictMapping.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardUsageZip, namePrefix+insertBeforeExtension(a.proguardUsageZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+
+ if a.deviceProps.Android_info != nil {
+ ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info))
+ }
+ if a.miscInfo != nil {
+ ctx.DistForGoal("droidcore-unbundled", a.miscInfo)
+ if a.partitionProps.Super_partition_name != nil {
+ ctx.DistForGoalWithFilename("dist_files", a.miscInfo, "super_misc_info.txt")
+ }
+ }
+ if a.targetFilesZip != nil {
+ ctx.DistForGoalWithFilename("target-files-package", a.targetFilesZip, namePrefix+insertBeforeExtension(a.targetFilesZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ }
+ if a.updatePackage != nil {
+ ctx.DistForGoalWithFilename("updatepackage", a.updatePackage, namePrefix+insertBeforeExtension(a.updatePackage.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+ }
+
+ }
+}
+
+func (a *androidDevice) MakeVars(_ android.MakeVarsModuleContext) []android.ModuleMakeVarsValue {
+ if proptools.Bool(a.deviceProps.Main_device) {
+ return []android.ModuleMakeVarsValue{{"SOONG_ONLY_ALL_IMAGES_ZIP", a.allImagesZip.String()}}
+ }
+ return nil
+}
+
+func (a *androidDevice) buildProguardZips(ctx android.ModuleContext, allInstalledModules []android.Module) {
+ dictZip := android.PathForModuleOut(ctx, "proguard-dict.zip")
+ dictZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ dictZipCmd := dictZipBuilder.Command().BuiltTool("soong_zip").Flag("-d").FlagWithOutput("-o ", dictZip)
+
+ dictMapping := android.PathForModuleOut(ctx, "proguard-dict-mapping.textproto")
+ dictMappingBuilder := android.NewRuleBuilder(pctx, ctx)
+ dictMappingCmd := dictMappingBuilder.Command().BuiltTool("symbols_map").Flag("-merge").Output(dictMapping)
+
+ protosDir := android.PathForModuleOut(ctx, "proguard_mapping_protos")
+
+ usageZip := android.PathForModuleOut(ctx, "proguard-usage.zip")
+ usageZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ usageZipCmd := usageZipBuilder.Command().BuiltTool("merge_zips").Output(usageZip)
+
+ for _, mod := range allInstalledModules {
+ if proguardInfo, ok := android.OtherModuleProvider(ctx, mod, java.ProguardProvider); ok {
+ // Maintain these out/target/common paths for backwards compatibility. They may be able
+ // to be changed if tools look up file locations from the protobuf, but I'm not
+ // exactly sure how that works.
+ dictionaryFakePath := fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/proguard_dictionary", proguardInfo.Class, proguardInfo.ModuleName)
+ dictZipCmd.FlagWithArg("-e ", dictionaryFakePath)
+ dictZipCmd.FlagWithInput("-f ", proguardInfo.ProguardDictionary)
+ dictZipCmd.Textf("-e out/target/common/obj/%s/%s_intermediates/classes.jar", proguardInfo.Class, proguardInfo.ModuleName)
+ dictZipCmd.FlagWithInput("-f ", proguardInfo.ClassesJar)
+
+ protoFile := protosDir.Join(ctx, filepath.Dir(dictionaryFakePath), "proguard_dictionary.textproto")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: proguardDictToProto,
+ Input: proguardInfo.ProguardDictionary,
+ Output: protoFile,
+ Args: map[string]string{
+ "location": dictionaryFakePath,
+ },
+ })
+ dictMappingCmd.Input(protoFile)
+
+ usageZipCmd.Input(proguardInfo.ProguardUsageZip)
+ }
+ }
+
+ dictZipBuilder.Build("proguard_dict_zip", "Building proguard dictionary zip")
+ dictMappingBuilder.Build("proguard_dict_mapping_proto", "Building proguard mapping proto")
+ usageZipBuilder.Build("proguard_usage_zip", "Building proguard usage zip")
+
+ a.proguardDictZip = dictZip
+ a.proguardDictMapping = dictMapping
+ a.proguardUsageZip = usageZip
+}
+
+// Helper structs for target_files.zip creation
+type targetFilesZipCopy struct {
+ srcModule *string
+ destSubdir string
+}
+
+type targetFilesystemZipCopy struct {
+ fsInfo FilesystemInfo
+ destSubdir string
+}
+
+func (a *androidDevice) buildTargetFilesZip(ctx android.ModuleContext, allInstalledModules []android.Module) {
+ targetFilesDir := android.PathForModuleOut(ctx, "target_files_dir")
+ targetFilesZip := android.PathForModuleOut(ctx, "target_files.zip")
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Textf("rm -rf %s", targetFilesDir.String())
+ builder.Command().Textf("mkdir -p %s", targetFilesDir.String())
+ toCopy := []targetFilesZipCopy{
+ targetFilesZipCopy{a.partitionProps.System_partition_name, "SYSTEM"},
+ targetFilesZipCopy{a.partitionProps.System_ext_partition_name, "SYSTEM_EXT"},
+ targetFilesZipCopy{a.partitionProps.Product_partition_name, "PRODUCT"},
+ targetFilesZipCopy{a.partitionProps.Vendor_partition_name, "VENDOR"},
+ targetFilesZipCopy{a.partitionProps.Odm_partition_name, "ODM"},
+ targetFilesZipCopy{a.partitionProps.System_dlkm_partition_name, "SYSTEM_DLKM"},
+ targetFilesZipCopy{a.partitionProps.Vendor_dlkm_partition_name, "VENDOR_DLKM"},
+ targetFilesZipCopy{a.partitionProps.Odm_dlkm_partition_name, "ODM_DLKM"},
+ targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "BOOT/RAMDISK"},
+ targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "INIT_BOOT/RAMDISK"},
+ targetFilesZipCopy{a.partitionProps.Vendor_boot_partition_name, "VENDOR_BOOT/RAMDISK"},
+ }
+
+ filesystemsToCopy := []targetFilesystemZipCopy{}
+ for _, zipCopy := range toCopy {
+ if zipCopy.srcModule == nil {
+ continue
+ }
+ filesystemsToCopy = append(
+ filesystemsToCopy,
+ targetFilesystemZipCopy{a.getFilesystemInfo(ctx, *zipCopy.srcModule), zipCopy.destSubdir},
+ )
+ }
+ // Get additional filesystems from super_partition dependency
+ if a.partitionProps.Super_partition_name != nil {
+ superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
+ for _, partition := range android.SortedKeys(info.SubImageInfo) {
+ filesystemsToCopy = append(
+ filesystemsToCopy,
+ targetFilesystemZipCopy{info.SubImageInfo[partition], strings.ToUpper(partition)},
+ )
+ }
+ } else {
+ ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
+ }
+ }
+
+ for _, toCopy := range filesystemsToCopy {
+ rootDirString := toCopy.fsInfo.RootDir.String()
+ if toCopy.destSubdir == "SYSTEM" {
+ rootDirString = rootDirString + "/system"
+ }
+ builder.Command().Textf("mkdir -p %s/%s", targetFilesDir.String(), toCopy.destSubdir)
+ builder.Command().
+ BuiltTool("acp").
+ Textf("-rd %s/. %s/%s", rootDirString, targetFilesDir, toCopy.destSubdir).
+ Implicit(toCopy.fsInfo.Output) // so that the staging dir is built
+ for _, extraRootDir := range toCopy.fsInfo.ExtraRootDirs {
+ builder.Command().
+ BuiltTool("acp").
+ Textf("-rd %s/. %s/%s", extraRootDir, targetFilesDir, toCopy.destSubdir).
+ Implicit(toCopy.fsInfo.Output) // so that the staging dir is built
+ }
+
+ if toCopy.destSubdir == "SYSTEM" {
+ // Create the ROOT partition in target_files.zip
+ builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", toCopy.fsInfo.RootDir, targetFilesDir.String())
+ // Add a duplicate rule to assemble the ROOT/ directory in separate intermediates.
+ // The output timestamp will be an input to a separate fs_config call.
+ a.rootDirForFsConfig = android.PathForModuleOut(ctx, "root_dir_for_fs_config").String()
+ rootDirBuilder := android.NewRuleBuilder(pctx, ctx)
+ rootDirForFsConfigTimestamp := android.PathForModuleOut(ctx, "root_dir_for_fs_config.timestamp")
+ rootDirBuilder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s", toCopy.fsInfo.RootDir, a.rootDirForFsConfig).
+ Implicit(toCopy.fsInfo.Output).
+ Text("&& touch").
+ Output(rootDirForFsConfigTimestamp)
+ rootDirBuilder.Build("assemble_root_dir_for_fs_config", "Assemble ROOT/ for fs_config")
+ a.rootDirForFsConfigTimestamp = rootDirForFsConfigTimestamp
+ }
+ }
+ // Copy cmdline, kernel etc. files of boot images
+ if a.partitionProps.Vendor_boot_partition_name != nil {
+ bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Vendor_boot_partition_name), filesystemDepTag)
+ bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ builder.Command().Textf("echo %s > %s/VENDOR_BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
+ builder.Command().Textf("echo %s > %s/VENDOR_BOOT/vendor_cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
+ if bootImgInfo.Dtb != nil {
+ builder.Command().Textf("cp ").Input(bootImgInfo.Dtb).Textf(" %s/VENDOR_BOOT/dtb", targetFilesDir)
+ }
+ if bootImgInfo.Bootconfig != nil {
+ builder.Command().Textf("cp ").Input(bootImgInfo.Bootconfig).Textf(" %s/VENDOR_BOOT/vendor_bootconfig", targetFilesDir)
+ }
+ }
+ if a.partitionProps.Boot_partition_name != nil {
+ bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
+ bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ builder.Command().Textf("echo %s > %s/BOOT/cmdline", proptools.ShellEscape(strings.Join(bootImgInfo.Cmdline, " ")), targetFilesDir)
+ if bootImgInfo.Dtb != nil {
+ builder.Command().Textf("cp ").Input(bootImgInfo.Dtb).Textf(" %s/BOOT/dtb", targetFilesDir)
+ }
+ if bootImgInfo.Kernel != nil {
+ builder.Command().Textf("cp ").Input(bootImgInfo.Kernel).Textf(" %s/BOOT/kernel", targetFilesDir)
+ // Even though kernel is not used to build vendor_boot, copy the kernel to VENDOR_BOOT to match the behavior of make packaging.
+ builder.Command().Textf("cp ").Input(bootImgInfo.Kernel).Textf(" %s/VENDOR_BOOT/kernel", targetFilesDir)
+ }
+ if bootImgInfo.Bootconfig != nil {
+ builder.Command().Textf("cp ").Input(bootImgInfo.Bootconfig).Textf(" %s/BOOT/bootconfig", targetFilesDir)
+ }
+ }
+
+ if a.deviceProps.Android_info != nil {
+ builder.Command().Textf("mkdir -p %s/OTA", targetFilesDir)
+ builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, *a.deviceProps.Android_info)).Textf(" %s/OTA/android-info.txt", targetFilesDir)
+ }
+
+ a.copyImagesToTargetZip(ctx, builder, targetFilesDir)
+ a.copyMetadataToTargetZip(ctx, builder, targetFilesDir, allInstalledModules)
+
+ a.targetFilesZip = targetFilesZip
+ builder.Command().
+ BuiltTool("soong_zip").
+ Text("-d").
+ FlagWithOutput("-o ", targetFilesZip).
+ FlagWithArg("-C ", targetFilesDir.String()).
+ FlagWithArg("-D ", targetFilesDir.String()).
+ Text("-sha256")
+ builder.Build("target_files_"+ctx.ModuleName(), "Build target_files.zip")
+}
+
+func (a *androidDevice) copyImagesToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath) {
+ // Create an IMAGES/ subdirectory
+ builder.Command().Textf("mkdir -p %s/IMAGES", targetFilesDir.String())
+ if a.deviceProps.Bootloader != nil {
+ builder.Command().Textf("cp ").Input(android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Bootloader))).Textf(" %s/IMAGES/bootloader", targetFilesDir.String())
+ }
+ // Copy the filesystem ,boot and vbmeta img files to IMAGES/
+ ctx.VisitDirectDepsProxyWithTag(filesystemDepTag, func(child android.ModuleProxy) {
+ if strings.Contains(child.Name(), "recovery") {
+ return // skip recovery.img to match the make packaging behavior
+ }
+ if info, ok := android.OtherModuleProvider(ctx, child, BootimgInfoProvider); ok {
+ // Check Boot img first so that the boot.img is copied and not its dep ramdisk.img
+ builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+ } else if info, ok := android.OtherModuleProvider(ctx, child, FilesystemProvider); ok {
+ builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+ } else if info, ok := android.OtherModuleProvider(ctx, child, vbmetaPartitionProvider); ok {
+ builder.Command().Textf("cp ").Input(info.Output).Textf(" %s/IMAGES/", targetFilesDir.String())
+ } else {
+ ctx.ModuleErrorf("Module %s does not provide an .img file output for target_files.zip", child.Name())
+ }
+ })
+
+ if a.partitionProps.Super_partition_name != nil {
+ superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
+ for _, partition := range android.SortedKeys(info.SubImageInfo) {
+ if info.SubImageInfo[partition].OutputHermetic != nil {
+ builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].OutputHermetic).Textf(" %s/IMAGES/", targetFilesDir.String())
+ }
+ if info.SubImageInfo[partition].MapFile != nil {
+ builder.Command().Textf("cp ").Input(info.SubImageInfo[partition].MapFile).Textf(" %s/IMAGES/", targetFilesDir.String())
+ }
+ }
+ // super_empty.img
+ if info.SuperEmptyImage != nil {
+ builder.Command().Textf("cp ").Input(info.SuperEmptyImage).Textf(" %s/IMAGES/", targetFilesDir.String())
+ }
+ } else {
+ ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
+ }
+ }
+}
+
+func (a *androidDevice) copyMetadataToTargetZip(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir android.WritablePath, allInstalledModules []android.Module) {
+ // Create a META/ subdirectory
+ builder.Command().Textf("mkdir -p %s/META", targetFilesDir.String())
+ if proptools.Bool(a.deviceProps.Ab_ota_updater) {
+ ctx.VisitDirectDepsProxyWithTag(targetFilesMetadataDepTag, func(child android.ModuleProxy) {
+ info, _ := android.OtherModuleProvider(ctx, child, android.OutputFilesProvider)
+ builder.Command().Textf("cp").Inputs(info.DefaultOutputFiles).Textf(" %s/META/", targetFilesDir.String())
+ })
+ builder.Command().Textf("cp").Input(android.PathForSource(ctx, "external/zucchini/version_info.h")).Textf(" %s/META/zucchini_config.txt", targetFilesDir.String())
+ builder.Command().Textf("cp").Input(android.PathForSource(ctx, "system/update_engine/update_engine.conf")).Textf(" %s/META/update_engine_config.txt", targetFilesDir.String())
+ if a.getFsInfos(ctx)["system"].ErofsCompressHints != nil {
+ builder.Command().Textf("cp").Input(a.getFsInfos(ctx)["system"].ErofsCompressHints).Textf(" %s/META/erofs_default_compress_hints.txt", targetFilesDir.String())
+ }
+ // ab_partitions.txt
+ abPartitionsSorted := android.SortedUniqueStrings(a.deviceProps.Ab_ota_partitions)
+ abPartitionsSortedString := proptools.ShellEscape(strings.Join(abPartitionsSorted, "\\n"))
+ builder.Command().Textf("echo -e").Flag(abPartitionsSortedString).Textf(" > %s/META/ab_partitions.txt", targetFilesDir.String())
+ // otakeys.txt
+ abOtaKeysSorted := android.SortedUniqueStrings(a.deviceProps.Ab_ota_keys)
+ abOtaKeysSortedString := proptools.ShellEscape(strings.Join(abOtaKeysSorted, "\\n"))
+ builder.Command().Textf("echo -e").Flag(abOtaKeysSortedString).Textf(" > %s/META/otakeys.txt", targetFilesDir.String())
+ // postinstall_config.txt
+ abOtaPostInstallConfigString := proptools.ShellEscape(strings.Join(a.deviceProps.Ab_ota_postinstall_config, "\\n"))
+ builder.Command().Textf("echo -e").Flag(abOtaPostInstallConfigString).Textf(" > %s/META/postinstall_config.txt", targetFilesDir.String())
+ // selinuxfc
+ if a.getFsInfos(ctx)["system"].SelinuxFc != nil {
+ builder.Command().Textf("cp").Input(a.getFsInfos(ctx)["system"].SelinuxFc).Textf(" %s/META/file_contexts.bin", targetFilesDir.String())
+ }
+ }
+ // Copy $partition_filesystem_config.txt
+ fsInfos := a.getFsInfos(ctx)
+ for _, partition := range android.SortedKeys(fsInfos) {
+ if fsInfos[partition].FilesystemConfig == nil {
+ continue
+ }
+ if android.InList(partition, []string{"userdata"}) {
+ continue
+ }
+ if partition != "vendor_ramdisk" {
+ // vendor_ramdisk will be handled separately.
+ builder.Command().Textf("cp").Input(fsInfos[partition].FilesystemConfig).Textf(" %s/META/%s", targetFilesDir.String(), a.filesystemConfigNameForTargetFiles(partition))
+ }
+ if partition == "ramdisk" {
+ // Create an additional copy at boot_filesystem_config.txt
+ builder.Command().Textf("cp").Input(fsInfos[partition].FilesystemConfig).Textf(" %s/META/boot_filesystem_config.txt", targetFilesDir.String())
+ }
+ if partition == "system" {
+ // Create root_filesystem_config from the assembled ROOT/ intermediates directory
+ a.generateFilesystemConfigForTargetFiles(ctx, builder, a.rootDirForFsConfigTimestamp, targetFilesDir.String(), a.rootDirForFsConfig, "root_filesystem_config.txt")
+ }
+ if partition == "vendor_ramdisk" {
+ // Create vendor_boot_filesystem_config from the assembled VENDOR_BOOT/RAMDISK intermediates directory
+ vendorRamdiskStagingDir := targetFilesDir.String() + "/VENDOR_BOOT/RAMDISK"
+ vendorRamdiskFsConfigOut := targetFilesDir.String() + "/META/vendor_boot_filesystem_config.txt"
+ fsConfigBin := ctx.Config().HostToolPath(ctx, "fs_config")
+ builder.Command().Textf(
+ `(cd %s; find . -type d | sed 's,$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,,' | %s -C -D %s -R \"\" > %s`,
+ vendorRamdiskStagingDir, fsConfigBin, vendorRamdiskStagingDir, vendorRamdiskFsConfigOut).
+ Implicit(fsConfigBin)
+ }
+ }
+ // Copy ramdisk_node_list
+ if ramdiskNodeList := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Ramdisk_node_list)); ramdiskNodeList != nil {
+ builder.Command().Textf("cp").Input(ramdiskNodeList).Textf(" %s/META/", targetFilesDir.String())
+ }
+ // Copy releasetools.py
+ if releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension)); releaseTools != nil {
+ builder.Command().Textf("cp").Input(releaseTools).Textf(" %s/META/", targetFilesDir.String())
+ }
+ // apexkeys.txt
+ var installedApexKeys []android.Path
+ for _, installedModule := range allInstalledModules {
+ if info, ok := android.OtherModuleProvider(ctx, installedModule, ApexKeyPathInfoProvider); ok {
+ installedApexKeys = append(installedApexKeys, info.ApexKeyPath)
+ }
+ }
+ installedApexKeys = android.SortedUniquePaths(installedApexKeys) // Sort by keypath to match make
+ builder.Command().Text("cat").Inputs(installedApexKeys).Textf(" >> %s/META/apexkeys.txt", targetFilesDir.String())
+ // apkcerts.txt
+ builder.Command().Textf("cp").Input(a.apkCertsInfo).Textf(" %s/META/", targetFilesDir.String())
+
+ // Copy fastboot-info.txt
+ if fastbootInfo := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.FastbootInfo)); fastbootInfo != nil {
+ // TODO (b/399788523): Autogenerate fastboot-info.txt if there is no source fastboot-info.txt
+ // https://cs.android.com/android/_/android/platform/build/+/80b9546f8f69e78b8fe1870e0e745d70fc18dfcd:core/Makefile;l=5831-5893;drc=077490384423dff9eac954da5c001c6f0be3fa6e;bpv=0;bpt=0
+ builder.Command().Textf("cp").Input(fastbootInfo).Textf(" %s/META/fastboot-info.txt", targetFilesDir.String())
+ }
+
+ // kernel_configs.txt and kernel_version.txt
+ if a.kernelConfig != nil {
+ builder.Command().Textf("cp").Input(a.kernelConfig).Textf(" %s/META/", targetFilesDir.String())
+ }
+ if a.kernelVersion != nil {
+ builder.Command().Textf("cp").Input(a.kernelVersion).Textf(" %s/META/", targetFilesDir.String())
+ }
+ // misc_info.txt
+ if a.miscInfo != nil {
+ builder.Command().Textf("cp").Input(a.miscInfo).Textf(" %s/META/", targetFilesDir.String())
+ }
+ // apex_info.pb, care_map.pb, vbmeta_digest.txt
+ a.addImgToTargetFiles(ctx, builder, targetFilesDir.String())
+
+ if a.partitionProps.Super_partition_name != nil {
+ superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
+ // dynamic_partitions_info.txt
+ // TODO (b/390192334): Add `building_super_empty_partition=true`
+ builder.Command().Text("cp").Input(info.DynamicPartitionsInfo).Textf(" %s/META/", targetFilesDir.String())
+ } else {
+ ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
+ }
+ }
+
+}
+
+var (
+ // https://cs.android.com/android/_/android/platform/build/+/30f05352c3e6f4333c77d4af66c253572d3ea6c9:core/Makefile;l=2111-2120;drc=519f75666431ee2926e0ec8991c682b28a4c9521;bpv=1;bpt=0
+ defaultTargetRecoveryFstypeMountOptions = "ext4=max_batch_time=0,commit=1,data=ordered,barrier=1,errors=panic,nodelalloc"
+)
+
+// A partial implementation of make's $PRODUCT_OUT/misc_info.txt
+// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5894?q=misc_info.txt%20f:build%2Fmake%2Fcore%2FMakefile&ss=android%2Fplatform%2Fsuperproject%2Fmain
+// This file is subsequently used by add_img_to_target_files to create additioanl metadata files like apex_info.pb
+// TODO (b/399788119): Complete the migration of misc_info.txt
+func (a *androidDevice) addMiscInfo(ctx android.ModuleContext) android.Path {
+ buildType := func() string {
+ if ctx.Config().Debuggable() {
+ return "userdebug"
+ } else if ctx.Config().Eng() {
+ return "eng"
+ } else {
+ return "user"
+ }
+ }
+ defaultAppCertificate := func() string {
+ pem, _ := ctx.Config().DefaultAppCertificate(ctx)
+ return strings.TrimSuffix(pem.String(), ".x509.pem")
+ }
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ miscInfo := android.PathForModuleOut(ctx, "misc_info.txt")
+ builder.Command().
+ Textf("rm -f %s", miscInfo).
+ Textf("&& echo recovery_api_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_api_version"), miscInfo).
+ Textf("&& echo fstab_version=%s >> %s", ctx.Config().VendorConfig("recovery").String("recovery_fstab_version"), miscInfo).
+ Textf("&& echo build_type=%s >> %s", buildType(), miscInfo).
+ Textf("&& echo default_system_dev_certificate=%s >> %s", defaultAppCertificate(), miscInfo).
+ Textf("&& echo root_dir=%s >> %s", android.PathForModuleInPartitionInstall(ctx, "root"), miscInfo).
+ ImplicitOutput(miscInfo)
+ if len(ctx.Config().ExtraOtaRecoveryKeys()) > 0 {
+ builder.Command().Textf(`echo "extra_recovery_keys=%s" >> %s`, strings.Join(ctx.Config().ExtraOtaRecoveryKeys(), ""), miscInfo)
+ } else {
+ if a.partitionProps.Boot_partition_name != nil {
+ builder.Command().
+ Textf("echo mkbootimg_args='--header_version %s' >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Boot_partition_name), miscInfo).
+ // TODO: Use boot's header version for recovery for now since cuttlefish does not set `BOARD_RECOVERY_MKBOOTIMG_ARGS`
+ Textf(" && echo recovery_mkbootimg_args='--header_version %s' >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Boot_partition_name), miscInfo)
+ }
+ if a.partitionProps.Init_boot_partition_name != nil {
+ builder.Command().
+ Textf("echo mkbootimg_init_args='--header_version' %s >> %s", a.getBootimgHeaderVersion(ctx, a.partitionProps.Init_boot_partition_name), miscInfo)
+ }
+ builder.Command().
+ Textf("echo mkbootimg_version_args='--os_version %s --os_patch_level %s' >> %s", ctx.Config().PlatformVersionLastStable(), ctx.Config().PlatformSecurityPatch(), miscInfo).
+ Textf(" && echo multistage_support=1 >> %s", miscInfo).
+ Textf(" && echo blockimgdiff_versions=3,4 >> %s", miscInfo)
+ }
+ fsInfos := a.getFsInfos(ctx)
+ if _, ok := fsInfos["vendor"]; ok {
+ builder.Command().Textf("echo board_uses_vendorimage=true >> %s", miscInfo)
+ }
+ if fsInfos["system"].ErofsCompressHints != nil {
+ builder.Command().Textf("echo erofs_default_compress_hints=%s >> %s", fsInfos["system"].ErofsCompressHints, miscInfo)
+ }
+ if releaseTools := android.PathForModuleSrc(ctx, proptools.String(a.deviceProps.Releasetools_extension)); releaseTools != nil {
+ builder.Command().Textf("echo tool_extensions=%s >> %s", filepath.Dir(releaseTools.String()), miscInfo)
+ }
+ // ramdisk uses `compressed_cpio` fs_type
+ // https://cs.android.com/android/_/android/platform/build/+/30f05352c3e6f4333c77d4af66c253572d3ea6c9:core/Makefile;l=5923-5925;drc=519f75666431ee2926e0ec8991c682b28a4c9521;bpv=1;bpt=0
+ if _, ok := fsInfos["ramdisk"]; ok {
+ builder.Command().Textf("echo lz4_ramdisks=true >> %s", miscInfo)
+ }
+ // recovery_mount_options
+ // TODO: Add support for TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS which can be used to override the default
+ builder.Command().Textf("echo recovery_mount_options=%s >> %s", defaultTargetRecoveryFstypeMountOptions, miscInfo)
+
+ // vintf information
+ if proptools.Bool(ctx.Config().ProductVariables().Enforce_vintf_manifest) {
+ builder.Command().Textf("echo vintf_enforce=true >> %s", miscInfo)
+ }
+ if len(ctx.Config().DeviceManifestFiles()) > 0 {
+ builder.Command().Textf("echo vintf_include_empty_vendor_sku=true >> %s", miscInfo)
+ }
+
+ if a.partitionProps.Recovery_partition_name == nil {
+ builder.Command().Textf("echo no_recovery=true >> %s", miscInfo)
+ }
+ for _, partition := range android.SortedKeys(fsInfos) {
+ if fsInfos[partition].PropFileForMiscInfo != nil {
+ builder.Command().Text("cat").Input(fsInfos[partition].PropFileForMiscInfo).Textf(" >> %s", miscInfo)
+ }
+ }
+ if len(a.partitionProps.Vbmeta_partitions) > 0 {
+ builder.Command().
+ Textf("echo avb_enable=true >> %s", miscInfo).
+ Textf("&& echo avb_building_vbmeta_image=true >> %s", miscInfo).
+ Textf("&& echo avb_avbtool=avbtool >> %s", miscInfo)
+
+ var allChainedVbmetaPartitionTypes []string
+ for _, vbmetaPartitionName := range a.partitionProps.Vbmeta_partitions {
+ img := ctx.GetDirectDepProxyWithTag(vbmetaPartitionName, filesystemDepTag)
+ if provider, ok := android.OtherModuleProvider(ctx, img, vbmetaPartitionProvider); ok {
+ builder.Command().Text("cat").Input(provider.PropFileForMiscInfo).Textf(" >> %s", miscInfo)
+ if provider.FilesystemPartitionType != "" { // the top-level vbmeta.img
+ allChainedVbmetaPartitionTypes = append(allChainedVbmetaPartitionTypes, provider.FilesystemPartitionType)
+ }
+ } else {
+ ctx.ModuleErrorf("vbmeta dep %s does not set vbmetaPartitionProvider\n", vbmetaPartitionName)
+ }
+ }
+ // Determine the custom vbmeta partitions by removing system and vendor
+ customVbmetaPartitionTypes := android.RemoveListFromList(allChainedVbmetaPartitionTypes, []string{"system", "vendor"})
+ builder.Command().Textf("echo avb_custom_vbmeta_images_partition_list=%s >> %s",
+ strings.Join(android.SortedUniqueStrings(customVbmetaPartitionTypes), " "),
+ miscInfo,
+ )
+
+ }
+ if a.partitionProps.Boot_partition_name != nil {
+ builder.Command().Textf("echo boot_images=boot.img >> %s", miscInfo)
+ }
+
+ if a.partitionProps.Super_partition_name != nil {
+ superPartition := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
+ // cat dynamic_partition_info.txt
+ builder.Command().Text("cat").Input(info.DynamicPartitionsInfo).Textf(" >> %s", miscInfo)
+ if info.AbUpdate {
+ builder.Command().Textf("echo ab_update=true >> %s", miscInfo)
+ }
+
+ } else {
+ ctx.ModuleErrorf("Super partition %s does set SuperImageProvider\n", superPartition.Name())
+ }
+ }
+ bootImgNames := []*string{
+ a.partitionProps.Boot_partition_name,
+ a.partitionProps.Init_boot_partition_name,
+ a.partitionProps.Vendor_boot_partition_name,
+ }
+ for _, bootImgName := range bootImgNames {
+ if bootImgName == nil {
+ continue
+ }
+
+ bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(bootImgName), filesystemDepTag)
+ bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ // cat avb_ metadata of the boot images
+ builder.Command().Text("cat").Input(bootImgInfo.PropFileForMiscInfo).Textf(" >> %s", miscInfo)
+ }
+
+ builder.Command().Textf("echo blocksize=%s >> %s", proptools.String(a.deviceProps.Flash_block_size), miscInfo)
+ if proptools.Bool(a.deviceProps.Bootloader_in_update_package) {
+ builder.Command().Textf("echo bootloader_in_update_package=true >> %s", miscInfo)
+ }
+ if len(a.deviceProps.Partial_ota_update_partitions) > 0 {
+ builder.Command().Textf("echo partial_ota_update_partitions_list=%s >> %s", strings.Join(a.deviceProps.Partial_ota_update_partitions, " "), miscInfo)
+ }
+
+ // Sort and dedup
+ builder.Command().Textf("sort -u %s -o %s", miscInfo, miscInfo)
+
+ builder.Build("misc_info", "Building misc_info")
+
+ return miscInfo
+}
+
+func (a *androidDevice) getBootimgHeaderVersion(ctx android.ModuleContext, bootImgName *string) string {
+ bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(bootImgName), filesystemDepTag)
+ bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ return bootImgInfo.HeaderVersion
+}
+
+// addImgToTargetFiles invokes `add_img_to_target_files` and creates the following files in META/
+// - apex_info.pb
+// - care_map.pb
+// - vbmeta_digest.txt
+func (a *androidDevice) addImgToTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir string) {
+ mkbootimg := ctx.Config().HostToolPath(ctx, "mkbootimg")
+ builder.Command().
+ Textf("PATH=%s:$PATH", ctx.Config().HostToolDir()).
+ Textf("MKBOOTIMG=%s", mkbootimg).
+ Implicit(mkbootimg).
+ BuiltTool("add_img_to_target_files").
+ Flag("-a -v -p").
+ Flag(ctx.Config().HostToolDir()).
+ Text(targetFilesDir)
+}
+
+func (a *androidDevice) buildUpdatePackage(ctx android.ModuleContext) {
+ var exclusions []string
+ fsInfos := a.getFsInfos(ctx)
+ // Exclude the partitions that are not supported by flashall
+ for _, partition := range android.SortedKeys(fsInfos) {
+ if fsInfos[partition].NoFlashall {
+ exclusions = append(exclusions, fmt.Sprintf("IMAGES/%s.img", partition))
+ exclusions = append(exclusions, fmt.Sprintf("IMAGES/%s.map", partition))
+ }
+ }
+
+ updatePackage := android.PathForModuleOut(ctx, "img.zip")
+ rule := android.NewRuleBuilder(pctx, ctx)
+
+ buildSuperImage := ctx.Config().HostToolPath(ctx, "build_super_image")
+ zip2zip := ctx.Config().HostToolPath(ctx, "zip2zip")
+
+ rule.Command().
+ BuiltTool("img_from_target_files").
+ Text("--additional IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto").
+ FlagForEachArg("--exclude ", exclusions).
+ FlagWithArg("--build_super_image ", buildSuperImage.String()).
+ Implicit(buildSuperImage).
+ Implicit(zip2zip).
+ Input(a.targetFilesZip).
+ Output(updatePackage)
+
+ rule.Build("updatepackage", "Building updatepackage")
+
+ a.updatePackage = updatePackage
+}
+
+type ApexKeyPathInfo struct {
+ ApexKeyPath android.Path
+}
+
+var ApexKeyPathInfoProvider = blueprint.NewProvider[ApexKeyPathInfo]()
+
+func (a *androidDevice) generateFilesystemConfigForTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, stagingDirTimestamp android.Path, targetFilesDir, stagingDir, filename string) {
+ fsConfigOut := android.PathForModuleOut(ctx, filename)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: fsConfigRule,
+ Implicit: stagingDirTimestamp,
+ Output: fsConfigOut,
+ Args: map[string]string{
+ "rootDir": stagingDir,
+ "prefix": "",
+ },
+ })
+ builder.Command().Textf("cp").Input(fsConfigOut).Textf(" %s/META/", targetFilesDir)
+}
+
+// Filenames for the partition specific fs_config files.
+// Hardcode the ramdisk files to their boot image prefix
+func (a *androidDevice) filesystemConfigNameForTargetFiles(partition string) string {
+ name := partition + "_filesystem_config.txt"
+ if partition == "system" {
+ name = "filesystem_config.txt"
+ } else if partition == "ramdisk" {
+ name = "init_boot_filesystem_config.txt"
+ }
+ return name
+}
+
+func (a *androidDevice) getFilesystemInfo(ctx android.ModuleContext, depName string) FilesystemInfo {
+ fsMod := ctx.GetDirectDepProxyWithTag(depName, filesystemDepTag)
+ fsInfo, ok := android.OtherModuleProvider(ctx, fsMod, FilesystemProvider)
+ if !ok {
+ ctx.ModuleErrorf("Expected dependency %s to be a filesystem", depName)
+ }
+ return fsInfo
+}
+
+func (a *androidDevice) setVbmetaPhonyTargets(ctx android.ModuleContext) {
+ if !proptools.Bool(a.deviceProps.Main_device) {
+ return
+ }
+
+ if !ctx.Config().KatiEnabled() {
+ for _, vbmetaPartitionName := range a.partitionProps.Vbmeta_partitions {
+ img := ctx.GetDirectDepProxyWithTag(vbmetaPartitionName, filesystemDepTag)
+ if provider, ok := android.OtherModuleProvider(ctx, img, vbmetaPartitionProvider); ok {
+ // make generates `vbmetasystemimage` phony target instead of `vbmeta_systemimage` phony target.
+ partitionName := strings.ReplaceAll(provider.Name, "_", "")
+ ctx.Phony(fmt.Sprintf("%simage", partitionName), provider.Output)
+ }
+ }
+ }
+}
+
+func (a *androidDevice) getKernel(ctx android.ModuleContext) android.Path {
+ if a.partitionProps.Boot_partition_name != nil {
+ bootImg := ctx.GetDirectDepProxyWithTag(proptools.String(a.partitionProps.Boot_partition_name), filesystemDepTag)
+ bootImgInfo, _ := android.OtherModuleProvider(ctx, bootImg, BootimgInfoProvider)
+ return bootImgInfo.Kernel
+ }
+ return nil
+}
+
+// Gets the kernel version and configs from the actual kernel file itself. Roughly equivalent to
+// this make code: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=5443;drc=c0b66fc59de069e06ce0ffd703d4d21613be30c6
+// However, it is a simplified version of that make code. Differences include:
+// - Not handling BOARD_KERNEL_CONFIG_FILE because BOARD_KERNEL_CONFIG_FILE was never used.
+// - Not unpacking the bootimage, as we should be able to just always export the kernel directly
+// in the BootimgInfo. We don't currently support prebuilt boot images, but even if we add that
+// in the future, it can be done in a prebuilt_bootimage module type that still exports the same
+// BootimgInfo.
+// - We don't print a warning and output '<unknown-kernel>' to kernel_version_for_uffd_gc.txt
+// because we expect the kernel to always be present. If it's not, we will get an error that
+// kernel_version_for_uffd_gc.txt doesn't exist. This may require later tweaking to the
+// dexpreopt rules so that they don't attempt to access that file in builds that don't have
+// a kernel.
+func (a *androidDevice) extractKernelVersionAndConfigs(ctx android.ModuleContext) (android.Path, android.Path) {
+ kernel := a.getKernel(ctx)
+ // If there's no kernel, don't create kernel version / kernel config files. Reverse dependencies
+ // on those files have to account for this, for example by disabling dexpreopt in unbundled
+ // builds.
+ if kernel == nil {
+ return nil, nil
+ }
+
+ lz4tool := ctx.Config().HostToolPath(ctx, "lz4")
+
+ extractedVersionFile := android.PathForModuleOut(ctx, "kernel_version.txt")
+ extractedConfigsFile := android.PathForModuleOut(ctx, "kernel_configs.txt")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().BuiltTool("extract_kernel").
+ Flag("--tools lz4:"+lz4tool.String()).Implicit(lz4tool).
+ FlagWithInput("--input ", kernel).
+ FlagWithOutput("--output-release ", extractedVersionFile).
+ FlagWithOutput("--output-configs ", extractedConfigsFile).
+ Textf(`&& printf "\n" >> %s`, extractedVersionFile)
+
+ if specifiedVersion := proptools.String(a.deviceProps.Kernel_version); specifiedVersion != "" {
+ specifiedVersionFile := android.PathForModuleOut(ctx, "specified_kernel_version.txt")
+ android.WriteFileRule(ctx, specifiedVersionFile, specifiedVersion)
+ builder.Command().Text("diff -q").
+ Input(specifiedVersionFile).
+ Input(extractedVersionFile).
+ Textf(`|| (echo "Specified kernel version '$(cat %s)' does not match actual kernel version '$(cat %s)'"; exit 1)`, specifiedVersionFile, extractedVersionFile)
+ }
+
+ builder.Build("extract_kernel_info", "Extract kernel version and configs")
+
+ if proptools.Bool(a.deviceProps.Main_device) && !ctx.Config().KatiEnabled() {
+ if ctx.Config().EnableUffdGc() == "default" {
+ kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpIfChanged,
+ Input: extractedVersionFile,
+ Output: kernelVersionFile,
+ })
+ }
+
+ ctx.DistForGoal("droid_targets", extractedVersionFile)
+ }
+
+ return extractedVersionFile, extractedConfigsFile
+}
+
+func (a *androidDevice) buildApkCertsInfo(ctx android.ModuleContext, allInstalledModules []android.Module) android.Path {
+ // TODO (spandandas): Add compressed
+ formatLine := func(cert java.Certificate, name, partition string) string {
+ pem := cert.AndroidMkString()
+ var key string
+ if cert.Key == nil {
+ key = ""
+ } else {
+ key = cert.Key.String()
+ }
+ return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
+ }
+
+ apkCerts := []string{}
+ var apkCertsFiles android.Paths
+ for _, installedModule := range allInstalledModules {
+ partition := ""
+ if commonInfo, ok := android.OtherModuleProvider(ctx, installedModule, android.CommonModuleInfoProvider); ok {
+ partition = commonInfo.PartitionTag
+ } else {
+ ctx.ModuleErrorf("%s does not set CommonModuleInfoKey", installedModule.Name())
+ }
+ if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfoProvider); ok {
+ if info.AppSet {
+ apkCertsFiles = append(apkCertsFiles, info.ApkCertsFile)
+ } else {
+ apkCerts = append(apkCerts, formatLine(info.Certificate, info.InstallApkName+".apk", partition))
+ }
+ } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.AppInfosProvider); ok {
+ for _, certInfo := range info {
+ // Partition information of apk-in-apex is not exported to the legacy Make packaging system.
+ // Hardcode the partition to "system"
+ apkCerts = append(apkCerts, formatLine(certInfo.Certificate, certInfo.InstallApkName+".apk", "system"))
+ }
+ } else if info, ok := android.OtherModuleProvider(ctx, installedModule, java.RuntimeResourceOverlayInfoProvider); ok {
+ apkCerts = append(apkCerts, formatLine(info.Certificate, info.OutputFile.Base(), partition))
+ }
+ }
+ slices.Sort(apkCerts) // sort by name
+ fsInfos := a.getFsInfos(ctx)
+ if fsInfos["system"].HasFsverity {
+ defaultPem, defaultKey := ctx.Config().DefaultAppCertificate(ctx)
+ apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifest.apk", "system"))
+ if info, ok := fsInfos["system_ext"]; ok && info.HasFsverity {
+ apkCerts = append(apkCerts, formatLine(java.Certificate{Pem: defaultPem, Key: defaultKey}, "BuildManifestSystemExt.apk", "system_ext"))
+ }
+ }
+
+ apkCertsInfoWithoutAppSets := android.PathForModuleOut(ctx, "apkcerts_without_app_sets.txt")
+ android.WriteFileRuleVerbatim(ctx, apkCertsInfoWithoutAppSets, strings.Join(apkCerts, "\n")+"\n")
+ apkCertsInfo := android.PathForModuleOut(ctx, "apkcerts.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Description: "combine apkcerts.txt",
+ Output: apkCertsInfo,
+ Inputs: append(apkCertsFiles, apkCertsInfoWithoutAppSets),
+ })
+ return apkCertsInfo
}
diff --git a/filesystem/android_device_product_out.go b/filesystem/android_device_product_out.go
new file mode 100644
index 0000000..aa06337
--- /dev/null
+++ b/filesystem/android_device_product_out.go
@@ -0,0 +1,260 @@
+// Copyright (C) 2025 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 (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ copyStagingDirRule = pctx.AndroidStaticRule("copy_staging_dir", blueprint.RuleParams{
+ Command: "rsync -a --checksum $dir/ $dest && touch $out",
+ }, "dir", "dest")
+)
+
+func (a *androidDevice) copyToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, src android.Path, dest string) {
+ destPath := android.PathForModuleInPartitionInstall(ctx, "").Join(ctx, dest)
+ builder.Command().Text("rsync").Flag("-a").Flag("--checksum").Input(src).Text(destPath.String())
+}
+
+func (a *androidDevice) copyFilesToProductOutForSoongOnly(ctx android.ModuleContext) android.Path {
+ filesystemInfos := a.getFsInfos(ctx)
+
+ var deps android.Paths
+ var depsNoImg android.Paths // subset of deps without any img files. used for sbom creation.
+
+ for _, partition := range android.SortedKeys(filesystemInfos) {
+ info := filesystemInfos[partition]
+ imgInstallPath := android.PathForModuleInPartitionInstall(ctx, "", partition+".img")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: info.Output,
+ Output: imgInstallPath,
+ })
+
+ // Make it so doing `m <moduleName>` or `m <partitionType>image` will copy the files to
+ // PRODUCT_OUT
+ if partition == "system_ext" {
+ partition = "systemext"
+ }
+ partition = partition + "image"
+ ctx.Phony(info.ModuleName, imgInstallPath)
+ ctx.Phony(partition, imgInstallPath)
+ for _, fip := range info.FullInstallPaths {
+ // TODO: Directories. But maybe they're not necessary? Adevice doesn't care
+ // about empty directories, still need to check if adb sync does.
+ if !fip.IsDir {
+ if !fip.RequiresFullInstall {
+ // Some modules set requires_full_install: false, which causes their staging
+ // directory file to not be installed. This is usually because the file appears
+ // in both PRODUCT_COPY_FILES and a soong module for the handwritten soong system
+ // image. In this case, that module's installed files would conflict with the
+ // PRODUCT_COPY_FILES. However, in soong-only builds, we don't automatically
+ // create rules for PRODUCT_COPY_FILES unless they're needed in the partition.
+ // So in that case, nothing is creating the installed path. Create them now
+ // if that's the case.
+ if fip.SymlinkTarget == "" {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpWithBash,
+ Input: fip.SourcePath,
+ Output: fip.FullInstallPath,
+ Args: map[string]string{
+ // Preserve timestamps for adb sync, so that this installed file's
+ // timestamp matches the timestamp in the filesystem's intermediate
+ // staging dir
+ "cpFlags": "-p",
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.SymlinkWithBash,
+ Output: fip.FullInstallPath,
+ Args: map[string]string{
+ "fromPath": fip.SymlinkTarget,
+ },
+ })
+ }
+ }
+ ctx.Phony(info.ModuleName, fip.FullInstallPath)
+ ctx.Phony(partition, fip.FullInstallPath)
+ deps = append(deps, fip.FullInstallPath)
+ depsNoImg = append(depsNoImg, fip.FullInstallPath)
+ ctx.Phony("sync_"+partition, fip.FullInstallPath)
+ ctx.Phony("sync", fip.FullInstallPath)
+ }
+ }
+
+ deps = append(deps, imgInstallPath)
+ }
+
+ a.createComplianceMetadataTimestamp(ctx, depsNoImg)
+
+ // List all individual files to be copied to PRODUCT_OUT here
+ if a.deviceProps.Bootloader != nil {
+ bootloaderInstallPath := android.PathForModuleInPartitionInstall(ctx, "", "bootloader")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: android.PathForModuleSrc(ctx, *a.deviceProps.Bootloader),
+ Output: bootloaderInstallPath,
+ })
+ deps = append(deps, bootloaderInstallPath)
+ }
+
+ copyBootImg := func(prop *string, type_ string) {
+ if proptools.String(prop) != "" {
+ partition := ctx.GetDirectDepWithTag(*prop, filesystemDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, partition, BootimgInfoProvider); ok {
+ installPath := android.PathForModuleInPartitionInstall(ctx, "", type_+".img")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: info.Output,
+ Output: installPath,
+ })
+ deps = append(deps, installPath)
+ } else {
+ ctx.ModuleErrorf("%s does not set BootimgInfo\n", *prop)
+ }
+ }
+ }
+
+ copyBootImg(a.partitionProps.Init_boot_partition_name, "init_boot")
+ copyBootImg(a.partitionProps.Boot_partition_name, "boot")
+ copyBootImg(a.partitionProps.Vendor_boot_partition_name, "vendor_boot")
+
+ for _, vbmetaModName := range a.partitionProps.Vbmeta_partitions {
+ partition := ctx.GetDirectDepWithTag(vbmetaModName, filesystemDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, partition, vbmetaPartitionProvider); ok {
+ installPath := android.PathForModuleInPartitionInstall(ctx, "", info.Name+".img")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: info.Output,
+ Output: installPath,
+ })
+ deps = append(deps, installPath)
+ } else {
+ ctx.ModuleErrorf("%s does not set vbmetaPartitionProvider\n", vbmetaModName)
+ }
+ }
+
+ if proptools.String(a.partitionProps.Super_partition_name) != "" {
+ partition := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, partition, SuperImageProvider); ok {
+ installPath := android.PathForModuleInPartitionInstall(ctx, "", "super.img")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: info.SuperImage,
+ Output: installPath,
+ })
+ deps = append(deps, installPath)
+ } else {
+ ctx.ModuleErrorf("%s does not set SuperImageProvider\n", *a.partitionProps.Super_partition_name)
+ }
+ }
+
+ if proptools.String(a.deviceProps.Android_info) != "" {
+ installPath := android.PathForModuleInPartitionInstall(ctx, "", "android-info.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: android.PathForModuleSrc(ctx, *a.deviceProps.Android_info),
+ Output: installPath,
+ })
+ deps = append(deps, installPath)
+ }
+
+ copyToProductOutTimestamp := android.PathForModuleOut(ctx, "product_out_copy_timestamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: copyToProductOutTimestamp,
+ Implicits: deps,
+ })
+
+ emptyFile := android.PathForModuleOut(ctx, "empty_file")
+ android.WriteFileRule(ctx, emptyFile, "")
+
+ // TODO: We don't have these tests building in soong yet. Add phonies for them so that CI builds
+ // that try to build them don't error out.
+ ctx.Phony("continuous_instrumentation_tests", emptyFile)
+ ctx.Phony("continuous_native_tests", emptyFile)
+ ctx.Phony("device-tests", emptyFile)
+ ctx.Phony("device-platinum-tests", emptyFile)
+ ctx.Phony("platform_tests", emptyFile)
+
+ return copyToProductOutTimestamp
+}
+
+// createComplianceMetadataTimestampForSoongOnly creates a timestamp file in m --soong-only
+// this timestamp file depends on installed files of the main `android_device`.
+// Any changes to installed files of the main `android_device` will retrigger SBOM generation
+func (a *androidDevice) createComplianceMetadataTimestamp(ctx android.ModuleContext, installedFiles android.Paths) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Implicits: installedFiles,
+ Output: android.PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "installed_files.stamp"),
+ })
+}
+
+// Returns a mapping from partition type -> FilesystemInfo. This includes filesystems that are
+// nested inside of other partitions, such as the partitions inside super.img, or ramdisk inside
+// of boot.
+func (a *androidDevice) getFsInfos(ctx android.ModuleContext) map[string]FilesystemInfo {
+ type propToType struct {
+ prop *string
+ ty string
+ }
+
+ filesystemInfos := make(map[string]FilesystemInfo)
+
+ partitionDefinitions := []propToType{
+ propToType{a.partitionProps.System_partition_name, "system"},
+ propToType{a.partitionProps.System_ext_partition_name, "system_ext"},
+ propToType{a.partitionProps.Product_partition_name, "product"},
+ propToType{a.partitionProps.Vendor_partition_name, "vendor"},
+ propToType{a.partitionProps.Odm_partition_name, "odm"},
+ propToType{a.partitionProps.Recovery_partition_name, "recovery"},
+ propToType{a.partitionProps.System_dlkm_partition_name, "system_dlkm"},
+ propToType{a.partitionProps.Vendor_dlkm_partition_name, "vendor_dlkm"},
+ propToType{a.partitionProps.Odm_dlkm_partition_name, "odm_dlkm"},
+ propToType{a.partitionProps.Userdata_partition_name, "userdata"},
+ // filesystemInfo from init_boot and vendor_boot actually are re-exports of the ramdisk
+ // images inside of them
+ propToType{a.partitionProps.Init_boot_partition_name, "ramdisk"},
+ propToType{a.partitionProps.Vendor_boot_partition_name, "vendor_ramdisk"},
+ }
+ for _, partitionDefinition := range partitionDefinitions {
+ if proptools.String(partitionDefinition.prop) != "" {
+ partition := ctx.GetDirectDepWithTag(*partitionDefinition.prop, filesystemDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, partition, FilesystemProvider); ok {
+ filesystemInfos[partitionDefinition.ty] = info
+ } else {
+ ctx.ModuleErrorf("Super partition %s does not set FilesystemProvider\n", partition.Name())
+ }
+ }
+ }
+ if a.partitionProps.Super_partition_name != nil {
+ superPartition := ctx.GetDirectDepWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag)
+ if info, ok := android.OtherModuleProvider(ctx, superPartition, SuperImageProvider); ok {
+ for partition := range info.SubImageInfo {
+ filesystemInfos[partition] = info.SubImageInfo[partition]
+ }
+ } else {
+ ctx.ModuleErrorf("Super partition %s does not set SuperImageProvider\n", superPartition.Name())
+ }
+ }
+
+ return filesystemInfos
+}
diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go
index 9d4ba3e..c776012 100644
--- a/filesystem/avb_add_hash_footer.go
+++ b/filesystem/avb_add_hash_footer.go
@@ -46,7 +46,7 @@
type avbAddHashFooterProperties struct {
// Source file of this image. Can reference a genrule type module with the ":module" syntax.
- Src *string `android:"path,arch_variant"`
+ Src proptools.Configurable[string] `android:"path,arch_variant,replace_instead_of_append"`
// Set the name of the output. Defaults to <module_name>.img.
Filename *string
@@ -70,7 +70,7 @@
Props []avbProp
// The index used to prevent rollback of the image on device.
- Rollback_index *int64
+ Rollback_index proptools.Configurable[int64] `android:"replace_instead_of_append"`
// Include descriptors from images
Include_descriptors_from_images []string `android:"path,arch_variant"`
@@ -91,12 +91,13 @@
func (a *avbAddHashFooter) GenerateAndroidBuildActions(ctx android.ModuleContext) {
builder := android.NewRuleBuilder(pctx, ctx)
+ src := a.properties.Src.GetOrDefault(ctx, "")
- if a.properties.Src == nil {
+ if src == "" {
ctx.PropertyErrorf("src", "missing source file")
return
}
- input := android.PathForModuleSrc(ctx, proptools.String(a.properties.Src))
+ input := android.PathForModuleSrc(ctx, src)
output := android.PathForModuleOut(ctx, a.installFileName())
builder.Command().Text("cp").Input(input).Output(output)
@@ -133,8 +134,9 @@
addAvbProp(ctx, cmd, prop)
}
- if a.properties.Rollback_index != nil {
- rollbackIndex := proptools.Int(a.properties.Rollback_index)
+ rollbackIndex := a.properties.Rollback_index.Get(ctx)
+ if rollbackIndex.IsPresent() {
+ rollbackIndex := rollbackIndex.Get()
if rollbackIndex < 0 {
ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative")
}
@@ -148,6 +150,8 @@
a.installDir = android.PathForModuleInstall(ctx, "etc")
ctx.InstallFile(a.installDir, a.installFileName(), output)
a.output = output
+
+ setCommonFilesystemInfo(ctx, a)
}
func addAvbProp(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, prop avbProp) {
@@ -207,6 +211,9 @@
// Implements android.SourceFileProducer
func (a *avbAddHashFooter) Srcs() android.Paths {
+ if a.output == nil {
+ return nil
+ }
return append(android.Paths{}, a.output)
}
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 0ffec26..485eae4 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -99,6 +99,9 @@
// The index used to prevent rollback of the image on device.
Avb_rollback_index *int64
+ // Rollback index location of this image. Must be 0, 1, 2, etc.
+ Avb_rollback_index_location *int64
+
// The security patch passed to as the com.android.build.<type>.security_patch avb property.
// Replacement for the make variables BOOT_SECURITY_PATCH / INIT_BOOT_SECURITY_PATCH.
Security_patch *string
@@ -197,12 +200,9 @@
ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel")
return
}
- var kernel android.Path
- if kernelProp != "" {
- kernel = android.PathForModuleSrc(ctx, kernelProp)
- }
- unsignedOutput := b.buildBootImage(ctx, kernel)
+ kernelPath := b.getKernelPath(ctx)
+ unsignedOutput := b.buildBootImage(ctx, kernelPath)
output := unsignedOutput
if proptools.Bool(b.properties.Use_avb) {
@@ -213,7 +213,7 @@
case "default":
output = b.signImage(ctx, unsignedOutput)
case "make_legacy":
- output = b.addAvbFooter(ctx, unsignedOutput, kernel)
+ output = b.addAvbFooter(ctx, unsignedOutput, kernelPath)
default:
ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode)
}
@@ -224,6 +224,103 @@
ctx.SetOutputFiles([]android.Path{output}, "")
b.output = output
+
+ // Set the Filesystem info of the ramdisk dependency.
+ // `android_device` will use this info to package `target_files.zip`
+ if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
+ ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep)
+ fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider)
+ android.SetProvider(ctx, FilesystemProvider, fsInfo)
+ } else {
+ setCommonFilesystemInfo(ctx, b)
+ }
+
+ // Set BootimgInfo for building target_files.zip
+ dtbPath := b.getDtbPath(ctx)
+ android.SetProvider(ctx, BootimgInfoProvider, BootimgInfo{
+ Cmdline: b.properties.Cmdline,
+ Kernel: kernelPath,
+ Dtb: dtbPath,
+ Bootconfig: b.getBootconfigPath(ctx),
+ Output: output,
+ PropFileForMiscInfo: b.buildPropFileForMiscInfo(ctx),
+ HeaderVersion: proptools.String(b.properties.Header_version),
+ })
+
+ extractedPublicKey := android.PathForModuleOut(ctx, b.partitionName()+".avbpubkey")
+ if b.properties.Avb_private_key != nil {
+ key := android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractPublicKeyRule,
+ Input: key,
+ Output: extractedPublicKey,
+ })
+ }
+ var ril int
+ if b.properties.Avb_rollback_index_location != nil {
+ ril = proptools.Int(b.properties.Avb_rollback_index_location)
+ }
+
+ android.SetProvider(ctx, vbmetaPartitionProvider, vbmetaPartitionInfo{
+ Name: b.bootImageType.String(),
+ RollbackIndexLocation: ril,
+ PublicKey: extractedPublicKey,
+ Output: output,
+ })
+
+ // Dump compliance metadata
+ complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+ prebuiltFilesCopied := make([]string, 0)
+ if kernelPath != nil {
+ prebuiltFilesCopied = append(prebuiltFilesCopied, kernelPath.String()+":kernel")
+ }
+ if dtbPath != nil {
+ prebuiltFilesCopied = append(prebuiltFilesCopied, dtbPath.String()+":dtb.img")
+ }
+ complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied)
+
+ if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
+ buildComplianceMetadata(ctx, bootimgRamdiskDep)
+ }
+}
+
+var BootimgInfoProvider = blueprint.NewProvider[BootimgInfo]()
+
+type BootimgInfo struct {
+ Cmdline []string
+ Kernel android.Path
+ Dtb android.Path
+ Bootconfig android.Path
+ Output android.Path
+ PropFileForMiscInfo android.Path
+ HeaderVersion string
+}
+
+func (b *bootimg) getKernelPath(ctx android.ModuleContext) android.Path {
+ var kernelPath android.Path
+ kernelName := proptools.String(b.properties.Kernel_prebuilt)
+ if kernelName != "" {
+ kernelPath = android.PathForModuleSrc(ctx, kernelName)
+ }
+ return kernelPath
+}
+
+func (b *bootimg) getDtbPath(ctx android.ModuleContext) android.Path {
+ var dtbPath android.Path
+ dtbName := proptools.String(b.properties.Dtb_prebuilt)
+ if dtbName != "" {
+ dtbPath = android.PathForModuleSrc(ctx, dtbName)
+ }
+ return dtbPath
+}
+
+func (b *bootimg) getBootconfigPath(ctx android.ModuleContext) android.Path {
+ var bootconfigPath android.Path
+ bootconfigName := proptools.String(b.properties.Bootconfig)
+ if bootconfigName != "" {
+ bootconfigPath = android.PathForModuleSrc(ctx, bootconfigName)
+ }
+ return bootconfigPath
}
func (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path) android.Path {
@@ -242,10 +339,8 @@
cmd.FlagWithArg("--os_patch_level ", ctx.Config().PlatformSecurityPatch())
}
- dtbName := proptools.String(b.properties.Dtb_prebuilt)
- if dtbName != "" {
- dtb := android.PathForModuleSrc(ctx, dtbName)
- cmd.FlagWithInput("--dtb ", dtb)
+ if b.getDtbPath(ctx) != nil {
+ cmd.FlagWithInput("--dtb ", b.getDtbPath(ctx))
}
cmdline := strings.Join(b.properties.Cmdline, " ")
@@ -391,15 +486,6 @@
return output
}
-// Calculates avb_salt from some input for deterministic output.
-func (b *bootimg) salt() string {
- var input []string
- input = append(input, b.properties.Cmdline...)
- input = append(input, proptools.StringDefault(b.properties.Partition_name, b.Name()))
- input = append(input, proptools.String(b.properties.Header_version))
- return sha1sum(input)
-}
-
func (b *bootimg) buildPropFile(ctx android.ModuleContext) (android.Path, android.Paths) {
var sb strings.Builder
var deps android.Paths
@@ -420,13 +506,71 @@
addStr("avb_add_hash_footer_args", "") // TODO(jiyong): add --rollback_index
partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name())
addStr("partition_name", partitionName)
- addStr("avb_salt", b.salt())
propFile := android.PathForModuleOut(ctx, "prop")
android.WriteFileRule(ctx, propFile, sb.String())
return propFile, deps
}
+func (b *bootimg) getAvbHashFooterArgs(ctx android.ModuleContext) string {
+ ret := ""
+ if !b.bootImageType.isVendorBoot() {
+ ret += "--prop " + fmt.Sprintf("com.android.build.%s.os_version:%s", b.bootImageType.String(), ctx.Config().PlatformVersionLastStable())
+ }
+
+ fingerprintFile := ctx.Config().BuildFingerprintFile(ctx)
+ ret += " --prop " + fmt.Sprintf("com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", b.bootImageType.String(), fingerprintFile.String())
+
+ if b.properties.Security_patch != nil {
+ ret += " --prop " + fmt.Sprintf("com.android.build.%s.security_patch:%s", b.bootImageType.String(), *b.properties.Security_patch)
+ }
+
+ if b.properties.Avb_rollback_index != nil {
+ ret += " --rollback_index " + strconv.FormatInt(*b.properties.Avb_rollback_index, 10)
+ }
+ return strings.TrimSpace(ret)
+}
+
+func (b *bootimg) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path {
+ var sb strings.Builder
+ addStr := func(name string, value string) {
+ fmt.Fprintf(&sb, "%s=%s\n", name, value)
+ }
+
+ bootImgType := proptools.String(b.properties.Boot_image_type)
+ addStr("avb_"+bootImgType+"_add_hash_footer_args", b.getAvbHashFooterArgs(ctx))
+ if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
+ ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep)
+ fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider)
+ if fsInfo.HasOrIsRecovery {
+ // Create a dup entry for recovery
+ addStr("avb_recovery_add_hash_footer_args", strings.ReplaceAll(b.getAvbHashFooterArgs(ctx), bootImgType, "recovery"))
+ }
+ }
+ if b.properties.Avb_private_key != nil {
+ addStr("avb_"+bootImgType+"_algorithm", proptools.StringDefault(b.properties.Avb_algorithm, "SHA256_RSA4096"))
+ addStr("avb_"+bootImgType+"_key_path", android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key)).String())
+ addStr("avb_"+bootImgType+"_rollback_index_location", strconv.Itoa(proptools.Int(b.properties.Avb_rollback_index_location)))
+ }
+ if b.properties.Partition_size != nil {
+ addStr(bootImgType+"_size", strconv.FormatInt(*b.properties.Partition_size, 10))
+ }
+ if bootImgType != "boot" {
+ addStr(bootImgType, "true")
+ }
+
+ propFilePreProcessing := android.PathForModuleOut(ctx, "prop_for_misc_info_pre_processing")
+ android.WriteFileRuleVerbatim(ctx, propFilePreProcessing, sb.String())
+ propFile := android.PathForModuleOut(ctx, "prop_file_for_misc_info")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: textFileProcessorRule,
+ Input: propFilePreProcessing,
+ Output: propFile,
+ })
+
+ return propFile
+}
+
var _ android.AndroidMkEntriesProvider = (*bootimg)(nil)
// Implements android.AndroidMkEntriesProvider
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index b9cb076..c3c3835 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -20,6 +20,7 @@
"io"
"path/filepath"
"slices"
+ "sort"
"strconv"
"strings"
@@ -29,12 +30,18 @@
"android/soong/linkerconfig"
"github.com/google/blueprint"
+ "github.com/google/blueprint/depset"
"github.com/google/blueprint/proptools"
)
+var pctx = android.NewPackageContext("android/soong/filesystem")
+
func init() {
registerBuildComponents(android.InitRegistrationContext)
registerMutators(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("fileslist", "fileslist")
+ pctx.HostBinToolVariable("fs_config", "fs_config")
+ pctx.HostBinToolVariable("symbols_map", "symbols_map")
}
func registerBuildComponents(ctx android.RegistrationContext) {
@@ -53,11 +60,28 @@
})
}
-// Remember to add referenced files to implicits!
-var textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
- Command: "build/soong/scripts/text_file_processor.py $in $out",
- CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
-})
+var (
+ // Remember to add referenced files to implicits!
+ textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{
+ Command: "build/soong/scripts/text_file_processor.py $in $out",
+ CommandDeps: []string{"build/soong/scripts/text_file_processor.py"},
+ })
+
+ // Remember to add the output image file as an implicit dependency!
+ installedFilesJsonRule = pctx.AndroidStaticRule("installed_files_json", blueprint.RuleParams{
+ Command: `${fileslist} ${rootDir} > ${out}`,
+ CommandDeps: []string{"${fileslist}"},
+ }, "rootDir")
+
+ installedFilesTxtRule = pctx.AndroidStaticRule("installed_files_txt", blueprint.RuleParams{
+ Command: `build/make/tools/fileslist_util.py -c ${in} > ${out}`,
+ CommandDeps: []string{"build/make/tools/fileslist_util.py"},
+ })
+ fsConfigRule = pctx.AndroidStaticRule("fs_config_rule", blueprint.RuleParams{
+ Command: `(cd ${rootDir}; find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,${prefix},' | ${fs_config} -C -D ${rootDir} -R "${prefix}" > ${out}`,
+ CommandDeps: []string{"${fs_config}"},
+ }, "rootDir", "prefix")
+)
type filesystem struct {
android.ModuleBase
@@ -75,10 +99,12 @@
entries []string
filesystemBuilder filesystemBuilder
+
+ selinuxFc android.Path
}
type filesystemBuilder interface {
- BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath)
+ BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo)
// Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs()
FilterPackagingSpec(spec android.PackagingSpec) bool
// Function that modifies PackagingSpec in PackagingBase.GatherPackagingSpecs() to customize.
@@ -98,6 +124,14 @@
Name *string
}
+// CopyWithNamePrefix returns a new [SymlinkDefinition] with prefix added to Name.
+func (s *SymlinkDefinition) CopyWithNamePrefix(prefix string) SymlinkDefinition {
+ return SymlinkDefinition{
+ Target: s.Target,
+ Name: proptools.StringPtr(filepath.Join(prefix, proptools.String(s.Name))),
+ }
+}
+
type FilesystemProperties struct {
// When set to true, sign the image with avbtool. Default is false.
Use_avb *bool
@@ -110,15 +144,21 @@
Avb_algorithm *string
// Hash algorithm used for avbtool (for descriptors). This is passed as hash_algorithm to
- // avbtool. Default used by avbtool is sha1.
+ // avbtool. Default is sha256.
Avb_hash_algorithm *string
+ // The security patch passed to as the com.android.build.<type>.security_patch avb property.
+ Security_patch *string
+
// Whether or not to use forward-error-correction codes when signing with AVB. Defaults to true.
Use_fec *bool
// The index used to prevent rollback of the image. Only used if use_avb is true.
Rollback_index *int64
+ // Rollback index location of this image. Must be 1, 2, 3, etc.
+ Rollback_index_location *int64
+
// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
Partition_name *string
@@ -144,6 +184,11 @@
// Directories to be created under root. e.g. /dev, /proc, etc.
Dirs proptools.Configurable[[]string]
+ // List of filesystem modules to include in creating the partition. The root directory of
+ // the provided filesystem modules are included in creating the partition.
+ // This is only supported for cpio and compressed cpio filesystem types.
+ Include_files_of []string
+
// Symbolic links to be created under root with "ln -sf <target> <name>".
Symlinks []SymlinkDefinition
@@ -157,12 +202,6 @@
// 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
-
// When set, builds etc/event-log-tags file by merging logtags from all dependencies.
// Default is false
Build_logtags *bool
@@ -194,6 +233,26 @@
// Additional dependencies used for building android products
Android_filesystem_deps AndroidFilesystemDeps
+
+ // Name of the output. Default is $(module_name).img
+ Stem *string
+
+ // The size of the partition on the device. It will be a build error if this built partition
+ // image exceeds this size.
+ Partition_size *int64
+
+ // Whether to format f2fs and ext4 in a way that supports casefolding
+ Support_casefolding *bool
+
+ // Whether to format f2fs and ext4 in a way that supports project quotas
+ Support_project_quota *bool
+
+ // Whether to enable per-file compression in f2fs
+ Enable_compression *bool
+
+ // Whether this partition is not supported by flashall.
+ // If true, this partition will not be included in the `updatedpackage` dist artifact.
+ No_flashall *bool
}
type AndroidFilesystemDeps struct {
@@ -270,6 +329,8 @@
var interPartitionDependencyTag = interPartitionDepTag{}
+var interPartitionInstallDependencyTag = interPartitionDepTag{}
+
var _ android.ExcludeFromVisibilityEnforcementTag = (*depTagWithVisibilityEnforcementBypass)(nil)
func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement() {}
@@ -298,6 +359,9 @@
if f.properties.Android_filesystem_deps.System_ext != nil {
ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System_ext))
}
+ for _, partition := range f.properties.Include_files_of {
+ ctx.AddDependency(ctx.Module(), interPartitionInstallDependencyTag, partition)
+ }
}
type fsType int
@@ -315,13 +379,132 @@
return fs == unknown
}
+// Type string that build_image.py accepts.
+func (t fsType) String() string {
+ switch t {
+ // TODO(372522486): add more types like f2fs, erofs, etc.
+ case ext4Type:
+ return "ext4"
+ case erofsType:
+ return "erofs"
+ case f2fsType:
+ return "f2fs"
+ }
+ panic(fmt.Errorf("unsupported fs type %d", t))
+}
+
+type InstalledFilesStruct struct {
+ Txt android.Path
+ Json android.Path
+}
+
+type InstalledModuleInfo struct {
+ Name string
+ Variation string
+}
+
type FilesystemInfo struct {
+ // The built filesystem image
+ Output android.Path
+ // Returns the output file that is signed by avbtool. If this module is not signed, returns
+ // nil.
+ SignedOutputPath android.Path
+ // An additional hermetic filesystem image.
+ // e.g. this will contain inodes with pinned timestamps.
+ // This will be copied to target_files.zip
+ OutputHermetic android.Path
// A text file containing the list of paths installed on the partition.
FileListFile android.Path
+ // The root staging directory used to build the output filesystem. If consuming this, make sure
+ // to add a dependency on the Output file, as you cannot add dependencies on directories
+ // in ninja.
+ RootDir android.Path
+ // Extra root directories that are also built into the partition. Currently only used for
+ // including the recovery partition files into the vendor_boot image.
+ ExtraRootDirs android.Paths
+ // The rebased staging directory used to build the output filesystem. If consuming this, make
+ // sure to add a dependency on the Output file, as you cannot add dependencies on directories
+ // in ninja. In many cases this is the same as RootDir, only in the system partition is it
+ // different. There, it points to the "system" sub-directory of RootDir.
+ RebasedDir android.Path
+ // A text file with block data of the .img file
+ // This is an implicit output of `build_image`
+ MapFile android.Path
+ // Name of the module that produced this FilesystemInfo origionally. (though it may be
+ // re-exported by super images or boot images)
+ ModuleName string
+ // The property file generated by this module and passed to build_image.
+ // It's exported here so that system_other can reuse system's property file.
+ BuildImagePropFile android.Path
+ // Paths to all the tools referenced inside of the build image property file.
+ BuildImagePropFileDeps android.Paths
+ // Packaging specs to be installed on the system_other image, for the initial boot's dexpreopt.
+ SpecsForSystemOther map[string]android.PackagingSpec
+
+ FullInstallPaths []FullInstallPathInfo
+
+ // Installed files dep set of this module and its dependency filesystem modules
+ InstalledFilesDepSet depset.DepSet[InstalledFilesStruct]
+
+ // Path to compress hints file for erofs filesystems
+ // This will be nil for other fileystems like ext4
+ ErofsCompressHints android.Path
+
+ SelinuxFc android.Path
+
+ FilesystemConfig android.Path
+
+ Owners []InstalledModuleInfo
+
+ HasFsverity bool
+
+ PropFileForMiscInfo android.Path
+
+ // Additional avb and partition size information.
+ // `system_other` will use this information of `system` dep for misc_info.txt processing.
+ PartitionSize *int64
+ UseAvb bool
+ AvbAlgorithm string
+ AvbHashAlgorithm string
+ AvbKey android.Path
+ PartitionName string
+ NoFlashall bool
+ // HasOrIsRecovery returns true for recovery and for ramdisks with a recovery partition.
+ HasOrIsRecovery bool
+}
+
+// FullInstallPathInfo contains information about the "full install" paths of all the files
+// inside this partition. The full install paths are the files installed in
+// out/target/product/<device>/<partition>. This is essentially legacy behavior, maintained for
+// tools like adb sync and adevice, but we should update them to query the build system for the
+// installed files no matter where they are.
+type FullInstallPathInfo struct {
+ // RequiresFullInstall tells us if the origional module did the install to FullInstallPath
+ // already. If it's false, the android_device module needs to emit the install rule.
+ RequiresFullInstall bool
+ // The "full install" paths for the files in this filesystem. This is the paths in the
+ // out/target/product/<device>/<partition> folder. They're not used by this filesystem,
+ // but can be depended on by the top-level android_device module to cause the staging
+ // directories to be built.
+ FullInstallPath android.InstallPath
+
+ // The file that's copied to FullInstallPath. May be nil if SymlinkTarget is set or IsDir is
+ // true.
+ SourcePath android.Path
+
+ // The target of the symlink, if this file is a symlink.
+ SymlinkTarget string
+
+ // If this file is a directory. Only used for empty directories, which are mostly mount points.
+ IsDir bool
}
var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]()
+type FilesystemDefaultsInfo struct{}
+
+var FilesystemDefaultsInfoProvider = blueprint.NewProvider[FilesystemDefaultsInfo]()
+
func GetFsTypeFromString(ctx android.EarlyModuleContext, typeStr string) fsType {
switch typeStr {
case "ext4":
@@ -349,7 +532,7 @@
}
func (f *filesystem) installFileName() string {
- return f.BaseModuleName() + ".img"
+ return proptools.StringDefault(f.properties.Stem, f.BaseModuleName()+".img")
}
func (f *filesystem) partitionName() string {
@@ -362,6 +545,13 @@
if ps.SkipInstall() {
return false
}
+ // "apex" is a fake partition used to install files in out/target/product/<device>/apex/.
+ // Don't include these files in the partition. We should also look into removing the following
+ // TODO to check the PackagingSpec's partition against this filesystem's partition for all
+ // modules, not just autogenerated ones, which will fix this as well.
+ if ps.Partition() == "apex" {
+ return false
+ }
if proptools.Bool(f.properties.Is_auto_generated) { // TODO (spandandas): Remove this.
pt := f.PartitionType()
return ps.Partition() == pt || strings.HasPrefix(ps.Partition(), pt+"/")
@@ -384,20 +574,104 @@
}
}
-var pctx = android.NewPackageContext("android/soong/filesystem")
+func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) InstalledFilesStruct {
+ fileName := "installed-files"
+ if len(partition) > 0 {
+ fileName += fmt.Sprintf("-%s", partition)
+ }
+ txt := android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName))
+ json := android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName))
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: installedFilesJsonRule,
+ Implicit: image,
+ Output: json,
+ Description: "Installed file list json",
+ Args: map[string]string{
+ "rootDir": rootDir.String(),
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: installedFilesTxtRule,
+ Input: json,
+ Output: txt,
+ Description: "Installed file list txt",
+ })
+
+ return InstalledFilesStruct{
+ Txt: txt,
+ Json: json,
+ }
+}
func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
validatePartitionType(ctx, f)
if f.filesystemBuilder.ShouldUseVintfFragmentModuleOnly() {
f.validateVintfFragments(ctx)
}
+
+ if len(f.properties.Include_files_of) > 0 && !android.InList(f.fsType(ctx), []fsType{compressedCpioType, cpioType}) {
+ ctx.PropertyErrorf("include_files_of", "include_files_of is only supported for cpio and compressed cpio filesystem types.")
+ }
+
+ rootDir := android.PathForModuleOut(ctx, f.rootDirString()).OutputPath
+ 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)
+
+ var fullInstallPaths []FullInstallPathInfo
+ for _, specRel := range android.SortedKeys(specs) {
+ spec := specs[specRel]
+ fullInstallPaths = append(fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: spec.FullInstallPath(),
+ RequiresFullInstall: spec.RequiresFullInstall(),
+ SourcePath: spec.SrcPath(),
+ SymlinkTarget: spec.ToGob().SymlinkTarget,
+ })
+ }
+
+ f.entries = f.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
+ f.buildNonDepsFiles(ctx, builder, rootDir, rebasedDir, &fullInstallPaths)
+ f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir, &fullInstallPaths)
+ f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths)
+ f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths)
+ f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths)
+ // Assemeble the staging dir and output a timestamp
+ builder.Command().Text("touch").Output(f.fileystemStagingDirTimestamp(ctx))
+ builder.Build("assemble_filesystem_staging_dir", fmt.Sprintf("Assemble filesystem staging dir %s", f.BaseModuleName()))
+
+ // Create a new rule builder for build_image
+ builder = android.NewRuleBuilder(pctx, ctx)
+ var mapFile android.Path
+ var outputHermetic android.WritablePath
+ var buildImagePropFile android.Path
+ var buildImagePropFileDeps android.Paths
+ var extraRootDirs android.Paths
+ var propFileForMiscInfo android.Path
switch f.fsType(ctx) {
case ext4Type, erofsType, f2fsType:
- f.output = f.buildImageUsingBuildImage(ctx)
+ buildImagePropFile, buildImagePropFileDeps = f.buildPropFile(ctx)
+ propFileForMiscInfo = f.buildPropFileForMiscInfo(ctx)
+ output := android.PathForModuleOut(ctx, f.installFileName())
+ f.buildImageUsingBuildImage(ctx, builder, buildImageParams{rootDir, buildImagePropFile, buildImagePropFileDeps, output})
+ f.output = output
+ // Create the hermetic img file using a separate rule builder so that it can be built independently
+ hermeticBuilder := android.NewRuleBuilder(pctx, ctx)
+ outputHermetic = android.PathForModuleOut(ctx, "for_target_files", f.installFileName())
+ propFileHermetic := f.propFileForHermeticImg(ctx, hermeticBuilder, buildImagePropFile)
+ f.buildImageUsingBuildImage(ctx, hermeticBuilder, buildImageParams{rootDir, propFileHermetic, buildImagePropFileDeps, outputHermetic})
+ mapFile = f.getMapFile(ctx)
case compressedCpioType:
- f.output = f.buildCpioImage(ctx, true)
+ f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, true)
case cpioType:
- f.output = f.buildCpioImage(ctx, false)
+ f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, false)
default:
return
}
@@ -406,17 +680,146 @@
ctx.InstallFile(f.installDir, f.installFileName(), f.output)
ctx.SetOutputFiles([]android.Path{f.output}, "")
+ if f.partitionName() == "recovery" {
+ rootDir = rootDir.Join(ctx, "root")
+ }
+
fileListFile := android.PathForModuleOut(ctx, "fileList")
android.WriteFileRule(ctx, fileListFile, f.installedFilesList())
- android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{
- FileListFile: fileListFile,
+ var partitionNameForInstalledFiles string
+ switch f.partitionName() {
+ case "system":
+ partitionNameForInstalledFiles = ""
+ case "vendor_ramdisk":
+ partitionNameForInstalledFiles = "vendor-ramdisk"
+ default:
+ partitionNameForInstalledFiles = f.partitionName()
+ }
+
+ var erofsCompressHints android.Path
+ if f.properties.Erofs.Compress_hints != nil {
+ erofsCompressHints = android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints)
+ }
+
+ fsInfo := FilesystemInfo{
+ Output: f.OutputPath(),
+ SignedOutputPath: f.SignedOutputPath(),
+ OutputHermetic: outputHermetic,
+ FileListFile: fileListFile,
+ RootDir: rootDir,
+ ExtraRootDirs: extraRootDirs,
+ RebasedDir: rebasedDir,
+ MapFile: mapFile,
+ ModuleName: ctx.ModuleName(),
+ BuildImagePropFile: buildImagePropFile,
+ BuildImagePropFileDeps: buildImagePropFileDeps,
+ SpecsForSystemOther: f.systemOtherFiles(ctx),
+ FullInstallPaths: fullInstallPaths,
+ InstalledFilesDepSet: depset.New(
+ depset.POSTORDER,
+ []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rootDir, f.output)},
+ includeFilesInstalledFiles(ctx),
+ ),
+ ErofsCompressHints: erofsCompressHints,
+ SelinuxFc: f.selinuxFc,
+ FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir),
+ Owners: f.gatherOwners(specs),
+ HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil,
+ PropFileForMiscInfo: propFileForMiscInfo,
+ PartitionSize: f.properties.Partition_size,
+ PartitionName: f.partitionName(),
+ HasOrIsRecovery: f.hasOrIsRecovery(ctx),
+ NoFlashall: proptools.Bool(f.properties.No_flashall),
+ }
+ if proptools.Bool(f.properties.Use_avb) {
+ fsInfo.UseAvb = true
+ fsInfo.AvbAlgorithm = proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096")
+ fsInfo.AvbHashAlgorithm = proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256")
+ if f.properties.Avb_private_key != nil {
+ fsInfo.AvbKey = android.PathForModuleSrc(ctx, *f.properties.Avb_private_key)
+ }
+ }
+
+ android.SetProvider(ctx, FilesystemProvider, fsInfo)
+
+ android.SetProvider(ctx, android.PartitionTypeInfoProvider, android.PartitionTypeInfo{
+ PartitionType: f.PartitionType(),
})
+
f.fileListFile = fileListFile
if proptools.Bool(f.properties.Unchecked_module) {
ctx.UncheckedModule()
}
+
+ f.setVbmetaPartitionProvider(ctx)
+
+ // Dump metadata that can not be done in android/compliance-metadata.go
+ complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+ filesContained := make([]string, 0, len(fullInstallPaths))
+ for _, file := range fullInstallPaths {
+ filesContained = append(filesContained, file.FullInstallPath.String())
+ }
+ complianceMetadataInfo.SetFilesContained(filesContained)
+}
+
+func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath {
+ return android.PathForModuleOut(ctx, "staging_dir.timestamp")
+}
+
+func (f *filesystem) generateFilesystemConfig(ctx android.ModuleContext, rootDir android.Path, rebasedDir android.Path) android.Path {
+ rootDirString := rootDir.String()
+ prefix := f.partitionName() + "/"
+ if f.partitionName() == "system" {
+ rootDirString = rebasedDir.String()
+ }
+ if f.partitionName() == "ramdisk" || f.partitionName() == "recovery" {
+ // Hardcoded to match make behavior.
+ // https://cs.android.com/android/_/android/platform/build/+/2a0ef42a432d4da00201e8eb7697dcaa68fd2389:core/Makefile;l=6957-6962;drc=9ea8ad9232cef4d0a24d70133b1b9d2ce2defe5f;bpv=1;bpt=0
+ prefix = ""
+ }
+ out := android.PathForModuleOut(ctx, "filesystem_config.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: fsConfigRule,
+ Input: f.fileystemStagingDirTimestamp(ctx), // assemble the staging directory
+ Output: out,
+ Args: map[string]string{
+ "rootDir": rootDirString,
+ "prefix": prefix,
+ },
+ })
+ return out
+}
+
+func (f *filesystem) setVbmetaPartitionProvider(ctx android.ModuleContext) {
+ var extractedPublicKey android.ModuleOutPath
+ if f.properties.Avb_private_key != nil {
+ key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key))
+ extractedPublicKey = android.PathForModuleOut(ctx, f.partitionName()+".avbpubkey")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractPublicKeyRule,
+ Input: key,
+ Output: extractedPublicKey,
+ })
+ }
+
+ var ril int
+ if f.properties.Rollback_index_location != nil {
+ ril = proptools.Int(f.properties.Rollback_index_location)
+ }
+
+ android.SetProvider(ctx, vbmetaPartitionProvider, vbmetaPartitionInfo{
+ Name: f.partitionName(),
+ RollbackIndexLocation: ril,
+ PublicKey: extractedPublicKey,
+ Output: f.output,
+ })
+}
+
+func (f *filesystem) getMapFile(ctx android.ModuleContext) android.WritablePath {
+ // create the filepath by replacing the extension of the corresponding img file
+ return android.PathForModuleOut(ctx, f.installFileName()).ReplaceExtension(ctx, "map")
}
func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) {
@@ -457,7 +860,7 @@
}
func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.Path) {
- partitionBaseDir := android.PathForModuleOut(ctx, "root", proptools.String(f.properties.Base_dir)).String() + "/"
+ partitionBaseDir := android.PathForModuleOut(ctx, f.rootDirString(), proptools.String(f.properties.Base_dir)).String() + "/"
relPath, inTargetPartition := strings.CutPrefix(installedFile.String(), partitionBaseDir)
if inTargetPartition {
@@ -477,12 +880,13 @@
ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, p.PartitionType())
}
- ctx.VisitDirectDepsWithTag(android.DefaultsDepTag, func(m android.Module) {
- if fdm, ok := m.(*filesystemDefaults); ok {
- if p.PartitionType() != fdm.PartitionType() {
+ ctx.VisitDirectDepsProxyWithTag(android.DefaultsDepTag, func(m android.ModuleProxy) {
+ if _, ok := android.OtherModuleProvider(ctx, m, FilesystemDefaultsInfoProvider); ok {
+ partitionInfo := android.OtherModuleProviderOrDefault(ctx, m, android.PartitionTypeInfoProvider)
+ if p.PartitionType() != partitionInfo.PartitionType {
ctx.PropertyErrorf("partition_type",
"%s doesn't match with the partition type %s of the filesystem default module %s",
- p.PartitionType(), fdm.PartitionType(), m.Name())
+ p.PartitionType(), partitionInfo.PartitionType, m.Name())
}
}
})
@@ -490,11 +894,36 @@
// 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) {
+func (f *filesystem) buildNonDepsFiles(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ rootDir android.OutputPath,
+ rebasedDir android.OutputPath,
+ fullInstallPaths *[]FullInstallPathInfo,
+) {
+ rebasedPrefix, err := filepath.Rel(rootDir.String(), rebasedDir.String())
+ if err != nil || strings.HasPrefix(rebasedPrefix, "../") {
+ panic("rebasedDir could not be made relative to rootDir")
+ }
+ if !strings.HasSuffix(rebasedPrefix, "/") {
+ rebasedPrefix += "/"
+ }
+ if rebasedPrefix == "./" {
+ rebasedPrefix = ""
+ }
+
// create dirs and symlinks
for _, dir := range f.properties.Dirs.GetOrDefault(ctx, nil) {
// OutputPath.Join verifies dir
builder.Command().Text("mkdir -p").Text(rootDir.Join(ctx, dir).String())
+ // Only add the fullInstallPath logic for files in the rebased dir. The root dir
+ // is harder to install to.
+ if strings.HasPrefix(dir, rebasedPrefix) {
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(dir, rebasedPrefix)),
+ IsDir: true,
+ })
+ }
}
for _, symlink := range f.properties.Symlinks {
@@ -517,6 +946,31 @@
builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String()))
builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String())
f.appendToEntry(ctx, dst)
+ // Add the fullInstallPath logic for files in the rebased dir, and for non-rebased files in "system" partition
+ // the fullInstallPath is changed to "root" which aligns to the behavior in Make.
+ if f.PartitionType() == "system" {
+ installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix))
+ if !strings.HasPrefix(name, rebasedPrefix) {
+ installPath = android.PathForModuleInPartitionInstall(ctx, "root", name)
+ }
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: installPath,
+ SymlinkTarget: target,
+ })
+ } else {
+ if strings.HasPrefix(name, rebasedPrefix) {
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)),
+ SymlinkTarget: target,
+ })
+ }
+ }
+ }
+
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2835;drc=b186569ef00ff2f2a1fab28aedc75ebc32bcd67b
+ if f.partitionName() == "recovery" {
+ builder.Command().Text("mkdir -p").Text(rootDir.Join(ctx, "root/linkerconfig").String())
+ builder.Command().Text("touch").Text(rootDir.Join(ctx, "root/linkerconfig/ld.config.txt").String())
}
}
@@ -536,46 +990,35 @@
dirsToSpecs[rootDir] = rootDirSpecs
dirsToSpecs[rebasedDir] = rebasedDirSpecs
- return f.CopySpecsToDirs(ctx, builder, dirsToSpecs)
+ // Preserve timestamps for adb sync, so that this staging dir file matches the timestamp in the
+ // out/target/product staging directory.
+ return f.CopySpecsToDirs(ctx, builder, dirsToSpecs, true)
}
-func (f *filesystem) copyFilesToProductOut(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
- if f.Name() != ctx.Config().SoongDefinedSystemImage() {
- return
- }
- installPath := android.PathForModuleInPartitionInstall(ctx, f.partitionName())
- builder.Command().Textf("cp -prf %s/* %s", rebasedDir, installPath)
+func (f *filesystem) rootDirString() string {
+ return f.partitionName()
}
-func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.Path {
- rootDir := android.PathForModuleOut(ctx, "root").OutputPath
- 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.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
+type buildImageParams struct {
+ // inputs
+ rootDir android.OutputPath
+ propFile android.Path
+ toolDeps android.Paths
+ // outputs
+ output android.WritablePath
+}
- f.buildNonDepsFiles(ctx, builder, rootDir)
- f.addMakeBuiltFiles(ctx, builder, rootDir)
- f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
- f.buildEventLogtagsFile(ctx, builder, rebasedDir)
- f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
- f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir)
- f.copyFilesToProductOut(ctx, builder, rebasedDir)
-
+func (f *filesystem) buildImageUsingBuildImage(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ params buildImageParams) {
// run host_init_verifier
// Ideally we should have a concept of pluggable linters that verify the generated image.
// While such concept is not implement this will do.
// TODO(b/263574231): substitute with pluggable linter.
builder.Command().
BuiltTool("host_init_verifier").
- FlagWithArg("--out_system=", rootDir.String()+"/system")
-
- propFile, toolDeps := f.buildPropFile(ctx)
+ FlagWithArg("--out_system=", params.rootDir.String()+"/system")
// Most of the time, if build_image were to call a host tool, it accepts the path to the
// host tool in a field in the prop file. However, it doesn't have that option for fec, which
@@ -583,21 +1026,32 @@
fec := ctx.Config().HostToolPath(ctx, "fec")
pathToolDirs := []string{filepath.Dir(fec.String())}
- output := android.PathForModuleOut(ctx, f.installFileName())
builder.Command().
Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
BuiltTool("build_image").
- Text(rootDir.String()). // input directory
- Input(propFile).
- Implicits(toolDeps).
+ Text(params.rootDir.String()). // input directory
+ Input(params.propFile).
+ Implicits(params.toolDeps).
Implicit(fec).
- Output(output).
- Text(rootDir.String()) // directory where to find fs_config_files|dirs
+ Implicit(f.fileystemStagingDirTimestamp(ctx)). // assemble the staging directory
+ Output(params.output).
+ Text(params.rootDir.String()) // directory where to find fs_config_files|dirs
+
+ if f.properties.Partition_size != nil {
+ assertMaxImageSize(builder, params.output, *f.properties.Partition_size, false)
+ }
// rootDir is not deleted. Might be useful for quick inspection.
- builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+ builder.Build("build_"+params.output.String(), fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+}
- return output
+func (f *filesystem) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path {
+ propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop")
+ builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp).
+ Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp).
+ Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output
+ builder.Command().Text("touch").Output(f.getMapFile(ctx))
+ return propFilePinnedTimestamp
}
func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path {
@@ -610,40 +1064,18 @@
return fcBin
}
-// Calculates avb_salt from entry list (sorted) for deterministic output.
-func (f *filesystem) salt() string {
- return sha1sum(f.entries)
-}
-
func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, android.Paths) {
var deps android.Paths
- var propFileString strings.Builder
+ var lines []string
addStr := func(name string, value string) {
- propFileString.WriteString(name)
- propFileString.WriteRune('=')
- propFileString.WriteString(value)
- propFileString.WriteRune('\n')
+ lines = append(lines, fmt.Sprintf("%s=%s", name, value))
}
addPath := func(name string, path android.Path) {
addStr(name, path.String())
deps = append(deps, path)
}
- // Type string that build_image.py accepts.
- fsTypeStr := func(t fsType) string {
- switch t {
- // TODO(372522486): add more types like f2fs, erofs, etc.
- case ext4Type:
- return "ext4"
- case erofsType:
- return "erofs"
- case f2fsType:
- return "f2fs"
- }
- panic(fmt.Errorf("unsupported fs type %v", t))
- }
-
- addStr("fs_type", fsTypeStr(f.fsType(ctx)))
+ addStr("fs_type", f.fsType(ctx).String())
addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/"))
addStr("use_dynamic_partition_size", "true")
addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs"))
@@ -662,51 +1094,35 @@
addPath("avb_key_path", key)
}
addStr("partition_name", f.partitionName())
- avb_add_hashtree_footer_args := ""
- if !proptools.BoolDefault(f.properties.Use_fec, true) {
- 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
- }
- if f.properties.Rollback_index != nil {
- rollbackIndex := proptools.Int(f.properties.Rollback_index)
- if rollbackIndex < 0 {
- ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative")
- }
- avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex)
- }
- avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable())
- avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx))
- avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), ctx.Config().PlatformSecurityPatch())
- addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args)
- addStr("avb_salt", f.salt())
+ addStr("avb_add_hashtree_footer_args", f.getAvbAddHashtreeFooterArgs(ctx))
}
if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil {
ctx.ModuleErrorf("file_contexts and precompiled_file_contexts cannot both be set")
} else if f.properties.File_contexts != nil {
- addPath("selinux_fc", f.buildFileContexts(ctx))
+ f.selinuxFc = f.buildFileContexts(ctx)
} else if f.properties.Precompiled_file_contexts != nil {
- src := android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts)
- if src != nil {
- addPath("selinux_fc", src)
- }
+ f.selinuxFc = android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts)
+ }
+ if f.selinuxFc != nil {
+ addPath("selinux_fc", f.selinuxFc)
}
if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" {
addStr("timestamp", timestamp)
+ } else if ctx.Config().Getenv("USE_FIXED_TIMESTAMP_IMG_FILES") == "true" {
+ addStr("use_fixed_timestamp", "true")
}
+
if uuid := proptools.String(f.properties.Uuid); uuid != "" {
addStr("uuid", uuid)
addStr("hash_seed", uuid)
}
- // TODO(b/381120092): This should only be added if none of the size-related properties are set,
- // but currently soong built partitions don't have size properties. Make code:
- // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2262;drc=39cd33701c9278db0e7e481a090605f428d5b12d
- // Make uses system_disable_sparse but disable_sparse has the same effect, and we shouldn't need
- // to qualify it because each partition gets its own property file built.
- addStr("disable_sparse", "true")
+ // Disable sparse only when partition size is not defined. disable_sparse has the same
+ // effect as <partition name>_disable_sparse.
+ if f.properties.Partition_size == nil {
+ addStr("disable_sparse", "true")
+ }
fst := f.fsType(ctx)
switch fst {
@@ -727,20 +1143,135 @@
addStr("f2fs_sparse_flag", "-S")
}
}
- f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst))
+ f.checkFsTypePropertyError(ctx, fst, fst.String())
+
+ if f.properties.Partition_size != nil {
+ addStr("partition_size", strconv.FormatInt(*f.properties.Partition_size, 10))
+ }
+
+ if proptools.BoolDefault(f.properties.Support_casefolding, false) {
+ addStr("needs_casefold", "1")
+ }
+
+ if proptools.BoolDefault(f.properties.Support_project_quota, false) {
+ addStr("needs_projid", "1")
+ }
+
+ if proptools.BoolDefault(f.properties.Enable_compression, false) {
+ addStr("needs_compress", "1")
+ }
+
+ sort.Strings(lines)
propFilePreProcessing := android.PathForModuleOut(ctx, "prop_pre_processing")
- android.WriteFileRuleVerbatim(ctx, propFilePreProcessing, propFileString.String())
+ android.WriteFileRule(ctx, propFilePreProcessing, strings.Join(lines, "\n"))
propFile := android.PathForModuleOut(ctx, "prop")
ctx.Build(pctx, android.BuildParams{
- Rule: textFileProcessorRule,
- Input: propFilePreProcessing,
- Output: propFile,
- Implicit: ctx.Config().BuildFingerprintFile(ctx),
+ Rule: textFileProcessorRule,
+ Input: propFilePreProcessing,
+ Output: propFile,
})
return propFile, deps
}
+func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path {
+ var lines []string
+ addStr := func(name string, value string) {
+ lines = append(lines, fmt.Sprintf("%s=%s", name, value))
+ }
+
+ addStr("use_dynamic_partition_size", "true")
+ addStr("ext_mkuserimg", "mkuserimg_mke2fs")
+
+ addStr("building_"+f.partitionName()+"_image", "true")
+ addStr(f.partitionName()+"_fs_type", f.fsType(ctx).String())
+
+ if proptools.Bool(f.properties.Use_avb) {
+ addStr("avb_"+f.partitionName()+"_hashtree_enable", "true")
+ addStr("avb_"+f.partitionName()+"_add_hashtree_footer_args", strings.TrimSpace(f.getAvbAddHashtreeFooterArgs(ctx)))
+ }
+
+ if f.selinuxFc != nil {
+ addStr(f.partitionName()+"_selinux_fc", f.selinuxFc.String())
+ }
+
+ // Disable sparse only when partition size is not defined. disable_sparse has the same
+ // effect as <partition name>_disable_sparse.
+ if f.properties.Partition_size == nil {
+ addStr(f.partitionName()+"_disable_sparse", "true")
+ } else if f.partitionName() == "userdata" {
+ // Add userdata's partition size to misc_info.txt.
+ // userdata has been special-cased to make the make packaging misc_info.txt implementation
+ addStr("userdata_size", strconv.FormatInt(*f.properties.Partition_size, 10))
+ }
+
+ fst := f.fsType(ctx)
+ switch fst {
+ case erofsType:
+ // Add erofs properties
+ addStr("erofs_default_compressor", proptools.StringDefault(f.properties.Erofs.Compressor, "lz4hc,9"))
+ if proptools.BoolDefault(f.properties.Erofs.Sparse, true) {
+ // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b
+ addStr("erofs_sparse_flag", "-s")
+ }
+ case f2fsType:
+ if proptools.BoolDefault(f.properties.F2fs.Sparse, true) {
+ // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2294;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0
+ addStr("f2fs_sparse_flag", "-S")
+ }
+ }
+
+ if proptools.BoolDefault(f.properties.Support_casefolding, false) {
+ addStr("needs_casefold", "1")
+ }
+
+ if proptools.BoolDefault(f.properties.Support_project_quota, false) {
+ addStr("needs_projid", "1")
+ }
+
+ if proptools.BoolDefault(f.properties.Enable_compression, false) {
+ addStr("needs_compress", "1")
+ }
+
+ sort.Strings(lines)
+
+ propFilePreProcessing := android.PathForModuleOut(ctx, "prop_misc_info_pre_processing")
+ android.WriteFileRule(ctx, propFilePreProcessing, strings.Join(lines, "\n"))
+ propFile := android.PathForModuleOut(ctx, "prop_file_for_misc_info")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: textFileProcessorRule,
+ Input: propFilePreProcessing,
+ Output: propFile,
+ })
+
+ return propFile
+}
+
+func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) string {
+ avb_add_hashtree_footer_args := ""
+ if !proptools.BoolDefault(f.properties.Use_fec, true) {
+ avb_add_hashtree_footer_args += " --do_not_generate_fec"
+ }
+ hashAlgorithm := proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256")
+ avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm
+ if f.properties.Rollback_index != nil {
+ rollbackIndex := proptools.Int(f.properties.Rollback_index)
+ if rollbackIndex < 0 {
+ ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative")
+ }
+ avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex)
+ }
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable())
+ // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because
+ // the build number changed, and we don't want to trigger rebuilds solely based on the build
+ // number.
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx))
+ if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" {
+ avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch))
+ }
+ return avb_add_hashtree_footer_args
+}
+
// This method checks if there is any property set for the fstype(s) other than
// the current fstype.
func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsType, fs string) {
@@ -761,7 +1292,47 @@
}
}
-func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) android.Path {
+func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, partitions android.Paths) {
+ ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+ if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok {
+ rootDirs = append(rootDirs, fsProvider.RootDir)
+ partitions = append(partitions, fsProvider.Output)
+ } else {
+ ctx.PropertyErrorf("include_files_of", "only filesystem modules can be listed in "+
+ "include_files_of but %s is not a filesystem module", m.Name())
+ }
+ })
+ return rootDirs, partitions
+}
+
+func includeFilesInstalledFiles(ctx android.ModuleContext) (ret []depset.DepSet[InstalledFilesStruct]) {
+ ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+ if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok {
+ ret = append(ret, fsProvider.InstalledFilesDepSet)
+ }
+ })
+ return
+}
+
+func (f *filesystem) hasOrIsRecovery(ctx android.ModuleContext) bool {
+ if f.partitionName() == "recovery" {
+ return true
+ }
+ ret := false
+ ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+ if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok && fsProvider.PartitionName == "recovery" {
+ ret = true
+ }
+ })
+ return ret
+}
+
+func (f *filesystem) buildCpioImage(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ rootDir android.OutputPath,
+ compressed bool,
+) (android.Path, android.Paths) {
if proptools.Bool(f.properties.Use_avb) {
ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+
"Consider adding this to bootimg module and signing the entire boot image.")
@@ -771,32 +1342,19 @@
ctx.PropertyErrorf("file_contexts", "file_contexts is not supported for compressed cpio image.")
}
- 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
- 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.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
-
- f.buildNonDepsFiles(ctx, builder, rootDir)
- f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
- f.buildEventLogtagsFile(ctx, builder, rebasedDir)
- f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
- f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir)
- f.copyFilesToProductOut(ctx, builder, rebasedDir)
+ rootDirs, partitions := includeFilesRootDir(ctx)
output := android.PathForModuleOut(ctx, f.installFileName())
cmd := builder.Command().
BuiltTool("mkbootfs").
+ Implicit(f.fileystemStagingDirTimestamp(ctx)).
Text(rootDir.String()) // input directory
+
+ for i := range len(rootDirs) {
+ cmd.Text(rootDirs[i].String())
+ }
+ cmd.Implicits(partitions)
+
if nodeList := f.properties.Dev_nodes_description_file; nodeList != nil {
cmd.FlagWithInput("-n ", android.PathForModuleSrc(ctx, proptools.String(nodeList)))
}
@@ -814,7 +1372,7 @@
// rootDir is not deleted. Might be useful for quick inspection.
builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
- return output
+ return output, rootDirs
}
var validPartitions = []string{
@@ -834,68 +1392,49 @@
"recovery",
}
-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) buildEventLogtagsFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
+func (f *filesystem) buildEventLogtagsFile(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ rebasedDir android.OutputPath,
+ fullInstallPaths *[]FullInstallPathInfo,
+) {
if !proptools.Bool(f.properties.Build_logtags) {
return
}
- logtagsFilePaths := make(map[string]bool)
- ctx.WalkDeps(func(child, parent android.Module) bool {
- if logtagsInfo, ok := android.OtherModuleProvider(ctx, child, android.LogtagsProviderKey); ok {
- for _, path := range logtagsInfo.Logtags {
- logtagsFilePaths[path.String()] = true
- }
- }
- return true
- })
-
- if len(logtagsFilePaths) == 0 {
- return
- }
-
etcPath := rebasedDir.Join(ctx, "etc")
eventLogtagsPath := etcPath.Join(ctx, "event-log-tags")
builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String())
- cmd := builder.Command().BuiltTool("merge-event-log-tags").
- FlagWithArg("-o ", eventLogtagsPath.String()).
- FlagWithInput("-m ", android.MergedLogtagsPath(ctx))
+ builder.Command().Text("cp").Input(android.MergedLogtagsPath(ctx)).Text(eventLogtagsPath.String())
- for _, path := range android.SortedKeys(logtagsFilePaths) {
- cmd.Text(path)
- }
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "event-log-tags"),
+ SourcePath: android.MergedLogtagsPath(ctx),
+ })
f.appendToEntry(ctx, eventLogtagsPath)
}
-func (f *filesystem) BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
+func (f *filesystem) BuildLinkerConfigFile(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ rebasedDir android.OutputPath,
+ fullInstallPaths *[]FullInstallPathInfo,
+) {
if !proptools.Bool(f.properties.Linker_config.Gen_linker_config) {
return
}
provideModules, _ := f.getLibsForLinkerConfig(ctx)
+ intermediateOutput := android.PathForModuleOut(ctx, "linker.config.pb")
+ linkerconfig.BuildLinkerConfig(ctx, android.PathsForModuleSrc(ctx, f.properties.Linker_config.Linker_config_srcs), provideModules, nil, intermediateOutput)
output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
- linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config.Linker_config_srcs), provideModules, nil, output)
+ builder.Command().Text("cp").Input(intermediateOutput).Output(output)
+
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "linker.config.pb"),
+ SourcePath: intermediateOutput,
+ })
f.appendToEntry(ctx, output)
}
@@ -959,8 +1498,33 @@
// Note that "apex" module installs its contents to "apex"(fake partition) as well
// for symbol lookup by imitating "activated" paths.
func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map[string]android.PackagingSpec {
- specs := f.PackagingBase.GatherPackagingSpecsWithFilterAndModifier(ctx, f.filesystemBuilder.FilterPackagingSpec, f.filesystemBuilder.ModifyPackagingSpec)
- return specs
+ return f.PackagingBase.GatherPackagingSpecsWithFilterAndModifier(ctx, f.filesystemBuilder.FilterPackagingSpec, f.filesystemBuilder.ModifyPackagingSpec)
+}
+
+func (f *filesystem) gatherOwners(specs map[string]android.PackagingSpec) []InstalledModuleInfo {
+ var owners []InstalledModuleInfo
+ for _, p := range android.SortedKeys(specs) {
+ spec := specs[p]
+ owners = append(owners, InstalledModuleInfo{
+ Name: spec.Owner(),
+ Variation: spec.Variation(),
+ })
+ }
+ return owners
+}
+
+// Dexpreopt files are installed to system_other. Collect the packaingSpecs for the dexpreopt files
+// from this partition to export to the system_other partition later.
+func (f *filesystem) systemOtherFiles(ctx android.ModuleContext) map[string]android.PackagingSpec {
+ filter := func(spec android.PackagingSpec) bool {
+ // For some reason system_other packaging specs don't set the partition field.
+ return strings.HasPrefix(spec.RelPathInPackage(), "system_other/")
+ }
+ modifier := func(spec *android.PackagingSpec) {
+ spec.SetRelPathInPackage(strings.TrimPrefix(spec.RelPathInPackage(), "system_other/"))
+ spec.SetPartition("system_other")
+ }
+ return f.PackagingBase.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, modifier)
}
func sha1sum(values []string) string {
@@ -1005,6 +1569,10 @@
func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
validatePartitionType(ctx, f)
+ android.SetProvider(ctx, FilesystemDefaultsInfoProvider, FilesystemDefaultsInfo{})
+ android.SetProvider(ctx, android.PartitionTypeInfoProvider, android.PartitionTypeInfo{
+ PartitionType: f.PartitionType(),
+ })
}
// getLibsForLinkerConfig returns
@@ -1014,13 +1582,16 @@
// `linkerconfig.BuildLinkerConfig` will convert these two to a linker.config.pb for the filesystem
// (1) will be added to --provideLibs if they are C libraries with a stable interface (has stubs)
// (2) will be added to --requireLibs if they are C libraries with a stable interface (has stubs)
-func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]android.Module, []android.Module) {
+func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]android.ModuleProxy, []android.ModuleProxy) {
// we need "Module"s for packaging items
- modulesInPackageByModule := make(map[android.Module]bool)
+ modulesInPackageByModule := make(map[android.ModuleProxy]bool)
modulesInPackageByName := make(map[string]bool)
deps := f.gatherFilteredPackagingSpecs(ctx)
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled {
+ return false
+ }
for _, ps := range android.OtherModuleProviderOrDefault(
ctx, child, android.InstallFilesProvider).PackagingSpecs {
if _, ok := deps[ps.RelPathInPackage()]; ok && ps.Partition() == f.PartitionType() {
@@ -1032,13 +1603,16 @@
return true
})
- provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
+ provideModules := make([]android.ModuleProxy, 0, len(modulesInPackageByModule))
for mod := range modulesInPackageByModule {
provideModules = append(provideModules, mod)
}
- var requireModules []android.Module
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ var requireModules []android.ModuleProxy
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled {
+ return false
+ }
_, parentInPackage := modulesInPackageByModule[parent]
_, childInPackageName := modulesInPackageByName[child.Name()]
@@ -1085,6 +1659,12 @@
}
thisPartition := f.PartitionType()
if thisPartition != "vendor" && thisPartition != "product" {
+ if f.properties.Android_filesystem_deps.System != nil {
+ ctx.PropertyErrorf("android_filesystem_deps.system", "only vendor or product partitions can use android_filesystem_deps")
+ }
+ if f.properties.Android_filesystem_deps.System_ext != nil {
+ ctx.PropertyErrorf("android_filesystem_deps.system_ext", "only vendor or product partitions can use android_filesystem_deps")
+ }
return
}
ctx.WalkDeps(func(child, parent android.Module) bool {
@@ -1101,3 +1681,17 @@
return true
})
}
+
+func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) []android.ModuleMakeVarsValue {
+ if f.Name() == ctx.Config().SoongDefinedSystemImage() {
+ return []android.ModuleMakeVarsValue{{"SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String()}}
+ }
+ return nil
+}
+
+func setCommonFilesystemInfo(ctx android.ModuleContext, m Filesystem) {
+ android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{
+ Output: m.OutputPath(),
+ SignedOutputPath: m.SignedOutputPath(),
+ })
+}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 0ed3870..e57e45c 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -16,7 +16,6 @@
import (
"os"
- "strings"
"testing"
"android/soong/android"
@@ -119,9 +118,9 @@
`)
// produces "myfilesystem.img"
- result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img")
+ result.ModuleForTests(t, "myfilesystem", "android_common").Output("myfilesystem.img")
- fs := result.ModuleForTests("myfilesystem", "android_common").Module().(*filesystem)
+ fs := result.ModuleForTests(t, "myfilesystem", "android_common").Module().(*filesystem)
expected := []string{
"app/myapp/myapp.apk",
"bin/foo",
@@ -137,22 +136,6 @@
}
}
-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 := "out/target/product/test_device/obj/PACKAGING/system_intermediates/staging_dir.stamp"
- fileListFile := "out/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 {
@@ -180,12 +163,10 @@
}
`)
- module := result.ModuleForTests("myfilesystem", "android_common")
- output := module.Output("out/soong/.intermediates/myfilesystem/android_common/root/system/etc/linker.config.pb")
+ module := result.ModuleForTests(t, "myfilesystem", "android_common")
+ output := module.Output("out/soong/.intermediates/myfilesystem/android_common/linker.config.pb")
- fullCommand := output.RuleParams.Command
- startIndex := strings.Index(fullCommand, "conv_linker_config")
- linkerConfigCommand := fullCommand[startIndex:]
+ linkerConfigCommand := output.RuleParams.Command
android.AssertStringDoesContain(t, "linker.config.pb should have libfoo",
linkerConfigCommand, "libfoo.so")
@@ -243,7 +224,7 @@
}
`)
- module := result.ModuleForTests("myfilesystem", "android_common").Module().(*systemImage)
+ module := result.ModuleForTests(t, "myfilesystem", "android_common").Module().(*systemImage)
android.AssertDeepEquals(t, "entries should have foo and not bar", []string{"components/foo", "etc/linker.config.pb"}, module.entries)
}
@@ -255,7 +236,7 @@
partition_name: "input_partition_name",
salt: "2222",
}`)
- cmd := result.ModuleForTests("input_hashdesc", "android_arm64_armv8-a").Rule("avbGenVbmetaImage").RuleParams.Command
+ cmd := result.ModuleForTests(t, "input_hashdesc", "android_arm64_armv8-a").Rule("avbGenVbmetaImage").RuleParams.Command
android.AssertStringDoesContain(t, "Can't find correct --partition_name argument",
cmd, "--partition_name input_partition_name")
android.AssertStringDoesContain(t, "Can't find --do_not_append_vbmeta_image",
@@ -295,7 +276,7 @@
include_descriptors_from_images: ["input_hashdesc"],
}
`)
- cmd := result.ModuleForTests("myfooter", "android_arm64_armv8-a").Rule("avbAddHashFooter").RuleParams.Command
+ cmd := result.ModuleForTests(t, "myfooter", "android_arm64_armv8-a").Rule("avbAddHashFooter").RuleParams.Command
android.AssertStringDoesContain(t, "Can't find correct --partition_name argument",
cmd, "--partition_name mypartition")
android.AssertStringDoesContain(t, "Can't find correct --key argument",
@@ -350,8 +331,8 @@
}
`)
- filesystem := result.ModuleForTests("myfilesystem", "android_common_cov")
- inputs := filesystem.Output("myfilesystem.img").Implicits
+ filesystem := result.ModuleForTests(t, "myfilesystem", "android_common_cov")
+ inputs := filesystem.Output("staging_dir.timestamp").Implicits
android.AssertStringListContains(t, "filesystem should have libfoo(cov)",
inputs.Strings(),
"out/soong/.intermediates/libfoo/android_arm64_armv8-a_shared_cov/libfoo.so")
@@ -359,8 +340,8 @@
inputs.Strings(),
"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared_cov/libbar.so")
- filesystemOutput := filesystem.Output("myfilesystem.img").Output
- prebuiltInput := result.ModuleForTests("prebuilt", "android_arm64_armv8-a").Rule("Cp").Input
+ filesystemOutput := filesystem.OutputFiles(result.TestContext, t, "")[0]
+ prebuiltInput := result.ModuleForTests(t, "prebuilt", "android_arm64_armv8-a").Rule("Cp").Input
if filesystemOutput != prebuiltInput {
t.Error("prebuilt should use cov variant of filesystem")
}
@@ -422,7 +403,7 @@
}
`)
- fs := result.ModuleForTests("system", "android_common").Module().(*systemImage)
+ fs := result.ModuleForTests(t, "system", "android_common").Module().(*systemImage)
expected := []string{
"bin/foo",
"lib/libbar.so",
@@ -502,7 +483,7 @@
}
`)
- fs := result.ModuleForTests("fs", "android_common").Module().(*filesystem)
+ fs := result.ModuleForTests(t, "fs", "android_common").Module().(*filesystem)
expected := []string{
"bin/foo",
"lib64/libbar.so",
@@ -565,7 +546,7 @@
},
}
for _, c := range testcases {
- fs := result.ModuleForTests(c.fsName, "android_common").Module().(*filesystem)
+ fs := result.ModuleForTests(t, c.fsName, "android_common").Module().(*filesystem)
for _, e := range c.expected {
android.AssertStringListContains(t, "missing entry", fs.entries, e)
}
@@ -592,7 +573,7 @@
}
`)
- partition := result.ModuleForTests("erofs_partition", "android_common")
+ partition := result.ModuleForTests(t, "erofs_partition", "android_common")
buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop_pre_processing"))
android.AssertStringDoesContain(t, "erofs fs type", buildImageConfig, "fs_type=erofs")
android.AssertStringDoesContain(t, "erofs fs type compress algorithm", buildImageConfig, "erofs_default_compressor=lz4hc,9")
@@ -608,7 +589,7 @@
}
`)
- partition := result.ModuleForTests("f2fs_partition", "android_common")
+ partition := result.ModuleForTests(t, "f2fs_partition", "android_common")
buildImageConfig := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("prop_pre_processing"))
android.AssertStringDoesContain(t, "f2fs fs type", buildImageConfig, "fs_type=f2fs")
android.AssertStringDoesContain(t, "f2fs fs type sparse", buildImageConfig, "f2fs_sparse_flag=-S")
@@ -650,7 +631,7 @@
}
`)
- partition := result.ModuleForTests("myfilesystem", "android_common")
+ partition := result.ModuleForTests(t, "myfilesystem", "android_common")
fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
android.AssertDeepEquals(t, "filesystem with dependencies on different partition", "bin/binfoo\n", fileList)
}
@@ -669,7 +650,7 @@
}
`)
- partition := result.ModuleForTests("myfilesystem", "android_common")
+ partition := result.ModuleForTests(t, "myfilesystem", "android_common")
fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
android.AssertDeepEquals(t, "cc_library listed in deps",
"lib64/bootstrap/libc.so\nlib64/bootstrap/libdl.so\nlib64/bootstrap/libm.so\nlib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo.so\nlib64/libm.so\n",
@@ -706,7 +687,7 @@
}
`)
- partition := result.ModuleForTests("myfilesystem", "android_common")
+ partition := result.ModuleForTests(t, "myfilesystem", "android_common")
fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
android.AssertDeepEquals(t, "Shared library dep of overridden binary should not be installed",
"bin/binfoo1\nlib64/bootstrap/libc.so\nlib64/bootstrap/libdl.so\nlib64/bootstrap/libm.so\nlib64/libc++.so\nlib64/libc.so\nlib64/libdl.so\nlib64/libfoo2.so\nlib64/libm.so\n",
@@ -735,33 +716,67 @@
}
`)
- linkerConfigCmd := result.ModuleForTests("myfilesystem", "android_common").Rule("build_filesystem_image").RuleParams.Command
+ linkerConfigCmd := result.ModuleForTests(t, "myfilesystem", "android_common").Output("out/soong/.intermediates/myfilesystem/android_common/linker.config.pb").RuleParams.Command
android.AssertStringDoesContain(t, "Could not find linker.config.json file in cmd", linkerConfigCmd, "conv_linker_config proto --force -s linker.config.json")
android.AssertStringDoesContain(t, "Could not find stub in `provideLibs`", linkerConfigCmd, "--key provideLibs --value libfoo_has_stubs.so")
}
// override_android_* modules implicitly override their base module.
// If both of these are listed in `deps`, the base module should not be installed.
+// Also, required deps should be updated too.
func TestOverrideModulesInDeps(t *testing.T) {
result := fixture.RunTestWithBp(t, `
- android_filesystem {
- name: "myfilesystem",
- deps: ["myapp", "myoverrideapp"],
+ cc_library_shared {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
}
-
+ cc_library_shared {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ }
+ phony {
+ name: "myapp_phony",
+ required: ["myapp"],
+ }
+ phony {
+ name: "myoverrideapp_phony",
+ required: ["myoverrideapp"],
+ }
android_app {
name: "myapp",
platform_apis: true,
+ required: ["libfoo"],
}
override_android_app {
name: "myoverrideapp",
base: "myapp",
+ required: ["libbar"],
+ }
+ android_filesystem {
+ name: "myfilesystem",
+ deps: ["myapp"],
+ }
+ android_filesystem {
+ name: "myfilesystem_overridden",
+ deps: ["myapp", "myoverrideapp"],
+ }
+ android_filesystem {
+ name: "myfilesystem_overridden_indirect",
+ deps: ["myapp_phony", "myoverrideapp_phony"],
}
`)
- partition := result.ModuleForTests("myfilesystem", "android_common")
+ partition := result.ModuleForTests(t, "myfilesystem", "android_common")
fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
- android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\n", fileList)
+ android.AssertStringEquals(t, "filesystem without override app", "app/myapp/myapp.apk\nlib64/libfoo.so\n", fileList)
+
+ for _, overridden := range []string{"myfilesystem_overridden", "myfilesystem_overridden_indirect"} {
+ overriddenPartition := result.ModuleForTests(t, overridden, "android_common")
+ overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList"))
+ android.AssertStringEquals(t, "filesystem with "+overridden, "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList)
+ }
}
func TestRamdiskPartitionSetsDevNodes(t *testing.T) {
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
index b9a4026..89da318 100644
--- a/filesystem/fsverity_metadata.go
+++ b/filesystem/fsverity_metadata.go
@@ -21,9 +21,27 @@
"android/soong/android"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
+func init() {
+ pctx.HostBinToolVariable("fsverity_metadata_generator", "fsverity_metadata_generator")
+ pctx.HostBinToolVariable("fsverity_manifest_generator", "fsverity_manifest_generator")
+ pctx.HostBinToolVariable("fsverity", "fsverity")
+}
+
+var (
+ buildFsverityMeta = pctx.AndroidStaticRule("build_fsverity_meta", blueprint.RuleParams{
+ Command: `$fsverity_metadata_generator --fsverity-path $fsverity --signature none --hash-alg sha256 --output $out $in`,
+ CommandDeps: []string{"$fsverity_metadata_generator", "$fsverity"},
+ })
+ buildFsverityManifest = pctx.AndroidStaticRule("build_fsverity_manifest", blueprint.RuleParams{
+ Command: `$fsverity_manifest_generator --fsverity-path $fsverity --output $out @$in`,
+ CommandDeps: []string{"$fsverity_manifest_generator", "$fsverity"},
+ })
+)
+
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.
@@ -35,16 +53,67 @@
Libs proptools.Configurable[[]string] `android:"path"`
}
-func (f *filesystem) writeManifestGeneratorListFile(ctx android.ModuleContext, outputPath android.WritablePath, 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())
+// Mapping of a given fsverity file, which may be a real file or a symlink, and the on-device
+// path it should have relative to the filesystem root.
+type fsveritySrcDest struct {
+ src android.Path
+ dest string
}
-func (f *filesystem) buildFsverityMetadataFiles(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir android.OutputPath, rebasedDir android.OutputPath) {
+func (f *filesystem) writeManifestGeneratorListFile(
+ ctx android.ModuleContext,
+ outputPath android.WritablePath,
+ matchedFiles []fsveritySrcDest,
+ rootDir android.OutputPath,
+ rebasedDir android.OutputPath,
+) []android.Path {
+ prefix, err := filepath.Rel(rootDir.String(), rebasedDir.String())
+ if err != nil {
+ panic("rebasedDir should be relative to rootDir")
+ }
+ if prefix == "." {
+ prefix = ""
+ }
+ if f.PartitionType() == "system_ext" {
+ // Use the equivalent of $PRODUCT_OUT as the base dir.
+ // This ensures that the paths in build_manifest.pb contain on-device paths
+ // e.g. system_ext/framework/javalib.jar
+ // and not framework/javalib.jar.
+ //
+ // Although base-dir is outside the rootdir provided for packaging, this action
+ // is hermetic since it uses `manifestGeneratorListPath` to filter the files to be written to build_manifest.pb
+ prefix = "system_ext"
+ }
+
+ var deps []android.Path
+ var buf strings.Builder
+ for _, spec := range matchedFiles {
+ src := spec.src.String()
+ dst := filepath.Join(prefix, spec.dest)
+ if strings.Contains(src, ",") {
+ ctx.ModuleErrorf("Path cannot contain a comma: %s", src)
+ }
+ if strings.Contains(dst, ",") {
+ ctx.ModuleErrorf("Path cannot contain a comma: %s", dst)
+ }
+ buf.WriteString(src)
+ buf.WriteString(",")
+ buf.WriteString(dst)
+ buf.WriteString("\n")
+ deps = append(deps, spec.src)
+ }
+ android.WriteFileRuleVerbatim(ctx, outputPath, buf.String())
+ return deps
+}
+
+func (f *filesystem) buildFsverityMetadataFiles(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ specs map[string]android.PackagingSpec,
+ rootDir android.OutputPath,
+ rebasedDir android.OutputPath,
+ fullInstallPaths *[]FullInstallPathInfo,
+) {
match := func(path string) bool {
for _, pattern := range f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) {
if matched, err := filepath.Match(pattern, path); matched {
@@ -57,53 +126,98 @@
return false
}
- var matchedSpecs []android.PackagingSpec
+ var matchedFiles []android.PackagingSpec
+ var matchedSymlinks []android.PackagingSpec
for _, relPath := range android.SortedKeys(specs) {
if match(relPath) {
- matchedSpecs = append(matchedSpecs, specs[relPath])
+ spec := specs[relPath]
+ if spec.SrcPath() != nil {
+ matchedFiles = append(matchedFiles, spec)
+ } else if spec.SymlinkTarget() != "" {
+ matchedSymlinks = append(matchedSymlinks, spec)
+ } else {
+ ctx.ModuleErrorf("Expected a file or symlink for fsverity packaging spec")
+ }
}
}
- if len(matchedSpecs) == 0 {
+ if len(matchedFiles) == 0 && len(matchedSymlinks) == 0 {
return
}
- fsverityPath := ctx.Config().HostToolPath(ctx, "fsverity")
-
// STEP 1: generate .fsv_meta
- var sb strings.Builder
- sb.WriteString("set -e\n")
- for _, spec := range matchedSpecs {
+ var fsverityFileSpecs []fsveritySrcDest
+ for _, spec := range matchedFiles {
+ rel := spec.RelPathInPackage() + ".fsv_meta"
+ outPath := android.PathForModuleOut(ctx, "fsverity/meta_files", rel)
+ destPath := rebasedDir.Join(ctx, rel)
// srcPath is copied by CopySpecsToDir()
- srcPath := rebasedDir.Join(ctx, spec.RelPathInPackage())
- destPath := rebasedDir.Join(ctx, spec.RelPathInPackage()+".fsv_meta")
- builder.Command().
- BuiltTool("fsverity_metadata_generator").
- FlagWithInput("--fsverity-path ", fsverityPath).
- FlagWithArg("--signature ", "none").
- FlagWithArg("--hash-alg ", "sha256").
- FlagWithArg("--output ", destPath.String()).
- Text(srcPath.String())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: buildFsverityMeta,
+ Input: spec.SrcPath(),
+ Output: outPath,
+ })
+ builder.Command().Textf("cp").Input(outPath).Output(destPath)
f.appendToEntry(ctx, destPath)
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ SourcePath: destPath,
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), rel),
+ })
+ fsverityFileSpecs = append(fsverityFileSpecs, fsveritySrcDest{
+ src: spec.SrcPath(),
+ dest: spec.RelPathInPackage(),
+ })
+ }
+ for _, spec := range matchedSymlinks {
+ rel := spec.RelPathInPackage() + ".fsv_meta"
+ outPath := android.PathForModuleOut(ctx, "fsverity/meta_files", rel)
+ destPath := rebasedDir.Join(ctx, rel)
+ target := spec.SymlinkTarget() + ".fsv_meta"
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Symlink,
+ Output: outPath,
+ Args: map[string]string{
+ "fromPath": target,
+ },
+ })
+ builder.Command().
+ Textf("cp").
+ Flag(ctx.Config().CpPreserveSymlinksFlags()).
+ Input(outPath).
+ Output(destPath)
+ f.appendToEntry(ctx, destPath)
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ SymlinkTarget: target,
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), rel),
+ })
+ // The fsverity manifest tool needs to actually look at the symlink. But symlink
+ // packagingSpecs are not actually created on disk, at least until the staging dir is
+ // built for the partition. Create a fake one now so the tool can see it.
+ realizedSymlink := android.PathForModuleOut(ctx, "fsverity/realized_symlinks", spec.RelPathInPackage())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Symlink,
+ Output: realizedSymlink,
+ Args: map[string]string{
+ "fromPath": spec.SymlinkTarget(),
+ },
+ })
+ fsverityFileSpecs = append(fsverityFileSpecs, fsveritySrcDest{
+ src: realizedSymlink,
+ dest: spec.RelPathInPackage(),
+ })
}
// STEP 2: generate signed BuildManifest.apk
// STEP 2-1: generate build_manifest.pb
- manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list")
- f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath, matchedSpecs, rebasedDir)
- assetsPath := android.PathForModuleOut(ctx, "fsverity_manifest/assets")
- manifestPbPath := assetsPath.Join(ctx, "build_manifest.pb")
- builder.Command().Text("rm -rf " + assetsPath.String())
- builder.Command().Text("mkdir -p " + assetsPath.String())
- builder.Command().
- BuiltTool("fsverity_manifest_generator").
- FlagWithInput("--fsverity-path ", fsverityPath).
- FlagWithArg("--base-dir ", rootDir.String()).
- FlagWithArg("--output ", manifestPbPath.String()).
- FlagWithInput("@", manifestGeneratorListPath)
-
- f.appendToEntry(ctx, manifestPbPath)
- f.appendToEntry(ctx, manifestGeneratorListPath)
+ manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity/fsverity_manifest.list")
+ manifestDeps := f.writeManifestGeneratorListFile(ctx, manifestGeneratorListPath, fsverityFileSpecs, rootDir, rebasedDir)
+ manifestPbPath := android.PathForModuleOut(ctx, "fsverity/build_manifest.pb")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: buildFsverityManifest,
+ Input: manifestGeneratorListPath,
+ Implicits: manifestDeps,
+ Output: manifestPbPath,
+ })
// STEP 2-2: generate BuildManifest.apk (unsigned)
apkNameSuffix := ""
@@ -111,8 +225,8 @@
//https://source.corp.google.com/h/googleplex-android/platform/build/+/e392d2b486c2d4187b20a72b1c67cc737ecbcca5:core/Makefile;l=3410;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0
apkNameSuffix = "SystemExt"
}
- apkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk", apkNameSuffix))
- idsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk.idsig", apkNameSuffix))
+ apkPath := android.PathForModuleOut(ctx, "fsverity", fmt.Sprintf("BuildManifest%s.apk", apkNameSuffix))
+ idsigPath := android.PathForModuleOut(ctx, "fsverity", fmt.Sprintf("BuildManifest%s.apk.idsig", apkNameSuffix))
manifestTemplatePath := android.PathForSource(ctx, "system/security/fsverity/AndroidManifest.xml")
libs := android.PathsForModuleSrc(ctx, f.properties.Fsverity.Libs.GetOrDefault(ctx, nil))
@@ -121,11 +235,23 @@
minSdkVersion = ctx.Config().PlatformSdkVersion().String()
}
- unsignedApkCommand := builder.Command().
+ apkBuilder := android.NewRuleBuilder(pctx, ctx)
+
+ // aapt2 doesn't support adding individual asset files. Create a temp directory to hold asset
+ // files and pass it to aapt2.
+ tmpAssetDir := android.PathForModuleOut(ctx, "fsverity/tmp_asset_dir")
+ stagedManifestPbPath := tmpAssetDir.Join(ctx, "build_manifest.pb")
+ apkBuilder.Command().
+ Text("rm -rf").Text(tmpAssetDir.String()).
+ Text("&&").
+ Text("mkdir -p").Text(tmpAssetDir.String())
+ apkBuilder.Command().Text("cp").Input(manifestPbPath).Output(stagedManifestPbPath)
+
+ unsignedApkCommand := apkBuilder.Command().
BuiltTool("aapt2").
Text("link").
FlagWithOutput("-o ", apkPath).
- FlagWithArg("-A ", assetsPath.String())
+ FlagWithArg("-A ", tmpAssetDir.String()).Implicit(stagedManifestPbPath)
for _, lib := range libs {
unsignedApkCommand.FlagWithInput("-I ", lib)
}
@@ -136,17 +262,35 @@
FlagWithInput("--manifest ", manifestTemplatePath).
Text(" --rename-manifest-package com.android.security.fsverity_metadata." + f.partitionName())
- f.appendToEntry(ctx, apkPath)
-
// STEP 2-3: sign BuildManifest.apk
pemPath, keyPath := ctx.Config().DefaultAppCertificate(ctx)
- builder.Command().
+ apkBuilder.Command().
BuiltTool("apksigner").
Text("sign").
FlagWithArg("--in ", apkPath.String()).
FlagWithInput("--cert ", pemPath).
FlagWithInput("--key ", keyPath).
ImplicitOutput(idsigPath)
+ apkBuilder.Build(fmt.Sprintf("%s_fsverity_apk", ctx.ModuleName()), "build fsverity apk")
- f.appendToEntry(ctx, idsigPath)
+ // STEP 2-4: Install the apk into the staging directory
+ installedApkPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk", apkNameSuffix))
+ installedIdsigPath := rebasedDir.Join(ctx, "etc", "security", "fsverity", fmt.Sprintf("BuildManifest%s.apk.idsig", apkNameSuffix))
+ builder.Command().Text("mkdir -p").Text(filepath.Dir(installedApkPath.String()))
+ builder.Command().Text("cp").Input(apkPath).Text(installedApkPath.String())
+ builder.Command().Text("cp").Input(idsigPath).Text(installedIdsigPath.String())
+
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ SourcePath: apkPath,
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), fmt.Sprintf("etc/security/fsverity/BuildManifest%s.apk", apkNameSuffix)),
+ })
+
+ f.appendToEntry(ctx, installedApkPath)
+
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ SourcePath: idsigPath,
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), fmt.Sprintf("etc/security/fsverity/BuildManifest%s.apk.idsig", apkNameSuffix)),
+ })
+
+ f.appendToEntry(ctx, installedIdsigPath)
}
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
index d0888a9..1fd2e76 100644
--- a/filesystem/logical_partition.go
+++ b/filesystem/logical_partition.go
@@ -198,6 +198,8 @@
ctx.SetOutputFiles([]android.Path{output}, "")
l.output = output
+
+ setCommonFilesystemInfo(ctx, l)
}
// Add a rule that converts the filesystem for the given partition to the given rule builder. The
diff --git a/filesystem/raw_binary.go b/filesystem/raw_binary.go
index 707fba0..6ca155a 100644
--- a/filesystem/raw_binary.go
+++ b/filesystem/raw_binary.go
@@ -88,6 +88,8 @@
ctx.SetOutputFiles([]android.Path{outputFile}, "")
r.output = outputFile
+
+ setCommonFilesystemInfo(ctx, r)
}
var _ android.AndroidMkEntriesProvider = (*rawBinary)(nil)
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index 0f8f614..cf7e125 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -17,10 +17,13 @@
import (
"fmt"
"path/filepath"
+ "regexp"
+ "slices"
"strconv"
"strings"
"android/soong/android"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -49,16 +52,36 @@
Ab_update *bool
// whether dynamic partitions is enabled on devices that were launched without this support
Retrofit *bool
- // whether virtual A/B seamless update is enabled
- Virtual_ab *bool
- // whether retrofitting virtual A/B seamless update is enabled
- Virtual_ab_retrofit *bool
// whether the output is a sparse image
Sparse *bool
// information about how partitions within the super partition are grouped together
Partition_groups []PartitionGroupsInfo
+ // Name of the system_other partition filesystem module. This module will be installed to
+ // the "b" slot of the system partition in a/b partition builds.
+ System_other_partition *string
// whether dynamic partitions is used
Use_dynamic_partitions *bool
+ Virtual_ab struct {
+ // whether virtual A/B seamless update is enabled
+ Enable *bool
+ // whether retrofitting virtual A/B seamless update is enabled
+ Retrofit *bool
+ // If set, device uses virtual A/B Compression
+ Compression *bool
+ // This value controls the compression algorithm used for VABC.
+ // Valid options are defined in system/core/fs_mgr/libsnapshot/cow_writer.cpp
+ // e.g. "none", "gz", "brotli"
+ Compression_method *string
+ // Specifies maximum bytes to be compressed at once during ota. Options: 4096, 8192, 16384, 32768, 65536, 131072, 262144.
+ Compression_factor *int64
+ // Specifies COW version to be used by update_engine and libsnapshot. If this value is not
+ // specified we default to COW version 2 in update_engine for backwards compatibility
+ Cow_version *int64
+ }
+ // Whether the super image will be disted in the update package
+ Super_image_in_update_package *bool
+ // Whether a super_empty.img should be created
+ Create_super_empty *bool
}
type PartitionGroupsInfo struct {
@@ -88,6 +111,23 @@
Odm_dlkm_partition *string
}
+type SuperImageInfo struct {
+ // The built super.img file, which contains the sub-partitions
+ SuperImage android.Path
+
+ // Mapping from the sub-partition type to its re-exported FileSystemInfo providers from the
+ // sub-partitions.
+ SubImageInfo map[string]FilesystemInfo
+
+ DynamicPartitionsInfo android.Path
+
+ SuperEmptyImage android.Path
+
+ AbUpdate bool
+}
+
+var SuperImageProvider = blueprint.NewProvider[SuperImageInfo]()
+
func SuperImageFactory() android.Module {
module := &superImage{}
module.AddProperties(&module.properties, &module.partitionProps)
@@ -99,12 +139,18 @@
blueprint.BaseDependencyTag
}
-var superImageDepTag superImageDepTagType
+var subImageDepTag superImageDepTagType
+
+type systemOtherDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var systemOtherDepTag systemOtherDepTagType
func (s *superImage) DepsMutator(ctx android.BottomUpMutatorContext) {
addDependencyIfDefined := func(dep *string) {
if dep != nil {
- ctx.AddDependency(ctx.Module(), superImageDepTag, proptools.String(dep))
+ ctx.AddDependency(ctx.Module(), subImageDepTag, proptools.String(dep))
}
}
@@ -117,10 +163,13 @@
addDependencyIfDefined(s.partitionProps.Vendor_dlkm_partition)
addDependencyIfDefined(s.partitionProps.Odm_partition)
addDependencyIfDefined(s.partitionProps.Odm_dlkm_partition)
+ if s.properties.System_other_partition != nil {
+ ctx.AddDependency(ctx.Module(), systemOtherDepTag, *s.properties.System_other_partition)
+ }
}
func (s *superImage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- miscInfo, deps := s.buildMiscInfo(ctx)
+ miscInfo, deps, subImageInfos := s.buildMiscInfo(ctx, false)
builder := android.NewRuleBuilder(pctx, ctx)
output := android.PathForModuleOut(ctx, s.installFileName())
lpMake := ctx.Config().HostToolPath(ctx, "lpmake")
@@ -133,104 +182,232 @@
Implicits(deps).
Output(output)
builder.Build("build_super_image", fmt.Sprintf("Creating super image %s", s.BaseModuleName()))
+ var superEmptyImage android.WritablePath
+ if proptools.Bool(s.properties.Create_super_empty) {
+ superEmptyImageBuilder := android.NewRuleBuilder(pctx, ctx)
+ superEmptyImage = android.PathForModuleOut(ctx, "super_empty.img")
+ superEmptyMiscInfo, superEmptyDeps, _ := s.buildMiscInfo(ctx, true)
+ if superEmptyDeps != nil {
+ ctx.ModuleErrorf("TODO: Handle additional deps when building super_empty.img")
+ }
+ superEmptyImageBuilder.Command().Textf("PATH=%s:\\$PATH", lpMakeDir).
+ BuiltTool("build_super_image").
+ Text("-v").
+ Input(superEmptyMiscInfo).
+ Implicit(lpMake).
+ Output(superEmptyImage)
+ superEmptyImageBuilder.Build("build_super_empty_image", fmt.Sprintf("Creating super empty image %s", s.BaseModuleName()))
+ }
+ android.SetProvider(ctx, SuperImageProvider, SuperImageInfo{
+ SuperImage: output,
+ SubImageInfo: subImageInfos,
+ DynamicPartitionsInfo: s.generateDynamicPartitionsInfo(ctx),
+ SuperEmptyImage: superEmptyImage,
+ AbUpdate: proptools.Bool(s.properties.Ab_update),
+ })
ctx.SetOutputFiles([]android.Path{output}, "")
+ ctx.CheckbuildFile(output)
+
+ buildComplianceMetadata(ctx, subImageDepTag)
}
func (s *superImage) installFileName() string {
- return s.BaseModuleName() + ".img"
+ return "super.img"
}
-func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths) {
+func (s *superImage) buildMiscInfo(ctx android.ModuleContext, superEmpty bool) (android.Path, android.Paths, map[string]FilesystemInfo) {
var miscInfoString strings.Builder
+ partitionList := s.dumpDynamicPartitionInfo(ctx, &miscInfoString)
addStr := func(name string, value string) {
miscInfoString.WriteString(name)
miscInfoString.WriteRune('=')
miscInfoString.WriteString(value)
miscInfoString.WriteRune('\n')
}
-
- addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions)))
- addStr("dynamic_partition_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Retrofit)))
- addStr("lpmake", "lpmake")
- addStr("super_metadata_device", proptools.String(s.properties.Metadata_device))
- if len(s.properties.Block_devices) > 0 {
- addStr("super_block_devices", strings.Join(s.properties.Block_devices, " "))
- }
- addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size)))
- var groups, partitionList []string
- for _, groupInfo := range s.properties.Partition_groups {
- groups = append(groups, groupInfo.Name)
- partitionList = append(partitionList, groupInfo.PartitionList...)
- addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize)
- addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " "))
- }
- addStr("super_partition_groups", strings.Join(groups, " "))
- addStr("dynamic_partition_list", strings.Join(partitionList, " "))
-
- addStr("virtual_ab", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab)))
- addStr("virtual_ab_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab_retrofit)))
addStr("ab_update", strconv.FormatBool(proptools.Bool(s.properties.Ab_update)))
- addStr("build_non_sparse_super_partition", strconv.FormatBool(!proptools.Bool(s.properties.Sparse)))
+ if superEmpty {
+ miscInfo := android.PathForModuleOut(ctx, "misc_info_super_empty.txt")
+ android.WriteFileRule(ctx, miscInfo, miscInfoString.String())
+ return miscInfo, nil, nil
+ }
- partitionToImagePath := make(map[string]string)
- nameToPartition := make(map[string]string)
- var systemOtherPartitionNameNeeded string
- addEntryToPartitionToName := func(p string, s *string) {
- if proptools.String(s) != "" {
- nameToPartition[*s] = p
+ subImageInfo := make(map[string]FilesystemInfo)
+ var deps android.Paths
+
+ missingPartitionErrorMessage := ""
+ handleSubPartition := func(partitionType string, name *string) {
+ if proptools.String(name) == "" {
+ missingPartitionErrorMessage += fmt.Sprintf("%s image listed in partition groups, but its module was not specified. ", partitionType)
+ return
}
+ mod := ctx.GetDirectDepWithTag(*name, subImageDepTag)
+ if mod == nil {
+ ctx.ModuleErrorf("Could not get dep %q", *name)
+ return
+ }
+ info, ok := android.OtherModuleProvider(ctx, mod, FilesystemProvider)
+ if !ok {
+ ctx.ModuleErrorf("Expected dep %q to provide FilesystemInfo", *name)
+ return
+ }
+ addStr(partitionType+"_image", info.Output.String())
+ deps = append(deps, info.Output)
+ if _, ok := subImageInfo[partitionType]; ok {
+ ctx.ModuleErrorf("Already set subimageInfo for %q", partitionType)
+ }
+ subImageInfo[partitionType] = info
}
// Build partitionToImagePath, because system partition may need system_other
// partition image path
for _, p := range partitionList {
- if _, ok := nameToPartition[p]; ok {
- continue
- }
switch p {
case "system":
- addEntryToPartitionToName(p, s.partitionProps.System_partition)
- systemOtherPartitionNameNeeded = proptools.String(s.partitionProps.System_other_partition)
+ handleSubPartition("system", s.partitionProps.System_partition)
case "system_dlkm":
- addEntryToPartitionToName(p, s.partitionProps.System_dlkm_partition)
+ handleSubPartition("system_dlkm", s.partitionProps.System_dlkm_partition)
case "system_ext":
- addEntryToPartitionToName(p, s.partitionProps.System_ext_partition)
+ handleSubPartition("system_ext", s.partitionProps.System_ext_partition)
case "product":
- addEntryToPartitionToName(p, s.partitionProps.Product_partition)
+ handleSubPartition("product", s.partitionProps.Product_partition)
case "vendor":
- addEntryToPartitionToName(p, s.partitionProps.Vendor_partition)
+ handleSubPartition("vendor", s.partitionProps.Vendor_partition)
case "vendor_dlkm":
- addEntryToPartitionToName(p, s.partitionProps.Vendor_dlkm_partition)
+ handleSubPartition("vendor_dlkm", s.partitionProps.Vendor_dlkm_partition)
case "odm":
- addEntryToPartitionToName(p, s.partitionProps.Odm_partition)
+ handleSubPartition("odm", s.partitionProps.Odm_partition)
case "odm_dlkm":
- addEntryToPartitionToName(p, s.partitionProps.Odm_dlkm_partition)
+ handleSubPartition("odm_dlkm", s.partitionProps.Odm_dlkm_partition)
default:
- ctx.ModuleErrorf("current partition %s not a super image supported partition", p)
+ ctx.ModuleErrorf("partition %q is not a super image supported partition", p)
}
}
- var deps android.Paths
- ctx.VisitDirectDeps(func(m android.Module) {
- if p, ok := nameToPartition[m.Name()]; ok {
- if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
- partitionToImagePath[p] = output.DefaultOutputFiles[0].String()
- deps = append(deps, output.DefaultOutputFiles[0])
- }
- } else if systemOtherPartitionNameNeeded != "" && m.Name() == systemOtherPartitionNameNeeded {
- if output, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
- partitionToImagePath["system_other"] = output.DefaultOutputFiles[0].String()
- // TODO: add system_other to deps after it can be generated
- // deps = append(deps, output.DefaultOutputFiles[0])
- }
+ if s.properties.System_other_partition != nil {
+ if !slices.Contains(partitionList, "system") {
+ ctx.PropertyErrorf("system_other_partition", "Must have a system partition to use a system_other partition")
}
- })
+ systemOther := ctx.GetDirectDepProxyWithTag(*s.properties.System_other_partition, systemOtherDepTag)
+ systemOtherFiles := android.OutputFilesForModule(ctx, systemOther, "")
+ if len(systemOtherFiles) != 1 {
+ ctx.PropertyErrorf("system_other_partition", "Expected 1 output file from module %q", *&s.properties.System_other_partition)
+ } else {
+ handleSubPartition("system_other", s.partitionProps.System_other_partition)
+ }
+ }
- for _, p := range android.SortedKeys(partitionToImagePath) {
- addStr(p+"_image", partitionToImagePath[p])
+ // Delay the error message until execution time because on aosp-main-future-without-vendor,
+ // BUILDING_VENDOR_IMAGE is false so we don't get the vendor image, but it's still listed in
+ // BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST.
+ missingPartitionErrorMessageFile := android.PathForModuleOut(ctx, "missing_partition_error.txt")
+ if missingPartitionErrorMessage != "" {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: missingPartitionErrorMessageFile,
+ Args: map[string]string{
+ "error": missingPartitionErrorMessage,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: missingPartitionErrorMessageFile,
+ })
}
miscInfo := android.PathForModuleOut(ctx, "misc_info.txt")
- android.WriteFileRule(ctx, miscInfo, miscInfoString.String())
- return miscInfo, deps
+ android.WriteFileRule(ctx, miscInfo, miscInfoString.String(), missingPartitionErrorMessageFile)
+ return miscInfo, deps, subImageInfo
+}
+
+func (s *superImage) dumpDynamicPartitionInfo(ctx android.ModuleContext, sb *strings.Builder) []string {
+ addStr := func(name string, value string) {
+ sb.WriteString(name)
+ sb.WriteRune('=')
+ sb.WriteString(value)
+ sb.WriteRune('\n')
+ }
+
+ addStr("use_dynamic_partitions", strconv.FormatBool(proptools.Bool(s.properties.Use_dynamic_partitions)))
+ if proptools.Bool(s.properties.Retrofit) {
+ addStr("dynamic_partition_retrofit", "true")
+ }
+ addStr("lpmake", "lpmake")
+ addStr("build_super_partition", "true")
+ if proptools.Bool(s.properties.Create_super_empty) {
+ addStr("build_super_empty_partition", "true")
+ }
+ addStr("super_metadata_device", proptools.String(s.properties.Metadata_device))
+ if len(s.properties.Block_devices) > 0 {
+ addStr("super_block_devices", strings.Join(s.properties.Block_devices, " "))
+ }
+ // TODO: In make, there's more complicated logic than just this surrounding super_*_device_size
+ addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size)))
+ var groups, partitionList []string
+ for _, groupInfo := range s.properties.Partition_groups {
+ groups = append(groups, groupInfo.Name)
+ partitionList = append(partitionList, groupInfo.PartitionList...)
+ }
+ addStr("dynamic_partition_list", strings.Join(android.SortedUniqueStrings(partitionList), " "))
+ addStr("super_partition_groups", strings.Join(groups, " "))
+ initialPartitionListLen := len(partitionList)
+ partitionList = android.SortedUniqueStrings(partitionList)
+ if len(partitionList) != initialPartitionListLen {
+ ctx.ModuleErrorf("Duplicate partitions found in the partition_groups property")
+ }
+ // Add Partition group info after adding `super_partition_groups` and `dynamic_partition_list`
+ for _, groupInfo := range s.properties.Partition_groups {
+ addStr("super_"+groupInfo.Name+"_group_size", groupInfo.GroupSize)
+ addStr("super_"+groupInfo.Name+"_partition_list", strings.Join(groupInfo.PartitionList, " "))
+ }
+
+ if proptools.Bool(s.properties.Super_image_in_update_package) {
+ addStr("super_image_in_update_package", "true")
+ }
+ addStr("super_partition_size", strconv.Itoa(proptools.Int(s.properties.Size)))
+
+ if proptools.Bool(s.properties.Virtual_ab.Enable) {
+ addStr("virtual_ab", "true")
+ if proptools.Bool(s.properties.Virtual_ab.Retrofit) {
+ addStr("virtual_ab_retrofit", "true")
+ }
+ addStr("virtual_ab_compression", strconv.FormatBool(proptools.Bool(s.properties.Virtual_ab.Compression)))
+ if s.properties.Virtual_ab.Compression_method != nil {
+ matched, _ := regexp.MatchString("^[a-zA-Z0-9_-]+$", *s.properties.Virtual_ab.Compression_method)
+ if !matched {
+ ctx.PropertyErrorf("virtual_ab.compression_method", "compression_method cannot have special characters")
+ }
+ addStr("virtual_ab_compression_method", *s.properties.Virtual_ab.Compression_method)
+ }
+ if s.properties.Virtual_ab.Cow_version != nil {
+ addStr("virtual_ab_cow_version", strconv.FormatInt(*s.properties.Virtual_ab.Cow_version, 10))
+ }
+ if s.properties.Virtual_ab.Compression_factor != nil {
+ addStr("virtual_ab_compression_factor", strconv.FormatInt(*s.properties.Virtual_ab.Compression_factor, 10))
+ }
+
+ } else {
+ if s.properties.Virtual_ab.Retrofit != nil {
+ ctx.PropertyErrorf("virtual_ab.retrofit", "This property cannot be set when virtual_ab is disabled")
+ }
+ if s.properties.Virtual_ab.Compression != nil {
+ ctx.PropertyErrorf("virtual_ab.compression", "This property cannot be set when virtual_ab is disabled")
+ }
+ if s.properties.Virtual_ab.Compression_method != nil {
+ ctx.PropertyErrorf("virtual_ab.compression_method", "This property cannot be set when virtual_ab is disabled")
+ }
+ if s.properties.Virtual_ab.Compression_factor != nil {
+ ctx.PropertyErrorf("virtual_ab.compression_factor", "This property cannot be set when virtual_ab is disabled")
+ }
+ }
+
+ return partitionList
+}
+
+func (s *superImage) generateDynamicPartitionsInfo(ctx android.ModuleContext) android.Path {
+ var contents strings.Builder
+ s.dumpDynamicPartitionInfo(ctx, &contents)
+ dynamicPartitionsInfo := android.PathForModuleOut(ctx, "dynamic_partitions_info.txt")
+ android.WriteFileRuleVerbatim(ctx, dynamicPartitionsInfo, contents.String())
+ return dynamicPartitionsInfo
}
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 60a5133..cc9093f 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/cc"
"android/soong/linkerconfig"
"strings"
@@ -43,14 +44,65 @@
return s.filesystem.properties
}
-func (s *systemImage) BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
+func (s *systemImage) BuildLinkerConfigFile(
+ ctx android.ModuleContext,
+ builder *android.RuleBuilder,
+ rebasedDir android.OutputPath,
+ fullInstallPaths *[]FullInstallPathInfo,
+) {
if !proptools.Bool(s.filesystem.properties.Linker_config.Gen_linker_config) {
return
}
- provideModules, requireModules := s.getLibsForLinkerConfig(ctx)
output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
- linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, s.filesystem.properties.Linker_config.Linker_config_srcs), provideModules, requireModules, output)
+ if s.filesystem.properties.Linker_config.Linker_config_srcs != nil {
+ provideModules, requireModules := s.getLibsForLinkerConfig(ctx)
+ intermediateOutput := android.PathForModuleOut(ctx, "linker.config.pb")
+ linkerconfig.BuildLinkerConfig(ctx, android.PathsForModuleSrc(ctx, s.filesystem.properties.Linker_config.Linker_config_srcs), provideModules, requireModules, intermediateOutput)
+ builder.Command().Text("cp").Input(intermediateOutput).Output(output)
+
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb"),
+ SourcePath: intermediateOutput,
+ })
+ } else {
+ // TODO: This branch is the logic that make uses for the linker config file, which is
+ // different than linkerconfig.BuildLinkerConfig used above. Keeping both branches for now
+ // because microdroid uses the other method and is in theory happy with it. But we should
+ // consider deduping them.
+ stubLibraries := cc.StubLibrariesFile(ctx)
+ llndkMovedToApexLibraries := cc.MovedToApexLlndkLibrariesFile(ctx)
+ outputStep1 := android.PathForModuleOut(ctx, "linker.config.pb.step1")
+ builder.Command().
+ BuiltTool("conv_linker_config").
+ Text("proto --force").
+ FlagWithInput("-s ", android.PathForSource(ctx, "system/core/rootdir/etc/linker.config.json")).
+ FlagWithOutput("-o ", outputStep1)
+ builder.Temporary(outputStep1)
+ builder.Command().
+ BuiltTool("conv_linker_config").
+ Text("systemprovide").
+ FlagWithInput("--source ", outputStep1).
+ FlagWithArg("--output ", output.String()).
+ Textf(`--value "$(cat %s)"`, stubLibraries).
+ Implicit(stubLibraries).
+ FlagWithArg("--system ", rebasedDir.String())
+ builder.Command().
+ BuiltTool("conv_linker_config").
+ Text("append").
+ FlagWithArg("--source ", output.String()).
+ FlagWithOutput("--output ", output).
+ FlagWithArg("--key ", "requireLibs").
+ Textf(`--value "$(cat %s)"`, llndkMovedToApexLibraries).
+ Implicit(llndkMovedToApexLibraries)
+ // TODO: Make also supports adding an extra append command with PRODUCT_EXTRA_STUB_LIBRARIES,
+ // but that variable appears to have no usages.
+
+ *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
+ FullInstallPath: android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb"),
+ SourcePath: output,
+ })
+ }
s.appendToEntry(ctx, output)
}
diff --git a/filesystem/system_other.go b/filesystem/system_other.go
new file mode 100644
index 0000000..32a6cc7
--- /dev/null
+++ b/filesystem/system_other.go
@@ -0,0 +1,266 @@
+// 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 (
+ "android/soong/android"
+ "fmt"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ systemOtherPropFileTweaks = pctx.AndroidStaticRule("system_other_prop_file_tweaks", blueprint.RuleParams{
+ Command: `rm -rf $out && sed -e 's@^mount_point=/$$@mount_point=system_other@g' -e 's@^partition_name=system$$@partition_name=system_other@g' $in > $out`,
+ })
+)
+
+type SystemOtherImageProperties struct {
+ // The system_other image always requires a reference to the system image. The system_other
+ // partition gets built into the system partition's "b" slot in a/b partition builds. Thus, it
+ // copies most of its configuration from the system image, such as filesystem type, avb signing
+ // info, etc. Including it here does not automatically mean that it will pick up the system
+ // image's dexpropt files, it must also be listed in Preinstall_dexpreopt_files_from for that.
+ System_image *string
+
+ // This system_other partition will include all the dexpreopt files from the apps on these
+ // partitions.
+ Preinstall_dexpreopt_files_from []string
+}
+
+type systemOtherImage struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ properties SystemOtherImageProperties
+}
+
+// The system_other image is the default contents of the "b" slot of the system image.
+// It contains the dexpreopt files of all the apps on the device, for a faster first boot.
+// Afterwards, at runtime, it will be used as a regular b slot for OTA updates, and the initial
+// dexpreopt files will be deleted.
+func SystemOtherImageFactory() android.Module {
+ module := &systemOtherImage{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ return module
+}
+
+type systemImageDeptag struct {
+ blueprint.BaseDependencyTag
+}
+
+var systemImageDependencyTag = systemImageDeptag{}
+
+type dexpreoptDeptag struct {
+ blueprint.BaseDependencyTag
+}
+
+var dexpreoptDependencyTag = dexpreoptDeptag{}
+
+func (m *systemOtherImage) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if proptools.String(m.properties.System_image) == "" {
+ ctx.ModuleErrorf("system_image property must be set")
+ return
+ }
+ ctx.AddDependency(ctx.Module(), systemImageDependencyTag, *m.properties.System_image)
+ ctx.AddDependency(ctx.Module(), dexpreoptDependencyTag, m.properties.Preinstall_dexpreopt_files_from...)
+}
+
+func (m *systemOtherImage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ systemImage := ctx.GetDirectDepProxyWithTag(*m.properties.System_image, systemImageDependencyTag)
+ systemInfo, ok := android.OtherModuleProvider(ctx, systemImage, FilesystemProvider)
+ if !ok {
+ ctx.PropertyErrorf("system_image", "Expected system_image module to provide FilesystemProvider")
+ return
+ }
+
+ output := android.PathForModuleOut(ctx, "system_other.img")
+ stagingDir := android.PathForModuleOut(ctx, "staging_dir")
+ stagingDirTimestamp := android.PathForModuleOut(ctx, "staging_dir.timestamp")
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Textf("rm -rf %s && mkdir -p %s", stagingDir, stagingDir)
+
+ specs := make(map[string]android.PackagingSpec)
+ for _, otherPartition := range m.properties.Preinstall_dexpreopt_files_from {
+ dexModule := ctx.GetDirectDepProxyWithTag(otherPartition, dexpreoptDependencyTag)
+ fsInfo, ok := android.OtherModuleProvider(ctx, dexModule, FilesystemProvider)
+ if !ok {
+ ctx.PropertyErrorf("preinstall_dexpreopt_files_from", "Expected module %q to provide FilesystemProvider", otherPartition)
+ return
+ }
+ // Merge all the packaging specs into 1 map
+ for k := range fsInfo.SpecsForSystemOther {
+ if _, ok := specs[k]; ok {
+ ctx.ModuleErrorf("Packaging spec %s given by two different partitions", k)
+ continue
+ }
+ specs[k] = fsInfo.SpecsForSystemOther[k]
+ }
+ }
+
+ // TOOD: CopySpecsToDir only exists on PackagingBase, but doesn't use any fields from it. Clean this up.
+ (&android.PackagingBase{}).CopySpecsToDir(ctx, builder, specs, stagingDir)
+
+ fullInstallPaths := []string{}
+ if len(m.properties.Preinstall_dexpreopt_files_from) > 0 {
+ builder.Command().Textf("touch %s", filepath.Join(stagingDir.String(), "system-other-odex-marker"))
+ installPath := android.PathForModuleInPartitionInstall(ctx, "system_other", "system-other-odex-marker")
+ fullInstallPaths = append(fullInstallPaths, installPath.String())
+ }
+ builder.Command().Textf("touch").Output(stagingDirTimestamp)
+ builder.Build("assemble_filesystem_staging_dir", "Assemble filesystem staging dir")
+
+ // Most of the time, if build_image were to call a host tool, it accepts the path to the
+ // host tool in a field in the prop file. However, it doesn't have that option for fec, which
+ // it expects to just be on the PATH. Add fec to the PATH.
+ fec := ctx.Config().HostToolPath(ctx, "fec")
+ pathToolDirs := []string{filepath.Dir(fec.String())}
+
+ // In make, the exact same prop file is used for both system and system_other. However, I
+ // believe make goes through a different build_image code path that is based on the name of
+ // the output file. So it sees the output file is named system_other.img and makes some changes.
+ // We don't use that codepath, so make the changes manually to the prop file.
+ propFile := android.PathForModuleOut(ctx, "prop")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: systemOtherPropFileTweaks,
+ Input: systemInfo.BuildImagePropFile,
+ Output: propFile,
+ })
+
+ builder = android.NewRuleBuilder(pctx, ctx)
+ builder.Command().
+ Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
+ BuiltTool("build_image").
+ Text(stagingDir.String()). // input directory
+ Input(propFile).
+ Implicits(systemInfo.BuildImagePropFileDeps).
+ Implicit(fec).
+ Implicit(stagingDirTimestamp).
+ Output(output).
+ Text(stagingDir.String())
+
+ builder.Build("build_system_other", "build system other")
+
+ // Create a hermetic system_other.img with pinned timestamps
+ builder = android.NewRuleBuilder(pctx, ctx)
+ outputHermetic := android.PathForModuleOut(ctx, "for_target_files", "system_other.img")
+ outputHermeticPropFile := m.propFileForHermeticImg(ctx, builder, propFile)
+ builder.Command().
+ Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")).
+ BuiltTool("build_image").
+ Text(stagingDir.String()). // input directory
+ Input(outputHermeticPropFile).
+ Implicits(systemInfo.BuildImagePropFileDeps).
+ Implicit(fec).
+ Implicit(stagingDirTimestamp).
+ Output(outputHermetic).
+ Text(stagingDir.String())
+
+ builder.Build("build_system_other_hermetic", "build system other")
+
+ fsInfo := FilesystemInfo{
+ Output: output,
+ OutputHermetic: outputHermetic,
+ RootDir: stagingDir,
+ FilesystemConfig: m.generateFilesystemConfig(ctx, stagingDir, stagingDirTimestamp),
+ PropFileForMiscInfo: m.buildPropFileForMiscInfo(ctx),
+ }
+
+ android.SetProvider(ctx, FilesystemProvider, fsInfo)
+
+ ctx.SetOutputFiles(android.Paths{output}, "")
+ ctx.CheckbuildFile(output)
+
+ // Dump compliance metadata
+ complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+ complianceMetadataInfo.SetFilesContained(fullInstallPaths)
+}
+
+func (s *systemOtherImage) generateFilesystemConfig(ctx android.ModuleContext, stagingDir, stagingDirTimestamp android.Path) android.Path {
+ out := android.PathForModuleOut(ctx, "filesystem_config.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: fsConfigRule,
+ Input: stagingDirTimestamp, // assemble the staging directory
+ Output: out,
+ Args: map[string]string{
+ "rootDir": stagingDir.String(),
+ "prefix": "system/",
+ },
+ })
+ return out
+}
+
+func (f *systemOtherImage) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path {
+ propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop")
+ builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp).
+ Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp)
+ return propFilePinnedTimestamp
+}
+
+func (f *systemOtherImage) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path {
+ var lines []string
+ addStr := func(name string, value string) {
+ lines = append(lines, fmt.Sprintf("%s=%s", name, value))
+ }
+
+ addStr("building_system_other_image", "true")
+
+ systemImage := ctx.GetDirectDepProxyWithTag(*f.properties.System_image, systemImageDependencyTag)
+ systemInfo, ok := android.OtherModuleProvider(ctx, systemImage, FilesystemProvider)
+ if !ok {
+ ctx.PropertyErrorf("system_image", "Expected system_image module to provide FilesystemProvider")
+ return nil
+ }
+ if systemInfo.PartitionSize == nil {
+ addStr("system_other_disable_sparse", "true")
+ }
+ if systemInfo.UseAvb {
+ addStr("avb_system_other_hashtree_enable", "true")
+ addStr("avb_system_other_algorithm", systemInfo.AvbAlgorithm)
+ footerArgs := fmt.Sprintf("--hash_algorithm %s", systemInfo.AvbHashAlgorithm)
+ if rollbackIndex, err := f.avbRollbackIndex(ctx); err == nil {
+ footerArgs += fmt.Sprintf(" --rollback_index %d", rollbackIndex)
+ } else {
+ ctx.ModuleErrorf("Could not determine rollback_index %s\n", err)
+ }
+ addStr("avb_system_other_add_hashtree_footer_args", footerArgs)
+ if systemInfo.AvbKey != nil {
+ addStr("avb_system_other_key_path", systemInfo.AvbKey.String())
+ }
+ }
+
+ sort.Strings(lines)
+
+ propFile := android.PathForModuleOut(ctx, "prop_file")
+ android.WriteFileRule(ctx, propFile, strings.Join(lines, "\n"))
+ return propFile
+}
+
+// Use the default: PlatformSecurityPatch
+// TODO: Get this value from vbmeta_system
+func (f *systemOtherImage) avbRollbackIndex(ctx android.ModuleContext) (int64, error) {
+ t, err := time.Parse(time.DateOnly, ctx.Config().PlatformSecurityPatch())
+ if err != nil {
+ return -1, err
+ }
+ return t.Unix(), err
+}
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index 6a47859..e7a39be 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -16,7 +16,10 @@
import (
"fmt"
+ "sort"
"strconv"
+ "strings"
+ "time"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -52,6 +55,10 @@
// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
Partition_name *string
+ // Type of the `android_filesystem` for which the vbmeta.img is created.
+ // Examples are system, vendor, product.
+ Filesystem_partition_type *string
+
// Set the name of the output. Defaults to <module_name>.img.
Stem *string
@@ -97,7 +104,7 @@
// Name of the chained partition
Name *string
- // Rollback index location of the chained partition. Must be 0, 1, 2, etc. Default is the
+ // Rollback index location of the chained partition. Must be 1, 2, 3, etc. Default is the
// index of this partition in the list + 1.
Rollback_index_location *int64
@@ -115,12 +122,22 @@
// Name of the partition
Name string
+ // Partition type of the correspdonding android_filesystem.
+ FilesystemPartitionType string
+
// Rollback index location, non-negative int
RollbackIndexLocation int
// The path to the public key of the private key used to sign this partition. Derived from
// the private key.
PublicKey android.Path
+
+ // The output of the vbmeta module
+ Output android.Path
+
+ // Information about the vbmeta partition that will be added to misc_info.txt
+ // created by android_device
+ PropFileForMiscInfo android.Path
}
var vbmetaPartitionProvider = blueprint.NewProvider[vbmetaPartitionInfo]()
@@ -145,8 +162,8 @@
var vbmetaChainedPartitionDep = chainedPartitionDep{}
func (v *vbmeta) DepsMutator(ctx android.BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), vbmetaPartitionDep, v.properties.Partitions.GetOrDefault(ctx, nil)...)
- ctx.AddDependency(ctx.Module(), vbmetaChainedPartitionDep, v.properties.Chained_partitions...)
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), vbmetaPartitionDep, v.properties.Partitions.GetOrDefault(ctx, nil)...)
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), vbmetaChainedPartitionDep, v.properties.Chained_partitions...)
}
func (v *vbmeta) installFileName() string {
@@ -170,13 +187,14 @@
algorithm := proptools.StringDefault(v.properties.Algorithm, "SHA256_RSA4096")
cmd.FlagWithArg("--algorithm ", algorithm)
+ cmd.FlagWithArg("--padding_size ", "4096")
+
cmd.FlagWithArg("--rollback_index ", v.rollbackIndexCommand(ctx))
ril := proptools.IntDefault(v.properties.Rollback_index_location, 0)
if ril < 0 {
ctx.PropertyErrorf("rollback_index_location", "must be 0, 1, 2, ...")
return
}
- cmd.FlagWithArg("--rollback_index_location ", strconv.Itoa(ril))
for _, avb_prop := range v.properties.Avb_properties {
key := proptools.String(avb_prop.Key)
@@ -221,8 +239,8 @@
}
ril := info.RollbackIndexLocation
- if ril < 0 {
- ctx.PropertyErrorf("chained_partitions", "rollback index location must be 0, 1, 2, ...")
+ if ril < 1 {
+ ctx.PropertyErrorf("chained_partitions", "rollback index location must be 1, 2, 3, ...")
continue
} else if seenRils[ril] {
ctx.PropertyErrorf("chained_partitions", "Multiple chained partitions with the same rollback index location %d", ril)
@@ -237,13 +255,13 @@
for _, cpm := range v.properties.Chained_partition_metadata {
name := proptools.String(cpm.Name)
if name == "" {
- ctx.PropertyErrorf("chained_partitions", "name must be specified")
+ ctx.PropertyErrorf("chained_partition_metadata", "name must be specified")
continue
}
- ril := proptools.IntDefault(cpm.Rollback_index_location, -1)
- if ril < 0 {
- ctx.PropertyErrorf("chained_partition_metadata", "rollback index location must be 0, 1, 2, ...")
+ ril := proptools.IntDefault(cpm.Rollback_index_location, 0)
+ if ril < 1 {
+ ctx.PropertyErrorf("chained_partition_metadata", "rollback index location must be 1, 2, 3, ...")
continue
} else if seenRils[ril] {
ctx.PropertyErrorf("chained_partition_metadata", "Multiple chained partitions with the same rollback index location %d", ril)
@@ -294,13 +312,53 @@
})
android.SetProvider(ctx, vbmetaPartitionProvider, vbmetaPartitionInfo{
- Name: v.partitionName(),
- RollbackIndexLocation: ril,
- PublicKey: extractedPublicKey,
+ Name: v.partitionName(),
+ FilesystemPartitionType: proptools.String(v.properties.Filesystem_partition_type),
+ RollbackIndexLocation: ril,
+ PublicKey: extractedPublicKey,
+ Output: output,
+ PropFileForMiscInfo: v.buildPropFileForMiscInfo(ctx),
})
ctx.SetOutputFiles([]android.Path{output}, "")
v.output = output
+
+ setCommonFilesystemInfo(ctx, v)
+}
+
+func (v *vbmeta) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path {
+ var lines []string
+ addStr := func(name string, value string) {
+ lines = append(lines, fmt.Sprintf("%s=%s", name, value))
+ }
+
+ addStr(fmt.Sprintf("avb_%s_algorithm", v.partitionName()), proptools.StringDefault(v.properties.Algorithm, "SHA256_RSA4096"))
+ if v.properties.Private_key != nil {
+ addStr(fmt.Sprintf("avb_%s_key_path", v.partitionName()), android.PathForModuleSrc(ctx, proptools.String(v.properties.Private_key)).String())
+ }
+ if v.properties.Rollback_index_location != nil {
+ addStr(fmt.Sprintf("avb_%s_rollback_index_location", v.partitionName()), strconv.FormatInt(*v.properties.Rollback_index_location, 10))
+ }
+
+ var partitionDepNames []string
+ ctx.VisitDirectDepsProxyWithTag(vbmetaPartitionDep, func(child android.ModuleProxy) {
+ if info, ok := android.OtherModuleProvider(ctx, child, vbmetaPartitionProvider); ok {
+ partitionDepNames = append(partitionDepNames, info.Name)
+ } else {
+ ctx.ModuleErrorf("vbmeta dep %s does not set vbmetaPartitionProvider\n", child)
+ }
+ })
+ if v.partitionName() != "vbmeta" { // skip for vbmeta to match Make's misc_info.txt
+ addStr(fmt.Sprintf("avb_%s", v.partitionName()), strings.Join(android.SortedUniqueStrings(partitionDepNames), " "))
+ }
+
+ addStr(fmt.Sprintf("avb_%s_args", v.partitionName()), fmt.Sprintf("--padding_size 4096 --rollback_index %s", v.rollbackIndexString(ctx)))
+
+ sort.Strings(lines)
+
+ propFile := android.PathForModuleOut(ctx, "prop_file_for_misc_info")
+ android.WriteFileRule(ctx, propFile, strings.Join(lines, "\n"))
+ return propFile
}
// Returns the embedded shell command that prints the rollback index
@@ -313,6 +371,17 @@
}
}
+// Similar to rollbackIndexCommand, but guarantees that the rollback index is
+// always computed during Soong analysis, even if v.properties.Rollback_index is nil
+func (v *vbmeta) rollbackIndexString(ctx android.ModuleContext) string {
+ if v.properties.Rollback_index != nil {
+ return fmt.Sprintf("%d", *v.properties.Rollback_index)
+ } else {
+ t, _ := time.Parse(time.DateOnly, ctx.Config().PlatformSecurityPatch())
+ return fmt.Sprintf("%d", t.Unix())
+ }
+}
+
var _ android.AndroidMkProviderInfoProducer = (*vbmeta)(nil)
func (v *vbmeta) PrepareAndroidMKProviderInfo(config android.Config) *android.AndroidMkProviderInfo {
diff --git a/fsgen/Android.bp b/fsgen/Android.bp
index 365d954..1b828c5 100644
--- a/fsgen/Android.bp
+++ b/fsgen/Android.bp
@@ -14,6 +14,7 @@
],
srcs: [
"boot_imgs.go",
+ "config.go",
"filesystem_creator.go",
"fsgen_mutators.go",
"prebuilt_etc_modules_gen.go",
diff --git a/fsgen/boot_imgs.go b/fsgen/boot_imgs.go
index 4e80720..0ba0a90 100644
--- a/fsgen/boot_imgs.go
+++ b/fsgen/boot_imgs.go
@@ -69,22 +69,27 @@
ctx.CreateModule(
filesystem.BootimgFactory,
&filesystem.BootimgProperties{
- Kernel_prebuilt: proptools.StringPtr(":" + kernelFilegroupName),
- Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
- Partition_size: partitionSize,
- Use_avb: avbInfo.avbEnable,
- Avb_mode: avbInfo.avbMode,
- Avb_private_key: avbInfo.avbkeyFilegroup,
- Avb_rollback_index: avbInfo.avbRollbackIndex,
- Avb_algorithm: avbInfo.avbAlgorithm,
- Security_patch: securityPatch,
- Dtb_prebuilt: dtbPrebuilt,
- Cmdline: cmdline,
+ Boot_image_type: proptools.StringPtr("boot"),
+ Kernel_prebuilt: proptools.StringPtr(":" + kernelFilegroupName),
+ Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
+ Partition_size: partitionSize,
+ Use_avb: avbInfo.avbEnable,
+ Avb_mode: avbInfo.avbMode,
+ Avb_private_key: avbInfo.avbkeyFilegroup,
+ Avb_rollback_index: avbInfo.avbRollbackIndex,
+ Avb_rollback_index_location: avbInfo.avbRollbackIndexLocation,
+ Avb_algorithm: avbInfo.avbAlgorithm,
+ Security_patch: securityPatch,
+ Dtb_prebuilt: dtbPrebuilt,
+ Cmdline: cmdline,
+ Stem: proptools.StringPtr("boot.img"),
},
&struct {
- Name *string
+ Name *string
+ Visibility []string
}{
- Name: proptools.StringPtr(bootImageName),
+ Name: proptools.StringPtr(bootImageName),
+ Visibility: []string{"//visibility:public"},
},
)
return true
@@ -109,25 +114,39 @@
vendorBootConfigImg = proptools.StringPtr(":" + name)
}
+ var partitionSize *int64
+ if partitionVariables.BoardVendorBootimagePartitionSize != "" {
+ // Base of zero will allow base 10 or base 16 if starting with 0x
+ parsed, err := strconv.ParseInt(partitionVariables.BoardVendorBootimagePartitionSize, 0, 64)
+ if err != nil {
+ ctx.ModuleErrorf("BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardVendorBootimagePartitionSize)
+ }
+ partitionSize = &parsed
+ }
+
ctx.CreateModule(
filesystem.BootimgFactory,
&filesystem.BootimgProperties{
- Boot_image_type: proptools.StringPtr("vendor_boot"),
- Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")),
- Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
- Use_avb: avbInfo.avbEnable,
- Avb_mode: avbInfo.avbMode,
- Avb_private_key: avbInfo.avbkeyFilegroup,
- Avb_rollback_index: avbInfo.avbRollbackIndex,
- Avb_algorithm: avbInfo.avbAlgorithm,
- Dtb_prebuilt: dtbPrebuilt,
- Cmdline: cmdline,
- Bootconfig: vendorBootConfigImg,
+ Boot_image_type: proptools.StringPtr("vendor_boot"),
+ Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")),
+ Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
+ Partition_size: partitionSize,
+ Use_avb: avbInfo.avbEnable,
+ Avb_mode: avbInfo.avbMode,
+ Avb_private_key: avbInfo.avbkeyFilegroup,
+ Avb_rollback_index: avbInfo.avbRollbackIndex,
+ Avb_rollback_index_location: avbInfo.avbRollbackIndexLocation,
+ Dtb_prebuilt: dtbPrebuilt,
+ Cmdline: cmdline,
+ Bootconfig: vendorBootConfigImg,
+ Stem: proptools.StringPtr("vendor_boot.img"),
},
&struct {
- Name *string
+ Name *string
+ Visibility []string
}{
- Name: proptools.StringPtr(bootImageName),
+ Name: proptools.StringPtr(bootImageName),
+ Visibility: []string{"//visibility:public"},
},
)
return true
@@ -160,21 +179,25 @@
ctx.CreateModule(
filesystem.BootimgFactory,
&filesystem.BootimgProperties{
- Boot_image_type: proptools.StringPtr("init_boot"),
- Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")),
- Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
- Security_patch: securityPatch,
- Partition_size: partitionSize,
- Use_avb: avbInfo.avbEnable,
- Avb_mode: avbInfo.avbMode,
- Avb_private_key: avbInfo.avbkeyFilegroup,
- Avb_rollback_index: avbInfo.avbRollbackIndex,
- Avb_algorithm: avbInfo.avbAlgorithm,
+ Boot_image_type: proptools.StringPtr("init_boot"),
+ Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")),
+ Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
+ Security_patch: securityPatch,
+ Partition_size: partitionSize,
+ Use_avb: avbInfo.avbEnable,
+ Avb_mode: avbInfo.avbMode,
+ Avb_private_key: avbInfo.avbkeyFilegroup,
+ Avb_rollback_index: avbInfo.avbRollbackIndex,
+ Avb_rollback_index_location: avbInfo.avbRollbackIndexLocation,
+ Avb_algorithm: avbInfo.avbAlgorithm,
+ Stem: proptools.StringPtr("init_boot.img"),
},
&struct {
- Name *string
+ Name *string
+ Visibility []string
}{
- Name: proptools.StringPtr(bootImageName),
+ Name: proptools.StringPtr(bootImageName),
+ Visibility: []string{"//visibility:public"},
},
)
return true
diff --git a/fsgen/config.go b/fsgen/config.go
new file mode 100644
index 0000000..a217600
--- /dev/null
+++ b/fsgen/config.go
@@ -0,0 +1,141 @@
+// 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 fsgen
+
+import (
+ "android/soong/filesystem"
+
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ // Most of the symlinks and directories listed here originate from create_root_structure.mk,
+ // but the handwritten generic system image also recreates them:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04
+ // TODO(b/377734331): only generate the symlinks if the relevant partitions exist
+ commonSymlinksFromRoot = []filesystem.SymlinkDefinition{
+ {
+ Target: proptools.StringPtr("/system/bin/init"),
+ Name: proptools.StringPtr("init"),
+ },
+ {
+ Target: proptools.StringPtr("/system/etc"),
+ Name: proptools.StringPtr("etc"),
+ },
+ {
+ Target: proptools.StringPtr("/system/bin"),
+ Name: proptools.StringPtr("bin"),
+ },
+ {
+ Target: proptools.StringPtr("/data/user_de/0/com.android.shell/files/bugreports"),
+ Name: proptools.StringPtr("bugreports"),
+ },
+ {
+ Target: proptools.StringPtr("/sys/kernel/debug"),
+ Name: proptools.StringPtr("d"),
+ },
+ {
+ Target: proptools.StringPtr("/product/etc/security/adb_keys"),
+ Name: proptools.StringPtr("adb_keys"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/app"),
+ Name: proptools.StringPtr("odm/app"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/bin"),
+ Name: proptools.StringPtr("odm/bin"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/etc"),
+ Name: proptools.StringPtr("odm/etc"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/firmware"),
+ Name: proptools.StringPtr("odm/firmware"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/framework"),
+ Name: proptools.StringPtr("odm/framework"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/lib"),
+ Name: proptools.StringPtr("odm/lib"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/lib64"),
+ Name: proptools.StringPtr("odm/lib64"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/overlay"),
+ Name: proptools.StringPtr("odm/overlay"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/priv-app"),
+ Name: proptools.StringPtr("odm/priv-app"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/usr"),
+ Name: proptools.StringPtr("odm/usr"),
+ },
+ // For Treble Generic System Image (GSI), system-as-root GSI needs to work on
+ // both devices with and without /odm_dlkm partition. Those symlinks are for
+ // devices without /odm_dlkm partition. For devices with /odm_dlkm
+ // partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
+ // Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
+ // via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink
+ {
+ Target: proptools.StringPtr("/odm/odm_dlkm/etc"),
+ Name: proptools.StringPtr("odm_dlkm/etc"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"),
+ Name: proptools.StringPtr("vendor_dlkm/etc"),
+ },
+ }
+
+ // Common directories between partitions that may be listed as `Dirs` property in the
+ // filesystem module.
+ commonPartitionDirs = []string{
+ // From generic_rootdirs in build/make/target/product/generic/Android.bp
+ "apex",
+ "bootstrap-apex",
+ "config",
+ "data",
+ "data_mirror",
+ "debug_ramdisk",
+ "dev",
+ "linkerconfig",
+ "metadata",
+ "mnt",
+ "odm",
+ "odm_dlkm",
+ "oem",
+ "postinstall",
+ "proc",
+ "second_stage_resources",
+ "storage",
+ "sys",
+ "system",
+ "system_dlkm",
+ "tmp",
+ "vendor",
+ "vendor_dlkm",
+
+ // from android_rootdirs in build/make/target/product/generic/Android.bp
+ "system_ext",
+ "product",
+ }
+)
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 11dfac0..14aa062 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -42,8 +42,85 @@
ctx.PreDepsMutators(RegisterCollectFileSystemDepsMutators)
}
+type generatedPartitionData struct {
+ partitionType string
+ moduleName string
+ // supported is true if the module was created successfully, false if there was some problem
+ // and the module couldn't be created.
+ supported bool
+ handwritten bool
+}
+
+type allGeneratedPartitionData []generatedPartitionData
+
+func (d allGeneratedPartitionData) moduleNames() []string {
+ var result []string
+ for _, data := range d {
+ if data.supported {
+ result = append(result, data.moduleName)
+ }
+ }
+ return result
+}
+
+func (d allGeneratedPartitionData) types() []string {
+ var result []string
+ for _, data := range d {
+ if data.supported {
+ result = append(result, data.partitionType)
+ }
+ }
+ return result
+}
+
+func (d allGeneratedPartitionData) unsupportedTypes() []string {
+ var result []string
+ for _, data := range d {
+ if !data.supported {
+ result = append(result, data.partitionType)
+ }
+ }
+ return result
+}
+
+func (d allGeneratedPartitionData) names() []string {
+ var result []string
+ for _, data := range d {
+ if data.supported {
+ result = append(result, data.moduleName)
+ }
+ }
+ return result
+}
+
+func (d allGeneratedPartitionData) nameForType(ty string) string {
+ for _, data := range d {
+ if data.supported && data.partitionType == ty {
+ return data.moduleName
+ }
+ }
+ return ""
+}
+
+func (d allGeneratedPartitionData) typeForName(name string) string {
+ for _, data := range d {
+ if data.supported && data.moduleName == name {
+ return data.partitionType
+ }
+ }
+ return ""
+}
+
+func (d allGeneratedPartitionData) isHandwritten(name string) bool {
+ for _, data := range d {
+ if data.supported && data.moduleName == name {
+ return data.handwritten
+ }
+ }
+ return false
+}
+
type filesystemCreatorProps struct {
- Generated_partition_types []string `blueprint:"mutated"`
Unsupported_partition_types []string `blueprint:"mutated"`
Vbmeta_module_names []string `blueprint:"mutated"`
@@ -78,56 +155,74 @@
return module
}
-func generatedPartitions(ctx android.LoadHookContext) []string {
+func generatedPartitions(ctx android.EarlyModuleContext) allGeneratedPartitionData {
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
- generatedPartitions := []string{"system"}
+
+ var result allGeneratedPartitionData
+ addGenerated := func(ty string) {
+ result = append(result, generatedPartitionData{
+ partitionType: ty,
+ moduleName: generatedModuleNameForPartition(ctx.Config(), ty),
+ supported: true,
+ })
+ }
+
+ if ctx.Config().UseSoongSystemImage() {
+ if ctx.Config().SoongDefinedSystemImage() == "" {
+ panic("PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE must be set if USE_SOONG_DEFINED_SYSTEM_IMAGE is true")
+ }
+ result = append(result, generatedPartitionData{
+ partitionType: "system",
+ moduleName: ctx.Config().SoongDefinedSystemImage(),
+ supported: true,
+ handwritten: true,
+ })
+ } else {
+ addGenerated("system")
+ }
if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
- generatedPartitions = append(generatedPartitions, "system_ext")
+ addGenerated("system_ext")
}
if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" {
- generatedPartitions = append(generatedPartitions, "vendor")
+ addGenerated("vendor")
}
if ctx.DeviceConfig().BuildingProductImage() && ctx.DeviceConfig().ProductPath() == "product" {
- generatedPartitions = append(generatedPartitions, "product")
+ addGenerated("product")
}
if ctx.DeviceConfig().BuildingOdmImage() && ctx.DeviceConfig().OdmPath() == "odm" {
- generatedPartitions = append(generatedPartitions, "odm")
+ addGenerated("odm")
}
if ctx.DeviceConfig().BuildingUserdataImage() && ctx.DeviceConfig().UserdataPath() == "data" {
- generatedPartitions = append(generatedPartitions, "userdata")
+ addGenerated("userdata")
}
if partitionVars.BuildingSystemDlkmImage {
- generatedPartitions = append(generatedPartitions, "system_dlkm")
+ addGenerated("system_dlkm")
}
if partitionVars.BuildingVendorDlkmImage {
- generatedPartitions = append(generatedPartitions, "vendor_dlkm")
+ addGenerated("vendor_dlkm")
}
if partitionVars.BuildingOdmDlkmImage {
- generatedPartitions = append(generatedPartitions, "odm_dlkm")
+ addGenerated("odm_dlkm")
}
if partitionVars.BuildingRamdiskImage {
- generatedPartitions = append(generatedPartitions, "ramdisk")
+ addGenerated("ramdisk")
}
if buildingVendorBootImage(partitionVars) {
- generatedPartitions = append(generatedPartitions, "vendor_ramdisk")
+ addGenerated("vendor_ramdisk")
}
if ctx.DeviceConfig().BuildingRecoveryImage() && ctx.DeviceConfig().RecoveryPath() == "recovery" {
- generatedPartitions = append(generatedPartitions, "recovery")
+ addGenerated("recovery")
}
- return generatedPartitions
+ return result
}
func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) {
- soongGeneratedPartitions := generatedPartitions(ctx)
- finalSoongGeneratedPartitions := make([]string, 0, len(soongGeneratedPartitions))
- for _, partitionType := range soongGeneratedPartitions {
- if f.createPartition(ctx, partitionType) {
- f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType)
- finalSoongGeneratedPartitions = append(finalSoongGeneratedPartitions, partitionType)
- } else {
- f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
- }
+ partitions := generatedPartitions(ctx)
+ for i := range partitions {
+ f.createPartition(ctx, partitions, &partitions[i])
}
+ // Create android_info.prop
+ f.createAndroidInfo(ctx)
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
dtbImg := createDtbImgFilegroup(ctx)
@@ -154,18 +249,37 @@
}
}
- for _, x := range createVbmetaPartitions(ctx, finalSoongGeneratedPartitions) {
+ var systemOtherImageName string
+ if buildingSystemOtherImage(partitionVars) {
+ systemModule := partitions.nameForType("system")
+ systemOtherImageName = generatedModuleNameForPartition(ctx.Config(), "system_other")
+ ctx.CreateModule(
+ filesystem.SystemOtherImageFactory,
+ &filesystem.SystemOtherImageProperties{
+ System_image: &systemModule,
+ Preinstall_dexpreopt_files_from: partitions.moduleNames(),
+ },
+ &struct {
+ Name *string
+ }{
+ Name: proptools.StringPtr(systemOtherImageName),
+ },
+ )
+ }
+
+ for _, x := range f.createVbmetaPartitions(ctx, partitions) {
f.properties.Vbmeta_module_names = append(f.properties.Vbmeta_module_names, x.moduleName)
f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName)
}
+ var superImageSubpartitions []string
if buildingSuperImage(partitionVars) {
- createSuperImage(ctx, finalSoongGeneratedPartitions, partitionVars)
- f.properties.Super_image = ":" + generatedModuleName(ctx.Config(), "super")
+ superImageSubpartitions = createSuperImage(ctx, partitions, partitionVars, systemOtherImageName)
+ f.properties.Super_image = ":" + generatedModuleNameForPartition(ctx.Config(), "super")
}
- ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions
- f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names)
+ ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = partitions
+ f.createDeviceModule(ctx, partitions, f.properties.Vbmeta_module_names, superImageSubpartitions)
}
func generatedModuleName(cfg android.Config, suffix string) string {
@@ -180,10 +294,77 @@
return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
}
+func buildingSystemOtherImage(partitionVars android.PartitionVariables) bool {
+ // TODO: Recreate this logic from make instead of just depending on the final result variable:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=429;drc=15a0df840e7093f65518003ab80cf24a3d9e8e6a
+ return partitionVars.BuildingSystemOtherImage
+}
+
+func (f *filesystemCreator) createBootloaderFilegroup(ctx android.LoadHookContext) (string, bool) {
+ bootloaderPath := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrebuiltBootloader
+ if len(bootloaderPath) == 0 {
+ return "", false
+ }
+
+ bootloaderFilegroupName := generatedModuleName(ctx.Config(), "bootloader")
+ filegroupProps := &struct {
+ Name *string
+ Srcs []string
+ Visibility []string
+ }{
+ Name: proptools.StringPtr(bootloaderFilegroupName),
+ Srcs: []string{bootloaderPath},
+ Visibility: []string{"//visibility:public"},
+ }
+ ctx.CreateModuleInDirectory(android.FileGroupFactory, ".", filegroupProps)
+ return bootloaderFilegroupName, true
+}
+
+func (f *filesystemCreator) createReleaseToolsFilegroup(ctx android.LoadHookContext) (string, bool) {
+ releaseToolsDir := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.ReleaseToolsExtensionDir
+ if releaseToolsDir == "" {
+ return "", false
+ }
+
+ releaseToolsFilegroupName := generatedModuleName(ctx.Config(), "releasetools")
+ filegroupProps := &struct {
+ Name *string
+ Srcs []string
+ Visibility []string
+ }{
+ Name: proptools.StringPtr(releaseToolsFilegroupName),
+ Srcs: []string{"releasetools.py"},
+ Visibility: []string{"//visibility:public"},
+ }
+ ctx.CreateModuleInDirectory(android.FileGroupFactory, releaseToolsDir, filegroupProps)
+ return releaseToolsFilegroupName, true
+}
+
+func (f *filesystemCreator) createFastbootInfoFilegroup(ctx android.LoadHookContext) (string, bool) {
+ fastbootInfoFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFastbootInfoFile
+ if fastbootInfoFile == "" {
+ return "", false
+ }
+
+ fastbootInfoFilegroupName := generatedModuleName(ctx.Config(), "fastboot")
+ filegroupProps := &struct {
+ Name *string
+ Srcs []string
+ Visibility []string
+ }{
+ Name: proptools.StringPtr(fastbootInfoFilegroupName),
+ Srcs: []string{fastbootInfoFile},
+ Visibility: []string{"//visibility:public"},
+ }
+ ctx.CreateModuleInDirectory(android.FileGroupFactory, ".", filegroupProps)
+ return fastbootInfoFilegroupName, true
+}
+
func (f *filesystemCreator) createDeviceModule(
ctx android.LoadHookContext,
- generatedPartitionTypes []string,
+ partitions allGeneratedPartitionData,
vbmetaPartitions []string,
+ superImageSubPartitions []string,
) {
baseProps := &struct {
Name *string
@@ -193,30 +374,78 @@
// Currently, only the system and system_ext partition module is created.
partitionProps := &filesystem.PartitionNameProperties{}
- if android.InList("system", generatedPartitionTypes) {
- partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ if f.properties.Super_image != "" {
+ partitionProps.Super_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "super"))
}
- if android.InList("system_ext", generatedPartitionTypes) {
- partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ if modName := partitions.nameForType("system"); modName != "" && !android.InList("system", superImageSubPartitions) {
+ partitionProps.System_partition_name = proptools.StringPtr(modName)
}
- if android.InList("vendor", generatedPartitionTypes) {
- partitionProps.Vendor_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
+ if modName := partitions.nameForType("system_ext"); modName != "" && !android.InList("system_ext", superImageSubPartitions) {
+ partitionProps.System_ext_partition_name = proptools.StringPtr(modName)
}
- if android.InList("product", generatedPartitionTypes) {
- partitionProps.Product_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
+ if modName := partitions.nameForType("vendor"); modName != "" && !android.InList("vendor", superImageSubPartitions) {
+ partitionProps.Vendor_partition_name = proptools.StringPtr(modName)
}
- if android.InList("odm", generatedPartitionTypes) {
- partitionProps.Odm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
+ if modName := partitions.nameForType("product"); modName != "" && !android.InList("product", superImageSubPartitions) {
+ partitionProps.Product_partition_name = proptools.StringPtr(modName)
}
- if android.InList("userdata", f.properties.Generated_partition_types) {
- partitionProps.Userdata_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "userdata"))
+ if modName := partitions.nameForType("odm"); modName != "" && !android.InList("odm", superImageSubPartitions) {
+ partitionProps.Odm_partition_name = proptools.StringPtr(modName)
+ }
+ if modName := partitions.nameForType("userdata"); modName != "" {
+ partitionProps.Userdata_partition_name = proptools.StringPtr(modName)
+ }
+ if modName := partitions.nameForType("recovery"); modName != "" && !ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
+ partitionProps.Recovery_partition_name = proptools.StringPtr(modName)
+ }
+ if modName := partitions.nameForType("system_dlkm"); modName != "" && !android.InList("system_dlkm", superImageSubPartitions) {
+ partitionProps.System_dlkm_partition_name = proptools.StringPtr(modName)
+ }
+ if modName := partitions.nameForType("vendor_dlkm"); modName != "" && !android.InList("vendor_dlkm", superImageSubPartitions) {
+ partitionProps.Vendor_dlkm_partition_name = proptools.StringPtr(modName)
+ }
+ if modName := partitions.nameForType("odm_dlkm"); modName != "" && !android.InList("odm_dlkm", superImageSubPartitions) {
+ partitionProps.Odm_dlkm_partition_name = proptools.StringPtr(modName)
+ }
+ if f.properties.Boot_image != "" {
+ partitionProps.Boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "boot"))
+ }
+ if f.properties.Vendor_boot_image != "" {
+ partitionProps.Vendor_boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_boot"))
+ }
+ if f.properties.Init_boot_image != "" {
+ partitionProps.Init_boot_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "init_boot"))
}
partitionProps.Vbmeta_partitions = vbmetaPartitions
- ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
+ deviceProps := &filesystem.DeviceProperties{
+ Main_device: proptools.BoolPtr(true),
+ Ab_ota_updater: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater),
+ Ab_ota_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions,
+ Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig,
+ Ramdisk_node_list: proptools.StringPtr(":ramdisk_node_list"),
+ Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
+ Kernel_version: ctx.Config().ProductVariables().BoardKernelVersion,
+ Partial_ota_update_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardPartialOtaUpdatePartitionsList,
+ Flash_block_size: proptools.StringPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFlashBlockSize),
+ Bootloader_in_update_package: proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BootloaderInUpdatePackage),
+ }
+
+ if bootloader, ok := f.createBootloaderFilegroup(ctx); ok {
+ deviceProps.Bootloader = proptools.StringPtr(":" + bootloader)
+ }
+ if releaseTools, ok := f.createReleaseToolsFilegroup(ctx); ok {
+ deviceProps.Releasetools_extension = proptools.StringPtr(":" + releaseTools)
+ }
+ if fastbootInfo, ok := f.createFastbootInfoFilegroup(ctx); ok {
+ deviceProps.FastbootInfo = proptools.StringPtr(":" + fastbootInfo)
+ }
+
+ ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps, deviceProps)
}
-func partitionSpecificFsProps(ctx android.EarlyModuleContext, fsProps *filesystem.FilesystemProperties, partitionVars android.PartitionVariables, partitionType string) {
+func partitionSpecificFsProps(ctx android.EarlyModuleContext, partitions allGeneratedPartitionData, fsProps *filesystem.FilesystemProperties, partitionType string) {
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
switch partitionType {
case "system":
fsProps.Build_logtags = proptools.BoolPtr(true)
@@ -235,146 +464,39 @@
})
fsProps.Fsverity.Libs = proptools.NewSimpleConfigurable([]string{":framework-res{.export-package.apk}"})
}
- // Most of the symlinks and directories listed here originate from create_root_structure.mk,
- // but the handwritten generic system image also recreates them:
- // https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04
- // TODO(b/377734331): only generate the symlinks if the relevant partitions exist
- fsProps.Symlinks = []filesystem.SymlinkDefinition{
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system/bin/init"),
- Name: proptools.StringPtr("init"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system/etc"),
- Name: proptools.StringPtr("etc"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system/bin"),
- Name: proptools.StringPtr("bin"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/data/user_de/0/com.android.shell/files/bugreports"),
- Name: proptools.StringPtr("bugreports"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/sys/kernel/debug"),
- Name: proptools.StringPtr("d"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/storage/self/primary"),
- Name: proptools.StringPtr("sdcard"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/product/etc/security/adb_keys"),
- Name: proptools.StringPtr("adb_keys"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/app"),
- Name: proptools.StringPtr("odm/app"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/bin"),
- Name: proptools.StringPtr("odm/bin"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/etc"),
- Name: proptools.StringPtr("odm/etc"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/firmware"),
- Name: proptools.StringPtr("odm/firmware"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/framework"),
- Name: proptools.StringPtr("odm/framework"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/lib"),
- Name: proptools.StringPtr("odm/lib"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/lib64"),
- Name: proptools.StringPtr("odm/lib64"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/overlay"),
- Name: proptools.StringPtr("odm/overlay"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/priv-app"),
- Name: proptools.StringPtr("odm/priv-app"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/usr"),
- Name: proptools.StringPtr("odm/usr"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/product"),
- Name: proptools.StringPtr("system/product"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system_ext"),
- Name: proptools.StringPtr("system/system_ext"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor"),
- Name: proptools.StringPtr("system/vendor"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system_dlkm/lib/modules"),
- Name: proptools.StringPtr("system/lib/modules"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/data/cache"),
- Name: proptools.StringPtr("cache"),
- },
- // For Treble Generic System Image (GSI), system-as-root GSI needs to work on
- // both devices with and without /odm_dlkm partition. Those symlinks are for
- // devices without /odm_dlkm partition. For devices with /odm_dlkm
- // partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
- // Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
- // via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/odm/odm_dlkm/etc"),
- Name: proptools.StringPtr("odm_dlkm/etc"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"),
- Name: proptools.StringPtr("vendor_dlkm/etc"),
- },
- }
+ fsProps.Symlinks = commonSymlinksFromRoot
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ []filesystem.SymlinkDefinition{
+ {
+ Target: proptools.StringPtr("/data/cache"),
+ Name: proptools.StringPtr("cache"),
+ },
+ {
+ Target: proptools.StringPtr("/storage/self/primary"),
+ Name: proptools.StringPtr("sdcard"),
+ },
+ {
+ Target: proptools.StringPtr("/system_dlkm/lib/modules"),
+ Name: proptools.StringPtr("system/lib/modules"),
+ },
+ {
+ Target: proptools.StringPtr("/product"),
+ Name: proptools.StringPtr("system/product"),
+ },
+ {
+ Target: proptools.StringPtr("/system_ext"),
+ Name: proptools.StringPtr("system/system_ext"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor"),
+ Name: proptools.StringPtr("system/vendor"),
+ },
+ }...,
+ )
fsProps.Base_dir = proptools.StringPtr("system")
- fsProps.Dirs = proptools.NewSimpleConfigurable([]string{
- // From generic_rootdirs in build/make/target/product/generic/Android.bp
- "acct",
- "apex",
- "bootstrap-apex",
- "config",
- "data",
- "data_mirror",
- "debug_ramdisk",
- "dev",
- "linkerconfig",
- "metadata",
- "mnt",
- "odm",
- "odm_dlkm",
- "oem",
- "postinstall",
- "proc",
- "second_stage_resources",
- "storage",
- "sys",
- "system",
- "system_dlkm",
- "tmp",
- "vendor",
- "vendor_dlkm",
-
- // from android_rootdirs in build/make/target/product/generic/Android.bp
- "system_ext",
- "product",
- })
+ fsProps.Dirs = proptools.NewSimpleConfigurable(commonPartitionDirs)
+ fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch())
+ fsProps.Stem = proptools.StringPtr("system.img")
case "system_ext":
if partitionVars.ProductFsverityGenerateMetadata {
fsProps.Fsverity.Inputs = proptools.NewSimpleConfigurable([]string{
@@ -384,12 +506,17 @@
})
fsProps.Fsverity.Libs = proptools.NewSimpleConfigurable([]string{":framework-res{.export-package.apk}"})
}
+ fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch())
+ fsProps.Stem = proptools.StringPtr("system_ext.img")
+ fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
case "product":
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
- fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
- if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
- fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ fsProps.Android_filesystem_deps.System = proptools.StringPtr(partitions.nameForType("system"))
+ if systemExtName := partitions.nameForType("system_ext"); systemExtName != "" {
+ fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(systemExtName)
}
+ fsProps.Security_patch = proptools.StringPtr(ctx.Config().PlatformSecurityPatch())
+ fsProps.Stem = proptools.StringPtr("product.img")
case "vendor":
fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
fsProps.Symlinks = []filesystem.SymlinkDefinition{
@@ -402,10 +529,12 @@
Name: proptools.StringPtr("lib/modules"),
},
}
- fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
- if ctx.DeviceConfig().SystemExtPath() == "system_ext" {
- fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ fsProps.Android_filesystem_deps.System = proptools.StringPtr(partitions.nameForType("system"))
+ if systemExtName := partitions.nameForType("system_ext"); systemExtName != "" {
+ fsProps.Android_filesystem_deps.System_ext = proptools.StringPtr(systemExtName)
}
+ fsProps.Security_patch = proptools.StringPtr(partitionVars.VendorSecurityPatch)
+ fsProps.Stem = proptools.StringPtr("vendor.img")
case "odm":
fsProps.Symlinks = []filesystem.SymlinkDefinition{
filesystem.SymlinkDefinition{
@@ -413,8 +542,36 @@
Name: proptools.StringPtr("lib/modules"),
},
}
+ fsProps.Security_patch = proptools.StringPtr(partitionVars.OdmSecurityPatch)
+ fsProps.Stem = proptools.StringPtr("odm.img")
case "userdata":
- fsProps.Base_dir = proptools.StringPtr("data")
+ fsProps.Stem = proptools.StringPtr("userdata.img")
+ if vars, ok := partitionVars.PartitionQualifiedVariables["userdata"]; ok {
+ parsed, err := strconv.ParseInt(vars.BoardPartitionSize, 10, 64)
+ if err != nil {
+ panic(fmt.Sprintf("Partition size must be an int, got %s", vars.BoardPartitionSize))
+ }
+ fsProps.Partition_size = &parsed
+ // Disable avb for userdata partition
+ fsProps.Use_avb = nil
+ }
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2265;drc=7f50a123045520f2c5e18e9eb4e83f92244a1459
+ if s, err := strconv.ParseBool(partitionVars.ProductFsCasefold); err == nil {
+ fsProps.Support_casefolding = proptools.BoolPtr(s)
+ } else if len(partitionVars.ProductFsCasefold) > 0 {
+ ctx.ModuleErrorf("Unrecognized PRODUCT_FS_CASEFOLD value %s", partitionVars.ProductFsCasefold)
+ }
+ if s, err := strconv.ParseBool(partitionVars.ProductQuotaProjid); err == nil {
+ fsProps.Support_project_quota = proptools.BoolPtr(s)
+ } else if len(partitionVars.ProductQuotaProjid) > 0 {
+ ctx.ModuleErrorf("Unrecognized PRODUCT_QUOTA_PROJID value %s", partitionVars.ProductQuotaProjid)
+ }
+ if s, err := strconv.ParseBool(partitionVars.ProductFsCompression); err == nil {
+ fsProps.Enable_compression = proptools.BoolPtr(s)
+ } else if len(partitionVars.ProductFsCompression) > 0 {
+ ctx.ModuleErrorf("Unrecognized PRODUCT_FS_COMPRESSION value %s", partitionVars.ProductFsCompression)
+ }
+
case "ramdisk":
// Following the logic in https://cs.android.com/android/platform/superproject/main/+/c3c5063df32748a8806ce5da5dd0db158eab9ad9:build/make/core/Makefile;l=1307
fsProps.Dirs = android.NewSimpleConfigurable([]string{
@@ -437,23 +594,37 @@
"first_stage_ramdisk/sys",
})
}
+ fsProps.Stem = proptools.StringPtr("ramdisk.img")
case "recovery":
- // Following https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2826;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526
- fsProps.Dirs = android.NewSimpleConfigurable([]string{
+ dirs := append(commonPartitionDirs, []string{
"sdcard",
- "tmp",
- })
- fsProps.Symlinks = []filesystem.SymlinkDefinition{
- {
- Target: proptools.StringPtr("/system/bin/init"),
- Name: proptools.StringPtr("init"),
- },
- {
- Target: proptools.StringPtr("prop.default"),
- Name: proptools.StringPtr("default.prop"),
- },
+ }...)
+
+ dirsWithRoot := make([]string, len(dirs))
+ for i, dir := range dirs {
+ dirsWithRoot[i] = filepath.Join("root", dir)
}
- fsProps.Base_dir = proptools.StringPtr("recovery")
+
+ fsProps.Dirs = proptools.NewSimpleConfigurable(dirsWithRoot)
+ fsProps.Symlinks = symlinksWithNamePrefix(append(commonSymlinksFromRoot, filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("prop.default"),
+ Name: proptools.StringPtr("default.prop"),
+ }), "root")
+ fsProps.Stem = proptools.StringPtr("recovery.img")
+ case "system_dlkm":
+ fsProps.Security_patch = proptools.StringPtr(partitionVars.SystemDlkmSecurityPatch)
+ fsProps.Stem = proptools.StringPtr("system_dlkm.img")
+ case "vendor_dlkm":
+ fsProps.Security_patch = proptools.StringPtr(partitionVars.VendorDlkmSecurityPatch)
+ fsProps.Stem = proptools.StringPtr("vendor_dlkm.img")
+ case "odm_dlkm":
+ fsProps.Security_patch = proptools.StringPtr(partitionVars.OdmDlkmSecurityPatch)
+ fsProps.Stem = proptools.StringPtr("odm_dlkm.img")
+ case "vendor_ramdisk":
+ if recoveryName := partitions.nameForType("recovery"); recoveryName != "" {
+ fsProps.Include_files_of = []string{recoveryName}
+ }
+ fsProps.Stem = proptools.StringPtr("vendor_ramdisk.img")
}
}
@@ -465,16 +636,22 @@
}
)
-// Creates a soong module to build the given partition. Returns false if we can't support building
-// it.
-func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitionType string) bool {
- baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
-
- fsProps, supported := generateFsProps(ctx, partitionType)
- if !supported {
- return false
+// Creates a soong module to build the given partition.
+func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitions allGeneratedPartitionData, partition *generatedPartitionData) {
+ // Nextgen team's handwritten soong system image, don't need to create anything ourselves
+ if partition.partitionType == "system" && ctx.Config().UseSoongSystemImage() {
+ return
}
+ baseProps := generateBaseProps(proptools.StringPtr(partition.moduleName))
+
+ fsProps, supported := generateFsProps(ctx, partitions, partition.partitionType)
+ if !supported {
+ partition.supported = false
+ return
+ }
+
+ partitionType := partition.partitionType
if partitionType == "vendor" || partitionType == "product" || partitionType == "system" {
fsProps.Linker_config.Gen_linker_config = proptools.BoolPtr(true)
if partitionType != "system" {
@@ -498,7 +675,6 @@
if partitionType == "vendor" {
f.createVendorBuildProp(ctx)
}
- return true
}
// Creates filegroups for the files specified in BOARD_(partition_)AVB_KEY_PATH
@@ -586,8 +762,10 @@
Load_by_default *bool
Blocklist_file *string
Options_file *string
+ Strip_debug_symbols *bool
}{
- Name: proptools.StringPtr(name),
+ Name: proptools.StringPtr(name),
+ Strip_debug_symbols: proptools.BoolPtr(false),
}
switch partitionType {
case "system_dlkm":
@@ -644,8 +822,8 @@
(*fsGenState.fsDeps[partitionType])[name] = defaultDepCandidateProps(ctx.Config())
}
-// Create a build_prop and android_info module. This will be used to create /vendor/build.prop
-func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) {
+// Create an android_info module. This will be used to create /vendor/build.prop
+func (f *filesystemCreator) createAndroidInfo(ctx android.LoadHookContext) {
// Create a android_info for vendor
// The board info files might be in a directory outside the root soong namespace, so create
// the module in "."
@@ -654,9 +832,11 @@
Name *string
Board_info_files []string
Bootloader_board_name *string
+ Stem *string
}{
- Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "android-info.prop")),
+ Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "android_info.prop")),
Board_info_files: partitionVars.BoardInfoFiles,
+ Stem: proptools.StringPtr("android-info.txt"),
}
if len(androidInfoProps.Board_info_files) == 0 {
androidInfoProps.Bootloader_board_name = proptools.StringPtr(partitionVars.BootLoaderBoardName)
@@ -667,25 +847,76 @@
androidInfoProps,
)
androidInfoProp.HideFromMake()
- // Create a build prop for vendor
+}
+
+func (f *filesystemCreator) createVendorBuildProp(ctx android.LoadHookContext) {
vendorBuildProps := &struct {
Name *string
Vendor *bool
Stem *string
Product_config *string
Android_info *string
+ Licenses []string
+ Dist android.Dist
}{
Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "vendor-build.prop")),
Vendor: proptools.BoolPtr(true),
Stem: proptools.StringPtr("build.prop"),
Product_config: proptools.StringPtr(":product_config"),
- Android_info: proptools.StringPtr(":" + androidInfoProp.Name()),
+ Android_info: proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop")),
+ Dist: android.Dist{
+ Targets: []string{"droidcore-unbundled"},
+ Dest: proptools.StringPtr("build.prop-vendor"),
+ },
+ Licenses: []string{"Android-Apache-2.0"},
}
vendorBuildProp := ctx.CreateModule(
android.BuildPropFactory,
vendorBuildProps,
)
- vendorBuildProp.HideFromMake()
+ // We don't want this to conflict with the make-built vendor build.prop, but unfortunately
+ // calling HideFromMake() prevents disting files, even in soong-only mode. So only call
+ // HideFromMake() on soong+make builds.
+ if ctx.Config().KatiEnabled() {
+ vendorBuildProp.HideFromMake()
+ }
+}
+
+func createRecoveryBuildProp(ctx android.LoadHookContext) string {
+ moduleName := generatedModuleName(ctx.Config(), "recovery-prop.default")
+
+ var vendorBuildProp *string
+ if ctx.DeviceConfig().BuildingVendorImage() && ctx.DeviceConfig().VendorPath() == "vendor" {
+ vendorBuildProp = proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "vendor-build.prop"))
+ }
+
+ recoveryBuildProps := &struct {
+ Name *string
+ System_build_prop *string
+ Vendor_build_prop *string
+ Odm_build_prop *string
+ Product_build_prop *string
+ System_ext_build_prop *string
+
+ Recovery *bool
+ No_full_install *bool
+ Visibility []string
+ }{
+ Name: proptools.StringPtr(moduleName),
+ System_build_prop: proptools.StringPtr(":system-build.prop"),
+ Vendor_build_prop: vendorBuildProp,
+ Odm_build_prop: proptools.StringPtr(":odm-build.prop"),
+ Product_build_prop: proptools.StringPtr(":product-build.prop"),
+ System_ext_build_prop: proptools.StringPtr(":system_ext-build.prop"),
+
+ Recovery: proptools.BoolPtr(true),
+ No_full_install: proptools.BoolPtr(true),
+ Visibility: []string{"//visibility:public"},
+ }
+
+ ctx.CreateModule(android.RecoveryBuildPropModuleFactory, recoveryBuildProps)
+
+ return moduleName
}
// createLinkerConfigSourceFilegroups creates filegroup modules to generate linker.config.pb for the following partitions
@@ -745,7 +976,7 @@
}
}
-func generateFsProps(ctx android.EarlyModuleContext, partitionType string) (*filesystem.FilesystemProperties, bool) {
+func generateFsProps(ctx android.EarlyModuleContext, partitions allGeneratedPartitionData, partitionType string) (*filesystem.FilesystemProperties, bool) {
fsProps := &filesystem.FilesystemProperties{}
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
@@ -789,6 +1020,8 @@
fsProps.Avb_algorithm = avbInfo.avbAlgorithm
// BOARD_AVB_SYSTEM_ROLLBACK_INDEX
fsProps.Rollback_index = avbInfo.avbRollbackIndex
+ // BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION
+ fsProps.Rollback_index_location = avbInfo.avbRollbackIndexLocation
fsProps.Avb_hash_algorithm = avbInfo.avbHashAlgorithm
fsProps.Partition_name = proptools.StringPtr(partitionType)
@@ -801,20 +1034,30 @@
}
fsProps.Is_auto_generated = proptools.BoolPtr(true)
+ if partitionType != "system" {
+ mountPoint := proptools.StringPtr(partitionType)
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/tools/releasetools/build_image.py;l=1012;drc=3f576a753594bad3fc838ccb8b1b72f7efac1d50
+ if partitionType == "userdata" {
+ mountPoint = proptools.StringPtr("data")
+ }
+ fsProps.Mount_point = mountPoint
- partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType)
+ }
+
+ partitionSpecificFsProps(ctx, partitions, fsProps, partitionType)
return fsProps, true
}
type avbInfo struct {
- avbEnable *bool
- avbKeyPath *string
- avbkeyFilegroup *string
- avbAlgorithm *string
- avbRollbackIndex *int64
- avbMode *string
- avbHashAlgorithm *string
+ avbEnable *bool
+ avbKeyPath *string
+ avbkeyFilegroup *string
+ avbAlgorithm *string
+ avbRollbackIndex *int64
+ avbRollbackIndexLocation *int64
+ avbMode *string
+ avbHashAlgorithm *string
}
func getAvbInfo(config android.Config, partitionType string) avbInfo {
@@ -854,12 +1097,12 @@
}
result.avbRollbackIndex = &parsed
}
- if specificPartitionVars.BoardAvbRollbackIndex != "" {
- parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64)
+ if specificPartitionVars.BoardAvbRollbackIndexLocation != "" {
+ parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndexLocation, 10, 64)
if err != nil {
- panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex))
+ panic(fmt.Sprintf("Rollback index location must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndexLocation))
}
- result.avbRollbackIndex = &parsed
+ result.avbRollbackIndexLocation = &parsed
}
// Make allows you to pass arbitrary arguments to avbtool via this variable, but in practice
@@ -881,12 +1124,12 @@
return result
}
-func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string) android.Path {
- partitionModuleName := generatedModuleNameForPartition(ctx.Config(), partitionType)
- systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
- filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider)
+func (f *filesystemCreator) createFileListDiffTest(ctx android.ModuleContext, partitionType string, partitionModuleName string) android.Path {
+ partitionImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
+ filesystemInfo, ok := android.OtherModuleProvider(ctx, partitionImage, filesystem.FilesystemProvider)
if !ok {
ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName)
+ return nil
}
makeFileList := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partitionType))
diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", partitionModuleName))
@@ -939,16 +1182,16 @@
builder.Build("diff test "+diffTestResultFile.String(), "diff test")
}
-type systemImageDepTagType struct {
+type imageDepTagType struct {
blueprint.BaseDependencyTag
}
-var generatedFilesystemDepTag systemImageDepTagType
-var generatedVbmetaPartitionDepTag systemImageDepTagType
+var generatedFilesystemDepTag imageDepTagType
+var generatedVbmetaPartitionDepTag imageDepTagType
func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
- for _, partitionType := range f.properties.Generated_partition_types {
- ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, generatedModuleNameForPartition(ctx.Config(), partitionType))
+ for _, name := range ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions.names() {
+ ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, name)
}
for _, vbmetaModule := range f.properties.Vbmeta_module_names {
ctx.AddDependency(ctx.Module(), generatedVbmetaPartitionDepTag, vbmetaModule)
@@ -961,9 +1204,11 @@
}
f.HideFromMake()
+ partitions := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions
+
var content strings.Builder
generatedBp := android.PathForModuleOut(ctx, "soong_generated_product_config.bp")
- for _, partition := range ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions {
+ for _, partition := range partitions.types() {
content.WriteString(generateBpContent(ctx, partition))
content.WriteString("\n")
}
@@ -971,13 +1216,17 @@
ctx.Phony("product_config_to_bp", generatedBp)
+ if !ctx.Config().KatiEnabled() {
+ // Cannot diff since the kati packaging rules will not be created.
+ return
+ }
var diffTestFiles []android.Path
- for _, partitionType := range f.properties.Generated_partition_types {
- diffTestFile := f.createFileListDiffTest(ctx, partitionType)
+ for _, partitionType := range partitions.types() {
+ diffTestFile := f.createFileListDiffTest(ctx, partitionType, partitions.nameForType(partitionType))
diffTestFiles = append(diffTestFiles, diffTestFile)
ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
}
- for _, partitionType := range f.properties.Unsupported_partition_types {
+ for _, partitionType := range slices.Concat(partitions.unsupportedTypes(), f.properties.Unsupported_partition_types) {
diffTestFile := createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType))
diffTestFiles = append(diffTestFiles, diffTestFile)
ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
@@ -1023,13 +1272,13 @@
}
func generateBpContent(ctx android.EarlyModuleContext, partitionType string) string {
- fsProps, fsTypeSupported := generateFsProps(ctx, partitionType)
+ fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+ fsProps, fsTypeSupported := generateFsProps(ctx, fsGenState.soongGeneratedPartitions, partitionType)
if !fsTypeSupported {
return ""
}
baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
- fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
deps := fsGenState.fsDeps[partitionType]
highPriorityDeps := fsGenState.generatedPrebuiltEtcModuleNames
depProps := generateDepStruct(*deps, highPriorityDeps)
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 97c890d..2c4d3c8 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -15,17 +15,29 @@
package fsgen
import (
+ "strings"
+ "testing"
+
"android/soong/android"
"android/soong/etc"
"android/soong/filesystem"
"android/soong/java"
- "testing"
"github.com/google/blueprint/proptools"
)
var prepareForTestWithFsgenBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
+var prepareMockRamdiksNodeList = android.FixtureMergeMockFs(android.MockFS{
+ "ramdisk_node_list/ramdisk_node_list": nil,
+ "ramdisk_node_list/Android.bp": []byte(`
+ filegroup {
+ name: "ramdisk_node_list",
+ srcs: ["ramdisk_node_list"],
+ }
+ `),
+})
+
func TestFileSystemCreatorSystemImageProps(t *testing.T) {
result := android.GroupFixturePreparers(
android.PrepareForIntegrationTestWithAndroid,
@@ -45,6 +57,7 @@
},
}
}),
+ prepareMockRamdiksNodeList,
android.FixtureMergeMockFs(android.MockFS{
"external/avb/test/data/testkey_rsa4096.pem": nil,
"external/avb/test/Android.bp": []byte(`
@@ -61,7 +74,7 @@
}),
).RunTest(t)
- fooSystem := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().(interface {
+ fooSystem := result.ModuleForTests(t, "test_product_generated_system_image", "android_common").Module().(interface {
FsProps() filesystem.FilesystemProperties
})
android.AssertBoolEquals(
@@ -114,6 +127,7 @@
},
}
}),
+ prepareMockRamdiksNodeList,
android.FixtureMergeMockFs(android.MockFS{
"external/avb/test/data/testkey_rsa4096.pem": nil,
"build/soong/fsgen/Android.bp": []byte(`
@@ -170,6 +184,7 @@
}
}),
android.PrepareForNativeBridgeEnabled,
+ prepareMockRamdiksNodeList,
android.FixtureMergeMockFs(android.MockFS{
"external/avb/test/data/testkey_rsa4096.pem": nil,
"build/soong/fsgen/Android.bp": []byte(`
@@ -198,14 +213,14 @@
).RunTest(t)
var packagingProps android.PackagingProperties
- for _, prop := range result.ModuleForTests("test_product_generated_system_image", "android_common").Module().GetProperties() {
+ for _, prop := range result.ModuleForTests(t, "test_product_generated_system_image", "android_common").Module().GetProperties() {
if packagingPropStruct, ok := prop.(*android.PackagingProperties); ok {
packagingProps = *packagingPropStruct
}
}
moduleDeps := packagingProps.Multilib.Lib64.Deps
- eval := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ eval := result.ModuleForTests(t, "test_product_generated_system_image", "android_common").Module().ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
android.AssertStringListContains(
t,
"Generated system image expected to depend on \"bar\" defined in \"a/b\" namespace",
@@ -227,6 +242,7 @@
android.PrepareForTestWithAllowMissingDependencies,
prepareForTestWithFsgenBuildComponents,
java.PrepareForTestWithJavaBuildComponents,
+ prepareMockRamdiksNodeList,
android.FixtureMergeMockFs(android.MockFS{
"external/avb/test/data/testkey_rsa4096.pem": nil,
"build/soong/fsgen/Android.bp": []byte(`
@@ -273,6 +289,10 @@
"device/sample/etc/apns-full-conf.xml:product/etc/apns-conf-2.xml",
"device/sample/etc/apns-full-conf.xml:system/foo/file.txt",
"device/sample/etc/apns-full-conf.xml:system/foo/apns-full-conf.xml",
+ "device/sample/firmware/firmware.bin:recovery/root/firmware.bin",
+ "device/sample/firmware/firmware.bin:recovery/root/firmware-2.bin",
+ "device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware.bin",
+ "device/sample/firmware/firmware.bin:recovery/root/lib/firmware/firmware-2.bin",
}
config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
map[string]android.PartitionQualifiedVariablesType{
@@ -281,6 +301,7 @@
},
}
}),
+ prepareMockRamdiksNodeList,
android.FixtureMergeMockFs(android.MockFS{
"external/avb/test/data/testkey_rsa4096.pem": nil,
"build/soong/fsgen/Android.bp": []byte(`
@@ -292,22 +313,23 @@
"frameworks/base/data/keyboards/Vendor_0079_Product_0011.kl": nil,
"frameworks/base/data/keyboards/Vendor_0079_Product_18d4.kl": nil,
"device/sample/etc/apns-full-conf.xml": nil,
+ "device/sample/firmware/firmware.bin": nil,
}),
).RunTest(t)
- checkModuleProp := func(m android.Module, matcher func(actual interface{}) bool) bool {
+ getModuleProp := func(m android.Module, matcher func(actual interface{}) string) string {
for _, prop := range m.GetProperties() {
- if matcher(prop) {
- return true
+ if str := matcher(prop); str != "" {
+ return str
}
}
- return false
+ return ""
}
// check generated prebuilt_* module type install path and install partition
- generatedModule := result.ModuleForTests("system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module()
- etcModule, _ := generatedModule.(*etc.PrebuiltEtc)
+ generatedModule := result.ModuleForTests(t, "system-frameworks_base_config-etc-0", "android_arm64_armv8-a").Module()
+ etcModule := generatedModule.(*etc.PrebuiltEtc)
android.AssertStringEquals(
t,
"module expected to have etc install path",
@@ -324,8 +346,8 @@
)
// check generated prebuilt_* module specifies correct relative_install_path property
- generatedModule = result.ModuleForTests("system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module()
- etcModule, _ = generatedModule.(*etc.PrebuiltEtc)
+ generatedModule = result.ModuleForTests(t, "system-frameworks_base_data_keyboards-usr_keylayout_subdir-0", "android_arm64_armv8-a").Module()
+ etcModule = generatedModule.(*etc.PrebuiltEtc)
android.AssertStringEquals(
t,
"module expected to set correct relative_install_path properties",
@@ -333,73 +355,308 @@
etcModule.SubDir(),
)
+ // check that generated prebuilt_* module sets correct srcs
+ eval := generatedModule.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct srcs property",
+ "Vendor_0079_Product_0011.kl",
+ getModuleProp(generatedModule, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
+ srcs := p.Srcs.GetOrDefault(eval, nil)
+ if len(srcs) == 2 {
+ return srcs[0]
+ }
+ }
+ return ""
+ }),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct srcs property",
+ "Vendor_0079_Product_18d4.kl",
+ getModuleProp(generatedModule, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
+ srcs := p.Srcs.GetOrDefault(eval, nil)
+ if len(srcs) == 2 {
+ return srcs[1]
+ }
+ }
+ return ""
+ }),
+ )
+
// check that prebuilt_* module is not generated for non existing source file
- android.AssertPanicMessageContains(
+ android.AssertStringEquals(
t,
"prebuilt_* module not generated for non existing source file",
- "failed to find module \"system-some_non_existing-etc-0\"",
- func() { result.ModuleForTests("system-some_non_existing-etc-0", "android_arm64_armv8-a") },
+ "",
+ strings.Join(result.ModuleVariantsForTests("system-some_non_existing-etc-0"), ","),
)
// check that duplicate src file can exist in PRODUCT_COPY_FILES and generates separate modules
- generatedModule0 := result.ModuleForTests("product-device_sample_etc-etc-0", "android_arm64_armv8-a").Module()
- generatedModule1 := result.ModuleForTests("product-device_sample_etc-etc-1", "android_arm64_armv8-a").Module()
+ generatedModule0 := result.ModuleForTests(t, "product-device_sample_etc-etc-0", "android_arm64_armv8-a").Module()
+ generatedModule1 := result.ModuleForTests(t, "product-device_sample_etc-etc-1", "android_arm64_armv8-a").Module()
// check that generated prebuilt_* module sets correct srcs and dsts property
- eval := generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
- android.AssertBoolEquals(
+ eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
t,
"module expected to set correct srcs property",
- true,
- checkModuleProp(generatedModule0, func(actual interface{}) bool {
+ "apns-full-conf.xml",
+ getModuleProp(generatedModule0, func(actual interface{}) string {
if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
srcs := p.Srcs.GetOrDefault(eval, nil)
- return len(srcs) == 1 &&
- srcs[0] == "apns-full-conf.xml"
+ if len(srcs) == 1 {
+ return srcs[0]
+ }
}
- return false
+ return ""
}),
)
- android.AssertBoolEquals(
+ android.AssertStringEquals(
t,
"module expected to set correct dsts property",
- true,
- checkModuleProp(generatedModule0, func(actual interface{}) bool {
+ "apns-conf.xml",
+ getModuleProp(generatedModule0, func(actual interface{}) string {
if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
dsts := p.Dsts.GetOrDefault(eval, nil)
- return len(dsts) == 1 &&
- dsts[0] == "apns-conf.xml"
+ if len(dsts) == 1 {
+ return dsts[0]
+ }
}
- return false
+ return ""
}),
)
// check that generated prebuilt_* module sets correct srcs and dsts property
eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
- android.AssertBoolEquals(
+ android.AssertStringEquals(
t,
"module expected to set correct srcs property",
- true,
- checkModuleProp(generatedModule1, func(actual interface{}) bool {
+ "apns-full-conf.xml",
+ getModuleProp(generatedModule1, func(actual interface{}) string {
if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
srcs := p.Srcs.GetOrDefault(eval, nil)
- return len(srcs) == 1 &&
- srcs[0] == "apns-full-conf.xml"
+ if len(srcs) == 1 {
+ return srcs[0]
+ }
}
- return false
+ return ""
}),
)
- android.AssertBoolEquals(
+ android.AssertStringEquals(
t,
"module expected to set correct dsts property",
- true,
- checkModuleProp(generatedModule1, func(actual interface{}) bool {
+ "apns-conf-2.xml",
+ getModuleProp(generatedModule1, func(actual interface{}) string {
if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
dsts := p.Dsts.GetOrDefault(eval, nil)
- return len(dsts) == 1 &&
- dsts[0] == "apns-conf-2.xml"
+ if len(dsts) == 1 {
+ return dsts[0]
+ }
}
- return false
+ return ""
+ }),
+ )
+
+ generatedModule0 = result.ModuleForTests(t, "system-device_sample_etc-foo-0", "android_common").Module()
+ generatedModule1 = result.ModuleForTests(t, "system-device_sample_etc-foo-1", "android_common").Module()
+
+ // check that generated prebuilt_* module sets correct srcs and dsts property
+ eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct srcs property",
+ "apns-full-conf.xml",
+ getModuleProp(generatedModule0, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
+ srcs := p.Srcs.GetOrDefault(eval, nil)
+ if len(srcs) == 1 {
+ return srcs[0]
+ }
+ }
+ return ""
+ }),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct dsts property",
+ "foo/file.txt",
+ getModuleProp(generatedModule0, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ if len(dsts) == 1 {
+ return dsts[0]
+ }
+ }
+ return ""
+ }),
+ )
+
+ // check generated prebuilt_* module specifies correct install path and relative install path
+ etcModule = generatedModule1.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to have . install path",
+ ".",
+ etcModule.BaseDir(),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct relative_install_path properties",
+ "foo",
+ etcModule.SubDir(),
+ )
+
+ // check that generated prebuilt_* module sets correct srcs
+ eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct srcs property",
+ "apns-full-conf.xml",
+ getModuleProp(generatedModule1, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltEtcProperties); ok {
+ srcs := p.Srcs.GetOrDefault(eval, nil)
+ if len(srcs) == 1 {
+ return srcs[0]
+ }
+ }
+ return ""
+ }),
+ )
+
+ generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-0", "android_recovery_arm64_armv8-a").Module()
+ generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-1", "android_recovery_common").Module()
+
+ // check generated prebuilt_* module specifies correct install path and relative install path
+ etcModule = generatedModule0.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to have . install path",
+ ".",
+ etcModule.BaseDir(),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set empty relative_install_path properties",
+ "",
+ etcModule.SubDir(),
+ )
+
+ // check that generated prebuilt_* module don't set dsts
+ eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to not set dsts property",
+ "",
+ getModuleProp(generatedModule0, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ if len(dsts) != 0 {
+ return dsts[0]
+ }
+ }
+ return ""
+ }),
+ )
+
+ // check generated prebuilt_* module specifies correct install path and relative install path
+ etcModule = generatedModule1.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to have . install path",
+ ".",
+ etcModule.BaseDir(),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set empty relative_install_path properties",
+ "",
+ etcModule.SubDir(),
+ )
+
+ // check that generated prebuilt_* module sets correct dsts
+ eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct dsts property",
+ "firmware-2.bin",
+ getModuleProp(generatedModule1, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ if len(dsts) == 1 {
+ return dsts[0]
+ }
+ }
+ return ""
+ }),
+ )
+
+ generatedModule0 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-0", "android_recovery_common").Module()
+ generatedModule1 = result.ModuleForTests(t, "recovery-device_sample_firmware-lib_firmware-1", "android_recovery_common").Module()
+
+ // check generated prebuilt_* module specifies correct install path and relative install path
+ etcModule = generatedModule0.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to have . install path",
+ ".",
+ etcModule.BaseDir(),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct relative_install_path properties",
+ "lib/firmware",
+ etcModule.SubDir(),
+ )
+
+ // check that generated prebuilt_* module sets correct srcs
+ eval = generatedModule0.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to not set dsts property",
+ "",
+ getModuleProp(generatedModule0, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ if len(dsts) != 0 {
+ return dsts[0]
+ }
+ }
+ return ""
+ }),
+ )
+
+ // check generated prebuilt_* module specifies correct install path and relative install path
+ etcModule = generatedModule1.(*etc.PrebuiltEtc)
+ android.AssertStringEquals(
+ t,
+ "module expected to have . install path",
+ ".",
+ etcModule.BaseDir(),
+ )
+ android.AssertStringEquals(
+ t,
+ "module expected to set empty relative_install_path properties",
+ "",
+ etcModule.SubDir(),
+ )
+
+ // check that generated prebuilt_* module sets correct srcs
+ eval = generatedModule1.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
+ android.AssertStringEquals(
+ t,
+ "module expected to set correct dsts property",
+ "lib/firmware/firmware-2.bin",
+ getModuleProp(generatedModule1, func(actual interface{}) string {
+ if p, ok := actual.(*etc.PrebuiltDstsProperties); ok {
+ dsts := p.Dsts.GetOrDefault(eval, nil)
+ if len(dsts) == 1 {
+ return dsts[0]
+ }
+ }
+ return ""
}),
)
}
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index f0a54db..4f3d2a7 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -60,8 +60,8 @@
depCandidates []string
// Map of names of partition to the information of modules to be added as deps
fsDeps map[string]*multilibDeps
- // List of name of partitions to be generated by the filesystem_creator module
- soongGeneratedPartitions []string
+ // Information about the main soong-generated partitions
+ soongGeneratedPartitions allGeneratedPartitionData
// Mutex to protect the fsDeps
fsDepsMutex sync.Mutex
// Map of _all_ soong module names to their corresponding installation properties
@@ -105,12 +105,14 @@
"libgsi": defaultDepCandidateProps(ctx.Config()),
"llndk.libraries.txt": defaultDepCandidateProps(ctx.Config()),
"logpersist.start": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_system": defaultDepCandidateProps(ctx.Config()),
"update_engine_sideload": defaultDepCandidateProps(ctx.Config()),
// keep-sorted end
},
"vendor": {
"fs_config_files_vendor": defaultDepCandidateProps(ctx.Config()),
"fs_config_dirs_vendor": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_vendor": defaultDepCandidateProps(ctx.Config()),
generatedModuleName(ctx.Config(), "vendor-build.prop"): defaultDepCandidateProps(ctx.Config()),
},
"odm": {
@@ -118,39 +120,62 @@
// https://cs.android.com/android/_/android/platform/build/+/e4849e87ab660b59a6501b3928693db065ee873b:tools/fs_config/Android.mk;l=34;drc=8d6481b92c4b4e9b9f31a61545b6862090fcc14b;bpv=1;bpt=0
"fs_config_files_odm": defaultDepCandidateProps(ctx.Config()),
"fs_config_dirs_odm": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_odm": defaultDepCandidateProps(ctx.Config()),
},
- "product": {},
+ "product": {
+ "notice_xml_product": defaultDepCandidateProps(ctx.Config()),
+ },
"system_ext": {
// VNDK apexes are automatically included.
// This hardcoded list will need to be updated if `PRODUCT_EXTRA_VNDK_VERSIONS` is updated.
// https://cs.android.com/android/_/android/platform/build/+/adba533072b00c53ac0f198c550a3cbd7a00e4cd:core/main.mk;l=984;bpv=1;bpt=0;drc=174db7b179592cf07cbfd2adb0119486fda911e7
- "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()),
- "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v30": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v31": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v32": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v33": defaultDepCandidateProps(ctx.Config()),
+ "com.android.vndk.v34": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_system_ext": defaultDepCandidateProps(ctx.Config()),
},
"userdata": {},
"system_dlkm": {
// these are phony required deps of the phony fs_config_dirs_nonsystem
"fs_config_dirs_system_dlkm": defaultDepCandidateProps(ctx.Config()),
"fs_config_files_system_dlkm": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_system_dlkm": defaultDepCandidateProps(ctx.Config()),
// build props are automatically added to `ALL_DEFAULT_INSTALLED_MODULES`
"system_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()),
},
"vendor_dlkm": {
"fs_config_dirs_vendor_dlkm": defaultDepCandidateProps(ctx.Config()),
"fs_config_files_vendor_dlkm": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_vendor_dlkm": defaultDepCandidateProps(ctx.Config()),
"vendor_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()),
},
"odm_dlkm": {
"fs_config_dirs_odm_dlkm": defaultDepCandidateProps(ctx.Config()),
"fs_config_files_odm_dlkm": defaultDepCandidateProps(ctx.Config()),
+ "notice_xml_odm_dlkm": defaultDepCandidateProps(ctx.Config()),
"odm_dlkm-build.prop": defaultDepCandidateProps(ctx.Config()),
},
"ramdisk": {},
"vendor_ramdisk": {},
- "recovery": {},
+ "recovery": {
+ "sepolicy.recovery": defaultDepCandidateProps(ctx.Config()),
+ "plat_file_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "plat_service_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "plat_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "system_ext_file_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "system_ext_service_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "system_ext_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "vendor_file_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "vendor_service_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "vendor_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "odm_file_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "odm_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "product_file_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "product_service_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ "product_property_contexts.recovery": defaultDepCandidateProps(ctx.Config()),
+ },
},
fsDepsMutex: sync.Mutex{},
moduleToInstallationProps: map[string]installationProperties{},
@@ -162,8 +187,14 @@
(*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config())
}
+ if len(ctx.Config().DeviceManifestFiles()) > 0 {
+ (*fsGenState.fsDeps["vendor"])["vendor_manifest.xml"] = defaultDepCandidateProps(ctx.Config())
+ }
+
// Add common resources `prebuilt_res` module as dep of recovery partition
(*fsGenState.fsDeps["recovery"])[fmt.Sprintf("recovery-resources-common-%s", getDpi(ctx))] = defaultDepCandidateProps(ctx.Config())
+ (*fsGenState.fsDeps["recovery"])[getRecoveryFontModuleName(ctx)] = defaultDepCandidateProps(ctx.Config())
+ (*fsGenState.fsDeps["recovery"])[createRecoveryBuildProp(ctx)] = defaultDepCandidateProps(ctx.Config())
return &fsGenState
}).(*FsGenState)
@@ -264,9 +295,12 @@
removeOverriddenDeps(mctx)
fsGenState := mctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
fsDeps := fsGenState.fsDeps
- soongGeneratedPartitionMap := getAllSoongGeneratedPartitionNames(mctx.Config(), fsGenState.soongGeneratedPartitions)
m := mctx.Module()
- if partition, ok := soongGeneratedPartitionMap[m.Name()]; ok {
+ if partition := fsGenState.soongGeneratedPartitions.typeForName(m.Name()); partition != "" {
+ if fsGenState.soongGeneratedPartitions.isHandwritten(m.Name()) {
+ // Handwritten image, don't modify it
+ return
+ }
depsStruct := generateDepStruct(*fsDeps[partition], fsGenState.generatedPrebuiltEtcModuleNames)
if err := proptools.AppendMatchingProperties(m.GetProperties(), depsStruct, nil); err != nil {
mctx.ModuleErrorf(err.Error())
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index 014c662..b3666a1 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -199,6 +199,7 @@
"etc/firmware": etc.PrebuiltFirmwareFactory,
"etc/firmware_8475": etc.PrebuiltFirmwareFactory,
"firmware": etc.PrebuiltFirmwareFactory,
+ "gpu": etc.PrebuiltGPUFactory,
"first_stage_ramdisk": etc.PrebuiltFirstStageRamdiskFactory,
"fonts": etc.PrebuiltFontFactory,
"framework": etc.PrebuiltFrameworkFactory,
@@ -210,10 +211,12 @@
"optee": etc.PrebuiltOpteeFactory,
"overlay": etc.PrebuiltOverlayFactory,
"priv-app": etc.PrebuiltPrivAppFactory,
+ "radio": etc.PrebuiltRadioFactory,
"sbin": etc.PrebuiltSbinFactory,
"system": etc.PrebuiltSystemFactory,
"res": etc.PrebuiltResFactory,
"rfs": etc.PrebuiltRfsFactory,
+ "tee": etc.PrebuiltTeeFactory,
"tts": etc.PrebuiltVoicepackFactory,
"tvconfig": etc.PrebuiltTvConfigFactory,
"tvservice": etc.PrebuiltTvServiceFactory,
@@ -225,6 +228,7 @@
"usr/idc": etc.PrebuiltUserIdcFactory,
"vendor": etc.PrebuiltVendorFactory,
"vendor_dlkm": etc.PrebuiltVendorDlkmFactory,
+ "vendor_overlay": etc.PrebuiltVendorOverlayFactory,
"wallpaper": etc.PrebuiltWallpaperFactory,
"wlc_upt": etc.PrebuiltWlcUptFactory,
}
@@ -334,6 +338,10 @@
propsList = append(propsList, &prebuiltInstallInRootProperties{
Install_in_root: proptools.BoolPtr(true),
})
+ // Discard any previously picked module and force it to prebuilt_{root,any} as
+ // they are the only modules allowed to specify the `install_in_root` property.
+ etcInstallPathKey = ""
+ relDestDirFromInstallDirBase = destDir
}
// Set appropriate srcs, dsts, and releative_install_path based on
@@ -355,16 +363,14 @@
}
if allCopyFileNamesUnchanged {
- // Specify relative_install_path if it is not installed in the root directory of the
- // partition
+ // Specify relative_install_path if it is not installed in the base directory of the module.
+ // In case of prebuilt_{root,any} this is equivalent to the root of the partition.
if !android.InList(relDestDirFromInstallDirBase, []string{"", "."}) {
propsList = append(propsList, &prebuiltSubdirProperties{
Relative_install_path: proptools.StringPtr(relDestDirFromInstallDirBase),
})
}
} else {
- // If dsts property has to be set and the selected module type is prebuilt_root,
- // use prebuilt_any instead.
dsts := proptools.NewConfigurable[[]string](nil, nil)
for _, installBaseFile := range installBaseFiles {
dsts.AppendSimpleValue([]string{filepath.Join(relDestDirFromInstallDirBase, installBaseFile)})
diff --git a/fsgen/super_img.go b/fsgen/super_img.go
index 8ee3bf2..1d610f6 100644
--- a/fsgen/super_img.go
+++ b/fsgen/super_img.go
@@ -19,6 +19,7 @@
"android/soong/android"
"android/soong/filesystem"
+
"github.com/google/blueprint/proptools"
)
@@ -26,21 +27,48 @@
return partitionVars.ProductBuildSuperPartition
}
-func createSuperImage(ctx android.LoadHookContext, partitions []string, partitionVars android.PartitionVariables) {
+func createSuperImage(
+ ctx android.LoadHookContext,
+ partitions allGeneratedPartitionData,
+ partitionVars android.PartitionVariables,
+ systemOtherImageName string,
+) []string {
baseProps := &struct {
Name *string
}{
- Name: proptools.StringPtr(generatedModuleName(ctx.Config(), "super")),
+ Name: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "super")),
}
superImageProps := &filesystem.SuperImageProperties{
- Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice),
- Block_devices: partitionVars.BoardSuperPartitionBlockDevices,
- Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater),
- Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions),
- Virtual_ab: proptools.BoolPtr(partitionVars.ProductVirtualAbOta),
- Virtual_ab_retrofit: proptools.BoolPtr(partitionVars.ProductVirtualAbOtaRetrofit),
- Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions),
+ Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice),
+ Block_devices: partitionVars.BoardSuperPartitionBlockDevices,
+ Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater),
+ Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions),
+ Use_dynamic_partitions: proptools.BoolPtr(partitionVars.ProductUseDynamicPartitions),
+ Super_image_in_update_package: proptools.BoolPtr(partitionVars.BoardSuperImageInUpdatePackage),
+ Create_super_empty: proptools.BoolPtr(partitionVars.BuildingSuperEmptyImage),
+ }
+ if partitionVars.ProductVirtualAbOta {
+ superImageProps.Virtual_ab.Enable = proptools.BoolPtr(true)
+ superImageProps.Virtual_ab.Retrofit = proptools.BoolPtr(partitionVars.ProductVirtualAbOtaRetrofit)
+ superImageProps.Virtual_ab.Compression = proptools.BoolPtr(partitionVars.ProductVirtualAbCompression)
+ if partitionVars.ProductVirtualAbCompressionMethod != "" {
+ superImageProps.Virtual_ab.Compression_method = proptools.StringPtr(partitionVars.ProductVirtualAbCompressionMethod)
+ }
+ if partitionVars.ProductVirtualAbCompressionFactor != "" {
+ factor, err := strconv.ParseInt(partitionVars.ProductVirtualAbCompressionFactor, 10, 32)
+ if err != nil {
+ ctx.ModuleErrorf("Compression factor must be an int, got %q", partitionVars.ProductVirtualAbCompressionFactor)
+ }
+ superImageProps.Virtual_ab.Compression_factor = proptools.Int64Ptr(factor)
+ }
+ if partitionVars.ProductVirtualAbCowVersion != "" {
+ version, err := strconv.ParseInt(partitionVars.ProductVirtualAbCowVersion, 10, 32)
+ if err != nil {
+ ctx.ModuleErrorf("COW version must be an int, got %q", partitionVars.ProductVirtualAbCowVersion)
+ }
+ superImageProps.Virtual_ab.Cow_version = proptools.Int64Ptr(version)
+ }
}
size, _ := strconv.ParseInt(partitionVars.BoardSuperPartitionSize, 10, 64)
superImageProps.Size = proptools.Int64Ptr(size)
@@ -58,34 +86,49 @@
}
superImageProps.Partition_groups = partitionGroupsInfo
+ if systemOtherImageName != "" {
+ superImageProps.System_other_partition = proptools.StringPtr(systemOtherImageName)
+ }
+
+ var superImageSubpartitions []string
partitionNameProps := &filesystem.SuperImagePartitionNameProperties{}
- if android.InList("system", partitions) {
- partitionNameProps.System_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
+ if modName := partitions.nameForType("system"); modName != "" {
+ partitionNameProps.System_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "system")
}
- if android.InList("system_ext", partitions) {
- partitionNameProps.System_ext_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
+ if modName := partitions.nameForType("system_ext"); modName != "" {
+ partitionNameProps.System_ext_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "system_ext")
}
- if android.InList("system_dlkm", partitions) {
- partitionNameProps.System_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_dlkm"))
+ if modName := partitions.nameForType("system_dlkm"); modName != "" {
+ partitionNameProps.System_dlkm_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "system_dlkm")
}
- if android.InList("system_other", partitions) {
- partitionNameProps.System_other_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_other"))
+ if modName := partitions.nameForType("system_other"); modName != "" {
+ partitionNameProps.System_other_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "system_other")
}
- if android.InList("product", partitions) {
- partitionNameProps.Product_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
+ if modName := partitions.nameForType("product"); modName != "" {
+ partitionNameProps.Product_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "product")
}
- if android.InList("vendor", partitions) {
- partitionNameProps.Vendor_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
+ if modName := partitions.nameForType("vendor"); modName != "" {
+ partitionNameProps.Vendor_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "vendor")
}
- if android.InList("vendor_dlkm", partitions) {
- partitionNameProps.Vendor_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_dlkm"))
+ if modName := partitions.nameForType("vendor_dlkm"); modName != "" {
+ partitionNameProps.Vendor_dlkm_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "vendor_dlkm")
}
- if android.InList("odm", partitions) {
- partitionNameProps.Odm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
+ if modName := partitions.nameForType("odm"); modName != "" {
+ partitionNameProps.Odm_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "odm")
}
- if android.InList("odm_dlkm", partitions) {
- partitionNameProps.Odm_dlkm_partition = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm_dlkm"))
+ if modName := partitions.nameForType("odm_dlkm"); modName != "" {
+ partitionNameProps.Odm_dlkm_partition = proptools.StringPtr(modName)
+ superImageSubpartitions = append(superImageSubpartitions, "odm_dlkm")
}
ctx.CreateModule(filesystem.SuperImageFactory, baseProps, superImageProps, partitionNameProps)
+ return superImageSubpartitions
}
diff --git a/fsgen/util.go b/fsgen/util.go
index 9ab3ad8..008f9fe 100644
--- a/fsgen/util.go
+++ b/fsgen/util.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/filesystem"
"fmt"
"strconv"
"strings"
@@ -58,3 +59,21 @@
return recoveryDensity
}
+
+// Returns the name of the appropriate prebuilt module for installing font.png file.
+// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2536;drc=a6af369e71ded123734523ea640b97b70a557cb9
+func getRecoveryFontModuleName(ctx android.LoadHookContext) string {
+ if android.InList(getDpi(ctx), []string{"xxxhdpi", "xxhdpi", "xhdpi"}) {
+ return "recovery-fonts-18"
+ }
+ return "recovery-fonts-12"
+}
+
+// Returns a new list of symlinks with prefix added to the dest directory for all symlinks
+func symlinksWithNamePrefix(symlinks []filesystem.SymlinkDefinition, prefix string) []filesystem.SymlinkDefinition {
+ ret := make([]filesystem.SymlinkDefinition, len(symlinks))
+ for i, symlink := range symlinks {
+ ret[i] = symlink.CopyWithNamePrefix(prefix)
+ }
+ return ret
+}
diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go
index 11c5759..594c404 100644
--- a/fsgen/vbmeta_partitions.go
+++ b/fsgen/vbmeta_partitions.go
@@ -17,9 +17,7 @@
import (
"android/soong/android"
"android/soong/filesystem"
- "slices"
"strconv"
- "strings"
"github.com/google/blueprint/proptools"
)
@@ -32,6 +30,27 @@
partitionName string
}
+// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4849;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
+var avbPartitions = []string{
+ "boot",
+ "init_boot",
+ "vendor_boot",
+ "vendor_kernel_boot",
+ "system",
+ "vendor",
+ "product",
+ "system_ext",
+ "odm",
+ "vendor_dlkm",
+ "odm_dlkm",
+ "system_dlkm",
+ "dtbo",
+ "pvmfw",
+ "recovery",
+ "vbmeta_system",
+ "vbmeta_vendor",
+}
+
// Creates the vbmeta partition and the chained vbmeta partitions. Returns the list of module names
// that the function created. May return nil if the product isn't using avb.
//
@@ -43,7 +62,7 @@
// like vbmeta_system might contain the avb metadata for just a few products. In cuttlefish
// vbmeta_system contains metadata about product, system, and system_ext. Using chained partitions,
// that group of partitions can be updated independently from the other signed partitions.
-func createVbmetaPartitions(ctx android.LoadHookContext, generatedPartitionTypes []string) []vbmetaModuleInfo {
+func (f *filesystemCreator) createVbmetaPartitions(ctx android.LoadHookContext, partitions allGeneratedPartitionData) []vbmetaModuleInfo {
partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
// Some products seem to have BuildingVbmetaImage as true even when BoardAvbEnable is false
if !partitionVars.BuildingVbmetaImage || !partitionVars.BoardAvbEnable {
@@ -52,14 +71,17 @@
var result []vbmetaModuleInfo
- var chainedPartitions []string
- var partitionTypesHandledByChainedPartitions []string
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4593;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
+ var internalAvbPartitionsInChainedVbmetaImages []string
+ var chainedPartitionTypes []string
for _, chainedName := range android.SortedKeys(partitionVars.ChainedVbmetaPartitions) {
props := partitionVars.ChainedVbmetaPartitions[chainedName]
+ filesystemPartitionType := chainedName
chainedName = "vbmeta_" + chainedName
if len(props.Partitions) == 0 {
continue
}
+ internalAvbPartitionsInChainedVbmetaImages = append(internalAvbPartitionsInChainedVbmetaImages, props.Partitions...)
if len(props.Key) == 0 {
ctx.ModuleErrorf("No key found for chained avb partition %q", chainedName)
continue
@@ -92,26 +114,24 @@
var partitionModules []string
for _, partition := range props.Partitions {
- partitionTypesHandledByChainedPartitions = append(partitionTypesHandledByChainedPartitions, partition)
- if !slices.Contains(generatedPartitionTypes, partition) {
- // The partition is probably unsupported.
- continue
+ if modName := partitions.nameForType(partition); modName != "" {
+ partitionModules = append(partitionModules, modName)
}
- partitionModules = append(partitionModules, generatedModuleNameForPartition(ctx.Config(), partition))
}
- name := generatedModuleName(ctx.Config(), chainedName)
+ name := generatedModuleNameForPartition(ctx.Config(), chainedName)
ctx.CreateModuleInDirectory(
filesystem.VbmetaFactory,
".", // Create in the root directory for now so its easy to get the key
&filesystem.VbmetaProperties{
- Partition_name: proptools.StringPtr(chainedName),
- Stem: proptools.StringPtr(chainedName + ".img"),
- Private_key: proptools.StringPtr(props.Key),
- Algorithm: &props.Algorithm,
- Rollback_index: rollbackIndex,
- Rollback_index_location: &ril,
- Partitions: proptools.NewSimpleConfigurable(partitionModules),
+ Partition_name: proptools.StringPtr(chainedName),
+ Filesystem_partition_type: proptools.StringPtr(filesystemPartitionType),
+ Stem: proptools.StringPtr(chainedName + ".img"),
+ Private_key: proptools.StringPtr(props.Key),
+ Algorithm: &props.Algorithm,
+ Rollback_index: rollbackIndex,
+ Rollback_index_location: &ril,
+ Partitions: proptools.NewSimpleConfigurable(partitionModules),
}, &struct {
Name *string
}{
@@ -119,15 +139,15 @@
},
).HideFromMake()
- chainedPartitions = append(chainedPartitions, name)
-
result = append(result, vbmetaModuleInfo{
moduleName: name,
partitionName: chainedName,
})
+
+ chainedPartitionTypes = append(chainedPartitionTypes, chainedName)
}
- vbmetaModuleName := generatedModuleName(ctx.Config(), "vbmeta")
+ vbmetaModuleName := generatedModuleNameForPartition(ctx.Config(), "vbmeta")
var algorithm *string
var ri *int64
@@ -148,19 +168,83 @@
ri = &parsedRi
}
- var partitionModules []string
- for _, partitionType := range generatedPartitionTypes {
- if slices.Contains(partitionTypesHandledByChainedPartitions, partitionType) {
- // Already handled by a chained vbmeta partition
+ // --chain_partition argument is only set for partitions that set
+ // `BOARD_AVB_<partition name>_KEY_PATH` value and is not "recovery"
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4823;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
+ includeAsChainedPartitionInVbmeta := func(partition string) bool {
+ val, ok := partitionVars.PartitionQualifiedVariables[partition]
+ return ok && len(val.BoardAvbKeyPath) > 0 && partition != "recovery"
+ }
+
+ // --include_descriptors_from_image is passed if both conditions are met:
+ // - `BOARD_AVB_<partition name>_KEY_PATH` value is not set
+ // - not included in INTERNAL_AVB_PARTITIONS_IN_CHAINED_VBMETA_IMAGES
+ // for partitions that set INSTALLED_<partition name>IMAGE_TARGET
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4827;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
+ includeAsIncludedPartitionInVbmeta := func(partition string) bool {
+ if android.InList(partition, internalAvbPartitionsInChainedVbmetaImages) {
+ // Already handled by chained vbmeta partitions
+ return false
+ }
+ partitionQualifiedVars := partitionVars.PartitionQualifiedVariables[partition]
+
+ // The return logic in the switch cases below are identical to
+ // ifdef INSTALLED_<partition name>IMAGE_TARGET
+ switch partition {
+ case "boot":
+ return partitionQualifiedVars.BuildingImage || partitionQualifiedVars.PrebuiltImage || partitionVars.BoardUsesRecoveryAsBoot
+ case "vendor_kernel_boot", "dtbo":
+ return partitionQualifiedVars.PrebuiltImage
+ case "system":
+ return partitionQualifiedVars.BuildingImage
+ case "init_boot", "vendor_boot", "vendor", "product", "system_ext", "odm", "vendor_dlkm", "odm_dlkm", "system_dlkm":
+ return partitionQualifiedVars.BuildingImage || partitionQualifiedVars.PrebuiltImage
+ // TODO: Import BOARD_USES_PVMFWIMAGE
+ // ifeq ($(BOARD_USES_PVMFWIMAGE),true)
+ // case "pvmfw":
+ case "recovery":
+ // ifdef INSTALLED_RECOVERYIMAGE_TARGET
+ return !ctx.DeviceConfig().BoardUsesRecoveryAsBoot() && !ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot()
+ // Technically these partitions are determined based on len(BOARD_AVB_VBMETA_SYSTEM) and
+ // len(BOARD_AVB_VBMETA_VENDOR) but if these are non empty these partitions are
+ // already included in the chained partitions.
+ case "vbmeta_system", "vbmeta_vendor":
+ return false
+ default:
+ return false
+ }
+ }
+
+ var chainedPartitionModules []string
+ var includePartitionModules []string
+ allGeneratedPartitionTypes := append(partitions.types(),
+ chainedPartitionTypes...,
+ )
+ if len(f.properties.Boot_image) > 0 {
+ allGeneratedPartitionTypes = append(allGeneratedPartitionTypes, "boot")
+ }
+ if len(f.properties.Init_boot_image) > 0 {
+ allGeneratedPartitionTypes = append(allGeneratedPartitionTypes, "init_boot")
+ }
+ if len(f.properties.Vendor_boot_image) > 0 {
+ allGeneratedPartitionTypes = append(allGeneratedPartitionTypes, "vendor_boot")
+ }
+
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=4919;drc=62e20f0d218f60bae563b4ee742d88cca1fc1901
+ for _, partitionType := range android.SortedUniqueStrings(append(avbPartitions, chainedPartitionTypes...)) {
+ if !android.InList(partitionType, allGeneratedPartitionTypes) {
+ // Skip if the partition is not auto generated
continue
}
- if strings.Contains(partitionType, "ramdisk") || strings.Contains(partitionType, "boot") {
- // ramdisk is never signed with avb information
- // boot partitions just have the avb footer, and don't have a corresponding vbmeta
- // partition.
- continue
+ name := partitions.nameForType(partitionType)
+ if name == "" {
+ name = generatedModuleNameForPartition(ctx.Config(), partitionType)
}
- partitionModules = append(partitionModules, generatedModuleNameForPartition(ctx.Config(), partitionType))
+ if includeAsChainedPartitionInVbmeta(partitionType) {
+ chainedPartitionModules = append(chainedPartitionModules, name)
+ } else if includeAsIncludedPartitionInVbmeta(partitionType) {
+ includePartitionModules = append(includePartitionModules, name)
+ }
}
ctx.CreateModuleInDirectory(
@@ -171,8 +255,9 @@
Algorithm: algorithm,
Private_key: key,
Rollback_index: ri,
- Chained_partitions: chainedPartitions,
- Partitions: proptools.NewSimpleConfigurable(partitionModules),
+ Chained_partitions: chainedPartitionModules,
+ Partitions: proptools.NewSimpleConfigurable(includePartitionModules),
+ Partition_name: proptools.StringPtr("vbmeta"),
}, &struct {
Name *string
}{
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index aa393a2..f08378d 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -22,6 +22,7 @@
"sort"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -309,14 +310,14 @@
return false
}
-func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool {
- var config = fuzzModule.FuzzProperties.Fuzz_config
+func IsValidConfig(fuzzModule *FuzzPackagedModuleInfo, moduleName string) bool {
+ var config = fuzzModule.FuzzConfig
if config != nil {
if !config.Vector.isValidVector() {
panic(fmt.Errorf("Invalid vector in fuzz config in %s", moduleName))
}
- if !config.Service_privilege.isValidServicePrivilege() {
+ if !config.ServicePrivilege.isValidServicePrivilege() {
panic(fmt.Errorf("Invalid service_privilege in fuzz config in %s", moduleName))
}
@@ -324,15 +325,15 @@
panic(fmt.Errorf("Invalid users (user_data) in fuzz config in %s", moduleName))
}
- if !config.Fuzzed_code_usage.isValidFuzzedCodeUsage() {
+ if !config.FuzzedCodeUsage.isValidFuzzedCodeUsage() {
panic(fmt.Errorf("Invalid fuzzed_code_usage in fuzz config in %s", moduleName))
}
- if !config.Automatically_route_to.isValidAutomaticallyRouteTo() {
+ if !config.AutomaticallyRouteTo.isValidAutomaticallyRouteTo() {
panic(fmt.Errorf("Invalid automatically_route_to in fuzz config in %s", moduleName))
}
- if !config.Use_platform_libs.isValidUsePlatformLibs() {
+ if !config.UsePlatformLibs.isValidUsePlatformLibs() {
panic(fmt.Errorf("Invalid use_platform_libs in fuzz config in %s", moduleName))
}
}
@@ -419,6 +420,20 @@
// Optional list of data files to be installed to the fuzz target's output
// directory. Directory structure relative to the module is preserved.
Data []string `android:"path"`
+ // Same as data, but adds dependencies on modules using the device's os variant, and common
+ // architecture's variant. Can be useful to add device-built apps to the data of a host
+ // test.
+ Device_common_data []string `android:"path_device_common"`
+ // Same as data, but adds dependencies on modules using the device's os variant, and the
+ // device's first architecture's variant. Can be useful to add device-built apps to the data
+ // of a host test.
+ Device_first_data []string `android:"path_device_first"`
+
+ // Same as data, but will add dependencies on modules using the host's os variation and
+ // the common arch variation. Useful for a device test that wants to depend on a host
+ // module, for example to include a custom Tradefed test runner.
+ Host_common_data []string `android:"path_host_common"`
+
// Optional dictionary to be installed to the fuzz target's output directory.
Dictionary *string `android:"path"`
// Define the fuzzing frameworks this fuzz target can be built for. If
@@ -437,6 +452,62 @@
Data android.Paths
}
+type FuzzConfigInfo struct {
+ Vector Vector
+ // How privileged the service being fuzzed is.
+ ServicePrivilege ServicePrivilege
+ // Whether the service being fuzzed handles data from multiple users or only
+ // a single one.
+ Users UserData
+ // Specifies the use state of the code being fuzzed. This state factors into
+ // how an issue is handled.
+ FuzzedCodeUsage FuzzedCodeUsage
+ // Which team to route this to, if it should be routed automatically.
+ AutomaticallyRouteTo AutomaticallyRouteTo
+ // Specifies libs used to initialize ART (java only, 'use_none' for no initialization)
+ UsePlatformLibs UsePlatformLibs
+ // Specify whether to enable continuous fuzzing on devices. Defaults to true.
+ FuzzOnHaikuDevice bool
+ // Specify whether to enable continuous fuzzing on host. Defaults to true.
+ FuzzOnHaikuHost bool
+ // Specifies whether fuzz target should check presubmitted code changes for crashes.
+ // Defaults to false.
+ UseForPresubmit bool
+}
+type FuzzPackagedModuleInfo struct {
+ FuzzConfig *FuzzConfigInfo
+ Dictionary android.Path
+ Corpus android.Paths
+ Config android.Path
+ Data android.Paths
+}
+
+var FuzzPackagedModuleInfoProvider = blueprint.NewProvider[FuzzPackagedModuleInfo]()
+
+func SetFuzzPackagedModuleInfo(ctx android.ModuleContext, fm *FuzzPackagedModule) {
+ info := FuzzPackagedModuleInfo{
+ Dictionary: fm.Dictionary,
+ Config: fm.Config,
+ Corpus: fm.Corpus,
+ Data: fm.Data,
+ }
+ if fm.FuzzProperties.Fuzz_config != nil {
+ info.FuzzConfig = &FuzzConfigInfo{
+ Vector: fm.FuzzProperties.Fuzz_config.Vector,
+ ServicePrivilege: fm.FuzzProperties.Fuzz_config.Service_privilege,
+ Users: fm.FuzzProperties.Fuzz_config.Users,
+ FuzzedCodeUsage: fm.FuzzProperties.Fuzz_config.Fuzzed_code_usage,
+ AutomaticallyRouteTo: fm.FuzzProperties.Fuzz_config.Automatically_route_to,
+ FuzzOnHaikuDevice: BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_device, true),
+ FuzzOnHaikuHost: BoolDefault(fm.FuzzProperties.Fuzz_config.Fuzz_on_haiku_host, true),
+ UsePlatformLibs: fm.FuzzProperties.Fuzz_config.Use_platform_libs,
+ UseForPresubmit: BoolDefault(fm.FuzzProperties.Fuzz_config.Use_for_presubmit, false),
+ }
+ }
+
+ android.SetProvider(ctx, FuzzPackagedModuleInfoProvider, info)
+}
+
func GetFramework(ctx android.LoadHookContext, lang Lang) Framework {
framework := ctx.Config().Getenv("FUZZ_FRAMEWORK")
@@ -495,7 +566,9 @@
return true
}
-func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
+func (s *FuzzPackager) PackageArtifacts(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, archDir android.OutputPath, builder *android.RuleBuilder) []FileToZip {
// Package the corpora into a zipfile.
var files []FileToZip
if fuzzModule.Corpus != nil {
@@ -534,7 +607,9 @@
return files
}
-func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule FuzzPackagedModule, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
+// TODO(b/397766191): Change the signature to take ModuleProxy
+// Please only access the module's internal data through providers.
+func (s *FuzzPackager) BuildZipFile(ctx android.SingletonContext, module android.Module, fuzzModule *FuzzPackagedModuleInfo, files []FileToZip, builder *android.RuleBuilder, archDir android.OutputPath, archString string, hostOrTargetString string, archOs ArchOs, archDirs map[ArchOs][]FileToZip) ([]FileToZip, bool) {
fuzzZip := archDir.Join(ctx, module.Name()+".zip")
command := builder.Command().BuiltTool("soong_zip").
@@ -556,10 +631,10 @@
builder.Build("create-"+fuzzZip.String(),
"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
- if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
- if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
+ if config := fuzzModule.FuzzConfig; config != nil {
+ if strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuHost {
return archDirs[archOs], false
- } else if !strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_device, true) {
+ } else if !strings.Contains(hostOrTargetString, "host") && !config.FuzzOnHaikuDevice {
return archDirs[archOs], false
}
}
diff --git a/genrule/Android.bp b/genrule/Android.bp
index 49df480..b82f2a9 100644
--- a/genrule/Android.bp
+++ b/genrule/Android.bp
@@ -14,7 +14,6 @@
"soong-shared",
],
srcs: [
- "allowlists.go",
"genrule.go",
"locations.go",
],
diff --git a/genrule/genrule.go b/genrule/genrule.go
index ac62b8d..a7c09e7 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -88,9 +88,7 @@
}
type SourceFileGenerator interface {
- GeneratedSourceFiles() android.Paths
- GeneratedHeaderDirs() android.Paths
- GeneratedDeps() android.Paths
+ android.SourceFileGenerator
}
// Alias for android.HostToolProvider
@@ -114,8 +112,8 @@
func (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy(
ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
- return android.OtherModuleProviderOrDefault(
- ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt
+ return android.OtherModulePointerProviderOrDefault(
+ ctx, target, android.CommonModuleInfoProvider).ReplacedByPrebuilt
}
var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil)
@@ -283,6 +281,7 @@
"hardware/google/camera/common/hal/aidl_service:aidl_camera_build_version",
"tools/tradefederation/core:tradefed_zip",
"vendor/google/services/LyricCameraHAL/src/apex:com.google.pixel.camera.hal.manifest",
+ "vendor/google_tradefederation/core:gen_google_tradefed_zip",
// go/keep-sorted end
}
allowlistMap := make(map[string]bool, len(allowlist))
@@ -351,10 +350,10 @@
// replaced the dependency.
module := android.PrebuiltGetPreferred(ctx, proxy)
tool := ctx.OtherModuleName(module)
- if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderKey); ok {
+ if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderInfoProvider); ok {
// A HostToolProvider provides the path to a tool, which will be copied
// into the sandbox.
- if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{tool})
} else {
@@ -455,7 +454,6 @@
srcFiles = append(srcFiles, addLabelsForInputs("device_first_srcs", g.properties.Device_first_srcs.GetOrDefault(ctx, nil), nil)...)
srcFiles = append(srcFiles, addLabelsForInputs("device_common_srcs", g.properties.Device_common_srcs.GetOrDefault(ctx, nil), nil)...)
srcFiles = append(srcFiles, addLabelsForInputs("common_os_srcs", g.properties.Common_os_srcs.GetOrDefault(ctx, nil), nil)...)
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
var copyFrom android.Paths
var outputFiles android.WritablePaths
@@ -729,11 +727,8 @@
var _ android.ApexModule = (*Module)(nil)
// Implements android.ApexModule
-func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // Because generated outputs are checked by client modules(e.g. cc_library, ...)
- // we can safely ignore the check here.
- return nil
+func (m *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
func generatorFactory(taskGenerator taskFunc, props ...interface{}) *Module {
@@ -974,30 +969,9 @@
return module
}
-var sandboxingAllowlistKey = android.NewOnceKey("genruleSandboxingAllowlistKey")
-
-type sandboxingAllowlistSets struct {
- sandboxingDenyModuleSet map[string]bool
-}
-
-func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSets {
- return ctx.Config().Once(sandboxingAllowlistKey, func() interface{} {
- sandboxingDenyModuleSet := map[string]bool{}
-
- android.AddToStringSet(sandboxingDenyModuleSet, SandboxingDenyModuleList)
- return &sandboxingAllowlistSets{
- sandboxingDenyModuleSet: sandboxingDenyModuleSet,
- }
- }).(*sandboxingAllowlistSets)
-}
-
func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder {
if !ctx.DeviceConfig().GenruleSandboxing() {
return r.SandboxTools()
}
- sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
- if sandboxingAllowlistSets.sandboxingDenyModuleSet[ctx.ModuleName()] {
- return r.SandboxTools()
- }
return r.SandboxInputs()
}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index f190750..dcec297 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -24,7 +24,6 @@
"android/soong/android"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -516,7 +515,7 @@
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
- gen := result.ModuleForTests(test.name, "")
+ gen := result.ModuleForTests(t, test.name, "")
manifest := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
hash := manifest.Commands[0].GetInputHash()
@@ -644,7 +643,7 @@
ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
RunTestWithBp(t, testGenruleBp()+bp)
- mod := result.ModuleForTests("gen", "")
+ mod := result.ModuleForTests(t, "gen", "")
if expectedErrors != nil {
return
}
@@ -694,13 +693,6 @@
expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
-
- srcsFileProvider, ok := android.OtherModuleProvider(result.TestContext, gen, blueprint.SrcsFileProviderKey)
- if !ok {
- t.Fatal("Expected genrule to have a SrcsFileProviderData, but did not")
- }
- expectedSrcs := []string{"in1"}
- android.AssertDeepEquals(t, "srcs", expectedSrcs, srcsFileProvider.SrcPaths)
}
func TestGenruleAllowMissingDependencies(t *testing.T) {
@@ -727,7 +719,7 @@
ctx.SetAllowMissingDependencies(true)
})).RunTestWithBp(t, bp)
- gen := result.ModuleForTests("gen", "").Output("out")
+ gen := result.ModuleForTests(t, "gen", "").Output("out")
if gen.Rule != android.ErrorRule {
t.Errorf("Expected missing dependency error rule for gen, got %q", gen.Rule.String())
}
@@ -758,15 +750,15 @@
android.AssertPathsRelativeToTopEquals(t,
"genrule.tag with output",
[]string{"out/soong/.intermediates/gen/gen/foo"},
- result.ModuleForTests("gen_foo", "").Module().(*useSource).srcs)
+ result.ModuleForTests(t, "gen_foo", "").Module().(*useSource).srcs)
android.AssertPathsRelativeToTopEquals(t,
"genrule.tag with output in subdir",
[]string{"out/soong/.intermediates/gen/gen/sub/bar"},
- result.ModuleForTests("gen_bar", "").Module().(*useSource).srcs)
+ result.ModuleForTests(t, "gen_bar", "").Module().(*useSource).srcs)
android.AssertPathsRelativeToTopEquals(t,
"genrule.tag with all",
[]string{"out/soong/.intermediates/gen/gen/foo", "out/soong/.intermediates/gen/gen/sub/bar"},
- result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
+ result.ModuleForTests(t, "gen_all", "").Module().(*useSource).srcs)
}
func TestGenruleInterface(t *testing.T) {
diff --git a/golang/golang.go b/golang/golang.go
index d33f5e0..9e0744a 100644
--- a/golang/golang.go
+++ b/golang/golang.go
@@ -97,17 +97,16 @@
outputFile := android.PathForArbitraryOutput(ctx, android.Rel(ctx, ctx.Config().OutDir(), g.IntermediateFile())).WithoutRel()
g.outputFile = outputFile
- // Don't create install rules for modules used by bootstrap, the install command line will differ from
- // what was used during bootstrap, which will cause ninja to rebuild the module on the next run,
- // triggering reanalysis.
- if !usedByBootstrap(ctx.ModuleName()) {
- installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile)
+ installPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), outputFile)
- // Modules in an unexported namespace have no install rule, only add modules in the exported namespaces
- // to the blueprint_tools phony rules.
- if !ctx.Config().KatiEnabled() || g.ExportedToMake() {
- ctx.Phony("blueprint_tools", installPath)
- }
+ // Modules in an unexported namespace have no install rule, only add modules in the exported namespaces
+ // to the blueprint_tools phony rules.
+ if g.ExportedToMake() && !usedByBootstrap(ctx.ModuleName()) {
+ // Don't add the installed file of bootstrap tools to the deps of `blueprint_tools`.
+ // The install command line will differ from what was used during bootstrap,
+ // which will cause ninja to rebuild the module on the next run,
+ // triggering reanalysis.
+ ctx.Phony("blueprint_tools", installPath)
}
ctx.SetOutputFiles(android.Paths{outputFile}, "")
diff --git a/golang/golang_test.go b/golang/golang_test.go
index 0a4baed..89a8761 100644
--- a/golang/golang_test.go
+++ b/golang/golang_test.go
@@ -45,9 +45,9 @@
}),
).RunTestWithBp(t, bp)
- bin := result.ModuleForTests("gobin", result.Config.BuildOSTarget.String())
+ bin := result.ModuleForTests(t, "gobin", result.Config.BuildOSTarget.String())
- expected := "^out/soong/host/" + result.Config.PrebuiltOS() + "/bin/go/gobin/?[^/]*/obj/gobin$"
+ expected := "^out/host/" + result.Config.PrebuiltOS() + "/bin/go/gobin/?[^/]*/obj/gobin$"
actual := android.PathsRelativeToTop(bin.OutputFiles(result.TestContext, t, ""))
if len(actual) != 1 {
t.Fatalf("Expected 1 output file, got %v", actual)
diff --git a/java/Android.bp b/java/Android.bp
index 885e682..99d9c38 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -51,6 +51,7 @@
"gen.go",
"generated_java_library.go",
"genrule.go",
+ "genrule_combiner.go",
"hiddenapi.go",
"hiddenapi_modular.go",
"hiddenapi_monolithic.go",
@@ -77,6 +78,7 @@
"system_modules.go",
"systemserver_classpath_fragment.go",
"testing.go",
+ "tracereferences.go",
"tradefed.go",
],
testSrcs: [
@@ -95,6 +97,7 @@
"droiddoc_test.go",
"droidstubs_test.go",
"fuzz_test.go",
+ "genrule_combiner_test.go",
"genrule_test.go",
"generated_java_library_test.go",
"hiddenapi_singleton_test.go",
diff --git a/java/aar.go b/java/aar.go
index 7322b09..86c6bfa 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -217,13 +217,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, true) &&
// TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries.
- !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib") &&
- // Use the legacy resource processor in kythe builds.
- // The legacy resource processor creates an R.srcjar, which kythe can use for generating crossrefs.
- // TODO(b/354854007): Re-enable BusyBox in kythe builds
- !ctx.Config().EmitXrefRules()
+ !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib")
}
func (a *aapt) filterProduct() string {
@@ -391,8 +387,9 @@
versionName = proptools.NinjaEscape(versionName)
linkFlags = append(linkFlags, "--version-name ", versionName)
}
-
- linkFlags, compileFlags = android.FilterList(linkFlags, []string{"--legacy"})
+ // Split the flags by prefix, as --png-compression-level has the "=value" suffix.
+ linkFlags, compileFlags = android.FilterListByPrefix(linkFlags,
+ []string{"--legacy", "--png-compression-level"})
// Always set --pseudo-localize, it will be stripped out later for release
// builds that don't want it.
@@ -878,13 +875,15 @@
rroDirsDepSetBuilder := depset.NewBuilder[rroDir](depset.TOPOLOGICAL)
manifestsDepSetBuilder := depset.NewBuilder[android.Path](depset.TOPOLOGICAL)
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
depTag := ctx.OtherModuleDependencyTag(module)
var exportPackage android.Path
- aarDep, _ := module.(AndroidLibraryDependency)
- if aarDep != nil {
- exportPackage = aarDep.ExportPackage()
+ var aarDep *AndroidLibraryDependencyInfo
+ javaInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
+ if ok && javaInfo.AndroidLibraryDependencyInfo != nil {
+ aarDep = javaInfo.AndroidLibraryDependencyInfo
+ exportPackage = aarDep.ExportPackage
}
switch depTag {
@@ -892,7 +891,7 @@
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
case sdkLibTag, libTag, rroDepTag:
if exportPackage != nil {
- sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
+ sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet)
sharedLibs = append(sharedLibs, exportPackage)
}
case frameworkResTag, omniromResTag:
@@ -901,9 +900,9 @@
}
case staticLibTag:
if exportPackage != nil {
- staticResourcesNodeDepSets = append(staticResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
- rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet())
- manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet())
+ staticResourcesNodeDepSets = append(staticResourcesNodeDepSets, aarDep.ResourcesNodeDepSet)
+ rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet)
+ manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet)
}
}
@@ -939,6 +938,18 @@
return staticResourcesNodes, sharedResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags
}
+type AndroidLibraryInfo struct {
+ // Empty for now
+}
+
+var AndroidLibraryInfoProvider = blueprint.NewProvider[AndroidLibraryInfo]()
+
+type AARImportInfo struct {
+ // Empty for now
+}
+
+var AARImportInfoProvider = blueprint.NewProvider[AARImportInfo]()
+
type AndroidLibrary struct {
Library
aapt
@@ -1025,7 +1036,7 @@
extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
}
- a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil)
+ javaInfo := a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil)
a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
var res android.Paths
@@ -1034,7 +1045,7 @@
}
prebuiltJniPackages := android.Paths{}
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok {
prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
}
@@ -1049,7 +1060,16 @@
AconfigTextFiles: aconfigTextFilePaths,
})
+ android.SetProvider(ctx, AndroidLibraryInfoProvider, AndroidLibraryInfo{})
+
+ if javaInfo != nil {
+ setExtraJavaInfo(ctx, a, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+ }
+
a.setOutputFiles(ctx)
+
+ buildComplianceMetadata(ctx)
}
func (a *AndroidLibrary) setOutputFiles(ctx android.ModuleContext) {
@@ -1445,7 +1465,7 @@
var transitiveStaticLibsImplementationJars []depset.DepSet[android.Path]
var transitiveStaticLibsResourceJars []depset.DepSet[android.Path]
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
tag := ctx.OtherModuleDependencyTag(module)
switch tag {
@@ -1467,12 +1487,7 @@
completeStaticLibsResourceJars := depset.New(depset.PREORDER, nil, transitiveStaticLibsResourceJars)
var implementationJarFile android.Path
- var combineJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- combineJars = completeStaticLibsImplementationJars.ToList()
- } else {
- combineJars = append(android.Paths{classpathFile}, staticJars...)
- }
+ combineJars := completeStaticLibsImplementationJars.ToList()
if len(combineJars) > 1 {
implementationJarOutputPath := android.PathForModuleOut(ctx, "combined", jarName)
@@ -1483,12 +1498,8 @@
}
var resourceJarFile android.Path
- var resourceJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- resourceJars = completeStaticLibsResourceJars.ToList()
- } else {
- resourceJars = staticResourceJars
- }
+ resourceJars := completeStaticLibsResourceJars.ToList()
+
if len(resourceJars) > 1 {
combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
@@ -1499,12 +1510,8 @@
}
// merge implementation jar with resources if necessary
- var implementationAndResourcesJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- implementationAndResourcesJars = append(slices.Clone(resourceJars), combineJars...)
- } else {
- implementationAndResourcesJars = android.PathsIfNonNil(resourceJarFile, implementationJarFile)
- }
+ implementationAndResourcesJars := append(slices.Clone(resourceJars), combineJars...)
+
var implementationAndResourcesJar android.Path
if len(implementationAndResourcesJars) > 1 {
combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
@@ -1519,12 +1526,7 @@
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
a.implementationAndResourcesJarFile = implementationAndResourcesJar.WithoutRel()
- var headerJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- headerJars = completeStaticLibsHeaderJars.ToList()
- } else {
- headerJars = append(android.Paths{classpathFile}, staticHeaderJars...)
- }
+ headerJars := completeStaticLibsHeaderJars.ToList()
if len(headerJars) > 1 {
headerJarFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
TransformJarsToJar(ctx, headerJarFile, "combine header jars", headerJars, android.OptionalPath{}, false, nil, nil)
@@ -1533,14 +1535,9 @@
a.headerJarFile = headerJars[0]
}
- if ctx.Config().UseTransitiveJarsInClasspath() {
- ctx.CheckbuildFile(classpathFile)
- } else {
- ctx.CheckbuildFile(a.headerJarFile)
- ctx.CheckbuildFile(a.implementationJarFile)
- }
+ ctx.CheckbuildFile(classpathFile)
- android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ javaInfo := &JavaInfo{
HeaderJars: android.PathsIfNonNil(a.headerJarFile),
LocalHeaderJars: android.PathsIfNonNil(classpathFile),
TransitiveStaticLibsHeaderJars: completeStaticLibsHeaderJars,
@@ -1553,7 +1550,9 @@
ImplementationJars: android.PathsIfNonNil(a.implementationJarFile),
StubsLinkType: Implementation,
// TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
- })
+ }
+ setExtraJavaInfo(ctx, a, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
if proptools.Bool(a.properties.Extract_jni) {
for _, t := range ctx.MultiTargets() {
@@ -1580,8 +1579,12 @@
JniPackages: a.jniPackages,
})
+ android.SetProvider(ctx, AARImportInfoProvider, AARImportInfo{})
+
ctx.SetOutputFiles([]android.Path{a.implementationAndResourcesJarFile}, "")
ctx.SetOutputFiles([]android.Path{a.aarPath}, ".aar")
+
+ buildComplianceMetadata(ctx)
}
func (a *AARImport) HeaderJars() android.Paths {
@@ -1609,14 +1612,21 @@
var _ android.ApexModule = (*AARImport)(nil)
// Implements android.ApexModule
-func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return a.depIsInSameApex(ctx, dep)
+func (m *AARImport) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return AARImportDepInSameApexChecker{}
+}
+
+type AARImportDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m AARImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return depIsInSameApex(tag)
}
// Implements android.ApexModule
-func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- return nil
+func (a *AARImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
var _ android.PrebuiltInterface = (*AARImport)(nil)
@@ -1646,5 +1656,5 @@
}
func (a *AARImport) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
- dpInfo.Jars = append(dpInfo.Jars, a.headerJarFile.String(), a.rJar.String())
+ dpInfo.Jars = append(dpInfo.Jars, a.implementationJarFile.String(), a.rJar.String())
}
diff --git a/java/aar_test.go b/java/aar_test.go
index aa4f0af..088ad6c 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -21,6 +21,7 @@
)
func TestAarImportProducesJniPackages(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -50,8 +51,9 @@
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
appMod := ctx.Module(tc.name, "android_common")
- appTestMod := ctx.ModuleForTests(tc.name, "android_common")
+ appTestMod := ctx.ModuleForTests(t, tc.name, "android_common")
info, ok := android.OtherModuleProvider(ctx, appMod, JniPackageProvider)
if !ok {
@@ -84,6 +86,7 @@
}
func TestLibraryFlagsPackages(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
).RunTestWithBp(t, `
@@ -114,7 +117,7 @@
}
`)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
// android_library module depends on aconfig_declarations listed in flags_packages
android.AssertBoolEquals(t, "foo expected to depend on bar", true,
@@ -133,6 +136,7 @@
}
func TestAndroidLibraryOutputFilesRel(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -155,9 +159,9 @@
}
`)
- foo := result.ModuleForTests("foo", "android_common")
- bar := result.ModuleForTests("bar", "android_common")
- baz := result.ModuleForTests("baz", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ bar := result.ModuleForTests(t, "bar", "android_common")
+ baz := result.ModuleForTests(t, "baz", "android_common")
fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
barOutputPaths := bar.OutputFiles(result.TestContext, t, "")
diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go
index 7c91884..ce227b9 100644
--- a/java/android_manifest_test.go
+++ b/java/android_manifest_test.go
@@ -21,6 +21,7 @@
)
func TestManifestMerger(t *testing.T) {
+ t.Parallel()
bp := `
android_app {
name: "app",
@@ -80,7 +81,7 @@
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
- manifestMergerRule := result.ModuleForTests("app", "android_common").Rule("manifestMerger")
+ manifestMergerRule := result.ModuleForTests(t, "app", "android_common").Rule("manifestMerger")
android.AssertPathRelativeToTopEquals(t, "main manifest",
"out/soong/.intermediates/app/android_common/manifest_fixer/AndroidManifest.xml",
manifestMergerRule.Input)
@@ -100,6 +101,7 @@
}
func TestManifestValuesApplicationIdSetsPackageName(t *testing.T) {
+ t.Parallel()
bp := `
android_test {
name: "test",
@@ -127,7 +129,7 @@
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
- manifestMergerRule := result.ModuleForTests("test", "android_common").Rule("manifestMerger")
+ manifestMergerRule := result.ModuleForTests(t, "test", "android_common").Rule("manifestMerger")
android.AssertStringMatches(t,
"manifest merger args",
manifestMergerRule.Args["args"],
diff --git a/java/androidmk.go b/java/androidmk.go
index eb33589..e9b1f64 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -23,13 +23,12 @@
"github.com/google/blueprint/proptools"
)
-func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
- hostDexNeeded := Bool(library.deviceProperties.Hostdex) && !library.Host()
- if library.hideApexVariantFromMake {
- hostDexNeeded = false
- }
+func (library *Library) hostDexNeeded() bool {
+ return Bool(library.deviceProperties.Hostdex) && !library.Host() && !library.hideApexVariantFromMake
+}
- if hostDexNeeded {
+func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
+ if library.hostDexNeeded() {
var output android.Path
if library.dexJarFile.IsSet() {
output = library.dexJarFile.Path()
@@ -71,11 +70,7 @@
if library.hideApexVariantFromMake {
// For a java library built for an APEX, we don't need a Make module for itself. Otherwise, it
// will conflict with the platform variant because they have the same module name in the
- // makefile. However, we need to add its dexpreopt outputs as sub-modules, if it is preopted.
- dexpreoptEntries := library.dexpreopter.AndroidMkEntriesForApex()
- if len(dexpreoptEntries) > 0 {
- entriesList = append(entriesList, dexpreoptEntries...)
- }
+ // makefile.
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
} else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
// Platform variant. If not available for the platform, we don't need Make module.
@@ -125,6 +120,14 @@
}
},
},
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string) {
+ if library.apiXmlFile != nil {
+ fmt.Fprintf(w, "$(call declare-1p-target,%s,)\n", library.apiXmlFile.String())
+ fmt.Fprintf(w, "$(eval $(call copy-one-file,%s,$(TARGET_OUT_COMMON_INTERMEDIATES)/%s))\n", library.apiXmlFile.String(), library.apiXmlFile.Base())
+ }
+ },
+ },
})
}
@@ -555,73 +558,11 @@
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
func(w io.Writer, name, prefix, moduleDir string) {
- if dstubs.apiFile != nil {
- fmt.Fprintf(w, ".PHONY: %s %s.txt\n", dstubs.Name(), dstubs.Name())
- fmt.Fprintf(w, "%s %s.txt: %s\n", dstubs.Name(), dstubs.Name(), dstubs.apiFile)
- }
- if dstubs.removedApiFile != nil {
- fmt.Fprintf(w, ".PHONY: %s %s.txt\n", dstubs.Name(), dstubs.Name())
- fmt.Fprintf(w, "%s %s.txt: %s\n", dstubs.Name(), dstubs.Name(), dstubs.removedApiFile)
- }
- if dstubs.checkCurrentApiTimestamp != nil {
- fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-current-api")
- fmt.Fprintln(w, dstubs.Name()+"-check-current-api:",
- dstubs.checkCurrentApiTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY: checkapi")
- fmt.Fprintln(w, "checkapi:",
- dstubs.checkCurrentApiTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY: droidcore")
- fmt.Fprintln(w, "droidcore: checkapi")
- }
- if dstubs.updateCurrentApiTimestamp != nil {
- fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-update-current-api")
- fmt.Fprintln(w, dstubs.Name()+"-update-current-api:",
- dstubs.updateCurrentApiTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY: update-api")
- fmt.Fprintln(w, "update-api:",
- dstubs.updateCurrentApiTimestamp.String())
- }
- if dstubs.checkLastReleasedApiTimestamp != nil {
- fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-last-released-api")
- fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:",
- dstubs.checkLastReleasedApiTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY: checkapi")
- fmt.Fprintln(w, "checkapi:",
- dstubs.checkLastReleasedApiTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY: droidcore")
- fmt.Fprintln(w, "droidcore: checkapi")
- }
if dstubs.apiLintTimestamp != nil {
- fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-api-lint")
- fmt.Fprintln(w, dstubs.Name()+"-api-lint:",
- dstubs.apiLintTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY: checkapi")
- fmt.Fprintln(w, "checkapi:",
- dstubs.Name()+"-api-lint")
-
- fmt.Fprintln(w, ".PHONY: droidcore")
- fmt.Fprintln(w, "droidcore: checkapi")
-
if dstubs.apiLintReport != nil {
- fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n", dstubs.Name()+"-api-lint",
- dstubs.apiLintReport.String(), "apilint/"+dstubs.Name()+"-lint-report.txt")
fmt.Fprintf(w, "$(call declare-0p-target,%s)\n", dstubs.apiLintReport.String())
}
}
- if dstubs.checkNullabilityWarningsTimestamp != nil {
- fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-nullability-warnings")
- fmt.Fprintln(w, dstubs.Name()+"-check-nullability-warnings:",
- dstubs.checkNullabilityWarningsTimestamp.String())
-
- fmt.Fprintln(w, ".PHONY:", "droidcore")
- fmt.Fprintln(w, "droidcore: ", dstubs.Name()+"-check-nullability-warnings")
- }
},
},
}}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 1d98b18..b4b13b1 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -23,6 +23,7 @@
)
func TestRequired(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -31,7 +32,7 @@
}
`)
- mod := ctx.ModuleForTests("foo", "android_common").Module()
+ mod := ctx.ModuleForTests(t, "foo", "android_common").Module()
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
expected := []string{"libfoo"}
@@ -42,6 +43,7 @@
}
func TestHostdex(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -50,7 +52,7 @@
}
`)
- mod := ctx.ModuleForTests("foo", "android_common").Module()
+ mod := ctx.ModuleForTests(t, "foo", "android_common").Module()
entriesList := android.AndroidMkEntriesForTest(t, ctx, mod)
if len(entriesList) != 2 {
t.Errorf("two entries are expected, but got %d", len(entriesList))
@@ -72,6 +74,7 @@
}
func TestHostdexRequired(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -81,7 +84,7 @@
}
`)
- mod := ctx.ModuleForTests("foo", "android_common").Module()
+ mod := ctx.ModuleForTests(t, "foo", "android_common").Module()
entriesList := android.AndroidMkEntriesForTest(t, ctx, mod)
if len(entriesList) != 2 {
t.Errorf("two entries are expected, but got %d", len(entriesList))
@@ -103,6 +106,7 @@
}
func TestHostdexSpecificRequired(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -116,7 +120,7 @@
}
`)
- mod := ctx.ModuleForTests("foo", "android_common").Module()
+ mod := ctx.ModuleForTests(t, "foo", "android_common").Module()
entriesList := android.AndroidMkEntriesForTest(t, ctx, mod)
if len(entriesList) != 2 {
t.Errorf("two entries are expected, but got %d", len(entriesList))
@@ -136,6 +140,7 @@
}
func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -153,7 +158,7 @@
`)
// Verify the existence of internal modules
- result.ModuleForTests("foo-shared_library.xml", "android_common")
+ result.ModuleForTests(t, "foo-shared_library.xml", "android_common")
testCases := []struct {
moduleName string
@@ -163,7 +168,7 @@
{"foo-no_shared_library", []string{"foo-no_shared_library.impl"}},
}
for _, tc := range testCases {
- mod := result.ModuleForTests(tc.moduleName, "android_common").Module()
+ mod := result.ModuleForTests(t, tc.moduleName, "android_common").Module()
entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
if !reflect.DeepEqual(tc.expected, actual) {
@@ -173,6 +178,7 @@
}
func TestImportSoongDexJar(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
java_import {
name: "my-java-import",
@@ -191,6 +197,7 @@
}
func TestAndroidTestHelperApp_LocalDisableTestConfig(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_test_helper_app {
name: "foo",
@@ -198,7 +205,7 @@
}
`)
- mod := ctx.ModuleForTests("foo", "android_common").Module()
+ mod := ctx.ModuleForTests(t, "foo", "android_common").Module()
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
expected := []string{"true"}
@@ -209,6 +216,7 @@
}
func TestGetOverriddenPackages(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(
t, `
android_app {
@@ -246,7 +254,7 @@
}
for _, expected := range expectedVariants {
- mod := ctx.ModuleForTests(expected.name, expected.variantName).Module()
+ mod := ctx.ModuleForTests(t, expected.name, expected.variantName).Module()
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
actual := entries.EntryMap["LOCAL_OVERRIDES_PACKAGES"]
@@ -255,6 +263,7 @@
}
func TestJniAsRequiredDeps(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcDefaultModules,
@@ -295,7 +304,7 @@
}
for _, tc := range testcases {
- mod := ctx.ModuleForTests(tc.name, "android_common").Module()
+ mod := ctx.ModuleForTests(t, tc.name, "android_common").Module()
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
required := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
android.AssertDeepEquals(t, "unexpected required deps", tc.expected, required)
diff --git a/java/app.go b/java/app.go
index 64ecc55..a3414f6 100644
--- a/java/app.go
+++ b/java/app.go
@@ -70,6 +70,19 @@
// EmbeddedJNILibs is the list of paths to JNI libraries that were embedded in the APK.
EmbeddedJNILibs android.Paths
+
+ MergedManifestFile android.Path
+
+ Prebuilt bool
+ AppSet bool
+ Privileged bool
+ OutputFile android.Path
+ InstallApkName string
+ JacocoReportClassesFile android.Path
+ Certificate Certificate
+ PrivAppAllowlist android.OptionalPath
+ OverriddenManifestPackageName *string
+ ApkCertsFile android.Path
}
var AppInfoProvider = blueprint.NewProvider[*AppInfo]()
@@ -399,9 +412,23 @@
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
TestOnly: true,
})
- android.SetProvider(ctx, AppInfoProvider, &AppInfo{
+ appInfo := &AppInfo{
Updatable: Bool(a.appProperties.Updatable),
TestHelperApp: true,
+ }
+ setCommonAppInfo(appInfo, a)
+ android.SetProvider(ctx, AppInfoProvider, appInfo)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
+ if len(a.appTestHelperAppProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, a.appTestHelperAppProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: a.appTestHelperAppProperties.Test_suites,
})
}
@@ -418,13 +445,28 @@
embeddedJniLibs = append(embeddedJniLibs, jni.path)
}
}
- android.SetProvider(ctx, AppInfoProvider, &AppInfo{
- Updatable: Bool(a.appProperties.Updatable),
- TestHelperApp: false,
- EmbeddedJNILibs: embeddedJniLibs,
- })
+ overriddenName := a.OverriddenManifestPackageName()
+ appInfo := &AppInfo{
+ Updatable: Bool(a.appProperties.Updatable),
+ TestHelperApp: false,
+ EmbeddedJNILibs: embeddedJniLibs,
+ MergedManifestFile: a.mergedManifest,
+ OverriddenManifestPackageName: &overriddenName,
+ }
+ setCommonAppInfo(appInfo, a)
+ android.SetProvider(ctx, AppInfoProvider, appInfo)
a.requiredModuleNames = a.getRequiredModuleNames(ctx)
+
+ if a.dexer.proguardDictionary.Valid() {
+ android.SetProvider(ctx, ProguardProvider, ProguardInfo{
+ ModuleName: ctx.ModuleName(),
+ Class: "APPS",
+ ProguardDictionary: a.dexer.proguardDictionary.Path(),
+ ProguardUsageZip: a.dexer.proguardUsageZip.Path(),
+ ClassesJar: a.implementationAndResourcesJar,
+ })
+ }
}
func (a *AndroidApp) getRequiredModuleNames(ctx android.ModuleContext) []string {
@@ -487,18 +529,28 @@
// This check is enforced for "updatable" APKs (including APK-in-APEX).
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
// It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType()
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) {
return
}
- dep, _ := m.(*cc.Module)
+ if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); !ok {
+ panic(fmt.Errorf("jni dependency is not a cc module: %v", m))
+ }
+ commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider)
+ if !ok {
+ panic(fmt.Errorf("jni dependency doesn't have CommonModuleInfo provider: %v", m))
+ }
// The domain of cc.sdk_version is "current" and <number>
// We can rely on android.SdkSpec to convert it to <number> so that "current" is
// handled properly regardless of sdk finalization.
- jniSdkVersion, err := android.SdkSpecFrom(ctx, dep.MinSdkVersion()).EffectiveVersion(ctx)
+ ver := ""
+ if !commonInfo.MinSdkVersion.IsPlatform {
+ ver = commonInfo.MinSdkVersion.ApiLevel.String()
+ }
+ jniSdkVersion, err := android.SdkSpecFrom(ctx, ver).EffectiveVersion(ctx)
if err != nil || minSdkVersion.LessThan(jniSdkVersion) {
- ctx.OtherModuleErrorf(dep, "min_sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
- dep.MinSdkVersion(), minSdkVersion, ctx.ModuleName())
+ ctx.OtherModuleErrorf(m, "min_sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
+ ver, minSdkVersion, ctx.ModuleName())
return
}
@@ -561,10 +613,10 @@
}
func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) {
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
- case staticLibTag:
+ case staticLibTag, rroDepTag:
if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok {
aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...)
}
@@ -640,7 +692,7 @@
}
// Use non final ids if we are doing optimized shrinking and are using R8.
- nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled()
+ nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled(ctx)
aconfigTextFilePaths := getAconfigFilePaths(ctx)
@@ -667,7 +719,7 @@
func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
var staticLibProguardFlagFiles android.Paths
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...)
if ctx.OtherModuleDependencyTag(m) == staticLibTag {
@@ -704,7 +756,7 @@
return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
}
-func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path) {
+func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path, *JavaInfo) {
a.dexpreopter.installPath = a.installPath(ctx)
a.dexpreopter.isApp = true
if a.dexProperties.Uncompress_dex == nil {
@@ -719,6 +771,7 @@
var packageResources = a.exportPackage
+ javaInfo := &JavaInfo{}
if ctx.ModuleName() != "framework-res" && ctx.ModuleName() != "omnirom-res" {
if a.dexProperties.resourceShrinkingEnabled(ctx) {
protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
@@ -742,7 +795,7 @@
extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
}
- a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil)
+ javaInfo = a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil)
if a.dexProperties.resourceShrinkingEnabled(ctx) {
binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
@@ -750,7 +803,7 @@
}
}
- return a.dexJarFile.PathOrNil(), packageResources
+ return a.dexJarFile.PathOrNil(), packageResources, javaInfo
}
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath {
@@ -960,7 +1013,7 @@
a.linter.resources = a.aapt.resourceFiles
a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
- dexJarFile, packageResources := a.dexBuildActions(ctx)
+ dexJarFile, packageResources, javaInfo := a.dexBuildActions(ctx)
// No need to check the SDK version of the JNI deps unless we embed them
checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis)
@@ -1076,7 +1129,28 @@
},
)
+ if javaInfo != nil {
+ javaInfo.OutputFile = a.outputFile
+ setExtraJavaInfo(ctx, a, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+ }
+
+ android.SetProvider(ctx, android.ApexBundleDepsDataProvider, android.ApexBundleDepsData{
+ FlatListPath: a.FlatListPath(),
+ Updatable: a.Updatable(),
+ })
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"APPS"}
+ if !a.embeddedJniLibs {
+ for _, jniLib := range a.jniLibs {
+ moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, jniLib.name)
+ }
+ }
+
a.setOutputFiles(ctx)
+
+ buildComplianceMetadata(ctx)
}
func (a *AndroidApp) setOutputFiles(ctx android.ModuleContext) {
@@ -1108,29 +1182,35 @@
app.SdkVersion(ctx).Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx)
}
jniLib, prebuiltJniPackages := collectJniDeps(ctx, shouldCollectRecursiveNativeDeps,
- checkNativeSdkVersion, func(parent, child android.Module) bool {
+ checkNativeSdkVersion, func(parent, child android.ModuleProxy) bool {
apkInApex := ctx.Module().(android.ApexModule).NotInPlatform()
- childLinkable, _ := child.(cc.LinkableInterface)
- parentLinkable, _ := parent.(cc.LinkableInterface)
- useStubsOfDep := childLinkable.IsStubs()
- if apkInApex && parentLinkable != nil {
+ childLinkable, _ := android.OtherModuleProvider(ctx, child, cc.LinkableInfoProvider)
+ parentIsLinkable := false
+ if android.EqualModules(ctx.Module(), parent) {
+ parentLinkable, _ := ctx.Module().(cc.LinkableInterface)
+ parentIsLinkable = parentLinkable != nil
+ } else {
+ _, parentIsLinkable = android.OtherModuleProvider(ctx, parent, cc.LinkableInfoProvider)
+ }
+ useStubsOfDep := childLinkable.IsStubs
+ if apkInApex && parentIsLinkable {
// APK-in-APEX
// If the parent is a linkable interface, use stubs if the dependency edge crosses an apex boundary.
- useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants() && cc.ShouldUseStubForApex(ctx, parent, child))
+ useStubsOfDep = useStubsOfDep || (childLinkable.HasStubsVariants && cc.ShouldUseStubForApex(ctx, parent, child))
}
- return !childLinkable.IsNdk(ctx.Config()) && !useStubsOfDep
+ return !childLinkable.IsNdk && !useStubsOfDep
})
var certificates []Certificate
var directImplementationDeps android.Paths
var transitiveImplementationDeps []depset.DepSet[android.Path]
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
if tag == certificateTag {
- if dep, ok := module.(*AndroidAppCertificate); ok {
+ if dep, ok := android.OtherModuleProvider(ctx, module, AndroidAppCertificateInfoProvider); ok {
certificates = append(certificates, dep.Certificate)
} else {
ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", otherName)
@@ -1154,22 +1234,25 @@
func collectJniDeps(ctx android.ModuleContext,
shouldCollectRecursiveNativeDeps bool,
checkNativeSdkVersion bool,
- filter func(parent, child android.Module) bool) ([]jniLib, android.Paths) {
+ filter func(parent, child android.ModuleProxy) bool) ([]jniLib, android.Paths) {
var jniLibs []jniLib
var prebuiltJniPackages android.Paths
seenModulePaths := make(map[string]bool)
- ctx.WalkDeps(func(module android.Module, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(module, parent android.ModuleProxy) bool {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
+ return false
+ }
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
- if dep, ok := module.(cc.LinkableInterface); ok {
+ if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
if filter != nil && !filter(parent, module) {
return false
}
- lib := dep.OutputFile()
+ lib := dep.OutputFile
if lib.Valid() {
path := lib.Path()
if seenModulePaths[path.String()] {
@@ -1177,7 +1260,8 @@
}
seenModulePaths[path.String()] = true
- if checkNativeSdkVersion && dep.SdkVersion() == "" {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider)
+ if checkNativeSdkVersion && commonInfo.SdkVersion == "" {
ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not",
otherName)
}
@@ -1185,11 +1269,11 @@
jniLibs = append(jniLibs, jniLib{
name: ctx.OtherModuleName(module),
path: path,
- target: module.Target(),
- coverageFile: dep.CoverageOutputFile(),
- unstrippedFile: dep.UnstrippedOutputFile(),
- partition: dep.Partition(),
- installPaths: android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider).InstallFiles,
+ target: commonInfo.Target,
+ coverageFile: dep.CoverageOutputFile,
+ unstrippedFile: dep.UnstrippedOutputFile,
+ partition: dep.Partition,
+ installPaths: android.OtherModuleProviderOrDefault(ctx, module, android.InstallFilesProvider).InstallFiles,
})
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{otherName})
@@ -1214,10 +1298,13 @@
}
func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
- ctx.WalkDeps(func(child, parent android.Module) bool {
- isExternal := !a.DepIsInSameApex(ctx, child)
- if am, ok := child.(android.ApexModule); ok {
- if !do(ctx, parent, am, isExternal) {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ // TODO(ccross): Should this use android.DepIsInSameApex? Right now it is applying the android app
+ // heuristics to every transitive dependency, when it should probably be using the heuristics of the
+ // immediate parent.
+ isExternal := !a.GetDepInSameApexChecker().OutgoingDepIsInSameApex(ctx.OtherModuleDependencyTag(child))
+ if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule {
+ if !do(ctx, parent, child, isExternal) {
return false
}
}
@@ -1231,12 +1318,12 @@
}
depsInfo := android.DepNameToDepInfoMap{}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
depName := to.Name()
// Skip dependencies that are only available to APEXes; they are developed with updatability
// in mind and don't need manual approval.
- if to.(android.ApexModule).NotAvailableForPlatform() {
+ if android.OtherModulePointerProviderOrDefault(ctx, to, android.CommonModuleInfoProvider).NotAvailableForPlatform {
return true
}
@@ -1246,18 +1333,9 @@
depsInfo[depName] = info
} else {
toMinSdkVersion := "(no version)"
- if m, ok := to.(interface {
- MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
- }); ok {
- if v := m.MinSdkVersion(ctx); !v.IsNone() {
- toMinSdkVersion = v.String()
- }
- } else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
- // TODO(b/175678607) eliminate the use of MinSdkVersion returning
- // string
- if v := m.MinSdkVersion(); v != "" {
- toMinSdkVersion = v
- }
+ if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoProvider); ok &&
+ !info.MinSdkVersion.IsPlatform && info.MinSdkVersion.ApiLevel != nil {
+ toMinSdkVersion = info.MinSdkVersion.ApiLevel.String()
}
depsInfo[depName] = android.ApexModuleDepInfo{
To: depName,
@@ -1292,11 +1370,19 @@
return a.overridableAppProperties.Certificate.GetOrDefault(ctx, "")
}
-func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- if IsJniDepTag(ctx.OtherModuleDependencyTag(dep)) {
+func (m *AndroidApp) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return AppDepInSameApexChecker{}
+}
+
+type AppDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m AppDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ if IsJniDepTag(tag) {
return true
}
- return a.Library.DepIsInSameApex(ctx, dep)
+ return depIsInSameApex(tag)
}
func (a *AndroidApp) Privileged() bool {
@@ -1560,6 +1646,9 @@
}
a.generateAndroidBuildActions(ctx)
+ for _, c := range a.testProperties.Test_options.Tradefed_options {
+ configs = append(configs, c)
+ }
for _, module := range a.testProperties.Test_mainline_modules {
configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module})
}
@@ -1573,6 +1662,24 @@
a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_common_data)...)
a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...)
a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...)
+ a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Host_common_data)...)
+
+ // Install test deps
+ if !ctx.Config().KatiEnabled() {
+ pathInTestCases := android.PathForModuleInstall(ctx, ctx.Module().Name())
+ if a.testConfig != nil {
+ ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".config", a.testConfig)
+ }
+ dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".dynamic", dynamicConfig.Path())
+ }
+ testDeps := append(a.data, a.extraTestConfigs...)
+ for _, data := range android.SortedUniquePaths(testDeps) {
+ dataPath := android.DataPath{SrcPath: data}
+ ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath})
+ }
+ }
android.SetProvider(ctx, tradefed.BaseTestProviderKey, tradefed.BaseTestProviderData{
TestcaseRelDataFiles: testcaseRel(a.data),
@@ -1591,6 +1698,26 @@
TopLevelTarget: true,
})
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
+ if a.testConfig != nil {
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, a.testConfig.String())
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, a.extraTestConfigs.Strings()...)
+ if len(a.testProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, a.testProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ if _, ok := testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, a.testProperties.Test_mainline_modules...)
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: a.testProperties.Test_suites,
+ })
}
func testcaseRel(paths android.Paths) []string {
@@ -1679,7 +1806,7 @@
module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
module.appProperties.AlwaysPackageNativeLibs = true
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
module.addHostAndDeviceProperties()
module.AddProperties(
@@ -1730,12 +1857,14 @@
// TODO(b/192032291): Disable by default after auditing downstream usage.
module.Module.dexProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.Ignore_library_extends_program = proptools.BoolPtr(true)
+ module.Module.dexProperties.Optimize.Proguard_compatibility = proptools.BoolPtr(false)
module.Module.properties.Installable = proptools.BoolPtr(true)
module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
module.appProperties.AlwaysPackageNativeLibs = true
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
module.addHostAndDeviceProperties()
module.AddProperties(
@@ -1762,6 +1891,12 @@
Certificate *string
}
+type AndroidAppCertificateInfo struct {
+ Certificate Certificate
+}
+
+var AndroidAppCertificateInfoProvider = blueprint.NewProvider[AndroidAppCertificateInfo]()
+
// android_app_certificate modules can be referenced by the certificates property of android_app modules to select
// the signing key.
func AndroidAppCertificateFactory() android.Module {
@@ -1777,6 +1912,10 @@
Pem: android.PathForModuleSrc(ctx, cert+".x509.pem"),
Key: android.PathForModuleSrc(ctx, cert+".pk8"),
}
+
+ android.SetProvider(ctx, AndroidAppCertificateInfoProvider, AndroidAppCertificateInfo{
+ Certificate: c.Certificate,
+ })
}
type OverrideAndroidApp struct {
@@ -1931,7 +2070,7 @@
return clcMap
}
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
tag, isUsesLibTag := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag)
if !isUsesLibTag {
return
@@ -1939,31 +2078,35 @@
dep := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(m))
+ javaInfo, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
+ if !ok {
+ return
+ }
// Skip stub libraries. A dependency on the implementation library has been added earlier,
// so it will be added to CLC, but the stub shouldn't be. Stub libraries can be distingushed
// from implementation libraries by their name, which is different as it has a suffix.
- if comp, ok := m.(SdkLibraryComponentDependency); ok {
- if impl := comp.OptionalSdkLibraryImplementation(); impl != nil && *impl != dep {
+ if comp := javaInfo.SdkLibraryComponentDependencyInfo; comp != nil {
+ if impl := comp.OptionalSdkLibraryImplementation; impl != nil && *impl != dep {
return
}
}
- if lib, ok := m.(UsesLibraryDependency); ok {
+ if lib := javaInfo.UsesLibraryDependencyInfo; lib != nil {
if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
// Skip java_sdk_library dependencies that provide stubs, but not an implementation.
// This will be restricted to optional_uses_libs
- if tag == usesLibOptTag && lib.DexJarBuildPath(ctx).PathOrNil() == nil {
+ if tag == usesLibOptTag && javaInfo.DexJarBuildPath.PathOrNil() == nil {
u.shouldDisableDexpreopt = true
return
}
}
libName := dep
- if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
- libName = *ulib.ProvidesUsesLib()
+ if ulib := javaInfo.ProvidesUsesLibInfo; ulib != nil && ulib.ProvidesUsesLib != nil {
+ libName = *ulib.ProvidesUsesLib
}
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
- lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
- lib.ClassLoaderContexts())
+ javaInfo.DexJarBuildPath.PathOrNil(), lib.DexJarInstallPath,
+ lib.ClassLoaderContexts)
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
} else {
@@ -2055,3 +2198,33 @@
classLoaderContexts *dexpreopt.ClassLoaderContextMap) {
u.verifyUsesLibraries(ctx, apk, nil, classLoaderContexts) // for APKs manifest_check does not write output file
}
+
+// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in
+// the same way.
+type androidApp interface {
+ android.Module
+ Privileged() bool
+ InstallApkName() string
+ OutputFile() android.Path
+ JacocoReportClassesFile() android.Path
+ Certificate() Certificate
+ BaseModuleName() string
+ PrivAppAllowlist() android.OptionalPath
+}
+
+var _ androidApp = (*AndroidApp)(nil)
+var _ androidApp = (*AndroidAppImport)(nil)
+var _ androidApp = (*AndroidTestHelperApp)(nil)
+
+func setCommonAppInfo(appInfo *AppInfo, m androidApp) {
+ appInfo.Privileged = m.Privileged()
+ appInfo.OutputFile = m.OutputFile()
+ appInfo.InstallApkName = m.InstallApkName()
+ appInfo.JacocoReportClassesFile = m.JacocoReportClassesFile()
+ appInfo.Certificate = m.Certificate()
+ appInfo.PrivAppAllowlist = m.PrivAppAllowlist()
+}
+
+type AppInfos []AppInfo
+
+var AppInfosProvider = blueprint.NewProvider[AppInfos]()
diff --git a/java/app_import.go b/java/app_import.go
index 8951c7d..9fb13ba 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -43,6 +43,12 @@
Description: "Uncompress embedded JNI libs",
})
+ stripEmbeddedJniLibsUnusedArchRule = pctx.AndroidStaticRule("strip-embedded-jni-libs-from-unused-arch", blueprint.RuleParams{
+ Command: `${config.Zip2ZipCmd} -i $in -o $out -x 'lib/**/*.so' $extraArgs`,
+ CommandDeps: []string{"${config.Zip2ZipCmd}"},
+ Description: "Remove all JNI libs from unused architectures",
+ }, "extraArgs")
+
uncompressDexRule = pctx.AndroidStaticRule("uncompress-dex", blueprint.RuleParams{
Command: `if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` +
`${config.Zip2ZipCmd} -i $in -o $out -0 'classes*.dex'` +
@@ -56,6 +62,18 @@
CommandDeps: []string{"build/soong/scripts/check_prebuilt_presigned_apk.py", "${config.Aapt2Cmd}", "${config.ZipAlign}"},
Description: "Check presigned apk",
}, "extraArgs")
+
+ extractApkRule = pctx.AndroidStaticRule("extract-apk", blueprint.RuleParams{
+ Command: "unzip -p $in $extract_apk > $out",
+ Description: "Extract specific sub apk",
+ }, "extract_apk")
+
+ gzipRule = pctx.AndroidStaticRule("gzip",
+ blueprint.RuleParams{
+ Command: "prebuilts/build-tools/path/linux-x86/gzip -9 -c $in > $out",
+ CommandDeps: []string{"prebuilts/build-tools/path/linux-x86/gzip"},
+ Description: "gzip $out",
+ })
)
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -150,10 +168,19 @@
// the prebuilt is Name() without "prebuilt_" prefix
Source_module_name *string
+ // Whether stripping all libraries from unused architectures.
+ Strip_unused_jni_arch *bool
+
// 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"`
+
+ // Path of extracted apk which is extracted from prebuilt apk. Use this extracted to import.
+ Extract_apk proptools.Configurable[string]
+
+ // Compress the output APK using gzip. Defaults to false.
+ Compress_apk proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -278,6 +305,19 @@
})
}
+func (a *AndroidAppImport) extractSubApk(
+ ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) {
+ extractApkPath := a.properties.Extract_apk.GetOrDefault(ctx, "")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractApkRule,
+ Input: inputPath,
+ Output: outputPath,
+ Args: map[string]string{
+ "extract_apk": extractApkPath,
+ },
+ })
+}
+
// Returns whether this module should have the dex file stored uncompressed in the APK.
func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
if ctx.Config().UnbundledBuild() || proptools.Bool(a.properties.Preprocessed) {
@@ -292,8 +332,34 @@
return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
}
+func (a *AndroidAppImport) stripEmbeddedJniLibsUnusedArch(
+ ctx android.ModuleContext, inputPath android.Path, outputPath android.WritablePath) {
+ var wantedJniLibSlice []string
+ for _, target := range ctx.MultiTargets() {
+ supported_abis := target.Arch.Abi
+ for _, arch := range supported_abis {
+ wantedJniLibSlice = append(wantedJniLibSlice, " -X 'lib/"+arch+"/*.so'")
+ }
+ }
+ wantedJniLibString := strings.Join(wantedJniLibSlice, " ")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: stripEmbeddedJniLibsUnusedArchRule,
+ Input: inputPath,
+ Output: outputPath,
+ Args: map[string]string{
+ "extraArgs": wantedJniLibString,
+ },
+ })
+}
+
func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.generateAndroidBuildActions(ctx)
+
+ appInfo := &AppInfo{
+ Prebuilt: true,
+ }
+ setCommonAppInfo(appInfo, a)
+ android.SetProvider(ctx, AppInfoProvider, appInfo)
}
func (a *AndroidAppImport) InstallApkName() string {
@@ -336,10 +402,14 @@
ctx.ModuleErrorf("One and only one of certficate, presigned (implied by preprocessed), and default_dev_cert properties must be set")
}
- // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS
srcApk := a.prebuilt.SingleSourcePath(ctx)
+ if a.properties.Extract_apk.GetOrDefault(ctx, "") != "" {
+ extract_apk := android.PathForModuleOut(ctx, "extract-apk", ctx.ModuleName()+".apk")
+ a.extractSubApk(ctx, srcApk, extract_apk)
+ srcApk = extract_apk
+ }
// TODO: Install or embed JNI libraries
@@ -347,6 +417,13 @@
jnisUncompressed := android.PathForModuleOut(ctx, "jnis-uncompressed", ctx.ModuleName()+".apk")
a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed)
+ // Strip all embedded JNI libs and include only required ones accordingly to the module's compile_multilib
+ if Bool(a.properties.Strip_unused_jni_arch) {
+ jnisStripped := android.PathForModuleOut(ctx, "jnis-stripped", ctx.ModuleName()+".apk")
+ a.stripEmbeddedJniLibsUnusedArch(ctx, jnisUncompressed, jnisStripped)
+ jnisUncompressed = jnisStripped
+ }
+
var pathFragments []string
relInstallPath := String(a.properties.Relative_install_path)
@@ -366,7 +443,9 @@
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries(ctx)
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
- if a.usesLibrary.shouldDisableDexpreopt {
+
+ // Disable Dexpreopt if Compress_apk is true. It follows the build/make/core/app_prebuilt_internal.mk
+ if a.usesLibrary.shouldDisableDexpreopt || a.properties.Compress_apk.GetOrDefault(ctx, false) {
a.dexpreopter.disableDexpreopt()
}
@@ -385,7 +464,13 @@
jnisUncompressed = dexUncompressed
}
- apkFilename := proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk")
+ defaultApkFilename := a.BaseModuleName()
+ if a.properties.Compress_apk.GetOrDefault(ctx, false) {
+ defaultApkFilename += ".apk.gz"
+ } else {
+ defaultApkFilename += ".apk"
+ }
+ apkFilename := proptools.StringDefault(a.properties.Filename, defaultApkFilename)
// TODO: Handle EXTERNAL
@@ -425,7 +510,16 @@
a.certificate = PresignedCertificate
}
- // TODO: Optionally compress the output apk.
+ if a.properties.Compress_apk.GetOrDefault(ctx, false) {
+ outputFile := android.PathForModuleOut(ctx, "compressed_apk", apkFilename)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: gzipRule,
+ Input: a.outputFile,
+ Output: outputFile,
+ Description: "Compressing " + a.outputFile.Base(),
+ })
+ a.outputFile = outputFile
+ }
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
@@ -443,6 +537,8 @@
ctx.SetOutputFiles([]android.Path{a.outputFile}, "")
+ buildComplianceMetadata(ctx)
+
// TODO: androidmk converter jni libs
}
@@ -538,7 +634,15 @@
return Bool(a.properties.Privileged)
}
-func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
+func (m *AndroidAppImport) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return AppImportDepInSameApexChecker{}
+}
+
+type AppImportDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m AppImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
// android_app_import might have extra dependencies via uses_libs property.
// Don't track the dependency as we don't automatically add those libraries
// to the classpath. It should be explicitly added to java_libs property of APEX
@@ -556,10 +660,8 @@
var _ android.ApexModule = (*AndroidAppImport)(nil)
// Implements android.ApexModule
-func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // Do not check for prebuilts against the min_sdk_version of enclosing APEX
- return nil
+func (m *AndroidAppImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
@@ -682,7 +784,29 @@
func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.generateAndroidBuildActions(ctx)
+ a.updateModuleInfoJSON(ctx)
+
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: a.testProperties.Test_suites,
+ })
+}
+
+func (a *AndroidTestImport) updateModuleInfoJSON(ctx android.ModuleContext) {
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"APPS"}
+ moduleInfoJSON.CompatibilitySuites = []string{"null-suite"}
+ if len(a.testProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = a.testProperties.Test_suites
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+ moduleInfoJSON.Tags = []string{"tests"}
+ moduleInfoJSON.RegisterNameOverride = a.BaseModuleName()
+ testConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml")
+ if testConfig.Valid() {
+ moduleInfoJSON.TestConfig = []string{testConfig.String()}
+ }
}
func (a *AndroidTestImport) InstallInTestcases() bool {
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 54a5e75..2600767 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -26,6 +26,7 @@
)
func TestAndroidAppImport(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -37,7 +38,47 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
+
+ // Check dexpreopt outputs.
+ if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
+ t.Errorf("can't find dexpreopt outputs")
+ }
+
+ // Check cert signing flag.
+ signedApk := variant.Output("signed/foo.apk")
+ signingFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
+ if expected != signingFlag {
+ t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
+ }
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
+}
+
+func TestAndroidAppImportWithDefaults(t *testing.T) {
+ t.Parallel()
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ defaults: ["foo_defaults"],
+ }
+
+ java_defaults {
+ name: "foo_defaults",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `)
+
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
// Check dexpreopt outputs.
if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
@@ -60,6 +101,7 @@
}
func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -71,7 +113,7 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
// Check dexpreopt outputs. They shouldn't exist.
if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil ||
@@ -87,6 +129,7 @@
}
func TestAndroidAppImport_Presigned(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -98,7 +141,7 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
// Check dexpreopt outputs.
if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
@@ -121,6 +164,7 @@
}
func TestAndroidAppImport_SigningLineage(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -137,7 +181,7 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
signedApk := variant.Output("signed/foo.apk")
// Check certificates
@@ -164,6 +208,7 @@
}
func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -178,7 +223,7 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
signedApk := variant.Output("signed/foo.apk")
// Check cert signing lineage flag.
@@ -196,6 +241,7 @@
}
func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -207,7 +253,7 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
// Check dexpreopt outputs.
if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
@@ -231,6 +277,7 @@
}
func TestAndroidAppImport_DpiVariants(t *testing.T) {
+ t.Parallel()
bp := `
android_app_import {
name: "foo",
@@ -302,7 +349,7 @@
}),
).RunTestWithBp(t, bp)
- variant := result.ModuleForTests("foo", "android_common")
+ variant := result.ModuleForTests(t, "foo", "android_common")
input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
if strings.HasSuffix(input, test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
@@ -317,6 +364,7 @@
}
func TestAndroidAppImport_Filename(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app_import {
name: "foo",
@@ -325,10 +373,25 @@
}
android_app_import {
+ name: "foo_compressed",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ compress_apk: true,
+ }
+
+ android_app_import {
name: "bar",
apk: "prebuilts/apk/app.apk",
presigned: true,
- filename: "bar_sample.apk"
+ filename: "bar_sample.apk",
+ }
+
+ android_app_import {
+ name: "compressed_bar",
+ apk: "prebuilts/apk/app.apk",
+ presigned: true,
+ filename: "bar_sample.apk",
+ compress_apk: true,
}
`)
@@ -347,16 +410,30 @@
expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
},
{
+ name: "foo_compressed",
+ expected: "foo_compressed.apk.gz",
+ onDevice: "/system/app/foo_compressed/foo_compressed.apk.gz",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo_compressed/provenance_metadata.textproto",
+ },
+ {
name: "bar",
expected: "bar_sample.apk",
onDevice: "/system/app/bar/bar_sample.apk",
expectedArtifactPath: "prebuilts/apk/app.apk",
expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
},
+ {
+ name: "compressed_bar",
+ expected: "bar_sample.apk",
+ onDevice: "/system/app/compressed_bar/bar_sample.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/compressed_bar/provenance_metadata.textproto",
+ },
}
for _, test := range testCases {
- variant := ctx.ModuleForTests(test.name, "android_common")
+ variant := ctx.ModuleForTests(t, test.name, "android_common")
if variant.MaybeOutput(test.expected).Rule == nil {
t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
}
@@ -380,6 +457,7 @@
}
func TestAndroidAppImport_ArchVariants(t *testing.T) {
+ t.Parallel()
// The test config's target arch is ARM64.
testCases := []struct {
name string
@@ -505,9 +583,10 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, test.bp)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
if test.expected == "" {
if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
t.Error("module should have been disabled, but wasn't")
@@ -530,6 +609,7 @@
}
func TestAndroidAppImport_SoongConfigVariables(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -572,6 +652,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
android.PrepareForTestWithSoongConfigModuleBuildComponents,
@@ -584,7 +665,7 @@
}),
).RunTestWithBp(t, test.bp).TestContext
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
if test.expected == "" {
if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
t.Error("module should have been disabled, but wasn't")
@@ -607,6 +688,7 @@
}
func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app {
name: "foo",
@@ -622,7 +704,7 @@
}
`)
- variant := ctx.ModuleForTests("prebuilt_foo", "android_common")
+ variant := ctx.ModuleForTests(t, "prebuilt_foo", "android_common")
a := variant.Module().(*AndroidAppImport)
// The prebuilt module should still be enabled and active even if the source-based counterpart
// is disabled.
@@ -635,6 +717,7 @@
}
func TestAndroidAppImport_relativeInstallPath(t *testing.T) {
+ t.Parallel()
bp := `
android_app_import {
name: "no_relative_install_path",
@@ -664,28 +747,49 @@
}{
{
name: "no_relative_install_path",
- expectedInstallPath: "out/soong/target/product/test_device/system/app/no_relative_install_path/no_relative_install_path.apk",
+ expectedInstallPath: "out/target/product/test_device/system/app/no_relative_install_path/no_relative_install_path.apk",
errorMessage: "Install path is not correct when relative_install_path is missing",
},
{
name: "relative_install_path",
- expectedInstallPath: "out/soong/target/product/test_device/system/app/my/path/relative_install_path/relative_install_path.apk",
+ expectedInstallPath: "out/target/product/test_device/system/app/my/path/relative_install_path/relative_install_path.apk",
errorMessage: "Install path is not correct for app when relative_install_path is present",
},
{
name: "privileged_relative_install_path",
- expectedInstallPath: "out/soong/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk",
+ expectedInstallPath: "out/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk",
errorMessage: "Install path is not correct for privileged app when relative_install_path is present",
},
}
for _, testCase := range testCases {
- ctx, _ := testJava(t, bp)
- mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*AndroidAppImport)
- android.AssertPathRelativeToTopEquals(t, testCase.errorMessage, testCase.expectedInstallPath, mod.installPath)
+ t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
+ ctx, _ := testJava(t, bp)
+ mod := ctx.ModuleForTests(t, testCase.name, "android_common").Module().(*AndroidAppImport)
+ android.AssertPathRelativeToTopEquals(t, testCase.errorMessage, testCase.expectedInstallPath, mod.installPath)
+ })
}
}
+func TestAndroidAppImport_ExtractApk(t *testing.T) {
+ t.Parallel()
+ ctx, _ := testJava(t, `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ certificate: "platform",
+ extract_apk: "extract_path/sub_app.apk"
+ }
+ `)
+
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
+ extractRuleArgs := variant.Output("extract-apk/foo.apk").BuildParams.Args
+ if extractRuleArgs["extract_apk"] != "extract_path/sub_app.apk" {
+ t.Errorf("Unexpected extract apk args: %s", extractRuleArgs["extract_apk"])
+ }
+}
func TestAndroidTestImport(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_test_import {
name: "foo",
@@ -697,7 +801,7 @@
}
`)
- test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
+ test := ctx.ModuleForTests(t, "foo", "android_common").Module().(*AndroidTestImport)
// Check android mks.
entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
@@ -714,6 +818,7 @@
}
func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_test_import {
name: "foo",
@@ -734,16 +839,16 @@
}
`)
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
jniRule := variant.Output("jnis-uncompressed/foo.apk").BuildParams.Rule.String()
if jniRule == android.Cp.String() {
- t.Errorf("Unexpected JNI uncompress rule command: " + jniRule)
+ t.Errorf("Unexpected JNI uncompress rule command: %s", jniRule)
}
- variant = ctx.ModuleForTests("foo_presigned", "android_common")
+ variant = ctx.ModuleForTests(t, "foo_presigned", "android_common")
jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
if jniRule != android.Cp.String() {
- t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+ t.Errorf("Unexpected JNI uncompress rule: %s", jniRule)
}
if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
t.Errorf("Presigned test apk should be aligned")
@@ -751,6 +856,7 @@
}
func TestAndroidTestImport_Preprocessed(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_test_import {
name: "foo",
@@ -761,10 +867,10 @@
`)
apkName := "foo.apk"
- variant := ctx.ModuleForTests("foo", "android_common")
+ variant := ctx.ModuleForTests(t, "foo", "android_common")
jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
if jniRule != android.Cp.String() {
- t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
+ t.Errorf("Unexpected JNI uncompress rule: %s", jniRule)
}
// Make sure signing and aligning were skipped.
@@ -777,9 +883,11 @@
}
func TestAndroidAppImport_Preprocessed(t *testing.T) {
+ t.Parallel()
for _, dontUncompressPrivAppDexs := range []bool{false, true} {
name := fmt.Sprintf("dontUncompressPrivAppDexs:%t", dontUncompressPrivAppDexs)
t.Run(name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -804,10 +912,10 @@
// non-privileged app
apkName := "foo.apk"
- variant := result.ModuleForTests("foo", "android_common")
+ variant := result.ModuleForTests(t, "foo", "android_common")
outputBuildParams := variant.Output(apkName).BuildParams
if outputBuildParams.Rule.String() != android.Cp.String() {
- t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
+ t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String())
}
// Make sure compression and aligning were validated.
@@ -817,7 +925,7 @@
validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
- t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
+ t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String())
}
expectedScriptArgs := "--preprocessed"
@@ -826,10 +934,10 @@
// privileged app
apkName = "bar.apk"
- variant = result.ModuleForTests("bar", "android_common")
+ variant = result.ModuleForTests(t, "bar", "android_common")
outputBuildParams = variant.Output(apkName).BuildParams
if outputBuildParams.Rule.String() != android.Cp.String() {
- t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
+ t.Errorf("Unexpected prebuilt android_app_import rule: %s", outputBuildParams.Rule.String())
}
// Make sure compression and aligning were validated.
@@ -839,7 +947,7 @@
validationBuildParams = variant.Output("validated-prebuilt/check.stamp").BuildParams
if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
- t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
+ t.Errorf("Unexpected validation rule: %s", validationBuildParams.Rule.String())
}
expectedScriptArgs = "--privileged"
@@ -854,6 +962,7 @@
}
func TestAndroidTestImport_UncompressDex(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -894,7 +1003,7 @@
}),
).RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
actual := foo.MaybeRule("uncompress-dex").Rule != nil
expect := !unbundled
@@ -917,6 +1026,7 @@
name := fmt.Sprintf("%s,unbundled:%t,dontUncompressPrivAppDexs:%t",
tt.name, unbundled, dontUncompressPrivAppDexs)
t.Run(name, func(t *testing.T) {
+ t.Parallel()
test(t, tt.bp, unbundled, dontUncompressPrivAppDexs)
})
}
@@ -925,6 +1035,7 @@
}
func TestAppImportMissingCertificateAllowMissingDependencies(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAllowMissingDependencies,
@@ -936,7 +1047,7 @@
certificate: ":missing_certificate",
}`)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
fooApk := foo.Output("signed/foo.apk")
if fooApk.Rule != android.ErrorRule {
t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
diff --git a/java/app_set.go b/java/app_set.go
index 7997570..6a2c678 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -192,6 +192,12 @@
},
)
+ android.SetProvider(ctx, AppInfoProvider, &AppInfo{
+ AppSet: true,
+ Privileged: as.Privileged(),
+ OutputFile: as.OutputFile(),
+ ApkCertsFile: as.apkcertsFile,
+ })
}
func (as *AndroidAppSet) InstallBypassMake() bool { return true }
diff --git a/java/app_set_test.go b/java/app_set_test.go
index c02b359..9b4c44b 100644
--- a/java/app_set_test.go
+++ b/java/app_set_test.go
@@ -24,13 +24,14 @@
)
func TestAndroidAppSet(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app_set {
name: "foo",
set: "prebuilts/apks/app.apks",
prerelease: true,
}`)
- module := result.ModuleForTests("foo", "android_common")
+ module := result.ModuleForTests(t, "foo", "android_common")
const packedSplitApks = "foo.zip"
params := module.Output(packedSplitApks)
if params.Rule == nil {
@@ -65,6 +66,7 @@
}
func TestAndroidAppSet_Variants(t *testing.T) {
+ t.Parallel()
bp := `
android_app_set {
name: "foo",
@@ -113,24 +115,24 @@
}
for _, test := range testCases {
- ctx := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
- variables.Platform_sdk_version = &test.sdkVersion
- }),
- android.FixtureModifyConfig(func(config android.Config) {
- config.Targets[android.Android] = test.targets
- }),
- ).RunTestWithBp(t, bp)
+ t.Run(test.name, func(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
+ variables.Platform_sdk_version = &test.sdkVersion
+ }),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.Targets[android.Android] = test.targets
+ }),
+ ).RunTestWithBp(t, bp)
- module := ctx.ModuleForTests("foo", "android_common")
- const packedSplitApks = "foo.zip"
- params := module.Output(packedSplitApks)
- for k, v := range test.expected {
- t.Run(test.name, func(t *testing.T) {
+ module := ctx.ModuleForTests(t, "foo", "android_common")
+ const packedSplitApks = "foo.zip"
+ params := module.Output(packedSplitApks)
+ for k, v := range test.expected {
android.AssertStringEquals(t, fmt.Sprintf("arg value for `%s`", k), v, params.Args[k])
- })
- }
+ }
+ })
}
}
diff --git a/java/app_test.go b/java/app_test.go
index e9422a6..c6b22c7 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -18,6 +18,7 @@
"fmt"
"path/filepath"
"reflect"
+ "regexp"
"sort"
"strings"
"testing"
@@ -41,6 +42,7 @@
}
func TestApp(t *testing.T) {
+ t.Parallel()
resourceFiles := []string{
"res/layout/layout.xml",
"res/values/strings.xml",
@@ -55,6 +57,7 @@
for _, moduleType := range []string{"android_app", "android_library"} {
t.Run(moduleType, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureModifyMockFS(func(fs android.MockFS) {
@@ -69,15 +72,15 @@
}
`)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
var expectedLinkImplicits []string
manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
- frameworkRes := result.ModuleForTests("framework-res", "android_common")
- omniromRes := result.ModuleForTests("omnirom-res", "android_common")
+ frameworkRes := result.ModuleForTests(t, "framework-res", "android_common")
+ omniromRes := result.ModuleForTests(t,"omnirom-res", "android_common")
expectedLinkImplicits = append(expectedLinkImplicits,
frameworkRes.Output("package-res.apk").Output.String())
expectedLinkImplicits = append(expectedLinkImplicits,
@@ -96,13 +99,14 @@
expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
// Check that the link rule uses
- res := result.ModuleForTests("foo", "android_common").Output("package-res.apk")
+ res := result.ModuleForTests(t, "foo", "android_common").Output("package-res.apk")
android.AssertDeepEquals(t, "aapt2 link implicits", expectedLinkImplicits, res.Implicits.Strings())
})
}
}
func TestAppSplits(t *testing.T) {
+ t.Parallel()
ctx := testApp(t, `
android_app {
name: "foo",
@@ -111,7 +115,7 @@
sdk_version: "current"
}`)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
expectedOutputs := []string{
"out/soong/.intermediates/foo/android_common/foo.apk",
@@ -127,6 +131,7 @@
}
func TestPlatformAPIs(t *testing.T) {
+ t.Parallel()
testJava(t, `
android_app {
name: "foo",
@@ -161,6 +166,7 @@
}
func TestAndroidAppLinkType(t *testing.T) {
+ t.Parallel()
testJava(t, `
android_app {
name: "foo",
@@ -250,6 +256,7 @@
}
func TestUpdatableApps(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -361,6 +368,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
errorHandler := android.FixtureExpectsNoErrors
if test.expectedError != "" {
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
@@ -375,6 +383,7 @@
}
func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
+ t.Parallel()
testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
android_app {
name: "foo",
@@ -393,6 +402,7 @@
}
func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
+ t.Parallel()
testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
android_app {
name: "foo",
@@ -413,6 +423,7 @@
}
func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
+ t.Parallel()
bp := cc.GatherRequiredDepsForTest(android.Android) + `
android_app {
name: "foo",
@@ -440,11 +451,11 @@
ctx, _ := testJavaWithFS(t, bp, fs)
- inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
+ inputs := ctx.ModuleForTests(t, "libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
var crtbeginFound, crtendFound bool
- expectedCrtBegin := ctx.ModuleForTests("crtbegin_so",
+ expectedCrtBegin := ctx.ModuleForTests(t, "crtbegin_so",
"android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
- expectedCrtEnd := ctx.ModuleForTests("crtend_so",
+ expectedCrtEnd := ctx.ModuleForTests(t, "crtend_so",
"android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
implicits := []string{}
for _, input := range inputs {
@@ -468,6 +479,7 @@
}
func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) {
+ t.Parallel()
bp := cc.GatherRequiredDepsForTest(android.Android) + `
android_app {
name: "foo",
@@ -489,6 +501,7 @@
}
func TestUpdatableApps_ErrorIfDepMinSdkVersionIsHigher(t *testing.T) {
+ t.Parallel()
bp := cc.GatherRequiredDepsForTest(android.Android) + `
android_app {
name: "foo",
@@ -520,6 +533,7 @@
}
func TestUpdatableApps_ApplyDefaultUpdatableModuleVersion(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -531,7 +545,7 @@
updatable: true,
}
`)
- foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+ foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer")
android.AssertStringDoesContain(t,
"com.android.foo: expected manifest fixer to set override-placeholder-version to RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION",
foo.BuildParams.Args["args"],
@@ -540,6 +554,7 @@
}
func TestUpdatableApps_ApplyOverrideApexManifestDefaultVersion(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureMergeEnv(map[string]string{
@@ -554,7 +569,7 @@
updatable: true,
}
`)
- foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+ foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer")
android.AssertStringDoesContain(t,
"com.android.foo: expected manifest fixer to set override-placeholder-version to 1234",
foo.BuildParams.Args["args"],
@@ -563,6 +578,7 @@
}
func TestResourceDirs(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
prop string
@@ -599,12 +615,13 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
fs.AddToFixture(),
).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop))
- module := result.ModuleForTests("foo", "android_common")
+ module := result.ModuleForTests(t, "foo", "android_common")
resourceList := module.MaybeOutput("aapt2/res.list")
var resources []string
@@ -620,6 +637,7 @@
}
func TestLibraryAssets(t *testing.T) {
+ t.Parallel()
bp := `
android_app {
name: "foo",
@@ -714,7 +732,8 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
- m := ctx.ModuleForTests(test.name, "android_common")
+ t.Parallel()
+ m := ctx.ModuleForTests(t, test.name, "android_common")
// Check asset flag in aapt2 link flags
var aapt2link android.TestingBuildParams
@@ -749,6 +768,7 @@
}
func TestAppJavaResources(t *testing.T) {
+ t.Parallel()
bp := `
android_app {
name: "foo",
@@ -766,7 +786,7 @@
ctx := testApp(t, bp)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
fooResources := foo.Output("res/foo.jar")
fooDexJar := foo.Output("dex-withres/foo.jar")
fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
@@ -784,7 +804,7 @@
t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
}
- bar := ctx.ModuleForTests("bar", "android_common")
+ bar := ctx.ModuleForTests(t, "bar", "android_common")
barResources := bar.Output("res/bar.jar")
barApk := bar.Rule("combineApk")
@@ -794,6 +814,7 @@
}
func TestAndroidResourceProcessor(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
appUsesRP bool
@@ -869,15 +890,24 @@
},
appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
appClasspath: []string{
- "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/turbine-combined/direct_import.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
+ "out/soong/.intermediates/direct/android_common/turbine/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.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/combined/direct_import.jar",
+ "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/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.jar",
},
directResources: nil,
@@ -890,21 +920,23 @@
directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
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/turbine-combined/transitive_import.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.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/combined/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
},
transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
transitiveOverlays: nil,
transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
transitiveSrcJars: []string{"out/soong/.intermediates/transitive/android_common/gen/android/R.srcjar"},
- transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar"},
+ transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar"},
transitiveCombined: nil,
sharedResources: nil,
@@ -918,9 +950,9 @@
},
sharedSrcJars: []string{"out/soong/.intermediates/shared/android_common/gen/android/R.srcjar"},
sharedClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.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",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/turbine/shared_transitive_shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
},
sharedCombined: []string{
"out/soong/.intermediates/shared/android_common/javac/shared.jar",
@@ -967,17 +999,26 @@
},
appSrcJars: nil,
appClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
"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/turbine-combined/direct_import.jar",
+ "out/soong/.intermediates/shared/android_common/turbine/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
+ "out/soong/.intermediates/direct/android_common/turbine/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.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/combined/direct_import.jar",
+ "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/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.jar",
},
directResources: nil,
@@ -990,18 +1031,20 @@
},
directSrcJars: nil,
directClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.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/turbine-combined/transitive_import.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.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/combined/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
},
transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -1009,7 +1052,7 @@
transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
transitiveSrcJars: nil,
transitiveClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
"out/soong/.intermediates/transitive/android_common/busybox/R.jar",
},
transitiveCombined: nil,
@@ -1023,12 +1066,12 @@
},
sharedSrcJars: nil,
sharedClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/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_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
- "out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/turbine/shared_transitive_shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
},
sharedCombined: []string{
"out/soong/.intermediates/shared/android_common/javac/shared.jar",
@@ -1072,18 +1115,27 @@
},
appSrcJars: nil,
appClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
// R.jar has to come before direct.jar
"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/turbine-combined/direct_import.jar",
+ "out/soong/.intermediates/shared/android_common/turbine/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
+ "out/soong/.intermediates/direct/android_common/turbine/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.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/combined/direct_import.jar",
+ "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/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.jar",
},
dontVerifyDirect: true,
@@ -1115,15 +1167,24 @@
},
appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
appClasspath: []string{
- "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/turbine-combined/direct_import.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
+ "out/soong/.intermediates/direct/android_common/turbine/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.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/combined/direct_import.jar",
+ "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/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.jar",
},
directResources: nil,
@@ -1136,17 +1197,19 @@
},
directSrcJars: nil,
directClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.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/turbine-combined/transitive_import.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.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/combined/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
},
dontVerifyTransitive: true,
@@ -1177,15 +1240,24 @@
},
appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
appClasspath: []string{
- "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/turbine-combined/direct_import.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine/shared_transitive_static.jar",
+ "out/soong/.intermediates/direct/android_common/turbine/direct.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.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/combined/direct_import.jar",
+ "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/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
+ "out/soong/.intermediates/direct_import/android_common/aar/direct_import.jar",
+ "out/soong/.intermediates/direct_import_dep/android_common/aar/direct_import_dep.jar",
},
directResources: nil,
@@ -1198,14 +1270,16 @@
directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
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/turbine-combined/transitive_import.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
+ "out/soong/.intermediates/transitive/android_common/turbine/transitive.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.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/combined/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import/android_common/aar/transitive_import.jar",
+ "out/soong/.intermediates/transitive_import_dep/android_common/aar/transitive_import_dep.jar",
},
transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
@@ -1213,7 +1287,7 @@
transitiveImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
transitiveSrcJars: nil,
transitiveClasspath: []string{
- "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine/android_stubs_current.jar",
"out/soong/.intermediates/transitive/android_common/busybox/R.jar",
},
transitiveCombined: nil,
@@ -1226,6 +1300,7 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
bp := fmt.Sprintf(`
android_app {
name: "app",
@@ -1333,7 +1408,7 @@
}
getAaptInfo := func(moduleName string) (aaptInfo aaptInfo) {
- mod := result.ModuleForTests(moduleName, "android_common")
+ mod := result.ModuleForTests(t, moduleName, "android_common")
resourceListRule := mod.MaybeOutput("aapt2/res.list")
overlayListRule := mod.MaybeOutput("aapt2/overlay.list")
aaptRule := mod.Rule("aapt2Link")
@@ -1422,6 +1497,7 @@
}
func TestAndroidResourceOverlays(t *testing.T) {
+ t.Parallel()
type moduleAndVariant struct {
module string
variant string
@@ -1460,7 +1536,6 @@
"device/vendor/blah/overlay/bar/res/values/strings.xml",
},
{"lib", "android_common"}: {
- "out/soong/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
"device/vendor/blah/overlay/lib/res/values/strings.xml",
},
@@ -1495,12 +1570,10 @@
"device/vendor/blah/overlay/bar/res/values/strings.xml",
},
{"lib", "android_common"}: {
- "out/soong/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
"device/vendor/blah/overlay/lib/res/values/strings.xml",
},
{"lib", "android_common_rro"}: {
- "out/soong/.intermediates/lib2/android_common_rro/package-res.apk",
"lib/res/res/values/strings.xml",
},
},
@@ -1540,7 +1613,6 @@
},
{"bar", "android_common"}: {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
{"lib", "android_common"}: {
- "out/soong/.intermediates/lib2/android_common/package-res.apk",
"lib/res/res/values/strings.xml",
},
},
@@ -1618,6 +1690,7 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
fs.AddToFixture(),
@@ -1649,7 +1722,7 @@
}
getResources := func(moduleName, variantName string) (resourceFiles, overlayFiles, rroDirs []string) {
- module := result.ModuleForTests(moduleName, variantName)
+ module := result.ModuleForTests(t, moduleName, variantName)
resourceList := module.MaybeOutput("aapt2/res.list")
if resourceList.Rule != nil {
resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs))
@@ -1708,7 +1781,7 @@
}
func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersion string) {
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
link := foo.Output("package-res.apk")
linkFlags := strings.Split(link.Args["flags"], " ")
min := android.IndexList("--min-sdk-version", linkFlags)
@@ -1727,6 +1800,7 @@
}
func TestAppSdkVersion(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
sdkVersion string
@@ -1794,6 +1868,7 @@
for _, moduleType := range []string{"android_app", "android_library"} {
for _, test := range testCases {
t.Run(moduleType+" "+test.name, func(t *testing.T) {
+ t.Parallel()
platformApiProp := ""
if test.platformApis {
platformApiProp = "platform_apis: true,"
@@ -1830,6 +1905,7 @@
}
func TestVendorAppSdkVersion(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
sdkVersion string
@@ -1872,6 +1948,7 @@
for _, sdkKind := range []string{"", "system_"} {
for _, test := range testCases {
t.Run(moduleType+" "+test.name, func(t *testing.T) {
+ t.Parallel()
bp := fmt.Sprintf(`%s {
name: "foo",
srcs: ["a.java"],
@@ -1903,6 +1980,7 @@
}
func TestJNIABI(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
name: "libjni",
@@ -1959,7 +2037,8 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
- app := ctx.ModuleForTests(test.name, "android_common")
+ t.Parallel()
+ app := ctx.ModuleForTests(t, test.name, "android_common")
jniLibZip := app.Output("jnilibs.zip")
var abis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
@@ -1977,6 +2056,7 @@
}
func TestAppSdkVersionByPartition(t *testing.T) {
+ t.Parallel()
testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
android_app {
name: "foo",
@@ -2021,6 +2101,7 @@
}
func TestJNIPackaging(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
name: "libjni",
@@ -2092,7 +2173,8 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
- app := ctx.ModuleForTests(test.name, "android_common")
+ t.Parallel()
+ app := ctx.ModuleForTests(t, test.name, "android_common")
jniLibZip := app.MaybeOutput("jnilibs.zip")
if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
t.Errorf("expected jni packaged %v, got %v", w, g)
@@ -2112,6 +2194,7 @@
}
func TestJNISDK(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
name: "libjni",
@@ -2173,16 +2256,17 @@
{name: "app_vendor", vendorJNI: true},
}
- platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
+ platformJNI := ctx.ModuleForTests(t, "libjni", "android_arm64_armv8-a_shared").
Output("libjni.so").Output.String()
- sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
+ sdkJNI := ctx.ModuleForTests(t, "libjni", "android_arm64_armv8-a_sdk_shared").
Output("libjni.so").Output.String()
- vendorJNI := ctx.ModuleForTests("libvendorjni", "android_vendor_arm64_armv8-a_shared").
+ vendorJNI := ctx.ModuleForTests(t, "libvendorjni", "android_vendor_arm64_armv8-a_shared").
Output("libvendorjni.so").Output.String()
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
- app := ctx.ModuleForTests(test.name, "android_common")
+ t.Parallel()
+ app := ctx.ModuleForTests(t, test.name, "android_common")
jniLibZip := app.MaybeOutput("jnilibs.zip")
if len(jniLibZip.Implicits) != 1 {
@@ -2207,6 +2291,7 @@
}
t.Run("jni_uses_platform_apis_error", func(t *testing.T) {
+ t.Parallel()
testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, `
android_test {
name: "app_platform",
@@ -2217,6 +2302,7 @@
})
t.Run("jni_uses_sdk_apis_error", func(t *testing.T) {
+ t.Parallel()
testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, `
android_test {
name: "app_sdk",
@@ -2229,6 +2315,7 @@
}
func TestCertificates(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -2366,6 +2453,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -2381,7 +2469,7 @@
}),
).RunTestWithBp(t, test.bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
certificate := foo.Module().(*AndroidApp).certificate
android.AssertPathRelativeToTopEquals(t, "certificates key", test.expectedCertificate+".pk8", certificate.Key)
@@ -2403,6 +2491,7 @@
}
func TestRequestV4SigningFlag(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -2447,11 +2536,12 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, test.bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
signapk := foo.Output("foo.apk")
signFlags := signapk.Args["flags"]
@@ -2461,6 +2551,7 @@
}
func TestPackageNameOverride(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -2479,7 +2570,7 @@
packageNameOverride: "",
expected: []string{
"out/soong/.intermediates/foo/android_common/foo.apk",
- "out/soong/target/product/test_device/system/app/foo/foo.apk",
+ "out/target/product/test_device/system/app/foo/foo.apk",
},
},
{
@@ -2495,7 +2586,7 @@
expected: []string{
// The package apk should be still be the original name for test dependencies.
"out/soong/.intermediates/foo/android_common/bar.apk",
- "out/soong/target/product/test_device/system/app/bar/bar.apk",
+ "out/target/product/test_device/system/app/bar/bar.apk",
},
},
{
@@ -2511,13 +2602,14 @@
packageNameOverride: "",
expected: []string{
"out/soong/.intermediates/foo/android_common/bar.apk",
- "out/soong/target/product/test_device/system/app/bar/bar.apk",
+ "out/target/product/test_device/system/app/bar/bar.apk",
},
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -2527,7 +2619,7 @@
}),
).RunTestWithBp(t, test.bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
outSoongDir := result.Config.SoongOutDir()
@@ -2546,6 +2638,7 @@
}
func TestInstrumentationTargetOverridden(t *testing.T) {
+ t.Parallel()
bp := `
android_app {
name: "foo",
@@ -2567,7 +2660,7 @@
}),
).RunTestWithBp(t, bp)
- bar := result.ModuleForTests("bar", "android_common")
+ bar := result.ModuleForTests(t, "bar", "android_common")
res := bar.Output("package-res.apk")
aapt2Flags := res.Args["flags"]
e := "--rename-instrumentation-target-package org.dandroid.bp"
@@ -2577,6 +2670,7 @@
}
func TestOverrideAndroidApp(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
t, `
android_app {
@@ -2654,7 +2748,7 @@
name: "foo",
moduleName: "foo",
variantName: "android_common",
- apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk",
+ apkPath: "out/target/product/test_device/system/app/foo/foo.apk",
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
certSigningFlags: "",
overrides: []string{"qux"},
@@ -2666,7 +2760,7 @@
name: "foo",
moduleName: "bar",
variantName: "android_common_bar",
- apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk",
+ apkPath: "out/target/product/test_device/system/app/bar/bar.apk",
certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8",
certSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
overrides: []string{"qux", "foo"},
@@ -2678,7 +2772,7 @@
name: "foo",
moduleName: "baz",
variantName: "android_common_baz",
- apkPath: "out/soong/target/product/test_device/system/app/baz/baz.apk",
+ apkPath: "out/target/product/test_device/system/app/baz/baz.apk",
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
certSigningFlags: "",
overrides: []string{"qux", "foo"},
@@ -2690,7 +2784,7 @@
name: "foo",
moduleName: "baz_no_rename_resources",
variantName: "android_common_baz_no_rename_resources",
- apkPath: "out/soong/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk",
+ apkPath: "out/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk",
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
certSigningFlags: "",
overrides: []string{"qux", "foo"},
@@ -2702,7 +2796,7 @@
name: "foo_no_rename_resources",
moduleName: "baz_base_no_rename_resources",
variantName: "android_common_baz_base_no_rename_resources",
- apkPath: "out/soong/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk",
+ apkPath: "out/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk",
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
certSigningFlags: "",
overrides: []string{"qux", "foo_no_rename_resources"},
@@ -2714,7 +2808,7 @@
name: "foo_no_rename_resources",
moduleName: "baz_override_base_rename_resources",
variantName: "android_common_baz_override_base_rename_resources",
- apkPath: "out/soong/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk",
+ apkPath: "out/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk",
certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
certSigningFlags: "",
overrides: []string{"qux", "foo_no_rename_resources"},
@@ -2724,7 +2818,7 @@
},
}
for _, expected := range expectedVariants {
- variant := result.ModuleForTests(expected.name, expected.variantName)
+ variant := result.ModuleForTests(t, expected.name, expected.variantName)
// Check the final apk name
variant.Output(expected.apkPath)
@@ -2759,6 +2853,7 @@
}
func TestOverrideAndroidAppOverrides(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(
t, `
android_app {
@@ -2808,7 +2903,7 @@
},
}
for _, expected := range expectedVariants {
- variant := ctx.ModuleForTests(expected.name, expected.variantName)
+ variant := ctx.ModuleForTests(t, expected.name, expected.variantName)
// Check if the overrides field values are correctly aggregated.
mod := variant.Module().(*AndroidApp)
@@ -2817,6 +2912,7 @@
}
func TestOverrideAndroidAppWithPrebuilt(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
t, `
android_app {
@@ -2839,19 +2935,20 @@
`)
// An app that has an override that also has a prebuilt should not be hidden.
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
if foo.Module().IsHideFromMake() {
t.Errorf("expected foo to have HideFromMake false")
}
// An override that also has a prebuilt should be hidden.
- barOverride := result.ModuleForTests("foo", "android_common_bar")
+ barOverride := result.ModuleForTests(t, "foo", "android_common_bar")
if !barOverride.Module().IsHideFromMake() {
t.Errorf("expected bar override variant of foo to have HideFromMake true")
}
}
func TestOverrideAndroidAppStem(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app {
name: "foo",
@@ -2891,41 +2988,42 @@
{
moduleName: "foo",
variantName: "android_common",
- apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk",
+ apkPath: "out/target/product/test_device/system/app/foo/foo.apk",
},
{
moduleName: "foo",
variantName: "android_common_bar",
- apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk",
+ apkPath: "out/target/product/test_device/system/app/bar/bar.apk",
},
{
moduleName: "foo",
variantName: "android_common_baz",
- apkPath: "out/soong/target/product/test_device/system/app/baz_stem/baz_stem.apk",
+ apkPath: "out/target/product/test_device/system/app/baz_stem/baz_stem.apk",
},
{
moduleName: "foo2",
variantName: "android_common",
- apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
+ apkPath: "out/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
},
{
moduleName: "foo2",
variantName: "android_common_bar2",
// Note that this may cause the duplicate output error.
- apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
+ apkPath: "out/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
},
{
moduleName: "foo2",
variantName: "android_common_baz2",
- apkPath: "out/soong/target/product/test_device/system/app/baz2_stem/baz2_stem.apk",
+ apkPath: "out/target/product/test_device/system/app/baz2_stem/baz2_stem.apk",
},
} {
- variant := ctx.ModuleForTests(expected.moduleName, expected.variantName)
+ variant := ctx.ModuleForTests(t, expected.moduleName, expected.variantName)
variant.Output(expected.apkPath)
}
}
func TestOverrideAndroidAppDependency(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app {
name: "foo",
@@ -2953,15 +3051,15 @@
`)
// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
- javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
- fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar"
+ javac := ctx.ModuleForTests(t, "baz", "android_common").Rule("javac")
+ fooTurbine := "out/soong/.intermediates/foo/android_common/turbine/foo.jar"
if !strings.Contains(javac.Args["classpath"], fooTurbine) {
t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
}
// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
- javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
- barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar"
+ javac = ctx.ModuleForTests(t, "qux", "android_common").Rule("javac")
+ barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine/foo.jar"
if !strings.Contains(javac.Args["classpath"], barTurbine) {
t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
}
@@ -3024,10 +3122,10 @@
},
}
for _, expected := range expectedVariants {
- variant := ctx.ModuleForTests("foo_test", expected.variantName)
+ variant := ctx.ModuleForTests(t, "foo_test", expected.variantName)
// Check the final apk name
- variant.Output("out/soong" + expected.apkPath)
+ variant.Output("out" + expected.apkPath)
// Check if the overrides field values are correctly aggregated.
mod := variant.Module().(*AndroidTest)
@@ -3038,7 +3136,7 @@
// Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides.
javac := variant.Rule("javac")
- turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar")
+ turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine", "foo.jar")
if !strings.Contains(javac.Args["classpath"], turbine) {
t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine)
}
@@ -3115,7 +3213,7 @@
}
for _, test := range testCases {
- variant := ctx.ModuleForTests(test.moduleName, test.variantName)
+ variant := ctx.ModuleForTests(t, test.moduleName, test.variantName)
params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml")
if len(test.expectedFlags) > 0 {
@@ -3161,6 +3259,7 @@
}
func TestStl(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
name: "libjni",
@@ -3203,7 +3302,8 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
- app := ctx.ModuleForTests(test.name, "android_common")
+ t.Parallel()
+ app := ctx.ModuleForTests(t, test.name, "android_common")
jniLibZip := app.Output("jnilibs.zip")
var jnis []string
args := strings.Fields(jniLibZip.Args["jarArgs"])
@@ -3380,8 +3480,8 @@
}),
).RunTestWithBp(t, bp)
- app := result.ModuleForTests("app", "android_common")
- prebuilt := result.ModuleForTests("prebuilt", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
+ prebuilt := result.ModuleForTests(t, "prebuilt", "android_common")
// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
// These also include explicit `uses_libs`/`optional_uses_libs` entries, as they may be
@@ -3433,6 +3533,7 @@
}
func TestDexpreoptBcp(t *testing.T) {
+ t.Parallel()
bp := `
java_sdk_library {
name: "foo",
@@ -3475,6 +3576,7 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -3484,7 +3586,7 @@
dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with),
).RunTestWithBp(t, bp)
- app := result.ModuleForTests("app", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
cmd := app.Rule("dexpreopt").RuleParams.Command
bcp := " -Xbootclasspath-locations:" + test.expect + " " // space at the end matters
android.AssertStringDoesContain(t, "dexpreopt app bcp", cmd, bcp)
@@ -3493,6 +3595,7 @@
}
func TestCodelessApp(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -3557,9 +3660,10 @@
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
ctx := testApp(t, test.bp)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
@@ -3569,6 +3673,7 @@
}
func TestUncompressDex(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -3656,7 +3761,7 @@
}),
).RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
dex := foo.Rule("r8")
uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
aligned := foo.MaybeRule("zipalign").Rule != nil
@@ -3668,10 +3773,13 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
t.Run("platform", func(t *testing.T) {
+ t.Parallel()
test(t, tt.bp, tt.uncompressedPlatform, false)
})
t.Run("unbundled", func(t *testing.T) {
+ t.Parallel()
test(t, tt.bp, tt.uncompressedUnbundled, true)
})
})
@@ -3693,6 +3801,7 @@
}
func TestExportedProguardFlagFiles(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
android_app {
name: "foo",
@@ -3738,7 +3847,7 @@
`)
- m := ctx.ModuleForTests("foo", "android_common")
+ m := ctx.ModuleForTests(t, "foo", "android_common")
r8 := m.Rule("java.r8")
implicits := r8.Implicits.RelativeToTop().Strings()
android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg")
@@ -3754,6 +3863,7 @@
}
func TestTargetSdkVersionManifestFixer(t *testing.T) {
+ t.Parallel()
platform_sdk_codename := "Tiramisu"
platform_sdk_version := 33
testCases := []struct {
@@ -3806,43 +3916,47 @@
},
}
for _, testCase := range testCases {
- targetSdkVersionTemplate := ""
- if testCase.targetSdkVersionInBp != "" {
- targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, testCase.targetSdkVersionInBp)
- }
- bp := fmt.Sprintf(`
+ t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
+ targetSdkVersionTemplate := ""
+ if testCase.targetSdkVersionInBp != "" {
+ targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, testCase.targetSdkVersionInBp)
+ }
+ bp := fmt.Sprintf(`
android_app {
name: "foo",
sdk_version: "current",
%s
}
`, targetSdkVersionTemplate)
- fixture := android.GroupFixturePreparers(
- prepareForJavaTest,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- if testCase.platformSdkFinal {
- variables.Platform_sdk_final = proptools.BoolPtr(true)
- }
- // explicitly set platform_sdk_codename to make the test deterministic
- variables.Platform_sdk_codename = &platform_sdk_codename
- variables.Platform_sdk_version = &platform_sdk_version
- variables.Platform_version_active_codenames = []string{platform_sdk_codename}
- // create a non-empty list if unbundledBuild==true
- if testCase.unbundledBuild {
- variables.Unbundled_build_apps = []string{"apex_a", "apex_b"}
- }
- }),
- )
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if testCase.platformSdkFinal {
+ variables.Platform_sdk_final = proptools.BoolPtr(true)
+ }
+ // explicitly set platform_sdk_codename to make the test deterministic
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Platform_sdk_version = &platform_sdk_version
+ variables.Platform_version_active_codenames = []string{platform_sdk_codename}
+ // create a non-empty list if unbundledBuild==true
+ if testCase.unbundledBuild {
+ variables.Unbundled_build_apps = []string{"apex_a", "apex_b"}
+ }
+ }),
+ )
- result := fixture.RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ result := fixture.RunTestWithBp(t, bp)
+ foo := result.ModuleForTests(t, "foo", "android_common")
- manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ })
}
}
func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) {
+ t.Parallel()
platform_sdk_codename := "Tiramisu"
platform_sdk_version := 33
testCases := []struct {
@@ -3898,11 +4012,13 @@
},
}
for _, testCase := range testCases {
- targetSdkVersionTemplate := ""
- if testCase.targetSdkVersionInBp != nil {
- targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, *testCase.targetSdkVersionInBp)
- }
- bp := fmt.Sprintf(`
+ t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
+ targetSdkVersionTemplate := ""
+ if testCase.targetSdkVersionInBp != nil {
+ targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, *testCase.targetSdkVersionInBp)
+ }
+ bp := fmt.Sprintf(`
android_app {
name: "foo",
sdk_version: "current",
@@ -3913,30 +4029,32 @@
}
`, targetSdkVersionTemplate, testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
- fixture := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.PrepareForTestWithAllowMissingDependencies,
- android.PrepareForTestWithAndroidMk,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- // explicitly set following platform variables to make the test deterministic
- variables.Platform_sdk_final = &testCase.platform_sdk_final
- variables.Platform_sdk_version = &platform_sdk_version
- variables.Platform_sdk_codename = &platform_sdk_codename
- variables.Platform_version_active_codenames = []string{platform_sdk_codename}
- variables.Unbundled_build = proptools.BoolPtr(true)
- variables.Unbundled_build_apps = []string{"sampleModule"}
- }),
- )
+ fixture := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // explicitly set following platform variables to make the test deterministic
+ variables.Platform_sdk_final = &testCase.platform_sdk_final
+ variables.Platform_sdk_version = &platform_sdk_version
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Platform_version_active_codenames = []string{platform_sdk_codename}
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ variables.Unbundled_build_apps = []string{"sampleModule"}
+ }),
+ )
- result := fixture.RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ result := fixture.RunTestWithBp(t, bp)
+ foo := result.ModuleForTests(t, "foo", "android_common")
- manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected)
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected)
+ })
}
}
func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) {
+ t.Parallel()
platform_sdk_codename := "Tiramisu"
platform_sdk_version := 33
testCases := []struct {
@@ -3981,8 +4099,10 @@
},
}
for _, testCase := range testCases {
- errExpected := testCase.expectedError != ""
- bp := fmt.Sprintf(`
+ t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
+ errExpected := testCase.expectedError != ""
+ bp := fmt.Sprintf(`
android_app {
name: "foo",
enforce_default_target_sdk_version: %t,
@@ -3993,35 +4113,37 @@
}
`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable)
- fixture := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.PrepareForTestWithAllowMissingDependencies,
- android.PrepareForTestWithAndroidMk,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- // explicitly set following platform variables to make the test deterministic
- variables.Platform_sdk_final = &testCase.platform_sdk_final
- variables.Platform_sdk_version = &platform_sdk_version
- variables.Platform_sdk_codename = &platform_sdk_codename
- variables.Unbundled_build = proptools.BoolPtr(true)
- variables.Unbundled_build_apps = []string{"sampleModule"}
- }),
- )
+ fixture := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // explicitly set following platform variables to make the test deterministic
+ variables.Platform_sdk_final = &testCase.platform_sdk_final
+ variables.Platform_sdk_version = &platform_sdk_version
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ variables.Unbundled_build_apps = []string{"sampleModule"}
+ }),
+ )
- errorHandler := android.FixtureExpectsNoErrors
- if errExpected {
- errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
- }
- result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
+ errorHandler := android.FixtureExpectsNoErrors
+ if errExpected {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
+ }
+ result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
- if !errExpected {
- foo := result.ModuleForTests("foo", "android_common")
- manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
- }
+ if !errExpected {
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ }
+ })
}
}
func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) {
+ t.Parallel()
platform_sdk_codename := "Tiramisu"
platform_sdk_version := 33
testCases := []struct {
@@ -4054,8 +4176,10 @@
},
}
for _, testCase := range testCases {
- errExpected := testCase.expectedError != ""
- bp := fmt.Sprintf(`
+ t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
+ errExpected := testCase.expectedError != ""
+ bp := fmt.Sprintf(`
android_test {
name: "foo",
enforce_default_target_sdk_version: %t,
@@ -4064,35 +4188,37 @@
}
`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp)
- fixture := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.PrepareForTestWithAllowMissingDependencies,
- android.PrepareForTestWithAndroidMk,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- // explicitly set following platform variables to make the test deterministic
- variables.Platform_sdk_final = &testCase.platform_sdk_final
- variables.Platform_sdk_version = &platform_sdk_version
- variables.Platform_sdk_codename = &platform_sdk_codename
- variables.Unbundled_build = proptools.BoolPtr(true)
- variables.Unbundled_build_apps = []string{"sampleModule"}
- }),
- )
+ fixture := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // explicitly set following platform variables to make the test deterministic
+ variables.Platform_sdk_final = &testCase.platform_sdk_final
+ variables.Platform_sdk_version = &platform_sdk_version
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ variables.Unbundled_build_apps = []string{"sampleModule"}
+ }),
+ )
- errorHandler := android.FixtureExpectsNoErrors
- if errExpected {
- errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
- }
- result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
+ errorHandler := android.FixtureExpectsNoErrors
+ if errExpected {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
+ }
+ result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
- if !errExpected {
- foo := result.ModuleForTests("foo", "android_common")
- manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
- }
+ if !errExpected {
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ }
+ })
}
}
func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAllowMissingDependencies,
@@ -4113,7 +4239,7 @@
sdk_version: "current",
}`)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
fooApk := foo.Output("foo.apk")
if fooApk.Rule != android.ErrorRule {
t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
@@ -4122,6 +4248,7 @@
}
func TestAppIncludesJniPackages(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -4184,7 +4311,8 @@
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- app := ctx.ModuleForTests(tc.name, "android_common")
+ t.Parallel()
+ app := ctx.ModuleForTests(t, tc.name, "android_common")
outputFile := "jnilibs.zip"
jniOutputLibZip := app.MaybeOutput(outputFile)
@@ -4208,6 +4336,7 @@
}
func TestTargetSdkVersionMtsTests(t *testing.T) {
+ t.Parallel()
platformSdkCodename := "Tiramisu"
android_test := "android_test"
android_test_helper_app := "android_test_helper_app"
@@ -4263,14 +4392,18 @@
}),
)
for _, testCase := range testCases {
- result := fixture.RunTestWithBp(t, fmt.Sprintf(bpTemplate, testCase.moduleType, testCase.targetSdkVersionInBp, testCase.testSuites))
- mytest := result.ModuleForTests("mytest", "android_common")
- manifestFixerArgs := mytest.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ t.Run(testCase.desc, func(t *testing.T) {
+ t.Parallel()
+ result := fixture.RunTestWithBp(t, fmt.Sprintf(bpTemplate, testCase.moduleType, testCase.targetSdkVersionInBp, testCase.testSuites))
+ mytest := result.ModuleForTests(t, "mytest", "android_common")
+ manifestFixerArgs := mytest.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ })
}
}
func TestPrivappAllowlist(t *testing.T) {
+ t.Parallel()
testJavaError(t, "privileged must be set in order to use privapp_allowlist", `
android_app {
name: "foo",
@@ -4296,8 +4429,8 @@
}
`,
)
- app := result.ModuleForTests("foo", "android_common")
- overrideApp := result.ModuleForTests("foo", "android_common_bar")
+ app := result.ModuleForTests(t, "foo", "android_common")
+ overrideApp := result.ModuleForTests(t, "foo", "android_common_bar")
// verify that privapp allowlist is created for override apps
overrideApp.Output("out/soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml")
@@ -4308,11 +4441,12 @@
}
// verify that permissions are copied to device
- app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml")
- overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml")
+ app.Output("out/target/product/test_device/system/etc/permissions/foo.xml")
+ overrideApp.Output("out/target/product/test_device/system/etc/permissions/bar.xml")
}
func TestPrivappAllowlistAndroidMk(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAndroidMk,
@@ -4333,8 +4467,8 @@
}
`,
)
- baseApp := result.ModuleForTests("foo", "android_common")
- overrideApp := result.ModuleForTests("foo", "android_common_bar")
+ baseApp := result.ModuleForTests(t, "foo", "android_common")
+ overrideApp := result.ModuleForTests(t, "foo", "android_common_bar")
baseAndroidApp := baseApp.Module().(*AndroidApp)
baseEntries := android.AndroidMkEntriesForTest(t, result.TestContext, baseAndroidApp)[0]
@@ -4392,6 +4526,7 @@
}
func TestAppFlagsPackages(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureMergeMockFs(
@@ -4429,7 +4564,7 @@
}
`)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
// android_app module depends on aconfig_declarations listed in flags_packages
android.AssertBoolEquals(t, "foo expected to depend on bar", true,
@@ -4456,6 +4591,7 @@
}
func TestAppFlagsPackagesPropagation(t *testing.T) {
+ t.Parallel()
ctx := testApp(t, `
aconfig_declarations {
name: "foo",
@@ -4513,7 +4649,7 @@
}
`)
- bazApp := ctx.ModuleForTests("baz_app", "android_common")
+ bazApp := ctx.ModuleForTests(t, "baz_app", "android_common")
// android_app module depends on aconfig_declarations listed in flags_packages
// and that of static libs, but not libs
@@ -4533,6 +4669,7 @@
// Test that dexpreopt is disabled if an optional_uses_libs exists, but does not provide an implementation.
func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) {
+ t.Parallel()
bp := `
java_sdk_library_import {
name: "sdklib_noimpl",
@@ -4550,7 +4687,7 @@
}
`
result := prepareForJavaTest.RunTestWithBp(t, bp)
- dexpreopt := result.ModuleForTests("app", "android_common").MaybeRule("dexpreopt").Rule
+ dexpreopt := result.ModuleForTests(t, "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)
}
@@ -4592,7 +4729,77 @@
assertTestOnlyAndTopLevel(t, ctx, expectedTestOnly, expectedTopLevel)
}
+func TestTestConfigTemplate(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ android_test {
+ name: "android-test",
+ test_config_template: "AndroidTestTemplate.xml",
+ test_options: {
+ tradefed_options: [
+ {
+ name: "name1",
+ key: "key1",
+ value: "value1",
+ },
+ {
+ name: "name2",
+ key: "key2",
+ value: "value2",
+ },
+ ],
+ test_runner_options: [
+ {
+ name: "name3",
+ key: "key3",
+ value: "value3",
+ },
+ {
+ name: "name4",
+ key: "key4",
+ value: "value4",
+ },
+ ],
+ },
+ }
+ `)
+ type option struct {
+ name string
+ key string
+ value string
+ }
+ re := regexp.MustCompile(`<option name="(.*)" key="(.*)" value="(.*)" />`)
+ parse_options := func(optionsString string) []option {
+ lines := strings.Split(optionsString, `\n`)
+ var ret []option
+ for _, l := range lines {
+ sm := re.FindStringSubmatch(l)
+ if sm == nil {
+ continue
+ }
+ ret = append(ret, option{sm[1], sm[2], sm[3]})
+ }
+ return ret
+ }
+ rule := ctx.ModuleForTests(t, "android-test", "android_common").Rule("autogenInstrumentationTest")
+ android.AssertSameArray(t, "extraConfigs mismatch",
+ []option{
+ {"name1", "key1", "value1"},
+ {"name2", "key2", "value2"},
+ },
+ parse_options(rule.Args["extraConfigs"]))
+ android.AssertSameArray(t, "extraTestRunnerConfigs mismatch",
+ []option{
+ {"name3", "key3", "value3"},
+ {"name4", "key4", "value4"},
+ },
+ parse_options(rule.Args["extraTestRunnerConfigs"]))
+}
+
func TestAppStem(t *testing.T) {
+ t.Parallel()
ctx := testApp(t, `
android_app {
name: "foo",
@@ -4601,7 +4808,7 @@
sdk_version: "current",
}`)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
outputs := fmt.Sprint(foo.AllOutputs())
if !strings.Contains(outputs, "foo-new.apk") {
@@ -4610,6 +4817,7 @@
}
func TestAppMinSdkVersionOverride(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -4626,8 +4834,8 @@
min_sdk_version: "33",
}
`)
- foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
- fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer")
+ foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer")
+ fooOverride := result.ModuleForTests(t, "com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer")
android.AssertStringDoesContain(t,
"com.android.foo: expected manifest fixer to set minSdkVersion to T",
@@ -4643,6 +4851,7 @@
}
func TestNotApplyDefaultUpdatableModuleVersion(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -4653,7 +4862,7 @@
min_sdk_version: "31",
}
`)
- foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+ foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer")
android.AssertStringDoesNotContain(t,
"com.android.foo: expected manifest fixer to not set override-placeholder-version",
foo.BuildParams.Args["args"],
@@ -4662,6 +4871,7 @@
}
func TestNotApplyOverrideApexManifestDefaultVersion(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureMergeEnv(map[string]string{
@@ -4675,7 +4885,7 @@
min_sdk_version: "31",
}
`)
- foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
+ foo := result.ModuleForTests(t, "com.android.foo", "android_common").Rule("manifestFixer")
android.AssertStringDoesNotContain(t,
"com.android.foo: expected manifest fixer to not set override-placeholder-version",
foo.BuildParams.Args["args"],
@@ -4684,6 +4894,7 @@
}
func TestResourcesWithFlagDirectories(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureMergeMockFs(android.MockFS{
@@ -4702,7 +4913,7 @@
],
}
`)
- fooModule := result.ModuleForTests("foo", "android_common")
+ fooModule := result.ModuleForTests(t, "foo", "android_common")
compileOutputPaths := fooModule.Rule("aapt2Compile").Outputs.Strings()
android.AssertStringListContains(
@@ -4788,17 +4999,20 @@
},
}
for _, tc := range testCases {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.EnforceRROTargets = []string{"*"}
- }),
- android.OptionalFixturePreparer(tc.preparer),
- ).RunTestWithBp(t, bp)
- vendorOverlayApk := result.ModuleForTests("foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("foo__test_product__auto_generated_rro_vendor.apk")
- android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, vendorOverlayApk.Rule != nil)
- overrideVendorOverlayApk := result.ModuleForTests("override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("override_foo__test_product__auto_generated_rro_vendor.apk")
- android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.Rule != nil)
+ t.Run(tc.desc, func(t *testing.T) {
+ t.Parallel()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.EnforceRROTargets = []string{"*"}
+ }),
+ android.OptionalFixturePreparer(tc.preparer),
+ ).RunTestWithBp(t, bp)
+ vendorOverlayApk := result.ModuleForTests(t, "foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("foo__test_product__auto_generated_rro_vendor.apk")
+ android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, vendorOverlayApk.Rule != nil)
+ overrideVendorOverlayApk := result.ModuleForTests(t, "override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("override_foo__test_product__auto_generated_rro_vendor.apk")
+ android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.Rule != nil)
+ })
}
}
@@ -4855,22 +5069,25 @@
},
}
for _, tc := range testCases {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.PrepareForTestWithSoongConfigModuleBuildComponents,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.EnforceRROTargets = []string{"*"}
- }),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.DeviceResourceOverlays = []string{"device/company/test_product"}
- }),
- android.MockFS{
- "res/foo.xml": nil,
- "device/company/test_product/res/foo.xml": nil,
- }.AddToFixture(),
- android.OptionalFixturePreparer(tc.preparer),
- ).RunTestWithBp(t, bp)
- overrideVendorOverlayApk := result.ModuleForTests("override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").Module().(*AutogenRuntimeResourceOverlay)
- android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.exportPackage != nil)
+ t.Run(tc.desc, func(t *testing.T) {
+ t.Parallel()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithSoongConfigModuleBuildComponents,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.EnforceRROTargets = []string{"*"}
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceResourceOverlays = []string{"device/company/test_product"}
+ }),
+ android.MockFS{
+ "res/foo.xml": nil,
+ "device/company/test_product/res/foo.xml": nil,
+ }.AddToFixture(),
+ android.OptionalFixturePreparer(tc.preparer),
+ ).RunTestWithBp(t, bp)
+ overrideVendorOverlayApk := result.ModuleForTests(t, "override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").Module().(*AutogenRuntimeResourceOverlay)
+ android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.exportPackage != nil)
+ })
}
}
diff --git a/java/base.go b/java/base.go
index c0ac4ab..8aa0109 100644
--- a/java/base.go
+++ b/java/base.go
@@ -60,6 +60,9 @@
// This is most useful in the arch/multilib variants to remove non-common files
Exclude_srcs []string `android:"path,arch_variant"`
+ // list of Kotlin source files that should excluded from the list of common_srcs.
+ Exclude_common_srcs []string `android:"path,arch_variant"`
+
// list of directories containing Java resources
Java_resource_dirs []string `android:"arch_variant"`
@@ -87,6 +90,10 @@
// list of module-specific flags that will be used for kotlinc compiles
Kotlincflags []string `android:"arch_variant"`
+ // Kotlin language version to target. Currently only 1.9 and 2 are supported.
+ // See kotlinc's `-language-version` flag.
+ Kotlin_lang_version *string
+
// list of java libraries that will be in the classpath
Libs []string `android:"arch_variant"`
@@ -106,6 +113,10 @@
// if not blank, used as prefix to generate repackage rule
Jarjar_prefix *string
+ // Number of shards for jarjar. It needs to be an integer represented as a string.
+ // TODO(b/383559945) change it to int, once Configurable supports the type.
+ Jarjar_shards proptools.Configurable[string]
+
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -362,13 +373,13 @@
e.initSdkLibraryComponent(module)
}
-// Module/Import's DepIsInSameApex(...) delegates to this method.
+// Module/Import's OutgoingDepIsInSameApex(...) delegates to this method.
//
-// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with
+// This cannot implement OutgoingDepIsInSameApex(...) directly as that leads to ambiguity with
// the one provided by ApexModuleBase.
-func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+func depIsInSameApex(tag blueprint.DependencyTag) bool {
// dependencies other than the static linkage are all considered crossing APEX boundary
- if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
+ if tag == staticLibTag {
return true
}
return false
@@ -618,7 +629,7 @@
return nil
}
if info.SdkVersion.Kind == android.SdkCorePlatform {
- if useLegacyCorePlatformApi(ctx, android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).BaseModuleName) {
+ if useLegacyCorePlatformApi(ctx, android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).BaseModuleName) {
return fmt.Errorf("non stable SDK %v - uses legacy core platform", info.SdkVersion)
} else {
// Treat stable core platform as stable.
@@ -645,14 +656,17 @@
// Make sure this module doesn't statically link to modules with lower-ranked SDK link type.
// See rank() for details.
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(module)
- switch module.(type) {
- // TODO(satayev): cover other types as well, e.g. imports
- case *Library, *AndroidLibrary:
+ libInfo, isJavaLibrary := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider)
+ _, isAndroidLibrary := android.OtherModuleProvider(ctx, module, AndroidLibraryInfoProvider)
+ _, isJavaAconfigLibrary := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider)
+ // Exclude java_aconfig_library modules to maintain consistency with existing behavior.
+ if (isJavaLibrary && !libInfo.Prebuilt && !isJavaAconfigLibrary) || isAndroidLibrary {
+ // TODO(satayev): cover other types as well, e.g. imports
switch tag {
case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag:
- j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag))
+ j.checkSdkLinkType(ctx, module)
}
}
})
@@ -835,13 +849,18 @@
}
func (j *Module) AvailableFor(what string) bool {
- if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) {
+ return android.CheckAvailableForApex(what, j.ApexAvailableFor())
+}
+
+func (j *Module) ApexAvailableFor() []string {
+ list := j.ApexModuleBase.ApexAvailable()
+ if Bool(j.deviceProperties.Hostdex) {
// Exception: for hostdex: true libraries, the platform variant is created
// even if it's not marked as available to platform. In that case, the platform
// variant is used only for the hostdex and not installed to the device.
- return true
+ list = append(list, android.AvailableToPlatform)
}
- return j.ApexModuleBase.AvailableFor(what)
+ return android.FirstUniqueStrings(list)
}
func (j *Module) staticLibs(ctx android.BaseModuleContext) []string {
@@ -869,6 +888,10 @@
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
+ // Add dependency on (soft) downstream libs from which to trace references during optimization.
+ traceRefs := j.dexProperties.Optimize.Trace_references_from.GetOrDefault(ctx, []string{})
+ ctx.AddVariationDependencies(nil, traceReferencesTag, traceRefs...)
+
// For library dependencies that are component libraries (like stubs), add the implementation
// as a dependency (dexpreopt needs to be against the implementation library, not stubs).
for _, dep := range libDeps {
@@ -922,7 +945,7 @@
if j.useCompose(ctx) {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
- "androidx.compose.compiler_compiler-hosted-plugin")
+ "kotlin-compose-compiler-plugin")
}
}
@@ -1141,7 +1164,7 @@
j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
}
-func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, extraDepCombinedJars android.Paths) {
+func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, extraDepCombinedJars android.Paths) *JavaInfo {
// Auto-propagating jarjar rules
jarjarProviderData := j.collectJarJarRules(ctx)
if jarjarProviderData != nil {
@@ -1182,7 +1205,7 @@
flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
}
- kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil)
+ kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, j.properties.Exclude_common_srcs)
if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
}
@@ -1229,7 +1252,6 @@
uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
j.uniqueSrcFiles = uniqueSrcFiles
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()})
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
@@ -1265,7 +1287,7 @@
localHeaderJars, combinedHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
extraCombinedJars)
- combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine")
+ combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false)
if jarjared {
localHeaderJars = android.Paths{combinedHeaderJarFile}
transitiveStaticLibsHeaderJars = nil
@@ -1276,22 +1298,19 @@
transitiveStaticLibsHeaderJars = nil
}
if ctx.Failed() {
- return
+ return nil
}
j.headerJarFile = combinedHeaderJarFile
- if ctx.Config().UseTransitiveJarsInClasspath() {
- if len(localHeaderJars) > 0 {
- ctx.CheckbuildFile(localHeaderJars...)
- } else {
- // There are no local sources or resources in this module, so there is nothing to checkbuild.
- ctx.UncheckedModule()
- }
+ if len(localHeaderJars) > 0 {
+ ctx.CheckbuildFile(localHeaderJars...)
} else {
- ctx.CheckbuildFile(j.headerJarFile)
+ // There are no local sources or resources in this module, so there is nothing to checkbuild.
+ ctx.UncheckedModule()
}
- android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ j.outputFile = j.headerJarFile
+ return &JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
LocalHeaderJars: localHeaderJars,
TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
@@ -1304,10 +1323,7 @@
StubsLinkType: j.stubsLinkType,
AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
SdkVersion: j.SdkVersion(ctx),
- })
-
- j.outputFile = j.headerJarFile
- return
+ }
}
if srcFiles.HasExt(".kt") {
@@ -1320,6 +1336,26 @@
kotlincFlags := j.properties.Kotlincflags
CheckKotlincFlags(ctx, kotlincFlags)
+ // Available kotlin versions can be found at
+ // https://github.com/JetBrains/kotlin/blob/master/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt#L560
+ // in the `LanguageVersion` class.
+ // For now, avoid targeting language versions directly, as we'd like to kee our source
+ // code version aligned as much as possible. Ideally, after defaulting to "2", we
+ // can remove the "1.9" option entirely, or at least make it emit a warning.
+ kotlin_default_lang_version := "1.9"
+ if build_flag_lang_version, ok := ctx.Config().GetBuildFlag("RELEASE_KOTLIN_LANG_VERSION"); ok {
+ kotlin_default_lang_version = build_flag_lang_version
+ }
+ kotlin_lang_version := proptools.StringDefault(j.properties.Kotlin_lang_version, kotlin_default_lang_version)
+ switch kotlin_lang_version {
+ case "1.9":
+ kotlincFlags = append(kotlincFlags, "-language-version 1.9")
+ case "2":
+ kotlincFlags = append(kotlincFlags, "-Xsuppress-version-warnings", "-Xconsistent-data-class-copy-visibility")
+ default:
+ ctx.PropertyErrorf("kotlin_lang_version", "Must be one of `1.9` or `2`")
+ }
+
// Workaround for KT-46512
kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class")
@@ -1364,7 +1400,7 @@
kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
if ctx.Failed() {
- return
+ return nil
}
kotlinJarPath, _ := j.repackageFlagsIfNecessary(ctx, kotlinJar, jarName, "kotlinc")
@@ -1401,7 +1437,7 @@
shardingHeaderJars = localHeaderJars
var jarjared bool
- j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine")
+ j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine", false)
if jarjared {
// jarjar modifies transitive static dependencies, use the combined header jar and drop the transitive
// static libs header jars.
@@ -1434,20 +1470,27 @@
// build.
flags = enableErrorproneFlags(flags)
} else if hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil {
- // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
- // a new jar file just for compiling with the errorprone compiler to.
- // This is because we don't want to cause the java files to get completely
- // rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
- // We also don't want to run this if errorprone is enabled by default for
- // this module, or else we could have duplicated errorprone messages.
- errorproneFlags := enableErrorproneFlags(flags)
- errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
- errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
+ if ctx.Config().RunErrorProneInline() {
+ // On CI, we're not going to toggle back/forth between errorprone and non-errorprone
+ // builds, so it's faster if we don't compile the module twice and instead always
+ // compile the module with errorprone.
+ flags = enableErrorproneFlags(flags)
+ } else {
+ // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
+ // a new jar file just for compiling with the errorprone compiler to.
+ // This is because we don't want to cause the java files to get completely
+ // rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
+ // We also don't want to run this if errorprone is enabled by default for
+ // this module, or else we could have duplicated errorprone messages.
+ errorproneFlags := enableErrorproneFlags(flags)
+ errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
+ errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
- transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
- "errorprone", "errorprone")
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
+ "errorprone", "errorprone")
- extraJarDeps = append(extraJarDeps, errorprone)
+ extraJarDeps = append(extraJarDeps, errorprone)
+ }
}
if enableSharding {
@@ -1484,7 +1527,7 @@
localImplementationJars = append(localImplementationJars, classes)
}
if ctx.Failed() {
- return
+ return nil
}
}
@@ -1524,7 +1567,7 @@
resourceJar := android.PathForModuleOut(ctx, "res", jarName)
TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
if ctx.Failed() {
- return
+ return nil
}
localResourceJars = append(localResourceJars, resourceJar)
}
@@ -1561,12 +1604,7 @@
completeStaticLibsResourceJars := depset.New(depset.PREORDER, localResourceJars, deps.transitiveStaticLibsResourceJars)
var combinedResourceJar android.Path
- var resourceJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- resourceJars = completeStaticLibsResourceJars.ToList()
- } else {
- resourceJars = append(slices.Clone(localResourceJars), deps.staticResourceJars...)
- }
+ resourceJars := completeStaticLibsResourceJars.ToList()
if len(resourceJars) == 1 {
combinedResourceJar = resourceJars[0]
} else if len(resourceJars) > 0 {
@@ -1587,12 +1625,7 @@
completeStaticLibsImplementationJars := depset.New(depset.PREORDER, localImplementationJars, deps.transitiveStaticLibsImplementationJars)
- var jars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- jars = completeStaticLibsImplementationJars.ToList()
- } else {
- jars = append(slices.Clone(localImplementationJars), deps.staticJars...)
- }
+ jars := completeStaticLibsImplementationJars.ToList()
jars = append(jars, extraDepCombinedJars...)
@@ -1628,7 +1661,7 @@
}
// jarjar implementation jar if necessary
- jarjarFile, jarjarred := j.jarjarIfNecessary(ctx, outputFile, jarName, "")
+ jarjarFile, jarjarred := j.jarjarIfNecessary(ctx, outputFile, jarName, "", true)
if jarjarred {
localImplementationJars = android.Paths{jarjarFile}
completeStaticLibsImplementationJars = depset.New(depset.PREORDER, localImplementationJars, nil)
@@ -1637,7 +1670,7 @@
// jarjar resource jar if necessary
if combinedResourceJar != nil {
- resourceJarJarFile, jarjarred := j.jarjarIfNecessary(ctx, combinedResourceJar, jarName, "resource")
+ resourceJarJarFile, jarjarred := j.jarjarIfNecessary(ctx, combinedResourceJar, jarName, "resource", false)
combinedResourceJar = resourceJarJarFile
if jarjarred {
localResourceJars = android.Paths{resourceJarJarFile}
@@ -1646,7 +1679,7 @@
}
if ctx.Failed() {
- return
+ return nil
}
if j.ravenizer.enabled {
@@ -1710,7 +1743,7 @@
CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
if ctx.Failed() {
- return
+ return nil
}
}
@@ -1723,7 +1756,7 @@
headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName)
convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile)
j.headerJarFile = headerJarFile
- if len(localImplementationJars) == 1 && ctx.Config().UseTransitiveJarsInClasspath() {
+ if len(localImplementationJars) == 1 {
localHeaderJarFile := android.PathForModuleOut(ctx, "local-javac-header", jarName)
convertImplementationJarToHeaderJar(ctx, localImplementationJars[0], localHeaderJarFile)
localHeaderJars = append(localHeaderJars, localHeaderJarFile)
@@ -1735,7 +1768,7 @@
// enforce syntax check to jacoco filters for any build (http://b/183622051)
specs := j.jacocoModuleToZipCommand(ctx)
if ctx.Failed() {
- return
+ return nil
}
completeStaticLibsImplementationJarsToCombine := completeStaticLibsImplementationJars
@@ -1753,16 +1786,10 @@
// merge implementation jar with resources if necessary
var implementationAndResourcesJarsToCombine android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- resourceJars := completeStaticLibsResourceJars.ToList()
- if len(resourceJars) > 0 {
- implementationAndResourcesJarsToCombine = append(resourceJars, completeStaticLibsImplementationJarsToCombine.ToList()...)
- implementationAndResourcesJarsToCombine = append(implementationAndResourcesJarsToCombine, extraDepCombinedJars...)
- }
- } else {
- if combinedResourceJar != nil {
- implementationAndResourcesJarsToCombine = android.Paths{combinedResourceJar, outputFile}
- }
+ combinedResourceJars := completeStaticLibsResourceJars.ToList()
+ if len(combinedResourceJars) > 0 {
+ implementationAndResourcesJarsToCombine = slices.Concat(combinedResourceJars,
+ completeStaticLibsImplementationJarsToCombine.ToList(), extraDepCombinedJars)
}
if len(implementationAndResourcesJarsToCombine) > 0 {
@@ -1789,7 +1816,7 @@
classesJar: outputFile,
jarName: jarName,
}
- if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting(ctx) {
+ if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled(ctx) && !j.EnableProfileRewriting(ctx) {
ctx.PropertyErrorf("enable_profile_rewriting",
"Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.",
)
@@ -1803,7 +1830,7 @@
}
dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params)
if ctx.Failed() {
- return
+ return nil
}
// If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
@@ -1812,18 +1839,9 @@
}
// merge dex jar with resources if necessary
- var dexAndResourceJarsToCombine android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- resourceJars := completeStaticLibsResourceJars.ToList()
- if len(resourceJars) > 0 {
- dexAndResourceJarsToCombine = append(android.Paths{dexOutputFile}, resourceJars...)
- }
- } else {
- if combinedResourceJar != nil {
- dexAndResourceJarsToCombine = android.Paths{dexOutputFile, combinedResourceJar}
- }
- }
- if len(dexAndResourceJarsToCombine) > 0 {
+ if len(combinedResourceJars) > 0 {
+ dexAndResourceJarsToCombine := append(android.Paths{dexOutputFile}, combinedResourceJars...)
+
combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
TransformJarsToJar(ctx, combinedJar, "for dex resources", dexAndResourceJarsToCombine, android.OptionalPath{},
false, nil, nil)
@@ -1862,7 +1880,7 @@
}
if ctx.Failed() {
- return
+ return nil
}
}
@@ -1895,21 +1913,19 @@
j.collectTransitiveSrcFiles(ctx, srcFiles)
- if ctx.Config().UseTransitiveJarsInClasspath() {
- if len(localImplementationJars) > 0 || len(localResourceJars) > 0 || len(localHeaderJars) > 0 {
- ctx.CheckbuildFile(localImplementationJars...)
- ctx.CheckbuildFile(localResourceJars...)
- ctx.CheckbuildFile(localHeaderJars...)
- } else {
- // There are no local sources or resources in this module, so there is nothing to checkbuild.
- ctx.UncheckedModule()
- }
+ if len(localImplementationJars) > 0 || len(localResourceJars) > 0 || len(localHeaderJars) > 0 {
+ ctx.CheckbuildFile(localImplementationJars...)
+ ctx.CheckbuildFile(localResourceJars...)
+ ctx.CheckbuildFile(localHeaderJars...)
} else {
- ctx.CheckbuildFile(j.implementationJarFile)
- ctx.CheckbuildFile(j.headerJarFile)
+ // There are no local sources or resources in this module, so there is nothing to checkbuild.
+ ctx.UncheckedModule()
}
- android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
+ j.outputFile = outputFile.WithoutRel()
+
+ return &JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
RepackagedHeaderJars: android.PathsIfNonNil(repackagedHeaderJarFile),
@@ -1934,10 +1950,8 @@
StubsLinkType: j.stubsLinkType,
AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles,
SdkVersion: j.SdkVersion(ctx),
- })
-
- // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
- j.outputFile = outputFile.WithoutRel()
+ OutputFile: j.outputFile,
+ }
}
func (j *Module) useCompose(ctx android.BaseModuleContext) bool {
@@ -1945,7 +1959,7 @@
}
func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []depset.DepSet[android.Path]) {
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
depTag := ctx.OtherModuleDependencyTag(m)
@@ -2041,7 +2055,9 @@
} else if strings.HasPrefix(flag, "-Xintellij-plugin-root") {
ctx.PropertyErrorf("kotlincflags",
"Bad flag: `%s`, only use internal compiler for consistency.", flag)
- } else if inList(flag, config.KotlincIllegalFlags) {
+ } else if slices.ContainsFunc(config.KotlincIllegalFlags, func(f string) bool {
+ return strings.HasPrefix(flag, f)
+ }) {
ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag)
} else if flag == "-include-runtime" {
ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag)
@@ -2070,13 +2086,8 @@
// Combine any static header libraries into classes-header.jar. If there is only
// one input jar this step will be skipped.
- var jars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- depSet := depset.New(depset.PREORDER, localHeaderJars, deps.transitiveStaticLibsHeaderJars)
- jars = depSet.ToList()
- } else {
- jars = append(slices.Clone(localHeaderJars), deps.staticHeaderJars...)
- }
+ depSet := depset.New(depset.PREORDER, localHeaderJars, deps.transitiveStaticLibsHeaderJars)
+ jars := depSet.ToList()
// we cannot skip the combine step for now if there is only one jar
// since we have to strip META-INF/TRANSITIVE dir from turbine.jar
@@ -2116,7 +2127,7 @@
directStaticLibs := android.Paths{}
transitiveLibs := []depset.DepSet[android.Path]{}
transitiveStaticLibs := []depset.DepSet[android.Path]{}
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
// don't add deps of the prebuilt version of the same library
if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
return
@@ -2184,6 +2195,8 @@
func (j *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
if j.expandJarjarRules != nil {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
+ }
+ if j.headerJarFile != nil {
// Add the header jar so that the rdeps can be resolved to the repackaged classes.
dpInfo.Jars = append(dpInfo.Jars, j.headerJarFile.String())
}
@@ -2202,29 +2215,33 @@
func (j *Module) hasCode(ctx android.ModuleContext) bool {
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
- return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
+ return len(srcFiles) > 0 || len(ctx.GetDirectDepsProxyWithTag(staticLibTag)) > 0
}
// Implements android.ApexModule
-func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return j.depIsInSameApex(ctx, dep)
+func (m *Module) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return JavaDepInSameApexChecker{}
+}
+
+type JavaDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m JavaDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return depIsInSameApex(tag)
}
// Implements android.ApexModule
-func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
+func (j *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
sdkVersionSpec := j.SdkVersion(ctx)
minSdkVersion := j.MinSdkVersion(ctx)
- if !minSdkVersion.Specified() {
- return fmt.Errorf("min_sdk_version is not specified")
- }
+
// If the module is compiling against core (via sdk_version), skip comparison check.
if sdkVersionSpec.Kind == android.SdkCore {
- return nil
+ return android.MinApiLevel
}
- if minSdkVersion.GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", minSdkVersion)
- }
- return nil
+
+ return minSdkVersion
}
func (j *Module) Stem() string {
@@ -2240,7 +2257,7 @@
func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
var fromDeps []depset.DepSet[android.Path]
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(module)
if tag == staticLibTag {
if depInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
@@ -2359,7 +2376,7 @@
// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
// this module's. See the comment on rank() for details and an example.
func (j *Module) checkSdkLinkType(
- ctx android.ModuleContext, dep moduleWithSdkDep, tag dependencyTag) {
+ ctx android.ModuleContext, dep android.ModuleProxy) {
if ctx.Host() {
return
}
@@ -2368,7 +2385,12 @@
if stubs {
return
}
- depLinkType, _ := dep.getSdkLinkType(ctx, ctx.OtherModuleName(dep))
+ info, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
+ if !ok || info.ModuleWithSdkDepInfo == nil {
+ panic(fmt.Errorf("dependency doesn't have ModuleWithSdkDepInfo: %v", dep))
+ }
+
+ depLinkType := info.ModuleWithSdkDepInfo.SdkLinkType
if myLinkType.rank() < depLinkType.rank() {
ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+
@@ -2393,7 +2415,7 @@
var transitiveStaticJarsImplementationLibs []depset.DepSet[android.Path]
var transitiveStaticJarsResourceLibs []depset.DepSet[android.Path]
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -2427,7 +2449,7 @@
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
case sdkLibTag, libTag, instrumentationForTag:
- if _, ok := module.(*Plugin); ok {
+ if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName)
}
deps.classpath = append(deps.classpath, dep.HeaderJars...)
@@ -2445,7 +2467,7 @@
deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
transitiveJava9ClasspathHeaderJars = append(transitiveJava9ClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
case staticLibTag:
- if _, ok := module.(*Plugin); ok {
+ if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName)
}
deps.classpath = append(deps.classpath, dep.HeaderJars...)
@@ -2465,40 +2487,40 @@
transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, dep.TransitiveStaticLibsImplementationJars)
transitiveStaticJarsResourceLibs = append(transitiveStaticJarsResourceLibs, dep.TransitiveStaticLibsResourceJars)
case pluginTag:
- if plugin, ok := module.(*Plugin); ok {
- if plugin.pluginProperties.Processor_class != nil {
- addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.pluginProperties.Processor_class)
+ if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
+ if plugin.ProcessorClass != nil {
+ addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.ProcessorClass)
} else {
addPlugins(&deps, dep.ImplementationAndResourcesJars)
}
// Turbine doesn't run annotation processors, so any module that uses an
// annotation processor that generates API is incompatible with the turbine
// optimization.
- deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
+ deps.disableTurbine = deps.disableTurbine || plugin.GeneratesApi
} else {
ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
}
case errorpronePluginTag:
- if _, ok := module.(*Plugin); ok {
+ if _, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...)
} else {
ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
}
case exportedPluginTag:
- if plugin, ok := module.(*Plugin); ok {
+ if plugin, ok := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider); ok {
j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...)
- if plugin.pluginProperties.Processor_class != nil {
- j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class)
+ if plugin.ProcessorClass != nil {
+ j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.ProcessorClass)
}
// Turbine doesn't run annotation processors, so any module that uses an
// annotation processor that generates API is incompatible with the turbine
// optimization.
- j.exportedDisableTurbine = Bool(plugin.pluginProperties.Generates_api)
+ j.exportedDisableTurbine = plugin.GeneratesApi
} else {
ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
}
case kotlinPluginTag:
- if _, ok := module.(*KotlinPlugin); ok {
+ if _, ok := android.OtherModuleProvider(ctx, module, KotlinPluginInfoProvider); ok {
deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
} else {
ctx.PropertyErrorf("kotlin_plugins", "%q is not a kotlin_plugin module", otherName)
@@ -2510,21 +2532,21 @@
JavaInfo: dep,
})
}
- } else if dep, ok := module.(android.SourceFileProducer); ok {
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, android.SourceFilesInfoProvider); ok {
switch tag {
case sdkLibTag, libTag:
- checkProducesJars(ctx, dep)
- deps.classpath = append(deps.classpath, dep.Srcs()...)
- deps.dexClasspath = append(deps.classpath, dep.Srcs()...)
+ checkProducesJars(ctx, dep, module)
+ deps.classpath = append(deps.classpath, dep.Srcs...)
+ deps.dexClasspath = append(deps.classpath, dep.Srcs...)
transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars,
- depset.New(depset.PREORDER, dep.Srcs(), nil))
+ depset.New(depset.PREORDER, dep.Srcs, nil))
case staticLibTag:
- checkProducesJars(ctx, dep)
- deps.classpath = append(deps.classpath, dep.Srcs()...)
- deps.staticJars = append(deps.staticJars, dep.Srcs()...)
- deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
+ checkProducesJars(ctx, dep, module)
+ deps.classpath = append(deps.classpath, dep.Srcs...)
+ deps.staticJars = append(deps.staticJars, dep.Srcs...)
+ deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs...)
- depHeaderJars := depset.New(depset.PREORDER, dep.Srcs(), nil)
+ depHeaderJars := depset.New(depset.PREORDER, dep.Srcs, nil)
transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, depHeaderJars)
transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, depHeaderJars)
transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, depHeaderJars)
@@ -2577,14 +2599,12 @@
deps.transitiveStaticLibsImplementationJars = transitiveStaticJarsImplementationLibs
deps.transitiveStaticLibsResourceJars = transitiveStaticJarsResourceLibs
- if ctx.Config().UseTransitiveJarsInClasspath() {
- depSet := depset.New(depset.PREORDER, nil, transitiveClasspathHeaderJars)
- deps.classpath = depSet.ToList()
- depSet = depset.New(depset.PREORDER, nil, transitiveBootClasspathHeaderJars)
- deps.bootClasspath = depSet.ToList()
- depSet = depset.New(depset.PREORDER, nil, transitiveJava9ClasspathHeaderJars)
- deps.java9Classpath = depSet.ToList()
- }
+ depSet := depset.New(depset.PREORDER, nil, transitiveClasspathHeaderJars)
+ deps.classpath = depSet.ToList()
+ depSet = depset.New(depset.PREORDER, nil, transitiveBootClasspathHeaderJars)
+ deps.bootClasspath = depSet.ToList()
+ depSet = depset.New(depset.PREORDER, nil, transitiveJava9ClasspathHeaderJars)
+ deps.java9Classpath = depSet.ToList()
if ctx.Device() {
sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
@@ -2625,18 +2645,11 @@
RenameUseExclude
)
-type RenameUseElement struct {
- DepName string
- RenameUse DependencyUse
- Why string // token for determining where in the logic the decision was made.
-}
-
type JarJarProviderData struct {
// Mapping of class names: original --> renamed. If the value is "", the class will be
// renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
// attribute). Rdeps of that module will inherit the renaming.
- Rename map[string]string
- RenameUse []RenameUseElement
+ Rename map[string]string
}
func (this JarJarProviderData) GetDebugString() string {
@@ -2707,7 +2720,7 @@
module := ctx.Module()
moduleName := module.Name()
- ctx.VisitDirectDeps(func(m android.Module) {
+ ctx.VisitDirectDepsProxy(func(m android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(m)
// This logic mirrors that in (*Module).collectDeps above. There are several places
// where we explicitly return RenameUseExclude, even though it is the default, to
@@ -2715,93 +2728,89 @@
//
// Note well: there are probably cases that are getting to the unconditional return
// and are therefore wrong.
- shouldIncludeRenames := func() (DependencyUse, string) {
+ shouldIncludeRenames := func() DependencyUse {
if moduleName == m.Name() {
- return RenameUseInclude, "name" // If we have the same module name, include the renames.
+ return RenameUseInclude // If we have the same module name, include the renames.
}
if sc, ok := module.(android.SdkContext); ok {
if ctx.Device() {
sdkDep := decodeSdkDep(ctx, sc)
if !sdkDep.invalidVersion && sdkDep.useFiles {
- return RenameUseExclude, "useFiles"
+ return RenameUseExclude
}
}
}
if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
- return RenameUseExclude, "tags"
+ return RenameUseExclude
}
if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
switch tag {
case sdkLibTag, libTag:
- return RenameUseExclude, "sdklibdep" // matches collectDeps()
+ return RenameUseExclude // matches collectDeps()
}
- return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps()
+ return RenameUseInvalid // dep is not used in collectDeps()
} else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
switch ji.StubsLinkType {
case Stubs:
- return RenameUseExclude, "info"
+ return RenameUseExclude
case Implementation:
- return RenameUseInclude, "info"
+ return RenameUseInclude
default:
//fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m)
// Fall through to the heuristic logic.
}
- switch reflect.TypeOf(m).String() {
- case "*java.GeneratedJavaLibraryModule":
+ if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
// Probably a java_aconfig_library module.
- // TODO: make this check better.
- return RenameUseInclude, "reflect"
+ return RenameUseInclude
}
switch tag {
case bootClasspathTag:
- return RenameUseExclude, "tagswitch"
+ return RenameUseExclude
case sdkLibTag, libTag, instrumentationForTag:
- return RenameUseInclude, "tagswitch"
+ return RenameUseInclude
case java9LibTag:
- return RenameUseExclude, "tagswitch"
+ return RenameUseExclude
case staticLibTag:
- return RenameUseInclude, "tagswitch"
+ return RenameUseInclude
case pluginTag:
- return RenameUseInclude, "tagswitch"
+ return RenameUseInclude
case errorpronePluginTag:
- return RenameUseInclude, "tagswitch"
+ return RenameUseInclude
case exportedPluginTag:
- return RenameUseInclude, "tagswitch"
+ return RenameUseInclude
case kotlinPluginTag:
- return RenameUseInclude, "tagswitch"
+ return RenameUseInclude
default:
- return RenameUseExclude, "tagswitch"
+ return RenameUseExclude
}
- } else if _, ok := m.(android.SourceFileProducer); ok {
+ } else if _, ok := android.OtherModuleProvider(ctx, m, android.SourceFilesInfoProvider); ok {
switch tag {
case sdkLibTag, libTag, staticLibTag:
- return RenameUseInclude, "srcfile"
+ return RenameUseInclude
default:
- return RenameUseExclude, "srcfile"
+ return RenameUseExclude
}
} else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
- return RenameUseInclude, "aconfig_declarations_group"
+ return RenameUseInclude
} else {
switch tag {
case bootClasspathTag:
- return RenameUseExclude, "else"
+ return RenameUseExclude
case systemModulesTag:
- return RenameUseInclude, "else"
+ return RenameUseInclude
}
}
// If we got here, choose the safer option, which may lead to a build failure, rather
// than runtime failures on the device.
- return RenameUseExclude, "end"
+ return RenameUseExclude
}
if result == nil {
result = &JarJarProviderData{
- Rename: make(map[string]string),
- RenameUse: make([]RenameUseElement, 0),
+ Rename: make(map[string]string),
}
}
- how, why := shouldIncludeRenames()
- result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why})
+ how := shouldIncludeRenames()
if how != RenameUseInclude {
// Nothing to merge.
return
@@ -2906,14 +2915,18 @@
// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map
// to "" won't be in this list because they shouldn't be renamed yet.
func getJarJarRuleText(provider *JarJarProviderData) string {
- result := ""
+ result := strings.Builder{}
for _, orig := range android.SortedKeys(provider.Rename) {
renamed := provider.Rename[orig]
if renamed != "" {
- result += "rule " + orig + " " + renamed + "\n"
+ result.WriteString("rule ")
+ result.WriteString(orig)
+ result.WriteString(" ")
+ result.WriteString(renamed)
+ result.WriteString("\n")
}
}
- return result
+ return result.String()
}
// Repackage the flags if the jarjar rule txt for the flags is generated
@@ -2926,12 +2939,23 @@
return repackagedJarjarFile, true
}
-func (j *Module) jarjarIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string) (android.Path, bool) {
+func (j *Module) jarjarIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string, useShards bool) (android.Path, bool) {
if j.expandJarjarRules == nil {
return infile, false
}
jarjarFile := android.PathForModuleOut(ctx, "jarjar", info, jarName)
- TransformJarJar(ctx, jarjarFile, infile, j.expandJarjarRules)
+
+ totalShards := 1
+ if useShards {
+ totalShardsStr := j.properties.Jarjar_shards.GetOrDefault(ctx, "1")
+ ts, err := strconv.Atoi(totalShardsStr)
+ if err != nil {
+ ctx.PropertyErrorf("jarjar_shards", "jarjar_shards must be an integer represented as a string")
+ return infile, false
+ }
+ totalShards = ts
+ }
+ TransformJarJarWithShards(ctx, jarjarFile, infile, j.expandJarjarRules, totalShards)
return jarjarFile, true
}
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 3413cf3..98fb417 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -15,6 +15,8 @@
package java
import (
+ "fmt"
+
"android/soong/android"
"github.com/google/blueprint"
@@ -23,36 +25,9 @@
// Contains code that is common to both platform_bootclasspath and bootclasspath_fragment.
-func init() {
- registerBootclasspathBuildComponents(android.InitRegistrationContext)
-}
-
-func registerBootclasspathBuildComponents(ctx android.RegistrationContext) {
- ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator)
- })
-}
-
-// BootclasspathDepsMutator is the interface that a module must implement if it wants to add
-// dependencies onto APEX specific variants of bootclasspath fragments or bootclasspath contents.
-type BootclasspathDepsMutator interface {
- // BootclasspathDepsMutator implementations should add dependencies using
- // addDependencyOntoApexModulePair and addDependencyOntoApexVariants.
- BootclasspathDepsMutator(ctx android.BottomUpMutatorContext)
-}
-
-// bootclasspathDepsMutator is called during the final deps phase after all APEX variants have
-// been created so can add dependencies onto specific APEX variants of modules.
-func bootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
- m := ctx.Module()
- if p, ok := m.(BootclasspathDepsMutator); ok {
- p.BootclasspathDepsMutator(ctx)
- }
-}
-
// addDependencyOntoApexVariants adds dependencies onto the appropriate apex specific variants of
// the module as specified in the ApexVariantReference list.
-func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tag blueprint.DependencyTag) {
+func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tagType bootclasspathDependencyTagType) {
for i, ref := range refs {
apex := proptools.StringDefault(ref.Apex, "platform")
@@ -62,7 +37,7 @@
}
name := proptools.String(ref.Module)
- addDependencyOntoApexModulePair(ctx, apex, name, tag)
+ addDependencyOntoApexModulePair(ctx, apex, name, tagType)
}
}
@@ -75,68 +50,154 @@
// module when both source and prebuilt modules are available.
//
// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
-func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) {
- var variations []blueprint.Variation
- if !android.IsConfiguredJarForPlatform(apex) {
- // Pick the correct apex variant.
- variations = []blueprint.Variation{
- {Mutator: "apex", Variation: apex},
- }
+func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tagType bootclasspathDependencyTagType) {
+ tag := bootclasspathDependencyTag{
+ typ: tagType,
}
-
target := ctx.Module().Target()
- variations = append(variations, target.Variations()...)
-
- addedDep := false
- if ctx.OtherModuleDependencyVariantExists(variations, name) {
- ctx.AddFarVariationDependencies(variations, tag, name)
- addedDep = true
+ if android.IsConfiguredJarForPlatform(apex) {
+ // Platform variant, add a direct dependency.
+ ctx.AddFarVariationDependencies(target.Variations(), tag, name)
+ } else {
+ // A module in an apex. Dependencies can't be added directly onto an apex variation, as that would
+ // require constructing a full ApexInfo configuration, which can't be predicted here. Add a dependency
+ // on the apex instead, and annotate the dependency tag with the desired module in the apex.
+ tag.moduleInApex = name
+ ctx.AddFarVariationDependencies(target.Variations(), tag, apex)
}
- // Add a dependency on the prebuilt module if it exists.
- prebuiltName := android.PrebuiltNameFromSource(name)
- if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) {
- ctx.AddVariationDependencies(variations, tag, prebuiltName)
- addedDep = true
- }
-
- // If no appropriate variant existing for this, so no dependency could be added, then it is an
- // error, unless missing dependencies are allowed. The simplest way to handle that is to add a
- // dependency that will not be satisfied and the default behavior will handle it.
- if !addedDep {
- // Add dependency on the unprefixed (i.e. source or renamed prebuilt) module which we know does
- // not exist. The resulting error message will contain useful information about the available
- // variants.
- reportMissingVariationDependency(ctx, variations, name)
-
- // Add dependency on the missing prefixed prebuilt variant too if a module with that name exists
- // so that information about its available variants will be reported too.
- if ctx.OtherModuleExists(prebuiltName) {
- reportMissingVariationDependency(ctx, variations, prebuiltName)
- }
- }
}
-// reportMissingVariationDependency intentionally adds a dependency on a missing variation in order
-// to generate an appropriate error message with information about the available variations.
-func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variations []blueprint.Variation, name string) {
- ctx.AddFarVariationDependencies(variations, nil, name)
+// gatherFragments collects fragments that are direct dependencies of this module, as well as
+// any fragments in apexes via the dependency on the apex. It returns a list of the fragment
+// modules and map from apex name to the fragment in that apex.
+func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[string]android.Module) {
+ var fragments []android.Module
+
+ type fragmentInApex struct {
+ module string
+ apex string
+ }
+
+ var fragmentsInApexes []fragmentInApex
+
+ // Find any direct dependencies, as well as a list of the modules in apexes.
+ ctx.VisitDirectDeps(func(module android.Module) {
+ t := ctx.OtherModuleDependencyTag(module)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
+ if bcpTag.moduleInApex != "" {
+ fragmentsInApexes = append(fragmentsInApexes, fragmentInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
+ } else {
+ fragments = append(fragments, module)
+ }
+ }
+ })
+
+ fragmentsMap := make(map[string]android.Module)
+ for _, fragmentInApex := range fragmentsInApexes {
+ var found android.Module
+ // Find a desired module in an apex.
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if parent == ctx.Module() {
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment && ctx.OtherModuleName(child) == fragmentInApex.apex {
+ // This is the dependency from this module to the apex, recurse into it.
+ return true
+ }
+ } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
+ return false
+ } else if t == android.PrebuiltDepTag {
+ return false
+ } else if IsBootclasspathFragmentContentDepTag(t) {
+ return false
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == fragmentInApex.module {
+ // This is the desired module inside the apex.
+ if found != nil && child != found {
+ panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
+ fragmentInApex.module, fragmentInApex.apex, found, child))
+ }
+ found = child
+ }
+ return false
+ })
+ if found != nil {
+ if existing, exists := fragmentsMap[fragmentInApex.apex]; exists {
+ ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", fragmentInApex.apex, fragmentInApex.module, existing)
+ } else {
+ fragmentsMap[fragmentInApex.apex] = found
+ fragments = append(fragments, found)
+ }
+ } else if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("failed to find fragment %q in apex %q\n",
+ fragmentInApex.module, fragmentInApex.apex)
+ }
+ }
+ return fragments, fragmentsMap
}
// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
// added by addDependencyOntoApexModulePair.
-func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module {
+func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) ([]android.Module, map[android.Module]string) {
var modules []android.Module
- isActiveModulePred := func(module android.Module) bool {
- return isActiveModule(ctx, module)
+ modulesToApex := make(map[android.Module]string)
+
+ type moduleInApex struct {
+ module string
+ apex string
}
- ctx.VisitDirectDepsIf(isActiveModulePred, func(module android.Module) {
+
+ var modulesInApexes []moduleInApex
+
+ ctx.VisitDirectDeps(func(module android.Module) {
t := ctx.OtherModuleDependencyTag(module)
- if t == tag {
- modules = append(modules, module)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType {
+ if bcpTag.moduleInApex != "" {
+ modulesInApexes = append(modulesInApexes, moduleInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
+ } else {
+ modules = append(modules, module)
+ }
}
})
- return modules
+
+ for _, moduleInApex := range modulesInApexes {
+ var found android.Module
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if parent == ctx.Module() {
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType && ctx.OtherModuleName(child) == moduleInApex.apex {
+ // recurse into the apex
+ return true
+ }
+ } else if tagType != fragment && android.IsFragmentInApexTag(t) {
+ return true
+ } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
+ return false
+ } else if t == android.PrebuiltDepTag {
+ return false
+ } else if IsBootclasspathFragmentContentDepTag(t) {
+ return false
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
+ if found != nil && child != found {
+ panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
+ moduleInApex.module, moduleInApex.apex, found, child))
+ }
+ found = child
+ }
+ return false
+ })
+ if found != nil {
+ modules = append(modules, found)
+ if existing, exists := modulesToApex[found]; exists && existing != moduleInApex.apex {
+ ctx.ModuleErrorf("module %s is in two apexes, %s and %s", moduleInApex.module, existing, moduleInApex.apex)
+ } else {
+ modulesToApex[found] = moduleInApex.apex
+ }
+ } else if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("failed to find module %q in apex %q\n",
+ moduleInApex.module, moduleInApex.apex)
+ }
+ }
+ return modules, modulesToApex
}
// ApexVariantReference specifies a particular apex variant of a module.
@@ -165,7 +226,7 @@
// addDependenciesOntoFragments adds dependencies to the fragments specified in this properties
// structure.
func (p *BootclasspathFragmentsDepsProperties) addDependenciesOntoFragments(ctx android.BottomUpMutatorContext) {
- addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, bootclasspathFragmentDepTag)
+ addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, fragment)
}
// bootclasspathDependencyTag defines dependencies from/to bootclasspath_fragment,
@@ -174,23 +235,38 @@
type bootclasspathDependencyTag struct {
blueprint.BaseDependencyTag
- name string
+ typ bootclasspathDependencyTagType
+
+ // moduleInApex is set to the name of the desired module when this dependency points
+ // to the apex that the modules is contained in.
+ moduleInApex string
}
+type bootclasspathDependencyTagType int
+
+const (
+ // The tag used for dependencies onto bootclasspath_fragments.
+ fragment bootclasspathDependencyTagType = iota
+ // The tag used for dependencies onto platform_bootclasspath.
+ platform
+ dexpreoptBootJar
+ artBootJar
+ platformBootJar
+ apexBootJar
+)
+
func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() {
}
+func (t bootclasspathDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
+ return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
+}
+
// Dependencies that use the bootclasspathDependencyTag instances are only added after all the
// visibility checking has been done so this has no functional effect. However, it does make it
// clear that visibility is not being enforced on these tags.
var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{}
-// The tag used for dependencies onto bootclasspath_fragments.
-var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"}
-
-// The tag used for dependencies onto platform_bootclasspath.
-var platformBootclasspathDepTag = bootclasspathDependencyTag{name: "platform"}
-
// BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the
// bootclasspath that are nested within the main BootclasspathAPIProperties.
type BootclasspathNestedAPIProperties struct {
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 375a1aa..a09416d 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -41,6 +41,10 @@
ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootclasspathFragmentFactory)
}
+type BootclasspathFragmentInfo struct{}
+
+var BootclasspathFragmentInfoProvider = blueprint.NewProvider[BootclasspathFragmentInfo]()
+
// BootclasspathFragmentSdkMemberType is the member type used to add bootclasspath_fragments to
// the SDK snapshot. It is exported for use by apex.
var BootclasspathFragmentSdkMemberType = &bootclasspathFragmentMemberType{
@@ -89,6 +93,19 @@
// The tag used for the dependency between the bootclasspath_fragment module and its contents.
var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
+type moduleInFragmentDependencyTag struct {
+ blueprint.DependencyTag
+}
+
+func (m moduleInFragmentDependencyTag) ExcludeFromVisibilityEnforcement() {
+}
+
+// moduleInFragmentDepTag is added alongside bootclasspathFragmentContentDependencyTag,
+// but doesn't set ReplaceSourceWithPrebuilt. It is used to find modules in the fragment
+// by traversing from the apex to the fragment to the module, which prevents having to
+// construct a dependency on the apex variant of the fragment directly.
+var moduleInFragmentDepTag = moduleInFragmentDependencyTag{}
+
var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag
var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
var _ android.SdkMemberDependencyTag = bootclasspathFragmentContentDepTag
@@ -239,6 +256,8 @@
profilePathErr error
}
+var _ android.ApexModule = (*BootclasspathFragmentModule)(nil)
+
// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
// bootclasspath fragment modules.
type commonBootclasspathFragment interface {
@@ -290,6 +309,10 @@
return m
}
+func (m *BootclasspathFragmentModule) UniqueApexVariations() bool {
+ return true
+}
+
func (m *BootclasspathFragmentModule) bootclasspathFragmentPropertyCheck(ctx android.ModuleContext) {
contents := m.properties.Contents.GetOrDefault(ctx, nil)
if len(contents) == 0 {
@@ -393,11 +416,17 @@
return i.profileInstallPathInApex
}
-func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- tag := ctx.OtherModuleDependencyTag(dep)
+func (m *BootclasspathFragmentModule) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return BootclasspathFragmentDepInSameApexChecker{}
+}
+type BootclasspathFragmentDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (b BootclasspathFragmentDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
// If the module is a default module, do not check the tag
- if _, ok := dep.(*Defaults); ok {
+ if tag == android.DefaultsDepTag {
return true
}
if IsBootclasspathFragmentContentDepTag(tag) {
@@ -408,17 +437,31 @@
// Cross-cutting metadata dependencies are metadata.
return false
}
+ if tag == moduleInFragmentDepTag {
+ return true
+ }
// Dependency to the bootclasspath fragment of another apex
// e.g. concsrypt-bootclasspath-fragment --> art-bootclasspath-fragment
- if tag == bootclasspathFragmentDepTag {
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
return false
-
}
- panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
+ if tag == moduleInFragmentDepTag {
+ return false
+ }
+ if tag == dexpreopt.Dex2oatDepTag {
+ return false
+ }
+ if tag == android.PrebuiltDepTag {
+ return false
+ }
+ if _, ok := tag.(hiddenAPIStubsDependencyTag); ok {
+ return false
+ }
+ panic(fmt.Errorf("boot_image module should not have a dependency tag %s", android.PrettyPrintTag(tag)))
}
-func (b *BootclasspathFragmentModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
- return nil
+func (m *BootclasspathFragmentModule) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
// ComponentDepsMutator adds dependencies onto modules before any prebuilt modules without a
@@ -456,24 +499,24 @@
}
}
- if !dexpreopt.IsDex2oatNeeded(ctx) {
- return
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
}
- // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
- // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
- dexpreopt.RegisterToolDeps(ctx)
-
// Add a dependency to `all_apex_contributions` to determine if prebuilts are active.
// If prebuilts are active, `contents` validation on the source bootclasspath fragment should be disabled.
if _, isPrebuiltModule := ctx.Module().(*PrebuiltBootclasspathFragmentModule); !isPrebuiltModule {
ctx.AddDependency(b, android.AcDepTag, "all_apex_contributions")
}
-}
-func (b *BootclasspathFragmentModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies on all the fragments.
b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx)
+
+ for _, name := range b.properties.Contents.GetOrDefault(ctx, nil) {
+ ctx.AddDependency(ctx.Module(), moduleInFragmentDepTag, name)
+ }
}
func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -496,7 +539,7 @@
}
})
- fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
+ fragments, _ := gatherFragments(ctx)
// Perform hidden API processing.
hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
@@ -518,6 +561,8 @@
if !ctx.IsFinalModule(ctx.Module()) {
b.HideFromMake()
}
+
+ android.SetProvider(ctx, BootclasspathFragmentInfoProvider, BootclasspathFragmentInfo{})
}
// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an
@@ -529,19 +574,18 @@
}
// Bootclasspath fragment modules that are for the platform do not produce boot related files.
- apexInfos, _ := android.ModuleProvider(ctx, android.AllApexInfoProvider)
- if apexInfos == nil {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if apexInfo.IsForPlatform() {
return ""
}
- for _, apexInfo := range apexInfos.ApexInfos {
- for _, apex := range apexInfo.InApexVariants {
- if isProfileProviderApex(ctx, apex) {
- return apex
+ for _, config := range genBootImageConfigs(ctx) {
+ if config.profileProviderModule == b.BaseModuleName() {
+ if len(config.profileImports) > 0 {
+ return config.profileImports[0]
}
}
}
-
return ""
}
@@ -605,7 +649,7 @@
if android.IsModulePrebuilt(ctx.Module()) {
// prebuilt bcpf. the validation of this will be done at the top-level apex
providerClasspathFragmentValidationInfoProvider(ctx, unknown)
- } else if !disableSourceApexVariant(ctx) {
+ } else if !disableSourceApexVariant(ctx) && android.IsModulePreferred(ctx.Module()) {
// source bcpf, and prebuilt apex are not selected.
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
}
@@ -1141,6 +1185,13 @@
android.InitPrebuiltModule(m, &[]string{"placeholder"})
android.InitApexModule(m)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(m)
+
+ m.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
+ if mctx.Config().AlwaysUsePrebuiltSdks() {
+ m.prebuilt.ForcePrefer()
+ }
+ })
return m
}
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 3aa1258..87b853c 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -31,6 +31,7 @@
)
func TestBootclasspathFragment_UnknownImageName(t *testing.T) {
+ t.Parallel()
prepareForTestWithBootclasspathFragment.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
`\Qimage_name: unknown image name "unknown", expected "art"\E`)).
@@ -50,6 +51,7 @@
}
func TestPrebuiltBootclasspathFragment_UnknownImageName(t *testing.T) {
+ t.Parallel()
prepareForTestWithBootclasspathFragment.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
`\Qimage_name: unknown image name "unknown", expected "art"\E`)).
@@ -68,6 +70,7 @@
}
func TestBootclasspathFragmentInconsistentArtConfiguration_Platform(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
dexpreopt.FixtureSetArtBootJars("platform:foo", "apex:bar"),
@@ -99,6 +102,7 @@
}
func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
dexpreopt.FixtureSetArtBootJars("apex1:foo", "apex2:bar"),
@@ -131,6 +135,7 @@
}
func TestBootclasspathFragment_Coverage(t *testing.T) {
+ t.Parallel()
prepareWithBp := android.FixtureWithRootAndroidBp(`
bootclasspath_fragment {
name: "myfragment",
@@ -204,11 +209,13 @@
)
t.Run("without coverage", func(t *testing.T) {
+ t.Parallel()
result := preparer.RunTest(t)
checkContents(t, result, "mybootlib")
})
t.Run("with coverage", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForTestWithFrameworkJacocoInstrumentation,
preparer,
@@ -364,7 +371,7 @@
}
`)
- fragment := result.ModuleForTests("myfragment", "android_common")
+ fragment := result.ModuleForTests(t, "myfragment", "android_common")
dependencyStubDexFlag := "--dependency-stub-dex=out/soong/.intermediates/default/java/android-non-updatable.stubs.test_module_lib/android_common/dex/android-non-updatable.stubs.test_module_lib.jar"
stubFlagsCommand := fragment.Output("modular-hiddenapi/stub-flags.csv").RuleParams.Command
android.AssertStringDoesContain(t,
@@ -472,7 +479,7 @@
// Make sure that the signature-patterns.csv is passed all the appropriate package properties
// from the bootclasspath_fragment and its contents.
- fragment := result.ModuleForTests("mybootclasspathfragment", "android_common")
+ fragment := result.ModuleForTests(t, "mybootclasspathfragment", "android_common")
rule := fragment.Output("modular-hiddenapi/signature-patterns.csv")
expectedCommand := strings.Join([]string{
"--split-package newlibrary",
diff --git a/java/builder.go b/java/builder.go
index 895ddb6..dff0032 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -46,6 +46,7 @@
`mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
+ `${config.FindInputDeltaCmd} --template '' --target "$out" --inputs_file "$out.rsp" && ` +
`${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
`${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
@@ -55,8 +56,10 @@
`$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` +
`if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` +
`if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` +
+ `if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
`rm -rf "$srcJarDir" "$outDir"`,
CommandDeps: []string{
+ "${config.FindInputDeltaCmd}",
"${config.JavacCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
@@ -165,7 +168,7 @@
"${config.JavaCmd}",
},
Rspfile: "$out.rsp",
- RspfileContent: "$in",
+ RspfileContent: "$in_newline",
Restat: true,
},
&remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"},
@@ -223,6 +226,12 @@
},
"jarArgs")
+ extractR8Rules = pctx.AndroidStaticRule("extractR8Rules",
+ blueprint.RuleParams{
+ Command: `${config.ExtractR8RulesCmd} --rules-output $out --include-origin-comments $in`,
+ CommandDeps: []string{"${config.ExtractR8RulesCmd}"},
+ })
+
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
Command: "" +
@@ -235,12 +244,12 @@
// for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes
// avoids adding new hiddenapis after jarjar'ing.
" -DremoveAndroidCompatAnnotations=true" +
- " -jar ${config.JarjarCmd} process $rulesFile $in $out && " +
+ " -jar ${config.JarjarCmd} process $rulesFile $in $out $total_shards $shard_index && " +
// Turn a missing output file into a ninja error
`[ -e ${out} ] || (echo "Missing output file"; exit 1)`,
CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
},
- "rulesFile")
+ "rulesFile", "total_shards", "shard_index")
packageCheck = pctx.AndroidStaticRule("packageCheck",
blueprint.RuleParams{
@@ -301,7 +310,7 @@
gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
blueprint.RuleParams{
- Command: `${aconfig} dump-cache --dedup --format='{fully_qualified_name}' ` +
+ Command: `${aconfig} dump-cache --dedup --format=protobuf ` +
`--out ${out} ` +
`${flags_path} ` +
`${filter_args} `,
@@ -311,8 +320,15 @@
generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule",
blueprint.RuleParams{
- Command: `${keep-flagged-apis} ${in} > ${out}`,
- CommandDeps: []string{"${keep-flagged-apis}"},
+ Command: `${aconfig-to-metalava-flags} ${in} > ${out}`,
+ CommandDeps: []string{"${aconfig-to-metalava-flags}"},
+ })
+
+ generateApiXMLRule = pctx.AndroidStaticRule("generateApiXMLRule",
+ blueprint.RuleParams{
+ Command: `${config.JavaCmd} ${config.JavaVmFlags} -Xmx4g -jar ${config.MetalavaJar} jar-to-jdiff ${in} ${out}`,
+ CommandDeps: []string{"${config.JavaCmd}", "${config.MetalavaJar}"},
+ Description: "Converting API file to XML",
})
)
@@ -323,7 +339,7 @@
pctx.HostBinToolVariable("aconfig", "aconfig")
pctx.HostBinToolVariable("ravenizer", "ravenizer")
pctx.HostBinToolVariable("apimapper", "apimapper")
- pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
+ pctx.HostBinToolVariable("aconfig-to-metalava-flags", "aconfig-to-metalava-flags")
}
type javaBuilderFlags struct {
@@ -456,9 +472,10 @@
const srcJarArgsLimit = 32 * 1024
if len(srcJarArgs) > srcJarArgsLimit {
srcJarRspFile := android.PathForModuleOut(ctx, "turbine", "srcjars.rsp")
- android.WriteFileRule(ctx, srcJarRspFile, srcJarArgs)
+ android.WriteFileRule(ctx, srcJarRspFile, strings.Join(srcJars.Strings(), "\n"))
srcJarArgs = "@" + srcJarRspFile.String()
implicits = append(implicits, srcJarRspFile)
+ rspFiles = append(rspFiles, srcJarRspFile)
rbeInputs = append(rbeInputs, srcJarRspFile)
} else {
rbeInputs = append(rbeInputs, srcJars...)
@@ -488,7 +505,7 @@
const classpathLimit = 32 * 1024
if len(classpathFlags) > classpathLimit {
classpathRspFile := android.PathForModuleOut(ctx, dir, "classpath.rsp")
- android.WriteFileRule(ctx, classpathRspFile, classpathFlags)
+ android.WriteFileRule(ctx, classpathRspFile, strings.Join(classpath.Strings(), "\n"))
classpathFlags = "@" + classpathRspFile.String()
implicits = append(implicits, classpathRspFile)
rspFiles = append(rspFiles, classpathRspFile)
@@ -736,6 +753,16 @@
})
}
+func TransformJarToR8Rules(ctx android.ModuleContext, outputFile android.WritablePath,
+ jar android.Path) {
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: extractR8Rules,
+ Output: outputFile,
+ Input: jar,
+ })
+}
+
func convertImplementationJarToHeaderJar(ctx android.ModuleContext, implementationJarFile android.Path,
headerJarFile android.WritablePath) {
ctx.Build(pctx, android.BuildParams{
@@ -747,16 +774,58 @@
func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
classesJar android.Path, rulesFile android.Path) {
+ TransformJarJarWithShards(ctx, outputFile, classesJar, rulesFile, 1)
+}
+
+func TransformJarJarWithShards(ctx android.ModuleContext, outputFile android.WritablePath,
+ classesJar android.Path, rulesFile android.Path, totalShards int) {
+
+ // If the total number of shards is 1, just run jarjar as-is, with `total_shards` = 1
+ // and `shard_index` == 0, which effectively disables sharding
+ if totalShards == 1 {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: jarjar,
+ Description: "jarjar",
+ Output: outputFile,
+ Input: classesJar,
+ Implicit: rulesFile,
+ Args: map[string]string{
+ "rulesFile": rulesFile.String(),
+ "total_shards": "1",
+ "shard_index": "0",
+ },
+ })
+ return
+ }
+
+ // Otherwise, run multiple jarjar instances and use merge_zips to combine the output.
+ tempJars := make([]android.Path, 0)
+ totalStr := strconv.Itoa(totalShards)
+ for i := 0; i < totalShards; i++ {
+ iStr := strconv.Itoa(i)
+ tempOut := outputFile.ReplaceExtension(ctx, "-"+iStr+".jar")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: jarjar,
+ Description: "jarjar (" + iStr + "/" + totalStr + ")",
+ Output: tempOut,
+ Input: classesJar,
+ Implicit: rulesFile,
+ Args: map[string]string{
+ "rulesFile": rulesFile.String(),
+ "total_shards": totalStr,
+ "shard_index": iStr,
+ },
+ })
+ tempJars = append(tempJars, tempOut)
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: jarjar,
- Description: "jarjar",
+ Rule: combineJar,
+ Description: "merge jarjar shards",
Output: outputFile,
- Input: classesJar,
- Implicit: rulesFile,
- Args: map[string]string{
- "rulesFile": rulesFile.String(),
- },
+ Inputs: tempJars,
})
+
}
func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath,
diff --git a/java/classpath_element.go b/java/classpath_element.go
index abbcae7..4af2770 100644
--- a/java/classpath_element.go
+++ b/java/classpath_element.go
@@ -108,33 +108,18 @@
//
// e.g. Given the following input:
//
-// libraries: com.android.art:core-oj, com.android.art:core-libart, framework, ext
-// fragments: com.android.art:art-bootclasspath-fragment
+// libraries: core-oj, core-libart, framework, ext
+// fragments: art-bootclasspath-fragment
+// libraryToApex: core-oj: com.android.art, core-libart: com.android.art
+// apexNameToFragment: com.android.art: art-bootclasspath-fragment
//
// Then this will return:
//
// ClasspathFragmentElement(art-bootclasspath-fragment, [core-oj, core-libart]),
// ClasspathLibraryElement(framework),
// ClasspathLibraryElement(ext),
-func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module) ClasspathElements {
- // Create a map from apex name to the fragment module. This makes it easy to find the fragment
- // associated with a particular apex.
- apexToFragment := map[string]android.Module{}
- for _, fragment := range fragments {
- apexInfo, ok := android.OtherModuleProvider(ctx, fragment, android.ApexInfoProvider)
- if !ok {
- ctx.ModuleErrorf("fragment %s is not part of an apex", fragment)
- continue
- }
-
- for _, apex := range apexInfo.InApexVariants {
- if existing, ok := apexToFragment[apex]; ok {
- ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", apex, fragment, existing)
- continue
- }
- apexToFragment[apex] = fragment
- }
- }
+func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module,
+ libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) ClasspathElements {
fragmentToElement := map[android.Module]*ClasspathFragmentElement{}
elements := []ClasspathElement{}
@@ -144,31 +129,28 @@
// Iterate over the libraries to construct the ClasspathElements list.
for _, library := range libraries {
var element ClasspathElement
- if apexInfo, ok := android.OtherModuleProvider(ctx, library, android.ApexInfoProvider); ok {
-
+ if libraryApex, ok := libraryToApex[library]; ok {
var fragment android.Module
// Make sure that the library is in only one fragment of the classpath.
- for _, apex := range apexInfo.InApexVariants {
- if f, ok := apexToFragment[apex]; ok {
- if fragment == nil {
- // This is the first fragment so just save it away.
- fragment = f
- } else if f != fragment {
- // This apex variant of the library is in a different fragment.
- ctx.ModuleErrorf("library %s is in two separate fragments, %s and %s", library, fragment, f)
- // Skip over this library entirely as otherwise the resulting classpath elements would
- // be invalid.
- continue skipLibrary
- }
- } else {
- // There is no fragment associated with the library's apex.
+ if f, ok := apexNameToFragment[libraryApex]; ok {
+ if fragment == nil {
+ // This is the first fragment so just save it away.
+ fragment = f
+ } else if f != fragment {
+ // This apex variant of the library is in a different fragment.
+ ctx.ModuleErrorf("library %s is in two separate fragments, %s and %s", library, fragment, f)
+ // Skip over this library entirely as otherwise the resulting classpath elements would
+ // be invalid.
+ continue skipLibrary
}
+ } else {
+ // There is no fragment associated with the library's apex.
}
if fragment == nil {
ctx.ModuleErrorf("library %s is from apexes %s which have no corresponding fragment in %s",
- library, apexInfo.InApexVariants, fragments)
+ library, []string{libraryApex}, fragments)
// Skip over this library entirely as otherwise the resulting classpath elements would
// be invalid.
continue skipLibrary
diff --git a/java/config/config.go b/java/config/config.go
index 87703d8..fdb8d78 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -159,6 +159,7 @@
pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar")
pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file")
+ pctx.HostBinToolVariable("FindInputDeltaCmd", "find_input_delta")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh")
@@ -170,7 +171,9 @@
pctx.HostBinToolVariable("ApiCheckCmd", "apicheck")
pctx.HostBinToolVariable("D8Cmd", "d8")
pctx.HostBinToolVariable("R8Cmd", "r8")
+ pctx.HostBinToolVariable("ExtractR8RulesCmd", "extract-r8-rules")
pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker")
+ pctx.HostBinToolVariable("TraceReferencesCmd", "tracereferences")
pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi")
pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks")
pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string {
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index 302d021..ffb025d 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -21,6 +21,7 @@
KotlincIllegalFlags = []string{
"-no-jdk",
"-no-stdlib",
+ "-language-version",
}
)
@@ -56,5 +57,5 @@
// platform that are not fully compatible with the kotlinc used in g3 kythe indexers.
// e.g. uninitialized variables are a warning in 1.*, but an error in 2.*
// https://github.com/JetBrains/kotlin/blob/master/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt#L748
- pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " "))
+ pctx.StaticVariable("KotlincKytheGlobalFlags", strings.Join([]string{}, " "))
}
diff --git a/java/container_test.go b/java/container_test.go
index 25cfa4c..35a3020 100644
--- a/java/container_test.go
+++ b/java/container_test.go
@@ -26,6 +26,7 @@
}
func TestJavaContainersModuleProperties(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
).RunTestWithBp(t, `
@@ -154,7 +155,7 @@
}
for _, c := range testcases {
- m := result.ModuleForTests(c.moduleName, "android_common")
+ m := result.ModuleForTests(t, c.moduleName, "android_common")
containers, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), m.Module(), android.ContainersInfoProvider)
belongingContainers := containers.BelongingContainers()
checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index bfacea6..04def3e 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -140,7 +140,7 @@
d.combinedHeaderJar = d.headerJars[0]
}
- android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ javaInfo := &JavaInfo{
HeaderJars: d.headerJars,
LocalHeaderJars: d.headerJars,
TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, nil, transitiveHeaderJars),
@@ -154,7 +154,9 @@
StubsLinkType: Implementation,
// TODO: Not sure if aconfig flags that have been moved between device and host variants
// make sense.
- })
+ }
+ setExtraJavaInfo(ctx, d, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
}
diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go
index 6ccc5c1..42e3b46 100644
--- a/java/device_host_converter_test.go
+++ b/java/device_host_converter_test.go
@@ -15,13 +15,15 @@
package java
import (
- "android/soong/android"
"slices"
"strings"
"testing"
+
+ "android/soong/android"
)
func TestDeviceForHost(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "device_module",
@@ -52,15 +54,15 @@
ctx, config := testJava(t, bp)
- deviceModule := ctx.ModuleForTests("device_module", "android_common")
- deviceTurbineCombined := deviceModule.Output("turbine-combined/device_module.jar")
+ deviceModule := ctx.ModuleForTests(t, "device_module", "android_common")
+ deviceTurbine := deviceModule.Output("turbine/device_module.jar")
deviceJavac := deviceModule.Output("javac/device_module.jar")
deviceRes := deviceModule.Output("res/device_module.jar")
- deviceImportModule := ctx.ModuleForTests("device_import_module", "android_common")
- deviceImportCombined := deviceImportModule.Output("combined/device_import_module.jar")
+ deviceImportModule := ctx.ModuleForTests(t, "device_import_module", "android_common")
+ deviceImportCombined := deviceImportModule.Output("local-combined/device_import_module.jar")
- hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String())
+ hostModule := ctx.ModuleForTests(t, "host_module", config.BuildOSCommonTarget.String())
hostJavac := hostModule.Output("javac/host_module.jar")
hostRes := hostModule.Output("res/host_module.jar")
combined := hostModule.Output("combined/host_module.jar")
@@ -68,7 +70,7 @@
// check classpath of host module with dependency on device_for_host_module
expectedClasspath := "-classpath " + strings.Join(android.Paths{
- deviceTurbineCombined.Output,
+ deviceTurbine.Output,
deviceImportCombined.Output,
}.Strings(), ":")
@@ -102,6 +104,7 @@
}
func TestHostForDevice(t *testing.T) {
+ t.Parallel()
bp := `
java_library_host {
name: "host_module",
@@ -133,15 +136,15 @@
ctx, config := testJava(t, bp)
- hostModule := ctx.ModuleForTests("host_module", config.BuildOSCommonTarget.String())
+ hostModule := ctx.ModuleForTests(t, "host_module", config.BuildOSCommonTarget.String())
hostJavac := hostModule.Output("javac/host_module.jar")
- hostJavacHeader := hostModule.Output("javac-header/host_module.jar")
+ hostJavacHeader := hostModule.Output("local-javac-header/host_module.jar")
hostRes := hostModule.Output("res/host_module.jar")
- hostImportModule := ctx.ModuleForTests("host_import_module", config.BuildOSCommonTarget.String())
- hostImportCombined := hostImportModule.Output("combined/host_import_module.jar")
+ hostImportModule := ctx.ModuleForTests(t, "host_import_module", config.BuildOSCommonTarget.String())
+ hostImportCombined := hostImportModule.Output("local-combined/host_import_module.jar")
- deviceModule := ctx.ModuleForTests("device_module", "android_common")
+ deviceModule := ctx.ModuleForTests(t, "device_module", "android_common")
deviceJavac := deviceModule.Output("javac/device_module.jar")
deviceRes := deviceModule.Output("res/device_module.jar")
combined := deviceModule.Output("combined/device_module.jar")
diff --git a/java/dex.go b/java/dex.go
index 2b3c931..e3058e9 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -42,13 +42,39 @@
// True if the module containing this has it set by default.
EnabledByDefault bool `blueprint:"mutated"`
+ // If true, then `d8` will be used on eng builds instead of `r8`, even though
+ // optimize.enabled is true.
+ D8_on_eng *bool
+
+ // Whether to allow that library classes inherit from program classes.
+ // Defaults to false.
+ Ignore_library_extends_program *bool
+
// Whether to continue building even if warnings are emitted. Defaults to true.
Ignore_warnings *bool
+ // Whether runtime invisible annotations should be kept by R8. Defaults to false.
+ // This is equivalent to:
+ // -keepattributes RuntimeInvisibleAnnotations,
+ // RuntimeInvisibleParameterAnnotations,
+ // RuntimeInvisibleTypeAnnotations
+ // This is only applicable when RELEASE_R8_ONLY_RUNTIME_VISIBLE_ANNOTATIONS is
+ // enabled and will be used to migrate away from keeping runtime invisible
+ // annotations (b/387958004).
+ Keep_runtime_invisible_annotations *bool
+
// If true, runs R8 in Proguard compatibility mode, otherwise runs R8 in full mode.
- // Defaults to false for apps, true for libraries and tests.
+ // Defaults to false for apps and tests, true for libraries.
Proguard_compatibility *bool
+ // If true, R8 will not add public or protected members (fields or methods) to
+ // the API surface of the compilation unit, i.e., classes that are kept or
+ // have kept subclasses will not expose any members added by R8 for internal
+ // use. That includes renamed members if obfuscation is enabled.
+ // This should only be used for building targets that go on the bootclasspath.
+ // Defaults to false.
+ Protect_api_surface *bool
+
// If true, optimize for size by removing unused code. Defaults to true for apps,
// false for libraries and tests.
Shrink *bool
@@ -81,6 +107,34 @@
// If true, transitive reverse dependencies of this module will have this
// module's proguard spec appended to their optimization action
Export_proguard_flags_files *bool
+
+ // Path to a file containing a list of class names that should not be compiled using R8.
+ // These classes will be compiled by D8 similar to when Optimize.Enabled is false.
+ //
+ // Example:
+ //
+ // r8.exclude:
+ // com.example.Foo
+ // com.example.Bar
+ // com.example.Bar$Baz
+ //
+ // By default all classes are compiled using R8 when Optimize.Enabled is set.
+ Exclude *string `android:"path"`
+
+ // Optional list of downstream (Java) libraries from which to trace and preserve references
+ // when optimizing. Note that this requires that the source reference does *not* have
+ // a strict lib dependency on this target; dependencies should be on intermediate targets
+ // statically linked into this target, e.g., if A references B, and we want to trace and
+ // keep references from A when optimizing B, you would create an intermediate B.impl (
+ // containing all static code), have A depend on `B.impl` via libs, and set
+ // `trace_references_from: ["A"]` on B.
+ //
+ // Also note that these are *not* inherited across targets, they must be specified at the
+ // top-level target that is optimized.
+ //
+ // TODO(b/212737576): Handle this implicitly using bottom-up deps mutation and implicit
+ // creation of a proxy `.impl` library.
+ Trace_references_from proptools.Configurable[[]string] `android:"arch_variant"`
}
// Keep the data uncompressed. We always need uncompressed dex for execution,
@@ -111,7 +165,12 @@
providesTransitiveHeaderJarsForR8
}
-func (d *dexer) effectiveOptimizeEnabled() bool {
+func (d *dexer) effectiveOptimizeEnabled(ctx android.EarlyModuleContext) bool {
+ // For eng builds, if Optimize.D8_on_eng is true, then disable optimization.
+ if ctx.Config().Eng() && proptools.Bool(d.dexProperties.Optimize.D8_on_eng) {
+ return false
+ }
+ // Otherwise, use the legacy logic of a default value which can be explicitly overridden by the module.
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
@@ -123,8 +182,8 @@
return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault())
}
-func (d *dexer) optimizeOrObfuscateEnabled() bool {
- return d.effectiveOptimizeEnabled() && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate))
+func (d *dexer) optimizeOrObfuscateEnabled(ctx android.EarlyModuleContext) bool {
+ return d.effectiveOptimizeEnabled(ctx) && (proptools.Bool(d.dexProperties.Optimize.Optimize) || proptools.Bool(d.dexProperties.Optimize.Obfuscate))
}
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
@@ -156,6 +215,71 @@
},
}, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil)
+// Include all of the args for d8r8, so that we can generate the partialcompileclean target's build using the same list.
+var d8r8Clean = pctx.AndroidStaticRule("d8r8-partialcompileclean",
+ blueprint.RuleParams{
+ Command: `rm -rf "${outDir}" "${outDict}" "${outConfig}" "${outUsage}" "${outUsageZip}" "${outUsageDir}" ` +
+ `"${resourcesOutput}" "${outR8ArtProfile}" ${builtOut}`,
+ }, "outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", "builtOut",
+ "d8Flags", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile", "implicits",
+)
+
+var d8r8, d8r8RE = pctx.MultiCommandRemoteStaticRules("d8r8",
+ blueprint.RuleParams{
+ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+ `rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` +
+ `mkdir -p $$(dirname ${outUsage}) && ` +
+ `if [ -n "$${SOONG_USE_PARTIAL_COMPILE}" ]; then ` +
+ ` for f in "${outConfig}" "${outDict}" "${outUsage}" "${resourcesOutput}"; do ` +
+ ` test -n "$${f}" && test ! -f "$${f}" && mkdir -p "$$(dirname "$${f}")" && touch "$${f}" || true; ` +
+ ` done && ` +
+ ` $d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in; ` +
+ `else ` +
+ ` $r8Template${config.R8Cmd} ${config.R8Flags} $r8Flags -injars $in --output $outDir ` +
+ ` --no-data-resources ` +
+ ` -printmapping ${outDict} ` +
+ ` -printconfiguration ${outConfig} ` +
+ ` -printusage ${outUsage} ` +
+ ` --deps-file ${out}.d && ` +
+ ` touch "${outDict}" "${outConfig}" "${outUsage}"; ` +
+ `fi && ` +
+ `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
+ `rm -rf ${outUsageDir} && ` +
+ `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar" `,
+ CommandDeps: []string{
+ "${config.D8Cmd}",
+ "${config.R8Cmd}",
+ "${config.SoongZipCmd}",
+ "${config.MergeZipsCmd}",
+ },
+ }, map[string]*remoteexec.REParams{
+ "$d8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "d8"},
+ Inputs: []string{"${config.D8Jar}"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$r8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "r8"},
+ Inputs: []string{"$implicits", "${config.R8Jar}"},
+ OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}", "${resourcesOutput}", "${outR8ArtProfile}"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$outDir/classes.dex.jar"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
+ "d8Flags", "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput", "outR8ArtProfile"}, []string{"implicits"})
+
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -220,21 +344,29 @@
deps = append(deps, f)
}
- var requestReleaseMode bool
+ var requestReleaseMode, requestDebugMode bool
requestReleaseMode, flags = android.RemoveFromList("--release", flags)
+ requestDebugMode, flags = android.RemoveFromList("--debug", flags)
if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" || ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
- flags = append(flags, "--debug")
+ requestDebugMode = true
requestReleaseMode = false
}
// Don't strip out debug information for eng builds, unless the target
// explicitly provided the `--release` build flag. This allows certain
// test targets to remain optimized as part of eng test_suites builds.
- if requestReleaseMode {
+ if requestDebugMode {
+ flags = append(flags, "--debug")
+ } else if requestReleaseMode {
flags = append(flags, "--release")
} else if ctx.Config().Eng() {
flags = append(flags, "--debug")
+ } else if !d.effectiveOptimizeEnabled(ctx) && d.dexProperties.Optimize.EnabledByDefault {
+ // D8 uses --debug by default, whereas R8 uses --release by default.
+ // For targets that default to R8 usage (e.g., apps), but override this default, we still
+ // want D8 to run in release mode, preserving semantics as much as possible between the two.
+ flags = append(flags, "--release")
}
// Supplying the platform build flag disables various features like API modeling and desugaring.
@@ -306,7 +438,7 @@
// TODO(b/360905238): Remove SdkSystemServer exception after resolving missing class references.
if !dexParams.sdkVersion.Stable() || dexParams.sdkVersion.Kind == android.SdkSystemServer {
var proguardRaiseDeps classpath
- ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(proguardRaiseTag, func(m android.ModuleProxy) {
if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
}
@@ -340,11 +472,30 @@
android.PathForSource(ctx, "build/make/core/proguard.flags"),
}
+ if ctx.Config().UseR8GlobalCheckNotNullFlags() {
+ flagFiles = append(flagFiles, android.PathForSource(ctx,
+ "build/make/core/proguard/checknotnull.flags"))
+ }
+
flagFiles = append(flagFiles, d.extraProguardFlagsFiles...)
// TODO(ccross): static android library proguard files
flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...)
+ traceReferencesSources := android.Paths{}
+ ctx.VisitDirectDepsProxyWithTag(traceReferencesTag, func(m android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+ traceReferencesSources = append(traceReferencesSources, dep.ImplementationJars...)
+ }
+ })
+ if len(traceReferencesSources) > 0 {
+ traceTarget := dexParams.classesJar
+ traceLibs := android.FirstUniquePaths(append(flags.bootClasspath.Paths(), flags.dexClasspath.Paths()...))
+ traceReferencesFlags := android.PathForModuleOut(ctx, "proguard", "trace_references.flags")
+ TraceReferences(ctx, traceReferencesSources, traceTarget, traceLibs, traceReferencesFlags)
+ flagFiles = append(flagFiles, traceReferencesFlags)
+ }
+
flagFiles = android.FirstUniquePaths(flagFiles)
r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
@@ -356,10 +507,22 @@
r8Flags = append(r8Flags, opt.Proguard_flags...)
- if BoolDefault(opt.Proguard_compatibility, true) {
+ if BoolDefault(opt.Ignore_library_extends_program, false) {
+ r8Flags = append(r8Flags, "--ignore-library-extends-program")
+ }
+
+ if BoolDefault(opt.Keep_runtime_invisible_annotations, false) {
+ r8Flags = append(r8Flags, "--keep-runtime-invisible-annotations")
+ }
+
+ if BoolDefault(opt.Proguard_compatibility, !ctx.Config().UseR8FullModeByDefault()) {
r8Flags = append(r8Flags, "--force-proguard-compatibility")
}
+ if BoolDefault(opt.Protect_api_surface, false) {
+ r8Flags = append(r8Flags, "--protect-api-surface")
+ }
+
// Avoid unnecessary stack frame noise by only injecting source map ids for non-debug
// optimized or obfuscated targets.
if (Bool(opt.Optimize) || Bool(opt.Obfuscate)) && !debugMode {
@@ -412,6 +575,15 @@
artProfileOutput = profileOutput
}
+ if ctx.Config().UseR8StoreStoreFenceConstructorInlining() {
+ r8Flags = append(r8Flags, "--store-store-fence-constructor-inlining")
+ }
+
+ if opt.Exclude != nil {
+ r8Flags = append(r8Flags, "--exclude", *opt.Exclude)
+ r8Deps = append(r8Deps, android.PathForModuleSrc(ctx, *opt.Exclude))
+ }
+
return r8Flags, r8Deps, artProfileOutput
}
@@ -448,6 +620,7 @@
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
+ cleanPhonyPath := android.PathForModuleOut(ctx, "dex", dexParams.jarName+"-partialcompileclean").OutputPath
outDir := android.PathForModuleOut(ctx, "dex")
zipFlags := "--ignore_missing_files"
@@ -463,8 +636,20 @@
mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins"
}
- useR8 := d.effectiveOptimizeEnabled()
+ useR8 := d.effectiveOptimizeEnabled(ctx)
+ useD8 := !useR8 || ctx.Config().PartialCompileFlags().Use_d8
+ rbeR8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8")
+ rbeD8 := ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8")
+ var rule blueprint.Rule
+ var description string
var artProfileOutputPath *android.OutputPath
+ var implicitOutputs android.WritablePaths
+ var deps android.Paths
+ args := map[string]string{
+ "zipFlags": zipFlags,
+ "outDir": outDir.String(),
+ "mergeZipsFlags": mergeZipsFlags,
+ }
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
@@ -477,83 +662,89 @@
d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
- implicitOutputs := android.WritablePaths{
+ implicitOutputs = append(implicitOutputs, android.WritablePaths{
proguardDictionary,
proguardUsageZip,
proguardConfiguration,
- }
+ }...)
+ description = "r8"
debugMode := android.InList("--debug", commonFlags)
r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode)
- rule := r8
- args := map[string]string{
- "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
- "zipFlags": zipFlags,
- "outDict": proguardDictionary.String(),
- "outConfig": proguardConfiguration.String(),
- "outUsageDir": proguardUsageDir.String(),
- "outUsage": proguardUsage.String(),
- "outUsageZip": proguardUsageZip.String(),
- "outDir": outDir.String(),
- "mergeZipsFlags": mergeZipsFlags,
- }
+ deps = append(deps, r8Deps...)
+ args["r8Flags"] = strings.Join(append(commonFlags, r8Flags...), " ")
if r8ArtProfileOutputPath != nil {
artProfileOutputPath = r8ArtProfileOutputPath
- implicitOutputs = append(
- implicitOutputs,
- artProfileOutputPath,
- )
// Add the implicit r8 Art profile output to args so that r8RE knows
// about this implicit output
- args["outR8ArtProfile"] = artProfileOutputPath.String()
+ args["outR8ArtProfile"] = r8ArtProfileOutputPath.String()
}
-
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
- rule = r8RE
- args["implicits"] = strings.Join(r8Deps.Strings(), ",")
- }
+ args["outDict"] = proguardDictionary.String()
+ args["outConfig"] = proguardConfiguration.String()
+ args["outUsageDir"] = proguardUsageDir.String()
+ args["outUsage"] = proguardUsage.String()
+ args["outUsageZip"] = proguardUsageZip.String()
if d.resourcesInput.Valid() {
implicitOutputs = append(implicitOutputs, resourcesOutput)
args["resourcesOutput"] = resourcesOutput.String()
}
- ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "r8",
- Output: javalibJar,
- ImplicitOutputs: implicitOutputs,
- Input: dexParams.classesJar,
- Implicits: r8Deps,
- Args: args,
- })
- } else {
- implicitOutputs := android.WritablePaths{}
+
+ rule = r8
+ if rbeR8 {
+ rule = r8RE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ }
+ }
+ if useD8 {
+ description = "d8"
d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams)
+ deps = append(deps, d8Deps...)
+ deps = append(deps, commonDeps...)
+ args["d8Flags"] = strings.Join(append(commonFlags, d8Flags...), " ")
if d8ArtProfileOutputPath != nil {
artProfileOutputPath = d8ArtProfileOutputPath
- implicitOutputs = append(
- implicitOutputs,
- artProfileOutputPath,
- )
}
- d8Deps = append(d8Deps, commonDeps...)
- rule := d8
- if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
+ // If we are generating both d8 and r8, only use RBE when both are enabled.
+ switch {
+ case useR8 && rule == r8:
+ rule = d8r8
+ description = "d8r8"
+ case useR8 && rule == r8RE && rbeD8:
+ rule = d8r8RE
+ description = "d8r8"
+ case rbeD8:
rule = d8RE
+ default:
+ rule = d8
}
- ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "d8",
- Output: javalibJar,
- Input: dexParams.classesJar,
- ImplicitOutputs: implicitOutputs,
- Implicits: d8Deps,
- Args: map[string]string{
- "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
- "zipFlags": zipFlags,
- "outDir": outDir.String(),
- "mergeZipsFlags": mergeZipsFlags,
- },
- })
}
+ if artProfileOutputPath != nil {
+ implicitOutputs = append(
+ implicitOutputs,
+ artProfileOutputPath,
+ )
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: description,
+ Output: javalibJar,
+ ImplicitOutputs: implicitOutputs,
+ Input: dexParams.classesJar,
+ Implicits: deps,
+ Args: args,
+ })
+ if useR8 && useD8 {
+ // Generate the rule for partial compile clean.
+ args["builtOut"] = javalibJar.String()
+ ctx.Build(pctx, android.BuildParams{
+ Rule: d8r8Clean,
+ Description: "d8r8Clean",
+ Output: cleanPhonyPath,
+ Args: args,
+ PhonyOutput: true,
+ })
+ ctx.Phony("partialcompileclean", cleanPhonyPath)
+ }
+
if proptools.Bool(d.dexProperties.Uncompress_dex) {
alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", dexParams.jarName).OutputPath
TransformZipAlign(ctx, alignedJavalibJar, javalibJar, nil)
@@ -562,3 +753,13 @@
return javalibJar, artProfileOutputPath
}
+
+type ProguardInfo struct {
+ ModuleName string
+ Class string
+ ProguardDictionary android.Path
+ ProguardUsageZip android.Path
+ ClassesJar android.Path
+}
+
+var ProguardProvider = blueprint.NewProvider[ProguardInfo]()
diff --git a/java/dex_test.go b/java/dex_test.go
index 8bc28e6..8c1e5f7 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "strconv"
"testing"
"android/soong/android"
@@ -24,6 +25,7 @@
)
func TestR8(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app {
name: "app",
@@ -58,26 +60,27 @@
}
`)
- app := result.ModuleForTests("app", "android_common")
- stableApp := result.ModuleForTests("stable_app", "android_common")
- corePlatformApp := result.ModuleForTests("core_platform_app", "android_common")
- lib := result.ModuleForTests("lib", "android_common")
- staticLib := result.ModuleForTests("static_lib", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
+ stableApp := result.ModuleForTests(t, "stable_app", "android_common")
+ corePlatformApp := result.ModuleForTests(t, "core_platform_app", "android_common")
+ lib := result.ModuleForTests(t, "lib", "android_common")
+ staticLib := result.ModuleForTests(t, "static_lib", "android_common")
appJavac := app.Rule("javac")
appR8 := app.Rule("r8")
stableAppR8 := stableApp.Rule("r8")
corePlatformAppR8 := corePlatformApp.Rule("r8")
- libHeader := lib.Output("turbine-combined/lib.jar").Output
- staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output
+ libHeader := lib.Output("turbine/lib.jar").Output
+ libCombinedHeader := lib.Output("turbine-combined/lib.jar").Output
+ staticLibHeader := staticLib.Output("turbine/static_lib.jar").Output
android.AssertStringDoesContain(t, "expected lib header jar in app javac classpath",
appJavac.Args["classpath"], libHeader.String())
android.AssertStringDoesContain(t, "expected static_lib header jar in app javac classpath",
appJavac.Args["classpath"], staticLibHeader.String())
- android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
- appR8.Args["r8Flags"], libHeader.String())
+ android.AssertStringDoesContain(t, "expected lib combined header jar in app r8 classpath",
+ appR8.Args["r8Flags"], libCombinedHeader.String())
android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
appR8.Args["r8Flags"], staticLibHeader.String())
android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
@@ -91,6 +94,7 @@
}
func TestR8TransitiveDeps(t *testing.T) {
+ t.Parallel()
bp := `
override_android_app {
name: "override_app",
@@ -192,6 +196,7 @@
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
fixturePreparer := PrepareForTestWithJavaDefaultModules
if tc.unbundled {
fixturePreparer = android.GroupFixturePreparers(
@@ -206,14 +211,14 @@
result := fixturePreparer.RunTestWithBp(t, bp)
getHeaderJar := func(name string) android.Path {
- mod := result.ModuleForTests(name, "android_common")
+ mod := result.ModuleForTests(t, name, "android_common")
return mod.Output("turbine-combined/" + name + ".jar").Output
}
- appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
- overrideAppR8 := result.ModuleForTests("app", "android_common_override_app").Rule("r8")
+ appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8")
+ overrideAppR8 := result.ModuleForTests(t, "app", "android_common_override_app").Rule("r8")
appHeader := getHeaderJar("app")
- overrideAppHeader := result.ModuleForTests("app", "android_common_override_app").Output("turbine-combined/app.jar").Output
+ overrideAppHeader := result.ModuleForTests(t, "app", "android_common_override_app").Output("turbine-combined/app.jar").Output
libHeader := getHeaderJar("lib")
transitiveLibHeader := getHeaderJar("transitive_lib")
transitiveLib2Header := getHeaderJar("transitive_lib_2")
@@ -222,7 +227,7 @@
repeatedDepHeader := getHeaderJar("repeated_dep")
usesLibHeader := getHeaderJar("uses_lib")
optionalUsesLibHeader := getHeaderJar("optional_uses_lib")
- prebuiltLibHeader := result.ModuleForTests("prebuilt_lib", "android_common").Output("combined/lib.jar").Output
+ prebuiltLibHeader := result.ModuleForTests(t, "prebuilt_lib", "android_common").Output("combined/lib.jar").Output
for _, rule := range []android.TestingBuildParams{appR8, overrideAppR8} {
android.AssertStringDoesNotContain(t, "expected no app header jar in app r8 classpath",
@@ -259,6 +264,7 @@
}
func TestR8Flags(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app {
name: "app",
@@ -273,7 +279,7 @@
}
`)
- app := result.ModuleForTests("app", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
appR8 := app.Rule("r8")
android.AssertStringDoesContain(t, "expected -dontshrink in app r8 flags",
appR8.Args["r8Flags"], "-dontshrink")
@@ -288,6 +294,7 @@
}
func TestD8(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
java_library {
name: "foo",
@@ -306,29 +313,52 @@
name: "static_lib",
srcs: ["foo.java"],
}
+
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ platform_apis: true,
+ optimize: {
+ enabled: false,
+ },
+ }
`)
- foo := result.ModuleForTests("foo", "android_common")
- lib := result.ModuleForTests("lib", "android_common")
- staticLib := result.ModuleForTests("static_lib", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ lib := result.ModuleForTests(t, "lib", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
+ staticLib := result.ModuleForTests(t, "static_lib", "android_common")
fooJavac := foo.Rule("javac")
fooD8 := foo.Rule("d8")
- libHeader := lib.Output("turbine-combined/lib.jar").Output
- staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output
+ appD8 := app.Rule("d8")
+ libHeader := lib.Output("turbine/lib.jar").Output
+ libCombinedHeader := lib.Output("turbine-combined/lib.jar").Output
+ staticLibHeader := staticLib.Output("turbine/static_lib.jar").Output
android.AssertStringDoesContain(t, "expected lib header jar in foo javac classpath",
fooJavac.Args["classpath"], libHeader.String())
android.AssertStringDoesContain(t, "expected static_lib header jar in foo javac classpath",
fooJavac.Args["classpath"], staticLibHeader.String())
- android.AssertStringDoesContain(t, "expected lib header jar in foo d8 classpath",
- fooD8.Args["d8Flags"], libHeader.String())
+ android.AssertStringDoesContain(t, "expected lib combined header jar in foo d8 classpath",
+ fooD8.Args["d8Flags"], libCombinedHeader.String())
android.AssertStringDoesNotContain(t, "expected no static_lib header jar in foo javac classpath",
fooD8.Args["d8Flags"], staticLibHeader.String())
+
+ // A --release flag is added only for targets that opt out of default R8 behavior (e.g., apps).
+ // For library targets that don't use R8 by default, no --debug or --release flag should be
+ // added, instead relying on default D8 behavior (--debug).
+ android.AssertStringDoesContain(t, "expected --release in app d8 flags",
+ appD8.Args["d8Flags"], "--release")
+ android.AssertStringDoesNotContain(t, "expected no --release flag in lib d8 flags",
+ fooD8.Args["d8Flags"], "--release")
+ android.AssertStringDoesNotContain(t, "expected no --debug flag in lib d8 flags",
+ fooD8.Args["d8Flags"], "--debug")
}
func TestProguardFlagsInheritanceStatic(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app {
name: "app",
@@ -370,7 +400,7 @@
}
`)
- app := result.ModuleForTests("app", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
appR8 := app.Rule("r8")
android.AssertStringDoesContain(t, "expected primary_lib's proguard flags from direct dep",
appR8.Args["r8Flags"], "primary.flags")
@@ -383,6 +413,7 @@
}
func TestProguardFlagsInheritance(t *testing.T) {
+ t.Parallel()
directDepFlagsFileName := "direct_dep.flags"
transitiveDepFlagsFileName := "transitive_dep.flags"
@@ -601,6 +632,7 @@
for _, topLevelModuleDef := range topLevelModules {
for _, tc := range testcases {
t.Run(topLevelModuleDef.name+"-"+tc.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureMergeMockFs(android.MockFS{
@@ -617,7 +649,7 @@
tc.transitiveDepExportsFlagsFiles,
),
)
- appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8")
shouldHaveDepFlags := android.InList(directDepFlagsFileName, tc.expectedFlagsFiles)
if shouldHaveDepFlags {
@@ -642,6 +674,7 @@
}
func TestProguardFlagsInheritanceAppImport(t *testing.T) {
+ t.Parallel()
bp := `
android_app {
name: "app",
@@ -658,12 +691,13 @@
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, bp)
- appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ appR8 := result.ModuleForTests(t, "app", "android_common").Rule("r8")
android.AssertStringDoesContain(t, "expected aarimports's proguard flags",
appR8.Args["r8Flags"], "proguard.txt")
}
func TestR8FlagsArtProfile(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app {
name: "app",
@@ -677,7 +711,7 @@
}
`)
- app := result.ModuleForTests("app", "android_common")
+ app := result.ModuleForTests(t, "app", "android_common")
appR8 := app.Rule("r8")
android.AssertStringDoesContain(t, "expected --art-profile in app r8 flags",
appR8.Args["r8Flags"], "--art-profile")
@@ -696,6 +730,7 @@
//
// The rewritten profile should be used since the dex signatures in the checked-in profile will not match the optimized binary.
func TestEnableProfileRewritingIsRequiredForOptimizedApps(t *testing.T) {
+ t.Parallel()
testJavaError(t,
"Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on",
`
@@ -715,11 +750,15 @@
}
func TestDebugReleaseFlags(t *testing.T) {
+ t.Parallel()
bp := `
android_app {
name: "app",
srcs: ["foo.java"],
platform_apis: true,
+ optimize: {
+ enabled: %s,
+ },
dxflags: ["%s"]
}
`
@@ -728,6 +767,7 @@
name string
envVar string
isEng bool
+ useD8 bool
dxFlags string
expectedFlags string
}{
@@ -757,20 +797,36 @@
},
{
name: "app_eng",
+ useD8: true,
isEng: true,
expectedFlags: "--debug",
},
{
name: "app_release_eng",
isEng: true,
+ useD8: true,
dxFlags: "--release",
// Eng mode does *not* override explicit dxflags.
expectedFlags: "--release",
},
+ {
+ name: "app_d8",
+ useD8: true,
+ // D8 usage w/ apps should explicitly enable --release mode.
+ expectedFlags: "--release",
+ },
+ {
+ name: "app_d8_debug",
+ useD8: true,
+ dxFlags: "--debug",
+ // D8 usage w/ apps respects overriding dxFlags.
+ expectedFlags: "--debug",
+ },
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
fixturePreparer := PrepareForTestWithJavaDefaultModules
fixturePreparer = android.GroupFixturePreparers(
fixturePreparer,
@@ -788,11 +844,16 @@
}),
)
}
- result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, tc.dxFlags))
+ result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, strconv.FormatBool(!tc.useD8), tc.dxFlags))
- appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
- android.AssertStringDoesContain(t, "expected flag in R8 flags",
- appR8.Args["r8Flags"], tc.expectedFlags)
+ dexRuleKey := "r8"
+ if tc.useD8 {
+ dexRuleKey = "d8"
+ }
+ dexFlagsKey := dexRuleKey + "Flags"
+ appDex := result.ModuleForTests(t, "app", "android_common").Rule(dexRuleKey)
+ android.AssertStringDoesContain(t, "expected flag in dex flags",
+ appDex.Args[dexFlagsKey], tc.expectedFlags)
var unexpectedFlags string
if tc.expectedFlags == "--debug" {
@@ -801,9 +862,52 @@
unexpectedFlags = "--debug"
}
if unexpectedFlags != "" {
- android.AssertStringDoesNotContain(t, "unexpected flag in R8 flags",
- appR8.Args["r8Flags"], unexpectedFlags)
+ android.AssertStringDoesNotContain(t, "unexpected flag in dex flags",
+ appDex.Args[dexFlagsKey], unexpectedFlags)
}
})
}
}
+
+func TestTraceReferences(t *testing.T) {
+ t.Parallel()
+ bp := `
+ android_app {
+ name: "app",
+ libs: ["lib.impl"],
+ srcs: ["foo.java"],
+ platform_apis: true,
+ }
+
+ java_library {
+ name: "lib",
+ optimize: {
+ enabled: true,
+ trace_references_from: ["app"],
+ },
+ srcs: ["bar.java"],
+ static_libs: ["lib.impl"],
+ installable: true,
+ }
+
+ java_library {
+ name: "lib.impl",
+ srcs: ["baz.java"],
+ }
+ `
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ appJar := result.ModuleForTests(t, "app", "android_common").Output("combined/app.jar").Output
+ libJar := result.ModuleForTests(t, "lib", "android_common").Output("combined/lib.jar").Output
+ libTraceRefs := result.ModuleForTests(t, "lib", "android_common").Rule("traceReferences")
+ libR8 := result.ModuleForTests(t, "lib", "android_common").Rule("r8")
+
+ android.AssertStringDoesContain(t, "expected trace reference source from app jar",
+ libTraceRefs.Args["sources"], "--source "+appJar.String())
+ android.AssertStringEquals(t, "expected trace reference target into lib jar",
+ libJar.String(), libTraceRefs.Input.String())
+ android.AssertStringDoesContain(t, "expected trace reference proguard flags in lib r8 flags",
+ libR8.Args["r8Flags"], "trace_references.flags")
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 5928446..e8e1cd4 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -36,61 +36,24 @@
// If the java module is to be installed into an APEX, this list contains information about the
// dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed
// outside of the APEX.
- DexpreoptBuiltInstalledForApex() []dexpreopterInstall
+ ApexSystemServerDexpreoptInstalls() []DexpreopterInstall
- // The Make entries to install the dexpreopt outputs. Derived from
- // `DexpreoptBuiltInstalledForApex`.
- AndroidMkEntriesForApex() []android.AndroidMkEntries
+ // ApexSystemServerDexJars returns the list of dex jars if this is an apex system server jar.
+ ApexSystemServerDexJars() android.Paths
// See `dexpreopter.outputProfilePathOnHost`.
OutputProfilePathOnHost() android.Path
}
-type dexpreopterInstall struct {
- // A unique name to distinguish an output from others for the same java library module. Usually in
- // the form of `<arch>-<encoded-path>.odex/vdex/art`.
- name string
-
- // The name of the input java module.
- moduleName string
-
+type DexpreopterInstall struct {
// The path to the dexpreopt output on host.
- outputPathOnHost android.Path
+ OutputPathOnHost android.Path
// The directory on the device for the output to install to.
- installDirOnDevice android.InstallPath
+ InstallDirOnDevice android.InstallPath
// The basename (the last segment of the path) for the output to install as.
- installFileOnDevice string
-}
-
-// The full module name of the output in the makefile.
-func (install *dexpreopterInstall) FullModuleName() string {
- return install.moduleName + install.SubModuleName()
-}
-
-// The sub-module name of the output in the makefile (the name excluding the java module name).
-func (install *dexpreopterInstall) SubModuleName() string {
- return "-dexpreopt-" + install.name
-}
-
-// Returns Make entries for installing the file.
-//
-// This function uses a value receiver rather than a pointer receiver to ensure that the object is
-// safe to use in `android.AndroidMkExtraEntriesFunc`.
-func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
- return android.AndroidMkEntries{
- Class: "ETC",
- OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE", install.FullModuleName())
- entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
- entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
- },
- },
- }
+ InstallFileOnDevice string
}
type Dexpreopter struct {
@@ -120,8 +83,9 @@
classLoaderContexts dexpreopt.ClassLoaderContextMap
// See the `dexpreopt` function for details.
- builtInstalled string
- builtInstalledForApex []dexpreopterInstall
+ builtInstalled string
+ apexSystemServerDexpreoptInstalls []DexpreopterInstall
+ apexSystemServerDexJars android.Paths
// The config is used for two purposes:
// - Passing dexpreopt information about libraries from Soong to Make. This is needed when
@@ -204,27 +168,23 @@
}
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
psi := android.PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDeps(func(am android.Module) {
+ ctx.VisitDirectDepsProxy(func(am android.ModuleProxy) {
if prebuiltSelectionInfo, ok := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); ok {
psi = prebuiltSelectionInfo
}
})
// Find the apex variant for this module
- apexVariantsWithoutTestApexes := []string{}
+ apexVariants := []string{}
if apexInfo.BaseApexName != "" {
- // This is a transitive dependency of an override_apex
- apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.BaseApexName)
- } else {
- _, variants, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes)
- apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, variants...)
+ apexVariants = append(apexVariants, apexInfo.BaseApexName)
}
if apexInfo.ApexAvailableName != "" {
- apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.ApexAvailableName)
+ apexVariants = append(apexVariants, apexInfo.ApexAvailableName)
}
disableSource := false
// find the selected apexes
- for _, apexVariant := range apexVariantsWithoutTestApexes {
+ for _, apexVariant := range apexVariants {
if len(psi.GetSelectedModulesForApiDomain(apexVariant)) > 0 {
// If the apex_contribution for this api domain is non-empty, disable the source variant
disableSource = true
@@ -279,20 +239,6 @@
if !isApexSystemServerJar {
return true
}
- ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
- allApexInfos := []android.ApexInfo{}
- if allApexInfosProvider, ok := android.ModuleProvider(ctx, android.AllApexInfoProvider); ok {
- allApexInfos = allApexInfosProvider.ApexInfos
- }
- if len(allApexInfos) > 0 && !ai.MinSdkVersion.EqualTo(allApexInfos[0].MinSdkVersion) {
- // Apex system server jars are dexpreopted and installed on to the system image.
- // Since we can have BigAndroid and Go variants of system server jar providing apexes,
- // and these two variants can have different min_sdk_versions, hide one of the apex variants
- // from make to prevent collisions.
- //
- // Unlike cc, min_sdk_version does not have an effect on the build actions of java libraries.
- ctx.Module().MakeUninstallable()
- }
} else {
// Don't preopt the platform variant of an APEX system server jar to avoid conflicts.
if isApexSystemServerJar {
@@ -347,7 +293,11 @@
d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
// generate the rules for creating the .odex and .vdex files for this system server jar
dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
-
+ if dexJarFile == nil {
+ ctx.ModuleErrorf(
+ `Could not find library %s in prebuilt apex %s.
+Please make sure that the value of PRODUCT_APEX_(SYSTEM_SERVER|STANDALONE_SYSTEM_SERVER)_JARS is correct`, libraryName, ctx.ModuleName())
+ }
d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless
if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) {
// Set the profile path to guide optimization
@@ -539,12 +489,8 @@
Output(appProductPackages)
productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages")
- // Prebuilts are active, do not copy the dexpreopt'd source javalib to out/soong/system_server_dexjars
- // The javalib from the deapexed prebuilt will be copied to this location.
- // TODO (b/331665856): Implement a principled solution for this.
- copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) && !ctx.Module().IsHideFromMake()
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(
- ctx, globalSoong, global, dexpreoptConfig, appProductPackages, copyApexSystemServerJarDex)
+ ctx, globalSoong, global, dexpreoptConfig, appProductPackages)
if err != nil {
ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
return
@@ -577,7 +523,6 @@
partition = ""
}
installBase := filepath.Base(install.To)
- arch := filepath.Base(installDir)
installPath := android.PathForModuleInPartitionInstall(ctx, partition, installDir)
isProfile := strings.HasSuffix(installBase, ".prof")
@@ -593,16 +538,13 @@
// libraries, only those in the system server classpath are handled here.
// Preopting of boot classpath jars in the ART APEX are handled in
// java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
- // The installs will be handled by Make as sub-modules of the java library.
- di := dexpreopterInstall{
- name: arch + "-" + installBase,
- moduleName: libName,
- outputPathOnHost: install.From,
- installDirOnDevice: installPath,
- installFileOnDevice: installBase,
+ // The installs will be handled the apex module that includes this library.
+ di := DexpreopterInstall{
+ OutputPathOnHost: install.From,
+ InstallDirOnDevice: installPath,
+ InstallFileOnDevice: installBase,
}
- ctx.InstallFile(di.installDirOnDevice, di.installFileOnDevice, di.outputPathOnHost)
- d.builtInstalledForApex = append(d.builtInstalledForApex, di)
+ d.apexSystemServerDexpreoptInstalls = append(d.apexSystemServerDexpreoptInstalls, di)
}
} else if !d.preventInstall {
@@ -611,9 +553,22 @@
}
}
+ if isApexSystemServerJar {
+ // Store the dex jar location for system server jars in apexes, the apex will copy the file into
+ // a known location for dex2oat.
+ d.apexSystemServerDexJars = append(d.apexSystemServerDexJars, dexJarFile)
+ } else if isSystemServerJar && !d.preventInstall {
+ // Copy the dex jar into a known location for dex2oat for non-apex system server jars.
+ android.CopyFileRule(ctx, dexJarFile, android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJarFile.Base()))
+ }
+
if !isApexSystemServerJar {
d.builtInstalled = dexpreoptRule.Installs().String()
}
+
+ if isSystemServerJar {
+ checkSystemServerOrder(ctx, libName)
+ }
}
func getModuleInstallPathInfo(ctx android.ModuleContext, fullInstallPath string) (android.InstallPath, string, string) {
@@ -645,16 +600,12 @@
}
}
-func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall {
- return d.builtInstalledForApex
+func (d *dexpreopter) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall {
+ return d.apexSystemServerDexpreoptInstalls
}
-func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
- var entries []android.AndroidMkEntries
- for _, install := range d.builtInstalledForApex {
- entries = append(entries, install.ToMakeEntries())
- }
- return entries
+func (d *dexpreopter) ApexSystemServerDexJars() android.Paths {
+ return d.apexSystemServerDexJars
}
func (d *dexpreopter) OutputProfilePathOnHost() android.Path {
@@ -684,3 +635,33 @@
func (d *dexpreopter) SetRewrittenProfile(p android.Path) {
d.rewrittenProfile = p
}
+
+// Check the order of jars on the system server classpath and give a warning/error if a jar precedes
+// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't
+// have the dependency jar in the class loader context, and it won't be able to resolve any
+// references to its classes and methods.
+func checkSystemServerOrder(ctx android.ModuleContext, libName string) {
+ config := dexpreopt.GetGlobalConfig(ctx)
+ jars := config.AllSystemServerClasspathJars(ctx)
+ jarIndex := config.AllSystemServerJars(ctx).IndexOfJar(libName)
+ ctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+ tag := ctx.OtherModuleDependencyTag(dep)
+ // Ideally this should only be walking relevant dependencies, but to maintain existing behavior
+ // for now just exclude any known irrelevant dependencies that would lead to incorrect errors.
+ if _, ok := tag.(bootclasspathDependencyTag); ok {
+ return false
+ } else if tag == traceReferencesTag {
+ // Allow ordering inversion if the dependency is purely for tracing references.
+ return false
+ }
+ depIndex := jars.IndexOfJar(dep.Name())
+ if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
+ jar := jars.Jar(jarIndex)
+ dep := jars.Jar(depIndex)
+ ctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+
+ " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+
+ " references from '%s' to '%s'.\n", jar, dep, jar, dep)
+ }
+ return true
+ })
+}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 8c60d23..2287043 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"path/filepath"
"strings"
@@ -225,7 +226,6 @@
}
var (
- dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
apexContributionsMetadataDepTag = dependencyTag{name: "all_apex_contributions"}
)
@@ -293,6 +293,9 @@
// Profiles imported from APEXes, in addition to the profile at the default path. Each entry must
// be the name of an APEX module.
profileImports []string
+
+ // The name of the module that provides boot image profiles, if any.
+ profileProviderModule string
}
// Target-dependent description of a boot image.
@@ -464,9 +467,6 @@
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
ctx.RegisterModuleType("art_boot_images", artBootImagesFactory)
- ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator)
- })
}
func SkipDexpreoptBootJars(ctx android.PathContext) bool {
@@ -502,12 +502,6 @@
func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) {
// Create a dependency on all_apex_contributions to determine the selected mainline module
ctx.AddDependency(ctx.Module(), apexContributionsMetadataDepTag, "all_apex_contributions")
-}
-
-func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
- if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
- return
- }
if dexpreopt.IsDex2oatNeeded(ctx) {
// Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
@@ -521,7 +515,7 @@
continue
}
// For accessing the boot jars.
- addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJar)
// Create a dependency on the apex selected using RELEASE_APEX_CONTRIBUTIONS_*
// TODO: b/308174306 - Remove the direct depedendency edge to the java_library (source/prebuilt) once all mainline modules
// have been flagged using RELEASE_APEX_CONTRIBUTIONS_*
@@ -534,11 +528,11 @@
if ctx.OtherModuleExists("platform-bootclasspath") {
// For accessing all bootclasspath fragments.
- addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag)
+ addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platform)
} else if ctx.OtherModuleExists("art-bootclasspath-fragment") {
// For accessing the ART bootclasspath fragment on a thin manifest (e.g., master-art) where
// platform-bootclasspath doesn't exist.
- addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", bootclasspathFragmentDepTag)
+ addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", fragment)
}
}
@@ -556,13 +550,13 @@
// We need to add a dep on only the apex listed in `contents` of the selected apex_contributions module
// This is not available in a structured format in `apex_contributions`, so this hack adds a dep on all `contents`
// (some modules like art.module.public.api do not have an apex variation since it is a pure stub module that does not get installed)
- apexVariationOfSelected := append(ctx.Target().Variations(), blueprint.Variation{Mutator: "apex", Variation: apex})
- if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, selected) {
- ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected)
- } else if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, android.RemoveOptionalPrebuiltPrefix(selected)) {
- // The prebuilt might have been renamed by prebuilt_rename mutator if the source module does not exist.
- // Remove the prebuilt_ prefix.
- ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, android.RemoveOptionalPrebuiltPrefix(selected))
+ tag := bootclasspathDependencyTag{
+ typ: dexpreoptBootJar,
+ }
+
+ dep := android.RemoveOptionalPrebuiltPrefix(selected)
+ if ctx.OtherModuleDependencyVariantExists(ctx.Target().Variations(), dep) {
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, dep)
}
}
}
@@ -571,23 +565,55 @@
func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
fragments := make(map[string]android.Module)
+
+ type moduleInApexPair struct {
+ module string
+ apex string
+ }
+
+ var modulesInApexes []moduleInApexPair
+
+ // Find the list of modules in apexes.
ctx.WalkDeps(func(child, parent android.Module) bool {
if !isActiveModule(ctx, child) {
return false
}
tag := ctx.OtherModuleDependencyTag(child)
- if tag == platformBootclasspathDepTag {
- return true
- }
- if tag == bootclasspathFragmentDepTag {
- apexInfo, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- for _, apex := range apexInfo.InApexVariants {
- fragments[apex] = child
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok {
+ if bcpTag.typ == platform {
+ return true
}
- return false
+ if bcpTag.typ == fragment {
+ if bcpTag.moduleInApex == "" {
+ panic(fmt.Errorf("expected fragment to be in apex"))
+ }
+ modulesInApexes = append(modulesInApexes, moduleInApexPair{bcpTag.moduleInApex, ctx.OtherModuleName(child)})
+ return true
+ }
}
return false
})
+
+ for _, moduleInApex := range modulesInApexes {
+ // Find a desired module in an apex.
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok {
+ if bcpTag.typ == platform {
+ return true
+ }
+ if bcpTag.typ == fragment && ctx.OtherModuleName(child) == moduleInApex.apex {
+ // This is the dependency from this module to the apex, recurse into it.
+ return true
+ }
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
+ // This is the desired module inside the apex.
+ fragments[android.RemoveOptionalPrebuiltPrefix(moduleInApex.apex)] = child
+ }
+ return false
+ })
+ }
+
return fragments
}).(map[string]android.Module)
}
@@ -649,6 +675,139 @@
installs: artBootImageHostInstalls,
},
)
+
+ d.buildBootZip(ctx)
+}
+
+// Build the boot.zip which contains the boot jars and their compilation output
+// We can do this only if preopt is enabled and if the product uses libart config (which sets the
+// default properties for preopting).
+// Origionally, this was only for ART Cloud.
+func (d *dexpreoptBootJars) buildBootZip(ctx android.ModuleContext) {
+ image := d.defaultBootImage
+ if image == nil || SkipDexpreoptBootJars(ctx) {
+ return
+ }
+ global := dexpreopt.GetGlobalConfig(ctx)
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
+ if global.DisablePreopt || global.OnlyPreoptArtBootImage {
+ return
+ }
+
+ bootclasspathDexFiles, bootclassPathLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
+ if len(bootclasspathDexFiles) == 0 {
+ return
+ }
+
+ systemServerDexjarsDir := android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir)
+
+ bootZipMetadataTmp := android.PathForModuleOut(ctx, "boot_zip", "METADATA.txt.tmp")
+ bootZipMetadata := android.PathForModuleOut(ctx, "boot_zip", "METADATA.txt")
+ newlineFile := android.PathForModuleOut(ctx, "boot_zip", "newline.txt")
+ android.WriteFileRule(ctx, newlineFile, "")
+
+ dexPreoptRootDir := filepath.Dir(filepath.Dir(bootclasspathDexFiles[0].String()))
+
+ var sb strings.Builder
+ sb.WriteString("bootclasspath = ")
+ for i, bootclasspathJar := range bootclasspathDexFiles {
+ if i > 0 {
+ sb.WriteString(":")
+ }
+ rel, err := filepath.Rel(dexPreoptRootDir, bootclasspathJar.String())
+ if err != nil {
+ ctx.ModuleErrorf("All dexpreopt jars should be under the same rootdir %q, but %q wasn't.", dexPreoptRootDir, bootclasspathJar)
+ } else {
+ sb.WriteString(rel)
+ }
+ }
+ sb.WriteString("\nbootclasspath-locations = ")
+ for i, bootclasspathLocation := range bootclassPathLocations {
+ if i > 0 {
+ sb.WriteString(":")
+ }
+ sb.WriteString(bootclasspathLocation)
+ }
+ sb.WriteString("\nboot-image = ")
+
+ // Infix can be 'art' (ART image for testing), 'boot' (primary), or 'mainline' (mainline
+ // extension). Soong creates a set of variables for Make, one or each boot image. The only
+ // reason why the ART image is exposed to Make is testing (art gtests) and benchmarking (art
+ // golem benchmarks). Install rules that use those variables are in dex_preopt_libart.mk. Here
+ // for dexpreopt purposes the infix is always 'boot' or 'mainline'.
+ dexpreoptInfix := "boot"
+ if global.PreoptWithUpdatableBcp {
+ dexpreoptInfix = "mainline"
+ }
+
+ var dexPreoptImageZipBoot android.Path
+ var dexPreoptImageZipArt android.Path
+ var dexPreoptImageZipMainline android.Path
+ for _, current := range append(d.otherImages, image) {
+ if current.name == dexpreoptInfix {
+ _, imageLocationsOnDevice := current.getAnyAndroidVariant().imageLocations()
+ for i, location := range imageLocationsOnDevice {
+ imageLocationsOnDevice[i] = strings.TrimPrefix(location, "/")
+ }
+ sb.WriteString(strings.Join(imageLocationsOnDevice, ":"))
+ }
+ switch current.name {
+ case "boot":
+ dexPreoptImageZipBoot = current.zip
+ case "art":
+ dexPreoptImageZipArt = current.zip
+ case "mainline":
+ dexPreoptImageZipMainline = current.zip
+ }
+ }
+ sb.WriteString("\nextra-args = ")
+ android.WriteFileRuleVerbatim(ctx, bootZipMetadataTmp, sb.String())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Inputs: []android.Path{
+ bootZipMetadataTmp,
+ globalSoong.UffdGcFlag,
+ newlineFile,
+ },
+ Output: bootZipMetadata,
+ })
+
+ bootZipFirstPart := android.PathForModuleOut(ctx, "boot_zip", "boot_first_part.zip")
+ bootZip := android.PathForModuleOut(ctx, "boot_zip", "boot.zip")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", bootZipFirstPart).
+ FlagWithArg("-C ", filepath.Dir(filepath.Dir(bootclasspathDexFiles[0].String())))
+ for _, bootclasspathJar := range bootclasspathDexFiles {
+ cmd.FlagWithInput("-f ", bootclasspathJar)
+ }
+ for i := range global.SystemServerJars.Len() {
+ // Use "/system" path for JARs with "platform:" prefix. These JARs counterintuitively use
+ // "platform" prefix but they will be actually installed to /system partition.
+ // For the remaining system server JARs use the partition signified by the prefix.
+ // For example, prefix "system_ext:" will use "/system_ext" path.
+ dir := global.SystemServerJars.Apex(i)
+ if dir == "platform" {
+ dir = "system"
+ }
+ jar := global.SystemServerJars.Jar(i) + ".jar"
+ cmd.FlagWithArg("-e ", dir+"/framework/"+jar)
+ cmd.FlagWithInput("-f ", systemServerDexjarsDir.Join(ctx, jar))
+ }
+ cmd.Flag("-j")
+ cmd.FlagWithInput("-f ", bootZipMetadata)
+
+ builder.Command().BuiltTool("merge_zips").
+ Output(bootZip).
+ Input(bootZipFirstPart).
+ Input(dexPreoptImageZipBoot).
+ Input(dexPreoptImageZipArt).
+ Input(dexPreoptImageZipMainline)
+
+ builder.Build("boot_zip", "build boot.zip")
+
+ ctx.DistForGoal("droidcore", bootZipMetadata)
+ ctx.DistForGoal("droidcore", bootZip)
}
// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
@@ -711,7 +870,8 @@
modules := make([]apexJarModulePair, 0, imageConfig.modules.Len())
for i := 0; i < imageConfig.modules.Len(); i++ {
found := false
- for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) {
+ dexpreoptBootJarModules, _ := gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJar)
+ for _, module := range dexpreoptBootJarModules {
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
if name == imageConfig.modules.Jar(i) {
modules = append(modules, apexJarModulePair{
@@ -794,11 +954,16 @@
"APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
pair.jarModule.Name(),
pair.apex)
+ return nil
}
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider)
jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
if err != nil {
- ctx.ModuleErrorf("%s", err)
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{pair.jarModule.String()})
+ } else {
+ ctx.ModuleErrorf("%s", err)
+ }
}
return jar
}
@@ -957,9 +1122,16 @@
func getApexNameToApexExportsInfoMap(ctx android.ModuleContext) apexNameToApexExportsInfoMap {
apexNameToApexExportsInfoMap := apexNameToApexExportsInfoMap{}
- ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) {
- if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
- apexNameToApexExportsInfoMap[info.ApexName] = info
+
+ ctx.VisitDirectDeps(func(am android.Module) {
+ tag := ctx.OtherModuleDependencyTag(am)
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
+ if bcpTag.moduleInApex == "" {
+ info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider)
+ if exists {
+ apexNameToApexExportsInfoMap[info.ApexName] = info
+ }
+ }
}
})
return apexNameToApexExportsInfoMap
@@ -1442,24 +1614,33 @@
func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) {
// Create a dependency on `dex_bootjars` to access the intermediate locations of host art boot image.
- ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), dexpreoptBootJarDepTag, "dex_bootjars")
+ tag := bootclasspathDependencyTag{
+ typ: dexpreoptBootJar,
+ }
+ ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), tag, "dex_bootjars")
}
func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(m android.Module) {
- hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider)
- if !ok {
- ctx.ModuleErrorf("Could not find information about the host variant of ART boot image")
- }
- installs := d.installFile(ctx, hostInstallsInfo.installs)
- if len(installs) > 0 {
- d.outputFile = android.OptionalPathForPath(installs[0])
- // Create a phony target that can ART run-tests can depend on.
- ctx.Phony(d.Name(), installs...)
- } else {
- // this might be true e.g. when building with `WITH_DEXPREOPT=false`
- // create an empty file so that the `art_boot_images` is known to the packaging system.
- d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images"))
+ ctx.VisitDirectDeps(func(m android.Module) {
+ tag := ctx.OtherModuleDependencyTag(m)
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
+ if bcpTag.moduleInApex != "" {
+ panic("unhandled moduleInApex")
+ }
+ hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider)
+ if !ok {
+ ctx.ModuleErrorf("Could not find information about the host variant of ART boot image")
+ }
+ installs := d.installFile(ctx, hostInstallsInfo.installs)
+ if len(installs) > 0 {
+ d.outputFile = android.OptionalPathForPath(installs[0])
+ // Create a phony target that can ART run-tests can depend on.
+ ctx.Phony(d.Name(), installs...)
+ } else {
+ // this might be true e.g. when building with `WITH_DEXPREOPT=false`
+ // create an empty file so that the `art_boot_images` is known to the packaging system.
+ d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images"))
+ }
}
})
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index dc0973c..fb5c325 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -67,15 +67,16 @@
// ART boot image for testing only. Do not rely on it to make any build-time decision.
artCfg := bootImageConfig{
- name: artBootImageName,
- enabledIfExists: "art-bootclasspath-fragment",
- stem: bootImageStem,
- installDir: "apex/art_boot_images/javalib",
- modules: global.TestOnlyArtBootImageJars,
- preloadedClassesFile: "art/build/boot/preloaded-classes",
- compilerFilter: "speed-profile",
- singleImage: false,
- profileImports: profileImports,
+ name: artBootImageName,
+ enabledIfExists: "art-bootclasspath-fragment",
+ stem: bootImageStem,
+ installDir: "apex/art_boot_images/javalib",
+ modules: global.TestOnlyArtBootImageJars,
+ preloadedClassesFile: "art/build/boot/preloaded-classes",
+ compilerFilter: "speed-profile",
+ singleImage: false,
+ profileImports: profileImports,
+ profileProviderModule: "art-bootclasspath-fragment",
}
// Framework config for the boot image extension.
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
index 44d2127..99b1f23 100644
--- a/java/dexpreopt_config_test.go
+++ b/java/dexpreopt_config_test.go
@@ -23,6 +23,7 @@
)
func TestBootImageConfig(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
t.Skipf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS)
}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 33c682b..241941e 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -1217,6 +1217,7 @@
}
t.Run(imageConfig.name, func(t *testing.T) {
+ t.Parallel()
nestedCheckBootImageConfig(t, result, imageConfig, mutated, expected)
})
}
@@ -1236,7 +1237,7 @@
android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip)
if !mutated {
- dexBootJarModule := result.ModuleForTests("dex_bootjars", "android_common")
+ dexBootJarModule := result.ModuleForTests(t, "dex_bootjars", "android_common")
profileInstallInfo, _ := android.OtherModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider)
assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, profileInstallInfo.profileInstalls)
android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, profileInstallInfo.profileLicenseMetadataFile.RelativeToTop().String())
@@ -1246,6 +1247,7 @@
for i, variant := range imageConfig.variants {
expectedVariant := expected.variants[i]
t.Run(variant.target.Arch.ArchType.String(), func(t *testing.T) {
+ t.Parallel()
android.AssertDeepEquals(t, "archType", expectedVariant.archType, variant.target.Arch.ArchType)
android.AssertDeepEquals(t, "dexLocations", expectedVariant.dexLocations, variant.dexLocations)
android.AssertDeepEquals(t, "dexLocationsDeps", expectedVariant.dexLocationsDeps, variant.dexLocationsDeps)
@@ -1279,7 +1281,7 @@
// checkDexpreoptMakeVars checks the DEXPREOPT_ prefixed make vars produced by dexpreoptBootJars
// singleton.
func checkDexpreoptMakeVars(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) {
- vars := result.MakeVarsForTesting(func(variable android.MakeVarVariable) bool {
+ vars := result.MakeVarsForTesting(t, func(variable android.MakeVarVariable) bool {
return strings.HasPrefix(variable.Name(), "DEXPREOPT_")
})
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 07d0595..f437da0 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -17,7 +17,6 @@
import (
"fmt"
"runtime"
- "strings"
"testing"
"android/soong/android"
@@ -30,6 +29,7 @@
}
func TestDexpreoptEnabled(t *testing.T) {
+ t.Parallel()
tests := []struct {
name string
bp string
@@ -219,6 +219,7 @@
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
preparers := android.GroupFixturePreparers(
PrepareForTestWithDexpreopt,
PrepareForTestWithFakeApexMutator,
@@ -238,7 +239,7 @@
variant += "_apex1000"
}
- dexpreopt := ctx.ModuleForTests(moduleName, variant).MaybeRule("dexpreopt")
+ dexpreopt := ctx.ModuleForTests(t, moduleName, variant).MaybeRule("dexpreopt")
enabled := dexpreopt.Rule != nil
if enabled != test.enabled {
@@ -258,6 +259,7 @@
}
func TestDex2oatToolDeps(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
// The host binary paths checked below are build OS dependent.
t.Skipf("Unsupported build OS %s", runtime.GOOS)
@@ -273,6 +275,7 @@
name := fmt.Sprintf("sourceEnabled:%t,prebuiltEnabled:%t,prebuiltPreferred:%t",
sourceEnabled, prebuiltEnabled, prebuiltPreferred)
t.Run(name, func(t *testing.T) {
+ t.Parallel()
result := preparers.RunTestWithBp(t, fmt.Sprintf(`
cc_binary {
name: "dex2oatd",
@@ -296,7 +299,7 @@
})
}
- sourceDex2oatPath := "host/linux-x86/bin/dex2oatd"
+ sourceDex2oatPath := "../host/linux-x86/bin/dex2oatd"
prebuiltDex2oatPath := ".intermediates/prebuilt_dex2oatd/linux_glibc_x86_64/dex2oatd"
testDex2oatToolDep(true, false, false, sourceDex2oatPath)
@@ -305,7 +308,7 @@
testDex2oatToolDep(false, true, false, prebuiltDex2oatPath)
}
-func TestDexpreoptBuiltInstalledForApex(t *testing.T) {
+func TestApexSystemServerDexpreoptInstalls(t *testing.T) {
preparers := android.GroupFixturePreparers(
PrepareForTestWithDexpreopt,
PrepareForTestWithFakeApexMutator,
@@ -322,28 +325,38 @@
sdk_version: "current",
}`)
ctx := result.TestContext
- module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
+ module := ctx.ModuleForTests(t, "service-foo", "android_common_apex1000")
library := module.Module().(*Library)
- installs := library.dexpreopter.DexpreoptBuiltInstalledForApex()
+ installs := library.dexpreopter.ApexSystemServerDexpreoptInstalls()
+ dexJars := library.dexpreopter.ApexSystemServerDexJars()
android.AssertIntEquals(t, "install count", 2, len(installs))
+ android.AssertIntEquals(t, "dexjar count", 1, len(dexJars))
- android.AssertStringEquals(t, "installs[0] FullModuleName",
- "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
- installs[0].FullModuleName())
+ android.AssertPathRelativeToTopEquals(t, "installs[0] OutputPathOnHost",
+ "out/soong/.intermediates/service-foo/android_common_apex1000/dexpreopt/service-foo/oat/arm64/javalib.odex",
+ installs[0].OutputPathOnHost)
- android.AssertStringEquals(t, "installs[0] SubModuleName",
- "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
- installs[0].SubModuleName())
+ android.AssertPathRelativeToTopEquals(t, "installs[0] InstallDirOnDevice",
+ "out/target/product/test_device/system/framework/oat/arm64",
+ installs[0].InstallDirOnDevice)
- android.AssertStringEquals(t, "installs[1] FullModuleName",
- "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
- installs[1].FullModuleName())
+ android.AssertStringEquals(t, "installs[0] InstallFileOnDevice",
+ "apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
+ installs[0].InstallFileOnDevice)
- android.AssertStringEquals(t, "installs[1] SubModuleName",
- "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
- installs[1].SubModuleName())
+ android.AssertPathRelativeToTopEquals(t, "installs[1] OutputPathOnHost",
+ "out/soong/.intermediates/service-foo/android_common_apex1000/dexpreopt/service-foo/oat/arm64/javalib.vdex",
+ installs[1].OutputPathOnHost)
+
+ android.AssertPathRelativeToTopEquals(t, "installs[1] InstallDirOnDevice",
+ "out/target/product/test_device/system/framework/oat/arm64",
+ installs[1].InstallDirOnDevice)
+
+ android.AssertStringEquals(t, "installs[1] InstallFileOnDevice",
+ "apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
+ installs[1].InstallFileOnDevice)
// Not an APEX system server jar.
result = preparers.RunTestWithBp(t, `
@@ -354,101 +367,14 @@
sdk_version: "current",
}`)
ctx = result.TestContext
- module = ctx.ModuleForTests("foo", "android_common")
+ module = ctx.ModuleForTests(t, "foo", "android_common")
library = module.Module().(*Library)
- installs = library.dexpreopter.DexpreoptBuiltInstalledForApex()
+ installs = library.dexpreopter.ApexSystemServerDexpreoptInstalls()
+ dexJars = library.dexpreopter.ApexSystemServerDexJars()
android.AssertIntEquals(t, "install count", 0, len(installs))
-}
-
-func filterDexpreoptEntriesList(entriesList []android.AndroidMkEntries) []android.AndroidMkEntries {
- var results []android.AndroidMkEntries
- for _, entries := range entriesList {
- if strings.Contains(entries.EntryMap["LOCAL_MODULE"][0], "-dexpreopt-") {
- results = append(results, entries)
- }
- }
- return results
-}
-
-func verifyEntries(t *testing.T, message string, expectedModule string,
- expectedPrebuiltModuleFile string, expectedModulePath string, expectedInstalledModuleStem string,
- entries android.AndroidMkEntries) {
- android.AssertStringEquals(t, message+" LOCAL_MODULE", expectedModule,
- entries.EntryMap["LOCAL_MODULE"][0])
-
- android.AssertStringEquals(t, message+" LOCAL_MODULE_CLASS", "ETC",
- entries.EntryMap["LOCAL_MODULE_CLASS"][0])
-
- android.AssertStringDoesContain(t, message+" LOCAL_PREBUILT_MODULE_FILE",
- entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"][0], expectedPrebuiltModuleFile)
-
- android.AssertStringDoesContain(t, message+" LOCAL_MODULE_PATH",
- entries.EntryMap["LOCAL_MODULE_PATH"][0], expectedModulePath)
-
- android.AssertStringEquals(t, message+" LOCAL_INSTALLED_MODULE_STEM",
- expectedInstalledModuleStem, entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
-
- android.AssertStringEquals(t, message+" LOCAL_NOT_AVAILABLE_FOR_PLATFORM",
- "false", entries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"][0])
-}
-
-func TestAndroidMkEntriesForApex(t *testing.T) {
- preparers := android.GroupFixturePreparers(
- PrepareForTestWithDexpreopt,
- PrepareForTestWithFakeApexMutator,
- dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
- )
-
- // An APEX system server jar.
- result := preparers.RunTestWithBp(t, `
- java_library {
- name: "service-foo",
- installable: true,
- srcs: ["a.java"],
- apex_available: ["com.android.apex1"],
- sdk_version: "current",
- }`)
- ctx := result.TestContext
- module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
-
- entriesList := android.AndroidMkEntriesForTest(t, ctx, module.Module())
- entriesList = filterDexpreoptEntriesList(entriesList)
-
- android.AssertIntEquals(t, "entries count", 2, len(entriesList))
-
- verifyEntries(t,
- "entriesList[0]",
- "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
- "/dexpreopt/service-foo/oat/arm64/javalib.odex",
- "/system/framework/oat/arm64",
- "apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
- entriesList[0])
-
- verifyEntries(t,
- "entriesList[1]",
- "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
- "/dexpreopt/service-foo/oat/arm64/javalib.vdex",
- "/system/framework/oat/arm64",
- "apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
- entriesList[1])
-
- // Not an APEX system server jar.
- result = preparers.RunTestWithBp(t, `
- java_library {
- name: "foo",
- installable: true,
- srcs: ["a.java"],
- sdk_version: "current",
- }`)
- ctx = result.TestContext
- module = ctx.ModuleForTests("foo", "android_common")
-
- entriesList = android.AndroidMkEntriesForTest(t, ctx, module.Module())
- entriesList = filterDexpreoptEntriesList(entriesList)
-
- android.AssertIntEquals(t, "entries count", 0, len(entriesList))
+ android.AssertIntEquals(t, "dexjar count", 0, len(dexJars))
}
func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) {
@@ -470,7 +396,7 @@
}`)
ctx := result.TestContext
- dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
+ dexpreopt := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("dexpreopt")
expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/foo/profile.prof"}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 2dda72b..3faf294 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -19,6 +19,7 @@
"path/filepath"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -194,6 +195,9 @@
"them instead.")
}
return false
+ } else if ctx.Config().PartialCompileFlags().Disable_stub_validation &&
+ !ctx.Config().BuildFromTextStub() {
+ return false
} else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" {
return true
} else if String(apiToCheck.Api_file) != "" {
@@ -357,7 +361,7 @@
deps.aidlPreprocess = sdkDep.aidl
}
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -381,9 +385,9 @@
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
- } else if dep, ok := module.(android.SourceFileProducer); ok {
- checkProducesJars(ctx, dep)
- deps.classpath = append(deps.classpath, dep.Srcs()...)
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, android.SourceFilesInfoProvider); ok {
+ checkProducesJars(ctx, dep, module)
+ deps.classpath = append(deps.classpath, dep.Srcs...)
} else {
ctx.ModuleErrorf("depends on non-java module %q", otherName)
}
@@ -874,6 +878,13 @@
Path *string
}
+type ExportedDroiddocDirInfo struct {
+ Deps android.Paths
+ Dir android.Path
+}
+
+var ExportedDroiddocDirInfoProvider = blueprint.NewProvider[ExportedDroiddocDirInfo]()
+
type ExportedDroiddocDir struct {
android.ModuleBase
@@ -897,6 +908,11 @@
path := String(d.properties.Path)
d.dir = android.PathForModuleSrc(ctx, path)
d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")})
+
+ android.SetProvider(ctx, ExportedDroiddocDirInfoProvider, ExportedDroiddocDirInfo{
+ Dir: d.dir,
+ Deps: d.deps,
+ })
}
// Defaults
diff --git a/java/droiddoc_test.go b/java/droiddoc_test.go
index 9e1ebbe..0c977bc 100644
--- a/java/droiddoc_test.go
+++ b/java/droiddoc_test.go
@@ -23,6 +23,7 @@
)
func TestDroiddoc(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
@@ -69,13 +70,13 @@
"bar-doc/a.java": nil,
"bar-doc/b.java": nil,
})
- barStubsOutputs := ctx.ModuleForTests("bar-stubs", "android_common").OutputFiles(ctx, t, "")
+ barStubsOutputs := ctx.ModuleForTests(t, "bar-stubs", "android_common").OutputFiles(ctx, t, "")
if len(barStubsOutputs) != 1 {
t.Errorf("Expected one output from \"bar-stubs\" got %s", barStubsOutputs)
}
barStubsOutput := barStubsOutputs[0]
- barDoc := ctx.ModuleForTests("bar-doc", "android_common")
+ barDoc := ctx.ModuleForTests(t, "bar-doc", "android_common")
javaDoc := barDoc.Rule("javadoc")
if g, w := android.PathsRelativeToTop(javaDoc.Implicits), android.PathRelativeToTop(barStubsOutput); !inList(w, g) {
t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
@@ -97,6 +98,7 @@
}
func TestDroiddocArgsAndFlagsCausesError(t *testing.T) {
+ t.Parallel()
testJavaError(t, "flags is set. Cannot set args", `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
diff --git a/java/droidstubs.go b/java/droidstubs.go
index e955949..b30c844 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -20,6 +20,7 @@
"regexp"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -27,6 +28,28 @@
"android/soong/remoteexec"
)
+type StubsInfo struct {
+ ApiVersionsXml android.Path
+ AnnotationsZip android.Path
+ ApiFile android.Path
+ RemovedApiFile android.Path
+}
+
+type DroidStubsInfo struct {
+ CurrentApiTimestamp android.Path
+ EverythingStubsInfo StubsInfo
+ ExportableStubsInfo StubsInfo
+}
+
+var DroidStubsInfoProvider = blueprint.NewProvider[DroidStubsInfo]()
+
+type StubsSrcInfo struct {
+ EverythingStubsSrcJar android.Path
+ ExportableStubsSrcJar android.Path
+}
+
+var StubsSrcInfoProvider = blueprint.NewProvider[StubsSrcInfo]()
+
// The values allowed for Droidstubs' Api_levels_sdk_type
var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
@@ -498,9 +521,9 @@
}
func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
- ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
- if t, ok := m.(*ExportedDroiddocDir); ok {
- cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
+ ctx.VisitDirectDepsProxyWithTag(metalavaMergeAnnotationsDirTag, func(m android.ModuleProxy) {
+ if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
+ cmd.FlagWithArg("--merge-qualifier-annotations ", t.Dir.String()).Implicits(t.Deps)
} else {
ctx.PropertyErrorf("merge_annotations_dirs",
"module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
@@ -509,9 +532,9 @@
}
func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
- ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
- if t, ok := m.(*ExportedDroiddocDir); ok {
- cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
+ ctx.VisitDirectDepsProxyWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.ModuleProxy) {
+ if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
+ cmd.FlagWithArg("--merge-inclusion-annotations ", t.Dir.String()).Implicits(t.Deps)
} else {
ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
"module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
@@ -525,12 +548,12 @@
d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
apiVersions = apiVersionsXml
} else {
- ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
- if s, ok := m.(*Droidstubs); ok {
+ ctx.VisitDirectDepsProxyWithTag(metalavaAPILevelsModuleTag, func(m android.ModuleProxy) {
+ if s, ok := android.OtherModuleProvider(ctx, m, DroidStubsInfoProvider); ok {
if stubsType == Everything {
- apiVersions = s.everythingArtifacts.apiVersionsXml
+ apiVersions = s.EverythingStubsInfo.ApiVersionsXml
} else if stubsType == Exportable {
- apiVersions = s.exportableArtifacts.apiVersionsXml
+ apiVersions = s.ExportableStubsInfo.ApiVersionsXml
} else {
ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
}
@@ -541,7 +564,15 @@
})
}
if apiVersions != nil {
- cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
+ // We are migrating from a single API level to major.minor
+ // versions and PlatformSdkVersionFull is not yet set in all
+ // release configs. If it is not set, fall back on the single
+ // API level.
+ if fullSdkVersion := ctx.Config().PlatformSdkVersionFull(); len(fullSdkVersion) > 0 {
+ cmd.FlagWithArg("--current-version ", fullSdkVersion)
+ } else {
+ cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
+ }
cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
cmd.FlagWithInput("--apply-api-levels ", apiVersions)
}
@@ -603,18 +634,18 @@
var dirs []string
var extensions_dir string
- ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
- if t, ok := m.(*ExportedDroiddocDir); ok {
- extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
+ ctx.VisitDirectDepsProxyWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.ModuleProxy) {
+ if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
+ extRegex := regexp.MustCompile(t.Dir.String() + extensionsPattern)
// Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
// ideally this should be read from prebuiltApis.properties.Extensions_*
- for _, dep := range t.deps {
+ for _, dep := range t.Deps {
// Check to see if it matches an extension first.
depBase := dep.Base()
if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
if extensions_dir == "" {
- extensions_dir = t.dir.String() + "/extensions"
+ extensions_dir = t.Dir.String() + "/extensions"
}
cmd.Implicit(dep)
} else if depBase == filename {
@@ -622,23 +653,17 @@
cmd.Implicit(dep)
} else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
// The output api-versions.xml has been requested to include information on SDK
- // extensions. That means it also needs to include
- // so
- // The module-lib and system-server directories should use `android-plus-updatable.jar`
- // instead of `android.jar`. See AndroidPlusUpdatableJar for more information.
- cmd.Implicit(dep)
- } else if filename != "android.jar" && depBase == "android.jar" {
- // Metalava implicitly searches these patterns:
- // prebuilts/tools/common/api-versions/android-%/android.jar
- // prebuilts/sdk/%/public/android.jar
- // Add android.jar files from the api_levels_annotations_dirs directories to try
- // to satisfy these patterns. If Metalava can't find a match for an API level
- // between 1 and 28 in at least one pattern it will fail.
+ // extensions, i.e. updatable Apis. That means it also needs to include the history of
+ // those updatable APIs. Usually, they would be included in the `android.jar` file but
+ // unfortunately, the `module-lib` and `system-server` cannot as it would lead to build
+ // cycles. So, the module-lib and system-server directories contain an
+ // `android-plus-updatable.jar` that should be used instead of `android.jar`. See
+ // AndroidPlusUpdatableJar for more information.
cmd.Implicit(dep)
}
}
- dirs = append(dirs, t.dir.String())
+ dirs = append(dirs, t.Dir.String())
} else {
ctx.PropertyErrorf("api_levels_annotations_dirs",
"module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
@@ -646,11 +671,11 @@
})
// Generate the list of --android-jar-pattern options. The order matters so the first one which
- // matches will be the one that is used for a specific api level..
+ // matches will be the one that is used for a specific api level.
for _, sdkDir := range sdkDirs {
for _, dir := range dirs {
addPattern := func(jarFilename string) {
- cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:major.minor?}/%s/%s", dir, sdkDir, jarFilename))
}
if sdkDir == "module-lib" || sdkDir == "system-server" {
@@ -665,6 +690,10 @@
addPattern(filename)
}
+
+ if extensions_dir != "" {
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:extension}/%s/{module}.jar", extensions_dir, sdkDir))
+ }
}
if d.properties.Extensions_info_file != nil {
@@ -673,7 +702,6 @@
}
info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
cmd.Implicit(info_file)
- cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
}
}
@@ -700,7 +728,8 @@
}
func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
- srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams, configFiles android.Paths) *android.RuleBuilderCommand {
+ srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams,
+ configFiles android.Paths, apiSurface *string) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -746,6 +775,8 @@
addMetalavaConfigFilesToCmd(cmd, configFiles)
+ addOptionalApiSurfaceToCmd(cmd, apiSurface)
+
return cmd
}
@@ -764,6 +795,14 @@
cmd.FlagForEachInput("--config-file ", configFiles)
}
+// addOptionalApiSurfaceToCmd adds --api-surface option is apiSurface is not `nil`.
+func addOptionalApiSurfaceToCmd(cmd *android.RuleBuilderCommand, apiSurface *string) {
+ if apiSurface != nil {
+ cmd.Flag("--api-surface")
+ cmd.Flag(*apiSurface)
+ }
+}
+
// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
// property is defined, apply transformations and only revert the flagged apis that are not
@@ -790,19 +829,17 @@
}
}
- if len(aconfigFlagsPaths) == 0 {
- // This argument should not be added for "everything" stubs
- cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
- return
- }
+ // If aconfigFlagsPaths is empty then it is still important to generate the
+ // Metalava flags config file, albeit with an empty set of flags, so that all
+ // flagged APIs will be reverted.
- releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
- revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
+ releasedFlagsFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flags-%s.pb", stubsType.String()))
+ metalavaFlagsConfigFile := android.PathForModuleOut(ctx, fmt.Sprintf("flags-config-%s.xml", stubsType.String()))
ctx.Build(pctx, android.BuildParams{
Rule: gatherReleasedFlaggedApisRule,
Inputs: aconfigFlagsPaths,
- Output: releasedFlaggedApisFile,
+ Output: releasedFlagsFile,
Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
Args: map[string]string{
"flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
@@ -812,12 +849,12 @@
ctx.Build(pctx, android.BuildParams{
Rule: generateMetalavaRevertAnnotationsRule,
- Input: releasedFlaggedApisFile,
- Output: revertAnnotationsFile,
- Description: fmt.Sprintf("%s revert annotations", stubsType),
+ Input: releasedFlagsFile,
+ Output: metalavaFlagsConfigFile,
+ Description: fmt.Sprintf("%s metalava flags config", stubsType),
})
- cmd.FlagWithInput("@", revertAnnotationsFile)
+ cmd.FlagWithInput("--config-file ", metalavaFlagsConfigFile)
}
func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
@@ -838,7 +875,8 @@
configFiles := android.PathsForModuleSrc(ctx, d.properties.ConfigFiles)
- cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig, configFiles)
+ cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig,
+ configFiles, d.properties.Api_surface)
cmd.Implicits(d.Javadoc.implicits)
d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
@@ -1177,6 +1215,34 @@
rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
}
+func (d *Droidstubs) setPhonyRules(ctx android.ModuleContext) {
+ if d.apiFile != nil {
+ ctx.Phony(d.Name(), d.apiFile)
+ ctx.Phony(fmt.Sprintf("%s.txt", d.Name()), d.apiFile)
+ }
+ if d.removedApiFile != nil {
+ ctx.Phony(d.Name(), d.removedApiFile)
+ ctx.Phony(fmt.Sprintf("%s.txt", d.Name()), d.removedApiFile)
+ }
+ if d.checkCurrentApiTimestamp != nil {
+ ctx.Phony(fmt.Sprintf("%s-check-current-api", d.Name()), d.checkCurrentApiTimestamp)
+ ctx.Phony("checkapi", d.checkCurrentApiTimestamp)
+ }
+ if d.updateCurrentApiTimestamp != nil {
+ ctx.Phony(fmt.Sprintf("%s-update-current-api", d.Name()), d.updateCurrentApiTimestamp)
+ ctx.Phony("update-api", d.updateCurrentApiTimestamp)
+ }
+ if d.checkLastReleasedApiTimestamp != nil {
+ ctx.Phony(fmt.Sprintf("%s-check-last-released-api", d.Name()), d.checkLastReleasedApiTimestamp)
+ }
+ if d.apiLintTimestamp != nil {
+ ctx.Phony(fmt.Sprintf("%s-api-lint", d.Name()), d.apiLintTimestamp)
+ }
+ if d.checkNullabilityWarningsTimestamp != nil {
+ ctx.Phony(fmt.Sprintf("%s-check-nullability-warnings", d.Name()), d.checkNullabilityWarningsTimestamp)
+ }
+}
+
func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
deps := d.Javadoc.collectDeps(ctx)
@@ -1185,7 +1251,7 @@
// Add options for the other optional tasks: API-lint and check-released.
// We generate separate timestamp files for them.
- doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
+ doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().PartialCompileFlags().Disable_api_lint
doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
writeSdkValues := Bool(d.properties.Write_sdk_values)
@@ -1220,6 +1286,41 @@
stubCmdParams.stubsType = Exportable
d.exportableStubCmd(ctx, stubCmdParams)
+ if String(d.properties.Check_nullability_warnings) != "" {
+ if d.everythingArtifacts.nullabilityWarningsFile == nil {
+ ctx.PropertyErrorf("check_nullability_warnings",
+ "Cannot specify check_nullability_warnings unless validating nullability")
+ }
+
+ checkNullabilityWarningsPath := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
+
+ d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
+
+ msg := fmt.Sprintf(`\n******************************\n`+
+ `The warnings encountered during nullability annotation validation did\n`+
+ `not match the checked in file of expected warnings. The diffs are shown\n`+
+ `above. You have two options:\n`+
+ ` 1. Resolve the differences by editing the nullability annotations.\n`+
+ ` 2. Update the file of expected warnings by running:\n`+
+ ` cp %s %s\n`+
+ ` and submitting the updated file as part of your change.`,
+ d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarningsPath)
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+
+ rule.Command().
+ Text("(").
+ Text("diff").Input(checkNullabilityWarningsPath).Input(d.everythingArtifacts.nullabilityWarningsFile).
+ Text("&&").
+ Text("touch").Output(d.checkNullabilityWarningsTimestamp).
+ Text(") || (").
+ Text("echo").Flag("-e").Flag(`"` + msg + `"`).
+ Text("; exit 38").
+ Text(")")
+
+ rule.Build("nullabilityWarningsCheck", "nullability warnings check")
+ }
+
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
if len(d.Javadoc.properties.Out) > 0 {
@@ -1269,13 +1370,25 @@
`Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
`******************************\n`, ctx.ModuleName())
- rule.Command().
+ cmd := rule.Command().
Text("touch").Output(d.checkCurrentApiTimestamp).
Text(") || (").
Text("echo").Flag("-e").Flag(`"` + msg + `"`).
Text("; exit 38").
Text(")")
+ if d.apiLintTimestamp != nil {
+ cmd.Validation(d.apiLintTimestamp)
+ }
+
+ if d.checkLastReleasedApiTimestamp != nil {
+ cmd.Validation(d.checkLastReleasedApiTimestamp)
+ }
+
+ if d.checkNullabilityWarningsTimestamp != nil {
+ cmd.Validation(d.checkNullabilityWarningsTimestamp)
+ }
+
rule.Build("metalavaCurrentApiCheck", "check current API")
d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
@@ -1305,42 +1418,49 @@
rule.Build("metalavaCurrentApiUpdate", "update current API")
}
- if String(d.properties.Check_nullability_warnings) != "" {
- if d.everythingArtifacts.nullabilityWarningsFile == nil {
- ctx.PropertyErrorf("check_nullability_warnings",
- "Cannot specify check_nullability_warnings unless validating nullability")
- }
-
- checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
-
- d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
-
- msg := fmt.Sprintf(`\n******************************\n`+
- `The warnings encountered during nullability annotation validation did\n`+
- `not match the checked in file of expected warnings. The diffs are shown\n`+
- `above. You have two options:\n`+
- ` 1. Resolve the differences by editing the nullability annotations.\n`+
- ` 2. Update the file of expected warnings by running:\n`+
- ` cp %s %s\n`+
- ` and submitting the updated file as part of your change.`,
- d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
-
- rule := android.NewRuleBuilder(pctx, ctx)
-
- rule.Command().
- Text("(").
- Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
- Text("&&").
- Text("touch").Output(d.checkNullabilityWarningsTimestamp).
- Text(") || (").
- Text("echo").Flag("-e").Flag(`"` + msg + `"`).
- Text("; exit 38").
- Text(")")
-
- rule.Build("nullabilityWarningsCheck", "nullability warnings check")
+ droidInfo := DroidStubsInfo{
+ CurrentApiTimestamp: d.CurrentApiTimestamp(),
+ EverythingStubsInfo: StubsInfo{},
+ ExportableStubsInfo: StubsInfo{},
}
+ setDroidInfo(ctx, d, &droidInfo.EverythingStubsInfo, Everything)
+ setDroidInfo(ctx, d, &droidInfo.ExportableStubsInfo, Exportable)
+ android.SetProvider(ctx, DroidStubsInfoProvider, droidInfo)
+
+ android.SetProvider(ctx, StubsSrcInfoProvider, StubsSrcInfo{
+ EverythingStubsSrcJar: d.stubsSrcJar,
+ ExportableStubsSrcJar: d.exportableStubsSrcJar,
+ })
d.setOutputFiles(ctx)
+
+ d.setPhonyRules(ctx)
+
+ if d.apiLintTimestamp != nil {
+ if d.apiLintReport != nil {
+ ctx.DistForGoalsWithFilename(
+ []string{fmt.Sprintf("%s-api-lint", d.Name()), "droidcore"},
+ d.apiLintReport,
+ fmt.Sprintf("apilint/%s-lint-report.txt", d.Name()),
+ )
+ }
+ }
+}
+
+func setDroidInfo(ctx android.ModuleContext, d *Droidstubs, info *StubsInfo, typ StubsType) {
+ if typ == Everything {
+ info.ApiFile = d.apiFile
+ info.RemovedApiFile = d.removedApiFile
+ info.AnnotationsZip = d.everythingArtifacts.annotationsZip
+ info.ApiVersionsXml = d.everythingArtifacts.apiVersionsXml
+ } else if typ == Exportable {
+ info.ApiFile = d.exportableApiFile
+ info.RemovedApiFile = d.exportableRemovedApiFile
+ info.AnnotationsZip = d.exportableArtifacts.annotationsZip
+ info.ApiVersionsXml = d.exportableArtifacts.apiVersionsXml
+ } else {
+ ctx.ModuleErrorf("failed to set ApiVersionsXml, stubs type not supported: %d", typ)
+ }
}
// This method sets the outputFiles property, which is used to set the
@@ -1508,6 +1628,11 @@
p.stubsSrcJar = outPath
}
+ android.SetProvider(ctx, StubsSrcInfoProvider, StubsSrcInfo{
+ EverythingStubsSrcJar: p.stubsSrcJar,
+ ExportableStubsSrcJar: p.stubsSrcJar,
+ })
+
ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
// prebuilt droidstubs does not output "exportable" stubs.
// Output the "everything" stubs srcjar file if the tag is ".exportable".
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 1e8362c..1f9d223 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -27,6 +27,7 @@
)
func TestDroidstubs(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
@@ -82,13 +83,13 @@
},
}
for _, c := range testcases {
- m := ctx.ModuleForTests(c.moduleName, "android_common")
+ m := ctx.ModuleForTests(t, c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
cmdline := String(sboxProto.Commands[0].Command)
android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml)
if c.expectedJarFilename != "" {
- expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
+ expected := "--android-jar-pattern ./{version:major.minor?}/public/" + c.expectedJarFilename
if !strings.Contains(cmdline, expected) {
t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, cmdline)
}
@@ -131,7 +132,7 @@
"foo-doc/a.java": nil,
})
- m := ctx.ModuleForTests("foo-stubs", "android_common")
+ m := ctx.ModuleForTests(t, "foo-stubs", "android_common")
manifest := m.Output("metalava.sbox.textproto")
cmd := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
@@ -139,35 +140,38 @@
}
func TestPublicDroidstubs(t *testing.T) {
+ t.Parallel()
patterns := getAndroidJarPatternsForDroidstubs(t, "public")
android.AssertArrayString(t, "order of patterns", []string{
- "--android-jar-pattern somedir/%/public/android.jar",
- "--android-jar-pattern someotherdir/%/public/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
}, patterns)
}
func TestSystemDroidstubs(t *testing.T) {
+ t.Parallel()
patterns := getAndroidJarPatternsForDroidstubs(t, "system")
android.AssertArrayString(t, "order of patterns", []string{
- "--android-jar-pattern somedir/%/system/android.jar",
- "--android-jar-pattern someotherdir/%/system/android.jar",
- "--android-jar-pattern somedir/%/public/android.jar",
- "--android-jar-pattern someotherdir/%/public/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
}, patterns)
}
func TestModuleLibDroidstubs(t *testing.T) {
+ t.Parallel()
patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib")
android.AssertArrayString(t, "order of patterns", []string{
- "--android-jar-pattern somedir/%/module-lib/android.jar",
- "--android-jar-pattern someotherdir/%/module-lib/android.jar",
- "--android-jar-pattern somedir/%/system/android.jar",
- "--android-jar-pattern someotherdir/%/system/android.jar",
- "--android-jar-pattern somedir/%/public/android.jar",
- "--android-jar-pattern someotherdir/%/public/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/module-lib/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/module-lib/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
}, patterns)
}
@@ -175,14 +179,14 @@
patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
android.AssertArrayString(t, "order of patterns", []string{
- "--android-jar-pattern somedir/%/system-server/android.jar",
- "--android-jar-pattern someotherdir/%/system-server/android.jar",
- "--android-jar-pattern somedir/%/module-lib/android.jar",
- "--android-jar-pattern someotherdir/%/module-lib/android.jar",
- "--android-jar-pattern somedir/%/system/android.jar",
- "--android-jar-pattern someotherdir/%/system/android.jar",
- "--android-jar-pattern somedir/%/public/android.jar",
- "--android-jar-pattern someotherdir/%/public/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/system-server/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/system-server/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/module-lib/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/module-lib/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/system/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/system/android.jar",
+ "--android-jar-pattern somedir/{version:major.minor?}/public/android.jar",
+ "--android-jar-pattern someotherdir/{version:major.minor?}/public/android.jar",
}, patterns)
}
@@ -206,7 +210,7 @@
"bar-doc/a.java": nil,
})
- m := ctx.ModuleForTests("bar-stubs", "android_common")
+ m := ctx.ModuleForTests(t, "bar-stubs", "android_common")
metalava := m.Rule("metalava")
if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
t.Errorf("Expected inputs %q, got %q", w, g)
@@ -267,7 +271,7 @@
}
func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
- metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
+ metalavaRule := ctx.ModuleForTests(t, moduleName, "android_common").Rule("metalava")
var systemJars []string
for _, i := range metalavaRule.Implicits {
systemJars = append(systemJars, i.Base())
@@ -300,10 +304,10 @@
"sdk/extensions/1/public/some-mainline-module-stubs.jar": nil,
"sdk/extensions/info.txt": nil,
})
- m := ctx.ModuleForTests("baz-stubs", "android_common")
+ m := ctx.ModuleForTests(t, "baz-stubs", "android_common")
manifest := m.Output("metalava.sbox.textproto")
cmdline := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
- android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions")
+ android.AssertStringDoesContain(t, "android-jar-pattern present", cmdline, "--android-jar-pattern sdk/extensions/{version:extension}/public/{module}.jar")
android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
}
@@ -328,7 +332,7 @@
},
)
- ctx.ModuleForTests("foo.api.contribution", "")
+ ctx.ModuleForTests(t, "foo.api.contribution", "")
}
func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
@@ -362,7 +366,7 @@
},
)
- ctx.ModuleForTests("bar", "android_common")
+ ctx.ModuleForTests(t, "bar", "android_common")
}
func TestAconfigDeclarations(t *testing.T) {
@@ -404,14 +408,14 @@
android.AssertBoolEquals(t, "foo expected to depend on bar",
CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
- m := result.ModuleForTests("foo", "android_common")
+ m := result.ModuleForTests(t, "foo", "android_common")
android.AssertStringDoesContain(t, "foo generates revert annotations file",
- strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+ strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml")
// revert-annotations.txt passed to exportable stubs generation metalava command
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, "flagged api hide command not included", cmdline, "flags-config-exportable.xml")
android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
@@ -454,9 +458,9 @@
}
`)
- m := result.ModuleForTests("foo", "android_common")
+ m := result.ModuleForTests(t, "foo", "android_common")
- rule := m.Output("released-flagged-apis-exportable.txt")
+ rule := m.Output("released-flags-exportable.pb")
exposeWritableApisFilter := "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
android.AssertStringEquals(t, "Filter argument expected to contain READ_WRITE permissions", exposeWritableApisFilter, rule.Args["filter_args"])
}
diff --git a/java/fuzz.go b/java/fuzz.go
index 90f09a8..0e239f0 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -63,7 +63,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
module.Module.sourceProperties.Top_level_test_target = true
@@ -107,23 +107,7 @@
}
func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
- j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
- }
- if j.fuzzPackagedModule.FuzzProperties.Device_common_corpus != nil {
- j.fuzzPackagedModule.Corpus = append(j.fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
- }
- if j.fuzzPackagedModule.FuzzProperties.Data != nil {
- j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data)
- }
- if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
- j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
- }
- if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
- configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
- android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
- j.fuzzPackagedModule.Config = configPath
- }
+ j.fuzzPackagedModule = cc.PackageFuzzModule(ctx, j.fuzzPackagedModule)
_, sharedDeps := cc.CollectAllSharedDependencies(ctx)
for _, dep := range sharedDeps {
@@ -148,6 +132,8 @@
}
j.Test.GenerateAndroidBuildActions(ctx)
+
+ fuzz.SetFuzzPackagedModuleInfo(ctx, &j.fuzzPackagedModule)
}
type javaFuzzPackager struct {
@@ -169,6 +155,10 @@
if !ok {
return
}
+ fuzzInfo, ok := android.OtherModuleProvider(ctx, module, fuzz.FuzzPackagedModuleInfoProvider)
+ if !ok {
+ return
+ }
hostOrTargetString := "target"
if javaFuzzModule.Target().HostCross {
@@ -195,7 +185,7 @@
builder := android.NewRuleBuilder(pctx, ctx)
// Package the artifacts (data, corpus, config and dictionary) into a zipfile.
- files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
+ files = s.PackageArtifacts(ctx, module, &fuzzInfo, archDir, builder)
// Add .jar
if !javaFuzzModule.Host() {
@@ -209,7 +199,7 @@
files = append(files, fuzz.FileToZip{SourceFilePath: fPath})
}
- archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaFuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
+ archDirs[archOs], ok = s.BuildZipFile(ctx, module, &fuzzInfo, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
return
}
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index f29c913..735b8da 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -30,6 +30,7 @@
)
func TestJavaFuzz(t *testing.T) {
+ t.Parallel()
result := prepForJavaFuzzTest.RunTestWithBp(t, `
java_fuzz {
name: "foo",
@@ -63,16 +64,16 @@
osCommonTarget := result.Config.BuildOSCommonTarget.String()
- javac := result.ModuleForTests("foo", osCommonTarget).Rule("javac")
- combineJar := result.ModuleForTests("foo", osCommonTarget).Description("for javac")
+ javac := result.ModuleForTests(t, "foo", osCommonTarget).Rule("javac")
+ combineJar := result.ModuleForTests(t, "foo", osCommonTarget).Description("for javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
}
- baz := result.ModuleForTests("baz", osCommonTarget).Rule("javac").Output.String()
- barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "javac-header", "bar.jar")
- bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "javac-header", "baz.jar")
+ baz := result.ModuleForTests(t, "baz", osCommonTarget).Rule("javac").Output.String()
+ barOut := filepath.Join("out", "soong", ".intermediates", "bar", osCommonTarget, "local-javac-header", "bar.jar")
+ bazOut := filepath.Join("out", "soong", ".intermediates", "baz", osCommonTarget, "local-javac-header", "baz.jar")
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], barOut)
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], bazOut)
@@ -82,7 +83,7 @@
}
ctx := result.TestContext
- foo := ctx.ModuleForTests("foo", osCommonTarget).Module().(*JavaFuzzTest)
+ foo := ctx.ModuleForTests(t, "foo", osCommonTarget).Module().(*JavaFuzzTest)
expected := "lib64/libjni.so"
if runtime.GOOS == "darwin" {
diff --git a/java/gen.go b/java/gen.go
index 1b4f4c7..aab8418 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -26,15 +26,14 @@
)
func init() {
- pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
- pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
+ pctx.HostBinToolVariable("logtagsCmd", "java-event-log-tags")
}
var (
logtags = pctx.AndroidStaticRule("logtags",
blueprint.RuleParams{
Command: "$logtagsCmd -o $out $in",
- CommandDeps: []string{"$logtagsCmd", "$logtagsLib"},
+ CommandDeps: []string{"$logtagsCmd"},
})
)
diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go
index a5c4be1..e5ee586 100644
--- a/java/generated_java_library_test.go
+++ b/java/generated_java_library_test.go
@@ -52,6 +52,7 @@
}
func TestGenLib(t *testing.T) {
+ t.Parallel()
bp := `
test_java_gen_lib {
name: "javagenlibtest",
@@ -60,6 +61,6 @@
`
result := testGenLib(t, android.FixtureExpectsNoErrors, bp)
- javagenlibtest := result.ModuleForTests("javagenlibtest", "android_common").Module().(*GeneratedJavaLibraryModule)
+ javagenlibtest := result.ModuleForTests(t, "javagenlibtest", "android_common").Module().(*GeneratedJavaLibraryModule)
android.AssertPathsEndWith(t, "Generated_srcjars", []string{"/blah.srcjar"}, javagenlibtest.Library.properties.Generated_srcjars)
}
diff --git a/java/genrule_combiner.go b/java/genrule_combiner.go
new file mode 100644
index 0000000..357dc2c
--- /dev/null
+++ b/java/genrule_combiner.go
@@ -0,0 +1,252 @@
+// Copyright 2019 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 java
+
+import (
+ "fmt"
+ "io"
+
+ "android/soong/android"
+ "android/soong/dexpreopt"
+
+ "github.com/google/blueprint/depset"
+ "github.com/google/blueprint/proptools"
+)
+
+type GenruleCombiner struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ genruleCombinerProperties GenruleCombinerProperties
+
+ headerJars android.Paths
+ implementationJars android.Paths
+ implementationAndResourceJars android.Paths
+ resourceJars android.Paths
+ aconfigProtoFiles android.Paths
+
+ srcJarArgs []string
+ srcJarDeps android.Paths
+
+ headerDirs android.Paths
+
+ combinedHeaderJar android.Path
+ combinedImplementationJar android.Path
+}
+
+type GenruleCombinerProperties struct {
+ // List of modules whose implementation (and resources) jars will be visible to modules
+ // that depend on this module.
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
+
+ // List of modules whose header jars will be visible to modules that depend on this module.
+ Headers proptools.Configurable[[]string] `android:"arch_variant"`
+}
+
+// java_genrule_combiner provides the implementation and resource jars from `static_libs`, with
+// the header jars from `headers`.
+//
+// This is useful when a java_genrule is used to change the implementation of a java library
+// without requiring a change in the header jars.
+func GenruleCombinerFactory() android.Module {
+ module := &GenruleCombiner{}
+
+ module.AddProperties(&module.genruleCombinerProperties)
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ return module
+}
+
+var genruleCombinerHeaderDepTag = dependencyTag{name: "genrule_combiner_header"}
+
+func (j *GenruleCombiner) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, staticLibTag,
+ j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...)
+ ctx.AddVariationDependencies(nil, genruleCombinerHeaderDepTag,
+ j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...)
+}
+
+func (j *GenruleCombiner) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if len(j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)) < 1 {
+ ctx.PropertyErrorf("static_libs", "at least one dependency is required")
+ }
+
+ if len(j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)) < 1 {
+ ctx.PropertyErrorf("headers", "at least one dependency is required")
+ }
+
+ var transitiveHeaderJars []depset.DepSet[android.Path]
+ var transitiveImplementationJars []depset.DepSet[android.Path]
+ var transitiveResourceJars []depset.DepSet[android.Path]
+ var sdkVersion android.SdkSpec
+ var stubsLinkType StubsLinkType
+ moduleWithSdkDepInfo := &ModuleWithSdkDepInfo{}
+
+ // Collect the headers first, so that aconfig flag values for the libraries will override
+ // values from the headers (if they are different).
+ ctx.VisitDirectDepsWithTag(genruleCombinerHeaderDepTag, func(m android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+ j.headerJars = append(j.headerJars, dep.HeaderJars...)
+
+ j.srcJarArgs = append(j.srcJarArgs, dep.SrcJarArgs...)
+ j.srcJarDeps = append(j.srcJarDeps, dep.SrcJarDeps...)
+ j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
+ sdkVersion = dep.SdkVersion
+ stubsLinkType = dep.StubsLinkType
+ *moduleWithSdkDepInfo = *dep.ModuleWithSdkDepInfo
+
+ transitiveHeaderJars = append(transitiveHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ } else if dep, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
+ j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
+ } else {
+ ctx.PropertyErrorf("headers", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
+ }
+ })
+ ctx.VisitDirectDepsWithTag(staticLibTag, func(m android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+ j.implementationJars = append(j.implementationJars, dep.ImplementationJars...)
+ j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.ImplementationAndResourcesJars...)
+ j.resourceJars = append(j.resourceJars, dep.ResourceJars...)
+
+ transitiveImplementationJars = append(transitiveImplementationJars, dep.TransitiveStaticLibsImplementationJars)
+ transitiveResourceJars = append(transitiveResourceJars, dep.TransitiveStaticLibsResourceJars)
+ j.aconfigProtoFiles = append(j.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
+ } else if dep, ok := android.OtherModuleProvider(ctx, m, android.OutputFilesProvider); ok {
+ // This is provided by `java_genrule` modules.
+ j.implementationJars = append(j.implementationJars, dep.DefaultOutputFiles...)
+ j.implementationAndResourceJars = append(j.implementationAndResourceJars, dep.DefaultOutputFiles...)
+ stubsLinkType = Implementation
+ } else {
+ ctx.PropertyErrorf("static_libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
+ }
+ })
+
+ jarName := ctx.ModuleName() + ".jar"
+
+ if len(j.implementationAndResourceJars) > 1 {
+ outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+ TransformJarsToJar(ctx, outputFile, "combine", j.implementationAndResourceJars,
+ android.OptionalPath{}, false, nil, nil)
+ j.combinedImplementationJar = outputFile
+ } else if len(j.implementationAndResourceJars) == 1 {
+ j.combinedImplementationJar = j.implementationAndResourceJars[0]
+ }
+
+ if len(j.headerJars) > 1 {
+ outputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, outputFile, "turbine combine", j.headerJars,
+ android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"})
+ j.combinedHeaderJar = outputFile
+ j.headerDirs = append(j.headerDirs, android.PathForModuleOut(ctx, "turbine-combined"))
+ } else if len(j.headerJars) == 1 {
+ j.combinedHeaderJar = j.headerJars[0]
+ }
+
+ javaInfo := &JavaInfo{
+ HeaderJars: android.Paths{j.combinedHeaderJar},
+ LocalHeaderJars: android.Paths{j.combinedHeaderJar},
+ TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, android.Paths{j.combinedHeaderJar}, transitiveHeaderJars),
+ TransitiveStaticLibsImplementationJars: depset.New(depset.PREORDER, android.Paths{j.combinedImplementationJar}, transitiveImplementationJars),
+ TransitiveStaticLibsResourceJars: depset.New(depset.PREORDER, nil, transitiveResourceJars),
+ GeneratedSrcjars: android.Paths{j.combinedImplementationJar},
+ ImplementationAndResourcesJars: android.Paths{j.combinedImplementationJar},
+ ImplementationJars: android.Paths{j.combinedImplementationJar},
+ ModuleWithSdkDepInfo: moduleWithSdkDepInfo,
+ ResourceJars: j.resourceJars,
+ OutputFile: j.combinedImplementationJar,
+ SdkVersion: sdkVersion,
+ SrcJarArgs: j.srcJarArgs,
+ SrcJarDeps: j.srcJarDeps,
+ StubsLinkType: stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: j.aconfigProtoFiles,
+ }
+ setExtraJavaInfo(ctx, j, javaInfo)
+ ctx.SetOutputFiles(android.Paths{javaInfo.OutputFile}, "")
+ ctx.SetOutputFiles(android.Paths{javaInfo.OutputFile}, android.DefaultDistTag)
+ ctx.SetOutputFiles(javaInfo.ImplementationAndResourcesJars, ".jar")
+ ctx.SetOutputFiles(javaInfo.HeaderJars, ".hjar")
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+
+}
+
+func (j *GenruleCombiner) GeneratedSourceFiles() android.Paths {
+ return append(android.Paths{}, j.combinedImplementationJar)
+}
+
+func (j *GenruleCombiner) GeneratedHeaderDirs() android.Paths {
+ return append(android.Paths{}, j.headerDirs...)
+}
+
+func (j *GenruleCombiner) GeneratedDeps() android.Paths {
+ return append(android.Paths{}, j.combinedImplementationJar)
+}
+
+func (j *GenruleCombiner) Srcs() android.Paths {
+ return append(android.Paths{}, j.implementationAndResourceJars...)
+}
+
+func (j *GenruleCombiner) HeaderJars() android.Paths {
+ return j.headerJars
+}
+
+func (j *GenruleCombiner) ImplementationAndResourcesJars() android.Paths {
+ return j.implementationAndResourceJars
+}
+
+func (j *GenruleCombiner) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
+ return nil
+}
+
+func (j *GenruleCombiner) DexJarInstallPath() android.Path {
+ return nil
+}
+
+func (j *GenruleCombiner) AidlIncludeDirs() android.Paths {
+ return nil
+}
+
+func (j *GenruleCombiner) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return nil
+}
+
+func (j *GenruleCombiner) JacocoReportClassesFile() android.Path {
+ return nil
+}
+
+func (j *GenruleCombiner) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Class: "JAVA_LIBRARIES",
+ OutputFile: android.OptionalPathForPath(j.combinedImplementationJar),
+ // Make does not support Windows Java modules
+ Disabled: j.Os() == android.Windows,
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ Extra: []android.AndroidMkExtraFunc{
+ func(w io.Writer, outputFile android.Path) {
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", j.combinedHeaderJar.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", j.combinedImplementationJar.String())
+ },
+ },
+ }
+}
+
+// implement the following interface for IDE completion.
+var _ android.IDEInfo = (*GenruleCombiner)(nil)
+
+func (j *GenruleCombiner) IDEInfo(ctx android.BaseModuleContext, ideInfo *android.IdeInfo) {
+ ideInfo.Deps = append(ideInfo.Deps, j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...)
+ ideInfo.Libs = append(ideInfo.Libs, j.genruleCombinerProperties.Static_libs.GetOrDefault(ctx, nil)...)
+ ideInfo.Deps = append(ideInfo.Deps, j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...)
+ ideInfo.Libs = append(ideInfo.Libs, j.genruleCombinerProperties.Headers.GetOrDefault(ctx, nil)...)
+}
diff --git a/java/genrule_combiner_test.go b/java/genrule_combiner_test.go
new file mode 100644
index 0000000..7d024cf
--- /dev/null
+++ b/java/genrule_combiner_test.go
@@ -0,0 +1,237 @@
+// Copyright 2018 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 java
+
+import (
+ "reflect"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestJarGenruleCombinerSingle(t *testing.T) {
+ t.Parallel()
+ t.Helper()
+ ctx := prepareForJavaTest.RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+
+ java_genrule {
+ name: "gen",
+ tool_files: ["b.java"],
+ cmd: "$(location b.java) $(in) $(out)",
+ out: ["gen.jar"],
+ srcs: [":foo"],
+ }
+
+ java_genrule_combiner {
+ name: "jarcomb",
+ static_libs: ["gen"],
+ headers: ["foo"],
+ }
+
+ java_library {
+ name: "bar",
+ static_libs: ["jarcomb"],
+ srcs: ["c.java"],
+ }
+
+ java_library {
+ name: "baz",
+ libs: ["jarcomb"],
+ srcs: ["c.java"],
+ }
+ `).TestContext
+
+ fooMod := ctx.ModuleForTests(t, "foo", "android_common")
+ fooCombined := fooMod.Output("turbine-combined/foo.jar")
+ fooOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), fooMod.Module(), android.OutputFilesProvider)
+ fooHeaderJars := fooOutputFiles.TaggedOutputFiles[".hjar"]
+
+ genMod := ctx.ModuleForTests(t, "gen", "android_common")
+ gen := genMod.Output("gen.jar")
+
+ jarcombMod := ctx.ModuleForTests(t, "jarcomb", "android_common")
+ jarcombInfo, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), JavaInfoProvider)
+ jarcombOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), android.OutputFilesProvider)
+
+ // Confirm that jarcomb simply forwards the jarcomb implementation and the foo headers.
+ if len(jarcombOutputFiles.DefaultOutputFiles) != 1 ||
+ android.PathRelativeToTop(jarcombOutputFiles.DefaultOutputFiles[0]) != android.PathRelativeToTop(gen.Output) {
+ t.Errorf("jarcomb Implementation %v is not [%q]",
+ android.PathsRelativeToTop(jarcombOutputFiles.DefaultOutputFiles), android.PathRelativeToTop(gen.Output))
+ }
+ jarcombHeaderJars := jarcombOutputFiles.TaggedOutputFiles[".hjar"]
+ if !reflect.DeepEqual(jarcombHeaderJars, fooHeaderJars) {
+ t.Errorf("jarcomb Header jar %v is not %q",
+ jarcombHeaderJars, fooHeaderJars)
+ }
+
+ // Confirm that JavaInfoProvider agrees.
+ if len(jarcombInfo.ImplementationJars) != 1 ||
+ android.PathRelativeToTop(jarcombInfo.ImplementationJars[0]) != android.PathRelativeToTop(gen.Output) {
+ t.Errorf("jarcomb ImplementationJars %v is not [%q]",
+ android.PathsRelativeToTop(jarcombInfo.ImplementationJars), android.PathRelativeToTop(gen.Output))
+ }
+ if len(jarcombInfo.HeaderJars) != 1 ||
+ android.PathRelativeToTop(jarcombInfo.HeaderJars[0]) != android.PathRelativeToTop(fooCombined.Output) {
+ t.Errorf("jarcomb HeaderJars %v is not [%q]",
+ android.PathsRelativeToTop(jarcombInfo.HeaderJars), android.PathRelativeToTop(fooCombined.Output))
+ }
+
+ barMod := ctx.ModuleForTests(t, "bar", "android_common")
+ bar := barMod.Output("javac/bar.jar")
+ barCombined := barMod.Output("combined/bar.jar")
+
+ // Confirm that bar uses the Implementation from gen and headerJars from foo.
+ if len(barCombined.Inputs) != 2 ||
+ barCombined.Inputs[0].String() != bar.Output.String() ||
+ barCombined.Inputs[1].String() != gen.Output.String() {
+ t.Errorf("bar combined jar inputs %v is not [%q, %q]",
+ barCombined.Inputs.Strings(), bar.Output.String(), gen.Output.String())
+ }
+
+ bazMod := ctx.ModuleForTests(t, "baz", "android_common")
+ baz := bazMod.Output("javac/baz.jar")
+
+ string_in_list := func(s string, l []string) bool {
+ for _, v := range l {
+ if s == v {
+ return true
+ }
+ }
+ return false
+ }
+
+ // Confirm that baz uses the headerJars from foo.
+ bazImplicitsRel := android.PathsRelativeToTop(baz.Implicits)
+ for _, v := range android.PathsRelativeToTop(fooHeaderJars) {
+ if !string_in_list(v, bazImplicitsRel) {
+ t.Errorf("baz Implicits %v does not contain %q", bazImplicitsRel, v)
+ }
+ }
+}
+
+func TestJarGenruleCombinerMulti(t *testing.T) {
+ t.Parallel()
+ t.Helper()
+ ctx := prepareForJavaTest.RunTestWithBp(t, `
+ java_library {
+ name: "foo1",
+ srcs: ["foo1_a.java"],
+ }
+
+ java_library {
+ name: "foo2",
+ srcs: ["foo2_a.java"],
+ }
+
+ java_genrule {
+ name: "gen1",
+ tool_files: ["b.java"],
+ cmd: "$(location b.java) $(in) $(out)",
+ out: ["gen1.jar"],
+ srcs: [":foo1"],
+ }
+
+ java_genrule {
+ name: "gen2",
+ tool_files: ["b.java"],
+ cmd: "$(location b.java) $(in) $(out)",
+ out: ["gen2.jar"],
+ srcs: [":foo2"],
+ }
+
+ // Combine multiple java_genrule modules.
+ java_genrule_combiner {
+ name: "jarcomb",
+ static_libs: ["gen1", "gen2"],
+ headers: ["foo1", "foo2"],
+ }
+
+ java_library {
+ name: "bar",
+ static_libs: ["jarcomb"],
+ srcs: ["c.java"],
+ }
+
+ java_library {
+ name: "baz",
+ libs: ["jarcomb"],
+ srcs: ["c.java"],
+ }
+ `).TestContext
+
+ gen1Mod := ctx.ModuleForTests(t, "gen1", "android_common")
+ gen1 := gen1Mod.Output("gen1.jar")
+ gen2Mod := ctx.ModuleForTests(t, "gen2", "android_common")
+ gen2 := gen2Mod.Output("gen2.jar")
+
+ jarcombMod := ctx.ModuleForTests(t, "jarcomb", "android_common")
+ jarcomb := jarcombMod.Output("combined/jarcomb.jar")
+ jarcombTurbine := jarcombMod.Output("turbine-combined/jarcomb.jar")
+ _ = jarcombTurbine
+ jarcombInfo, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), JavaInfoProvider)
+ _ = jarcombInfo
+ jarcombOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), android.OutputFilesProvider)
+ jarcombHeaderJars := jarcombOutputFiles.TaggedOutputFiles[".hjar"]
+
+ if len(jarcomb.Inputs) != 2 ||
+ jarcomb.Inputs[0].String() != gen1.Output.String() ||
+ jarcomb.Inputs[1].String() != gen2.Output.String() {
+ t.Errorf("jarcomb inputs %v are not [%q, %q]",
+ jarcomb.Inputs.Strings(), gen1.Output.String(), gen2.Output.String())
+ }
+
+ if len(jarcombHeaderJars) != 1 ||
+ android.PathRelativeToTop(jarcombHeaderJars[0]) != android.PathRelativeToTop(jarcombTurbine.Output) {
+ t.Errorf("jarcomb Header jars %v is not [%q]",
+ android.PathsRelativeToTop(jarcombHeaderJars), android.PathRelativeToTop(jarcombTurbine.Output))
+ }
+
+ barMod := ctx.ModuleForTests(t, "bar", "android_common")
+ bar := barMod.Output("javac/bar.jar")
+ barCombined := barMod.Output("combined/bar.jar")
+
+ // Confirm that bar uses the Implementation and Headers from jarcomb.
+ if len(barCombined.Inputs) != 2 ||
+ barCombined.Inputs[0].String() != bar.Output.String() ||
+ barCombined.Inputs[1].String() != jarcomb.Output.String() {
+ t.Errorf("bar combined jar inputs %v is not [%q, %q]",
+ barCombined.Inputs.Strings(), bar.Output.String(), jarcomb.Output.String())
+ }
+
+ bazMod := ctx.ModuleForTests(t, "baz", "android_common")
+ baz := bazMod.Output("javac/baz.jar")
+
+ string_in_list := func(s string, l []string) bool {
+ for _, v := range l {
+ if s == v {
+ return true
+ }
+ }
+ return false
+ }
+
+ // Confirm that baz uses the headerJars from foo.
+ bazImplicitsRel := android.PathsRelativeToTop(baz.Implicits)
+ for _, v := range android.PathsRelativeToTop(jarcombHeaderJars) {
+ if !string_in_list(v, bazImplicitsRel) {
+ t.Errorf("baz Implicits %v does not contain %q", bazImplicitsRel, v)
+ }
+ }
+}
diff --git a/java/genrule_test.go b/java/genrule_test.go
index 1c294b2..c112e45 100644
--- a/java/genrule_test.go
+++ b/java/genrule_test.go
@@ -31,6 +31,7 @@
}
func TestGenruleCmd(t *testing.T) {
+ t.Parallel()
fs := map[string][]byte{
"tool": nil,
"foo": nil,
@@ -56,7 +57,7 @@
t.Fatal(errs)
}
- gen := ctx.ModuleForTests("gen", "android_common").Output("out")
+ gen := ctx.ModuleForTests(t, "gen", "android_common").Output("out")
expected := []string{"foo"}
if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
@@ -64,6 +65,7 @@
}
func TestJarGenrules(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -91,11 +93,11 @@
}
`)
- foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
- jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
- bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
- baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
- barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
+ foo := ctx.ModuleForTests(t, "foo", "android_common").Output("javac/foo.jar")
+ jargen := ctx.ModuleForTests(t, "jargen", "android_common").Output("jargen.jar")
+ bar := ctx.ModuleForTests(t, "bar", "android_common").Output("javac/bar.jar")
+ baz := ctx.ModuleForTests(t, "baz", "android_common").Output("javac/baz.jar")
+ barCombined := ctx.ModuleForTests(t, "bar", "android_common").Output("combined/bar.jar")
if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) {
t.Errorf("expected jargen inputs [%q], got %q", w, g)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index b1a9deb..c9a1f2b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -97,7 +97,7 @@
// Save the classes jars even if this is not active as they may be used by modular hidden API
// processing.
classesJars := android.Paths{classesJar}
- ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(hiddenApiAnnotationsTag, func(dep android.ModuleProxy) {
if javaInfo, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
classesJars = append(classesJars, javaInfo.ImplementationJars...)
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 7d21b7a..2c86942 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -171,11 +171,11 @@
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
if android.IsConfiguredJarForPlatform(requiredApex) {
- if len(apexInfo.InApexVariants) != 0 {
+ if apexInfo.ApexVariationName != "" {
// A platform variant is required but this is for an apex so ignore it.
return false
}
- } else if !apexInfo.InApexVariant(requiredApex) {
+ } else if apexInfo.BaseApexName != requiredApex {
// An apex variant for a specific apex is required but this is the wrong apex.
return false
}
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index afe8b4c..147f326 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -44,6 +44,7 @@
)
func TestHiddenAPISingleton(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
@@ -56,13 +57,14 @@
}
`)
- hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) {
+ t.Parallel()
expectedErrorMessage := "module prebuilt_foo{os:android,arch:common} does not provide a dex jar"
android.GroupFixturePreparers(
@@ -86,6 +88,7 @@
}
func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
@@ -98,13 +101,14 @@
}
`)
- hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
@@ -124,7 +128,7 @@
}
`)
- hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)
@@ -134,6 +138,7 @@
}
func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
FixtureConfigureBootJars("platform:foo"),
@@ -153,7 +158,7 @@
}
`)
- hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)
@@ -163,6 +168,7 @@
}
func TestHiddenAPISingletonSdks(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
unbundledBuild bool
@@ -213,7 +219,7 @@
}
`)
- hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
+ hiddenAPI := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs)
@@ -246,6 +252,7 @@
}
func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
+ t.Parallel()
// The idea behind this test is to ensure that when the build is
// confugured with a PrebuiltHiddenApiDir that the rules for the
@@ -272,9 +279,9 @@
expectedCpOutput := "out/soong/hiddenapi/hiddenapi-flags.csv"
expectedFlagsCsv := "out/soong/hiddenapi/hiddenapi-flags.csv"
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
- hiddenAPI := result.SingletonForTests("hiddenapi")
+ hiddenAPI := result.SingletonForTests(t, "hiddenapi")
cpRule := hiddenAPI.Rule("Cp")
actualCpInput := cpRule.BuildParams.Input
actualCpOutput := cpRule.BuildParams.Output
@@ -289,6 +296,7 @@
}
func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
@@ -310,7 +318,7 @@
`)
checkDexEncoded := func(t *testing.T, name, unencodedDexJar, encodedDexJar string) {
- moduleForTests := result.ModuleForTests(name+".impl", "android_common")
+ moduleForTests := result.ModuleForTests(t, name+".impl", "android_common")
encodeDexRule := moduleForTests.Rule("hiddenAPIEncodeDex")
actualUnencodedDexJar := encodeDexRule.Input
@@ -324,10 +332,7 @@
android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
}
- // The java_library embedded with the java_sdk_library must be dex encoded.
- t.Run("foo", func(t *testing.T) {
- expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar"
- expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar"
- checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar)
- })
+ expectedUnencodedDexJar := "out/soong/.intermediates/foo.impl/android_common/aligned/foo.jar"
+ expectedEncodedDexJar := "out/soong/.intermediates/foo.impl/android_common/hiddenapi/foo.jar"
+ checkDexEncoded(t, "foo", expectedUnencodedDexJar, expectedEncodedDexJar)
}
diff --git a/java/jacoco_test.go b/java/jacoco_test.go
index 1882908..58a091e 100644
--- a/java/jacoco_test.go
+++ b/java/jacoco_test.go
@@ -17,6 +17,7 @@
import "testing"
func TestJacocoFilterToSpecs(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name, in, out string
}{
@@ -54,6 +55,7 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
got, err := jacocoFilterToSpec(testCase.in)
if err != nil {
t.Error(err)
@@ -66,6 +68,7 @@
}
func TestJacocoFiltersToZipCommand(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
includes, excludes []string
@@ -96,6 +99,7 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
got := jacocoFiltersToZipCommand(testCase.includes, testCase.excludes)
if got != testCase.out {
t.Errorf("expected %q got %q", testCase.out, got)
diff --git a/java/jarjar_test.go b/java/jarjar_test.go
index 82bfa2b..b689761 100644
--- a/java/jarjar_test.go
+++ b/java/jarjar_test.go
@@ -22,7 +22,7 @@
)
func AssertJarJarRename(t *testing.T, result *android.TestResult, libName, original, expectedRename string) {
- module := result.ModuleForTests(libName, "android_common")
+ module := result.ModuleForTests(t, libName, "android_common")
provider, found := android.OtherModuleProvider(result.OtherModuleProviderAdaptor(), module.Module(), JarJarProvider)
android.AssertBoolEquals(t, fmt.Sprintf("found provider (%s)", libName), true, found)
diff --git a/java/java.go b/java/java.go
index e1cfea5..2e14b82 100644
--- a/java/java.go
+++ b/java/java.go
@@ -64,6 +64,7 @@
ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory)
+ ctx.RegisterModuleType("java_genrule_combiner", GenruleCombinerFactory)
// This mutator registers dependencies on dex2oat for modules that should be
// dexpreopted. This is done late when the final variants have been
@@ -250,6 +251,36 @@
var ProguardSpecInfoProvider = blueprint.NewProvider[ProguardSpecInfo]()
+type AndroidLibraryDependencyInfo struct {
+ ExportPackage android.Path
+ ResourcesNodeDepSet depset.DepSet[*resourcesNode]
+ RRODirsDepSet depset.DepSet[rroDir]
+ ManifestsDepSet depset.DepSet[android.Path]
+}
+
+type UsesLibraryDependencyInfo struct {
+ DexJarInstallPath android.Path
+ ClassLoaderContexts dexpreopt.ClassLoaderContextMap
+}
+
+type SdkLibraryComponentDependencyInfo struct {
+ // The name of the implementation library for the optional SDK library or nil, if there isn't one.
+ OptionalSdkLibraryImplementation *string
+}
+
+type ProvidesUsesLibInfo struct {
+ ProvidesUsesLib *string
+}
+
+type ModuleWithUsesLibraryInfo struct {
+ UsesLibrary *usesLibrary
+}
+
+type ModuleWithSdkDepInfo struct {
+ SdkLinkType sdkLinkType
+ Stubs bool
+}
+
// JavaInfo contains information about a java module for use by modules that depend on it.
type JavaInfo struct {
// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
@@ -328,10 +359,109 @@
AconfigIntermediateCacheOutputPaths android.Paths
SdkVersion android.SdkSpec
+
+ // output file of the module, which may be a classes jar or a dex jar
+ OutputFile android.Path
+
+ ExtraOutputFiles android.Paths
+
+ AndroidLibraryDependencyInfo *AndroidLibraryDependencyInfo
+
+ UsesLibraryDependencyInfo *UsesLibraryDependencyInfo
+
+ SdkLibraryComponentDependencyInfo *SdkLibraryComponentDependencyInfo
+
+ ProvidesUsesLibInfo *ProvidesUsesLibInfo
+
+ MissingOptionalUsesLibs []string
+
+ ModuleWithSdkDepInfo *ModuleWithSdkDepInfo
+
+ // output file containing classes.dex and resources
+ DexJarFile OptionalDexJarPath
+
+ // installed file for binary dependency
+ InstallFile android.Path
+
+ // The path to the dex jar that is in the boot class path. If this is unset then the associated
+ // module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional
+ // annotations for the <x> boot dex jar but which do not actually provide a boot dex jar
+ // themselves.
+ //
+ // This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on
+ // this file so using the encoded dex jar here would result in a cycle in the ninja rules.
+ BootDexJarPath OptionalDexJarPath
+
+ // The compressed state of the dex file being encoded. This is used to ensure that the encoded
+ // dex file has the same state.
+ UncompressDexState *bool
+
+ // True if the module containing this structure contributes to the hiddenapi information or has
+ // that information encoded within it.
+ Active bool
+
+ BuiltInstalled string
+
+ // The config is used for two purposes:
+ // - Passing dexpreopt information about libraries from Soong to Make. This is needed when
+ // a <uses-library> is defined in Android.bp, but used in Android.mk (see dex_preopt_config_merger.py).
+ // Note that dexpreopt.config might be needed even if dexpreopt is disabled for the library itself.
+ // - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally
+ // dexpreopt another partition).
+ ConfigPath android.WritablePath
+
+ LogtagsSrcs android.Paths
+
+ ProguardDictionary android.OptionalPath
+
+ ProguardUsageZip android.OptionalPath
+
+ LinterReports android.Paths
+
+ // installed file for hostdex copy
+ HostdexInstallFile android.InstallPath
+
+ // Additional srcJars tacked in by GeneratedJavaLibraryModule
+ GeneratedSrcjars []android.Path
+
+ // True if profile-guided optimization is actually enabled.
+ ProfileGuided bool
+
+ Stem string
+
+ DexJarBuildPath OptionalDexJarPath
+
+ DexpreopterInfo *DexpreopterInfo
+
+ XrefJavaFiles android.Paths
+ XrefKotlinFiles android.Paths
}
var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]()
+type DexpreopterInfo struct {
+ // The path to the profile on host that dexpreopter generates. This is used as the input for
+ // dex2oat.
+ OutputProfilePathOnHost android.Path
+ // If the java module is to be installed into an APEX, this list contains information about the
+ // dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed
+ // outside of the APEX.
+ ApexSystemServerDexpreoptInstalls []DexpreopterInstall
+
+ // ApexSystemServerDexJars returns the list of dex jars if this is an apex system server jar.
+ ApexSystemServerDexJars android.Paths
+}
+
+type JavaLibraryInfo struct {
+ Prebuilt bool
+}
+
+var JavaLibraryInfoProvider = blueprint.NewProvider[JavaLibraryInfo]()
+
+type JavaDexImportInfo struct{}
+
+var JavaDexImportInfoProvider = blueprint.NewProvider[JavaDexImportInfo]()
+
// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
// the sysprop implementation library.
type SyspropPublicStubInfo struct {
@@ -449,6 +579,7 @@
extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true}
jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
+ traceReferencesTag = dependencyTag{name: "trace-references"}
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
@@ -479,11 +610,12 @@
kotlinPluginTag,
syspropPublicStubDepTag,
instrumentationForTag,
+ traceReferencesTag,
}
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
- return depTag == libTag || depTag == sdkLibTag
+ return depTag == libTag
}
func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -540,12 +672,12 @@
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
- if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
+ if d.effectiveOptimizeEnabled(ctx) && sdkDep.hasStandardLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag,
config.LegacyCorePlatformBootclasspathLibraries...,
)
}
- if d.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
+ if d.effectiveOptimizeEnabled(ctx) && sdkDep.hasFrameworkLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...)
}
}
@@ -599,11 +731,11 @@
transitiveStaticLibsResourceJars []depset.DepSet[android.Path]
}
-func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
- for _, f := range dep.Srcs() {
+func checkProducesJars(ctx android.ModuleContext, dep android.SourceFilesInfo, module android.ModuleProxy) {
+ for _, f := range dep.Srcs {
if f.Ext() != ".jar" {
ctx.ModuleErrorf("genrule %q must generate files ending with .jar to be used as a libs or static_libs dependency",
- ctx.OtherModuleName(dep.(blueprint.Module)))
+ ctx.OtherModuleName(module))
}
}
}
@@ -721,6 +853,8 @@
combinedExportedProguardFlagsFile android.Path
InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.InstallPaths)
+
+ apiXmlFile android.WritablePath
}
var _ android.ApexModule = (*Library)(nil)
@@ -1008,7 +1142,7 @@
j.dexpreopter.disableDexpreopt()
}
}
- j.compile(ctx, nil, nil, nil, nil)
+ javaInfo := j.compile(ctx, nil, nil, nil, nil)
j.setInstallRules(ctx)
@@ -1017,7 +1151,97 @@
TopLevelTarget: j.sourceProperties.Top_level_test_target,
})
+ android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{
+ Prebuilt: false,
+ })
+
+ if javaInfo != nil {
+ setExtraJavaInfo(ctx, j, javaInfo)
+ javaInfo.ExtraOutputFiles = j.extraOutputFiles
+ javaInfo.DexJarFile = j.dexJarFile
+ javaInfo.InstallFile = j.installFile
+ javaInfo.BootDexJarPath = j.bootDexJarPath
+ javaInfo.UncompressDexState = j.uncompressDexState
+ javaInfo.Active = j.active
+ javaInfo.BuiltInstalled = j.builtInstalled
+ javaInfo.ConfigPath = j.configPath
+ javaInfo.LogtagsSrcs = j.logtagsSrcs
+ javaInfo.ProguardDictionary = j.proguardDictionary
+ javaInfo.ProguardUsageZip = j.proguardUsageZip
+ javaInfo.LinterReports = j.reports
+ javaInfo.HostdexInstallFile = j.hostdexInstallFile
+ javaInfo.GeneratedSrcjars = j.properties.Generated_srcjars
+ javaInfo.ProfileGuided = j.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided
+
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+ }
+
setOutputFiles(ctx, j.Module)
+
+ j.javaLibraryModuleInfoJSON(ctx)
+
+ buildComplianceMetadata(ctx)
+
+ j.createApiXmlFile(ctx)
+
+ if j.dexer.proguardDictionary.Valid() {
+ android.SetProvider(ctx, ProguardProvider, ProguardInfo{
+ ModuleName: ctx.ModuleName(),
+ Class: "JAVA_LIBRARIES",
+ ProguardDictionary: j.dexer.proguardDictionary.Path(),
+ ProguardUsageZip: j.dexer.proguardUsageZip.Path(),
+ ClassesJar: j.implementationAndResourcesJar,
+ })
+ }
+}
+
+func (j *Library) javaLibraryModuleInfoJSON(ctx android.ModuleContext) *android.ModuleInfoJSON {
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if j.implementationAndResourcesJar != nil {
+ moduleInfoJSON.ClassesJar = []string{j.implementationAndResourcesJar.String()}
+ }
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+
+ if j.hostDexNeeded() {
+ hostDexModuleInfoJSON := ctx.ExtraModuleInfoJSON()
+ hostDexModuleInfoJSON.SubName = "-hostdex"
+ hostDexModuleInfoJSON.Class = []string{"JAVA_LIBRARIES"}
+ if j.implementationAndResourcesJar != nil {
+ hostDexModuleInfoJSON.ClassesJar = []string{j.implementationAndResourcesJar.String()}
+ }
+ hostDexModuleInfoJSON.SystemSharedLibs = []string{"none"}
+ hostDexModuleInfoJSON.SupportedVariantsOverride = []string{"HOST"}
+ }
+
+ if j.hideApexVariantFromMake {
+ moduleInfoJSON.Disabled = true
+ }
+ return moduleInfoJSON
+}
+
+func buildComplianceMetadata(ctx android.ModuleContext) {
+ // Dump metadata that can not be done in android/compliance-metadata.go
+ complianceMetadataInfo := ctx.ComplianceMetadataInfo()
+ builtFiles := ctx.GetOutputFiles().DefaultOutputFiles.Strings()
+ for _, paths := range ctx.GetOutputFiles().TaggedOutputFiles {
+ builtFiles = append(builtFiles, paths.Strings()...)
+ }
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.BUILT_FILES, android.SortedUniqueStrings(builtFiles))
+
+ // Static deps
+ staticDepNames := make([]string, 0)
+ staticDepFiles := android.Paths{}
+ ctx.VisitDirectDepsWithTag(staticLibTag, func(module android.Module) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ staticDepNames = append(staticDepNames, module.Name())
+ staticDepFiles = append(staticDepFiles, dep.ImplementationJars...)
+ staticDepFiles = append(staticDepFiles, dep.HeaderJars...)
+ staticDepFiles = append(staticDepFiles, dep.ResourceJars...)
+ }
+ })
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.SortedUniqueStrings(staticDepNames))
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.SortedUniqueStrings(staticDepFiles.Strings()))
}
func (j *Library) getJarInstallDir(ctx android.ModuleContext) android.InstallPath {
@@ -1073,6 +1297,28 @@
}
}
+var apiXMLGeneratingApiSurfaces = []android.SdkKind{
+ android.SdkPublic,
+ android.SdkSystem,
+ android.SdkModule,
+ android.SdkSystemServer,
+ android.SdkTest,
+}
+
+func (j *Library) createApiXmlFile(ctx android.ModuleContext) {
+ if kind, ok := android.JavaLibraryNameToSdkKind(ctx.ModuleName()); ok && android.InList(kind, apiXMLGeneratingApiSurfaces) {
+ scopePrefix := AllApiScopes.matchingScopeFromSdkKind(kind).apiFilePrefix
+ j.apiXmlFile = android.PathForModuleOut(ctx, fmt.Sprintf("%sapi.xml", scopePrefix))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: generateApiXMLRule,
+ // LOCAL_SOONG_CLASSES_JAR
+ Input: j.implementationAndResourcesJar,
+ Output: j.apiXmlFile,
+ })
+ ctx.DistForGoal("dist_files", j.apiXmlFile)
+ }
+}
+
const (
aidlIncludeDir = "aidl"
javaDir = "java"
@@ -1314,6 +1560,11 @@
// host test.
Device_first_prefer32_data []string `android:"path_device_first_prefer32"`
+ // Same as data, but will add dependencies on modules using the host's os variation and
+ // the common arch variation. Useful for a device test that wants to depend on a host
+ // module, for example to include a custom Tradefed test runner.
+ Host_common_data []string `android:"path_host_common"`
+
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
@@ -1576,6 +1827,11 @@
MkInclude: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
MkAppClass: "JAVA_LIBRARIES",
})
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ if proptools.Bool(j.testProperties.Test_options.Unit_test) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1607,20 +1863,21 @@
j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_common_data)...)
j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_data)...)
j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_prefer32_data)...)
+ j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Host_common_data)...)
j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs)
- ctx.VisitDirectDepsWithTag(dataNativeBinsTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataNativeBinsTag, func(dep android.ModuleProxy) {
j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
})
- ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataDeviceBinsTag, func(dep android.ModuleProxy) {
j.data = append(j.data, android.OutputFileForModule(ctx, dep, ""))
})
var directImplementationDeps android.Paths
var transitiveImplementationDeps []depset.DepSet[android.Path]
- ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(jniLibTag, func(dep android.ModuleProxy) {
sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
if sharedLibInfo.SharedLibrary != nil {
// Copy to an intermediate output directory to append "lib[64]" to the path,
@@ -1653,10 +1910,82 @@
})
j.Library.GenerateAndroidBuildActions(ctx)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ // LOCAL_MODULE_TAGS
+ moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
+ var allTestConfigs android.Paths
+ if j.testConfig != nil {
+ allTestConfigs = append(allTestConfigs, j.testConfig)
+ }
+ allTestConfigs = append(allTestConfigs, j.extraTestConfigs...)
+ if len(allTestConfigs) > 0 {
+ moduleInfoJSON.TestConfig = allTestConfigs.Strings()
+ } else {
+ optionalConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml")
+ if optionalConfig.Valid() {
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String())
+ }
+ }
+ if len(j.testProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, j.testProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+ if _, ok := j.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ if proptools.Bool(j.testProperties.Test_options.Unit_test) {
+ moduleInfoJSON.IsUnitTest = "true"
+ if ctx.Host() {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
+ }
+ moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, j.testProperties.Test_mainline_modules...)
+
+ // Install test deps
+ if !ctx.Config().KatiEnabled() {
+ pathInTestCases := android.PathForModuleInstall(ctx, "testcases", ctx.ModuleName())
+ if j.testConfig != nil {
+ ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".config", j.testConfig)
+ }
+ dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+ }
+ testDeps := append(j.data, j.extraTestConfigs...)
+ for _, data := range android.SortedUniquePaths(testDeps) {
+ dataPath := android.DataPath{SrcPath: data}
+ ctx.InstallTestData(pathInTestCases, []android.DataPath{dataPath})
+ }
+ if j.outputFile != nil {
+ ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".jar", j.outputFile)
+ }
+ }
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: j.testProperties.Test_suites,
+ })
}
func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.Library.GenerateAndroidBuildActions(ctx)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
+ if len(j.testHelperLibraryProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, j.testHelperLibraryProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+ optionalConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "AndroidTest.xml")
+ if optionalConfig.Valid() {
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, optionalConfig.String())
+ }
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: j.testHelperLibraryProperties.Test_suites,
+ })
}
func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1746,7 +2075,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
module.Module.sourceProperties.Top_level_test_target = true
@@ -1763,7 +2092,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
InitJavaModule(module, android.HostAndDeviceSupported)
@@ -1910,13 +2239,13 @@
// Set the jniLibs of this binary.
// These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will
// install these alongside the java binary.
- ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(jniInstallTag, func(jni android.ModuleProxy) {
// Use the BaseModuleName of the dependency (without any prebuilt_ prefix)
- bmn, _ := jni.(interface{ BaseModuleName() string })
- j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness())
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, jni, android.CommonModuleInfoProvider)
+ j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, commonInfo.BaseModuleName+":"+commonInfo.Target.Arch.ArchType.Bitness())
})
// Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead.
- ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(android.RequiredDepTag, func(dep android.ModuleProxy) {
if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo {
ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name())
}
@@ -2135,7 +2464,7 @@
func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
srcs android.Paths, homeDir android.WritablePath,
- classpath android.Paths, configFiles android.Paths) *android.RuleBuilderCommand {
+ classpath android.Paths, configFiles android.Paths, apiSurface *string) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -2176,6 +2505,8 @@
addMetalavaConfigFilesToCmd(cmd, configFiles)
+ addOptionalApiSurfaceToCmd(cmd, apiSurface)
+
if len(classpath) == 0 {
// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
// classes on the classpath when an API file contains missing classes. However, as this command
@@ -2215,6 +2546,7 @@
apiContributions := al.properties.Api_contributions
addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
!ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
+ !ctx.Config().PartialCompileFlags().Disable_stub_validation &&
proptools.BoolDefault(al.properties.Enable_validation, true)
for _, apiContributionName := range apiContributions {
ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
@@ -2259,6 +2591,17 @@
var scopeOrderMap = AllApiScopes.MapToIndex(
func(s *apiScope) string { return s.name })
+// Add some extra entries into scopeOrderMap for some special api surface names needed by libcore,
+// external/conscrypt and external/icu and java/core-libraries.
+func init() {
+ count := len(scopeOrderMap)
+ scopeOrderMap["core"] = count + 1
+ scopeOrderMap["core-platform"] = count + 2
+ scopeOrderMap["intra-core"] = count + 3
+ scopeOrderMap["core-platform-plus-public"] = count + 4
+ scopeOrderMap["core-platform-legacy"] = count + 5
+}
+
func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
for _, srcFileInfo := range srcFilesInfo {
if srcFileInfo.ApiSurface == "" {
@@ -2307,7 +2650,7 @@
var bootclassPaths android.Paths
var staticLibs android.Paths
var systemModulesPaths android.Paths
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
case javaApiContributionTag:
@@ -2336,8 +2679,8 @@
systemModulesPaths = append(systemModulesPaths, sm.HeaderJars...)
}
case metalavaCurrentApiTimestampTag:
- if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok {
- al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp())
+ if currentApiTimestampProvider, ok := android.OtherModuleProvider(ctx, dep, DroidStubsInfoProvider); ok {
+ al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp)
}
case aconfigDeclarationTag:
if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
@@ -2369,7 +2712,7 @@
combinedPaths := append(([]android.Path)(nil), systemModulesPaths...)
combinedPaths = append(combinedPaths, classPaths...)
combinedPaths = append(combinedPaths, bootclassPaths...)
- cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, combinedPaths, configFiles)
+ cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, combinedPaths, configFiles, al.properties.Api_surface)
al.stubsFlags(ctx, cmd, stubsDir)
@@ -2433,7 +2776,7 @@
ctx.Phony(ctx.ModuleName(), al.stubsJar)
- android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ javaInfo := &JavaInfo{
HeaderJars: android.PathsIfNonNil(al.stubsJar),
LocalHeaderJars: android.PathsIfNonNil(al.stubsJar),
TransitiveStaticLibsHeaderJars: depset.New(depset.PREORDER, android.PathsIfNonNil(al.stubsJar), nil),
@@ -2443,7 +2786,9 @@
AidlIncludeDirs: android.Paths{},
StubsLinkType: Stubs,
// No aconfig libraries on api libraries
- })
+ }
+ setExtraJavaInfo(ctx, al, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
}
func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
@@ -2711,7 +3056,7 @@
var staticJars android.Paths
var staticResourceJars android.Paths
var staticHeaderJars android.Paths
- ctx.VisitDirectDeps(func(module android.Module) {
+ ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(module)
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
switch tag {
@@ -2763,12 +3108,7 @@
// file of the module to be named jarName.
var outputFile android.Path
combinedImplementationJar := android.PathForModuleOut(ctx, "combined", jarName)
- var implementationJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- implementationJars = completeStaticLibsImplementationJars.ToList()
- } else {
- implementationJars = append(slices.Clone(localJars), staticJars...)
- }
+ implementationJars := completeStaticLibsImplementationJars.ToList()
TransformJarsToJar(ctx, combinedImplementationJar, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
false, j.properties.Exclude_files, j.properties.Exclude_dirs)
outputFile = combinedImplementationJar
@@ -2791,12 +3131,7 @@
if reuseImplementationJarAsHeaderJar {
headerJar = outputFile
} else {
- var headerJars android.Paths
- if ctx.Config().UseTransitiveJarsInClasspath() {
- headerJars = completeStaticLibsHeaderJars.ToList()
- } else {
- headerJars = append(slices.Clone(localJars), staticHeaderJars...)
- }
+ headerJars := completeStaticLibsHeaderJars.ToList()
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)
@@ -2833,6 +3168,23 @@
outputFile = combinedJar
}
+ proguardFlags := android.PathForModuleOut(ctx, "proguard_flags")
+ TransformJarToR8Rules(ctx, proguardFlags, outputFile)
+
+ transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
+ android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{
+ ProguardFlagsFiles: depset.New[android.Path](
+ depset.POSTORDER,
+ android.Paths{proguardFlags},
+ transitiveProguardFlags,
+ ),
+ UnconditionallyExportedProguardFlags: depset.New[android.Path](
+ depset.POSTORDER,
+ nil,
+ transitiveUnconditionalExportedFlags,
+ ),
+ })
+
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource.
// Also strip the relative path from the header output file so that the reuseImplementationJarAsHeaderJar check
// in a module that depends on this module considers them equal.
@@ -2843,11 +3195,7 @@
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
- if ctx.Config().UseTransitiveJarsInClasspath() {
- ctx.CheckbuildFile(localJars...)
- } else {
- ctx.CheckbuildFile(outputFile)
- }
+ ctx.CheckbuildFile(localJars...)
if ctx.Device() {
// Shared libraries deapexed from prebuilt apexes are no longer supported.
@@ -2901,7 +3249,7 @@
}
}
- android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ javaInfo := &JavaInfo{
HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
LocalHeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
TransitiveLibsHeaderJarsForR8: j.transitiveLibsHeaderJarsForR8,
@@ -2915,10 +3263,18 @@
AidlIncludeDirs: j.exportAidlIncludeDirs,
StubsLinkType: j.stubsLinkType,
// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
+ }
+ setExtraJavaInfo(ctx, j, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+
+ android.SetProvider(ctx, JavaLibraryInfoProvider, JavaLibraryInfo{
+ Prebuilt: true,
})
ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, "")
ctx.SetOutputFiles(android.Paths{j.combinedImplementationFile}, ".jar")
+
+ buildComplianceMetadata(ctx)
}
func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) {
@@ -2965,26 +3321,29 @@
var _ android.ApexModule = (*Import)(nil)
// Implements android.ApexModule
-func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return j.depIsInSameApex(ctx, dep)
+func (m *Import) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return JavaImportDepInSameApexChecker{}
+}
+
+type JavaImportDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m JavaImportDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return depIsInSameApex(tag)
}
// Implements android.ApexModule
-func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
+func (j *Import) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
sdkVersionSpec := j.SdkVersion(ctx)
minSdkVersion := j.MinSdkVersion(ctx)
- if !minSdkVersion.Specified() {
- return fmt.Errorf("min_sdk_version is not specified")
- }
+
// If the module is compiling against core (via sdk_version), skip comparison check.
if sdkVersionSpec.Kind == android.SdkCore {
- return nil
+ return android.MinApiLevel
}
- if minSdkVersion.GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", minSdkVersion)
- }
- return nil
+
+ return minSdkVersion
}
// requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or
@@ -3021,19 +3380,10 @@
// Add compile time check for interface implementation
var _ android.IDEInfo = (*Import)(nil)
-var _ android.IDECustomizedModuleName = (*Import)(nil)
// Collect information for opening IDE project files in java/jdeps.go.
-
func (j *Import) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
- dpInfo.Jars = append(dpInfo.Jars, j.combinedHeaderFile.String())
-}
-
-func (j *Import) IDECustomizedModuleName() string {
- // TODO(b/113562217): Extract the base module name from the Import name, often the Import name
- // has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better
- // solution to get the Import name.
- return android.RemoveOptionalPrebuiltPrefix(j.Name())
+ dpInfo.Jars = append(dpInfo.Jars, j.combinedImplementationFile.String())
}
var _ android.PrebuiltInterface = (*Import)(nil)
@@ -3191,6 +3541,12 @@
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", dexOutputFile)
}
+
+ javaInfo := &JavaInfo{}
+ setExtraJavaInfo(ctx, j, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+
+ android.SetProvider(ctx, JavaDexImportInfoProvider, JavaDexImportInfo{})
}
func (j *DexImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
@@ -3200,10 +3556,8 @@
var _ android.ApexModule = (*DexImport)(nil)
// Implements android.ApexModule
-func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // we don't check prebuilt modules for sdk_version
- return nil
+func (m *DexImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
// dex_import imports a `.jar` file containing classes.dex files.
@@ -3225,7 +3579,6 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
- android.ApexModuleBase
}
// java_defaults provides a set of properties that can be inherited by other java or android modules.
@@ -3289,6 +3642,8 @@
&bootclasspathFragmentProperties{},
&SourceOnlyBootclasspathProperties{},
&ravenwoodTestProperties{},
+ &AndroidAppImportProperties{},
+ &UsesLibraryProperties{},
)
android.InitDefaultsModule(module)
@@ -3305,10 +3660,10 @@
func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var xrefTargets android.Paths
var xrefKotlinTargets android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if javaModule, ok := module.(xref); ok {
- xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...)
- xrefKotlinTargets = append(xrefKotlinTargets, javaModule.XrefKotlinFiles()...)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if javaInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ xrefTargets = append(xrefTargets, javaInfo.XrefJavaFiles...)
+ xrefKotlinTargets = append(xrefKotlinTargets, javaInfo.XrefKotlinFiles...)
}
})
// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
@@ -3326,11 +3681,11 @@
var inList = android.InList[string]
// Add class loader context (CLC) of a given dependency to the current CLC.
-func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
+func addCLCFromDep(ctx android.ModuleContext, depModule android.ModuleProxy,
clcMap dexpreopt.ClassLoaderContextMap) {
- dep, ok := depModule.(UsesLibraryDependency)
- if !ok {
+ dep, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider)
+ if !ok || dep.UsesLibraryDependencyInfo == nil {
return
}
@@ -3340,14 +3695,14 @@
if lib, ok := android.OtherModuleProvider(ctx, depModule, SdkLibraryInfoProvider); ok && lib.SharedLibrary {
// A shared SDK library. This should be added as a top-level CLC element.
sdkLib = &depName
- } else if lib, ok := depModule.(SdkLibraryComponentDependency); ok && lib.OptionalSdkLibraryImplementation() != nil {
- if depModule.Name() == proptools.String(lib.OptionalSdkLibraryImplementation())+".impl" {
- sdkLib = lib.OptionalSdkLibraryImplementation()
+ } else if lib := dep.SdkLibraryComponentDependencyInfo; lib != nil && lib.OptionalSdkLibraryImplementation != nil {
+ if depModule.Name() == proptools.String(lib.OptionalSdkLibraryImplementation)+".impl" {
+ sdkLib = lib.OptionalSdkLibraryImplementation
}
- } else if ulib, ok := depModule.(ProvidesUsesLib); ok {
+ } else if ulib := dep.ProvidesUsesLibInfo; ulib != nil {
// A non-SDK library disguised as an SDK library by the means of `provides_uses_lib`
// property. This should be handled in the same way as a shared SDK library.
- sdkLib = ulib.ProvidesUsesLib()
+ sdkLib = ulib.ProvidesUsesLib
}
depTag := ctx.OtherModuleDependencyTag(depModule)
@@ -3379,21 +3734,22 @@
}
}
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, optional,
- dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
+ dep.DexJarBuildPath.PathOrNil(),
+ dep.UsesLibraryDependencyInfo.DexJarInstallPath, dep.UsesLibraryDependencyInfo.ClassLoaderContexts)
} else {
- clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
+ clcMap.AddContextMap(dep.UsesLibraryDependencyInfo.ClassLoaderContexts, depName)
}
}
-func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.Module,
+func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.ModuleProxy,
usesLibrary *usesLibrary) {
- dep, ok := depModule.(ModuleWithUsesLibrary)
+ dep, ok := android.OtherModuleProvider(ctx, depModule, JavaInfoProvider)
if !ok {
return
}
- for _, lib := range dep.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs {
+ for _, lib := range dep.MissingOptionalUsesLibs {
if !android.InList(lib, usesLibrary.usesLibraryProperties.Missing_optional_uses_libs) {
usesLibrary.usesLibraryProperties.Missing_optional_uses_libs =
append(usesLibrary.usesLibraryProperties.Missing_optional_uses_libs, lib)
@@ -3449,3 +3805,68 @@
func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
}
+
+func setExtraJavaInfo(ctx android.ModuleContext, module android.Module, javaInfo *JavaInfo) {
+ if alDep, ok := module.(AndroidLibraryDependency); ok {
+ javaInfo.AndroidLibraryDependencyInfo = &AndroidLibraryDependencyInfo{
+ ExportPackage: alDep.ExportPackage(),
+ ResourcesNodeDepSet: alDep.ResourcesNodeDepSet(),
+ RRODirsDepSet: alDep.RRODirsDepSet(),
+ ManifestsDepSet: alDep.ManifestsDepSet(),
+ }
+ }
+
+ if ulDep, ok := module.(UsesLibraryDependency); ok {
+ javaInfo.UsesLibraryDependencyInfo = &UsesLibraryDependencyInfo{
+ DexJarInstallPath: ulDep.DexJarInstallPath(),
+ ClassLoaderContexts: ulDep.ClassLoaderContexts(),
+ }
+ }
+
+ if slcDep, ok := module.(SdkLibraryComponentDependency); ok {
+ javaInfo.SdkLibraryComponentDependencyInfo = &SdkLibraryComponentDependencyInfo{
+ OptionalSdkLibraryImplementation: slcDep.OptionalSdkLibraryImplementation(),
+ }
+ }
+
+ if pul, ok := module.(ProvidesUsesLib); ok {
+ javaInfo.ProvidesUsesLibInfo = &ProvidesUsesLibInfo{
+ ProvidesUsesLib: pul.ProvidesUsesLib(),
+ }
+ }
+
+ if mwul, ok := module.(ModuleWithUsesLibrary); ok {
+ javaInfo.MissingOptionalUsesLibs = mwul.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs
+ }
+
+ if mwsd, ok := module.(moduleWithSdkDep); ok {
+ linkType, stubs := mwsd.getSdkLinkType(ctx, ctx.ModuleName())
+ javaInfo.ModuleWithSdkDepInfo = &ModuleWithSdkDepInfo{
+ SdkLinkType: linkType,
+ Stubs: stubs,
+ }
+ }
+
+ if st, ok := module.(ModuleWithStem); ok {
+ javaInfo.Stem = st.Stem()
+ }
+
+ if mm, ok := module.(interface {
+ DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
+ }); ok {
+ javaInfo.DexJarBuildPath = mm.DexJarBuildPath(ctx)
+ }
+
+ if di, ok := module.(DexpreopterInterface); ok {
+ javaInfo.DexpreopterInfo = &DexpreopterInfo{
+ OutputProfilePathOnHost: di.OutputProfilePathOnHost(),
+ ApexSystemServerDexpreoptInstalls: di.ApexSystemServerDexpreoptInstalls(),
+ ApexSystemServerDexJars: di.ApexSystemServerDexJars(),
+ }
+ }
+
+ if xr, ok := module.(xref); ok {
+ javaInfo.XrefJavaFiles = xr.XrefJavaFiles()
+ javaInfo.XrefKotlinFiles = xr.XrefKotlinFiles()
+ }
+}
diff --git a/java/java_test.go b/java/java_test.go
index d415679..1ba78d4 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -110,13 +110,14 @@
case strings.HasSuffix(name, ".jar"):
return name
default:
- return filepath.Join("out", "soong", ".intermediates", defaultJavaDir, name, "android_common", "turbine-combined", name+".jar")
+ return filepath.Join("out", "soong", ".intermediates", defaultJavaDir, name, "android_common", "turbine", name+".jar")
}
}
// Test that the PrepareForTestWithJavaDefaultModules provides all the files that it uses by
// running it in a fixture that requires all source files to exist.
func TestPrepareForTestWithJavaDefaultModules(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestDisallowNonExistentPaths,
@@ -124,6 +125,7 @@
}
func TestJavaLinkType(t *testing.T) {
+ t.Parallel()
testJava(t, `
java_library {
name: "foo",
@@ -212,6 +214,7 @@
}
func TestSimple(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "foo",
@@ -237,11 +240,6 @@
srcs: ["d.java"],
}`
- frameworkTurbineCombinedJars := []string{
- "out/soong/.intermediates/default/java/ext/android_common/turbine-combined/ext.jar",
- "out/soong/.intermediates/default/java/framework/android_common/turbine-combined/framework.jar",
- }
-
frameworkTurbineJars := []string{
"out/soong/.intermediates/default/java/ext/android_common/turbine/ext.jar",
"out/soong/.intermediates/default/java/framework/android_common/turbine/framework.jar",
@@ -267,43 +265,6 @@
preparer: android.NullFixturePreparer,
fooJavacInputs: []string{"a.java"},
fooJavacClasspath: slices.Concat(
- frameworkTurbineCombinedJars,
- []string{
- "out/soong/.intermediates/bar/android_common/turbine-combined/bar.jar",
- "out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar",
- },
- ),
- fooCombinedInputs: []string{
- "out/soong/.intermediates/foo/android_common/javac/foo.jar",
- "out/soong/.intermediates/baz/android_common/combined/baz.jar",
- },
-
- fooHeaderCombinedInputs: []string{
- "out/soong/.intermediates/foo/android_common/turbine/foo.jar",
- "out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar",
- },
-
- barJavacInputs: []string{"b.java"},
- barJavacClasspath: slices.Concat(
- frameworkTurbineCombinedJars,
- []string{
- "out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar",
- },
- ),
- barCombinedInputs: []string{
- "out/soong/.intermediates/bar/android_common/javac/bar.jar",
- "out/soong/.intermediates/quz/android_common/javac/quz.jar",
- },
- barHeaderCombinedInputs: []string{
- "out/soong/.intermediates/bar/android_common/turbine/bar.jar",
- "out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar",
- },
- },
- {
- name: "transitive classpath",
- preparer: PrepareForTestWithTransitiveClasspathEnabled,
- fooJavacInputs: []string{"a.java"},
- fooJavacClasspath: slices.Concat(
frameworkTurbineJars,
[]string{
"out/soong/.intermediates/bar/android_common/turbine/bar.jar",
@@ -341,11 +302,12 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
tt.preparer,
).RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
fooJavac := foo.Rule("javac")
android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs)
@@ -360,7 +322,7 @@
fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar")
android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs)
- bar := result.ModuleForTests("bar", "android_common")
+ bar := result.ModuleForTests(t, "bar", "android_common")
barJavac := bar.Rule("javac")
android.AssertPathsRelativeToTopEquals(t, "bar javac inputs", tt.barJavacInputs, barJavac.Inputs)
@@ -378,6 +340,7 @@
}
func TestExportedPlugins(t *testing.T) {
+ t.Parallel()
type Result struct {
library string
processors string
@@ -456,6 +419,7 @@
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_plugin {
name: "plugin",
@@ -469,11 +433,11 @@
`+test.extra)
for _, want := range test.results {
- javac := ctx.ModuleForTests(want.library, "android_common").Rule("javac")
+ javac := ctx.ModuleForTests(t, want.library, "android_common").Rule("javac")
if javac.Args["processor"] != want.processors {
t.Errorf("For library %v, expected %v, found %v", want.library, want.processors, javac.Args["processor"])
}
- turbine := ctx.ModuleForTests(want.library, "android_common").MaybeRule("turbine")
+ turbine := ctx.ModuleForTests(t, want.library, "android_common").MaybeRule("turbine")
disableTurbine := turbine.BuildParams.Rule == nil
if disableTurbine != want.disableTurbine {
t.Errorf("For library %v, expected disableTurbine %v, found %v", want.library, want.disableTurbine, disableTurbine)
@@ -484,6 +448,7 @@
}
func TestSdkVersionByPartition(t *testing.T) {
+ t.Parallel()
testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
java_library {
name: "foo",
@@ -525,6 +490,7 @@
}
func TestArchSpecific(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -537,13 +503,14 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
if len(javac.Inputs) != 2 || javac.Inputs[0].String() != "a.java" || javac.Inputs[1].String() != "b.java" {
t.Errorf(`foo inputs %v != ["a.java", "b.java"]`, javac.Inputs)
}
}
func TestBinary(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library_host {
name: "foo",
@@ -567,11 +534,11 @@
buildOS := ctx.Config().BuildOS.String()
- bar := ctx.ModuleForTests("bar", buildOS+"_common")
+ bar := ctx.ModuleForTests(t, "bar", buildOS+"_common")
barJar := bar.Output("bar.jar").Output.String()
barWrapperDeps := bar.Output("bar").Implicits.Strings()
- libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared")
+ libjni := ctx.ModuleForTests(t, "libjni", buildOS+"_x86_64_shared")
libjniSO := libjni.Rule("Cp").Output.String()
// Test that the install binary wrapper depends on the installed jar file
@@ -586,6 +553,7 @@
}
func TestTest(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_test_host {
name: "foo",
@@ -603,7 +571,7 @@
buildOS := ctx.Config().BuildOS.String()
- foo := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
+ foo := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost)
expected := "lib64/libjni.so"
if runtime.GOOS == "darwin" {
@@ -617,7 +585,31 @@
}
}
+func TestHostCommonData(t *testing.T) {
+ t.Parallel()
+ ctx, _ := testJava(t, `
+ java_library_host {
+ name: "host",
+ srcs: ["a.java"],
+ }
+
+ java_test {
+ name: "foo",
+ srcs: ["a.java"],
+ host_common_data: [":host"],
+ }
+ `)
+
+ foo := ctx.ModuleForTests(t, "foo", "android_common").Module().(*Test)
+ host := ctx.ModuleForTests(t, "host", ctx.Config().BuildOSCommonTarget.String()).Module().(*Library)
+
+ if g, w := foo.data.RelativeToTop().Strings(), []string{host.outputFile.RelativeToTop().String()}; !slices.Equal(g, w) {
+ t.Errorf("expected test data %q, got %q\n", w, g)
+ }
+}
+
func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "target_library",
@@ -638,7 +630,7 @@
).RunTestWithBp(t, bp)
// first, check that the -g flag is added to target modules
- targetLibrary := result.ModuleForTests("target_library", "android_common")
+ targetLibrary := result.ModuleForTests(t, "target_library", "android_common")
targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"]
if !strings.Contains(targetJavaFlags, "-g:source,lines") {
t.Errorf("target library javac flags %v should contain "+
@@ -647,7 +639,7 @@
// check that -g is not overridden for host modules
buildOS := result.Config.BuildOS.String()
- hostBinary := result.ModuleForTests("host_binary", buildOS+"_common")
+ hostBinary := result.ModuleForTests(t, "host_binary", buildOS+"_common")
hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"]
if strings.Contains(hostJavaFlags, "-g:source,lines") {
t.Errorf("java_binary_host javac flags %v should not have "+
@@ -665,6 +657,7 @@
var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil)
func TestPrebuilts(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -710,15 +703,15 @@
}
`)
- fooModule := ctx.ModuleForTests("foo", "android_common")
+ fooModule := ctx.ModuleForTests(t, "foo", "android_common")
javac := fooModule.Rule("javac")
- combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
- barModule := ctx.ModuleForTests("bar", "android_common")
- barJar := barModule.Output("combined/bar.jar").Output
- bazModule := ctx.ModuleForTests("baz", "android_common")
- bazJar := bazModule.Output("combined/baz.jar").Output
- sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").
- Output("combined/sdklib.stubs.jar").Output
+ combineJar := ctx.ModuleForTests(t, "foo", "android_common").Description("for javac")
+ barModule := ctx.ModuleForTests(t, "bar", "android_common")
+ barJar := barModule.Output("local-combined/bar.jar").Output
+ bazModule := ctx.ModuleForTests(t, "baz", "android_common")
+ bazJar := bazModule.Output("local-combined/baz.jar").Output
+ sdklibStubsJar := ctx.ModuleForTests(t, "sdklib.stubs", "android_common").
+ Output("local-combined/sdklib.stubs.jar").Output
fooLibrary := fooModule.Module().(*Library)
assertDeepEquals(t, "foo unique sources incorrect",
@@ -750,7 +743,7 @@
expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
- ctx.ModuleForTests("qux", "android_common").Rule("Cp")
+ ctx.ModuleForTests(t, "qux", "android_common").Rule("Cp")
entries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0]
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
@@ -765,6 +758,7 @@
}
func TestPrebuiltStubsSources(t *testing.T) {
+ t.Parallel()
test := func(t *testing.T, sourcesPath string, expectedInputs []string) {
ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
prebuilt_stubs_sources {
@@ -775,17 +769,19 @@
"stubs/sources/pkg/B.java": nil,
})
- zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src")
+ zipSrc := ctx.ModuleForTests(t, "stubs-source", "android_common").Rule("zip_src")
if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) {
t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual)
}
}
t.Run("empty/missing directory", func(t *testing.T) {
+ t.Parallel()
test(t, "empty-directory", nil)
})
t.Run("non-empty set of sources", func(t *testing.T) {
+ t.Parallel()
test(t, "stubs/sources", []string{
"stubs/sources/pkg/A.java",
"stubs/sources/pkg/B.java",
@@ -794,6 +790,7 @@
}
func TestDefaults(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_defaults {
name: "defaults",
@@ -835,40 +832,41 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
+ combineJar := ctx.ModuleForTests(t, "foo", "android_common").Description("for javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
}
- barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
+ barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
if !strings.Contains(javac.Args["classpath"], barTurbine) {
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
}
- baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
+ baz := ctx.ModuleForTests(t, "baz", "android_common").Rule("javac").Output.String()
if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
}
- atestOptimize := ctx.ModuleForTests("atestOptimize", "android_common").MaybeRule("r8")
+ atestOptimize := ctx.ModuleForTests(t, "atestOptimize", "android_common").MaybeRule("r8")
if atestOptimize.Output == nil {
t.Errorf("atestOptimize should optimize APK")
}
- atestNoOptimize := ctx.ModuleForTests("atestNoOptimize", "android_common").MaybeRule("d8")
+ atestNoOptimize := ctx.ModuleForTests(t, "atestNoOptimize", "android_common").MaybeRule("d8")
if atestNoOptimize.Output == nil {
t.Errorf("atestNoOptimize should not optimize APK")
}
- atestDefault := ctx.ModuleForTests("atestDefault", "android_common").MaybeRule("d8")
+ atestDefault := ctx.ModuleForTests(t, "atestDefault", "android_common").MaybeRule("d8")
if atestDefault.Output == nil {
t.Errorf("atestDefault should not optimize APK")
}
}
func TestResources(t *testing.T) {
+ t.Parallel()
var table = []struct {
name string
prop string
@@ -940,6 +938,7 @@
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -958,8 +957,8 @@
},
)
- foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
- fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
+ foo := ctx.ModuleForTests(t, "foo", "android_common").Output("withres/foo.jar")
+ fooRes := ctx.ModuleForTests(t, "foo", "android_common").Output("res/foo.jar")
if !inList(fooRes.Output.String(), foo.Inputs.Strings()) {
t.Errorf("foo combined jars %v does not contain %q",
@@ -975,6 +974,7 @@
}
func TestIncludeSrcs(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -1003,8 +1003,8 @@
})
// Test a library with include_srcs: true
- foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
- fooSrcJar := ctx.ModuleForTests("foo", "android_common").Output("foo.srcjar")
+ foo := ctx.ModuleForTests(t, "foo", "android_common").Output("withres/foo.jar")
+ fooSrcJar := ctx.ModuleForTests(t, "foo", "android_common").Output("foo.srcjar")
if g, w := fooSrcJar.Output.String(), foo.Inputs.Strings(); !inList(g, w) {
t.Errorf("foo combined jars %v does not contain %q", w, g)
@@ -1015,10 +1015,10 @@
}
// Test a library with include_srcs: true and resources
- bar := ctx.ModuleForTests("bar", "android_common").Output("withres/bar.jar")
- barResCombined := ctx.ModuleForTests("bar", "android_common").Output("res-combined/bar.jar")
- barRes := ctx.ModuleForTests("bar", "android_common").Output("res/bar.jar")
- barSrcJar := ctx.ModuleForTests("bar", "android_common").Output("bar.srcjar")
+ bar := ctx.ModuleForTests(t, "bar", "android_common").Output("withres/bar.jar")
+ barResCombined := ctx.ModuleForTests(t, "bar", "android_common").Output("res-combined/bar.jar")
+ barRes := ctx.ModuleForTests(t, "bar", "android_common").Output("res/bar.jar")
+ barSrcJar := ctx.ModuleForTests(t, "bar", "android_common").Output("bar.srcjar")
if g, w := barSrcJar.Output.String(), barResCombined.Inputs.Strings(); !inList(g, w) {
t.Errorf("bar combined resource jars %v does not contain %q", w, g)
@@ -1028,7 +1028,7 @@
t.Errorf("bar combined resource jars %v does not contain %q", w, g)
}
- if g, w := barResCombined.Output.String(), bar.Inputs.Strings(); !inList(g, w) {
+ if g, w := barRes.Output.String(), bar.Inputs.Strings(); !inList(g, w) {
t.Errorf("bar combined jars %v does not contain %q", w, g)
}
@@ -1042,6 +1042,7 @@
}
func TestGeneratedSources(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -1062,8 +1063,8 @@
"b.java": nil,
})
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- genrule := ctx.ModuleForTests("gen", "").Rule("generator")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
+ genrule := ctx.ModuleForTests(t, "gen", "").Rule("generator")
if filepath.Base(genrule.Output.String()) != "gen.java" {
t.Fatalf(`gen output file %v is not ".../gen.java"`, genrule.Output.String())
@@ -1078,6 +1079,7 @@
}
func TestTurbine(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}})).
RunTestWithBp(t, `
@@ -1102,15 +1104,15 @@
}
`)
- fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine")
- barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine")
- barJavac := result.ModuleForTests("bar", "android_common").Rule("javac")
- barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine")
- bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
+ fooTurbine := result.ModuleForTests(t, "foo", "android_common").Rule("turbine")
+ barTurbine := result.ModuleForTests(t, "bar", "android_common").Rule("turbine")
+ barJavac := result.ModuleForTests(t, "bar", "android_common").Rule("javac")
+ barTurbineCombined := result.ModuleForTests(t, "bar", "android_common").Description("for turbine")
+ bazJavac := result.ModuleForTests(t, "baz", "android_common").Rule("javac")
android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs)
- fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
+ fooHeaderJar := filepath.Join("out", "soong", ".intermediates", "foo", "android_common", "turbine", "foo.jar")
barTurbineJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
android.AssertStringDoesContain(t, "bar turbine classpath", barTurbine.Args["turbineFlags"], fooHeaderJar)
android.AssertStringDoesContain(t, "bar javac classpath", barJavac.Args["classpath"], fooHeaderJar)
@@ -1119,6 +1121,7 @@
}
func TestSharding(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "bar",
@@ -1129,7 +1132,7 @@
barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
for i := 0; i < 3; i++ {
- barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
+ barJavac := ctx.ModuleForTests(t, "bar", "android_common").Description("javac" + strconv.Itoa(i))
if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") {
t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar)
}
@@ -1137,6 +1140,7 @@
}
func TestExcludeFileGroupInSrcs(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -1155,7 +1159,7 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "java-fg/c.java" {
t.Errorf(`foo inputs %v != ["java-fg/c.java"]`, javac.Inputs)
@@ -1163,6 +1167,7 @@
}
func TestJavaLibraryOutputFiles(t *testing.T) {
+ t.Parallel()
testJavaWithFS(t, "", map[string][]byte{
"libcore/Android.bp": []byte(`
java_library {
@@ -1180,6 +1185,7 @@
}
func TestJavaImportOutputFiles(t *testing.T) {
+ t.Parallel()
testJavaWithFS(t, "", map[string][]byte{
"libcore/Android.bp": []byte(`
java_import {
@@ -1196,6 +1202,7 @@
}
func TestJavaImport(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "source_library",
@@ -1223,18 +1230,20 @@
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, bp)
- source := ctx.ModuleForTests("source_library", "android_common")
+ source := ctx.ModuleForTests(t, "source_library", "android_common")
sourceJar := source.Output("javac/source_library.jar")
- sourceHeaderJar := source.Output("turbine-combined/source_library.jar")
+ sourceHeaderJar := source.Output("turbine/source_library.jar")
+ sourceCombinedHeaderJar := source.Output("turbine-combined/source_library.jar")
sourceJavaInfo, _ := android.OtherModuleProvider(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)
+ []string{sourceCombinedHeaderJar.Output.String()}, sourceJavaInfo.HeaderJars)
- importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common")
+ importWithNoDeps := ctx.ModuleForTests(t, "import_with_no_deps", "android_common")
+ importWithNoDepsLocalJar := importWithNoDeps.Output("local-combined/import_with_no_deps.jar")
importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar")
importWithNoDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
@@ -1244,10 +1253,14 @@
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)
+ []string{importWithNoDepsLocalJar.Output.String()}, importWithNoDepsJar.Inputs)
+ android.AssertPathsRelativeToTopEquals(t, "import with no deps local combined inputs",
+ []string{"no_deps.jar"}, importWithNoDepsLocalJar.Inputs)
- importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common")
+ importWithSourceDeps := ctx.ModuleForTests(t, "import_with_source_deps", "android_common")
+ importWithSourceDepsLocalJar := importWithSourceDeps.Output("local-combined/import_with_source_deps.jar")
importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar")
+ importWithSourceDepsLocalHeaderJar := importWithSourceDeps.Output("local-combined/import_with_source_deps.jar")
importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar")
importWithSourceDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
@@ -1257,11 +1270,16 @@
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)
+ []string{importWithSourceDepsLocalJar.Output.String(), 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)
+ []string{importWithSourceDepsLocalHeaderJar.Output.String(), sourceHeaderJar.Output.String()}, importWithSourceDepsHeaderJar.Inputs)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps local combined implementation jar inputs",
+ []string{"source_deps.jar"}, importWithSourceDepsLocalJar.Inputs)
+ android.AssertPathsRelativeToTopEquals(t, "import with source deps local combined header jar inputs",
+ []string{"source_deps.jar"}, importWithSourceDepsLocalHeaderJar.Inputs)
- importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common")
+ importWithImportDeps := ctx.ModuleForTests(t, "import_with_import_deps", "android_common")
+ importWithImportDepsLocalJar := importWithImportDeps.Output("local-combined/import_with_import_deps.jar")
importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar")
importWithImportDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
@@ -1271,7 +1289,9 @@
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)
+ []string{importWithImportDepsLocalJar.Output.String(), importWithNoDepsLocalJar.Output.String()}, importWithImportDepsJar.Inputs)
+ android.AssertPathsRelativeToTopEquals(t, "import with import deps local combined implementation jar inputs",
+ []string{"import_deps.jar"}, importWithImportDepsLocalJar.Inputs)
}
var compilerFlagsTestCases = []struct {
@@ -1323,6 +1343,7 @@
}
func TestCompilerFlags(t *testing.T) {
+ t.Parallel()
for _, testCase := range compilerFlagsTestCases {
ctx := &mockContext{result: true}
CheckKotlincFlags(ctx, []string{testCase.in})
@@ -1337,7 +1358,8 @@
// TODO(jungjw): Consider making this more robust by ignoring path order.
func checkPatchModuleFlag(t *testing.T, ctx *android.TestContext, moduleName string, expected string) {
- variables := ctx.ModuleForTests(moduleName, "android_common").VariablesForTestsRelativeToTop()
+ t.Helper()
+ variables := ctx.ModuleForTests(t, moduleName, "android_common").VariablesForTestsRelativeToTop()
flags := strings.Split(variables["javacFlags"], " ")
got := ""
for _, flag := range flags {
@@ -1353,7 +1375,9 @@
}
func TestPatchModule(t *testing.T) {
+ t.Parallel()
t.Run("Java language level 8", func(t *testing.T) {
+ t.Parallel()
// Test with legacy javac -source 1.8 -target 1.8
bp := `
java_library {
@@ -1386,6 +1410,7 @@
})
t.Run("Java language level 9", func(t *testing.T) {
+ t.Parallel()
// Test with default javac -source 9 -target 9
bp := `
java_library {
@@ -1426,6 +1451,7 @@
}
func TestJavaLibraryWithSystemModules(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "lib-with-source-system-modules",
@@ -1474,7 +1500,7 @@
}
func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
- javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac")
+ javacRule := ctx.ModuleForTests(t, moduleName, "android_common").Rule("javac")
bootClasspath := javacRule.Args["bootClasspath"]
if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) {
t.Errorf("bootclasspath of %q must start with --system and end with %q, but was %#v.", moduleName, expectedSuffix, bootClasspath)
@@ -1482,6 +1508,7 @@
}
func TestAidlExportIncludeDirsFromImports(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -1498,7 +1525,7 @@
}
`)
- aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
expectedAidlFlag := "-Iaidl/bar"
if !strings.Contains(aidlCommand, expectedAidlFlag) {
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
@@ -1506,6 +1533,7 @@
}
func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -1514,7 +1542,7 @@
}
`)
- aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
expectedAidlFlag := "-Werror"
if !strings.Contains(aidlCommand, expectedAidlFlag) {
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
@@ -1522,6 +1550,7 @@
}
func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
+ t.Parallel()
fixture := android.GroupFixturePreparers(
prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}}))
@@ -1535,6 +1564,7 @@
{"system_current", `sdk_version: "system_current"`, "current"},
} {
t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
ctx := fixture.RunTestWithBp(t, `
java_library {
name: "foo",
@@ -1542,7 +1572,7 @@
`+tc.sdkVersion+`
}
`)
- aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
expectedAidlFlag := "--min_sdk_version=" + tc.expected
if !strings.Contains(aidlCommand, expectedAidlFlag) {
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
@@ -1552,6 +1582,7 @@
}
func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) {
+ t.Parallel()
bpTemplate := `
droidstubs {
name: "foo-stubs",
@@ -1578,13 +1609,14 @@
}
for _, tc := range testCases {
ctx := prepareForJavaTest.RunTestWithBp(t, fmt.Sprintf(bpTemplate, tc.sdkVersionBp))
- aidlCmd := ctx.ModuleForTests("foo-stubs", "android_common").Rule("aidl").RuleParams.Command
+ aidlCmd := ctx.ModuleForTests(t, "foo-stubs", "android_common").Rule("aidl").RuleParams.Command
expected := "--min_sdk_version=" + tc.minSdkVersionExpected
android.AssertStringDoesContain(t, "aidl command conatins incorrect min_sdk_version for testCse: "+tc.desc, aidlCmd, expected)
}
}
func TestAidlEnforcePermissions(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -1593,7 +1625,7 @@
}
`)
- aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
expectedAidlFlag := "-Wmissing-permission-annotation -Werror"
if !strings.Contains(aidlCommand, expectedAidlFlag) {
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
@@ -1601,6 +1633,7 @@
}
func TestAidlEnforcePermissionsException(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -1609,7 +1642,7 @@
}
`)
- aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ aidlCommand := ctx.ModuleForTests(t, "foo", "android_common").Rule("aidl").RuleParams.Command
expectedAidlFlag := "$$FLAGS -Wmissing-permission-annotation -Werror aidl/foo/IFoo.aidl"
if !strings.Contains(aidlCommand, expectedAidlFlag) {
t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
@@ -1621,6 +1654,7 @@
}
func TestDataNativeBinaries(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
android.PrepareForTestWithAllowMissingDependencies).RunTestWithBp(t, `
@@ -1638,7 +1672,7 @@
buildOS := ctx.Config().BuildOS.String()
- test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
+ test := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost)
entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64/bin:bin"}
actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
@@ -1646,6 +1680,7 @@
}
func TestDefaultInstallable(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_test_host {
name: "foo"
@@ -1653,12 +1688,13 @@
`)
buildOS := ctx.Config().BuildOS.String()
- module := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost)
+ module := ctx.ModuleForTests(t, "foo", buildOS+"_common").Module().(*TestHost)
assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true),
module.properties.Installable)
}
func TestErrorproneEnabled(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -1669,7 +1705,7 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac")
// Test that the errorprone plugins are passed to javac
expectedSubstring := "-Xplugin:ErrorProne"
@@ -1680,13 +1716,14 @@
// Modules with errorprone { enabled: true } will include errorprone checks
// in the main javac build rule. Only when RUN_ERROR_PRONE is true will
// the explicit errorprone build rule be created.
- errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
+ errorprone := ctx.ModuleForTests(t, "foo", "android_common").MaybeDescription("errorprone")
if errorprone.RuleParams.Description != "" {
t.Errorf("expected errorprone build rule to not exist, but it did")
}
}
func TestErrorproneDisabled(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "foo",
@@ -1703,7 +1740,7 @@
}),
).RunTestWithBp(t, bp)
- javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac")
// Test that the errorprone plugins are not passed to javac, like they would
// be if enabled was true.
@@ -1714,13 +1751,14 @@
// Check that no errorprone build rule is created, like there would be
// if enabled was unset and RUN_ERROR_PRONE was true.
- errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
+ errorprone := ctx.ModuleForTests(t, "foo", "android_common").MaybeDescription("errorprone")
if errorprone.RuleParams.Description != "" {
t.Errorf("expected errorprone build rule to not exist, but it did")
}
}
func TestErrorproneEnabledOnlyByEnvironmentVariable(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "foo",
@@ -1734,8 +1772,8 @@
}),
).RunTestWithBp(t, bp)
- javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
- errorprone := ctx.ModuleForTests("foo", "android_common").Description("errorprone")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Description("javac")
+ errorprone := ctx.ModuleForTests(t, "foo", "android_common").Description("errorprone")
// Check that the errorprone plugins are not passed to javac, because they
// will instead be passed to the separate errorprone compilation
@@ -1751,6 +1789,7 @@
}
func TestDataDeviceBinsBuildsDeviceBinary(t *testing.T) {
+ t.Parallel()
testCases := []struct {
dataDeviceBinType string
depCompileMultilib string
@@ -1887,6 +1926,7 @@
testName := fmt.Sprintf(`data_device_bins_%s with compile_multilib:"%s"`, tc.dataDeviceBinType, tc.depCompileMultilib)
t.Run(testName, func(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(PrepareForIntegrationTestWithJava).
ExtendWithErrorHandler(errorHandler).
RunTestWithBp(t, bp)
@@ -1895,7 +1935,7 @@
}
buildOS := ctx.Config.BuildOS.String()
- fooVariant := ctx.ModuleForTests("foo", buildOS+"_common")
+ fooVariant := ctx.ModuleForTests(t, "foo", buildOS+"_common")
fooMod := fooVariant.Module().(*TestHost)
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, fooMod)[0]
@@ -1907,7 +1947,7 @@
expectedData := []string{}
for _, variant := range tc.variants {
- barVariant := ctx.ModuleForTests("bar", variant)
+ barVariant := ctx.ModuleForTests(t, "bar", variant)
relocated := barVariant.Output("bar")
expectedInput := fmt.Sprintf("out/soong/.intermediates/bar/%s/unstripped/bar", variant)
android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
@@ -1916,12 +1956,13 @@
}
actualData := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
- android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, expectedData, actualData)
+ android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", ctx.Config, android.SortedUniqueStrings(expectedData), android.SortedUniqueStrings(actualData))
})
}
}
func TestDeviceBinaryWrapperGeneration(t *testing.T) {
+ t.Parallel()
// Scenario 1: java_binary has main_class property in its bp
ctx, _ := testJava(t, `
java_binary {
@@ -1930,7 +1971,7 @@
main_class: "foo.bar.jb",
}
`)
- wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_common").AllOutputs())
+ wrapperPath := fmt.Sprint(ctx.ModuleForTests(t, "foo", "android_common").AllOutputs())
if !strings.Contains(wrapperPath, "foo.sh") {
t.Errorf("wrapper file foo.sh is not generated")
}
@@ -1945,6 +1986,7 @@
}
func TestJavaApiContributionEmptyApiFile(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureMergeEnv(
@@ -1968,6 +2010,7 @@
}
func TestJavaApiLibraryAndProviderLink(t *testing.T) {
+ t.Parallel()
provider_bp_a := `
java_api_contribution {
name: "foo1",
@@ -2024,7 +2067,7 @@
},
}
for _, c := range testcases {
- m := ctx.ModuleForTests(c.moduleName, "android_common")
+ m := ctx.ModuleForTests(t, c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
@@ -2034,6 +2077,7 @@
}
func TestJavaApiLibraryAndDefaultsLink(t *testing.T) {
+ t.Parallel()
provider_bp_a := `
java_api_contribution {
name: "foo1",
@@ -2132,7 +2176,7 @@
},
}
for _, c := range testcases {
- m := ctx.ModuleForTests(c.moduleName, "android_common")
+ m := ctx.ModuleForTests(t, c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
@@ -2142,6 +2186,7 @@
}
func TestJavaApiLibraryJarGeneration(t *testing.T) {
+ t.Parallel()
provider_bp_a := `
java_api_contribution {
name: "foo1",
@@ -2199,7 +2244,7 @@
},
}
for _, c := range testcases {
- m := ctx.ModuleForTests(c.moduleName, "android_common")
+ m := ctx.ModuleForTests(t, c.moduleName, "android_common")
outputs := fmt.Sprint(m.AllOutputs())
if !strings.Contains(outputs, c.outputJarName) {
t.Errorf("Module output does not contain expected jar %s", c.outputJarName)
@@ -2208,6 +2253,7 @@
}
func TestJavaApiLibraryLibsLink(t *testing.T) {
+ t.Parallel()
provider_bp_a := `
java_api_contribution {
name: "foo1",
@@ -2284,7 +2330,7 @@
},
}
for _, c := range testcases {
- m := ctx.ModuleForTests(c.moduleName, "android_common")
+ m := ctx.ModuleForTests(t, c.moduleName, "android_common")
javacRules := m.Rule("javac")
classPathArgs := javacRules.Args["classpath"]
for _, jarName := range c.classPathJarNames {
@@ -2296,6 +2342,7 @@
}
func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
+ t.Parallel()
provider_bp_a := `
java_api_contribution {
name: "foo1",
@@ -2372,7 +2419,7 @@
},
}
for _, c := range testcases {
- m := ctx.ModuleForTests(c.moduleName, "android_common")
+ m := ctx.ModuleForTests(t, c.moduleName, "android_common")
mergeZipsCommand := m.Rule("merge_zips").RuleParams.Command
for _, jarName := range c.staticLibJarNames {
if !strings.Contains(mergeZipsCommand, jarName) {
@@ -2383,6 +2430,7 @@
}
func TestTransitiveSrcFiles(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "a",
@@ -2399,13 +2447,14 @@
static_libs: ["b"],
}
`)
- c := ctx.ModuleForTests("c", "android_common").Module()
+ c := ctx.ModuleForTests(t, "c", "android_common").Module()
javaInfo, _ := android.OtherModuleProvider(ctx, c, JavaInfoProvider)
transitiveSrcFiles := android.Paths(javaInfo.TransitiveSrcFiles.ToList())
android.AssertArrayString(t, "unexpected jar deps", []string{"b.java", "c.java"}, transitiveSrcFiles.Strings())
}
func TestTradefedOptions(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
java_test_host {
name: "foo",
@@ -2421,7 +2470,7 @@
`)
buildOS := result.Config.BuildOS.String()
- args := result.ModuleForTests("foo", buildOS+"_common").
+ args := result.ModuleForTests(t, "foo", buildOS+"_common").
Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
expected := proptools.NinjaAndShellEscape("<option name=\"exclude-path\" value=\"org/apache\" />")
if args["extraConfigs"] != expected {
@@ -2430,6 +2479,7 @@
}
func TestTestRunnerOptions(t *testing.T) {
+ t.Parallel()
result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
java_test_host {
name: "foo",
@@ -2445,7 +2495,7 @@
`)
buildOS := result.Config.BuildOS.String()
- args := result.ModuleForTests("foo", buildOS+"_common").
+ args := result.ModuleForTests(t, "foo", buildOS+"_common").
Output("out/soong/.intermediates/foo/" + buildOS + "_common/foo.config").Args
expected := proptools.NinjaAndShellEscape("<option name=\"test-timeout\" value=\"10m\" />\\n ")
if args["extraTestRunnerConfigs"] != expected {
@@ -2454,6 +2504,7 @@
}
func TestJavaLibraryWithResourcesStem(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -2465,7 +2516,7 @@
"test-jar/test/resource.txt": nil,
})
- m := ctx.ModuleForTests("foo", "android_common")
+ m := ctx.ModuleForTests(t, "foo", "android_common")
outputs := fmt.Sprint(m.AllOutputs())
if !strings.Contains(outputs, "test.jar") {
t.Errorf("Module output does not contain expected jar %s", "test.jar")
@@ -2473,6 +2524,7 @@
}
func TestHeadersOnly(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -2481,16 +2533,17 @@
}
`)
- turbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine")
+ turbine := ctx.ModuleForTests(t, "foo", "android_common").Rule("turbine")
if len(turbine.Inputs) != 1 || turbine.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, turbine.Inputs)
}
- javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("javac")
android.AssertDeepEquals(t, "javac rule", nil, javac.Rule)
}
func TestJavaApiContributionImport(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureMergeEnv(
@@ -2510,7 +2563,7 @@
api_surface: "public",
}
`)
- m := ctx.ModuleForTests("foo", "android_common")
+ m := ctx.ModuleForTests(t, "foo", "android_common")
manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
@@ -2519,6 +2572,7 @@
}
func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_api_library {
name: "foo",
@@ -2532,7 +2586,7 @@
stubs_type: "everything",
}
`)
- m := ctx.ModuleForTests("foo", "android_common")
+ m := ctx.ModuleForTests(t, "foo", "android_common")
manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
@@ -2547,6 +2601,7 @@
}
func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -2576,6 +2631,7 @@
}
func TestApiLibraryDroidstubsDependency(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -2605,9 +2661,9 @@
`)
currentApiTimestampPath := "api-stubs-docs-non-updatable/android_common/everything/check_current_api.timestamp"
- foo := result.ModuleForTests("foo", "android_common").Module().(*ApiLibrary)
+ foo := result.ModuleForTests(t, "foo", "android_common").Module().(*ApiLibrary)
fooValidationPathsString := strings.Join(foo.validationPaths.Strings(), " ")
- bar := result.ModuleForTests("bar", "android_common").Module().(*ApiLibrary)
+ bar := result.ModuleForTests(t, "bar", "android_common").Module().(*ApiLibrary)
barValidationPathsString := strings.Join(bar.validationPaths.Strings(), " ")
android.AssertStringDoesContain(t,
"Module expected to have validation",
@@ -2622,6 +2678,7 @@
}
func TestDisableFromTextStubForCoverageBuild(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -2651,6 +2708,7 @@
}
func TestMultiplePrebuilts(t *testing.T) {
+ t.Parallel()
bp := `
// an rdep
java_library {
@@ -2733,8 +2791,8 @@
).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
// check that rdep gets the correct variation of dep
- foo := ctx.ModuleForTests("foo", "android_common")
- expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
+ expectedDependency := ctx.ModuleForTests(t, tc.expectedDependencyName, "android_common")
android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module()))
// check that output file of dep is always bar.jar
@@ -2749,6 +2807,7 @@
}
func TestMultiplePlatformCompatConfigPrebuilts(t *testing.T) {
+ t.Parallel()
bp := `
// multiple variations of platform_compat_config
// source
@@ -2802,13 +2861,14 @@
android.PrepareForTestWithBuildFlag("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")
+ mergedGlobalConfig := ctx.SingletonForTests(t, "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) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -2850,14 +2910,14 @@
android.AssertBoolEquals(t, "foo expected to depend on bar",
CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
- m := result.ModuleForTests("foo", "android_common")
+ m := result.ModuleForTests(t, "foo", "android_common")
android.AssertStringDoesContain(t, "foo generates revert annotations file",
- strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+ strings.Join(m.AllOutputs(), ""), "flags-config-exportable.xml")
// revert-annotations.txt passed to exportable stubs generation metalava command
manifest := m.Output("metalava.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, "flagged api hide command not included", cmdline, "flags-config-exportable.xml")
}
func TestTestOnly(t *testing.T) {
@@ -2919,6 +2979,7 @@
// Don't allow setting test-only on things that are always tests or never tests.
func TestInvalidTestOnlyTargets(t *testing.T) {
+ t.Parallel()
testCases := []string{
` java_test { name: "java-test", test_only: true, srcs: ["foo.java"], } `,
` java_test_host { name: "java-test-host", test_only: true, srcs: ["foo.java"], } `,
@@ -2954,6 +3015,7 @@
}
func TestJavaLibHostWithStem(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library_host {
name: "foo",
@@ -2963,7 +3025,7 @@
`)
buildOS := ctx.Config().BuildOS.String()
- foo := ctx.ModuleForTests("foo", buildOS+"_common")
+ foo := ctx.ModuleForTests(t, "foo", buildOS+"_common")
outputs := fmt.Sprint(foo.AllOutputs())
if !strings.Contains(outputs, "foo-new.jar") {
@@ -2972,6 +3034,7 @@
}
func TestJavaLibWithStem(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -2980,7 +3043,7 @@
}
`)
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
outputs := fmt.Sprint(foo.AllOutputs())
if !strings.Contains(outputs, "foo-new.jar") {
@@ -2989,6 +3052,7 @@
}
func TestJavaLibraryOutputFilesRel(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -3010,9 +3074,9 @@
}
`)
- foo := result.ModuleForTests("foo", "android_common")
- bar := result.ModuleForTests("bar", "android_common")
- baz := result.ModuleForTests("baz", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ bar := result.ModuleForTests(t, "bar", "android_common")
+ baz := result.ModuleForTests(t, "baz", "android_common")
fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
barOutputPaths := bar.OutputFiles(result.TestContext, t, "")
@@ -3034,10 +3098,10 @@
}
func TestCoverage(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
prepareForTestWithFrameworkJacocoInstrumentation,
- PrepareForTestWithTransitiveClasspathEnabled,
).RunTestWithBp(t, `
android_app {
name: "foo",
@@ -3054,8 +3118,8 @@
}
`)
- foo := result.ModuleForTests("foo", "android_common")
- androidCar := result.ModuleForTests("android.car", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ androidCar := result.ModuleForTests(t, "android.car", "android_common")
fooJacoco := foo.Rule("jacoco")
fooCombine := foo.Description("for javac")
@@ -3104,6 +3168,7 @@
// Test that a dependency edge is created to the matching variant of a native library listed in `jni_libs` of java_binary
func TestNativeRequiredDepOfJavaBinary(t *testing.T) {
+ t.Parallel()
findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module {
var ret []blueprint.Module
ctx.VisitDirectDeps(module, func(dep blueprint.Module) {
@@ -3125,6 +3190,75 @@
}
`
res, _ := testJava(t, bp)
- deps := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib")
+ deps := findDepsOfModule(res, res.ModuleForTests(t, "myjavabin", "android_common").Module(), "mynativelib")
android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps))
}
+
+func TestBootJarNotInUsesLibs(t *testing.T) {
+ t.Parallel()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"),
+ FixtureConfigureApexBootJars("myapex:mysdklibrary"),
+ ).RunTestWithBp(t, `
+ bootclasspath_fragment {
+ name: "myfragment",
+ contents: ["mysdklibrary"],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ java_sdk_library {
+ name: "mysdklibrary",
+ srcs: ["Test.java"],
+ compile_dex: true,
+ public: {enabled: true},
+ min_sdk_version: "2",
+ permitted_packages: ["mysdklibrary"],
+ sdk_version: "current",
+ }
+
+ java_sdk_library {
+ name: "myothersdklibrary",
+ srcs: ["Test.java"],
+ compile_dex: true,
+ public: {enabled: true},
+ min_sdk_version: "2",
+ permitted_packages: ["myothersdklibrary"],
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "foo",
+ libs: [
+ "bar",
+ "mysdklibrary.stubs",
+ ],
+ srcs: ["A.java"],
+ }
+
+ java_library {
+ name: "bar",
+ libs: [
+ "myothersdklibrary.stubs"
+ ],
+ }
+ `)
+ ctx := result.TestContext
+ fooModule := ctx.ModuleForTests(t, "foo", "android_common")
+
+ androidMkEntries := android.AndroidMkEntriesForTest(t, ctx, fooModule.Module())[0]
+ localExportSdkLibraries := androidMkEntries.EntryMap["LOCAL_EXPORT_SDK_LIBRARIES"]
+ android.AssertStringListDoesNotContain(t,
+ "boot jar should not be included in uses libs entries",
+ localExportSdkLibraries,
+ "mysdklibrary",
+ )
+ android.AssertStringListContains(t,
+ "non boot jar is included in uses libs entries",
+ localExportSdkLibraries,
+ "myothersdklibrary",
+ )
+}
diff --git a/java/jdeps.go b/java/jdeps.go
index c2ce503..56142c8 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -37,8 +37,6 @@
outputPath android.Path
}
-var _ android.SingletonMakeVarsProvider = (*jdepsGeneratorSingleton)(nil)
-
const (
jdepsJsonFileName = "module_bp_java_deps.json"
)
@@ -47,13 +45,13 @@
// (b/204397180) Generate module_bp_java_deps.json by default.
moduleInfos := make(map[string]android.IdeInfo)
- ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
// Prevent including both prebuilts and matching source modules when one replaces the other.
- if !android.IsModulePreferred(module) {
+ if !android.IsModulePreferredProxy(ctx, module) {
return
}
@@ -62,9 +60,11 @@
return
}
name := ideInfoProvider.BaseModuleName
- ideModuleNameProvider, ok := module.(android.IDECustomizedModuleName)
- if ok {
- name = ideModuleNameProvider.IDECustomizedModuleName()
+ if info, ok := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider); ok && info.Prebuilt {
+ // TODO(b/113562217): Extract the base module name from the Import name, often the Import name
+ // has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better
+ // solution to get the Import name.
+ name = android.RemoveOptionalPrebuiltPrefix(module.Name())
}
dpInfo := moduleInfos[name]
@@ -72,13 +72,12 @@
dpInfo.Paths = []string{ctx.ModuleDir(module)}
moduleInfos[name] = dpInfo
- mkProvider, ok := module.(android.AndroidMkDataProvider)
+ mkProvider, ok := android.OtherModuleProvider(ctx, module, android.AndroidMkDataInfoProvider)
if !ok {
return
}
- data := mkProvider.AndroidMk()
- if data.Class != "" {
- dpInfo.Classes = append(dpInfo.Classes, data.Class)
+ if mkProvider.Class != "" {
+ dpInfo.Classes = append(dpInfo.Classes, mkProvider.Class)
}
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
@@ -101,14 +100,7 @@
Rule: android.Touch,
Output: jfpath,
})
-}
-
-func (j *jdepsGeneratorSingleton) MakeVars(ctx android.MakeVarsContext) {
- if j.outputPath == nil {
- return
- }
-
- ctx.DistForGoal("general-tests", j.outputPath)
+ ctx.DistForGoals([]string{"general-tests", "dist_files"}, j.outputPath)
}
func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath android.WritablePath) error {
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index 1435000..00f3839 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -22,6 +22,7 @@
)
func TestCollectJavaLibraryPropertiesAddLibsDeps(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t,
`
java_library {name: "Foo"}
@@ -31,7 +32,7 @@
libs: ["Foo", "Bar"],
}
`)
- module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
for _, expected := range []string{"Foo", "Bar"} {
@@ -42,6 +43,7 @@
}
func TestCollectJavaLibraryPropertiesAddStaticLibsDeps(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t,
`
java_library {name: "Foo"}
@@ -51,7 +53,7 @@
static_libs: ["Foo", "Bar"],
}
`)
- module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
for _, expected := range []string{"Foo", "Bar"} {
@@ -62,6 +64,7 @@
}
func TestCollectJavaLibraryPropertiesAddScrs(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t,
`
java_library {
@@ -69,7 +72,7 @@
srcs: ["Foo.java", "Bar.java"],
}
`)
- module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
expected := []string{"Foo.java", "Bar.java"}
@@ -79,6 +82,7 @@
}
func TestCollectJavaLibraryPropertiesAddAidlIncludeDirs(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t,
`
java_library {
@@ -88,7 +92,7 @@
},
}
`)
- module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
expected := []string{"Foo", "Bar"}
@@ -98,6 +102,7 @@
}
func TestCollectJavaLibraryWithJarJarRules(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t,
`
java_library {
@@ -106,7 +111,7 @@
jarjar_rules: "jarjar_rules.txt",
}
`)
- module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
android.AssertStringEquals(t, "IdeInfo.Srcs of repackaged library should not be empty", "foo.java", dpInfo.Srcs[0])
@@ -117,6 +122,7 @@
}
func TestCollectJavaLibraryLinkingAgainstVersionedSdk(t *testing.T) {
+ t.Parallel()
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
FixtureWithPrebuiltApis(map[string][]string{
@@ -129,7 +135,7 @@
sdk_version: "29",
}
`)
- module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ module := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
android.AssertStringListContains(t, "IdeInfo.Deps should contain versioned sdk module", dpInfo.Deps, "sdk_public_29_android")
@@ -165,11 +171,11 @@
api_surface: "public",
}
`)
- javalib := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ javalib := ctx.ModuleForTests(t, "javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, javalib, android.IdeInfoProviderKey)
android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none")
- javalib_stubs := ctx.ModuleForTests("javalib.stubs", "android_common").Module().(*ApiLibrary)
+ javalib_stubs := ctx.ModuleForTests(t, "javalib.stubs", "android_common").Module().(*ApiLibrary)
dpInfo, _ = android.OtherModuleProvider(ctx, javalib_stubs, android.IdeInfoProviderKey)
android.AssertStringListDoesNotContain(t, "IdeInfo.Deps should contain not contain `none`", dpInfo.Deps, "none")
}
diff --git a/java/kotlin.go b/java/kotlin.go
index f42d163..308bb03 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -181,6 +181,7 @@
Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` +
`mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
+ `${config.FindInputDeltaCmd} --template '' --target "$out" --inputs_file "$out.rsp" && ` +
`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
` --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
@@ -197,8 +198,10 @@
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
`${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
+ `if [ -f "$out.pc_state.new" ]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
+ "${config.FindInputDeltaCmd}",
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
"${config.KotlinKaptJar}",
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 45eac01..4b56cff 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -24,6 +24,7 @@
)
func TestKotlin(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "foo",
@@ -49,13 +50,6 @@
srcs: ["d.kt"],
}`
- kotlinStdlibTurbineCombinedJars := []string{
- "out/soong/.intermediates/default/java/kotlin-stdlib/android_common/turbine-combined/kotlin-stdlib.jar",
- "out/soong/.intermediates/default/java/kotlin-stdlib-jdk7/android_common/turbine-combined/kotlin-stdlib-jdk7.jar",
- "out/soong/.intermediates/default/java/kotlin-stdlib-jdk8/android_common/turbine-combined/kotlin-stdlib-jdk8.jar",
- "out/soong/.intermediates/default/java/kotlin-annotations/android_common/turbine-combined/kotlin-annotations.jar",
- }
-
kotlinStdlibTurbineJars := []string{
"out/soong/.intermediates/default/java/kotlin-stdlib/android_common/turbine/kotlin-stdlib.jar",
"out/soong/.intermediates/default/java/kotlin-stdlib-jdk7/android_common/turbine/kotlin-stdlib-jdk7.jar",
@@ -70,21 +64,11 @@
"out/soong/.intermediates/default/java/kotlin-annotations/android_common/javac/kotlin-annotations.jar",
}
- bootclasspathTurbineCombinedJars := []string{
- "out/soong/.intermediates/default/java/stable.core.platform.api.stubs/android_common/turbine-combined/stable.core.platform.api.stubs.jar",
- "out/soong/.intermediates/default/java/core-lambda-stubs/android_common/turbine-combined/core-lambda-stubs.jar",
- }
-
bootclasspathTurbineJars := []string{
"out/soong/.intermediates/default/java/stable.core.platform.api.stubs/android_common/turbine/stable.core.platform.api.stubs.jar",
"out/soong/.intermediates/default/java/core-lambda-stubs/android_common/turbine/core-lambda-stubs.jar",
}
- frameworkTurbineCombinedJars := []string{
- "out/soong/.intermediates/default/java/ext/android_common/turbine-combined/ext.jar",
- "out/soong/.intermediates/default/java/framework/android_common/turbine-combined/framework.jar",
- }
-
frameworkTurbineJars := []string{
"out/soong/.intermediates/default/java/ext/android_common/turbine/ext.jar",
"out/soong/.intermediates/default/java/framework/android_common/turbine/framework.jar",
@@ -108,68 +92,8 @@
barHeaderCombinedInputs []string
}{
{
- name: "normal",
- preparer: android.NullFixturePreparer,
- fooKotlincInputs: []string{"a.java", "b.kt"},
- fooJavacInputs: []string{"a.java"},
- fooKotlincClasspath: slices.Concat(
- bootclasspathTurbineCombinedJars,
- frameworkTurbineCombinedJars,
- []string{"out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar"},
- kotlinStdlibTurbineCombinedJars,
- ),
- fooJavacClasspath: slices.Concat(
- []string{"out/soong/.intermediates/foo/android_common/kotlin_headers/foo.jar"},
- frameworkTurbineCombinedJars,
- []string{"out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar"},
- kotlinStdlibTurbineCombinedJars,
- ),
- fooCombinedInputs: slices.Concat(
- []string{
- "out/soong/.intermediates/foo/android_common/kotlin/foo.jar",
- "out/soong/.intermediates/foo/android_common/javac/foo.jar",
- "out/soong/.intermediates/quz/android_common/combined/quz.jar",
- },
- kotlinStdlibJavacJars,
- ),
- fooHeaderCombinedInputs: slices.Concat(
- []string{
- "out/soong/.intermediates/foo/android_common/turbine/foo.jar",
- "out/soong/.intermediates/foo/android_common/kotlin_headers/foo.jar",
- "out/soong/.intermediates/quz/android_common/turbine-combined/quz.jar",
- },
- kotlinStdlibTurbineCombinedJars,
- ),
-
- barKotlincInputs: []string{"b.kt"},
- barKotlincClasspath: slices.Concat(
- bootclasspathTurbineCombinedJars,
- frameworkTurbineCombinedJars,
- []string{
- "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar",
- "out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar",
- },
- kotlinStdlibTurbineCombinedJars,
- ),
- barCombinedInputs: slices.Concat(
- []string{
- "out/soong/.intermediates/bar/android_common/kotlin/bar.jar",
- "out/soong/.intermediates/baz/android_common/combined/baz.jar",
- },
- kotlinStdlibJavacJars,
- []string{},
- ),
- barHeaderCombinedInputs: slices.Concat(
- []string{
- "out/soong/.intermediates/bar/android_common/kotlin_headers/bar.jar",
- "out/soong/.intermediates/baz/android_common/turbine-combined/baz.jar",
- },
- kotlinStdlibTurbineCombinedJars,
- ),
- },
- {
name: "transitive classpath",
- preparer: PrepareForTestWithTransitiveClasspathEnabled,
+ preparer: android.NullFixturePreparer,
fooKotlincInputs: []string{"a.java", "b.kt"},
fooJavacInputs: []string{"a.java"},
fooKotlincClasspath: slices.Concat(
@@ -234,11 +158,12 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
tt.preparer,
).RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
fooKotlinc := foo.Rule("kotlinc")
android.AssertPathsRelativeToTopEquals(t, "foo kotlinc inputs", tt.fooKotlincInputs, fooKotlinc.Inputs)
@@ -258,7 +183,7 @@
fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar")
android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs)
- bar := result.ModuleForTests("bar", "android_common")
+ bar := result.ModuleForTests(t, "bar", "android_common")
barKotlinc := bar.Rule("kotlinc")
android.AssertPathsRelativeToTopEquals(t, "bar kotlinc inputs", tt.barKotlincInputs, barKotlinc.Inputs)
@@ -275,6 +200,7 @@
}
func TestKapt(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "foo",
@@ -303,18 +229,19 @@
}
`
t.Run("", func(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, bp)
buildOS := ctx.Config().BuildOS.String()
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
kaptStubs := foo.Rule("kapt")
turbineApt := foo.Description("turbine apt")
kotlinc := foo.Rule("kotlinc")
javac := foo.Rule("javac")
- bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
- baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
+ bar := ctx.ModuleForTests(t, "bar", buildOS+"_common").Rule("javac").Output.String()
+ baz := ctx.ModuleForTests(t, "baz", buildOS+"_common").Rule("javac").Output.String()
// Test that the kotlin and java sources are passed to kapt and kotlinc
if len(kaptStubs.Inputs) != 2 || kaptStubs.Inputs[0].String() != "a.java" || kaptStubs.Inputs[1].String() != "b.kt" {
@@ -384,6 +311,7 @@
})
t.Run("errorprone", func(t *testing.T) {
+ t.Parallel()
env := map[string]string{
"RUN_ERROR_PRONE": "true",
}
@@ -395,13 +323,13 @@
buildOS := result.Config.BuildOS.String()
- kapt := result.ModuleForTests("foo", "android_common").Rule("kapt")
- javac := result.ModuleForTests("foo", "android_common").Description("javac")
- errorprone := result.ModuleForTests("foo", "android_common").Description("errorprone")
+ kapt := result.ModuleForTests(t, "foo", "android_common").Rule("kapt")
+ javac := result.ModuleForTests(t, "foo", "android_common").Description("javac")
+ errorprone := result.ModuleForTests(t, "foo", "android_common").Description("errorprone")
- bar := result.ModuleForTests("bar", buildOS+"_common").Description("javac").Output.String()
- baz := result.ModuleForTests("baz", buildOS+"_common").Description("javac").Output.String()
- myCheck := result.ModuleForTests("my_check", buildOS+"_common").Description("javac").Output.String()
+ bar := result.ModuleForTests(t, "bar", buildOS+"_common").Description("javac").Output.String()
+ baz := result.ModuleForTests(t, "baz", buildOS+"_common").Description("javac").Output.String()
+ myCheck := result.ModuleForTests(t, "my_check", buildOS+"_common").Description("javac").Output.String()
// Test that the errorprone plugins are not passed to kapt
expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
@@ -434,6 +362,7 @@
}
func TestKaptEncodeFlags(t *testing.T) {
+ t.Parallel()
// Compares the kaptEncodeFlags against the results of the example implementation at
// https://kotlinlang.org/docs/reference/kapt.html#apjavac-options-encoding
tests := []struct {
@@ -484,6 +413,7 @@
for i, test := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) {
+ t.Parallel()
got := kaptEncodeFlags(test.in)
if got != test.out {
t.Errorf("\nwant %q\n got %q", test.out, got)
@@ -493,6 +423,7 @@
}
func TestKotlinCompose(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -501,7 +432,7 @@
}
kotlin_plugin {
- name: "androidx.compose.compiler_compiler-hosted-plugin",
+ name: "kotlin-compose-compiler-plugin",
}
java_library {
@@ -523,9 +454,9 @@
buildOS := result.Config.BuildOS.String()
- composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted-plugin", buildOS+"_common").Rule("combineJar").Output
- withCompose := result.ModuleForTests("withcompose", "android_common")
- noCompose := result.ModuleForTests("nocompose", "android_common")
+ composeCompiler := result.ModuleForTests(t, "kotlin-compose-compiler-plugin", buildOS+"_common").Rule("combineJar").Output
+ withCompose := result.ModuleForTests(t, "withcompose", "android_common")
+ noCompose := result.ModuleForTests(t, "nocompose", "android_common")
android.AssertStringListContains(t, "missing compose compiler dependency",
withCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
@@ -544,6 +475,7 @@
}
func TestKotlinPlugin(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
).RunTestWithBp(t, `
@@ -570,9 +502,9 @@
buildOS := result.Config.BuildOS.String()
- kotlinPlugin := result.ModuleForTests("kotlin_plugin", buildOS+"_common").Rule("combineJar").Output
- withKotlinPlugin := result.ModuleForTests("with_kotlin_plugin", "android_common")
- noKotlinPlugin := result.ModuleForTests("no_kotlin_plugin", "android_common")
+ kotlinPlugin := result.ModuleForTests(t, "kotlin_plugin", buildOS+"_common").Rule("combineJar").Output
+ withKotlinPlugin := result.ModuleForTests(t, "with_kotlin_plugin", "android_common")
+ noKotlinPlugin := result.ModuleForTests(t, "no_kotlin_plugin", "android_common")
android.AssertStringListContains(t, "missing plugin compiler dependency",
withKotlinPlugin.Rule("kotlinc").Implicits.Strings(), kotlinPlugin.String())
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 4be7d04..21895d4 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -47,8 +47,8 @@
"sam",
"saminterfacelibrary",
"sammanagerlibrary",
- "services",
"services.core.unboosted",
+ "services.impl",
"Settings-core",
"SettingsGoogle",
"SettingsGoogleOverlayCoral",
diff --git a/java/lint.go b/java/lint.go
index ac90e19..dc1e51f 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -69,6 +69,11 @@
// If soong gets support for testonly, this flag should be replaced with that.
Test *bool
+ // Same as the regular Test property, but set by internal soong code based on if the module
+ // type is a test module type. This will act as the default value for the test property,
+ // but can be overridden by the user.
+ Test_module_type *bool `blueprint:"mutated"`
+
// Whether to ignore the exit code of Android lint. This is the --exit_code
// option. Defaults to false.
Suppress_exit_code *bool
@@ -257,7 +262,12 @@
if l.library {
cmd.Flag("--library")
}
- if proptools.BoolDefault(l.properties.Lint.Test, false) {
+
+ test := proptools.BoolDefault(l.properties.Lint.Test_module_type, false)
+ if l.properties.Lint.Test != nil {
+ test = *l.properties.Lint.Test
+ }
+ if test {
cmd.Flag("--test")
}
if l.manifest != nil {
@@ -388,7 +398,7 @@
}
}
- extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
+ extraLintCheckModules := ctx.GetDirectDepsProxyWithTag(extraLintCheckTag)
for _, extraLintCheckModule := range extraLintCheckModules {
if dep, ok := android.OtherModuleProvider(ctx, extraLintCheckModule, JavaInfoProvider); ok {
l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...)
@@ -413,7 +423,7 @@
depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline)
- ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(staticLibTag, func(dep android.ModuleProxy) {
if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
depSetsBuilder.Transitive(info)
}
@@ -470,7 +480,7 @@
cmd := rule.Command()
- cmd.Flag(`JAVA_OPTS="-Xmx3072m --add-opens java.base/java.util=ALL-UNNAMED"`).
+ cmd.Flag(`JAVA_OPTS="-Xmx4096m --add-opens java.base/java.util=ALL-UNNAMED"`).
FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
@@ -585,12 +595,12 @@
l.copyLintDependencies(ctx)
}
-func findModuleOrErr(ctx android.SingletonContext, moduleName string) android.Module {
- var res android.Module
- ctx.VisitAllModules(func(m android.Module) {
+func findModuleOrErr(ctx android.SingletonContext, moduleName string) *android.ModuleProxy {
+ var res *android.ModuleProxy
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
if ctx.ModuleName(m) == moduleName {
if res == nil {
- res = m
+ res = &m
} else {
ctx.Errorf("lint: multiple %s modules found: %s and %s", moduleName,
ctx.ModuleSubDir(m), ctx.ModuleSubDir(res))
@@ -625,13 +635,13 @@
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
- Input: android.OutputFileForModule(ctx, sdkAnnotations, ""),
+ Input: android.OutputFileForModule(ctx, *sdkAnnotations, ""),
Output: copiedLintDatabaseFilesPath(ctx, files.annotationCopiedName),
})
ctx.Build(pctx, android.BuildParams{
Rule: android.CpIfChanged,
- Input: android.OutputFileForModule(ctx, apiVersionsDb, ".api_versions.xml"),
+ Input: android.OutputFileForModule(ctx, *apiVersionsDb, ".api_versions.xml"),
Output: copiedLintDatabaseFilesPath(ctx, files.apiVersionsCopiedName),
})
}
@@ -648,12 +658,13 @@
var outputs []*LintInfo
var dirs []string
- ctx.VisitAllModules(func(m android.Module) {
- if ctx.Config().KatiEnabled() && !m.ExportedToMake() {
+ ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider)
+ if ctx.Config().KatiEnabled() && !commonInfo.ExportedToMake {
return
}
- if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
+ if commonInfo.IsApexModule && commonInfo.NotAvailableForPlatform {
apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
// There are stray platform variants of modules in apexes that are not available for
@@ -694,16 +705,12 @@
zip(l.referenceBaselineZip, func(l *LintInfo) android.Path { return l.ReferenceBaseline })
ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip)
-}
-func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) {
if !ctx.Config().UnbundledBuild() {
ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip)
}
}
-var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil)
-
func init() {
android.RegisterParallelSingletonType("lint",
func() android.Singleton { return &lintSingleton{} })
diff --git a/java/lint_test.go b/java/lint_test.go
index afe3914..236fa63 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -22,6 +22,7 @@
)
func TestJavaLintDoesntUseBaselineImplicitly(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -37,7 +38,7 @@
"lint-baseline.xml": nil,
})
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
if strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
@@ -46,6 +47,7 @@
}
func TestJavaLintRequiresCustomLintFileToExist(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.PrepareForTestDisallowNonExistentPaths,
@@ -65,6 +67,7 @@
}
func TestJavaLintUsesCorrectBpConfig(t *testing.T) {
+ t.Parallel()
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -84,7 +87,7 @@
"mybaseline.xml": nil,
})
- foo := ctx.ModuleForTests("foo", "android_common")
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") {
@@ -101,6 +104,7 @@
}
func TestJavaLintBypassUpdatableChecks(t *testing.T) {
+ t.Parallel()
testCases := []struct {
name string
bp string
@@ -144,6 +148,7 @@
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
+ t.Parallel()
errorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.error)
android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules).
ExtendWithErrorHandler(errorHandler).
@@ -153,6 +158,7 @@
}
func TestJavaLintStrictUpdatabilityLinting(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "foo",
@@ -187,7 +193,7 @@
result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()).
RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
strictUpdatabilityCheck := foo.Output("lint_strict_updatability_check.stamp")
if !strings.Contains(strictUpdatabilityCheck.RuleParams.Command,
"--disallowed_issues NewApi") {
@@ -250,7 +256,7 @@
})).
RunTestWithBp(t, thisBp)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "foo", "android_common")
sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto"))
if !strings.Contains(*sboxProto.Commands[0].Command, "/"+testCase.expected_file) {
t.Error("did not use full api database for case", testCase)
@@ -276,3 +282,50 @@
ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields")).
RunTestWithBp(t, bp)
}
+
+// b/358643466
+func TestNotTestViaDefault(t *testing.T) {
+ bp := `
+ java_defaults {
+ name: "mydefaults",
+ lint: {
+ test: false,
+ },
+ }
+ android_test {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ defaults: ["mydefaults"],
+ }
+ android_test {
+ name: "foo2",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ }
+ `
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
+ ctx := result.TestContext
+
+ foo := ctx.ModuleForTests(t, "foo", "android_common")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
+ command := *sboxProto.Commands[0].Command
+
+ if strings.Contains(command, "--test") {
+ t.Fatalf("Expected command to not contain --test")
+ }
+
+ foo2 := ctx.ModuleForTests(t, "foo2", "android_common")
+ sboxProto2 := android.RuleBuilderSboxProtoForTests(t, ctx, foo2.Output("lint.sbox.textproto"))
+ command2 := *sboxProto2.Commands[0].Command
+
+ if !strings.Contains(command2, "--test") {
+ t.Fatalf("Expected command to contain --test")
+ }
+}
diff --git a/java/metalava/main-config.xml b/java/metalava/main-config.xml
index c61196f..c2881ac 100644
--- a/java/metalava/main-config.xml
+++ b/java/metalava/main-config.xml
@@ -16,4 +16,20 @@
<config xmlns="http://www.google.com/tools/metalava/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.google.com/tools/metalava/config ../../../../tools/metalava/metalava/src/main/resources/schemas/config.xsd"/>
+ xsi:schemaLocation="http://www.google.com/tools/metalava/config ../../../../tools/metalava/metalava/src/main/resources/schemas/config.xsd">
+ <api-surfaces>
+ <!-- These are hard coded into java_sdk_library. -->
+ <api-surface name="public"/>
+ <api-surface name="system" extends="public"/>
+ <api-surface name="module-lib" extends="system"/>
+ <api-surface name="test" extends="system"/>
+ <api-surface name="system-server" extends="public"/>
+ <!-- This is used in java/core-libraries/Android.bp. -->
+ <api-surface name="core"/>
+ <!-- These are used in libcore, external/conscrypt and external/icu. -->
+ <api-surface name="core-platform" extends="public"/>
+ <api-surface name="core-platform-legacy" extends="public"/>
+ <api-surface name="core-platform-plus-public"/>
+ <api-surface name="intra-core" extends="public"/>
+ </api-surfaces>
+</config>
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index d09a02e..155afc6 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -15,6 +15,11 @@
package java
import (
+ "maps"
+ "slices"
+
+ "github.com/google/blueprint"
+
"android/soong/android"
"android/soong/dexpreopt"
)
@@ -29,12 +34,15 @@
// The tags used for the dependencies between the platform bootclasspath and any configured boot
// jars.
-var (
- platformBootclasspathArtBootJarDepTag = bootclasspathDependencyTag{name: "art-boot-jar"}
- platformBootclasspathBootJarDepTag = bootclasspathDependencyTag{name: "platform-boot-jar"}
- platformBootclasspathApexBootJarDepTag = bootclasspathDependencyTag{name: "apex-boot-jar"}
- platformBootclasspathImplLibDepTag = dependencyTag{name: "impl-lib-tag"}
-)
+type platformBootclasspathImplLibDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+func (p platformBootclasspathImplLibDepTagType) ExcludeFromVisibilityEnforcement() {}
+
+var platformBootclasspathImplLibDepTag platformBootclasspathImplLibDepTagType
+
+var _ android.ExcludeFromVisibilityEnforcementTag = platformBootclasspathImplLibDepTag
type platformBootclasspathModule struct {
android.ModuleBase
@@ -48,6 +56,12 @@
// The apex:module pairs obtained from the fragments.
fragments []android.Module
+ // The map of apex to the fragments they contain.
+ apexNameToFragment map[string]android.Module
+
+ // The map of library modules in the bootclasspath to the fragments that contain them.
+ libraryToApex map[android.Module]string
+
// Path to the monolithic hiddenapi-flags.csv file.
hiddenAPIFlagsCSV android.OutputPath
@@ -89,26 +103,12 @@
b.hiddenAPIDepsMutator(ctx)
- if !dexpreopt.IsDex2oatNeeded(ctx) {
- return
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
}
- // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
- // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
- dexpreopt.RegisterToolDeps(ctx)
-}
-
-func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Config().DisableHiddenApiChecks() {
- return
- }
-
- // Add dependencies onto the stub lib modules.
- apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
- hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
-}
-
-func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies on all the ART jars.
global := dexpreopt.GetGlobalConfig(ctx)
addDependenciesOntoSelectedBootImageApexes(ctx, "com.android.art")
@@ -116,13 +116,13 @@
var bootImageModuleNames []string
// TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
- addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, artBootJar)
bootImageModuleNames = append(bootImageModuleNames, global.ArtApexJars.CopyOfJars()...)
// Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
// APEXes.
platformJars := b.platformJars(ctx)
- addDependenciesOntoBootImageModules(ctx, platformJars, platformBootclasspathBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, platformJars, platformBootJar)
bootImageModuleNames = append(bootImageModuleNames, platformJars.CopyOfJars()...)
// Add dependencies on all the updatable jars, except the ART jars.
@@ -133,7 +133,7 @@
}
addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
// TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
- addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, apexJars, apexBootJar)
bootImageModuleNames = append(bootImageModuleNames, apexJars.CopyOfJars()...)
// Add dependencies on all the fragments.
@@ -147,32 +147,42 @@
}
}
-func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tag bootclasspathDependencyTag) {
+func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
+ if ctx.Config().DisableHiddenApiChecks() {
+ return
+ }
+
+ // Add dependencies onto the stub lib modules.
+ apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
+ hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
+}
+
+func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tagType bootclasspathDependencyTagType) {
for i := 0; i < modules.Len(); i++ {
apex := modules.Apex(i)
name := modules.Jar(i)
- addDependencyOntoApexModulePair(ctx, apex, name, tag)
+ addDependencyOntoApexModulePair(ctx, apex, name, tagType)
}
}
func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Gather all the dependencies from the art, platform, and apex boot jars.
- artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag)
- platformModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathBootJarDepTag)
- apexModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathApexBootJarDepTag)
+ artModules, artModulesToApex := gatherApexModulePairDepsWithTag(ctx, artBootJar)
+ platformModules, platformModulesToApex := gatherApexModulePairDepsWithTag(ctx, platformBootJar)
+ apexModules, apexModulesToApex := gatherApexModulePairDepsWithTag(ctx, apexBootJar)
// Concatenate them all, in order as they would appear on the bootclasspath.
- var allModules []android.Module
- allModules = append(allModules, artModules...)
- allModules = append(allModules, platformModules...)
- allModules = append(allModules, apexModules...)
+ allModules := slices.Concat(artModules, platformModules, apexModules)
b.configuredModules = allModules
+ b.libraryToApex = maps.Clone(artModulesToApex)
+ maps.Copy(b.libraryToApex, platformModulesToApex)
+ maps.Copy(b.libraryToApex, apexModulesToApex)
// Do not add implLibModule to allModules as the impl lib is only used to collect the
// transitive source files
var implLibModule []android.Module
- ctx.VisitDirectDepsWithTag(implLibraryTag, func(m android.Module) {
+ ctx.VisitDirectDepsWithTag(platformBootclasspathImplLibDepTag, func(m android.Module) {
implLibModule = append(implLibModule, m)
})
@@ -188,7 +198,7 @@
TransformResourcesToJar(ctx, srcjar, jarArgs, transitiveSrcFiles)
// Gather all the fragments dependencies.
- b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
+ b.fragments, b.apexNameToFragment = gatherFragments(ctx)
// Check the configuration of the boot modules.
// ART modules are checked by the art-bootclasspath-fragment.
@@ -197,7 +207,7 @@
b.generateClasspathProtoBuildActions(ctx)
- bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
+ bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments, b.libraryToApex, b.apexNameToFragment)
buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
ctx.SetOutputFiles(android.Paths{b.hiddenAPIFlagsCSV}, "hiddenapi-flags.csv")
@@ -248,7 +258,7 @@
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// error: this jar is part of an updatable apex
- ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.InApexVariants)
+ ctx.ModuleErrorf("module %q from updatable apex %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.BaseApexName)
} else {
// ok: this jar is part of the platform or a non-updatable apex
}
@@ -272,7 +282,11 @@
// modules is complete.
if !ctx.Config().AlwaysUsePrebuiltSdks() {
// error: this jar is part of the platform
- ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name)
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{"module_" + name + "_from_platform_is_not_allowed_in_the_apex_boot_jars_list"})
+ } else {
+ ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name)
+ }
}
} else {
// TODO(b/177892522): Treat this as an error.
@@ -284,7 +298,8 @@
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) bootDexJarByModule {
+func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module,
+ fragments []android.Module, libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) bootDexJarByModule {
createEmptyHiddenApiFiles := func() {
paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
for _, path := range paths {
@@ -311,7 +326,7 @@
}
// Construct a list of ClasspathElement objects from the modules and fragments.
- classpathElements := CreateClasspathElements(ctx, modules, fragments)
+ classpathElements := CreateClasspathElements(ctx, modules, fragments, libraryToApex, apexNameToFragment)
monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, classpathElements)
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 7fa6ddb..727e306 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -27,21 +27,27 @@
)
func TestPlatformBootclasspath(t *testing.T) {
+ t.Parallel()
preparer := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
FixtureConfigureBootJars("platform:foo", "system_ext:bar"),
+ android.FixtureMergeMockFs(android.MockFS{
+ "api/current.txt": nil,
+ "api/removed.txt": nil,
+ }),
android.FixtureWithRootAndroidBp(`
platform_bootclasspath {
name: "platform-bootclasspath",
}
- java_library {
+ java_sdk_library {
name: "bar",
srcs: ["a.java"],
system_modules: "none",
sdk_version: "none",
compile_dex: true,
system_ext_specific: true,
+ unsafe_ignore_missing_latest_api: true,
}
`),
)
@@ -76,6 +82,7 @@
`)
t.Run("missing", func(t *testing.T) {
+ t.Parallel()
preparer.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"platform-bootclasspath" depends on undefined module "foo"`)).
RunTest(t)
@@ -86,11 +93,12 @@
checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
- srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar")
+ srcjar := result.ModuleForTests(t, name, "android_common").Output(name + "-transitive.srcjar")
android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar")
android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings())
}
t.Run("source", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
preparer,
addSourceBootclassPathModule,
@@ -107,6 +115,7 @@
})
t.Run("prebuilt", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
preparer,
addPrebuiltBootclassPathModule,
@@ -123,6 +132,7 @@
})
t.Run("source+prebuilt - source preferred", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
preparer,
addSourceBootclassPathModule,
@@ -140,6 +150,7 @@
})
t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
preparer,
addSourceBootclassPathModule,
@@ -157,6 +168,7 @@
})
t.Run("dex import", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
preparer,
android.FixtureAddTextFile("deximport/Android.bp", `
@@ -179,6 +191,7 @@
}
func TestPlatformBootclasspathVariant(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
android.FixtureWithRootAndroidBp(`
@@ -193,6 +206,7 @@
}
func TestPlatformBootclasspath_ClasspathFragmentPaths(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
android.FixtureWithRootAndroidBp(`
@@ -204,10 +218,11 @@
p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
android.AssertStringEquals(t, "output filepath", "bootclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base())
- android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install filepath", "out/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
}
func TestPlatformBootclasspathModule_AndroidMkEntries(t *testing.T) {
+ t.Parallel()
preparer := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
android.FixtureWithRootAndroidBp(`
@@ -218,6 +233,7 @@
)
t.Run("AndroidMkEntries", func(t *testing.T) {
+ t.Parallel()
result := preparer.RunTest(t)
p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
@@ -227,6 +243,7 @@
})
t.Run("hiddenapi-flags-entry", func(t *testing.T) {
+ t.Parallel()
result := preparer.RunTest(t)
p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
@@ -238,6 +255,7 @@
})
t.Run("classpath-fragment-entry", func(t *testing.T) {
+ t.Parallel()
result := preparer.RunTest(t)
want := map[string][]string{
@@ -262,6 +280,7 @@
}
func TestPlatformBootclasspath_Dist(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
FixtureConfigureBootJars("platform:foo", "platform:bar"),
@@ -305,6 +324,7 @@
}
func TestPlatformBootclasspath_HiddenAPIMonolithicFiles(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
hiddenApiFixtureFactory,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -347,7 +367,7 @@
// Make sure that the foo-hiddenapi-annotations.jar is included in the inputs to the rules that
// creates the index.csv file.
- platformBootclasspath := result.ModuleForTests("myplatform-bootclasspath", "android_common")
+ platformBootclasspath := result.ModuleForTests(t, "myplatform-bootclasspath", "android_common")
var rule android.TestingBuildParams
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 5b145c6..d2ec8bd 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -43,6 +43,13 @@
ctx.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
}
+type PlatformCompatConfigInfo struct {
+ CompatConfig android.OutputPath
+ SubDir string
+}
+
+var PlatformCompatConfigInfoProvider = blueprint.NewProvider[PlatformCompatConfigInfo]()
+
var PrepareForTestWithPlatformCompatConfig = android.FixtureRegisterWithContext(registerPlatformCompatConfigBuildComponents)
func platformCompatConfigPath(ctx android.PathContext) android.OutputPath {
@@ -51,6 +58,10 @@
type platformCompatConfigProperties struct {
Src *string `android:"path"`
+
+ // If true, we include it in the "merged" XML (merged_compat_config.xml).
+ // Default is true.
+ Include_in_merged_xml *bool
}
type platformCompatConfig struct {
@@ -60,6 +71,7 @@
installDirPath android.InstallPath
configFile android.OutputPath
metadataFile android.OutputPath
+ doMerge bool
installConfigFile android.InstallPath
}
@@ -68,6 +80,10 @@
return p.metadataFile
}
+func (p *platformCompatConfig) includeInMergedXml() bool {
+ return p.doMerge
+}
+
func (p *platformCompatConfig) CompatConfig() android.OutputPath {
return p.configFile
}
@@ -78,8 +94,19 @@
type platformCompatConfigMetadataProvider interface {
compatConfigMetadata() android.Path
+
+ // Whether to include it in the "merged" XML (merged_compat_config.xml) or not.
+ includeInMergedXml() bool
}
+type PlatformCompatConfigMetadataInfo struct {
+ CompatConfigMetadata android.Path
+ // Whether to include it in the "merged" XML (merged_compat_config.xml) or not.
+ IncludeInMergedXml bool
+}
+
+var PlatformCompatConfigMetadataInfoProvider = blueprint.NewProvider[PlatformCompatConfigMetadataInfo]()
+
type PlatformCompatConfigIntf interface {
android.Module
@@ -98,6 +125,7 @@
metadataFileName := p.Name() + "_meta.xml"
p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath
p.metadataFile = android.PathForModuleOut(ctx, metadataFileName).OutputPath
+ p.doMerge = proptools.BoolDefault(p.properties.Include_in_merged_xml, true)
path := android.PathForModuleSrc(ctx, String(p.properties.Src))
rule.Command().
@@ -111,6 +139,16 @@
rule.Build(configFileName, "Extract compat/compat_config.xml and install it")
ctx.InstallFile(p.installDirPath, p.configFile.Base(), p.configFile)
ctx.SetOutputFiles(android.Paths{p.configFile}, "")
+
+ android.SetProvider(ctx, PlatformCompatConfigInfoProvider, PlatformCompatConfigInfo{
+ CompatConfig: p.CompatConfig(),
+ SubDir: p.SubDir(),
+ })
+
+ android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{
+ CompatConfigMetadata: p.compatConfigMetadata(),
+ IncludeInMergedXml: p.includeInMergedXml(),
+ })
}
func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
@@ -201,6 +239,10 @@
return module.metadataFile
}
+func (module *prebuiltCompatConfigModule) includeInMergedXml() bool {
+ return true // Always include in merged.xml
+}
+
func (module *prebuiltCompatConfigModule) BaseModuleName() string {
return proptools.StringDefault(module.properties.Source_module_name, module.ModuleBase.Name())
}
@@ -209,6 +251,11 @@
func (module *prebuiltCompatConfigModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.metadataFile = module.prebuilt.SingleSourcePath(ctx)
+
+ android.SetProvider(ctx, PlatformCompatConfigMetadataInfoProvider, PlatformCompatConfigMetadataInfo{
+ CompatConfigMetadata: module.compatConfigMetadata(),
+ IncludeInMergedXml: module.includeInMergedXml(),
+ })
}
// A prebuilt version of platform_compat_config that provides the metadata.
@@ -229,15 +276,18 @@
var compatConfigMetadata android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
- if c, ok := module.(platformCompatConfigMetadataProvider); ok {
- if !android.IsModulePreferred(module) {
+ if c, ok := android.OtherModuleProvider(ctx, module, PlatformCompatConfigMetadataInfoProvider); ok {
+ if !android.IsModulePreferredProxy(ctx, module) {
return
}
- metadata := c.compatConfigMetadata()
+ if !c.IncludeInMergedXml {
+ return
+ }
+ metadata := c.CompatConfigMetadata
compatConfigMetadata = append(compatConfigMetadata, metadata)
}
})
@@ -258,12 +308,7 @@
rule.Build("merged-compat-config", "Merge compat config")
p.metadata = outputPath
-}
-
-func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) {
- if p.metadata != nil {
- ctx.DistForGoal("droidcore", p.metadata)
- }
+ ctx.DistForGoal("droidcore", p.metadata)
}
func platformCompatConfigSingletonFactory() android.Singleton {
diff --git a/java/platform_compat_config_test.go b/java/platform_compat_config_test.go
index 80d991c..72f81e0 100644
--- a/java/platform_compat_config_test.go
+++ b/java/platform_compat_config_test.go
@@ -21,11 +21,13 @@
)
func TestPlatformCompatConfig(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithPlatformCompatConfig,
android.FixtureWithRootAndroidBp(`
platform_compat_config {
name: "myconfig2",
+ include_in_merged_xml: false,
}
platform_compat_config {
name: "myconfig1",
@@ -38,7 +40,6 @@
CheckMergedCompatConfigInputs(t, result, "myconfig",
"out/soong/.intermediates/myconfig1/myconfig1_meta.xml",
- "out/soong/.intermediates/myconfig2/myconfig2_meta.xml",
"out/soong/.intermediates/myconfig3/myconfig3_meta.xml",
)
}
diff --git a/java/plugin.go b/java/plugin.go
index 610c9fd..3534c7b 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -16,8 +16,21 @@
import (
"android/soong/android"
+ "github.com/google/blueprint"
)
+type JavaPluginInfo struct {
+ ProcessorClass *string
+ GeneratesApi bool
+}
+
+var JavaPluginInfoProvider = blueprint.NewProvider[JavaPluginInfo]()
+
+type KotlinPluginInfo struct {
+}
+
+var KotlinPluginInfoProvider = blueprint.NewProvider[KotlinPluginInfo]()
+
func init() {
registerJavaPluginBuildComponents(android.InitRegistrationContext)
}
@@ -65,7 +78,22 @@
Generates_api *bool
}
+func (p *Plugin) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.Library.GenerateAndroidBuildActions(ctx)
+
+ android.SetProvider(ctx, JavaPluginInfoProvider, JavaPluginInfo{
+ ProcessorClass: p.pluginProperties.Processor_class,
+ GeneratesApi: Bool(p.pluginProperties.Generates_api),
+ })
+}
+
// Plugin describes a kotlin_plugin module, a host java/kotlin library that will be used by kotlinc as a compiler plugin.
type KotlinPlugin struct {
Library
}
+
+func (p *KotlinPlugin) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.Library.GenerateAndroidBuildActions(ctx)
+
+ android.SetProvider(ctx, KotlinPluginInfoProvider, KotlinPluginInfo{})
+}
diff --git a/java/plugin_test.go b/java/plugin_test.go
index dc29b1c..007b74a 100644
--- a/java/plugin_test.go
+++ b/java/plugin_test.go
@@ -19,6 +19,7 @@
)
func TestNoPlugin(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -26,8 +27,8 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
+ turbine := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("turbine")
if turbine.Rule == nil {
t.Errorf("expected turbine to be enabled")
@@ -43,6 +44,7 @@
}
func TestPlugin(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -59,14 +61,14 @@
buildOS := ctx.Config().BuildOS.String()
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
+ turbine := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("turbine")
if turbine.Rule == nil {
t.Errorf("expected turbine to be enabled")
}
- bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+ bar := ctx.ModuleForTests(t, "bar", buildOS+"_common").Rule("javac").Output.String()
if !inList(bar, javac.Implicits.Strings()) {
t.Errorf("foo implicits %v does not contain %q", javac.Implicits.Strings(), bar)
@@ -82,6 +84,7 @@
}
func TestPluginGeneratesApi(t *testing.T) {
+ t.Parallel()
ctx, _ := testJava(t, `
java_library {
name: "foo",
@@ -99,14 +102,14 @@
buildOS := ctx.Config().BuildOS.String()
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine")
+ javac := ctx.ModuleForTests(t, "foo", "android_common").Rule("javac")
+ turbine := ctx.ModuleForTests(t, "foo", "android_common").MaybeRule("turbine")
if turbine.Rule != nil {
t.Errorf("expected turbine to be disabled")
}
- bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+ bar := ctx.ModuleForTests(t, "bar", buildOS+"_common").Rule("javac").Output.String()
if !inList(bar, javac.Implicits.Strings()) {
t.Errorf("foo implicits %v does not contain %q", javac.Implicits.Strings(), bar)
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 527e479..31f149e 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -55,11 +55,6 @@
// If set to true, compile dex for java_import modules. Defaults to false.
Imports_compile_dex *bool
-
- // If set to true, allow incremental platform API of the form MM.m where MM is the major release
- // version corresponding to the API level/SDK_INT and m is an incremental release version
- // (e.g. API changes associated with QPR). Defaults to false.
- Allow_incremental_platform_api *bool
}
type prebuiltApis struct {
@@ -97,28 +92,28 @@
}
// parseFinalizedPrebuiltPath is like parsePrebuiltPath, but verifies the version is numeric (a finalized version).
-func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string, allowIncremental bool) (module string, version int, release int, scope string) {
+func parseFinalizedPrebuiltPath(ctx android.LoadHookContext, p string) (module string, version int, release int, scope string) {
module, v, scope := parsePrebuiltPath(ctx, p)
- if allowIncremental {
- parts := strings.Split(v, ".")
- if len(parts) != 2 {
- ctx.ModuleErrorf("Found unexpected version '%v' for incremental prebuilts - expect MM.m format for incremental API with both major (MM) an minor (m) revision.", v)
- return
- }
+
+ // assume a major.minor version code
+ parts := strings.Split(v, ".")
+ if len(parts) == 2 {
sdk, sdk_err := strconv.Atoi(parts[0])
qpr, qpr_err := strconv.Atoi(parts[1])
if sdk_err != nil || qpr_err != nil {
- ctx.ModuleErrorf("Unable to read version number for incremental prebuilt api '%v'", v)
+ ctx.ModuleErrorf("Unable to read major.minor version for prebuilt api '%v'", v)
return
}
version = sdk
release = qpr
return
}
+
+ // assume a legacy integer only api level
release = 0
version, err := strconv.Atoi(v)
if err != nil {
- ctx.ModuleErrorf("Found finalized API files in non-numeric dir '%v'", v)
+ ctx.ModuleErrorf("Unable to read API level for prebuilt api '%v'", v)
return
}
return
@@ -279,12 +274,11 @@
}
// Create modules for all (<module>, <scope, <version>) triplets,
- allowIncremental := proptools.BoolDefault(p.properties.Allow_incremental_platform_api, false)
for _, f := range apiLevelFiles {
- module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f, allowIncremental)
- if allowIncremental {
- incrementalVersion := strconv.Itoa(version) + "." + strconv.Itoa(release)
- createApiModule(mctx, PrebuiltApiModuleName(module, scope, incrementalVersion), f)
+ module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f)
+ if release != 0 {
+ majorDotMinorVersion := strconv.Itoa(version) + "." + strconv.Itoa(release)
+ createApiModule(mctx, PrebuiltApiModuleName(module, scope, majorDotMinorVersion), f)
} else {
createApiModule(mctx, PrebuiltApiModuleName(module, scope, strconv.Itoa(version)), f)
}
@@ -300,7 +294,7 @@
getLatest := func(files []string, isExtensionApiFile bool) map[string]latestApiInfo {
m := make(map[string]latestApiInfo)
for _, f := range files {
- module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f, allowIncremental)
+ module, version, release, scope := parseFinalizedPrebuiltPath(mctx, f)
if strings.HasSuffix(module, "incompatibilities") {
continue
}
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index b6fb2c6..17fdae9 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -29,6 +29,7 @@
}
func TestPrebuiltApis_SystemModulesCreation(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
FixtureWithPrebuiltApis(map[string][]string{
@@ -61,6 +62,7 @@
}
func TestPrebuiltApis_WithExtensions(t *testing.T) {
+ t.Parallel()
runTestWithBaseExtensionLevel := func(v int) (foo_input, bar_input, baz_input string) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
@@ -76,9 +78,9 @@
"2": {"foo", "bar"},
}),
).RunTest(t)
- foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String()
- bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String()
- baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String()
+ foo_input = result.ModuleForTests(t, "foo.api.public.latest", "").Rule("generator").Implicits[0].String()
+ bar_input = result.ModuleForTests(t, "bar.api.public.latest", "").Rule("generator").Implicits[0].String()
+ baz_input = result.ModuleForTests(t, "baz.api.public.latest", "").Rule("generator").Implicits[0].String()
return
}
// Extension 2 is the latest for both foo and bar, finalized after the base extension version.
@@ -100,25 +102,26 @@
android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
}
-func TestPrebuiltApis_WithIncrementalApi(t *testing.T) {
+func TestPrebuiltApis_WithMixedVersionCodes(t *testing.T) {
+ t.Parallel()
runTestWithIncrementalApi := func() (foo_input, bar_input, baz_input string) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
- FixtureWithPrebuiltIncrementalApis(map[string][]string{
+ FixtureWithPrebuiltApis(map[string][]string{
"33.0": {"foo"},
- "33.1": {"foo", "bar", "baz"},
- "33.2": {"foo", "bar"},
+ "34": {"foo", "bar", "baz"},
+ "34.1": {"foo", "bar"},
"current": {"foo", "bar"},
}),
).RunTest(t)
- foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String()
- bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String()
- baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String()
+ foo_input = result.ModuleForTests(t, "foo.api.public.latest", "").Rule("generator").Implicits[0].String()
+ bar_input = result.ModuleForTests(t, "bar.api.public.latest", "").Rule("generator").Implicits[0].String()
+ baz_input = result.ModuleForTests(t, "baz.api.public.latest", "").Rule("generator").Implicits[0].String()
return
}
- // 33.1 is the latest for baz, 33.2 is the latest for both foo & bar
+ // 34 is the latest for baz, 34.1 is the latest for both foo & bar
foo_input, bar_input, baz_input := runTestWithIncrementalApi()
- android.AssertStringEquals(t, "Expected latest foo = api level 33.2", "prebuilts/sdk/33.2/public/api/foo.txt", foo_input)
- android.AssertStringEquals(t, "Expected latest bar = api level 33.2", "prebuilts/sdk/33.2/public/api/bar.txt", bar_input)
- android.AssertStringEquals(t, "Expected latest baz = api level 33.1", "prebuilts/sdk/33.1/public/api/baz.txt", baz_input)
+ android.AssertStringEquals(t, "Expected latest foo = api level 34.1", "prebuilts/sdk/34.1/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = api level 34.1", "prebuilts/sdk/34.1/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 34", "prebuilts/sdk/34/public/api/baz.txt", baz_input)
}
diff --git a/java/proto_test.go b/java/proto_test.go
index d1cb714..3fbe3e6 100644
--- a/java/proto_test.go
+++ b/java/proto_test.go
@@ -28,6 +28,7 @@
`
func TestProtoStream(t *testing.T) {
+ t.Parallel()
bp := `
java_library {
name: "java-stream-protos",
@@ -45,7 +46,7 @@
PrepareForIntegrationTestWithJava,
).RunTestWithBp(t, protoModules+bp)
- proto0 := ctx.ModuleForTests("java-stream-protos", "android_common").Output("proto/proto0.srcjar")
+ proto0 := ctx.ModuleForTests(t, "java-stream-protos", "android_common").Output("proto/proto0.srcjar")
if cmd := proto0.RuleParams.Command; !strings.Contains(cmd, "--javastream_out=") {
t.Errorf("expected '--javastream_out' in %q", cmd)
diff --git a/java/ravenwood.go b/java/ravenwood.go
index 4c43a9f..a942dc6 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -110,13 +110,15 @@
module.AddProperties(&module.testProperties, &module.ravenwoodTestProperties)
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
module.testProperties.Test_suites = []string{
"general-tests",
"ravenwood-tests",
}
module.testProperties.Test_options.Unit_test = proptools.BoolPtr(false)
+ module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
+ module.Module.sourceProperties.Top_level_test_target = true
InitJavaModule(module, android.DeviceSupported)
android.InitDefaultableModule(module)
@@ -185,26 +187,24 @@
// All JNI libraries included in the runtime
var runtimeJniModuleNames map[string]bool
- if utils := ctx.GetDirectDepsWithTag(ravenwoodUtilsTag)[0]; utils != nil {
- for _, installFile := range android.OtherModuleProviderOrDefault(
- ctx, utils, android.InstallFilesProvider).InstallFiles {
- installDeps = append(installDeps, installFile)
- }
- jniDeps, ok := android.OtherModuleProvider(ctx, utils, ravenwoodLibgroupJniDepProvider)
- if ok {
- runtimeJniModuleNames = jniDeps.names
- }
+ utils := ctx.GetDirectDepsProxyWithTag(ravenwoodUtilsTag)[0]
+ for _, installFile := range android.OtherModuleProviderOrDefault(
+ ctx, utils, android.InstallFilesProvider).InstallFiles {
+ installDeps = append(installDeps, installFile)
+ }
+ jniDeps, ok := android.OtherModuleProvider(ctx, utils, ravenwoodLibgroupJniDepProvider)
+ if ok {
+ runtimeJniModuleNames = jniDeps.names
}
- if runtime := ctx.GetDirectDepsWithTag(ravenwoodRuntimeTag)[0]; runtime != nil {
- for _, installFile := range android.OtherModuleProviderOrDefault(
- ctx, runtime, android.InstallFilesProvider).InstallFiles {
- installDeps = append(installDeps, installFile)
- }
- jniDeps, ok := android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider)
- if ok {
- runtimeJniModuleNames = jniDeps.names
- }
+ runtime := ctx.GetDirectDepsProxyWithTag(ravenwoodRuntimeTag)[0]
+ for _, installFile := range android.OtherModuleProviderOrDefault(
+ ctx, runtime, android.InstallFilesProvider).InstallFiles {
+ installDeps = append(installDeps, installFile)
+ }
+ jniDeps, ok = android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider)
+ if ok {
+ runtimeJniModuleNames = jniDeps.names
}
// Also remember what JNI libs are in the runtime.
@@ -228,7 +228,7 @@
resApkInstallPath := installPath.Join(ctx, "ravenwood-res-apks")
copyResApk := func(tag blueprint.DependencyTag, toFileName string) {
- if resApk := ctx.GetDirectDepsWithTag(tag); len(resApk) > 0 {
+ if resApk := ctx.GetDirectDepsProxyWithTag(tag); len(resApk) > 0 {
installFile := android.OutputFileForModule(ctx, resApk[0], "")
installResApk := ctx.InstallFile(resApkInstallPath, toFileName, installFile)
installDeps = append(installDeps, installResApk)
@@ -260,6 +260,19 @@
// Install our JAR with all dependencies
ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ if _, ok := r.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ if r.testConfig != nil {
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, r.testConfig.String())
+ }
+ moduleInfoJSON.CompatibilitySuites = []string{"general-tests", "ravenwood-tests"}
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: r.TestSuites(),
+ })
}
func (r *ravenwoodTest) AndroidMkEntries() []android.AndroidMkEntries {
@@ -345,7 +358,7 @@
// Install our runtime into expected location for packaging
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
for _, lib := range r.ravenwoodLibgroupProperties.Libs {
- libModule := ctx.GetDirectDepWithTag(lib, ravenwoodLibContentTag)
+ libModule := ctx.GetDirectDepProxyWithTag(lib, ravenwoodLibContentTag)
if libModule == nil {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{lib})
@@ -377,6 +390,10 @@
// Normal build should perform install steps
ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: r.TestSuites(),
+ })
}
// collectTransitiveJniDeps returns all JNI dependencies, including transitive
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
index 6394a9a..d6493bc 100644
--- a/java/ravenwood_test.go
+++ b/java/ravenwood_test.go
@@ -100,9 +100,10 @@
`),
)
-var installPathPrefix = "out/soong/host/linux-x86/testcases"
+var installPathPrefix = "out/host/linux-x86/testcases"
func TestRavenwoodRuntime(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("requires linux")
}
@@ -120,7 +121,7 @@
CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-utils", "android_common", "framework-rules.ravenwood")
// Verify that we've emitted artifacts in expected location
- runtime := ctx.ModuleForTests("ravenwood-runtime", "android_common")
+ runtime := ctx.ModuleForTests(t, "ravenwood-runtime", "android_common")
runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-minus-apex.ravenwood.jar")
runtime.Output(installPathPrefix + "/ravenwood-runtime/framework-services.ravenwood.jar")
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni1.so")
@@ -128,11 +129,12 @@
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
runtime.Output(installPathPrefix + "/ravenwood-runtime/ravenwood-data/app1.apk")
runtime.Output(installPathPrefix + "/ravenwood-runtime/fonts/Font.ttf")
- utils := ctx.ModuleForTests("ravenwood-utils", "android_common")
+ utils := ctx.ModuleForTests(t, "ravenwood-utils", "android_common")
utils.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
}
func TestRavenwoodTest(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("requires linux")
}
@@ -191,7 +193,7 @@
CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "ravenwood-utils")
CheckModuleHasDependency(t, ctx.TestContext, "ravenwood-test", "android_common", "jni-lib")
- module := ctx.ModuleForTests("ravenwood-test", "android_common")
+ module := ctx.ModuleForTests(t, "ravenwood-test", "android_common")
classpath := module.Rule("javac").Args["classpath"]
// Verify that we're linking against test_current
@@ -212,7 +214,7 @@
module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-res.apk")
module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-inst-res.apk")
- module = ctx.ModuleForTests("ravenwood-test-empty", "android_common")
+ module = ctx.ModuleForTests(t, "ravenwood-test-empty", "android_common")
module.Output(installPathPrefix + "/ravenwood-test-empty/ravenwood.properties")
// ravenwood-runtime*.so are included in the runtime, so it shouldn't be emitted.
@@ -228,4 +230,15 @@
android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/libred.so")
android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-runtime/lib64/ravenwood-runtime-jni3.so")
android.AssertStringListContains(t, "orderOnly", orderOnly, installPathPrefix+"/ravenwood-utils/framework-rules.ravenwood.jar")
+
+ // Ensure they are listed as "test" modules for code coverage
+ expectedTestOnlyModules := []string{
+ "ravenwood-test",
+ "ravenwood-test-empty",
+ }
+ expectedTopLevelTests := []string{
+ "ravenwood-test",
+ "ravenwood-test-empty",
+ }
+ assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests)
}
diff --git a/java/robolectric.go b/java/robolectric.go
index 5f46267..1d204a4 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -21,6 +21,7 @@
"android/soong/java/config"
"android/soong/tradefed"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -28,6 +29,23 @@
RegisterRobolectricBuildComponents(android.InitRegistrationContext)
}
+type RobolectricRuntimesInfo struct {
+ Runtimes []android.InstallPath
+}
+
+var RobolectricRuntimesInfoProvider = blueprint.NewProvider[RobolectricRuntimesInfo]()
+
+type roboRuntimeOnlyDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var roboRuntimeOnlyDepTag roboRuntimeOnlyDependencyTag
+
+// Mark this tag so dependencies that use it are excluded from visibility enforcement.
+func (t roboRuntimeOnlyDependencyTag) ExcludeFromVisibilityEnforcement() {}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = roboRuntimeOnlyDepTag
+
func RegisterRobolectricBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_robolectric_test", RobolectricTestFactory)
ctx.RegisterModuleType("android_robolectric_runtimes", robolectricRuntimesFactory)
@@ -41,12 +59,12 @@
}
const robolectricCurrentLib = "Robolectric_all-target"
+const clearcutJunitLib = "ClearcutJunitListenerAar"
const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
var (
roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
roboRuntimesTag = dependencyTag{name: "roboRuntimes"}
- roboRuntimeOnlyTag = dependencyTag{name: "roboRuntimeOnlyTag"}
)
type robolectricProperties struct {
@@ -64,10 +82,6 @@
Shards *int64
}
- // The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
- // instead of the one built from source in external/robolectric-shadows.
- Robolectric_prebuilt_version *string
-
// Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectric
// to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
Upstream *bool
@@ -106,21 +120,12 @@
ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
}
- if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
- ctx.AddVariationDependencies(nil, staticLibTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
- } else if !proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
- if proptools.Bool(r.robolectricProperties.Upstream) {
- ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib+"_upstream")
- } else {
- ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib)
- }
- }
+ ctx.AddVariationDependencies(nil, roboRuntimeOnlyDepTag, clearcutJunitLib)
if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
- ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream")
+ ctx.AddVariationDependencies(nil, roboRuntimeOnlyDepTag, robolectricCurrentLib)
} else {
- // opting out from strict mode, robolectric_non_strict_mode_permission lib should be added
- ctx.AddVariationDependencies(nil, staticLibTag, "robolectric_non_strict_mode_permission")
+ ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib)
}
ctx.AddVariationDependencies(nil, staticLibTag, robolectricDefaultLibs...)
@@ -139,39 +144,54 @@
r.forceOSType = ctx.Config().BuildOS
r.forceArchType = ctx.Config().BuildArch
+ var extraTestRunnerOptions []tradefed.Option
+ extraTestRunnerOptions = append(extraTestRunnerOptions, tradefed.Option{Name: "java-flags", Value: "-Drobolectric=true"})
+ if proptools.BoolDefault(r.robolectricProperties.Strict_mode, true) {
+ extraTestRunnerOptions = append(extraTestRunnerOptions, tradefed.Option{Name: "java-flags", Value: "-Drobolectric.strict.mode=true"})
+ }
+
+ var extraOptions []tradefed.Option
+ var javaHome = ctx.Config().Getenv("ANDROID_JAVA_HOME")
+ extraOptions = append(extraOptions, tradefed.Option{Name: "java-folder", Value: javaHome})
+
r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
- TestConfigProp: r.testProperties.Test_config,
- TestConfigTemplateProp: r.testProperties.Test_config_template,
- TestSuites: r.testProperties.Test_suites,
- AutoGenConfig: r.testProperties.Auto_gen_config,
- DeviceTemplate: "${RobolectricTestConfigTemplate}",
- HostTemplate: "${RobolectricTestConfigTemplate}",
+ TestConfigProp: r.testProperties.Test_config,
+ TestConfigTemplateProp: r.testProperties.Test_config_template,
+ TestSuites: r.testProperties.Test_suites,
+ OptionsForAutogenerated: extraOptions,
+ TestRunnerOptions: extraTestRunnerOptions,
+ AutoGenConfig: r.testProperties.Auto_gen_config,
+ DeviceTemplate: "${RobolectricTestConfigTemplate}",
+ HostTemplate: "${RobolectricTestConfigTemplate}",
})
r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data)
r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...)
r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_data)...)
r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_prefer32_data)...)
+ r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Host_common_data)...)
var ok bool
- var instrumentedApp *AndroidApp
+ var instrumentedApp *JavaInfo
+ var appInfo *AppInfo
// TODO: this inserts paths to built files into the test, it should really be inserting the contents.
- instrumented := ctx.GetDirectDepsWithTag(instrumentationForTag)
+ instrumented := ctx.GetDirectDepsProxyWithTag(instrumentationForTag)
if len(instrumented) == 1 {
- instrumentedApp, ok = instrumented[0].(*AndroidApp)
+ appInfo, ok = android.OtherModuleProvider(ctx, instrumented[0], AppInfoProvider)
if !ok {
ctx.PropertyErrorf("instrumentation_for", "dependency must be an android_app")
}
+ instrumentedApp = android.OtherModuleProviderOrDefault(ctx, instrumented[0], JavaInfoProvider)
} else if !ctx.Config().AllowMissingDependencies() {
panic(fmt.Errorf("expected exactly 1 instrumented dependency, got %d", len(instrumented)))
}
var resourceApk android.Path
var manifest android.Path
- if instrumentedApp != nil {
- manifest = instrumentedApp.mergedManifestFile
- resourceApk = instrumentedApp.outputFile
+ if appInfo != nil {
+ manifest = appInfo.MergedManifestFile
+ resourceApk = instrumentedApp.OutputFile
}
roboTestConfigJar := android.PathForModuleOut(ctx, "robolectric_samedir", "samedir_config.jar")
@@ -179,7 +199,7 @@
extraCombinedJars := android.Paths{roboTestConfigJar}
- handleLibDeps := func(dep android.Module) {
+ handleLibDeps := func(dep android.ModuleProxy) {
if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
if m, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
extraCombinedJars = append(extraCombinedJars, m.ImplementationAndResourcesJars...)
@@ -187,25 +207,25 @@
}
}
- for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(libTag) {
handleLibDeps(dep)
}
- for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(sdkLibTag) {
handleLibDeps(dep)
}
// handle the runtimeOnly tag for strict_mode
- for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) {
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(roboRuntimeOnlyDepTag) {
handleLibDeps(dep)
}
- if instrumentedApp != nil {
- extraCombinedJars = append(extraCombinedJars, instrumentedApp.implementationAndResourcesJar)
+ if appInfo != nil {
+ extraCombinedJars = append(extraCombinedJars, instrumentedApp.ImplementationAndResourcesJars...)
}
r.stem = proptools.StringDefault(r.overridableProperties.Stem, ctx.ModuleName())
r.classLoaderContexts = r.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
r.dexpreopter.disableDexpreopt()
- r.compile(ctx, nil, nil, nil, extraCombinedJars)
+ javaInfo := r.compile(ctx, nil, nil, nil, extraCombinedJars)
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
var installDeps android.InstallPaths
@@ -227,8 +247,8 @@
installDeps = append(installDeps, installedResourceApk)
}
- runtimes := ctx.GetDirectDepWithTag("robolectric-android-all-prebuilts", roboRuntimesTag)
- for _, runtime := range runtimes.(*robolectricRuntimes).runtimes {
+ runtimes := ctx.GetDirectDepProxyWithTag("robolectric-android-all-prebuilts", roboRuntimesTag)
+ for _, runtime := range android.OtherModuleProviderOrDefault(ctx, runtimes, RobolectricRuntimesInfoProvider).Runtimes {
installDeps = append(installDeps, runtime)
}
@@ -242,6 +262,33 @@
}
r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
+
+ if javaInfo != nil {
+ setExtraJavaInfo(ctx, r, javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+ }
+
+ moduleInfoJSON := r.javaLibraryModuleInfoJSON(ctx)
+ if _, ok := r.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ if r.testConfig != nil {
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, r.testConfig.String())
+ }
+ if len(r.testProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, r.testProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: r.TestSuites(),
+ })
+
+ android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
+ TestOnly: Bool(r.sourceProperties.Test_only),
+ TopLevelTarget: r.sourceProperties.Top_level_test_target,
+ })
}
func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) {
@@ -292,8 +339,9 @@
&module.testProperties)
module.Module.dexpreopter.isTest = true
- module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
-
+ module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)
+ module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
+ module.Module.sourceProperties.Top_level_test_target = true
module.testProperties.Test_suites = []string{"robolectric-tests"}
InitJavaModule(module, android.DeviceSupported)
@@ -357,7 +405,7 @@
}
if !ctx.Config().AlwaysUsePrebuiltSdks() && r.props.Lib != nil {
- runtimeFromSourceModule := ctx.GetDirectDepWithTag(String(r.props.Lib), libTag)
+ runtimeFromSourceModule := ctx.GetDirectDepProxyWithTag(String(r.props.Lib), libTag)
if runtimeFromSourceModule == nil {
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{String(r.props.Lib)})
@@ -375,6 +423,14 @@
installedRuntime := ctx.InstallFile(androidAllDir, runtimeName, runtimeFromSourceJar)
r.runtimes = append(r.runtimes, installedRuntime)
}
+
+ android.SetProvider(ctx, RobolectricRuntimesInfoProvider, RobolectricRuntimesInfo{
+ Runtimes: r.runtimes,
+ })
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: r.TestSuites(),
+ })
}
func (r *robolectricRuntimes) InstallInTestcases() bool { return true }
diff --git a/java/robolectric_test.go b/java/robolectric_test.go
index 4775bac..cc16c6a 100644
--- a/java/robolectric_test.go
+++ b/java/robolectric_test.go
@@ -32,6 +32,11 @@
}
java_library {
+ name: "Robolectric_all-target",
+ srcs: ["Robo.java"]
+ }
+
+ java_library {
name: "mockito-robolectric-prebuilt",
srcs: ["Mockito.java"]
}
@@ -44,6 +49,12 @@
java_library {
name: "junitxml",
srcs: ["JUnitXml.java"]
+
+ }
+
+ java_library {
+ name: "ClearcutJunitListenerAar",
+ srcs: ["Runtime.java"]
}
java_library_host {
@@ -60,6 +71,7 @@
)
func TestRobolectricJniTest(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("requires linux")
}
@@ -93,6 +105,17 @@
CheckModuleHasDependency(t, ctx.TestContext, "robo-test", "android_common", "jni-lib1")
// Check that the .so files make it into the output.
- module := ctx.ModuleForTests("robo-test", "android_common")
+ module := ctx.ModuleForTests(t, "robo-test", "android_common")
module.Output(installPathPrefix + "/robo-test/lib64/jni-lib1.so")
+
+ // Ensure they are listed as "test" modules for code coverage
+ expectedTestOnlyModules := []string{
+ "robo-test",
+ }
+
+ expectedTopLevelTests := []string{
+ "robo-test",
+ }
+ assertTestOnlyAndTopLevel(t, ctx, expectedTestOnlyModules, expectedTopLevelTests)
+
}
diff --git a/java/rro.go b/java/rro.go
index ab4fafa..4ae8d7f 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -34,6 +34,15 @@
ctx.RegisterModuleType("override_runtime_resource_overlay", OverrideRuntimeResourceOverlayModuleFactory)
}
+type RuntimeResourceOverlayInfo struct {
+ OutputFile android.Path
+ Certificate Certificate
+ Theme string
+ OverriddenManifestPackageName string
+}
+
+var RuntimeResourceOverlayInfoProvider = blueprint.NewProvider[RuntimeResourceOverlayInfo]()
+
type RuntimeResourceOverlay struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -90,15 +99,6 @@
Overrides []string
}
-// RuntimeResourceOverlayModule interface is used by the apex package to gather information from
-// a RuntimeResourceOverlay module.
-type RuntimeResourceOverlayModule interface {
- android.Module
- OutputFile() android.Path
- Certificate() Certificate
- Theme() string
-}
-
// RRO's partition logic is different from the partition logic of other modules defined in soong/android/paths.go
// The default partition for RRO is "/product" and not "/system"
func rroPartition(ctx android.ModuleContext) string {
@@ -139,6 +139,25 @@
r.aapt.hasNoCode = true
// Do not remove resources without default values nor dedupe resource configurations with the same value
aaptLinkFlags := []string{"--no-resource-deduping", "--no-resource-removal"}
+
+ // Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
+ hasProduct := android.PrefixInList(r.aaptProperties.Aaptflags, "--product")
+ if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
+ aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
+ }
+
+ if !Bool(r.aaptProperties.Aapt_include_all_resources) {
+ // Product AAPT config
+ for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
+ aaptLinkFlags = append(aaptLinkFlags, "-c", aaptConfig)
+ }
+
+ // Product AAPT preferred config
+ if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
+ aaptLinkFlags = append(aaptLinkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
+ }
+ }
+
// Allow the override of "package name" and "overlay target package name"
manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
if overridden || r.overridableProperties.Package_name != nil {
@@ -187,6 +206,16 @@
android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
AconfigTextFiles: aconfigTextFilePaths,
})
+
+ android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{
+ OutputFile: r.outputFile,
+ Certificate: r.Certificate(),
+ Theme: r.Theme(),
+ })
+
+ ctx.SetOutputFiles([]android.Path{r.outputFile}, "")
+
+ buildComplianceMetadata(ctx)
}
func (r *RuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
@@ -216,10 +245,6 @@
return r.certificate
}
-func (r *RuntimeResourceOverlay) OutputFile() android.Path {
- return r.outputFile
-}
-
func (r *RuntimeResourceOverlay) Theme() string {
return String(r.properties.Theme)
}
@@ -370,10 +395,11 @@
a.aapt.buildActions(ctx,
aaptBuildActionOptions{
- sdkContext: a,
- extraLinkFlags: aaptLinkFlags,
- rroDirs: &rroDirs,
- manifestForAapt: genManifest,
+ sdkContext: a,
+ extraLinkFlags: aaptLinkFlags,
+ rroDirs: &rroDirs,
+ manifestForAapt: genManifest,
+ aconfigTextFiles: getAconfigFilePaths(ctx),
},
)
@@ -390,6 +416,11 @@
// Install the signed apk
installDir := android.PathForModuleInstall(ctx, "overlay")
ctx.InstallFile(installDir, signed.Base(), signed)
+
+ android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{
+ OutputFile: signed,
+ Certificate: a.certificate,
+ })
}
func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
diff --git a/java/rro_test.go b/java/rro_test.go
index 4d58bb4..3e4fed5 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -24,6 +24,7 @@
)
func TestRuntimeResourceOverlay(t *testing.T) {
+ t.Parallel()
fs := android.MockFS{
"baz/res/res/values/strings.xml": nil,
"bar/res/res/values/strings.xml": nil,
@@ -66,7 +67,7 @@
fs.AddToFixture(),
).RunTestWithBp(t, bp)
- m := result.ModuleForTests("foo", "android_common")
+ m := result.ModuleForTests(t, "foo", "android_common")
// Check AAPT2 link flags.
aapt2Flags := m.Output("package-res.apk").Args["flags"]
@@ -115,7 +116,7 @@
android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
// A themed module has a different device location
- m = result.ModuleForTests("foo_themed", "android_common")
+ m = result.ModuleForTests(t, "foo_themed", "android_common")
androidMkEntries = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0]
path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay/faza")}
@@ -129,6 +130,7 @@
}
func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureModifyConfig(android.SetKatiEnabledForTests),
@@ -153,7 +155,7 @@
//
// RRO module with defaults
//
- m := result.ModuleForTests("foo_with_defaults", "android_common")
+ m := result.ModuleForTests(t, "foo_with_defaults", "android_common")
// Check AAPT2 link flags.
aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ")
@@ -171,7 +173,7 @@
//
// RRO module without defaults
//
- m = result.ModuleForTests("foo_barebones", "android_common")
+ m = result.ModuleForTests(t, "foo_barebones", "android_common")
// Check AAPT2 link flags.
aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ")
@@ -216,7 +218,7 @@
}{
{
variantName: "android_common",
- apkPath: "out/soong/target/product/test_device/product/overlay/foo_overlay.apk",
+ apkPath: "out/target/product/test_device/product/overlay/foo_overlay.apk",
overrides: nil,
targetVariant: "android_common",
packageFlag: "",
@@ -224,7 +226,7 @@
},
{
variantName: "android_common_bar_overlay",
- apkPath: "out/soong/target/product/test_device/product/overlay/bar_overlay.apk",
+ apkPath: "out/target/product/test_device/product/overlay/bar_overlay.apk",
overrides: []string{"foo_overlay"},
targetVariant: "android_common_bar",
packageFlag: "com.android.bar.overlay",
@@ -233,7 +235,7 @@
},
}
for _, expected := range expectedVariants {
- variant := ctx.ModuleForTests("foo_overlay", expected.variantName)
+ variant := ctx.ModuleForTests(t, "foo_overlay", expected.variantName)
// Check the final apk name
variant.Output(expected.apkPath)
@@ -283,28 +285,28 @@
}{
{
name: "device_specific",
- expectedPath: "out/soong/target/product/test_device/odm/overlay",
+ expectedPath: "out/target/product/test_device/odm/overlay",
},
{
name: "soc_specific",
- expectedPath: "out/soong/target/product/test_device/vendor/overlay",
+ expectedPath: "out/target/product/test_device/vendor/overlay",
},
{
name: "system_ext_specific",
- expectedPath: "out/soong/target/product/test_device/system_ext/overlay",
+ expectedPath: "out/target/product/test_device/system_ext/overlay",
},
{
name: "product_specific",
- expectedPath: "out/soong/target/product/test_device/product/overlay",
+ expectedPath: "out/target/product/test_device/product/overlay",
},
{
name: "default",
- expectedPath: "out/soong/target/product/test_device/product/overlay",
+ expectedPath: "out/target/product/test_device/product/overlay",
},
}
for _, testCase := range testCases {
ctx, _ := testJava(t, bp)
- mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*RuntimeResourceOverlay)
+ mod := ctx.ModuleForTests(t, testCase.name, "android_common").Module().(*RuntimeResourceOverlay)
android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir)
}
}
@@ -339,7 +341,7 @@
}
`)
- foo := result.ModuleForTests("foo", "android_common")
+ foo := result.ModuleForTests(t, "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,
@@ -356,3 +358,21 @@
"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
)
}
+
+func TestCanBeDataOfTest(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ ).RunTestWithBp(t, `
+ runtime_resource_overlay {
+ name: "foo",
+ sdk_version: "current",
+ }
+ android_test {
+ name: "bar",
+ data: [
+ ":foo",
+ ],
+ }
+ `)
+ // Just test that this doesn't get errors
+}
diff --git a/java/sdk.go b/java/sdk.go
index 407fdcf..1dbea3b 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -276,7 +276,7 @@
func createFrameworkAidl(stubsModules []string, path android.WritablePath, ctx android.SingletonContext) *android.RuleBuilder {
stubsJars := make([]android.Paths, len(stubsModules))
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
// Collect dex jar paths for the modules listed above.
if j, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
name := ctx.ModuleName(module)
@@ -360,7 +360,7 @@
"api_fingerprint",
}
count := 0
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
name := ctx.ModuleName(module)
if android.InList(name, apiTxtFileModules) {
cmd.Inputs(android.OutputFilesForModule(ctx, module, ""))
@@ -383,6 +383,10 @@
}
rule.Build("api_fingerprint", "generate api_fingerprint.txt")
+
+ if ctx.Config().BuildOS.Linux() {
+ ctx.DistForGoals([]string{"sdk", "droidcore"}, out)
+ }
}
func sdkMakeVars(ctx android.MakeVarsContext) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 7891776..00ba8b2 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -316,6 +316,15 @@
return name
}
+func (scopes apiScopes) matchingScopeFromSdkKind(kind android.SdkKind) *apiScope {
+ for _, scope := range scopes {
+ if scope.kind == kind {
+ return scope
+ }
+ }
+ return nil
+}
+
var (
scopeByName = make(map[string]*apiScope)
allScopeNames []string
@@ -480,6 +489,9 @@
// Extra libs used when compiling stubs for this scope.
Libs []string
+
+ // Name to override the api_surface that is passed down to droidstubs.
+ Api_surface *string
}
type sdkLibraryProperties struct {
@@ -690,9 +702,9 @@
paths.stubsHeaderPath = lib.HeaderJars
paths.stubsImplPath = lib.ImplementationJars
- libDep := dep.(UsesLibraryDependency)
- paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
- paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider)
+ paths.stubsDexJarPath = libDep.DexJarBuildPath
+ paths.exportableStubsDexJarPath = libDep.DexJarBuildPath
return nil
} else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
@@ -706,8 +718,8 @@
paths.stubsImplPath = lib.ImplementationJars
}
- libDep := dep.(UsesLibraryDependency)
- paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider)
+ paths.stubsDexJarPath = libDep.DexJarBuildPath
return nil
} else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
@@ -720,58 +732,67 @@
paths.stubsImplPath = lib.ImplementationJars
}
- libDep := dep.(UsesLibraryDependency)
- paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ libDep := android.OtherModuleProviderOrDefault(ctx, dep, JavaInfoProvider)
+ paths.exportableStubsDexJarPath = libDep.DexJarBuildPath
return nil
} else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
}
}
-func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider) error) error {
- if apiStubsProvider, ok := dep.(ApiStubsProvider); ok {
- err := action(apiStubsProvider)
+func (paths *scopePaths) treatDepAsApiStubsProvider(ctx android.ModuleContext, dep android.Module,
+ action func(*DroidStubsInfo, *StubsSrcInfo) error) error {
+ apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, DroidStubsInfoProvider)
+ if !ok {
+ return fmt.Errorf("expected module that provides DroidStubsInfo, e.g. droidstubs")
+ }
+
+ apiStubsSrcProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider)
+ if !ok {
+ return fmt.Errorf("expected module that provides StubsSrcInfo, e.g. droidstubs")
+ }
+ return action(&apiStubsProvider, &apiStubsSrcProvider)
+}
+
+func (paths *scopePaths) treatDepAsApiStubsSrcProvider(
+ ctx android.ModuleContext, dep android.Module, action func(provider *StubsSrcInfo) error) error {
+ if apiStubsProvider, ok := android.OtherModuleProvider(ctx, dep, StubsSrcInfoProvider); ok {
+ err := action(&apiStubsProvider)
if err != nil {
return err
}
return nil
} else {
- return fmt.Errorf("expected module that implements ExportableApiStubsSrcProvider, e.g. droidstubs")
+ return fmt.Errorf("expected module that provides DroidStubsInfo, e.g. droidstubs")
}
}
-func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider) error) error {
- if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok {
- err := action(apiStubsProvider)
- if err != nil {
- return err
- }
- return nil
- } else {
- return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs")
+func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider *DroidStubsInfo, stubsType StubsType) error {
+ var currentApiFilePathErr, removedApiFilePathErr error
+ info, err := getStubsInfoForType(provider, stubsType)
+ if err != nil {
+ return err
}
-}
-
-func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider, stubsType StubsType) error {
- var annotationsZip, currentApiFilePath, removedApiFilePath android.Path
- annotationsZip, annotationsZipErr := provider.AnnotationsZip(stubsType)
- currentApiFilePath, currentApiFilePathErr := provider.ApiFilePath(stubsType)
- removedApiFilePath, removedApiFilePathErr := provider.RemovedApiFilePath(stubsType)
-
- combinedError := errors.Join(annotationsZipErr, currentApiFilePathErr, removedApiFilePathErr)
+ if info.ApiFile == nil {
+ currentApiFilePathErr = fmt.Errorf("expected module that provides ApiFile")
+ }
+ if info.RemovedApiFile == nil {
+ removedApiFilePathErr = fmt.Errorf("expected module that provides RemovedApiFile")
+ }
+ combinedError := errors.Join(currentApiFilePathErr, removedApiFilePathErr)
if combinedError == nil {
- paths.annotationsZip = android.OptionalPathForPath(annotationsZip)
- paths.currentApiFilePath = android.OptionalPathForPath(currentApiFilePath)
- paths.removedApiFilePath = android.OptionalPathForPath(removedApiFilePath)
+ paths.annotationsZip = android.OptionalPathForPath(info.AnnotationsZip)
+ paths.currentApiFilePath = android.OptionalPathForPath(info.ApiFile)
+ paths.removedApiFilePath = android.OptionalPathForPath(info.RemovedApiFile)
}
return combinedError
}
-func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider, stubsType StubsType) error {
- stubsSrcJar, err := provider.StubsSrcJar(stubsType)
+func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider *StubsSrcInfo, stubsType StubsType) error {
+ path, err := getStubsSrcInfoForType(provider, stubsType)
if err == nil {
- paths.stubsSrcJar = android.OptionalPathForPath(stubsSrcJar)
+ paths.stubsSrcJar = android.OptionalPathForPath(path)
}
return err
}
@@ -781,7 +802,7 @@
if ctx.Config().ReleaseHiddenApiExportableStubs() {
stubsType = Exportable
}
- return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) error {
+ return paths.treatDepAsApiStubsSrcProvider(ctx, dep, func(provider *StubsSrcInfo) error {
return paths.extractStubsSourceInfoFromApiStubsProviders(provider, stubsType)
})
}
@@ -791,17 +812,17 @@
if ctx.Config().ReleaseHiddenApiExportableStubs() {
stubsType = Exportable
}
- return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
- extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, stubsType)
- extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, stubsType)
+ return paths.treatDepAsApiStubsProvider(ctx, dep, func(apiStubsProvider *DroidStubsInfo, apiStubsSrcProvider *StubsSrcInfo) error {
+ extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(apiStubsProvider, stubsType)
+ extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(apiStubsSrcProvider, stubsType)
return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr)
})
}
-func extractOutputPaths(dep android.Module) (android.Paths, error) {
+func extractOutputPaths(ctx android.ModuleContext, dep android.Module) (android.Paths, error) {
var paths android.Paths
- if sourceFileProducer, ok := dep.(android.SourceFileProducer); ok {
- paths = sourceFileProducer.Srcs()
+ if sourceFileProducer, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok {
+ paths = sourceFileProducer.Srcs
return paths, nil
} else {
return nil, fmt.Errorf("module %q does not produce source files", dep)
@@ -809,17 +830,47 @@
}
func (paths *scopePaths) extractLatestApiPath(ctx android.ModuleContext, dep android.Module) error {
- outputPaths, err := extractOutputPaths(dep)
+ outputPaths, err := extractOutputPaths(ctx, dep)
paths.latestApiPaths = outputPaths
return err
}
func (paths *scopePaths) extractLatestRemovedApiPath(ctx android.ModuleContext, dep android.Module) error {
- outputPaths, err := extractOutputPaths(dep)
+ outputPaths, err := extractOutputPaths(ctx, dep)
paths.latestRemovedApiPaths = outputPaths
return err
}
+func getStubsInfoForType(info *DroidStubsInfo, stubsType StubsType) (ret *StubsInfo, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = &info.EverythingStubsInfo, nil
+ case Exportable:
+ ret, err = &info.ExportableStubsInfo, nil
+ default:
+ ret, err = nil, fmt.Errorf("stubs info not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs info is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func getStubsSrcInfoForType(info *StubsSrcInfo, stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = info.EverythingStubsSrcJar, nil
+ case Exportable:
+ ret, err = info.ExportableStubsSrcJar, nil
+ default:
+ ret, err = nil, fmt.Errorf("stubs src info not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs src info is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
type commonToSdkLibraryAndImportProperties struct {
// Specifies whether this module can be used as an Android shared library; defaults
// to true.
@@ -880,6 +931,8 @@
RootLibraryName() string
}
+var _ android.ApexModule = (*SdkLibrary)(nil)
+
func (m *SdkLibrary) RootLibraryName() string {
return m.BaseModuleName()
}
@@ -908,9 +961,9 @@
// This is non-empty only when api_only is false.
implLibraryHeaderJars android.Paths
- // The reference to the implementation library created by the source module.
- // Is nil if the source module does not exist.
- implLibraryModule *Library
+ // The reference to the JavaInfo provided by implementation library created by
+ // the source module. Is nil if the source module does not exist.
+ implLibraryInfo *JavaInfo
}
func (c *commonToSdkLibraryAndImport) initCommon(module commonSdkLibraryAndImportModule) {
@@ -1170,6 +1223,8 @@
// Whether if this can be used as a shared library.
SharedLibrary bool
+
+ Prebuilt bool
}
var SdkLibraryInfoProvider = blueprint.NewProvider[SdkLibraryInfo]()
@@ -1200,7 +1255,8 @@
commonToSdkLibraryAndImport
- builtInstalledForApex []dexpreopterInstall
+ apexSystemServerDexpreoptInstalls []DexpreopterInstall
+ apexSystemServerDexJars android.Paths
}
func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
@@ -1211,16 +1267,16 @@
// To satisfy the UsesLibraryDependency interface
func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
- if module.implLibraryModule != nil {
- return module.implLibraryModule.DexJarBuildPath(ctx)
+ if module.implLibraryInfo != nil {
+ return module.implLibraryInfo.DexJarFile
}
return makeUnsetDexJarPath()
}
// To satisfy the UsesLibraryDependency interface
func (module *SdkLibrary) DexJarInstallPath() android.Path {
- if module.implLibraryModule != nil {
- return module.implLibraryModule.DexJarInstallPath()
+ if module.implLibraryInfo != nil {
+ return module.implLibraryInfo.InstallFile
}
return nil
}
@@ -1281,10 +1337,10 @@
func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) {
android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.BaseModuleContext, do android.PayloadDepsCallback) {
- ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
- isExternal := !module.depIsInSameApex(ctx, child)
- if am, ok := child.(android.ApexModule); ok {
- if !do(ctx, parent, am, isExternal) {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ isExternal := !android.IsDepInSameApex(ctx, module, child)
+ if am, ok := android.OtherModuleProvider(ctx, child, android.CommonModuleInfoProvider); ok && am.IsApexModule {
+ if !do(ctx, parent, child, isExternal) {
return false
}
}
@@ -1407,11 +1463,11 @@
// Collate the components exported by this module. All scope specific modules are exported but
// the impl and xml component modules are not.
exportedComponents := map[string]struct{}{}
-
+ var implLib android.ModuleProxy
// Record the paths to the header jars of the library (stubs and impl).
// When this java_sdk_library is depended upon from others via "libs" property,
// the recorded paths will be returned depending on the link type of the caller.
- ctx.VisitDirectDeps(func(to android.Module) {
+ ctx.VisitDirectDepsProxy(func(to android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(to)
// Extract information from any of the scope specific dependencies.
@@ -1431,7 +1487,8 @@
if tag == implLibraryTag {
if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...)
- module.implLibraryModule = to.(*Library)
+ module.implLibraryInfo = dep
+ implLib = to
}
}
})
@@ -1442,44 +1499,44 @@
module.hideApexVariantFromMake = true
}
- if module.implLibraryModule != nil {
+ if module.implLibraryInfo != nil {
if ctx.Device() {
- module.classesJarPaths = android.Paths{module.implLibraryModule.implementationJarFile}
- module.bootDexJarPath = module.implLibraryModule.bootDexJarPath
- module.uncompressDexState = module.implLibraryModule.uncompressDexState
- module.active = module.implLibraryModule.active
+ module.classesJarPaths = module.implLibraryInfo.ImplementationJars
+ module.bootDexJarPath = module.implLibraryInfo.BootDexJarPath
+ module.uncompressDexState = module.implLibraryInfo.UncompressDexState
+ module.active = module.implLibraryInfo.Active
}
- module.outputFile = module.implLibraryModule.outputFile
- module.dexJarFile = makeDexJarPathFromPath(module.implLibraryModule.dexJarFile.Path())
- module.headerJarFile = module.implLibraryModule.headerJarFile
- module.implementationAndResourcesJar = module.implLibraryModule.implementationAndResourcesJar
- module.builtInstalledForApex = module.implLibraryModule.builtInstalledForApex
- module.dexpreopter.configPath = module.implLibraryModule.dexpreopter.configPath
- module.dexpreopter.outputProfilePathOnHost = module.implLibraryModule.dexpreopter.outputProfilePathOnHost
+ module.outputFile = module.implLibraryInfo.OutputFile
+ module.dexJarFile = makeDexJarPathFromPath(module.implLibraryInfo.DexJarFile.Path())
+ module.headerJarFile = module.implLibraryInfo.HeaderJars[0]
+ module.implementationAndResourcesJar = module.implLibraryInfo.ImplementationAndResourcesJars[0]
+ module.apexSystemServerDexpreoptInstalls = module.implLibraryInfo.DexpreopterInfo.ApexSystemServerDexpreoptInstalls
+ module.apexSystemServerDexJars = module.implLibraryInfo.DexpreopterInfo.ApexSystemServerDexJars
+ module.dexpreopter.configPath = module.implLibraryInfo.ConfigPath
+ module.dexpreopter.outputProfilePathOnHost = module.implLibraryInfo.DexpreopterInfo.OutputProfilePathOnHost
// Properties required for Library.AndroidMkEntries
- module.logtagsSrcs = module.implLibraryModule.logtagsSrcs
- module.dexpreopter.builtInstalled = module.implLibraryModule.dexpreopter.builtInstalled
- module.jacocoReportClassesFile = module.implLibraryModule.jacocoReportClassesFile
- module.dexer.proguardDictionary = module.implLibraryModule.dexer.proguardDictionary
- module.dexer.proguardUsageZip = module.implLibraryModule.dexer.proguardUsageZip
- module.linter.reports = module.implLibraryModule.linter.reports
+ module.logtagsSrcs = module.implLibraryInfo.LogtagsSrcs
+ module.dexpreopter.builtInstalled = module.implLibraryInfo.BuiltInstalled
+ module.jacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile
+ module.dexer.proguardDictionary = module.implLibraryInfo.ProguardDictionary
+ module.dexer.proguardUsageZip = module.implLibraryInfo.ProguardUsageZip
+ module.linter.reports = module.implLibraryInfo.LinterReports
- if lintInfo, ok := android.OtherModuleProvider(ctx, module.implLibraryModule, LintProvider); ok {
+ if lintInfo, ok := android.OtherModuleProvider(ctx, implLib, LintProvider); ok {
android.SetProvider(ctx, LintProvider, lintInfo)
}
if !module.Host() {
- module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile
+ module.hostdexInstallFile = module.implLibraryInfo.HostdexInstallFile
}
- if installFilesInfo, ok := android.OtherModuleProvider(ctx, module.implLibraryModule, android.InstallFilesProvider); ok {
+ if installFilesInfo, ok := android.OtherModuleProvider(ctx, implLib, android.InstallFilesProvider); ok {
if installFilesInfo.CheckbuildTarget != nil {
ctx.CheckbuildFile(installFilesInfo.CheckbuildTarget)
}
}
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()})
}
// Make the set of components exported by this module available for use elsewhere.
@@ -1518,17 +1575,39 @@
}
}
- if module.requiresRuntimeImplementationLibrary() && module.implLibraryModule != nil {
+ if module.requiresRuntimeImplementationLibrary() && module.implLibraryInfo != nil {
generatingLibs = append(generatingLibs, module.implLibraryModuleName())
- setOutputFiles(ctx, module.implLibraryModule.Module)
+ setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo)
}
+ javaInfo := &JavaInfo{
+ JacocoReportClassesFile: module.jacocoReportClassesFile,
+ }
+ setExtraJavaInfo(ctx, ctx.Module(), javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+
sdkLibInfo.GeneratingLibs = generatingLibs
+ sdkLibInfo.Prebuilt = false
android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo)
}
-func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
- return module.builtInstalledForApex
+func setOutputFilesFromJavaInfo(ctx android.ModuleContext, info *JavaInfo) {
+ ctx.SetOutputFiles(append(android.PathsIfNonNil(info.OutputFile), info.ExtraOutputFiles...), "")
+ ctx.SetOutputFiles(android.PathsIfNonNil(info.OutputFile), android.DefaultDistTag)
+ ctx.SetOutputFiles(info.ImplementationAndResourcesJars, ".jar")
+ ctx.SetOutputFiles(info.HeaderJars, ".hjar")
+ if info.ProguardDictionary.Valid() {
+ ctx.SetOutputFiles(android.Paths{info.ProguardDictionary.Path()}, ".proguard_map")
+ }
+ ctx.SetOutputFiles(info.GeneratedSrcjars, ".generated_srcjars")
+}
+
+func (module *SdkLibrary) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall {
+ return module.apexSystemServerDexpreoptInstalls
+}
+
+func (module *SdkLibrary) ApexSystemServerDexJars() android.Paths {
+ return module.apexSystemServerDexJars
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
@@ -1636,15 +1715,22 @@
}
// Implements android.ApexModule
-func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
- depTag := mctx.OtherModuleDependencyTag(dep)
- if depTag == xmlPermissionsFileTag {
+func (m *SdkLibrary) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return SdkLibraryDepInSameApexChecker{}
+}
+
+type SdkLibraryDepInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m SdkLibraryDepInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ if tag == xmlPermissionsFileTag {
return true
}
- if dep.Name() == module.implLibraryModuleName() {
+ if tag == implLibraryTag {
return true
}
- return module.Library.DepIsInSameApex(mctx, dep)
+ return depIsInSameApex(tag)
}
// Implements android.ApexModule
@@ -1901,10 +1987,6 @@
commonToSdkLibraryAndImport
- // The reference to the xml permissions module created by the source module.
- // Is nil if the source module does not exist.
- xmlPermissionsFileModule *sdkLibraryXml
-
// Build path to the dex implementation jar obtained from the prebuilt_apex, if any.
dexJarFile OptionalDexJarPath
dexJarFileErr error
@@ -2059,9 +2141,16 @@
var _ android.ApexModule = (*SdkLibraryImport)(nil)
// Implements android.ApexModule
-func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
- depTag := mctx.OtherModuleDependencyTag(dep)
- if depTag == xmlPermissionsFileTag {
+func (m *SdkLibraryImport) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return SdkLibraryImportDepIsInSameApexChecker{}
+}
+
+type SdkLibraryImportDepIsInSameApexChecker struct {
+ android.BaseDepInSameApexChecker
+}
+
+func (m SdkLibraryImportDepIsInSameApexChecker) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ if tag == xmlPermissionsFileTag {
return true
}
@@ -2071,13 +2160,10 @@
}
// Implements android.ApexModule
-func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // we don't check prebuilt modules for sdk_version
- return nil
+func (m *SdkLibraryImport) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
-// Implements android.ApexModule
func (module *SdkLibraryImport) UniqueApexVariations() bool {
return module.uniqueApexVariations()
}
@@ -2094,7 +2180,7 @@
module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar")
// Record the paths to the prebuilt stubs library and stubs source.
- ctx.VisitDirectDeps(func(to android.Module) {
+ ctx.VisitDirectDepsProxy(func(to android.ModuleProxy) {
tag := ctx.OtherModuleDependencyTag(to)
// Extract information from any of the scope specific dependencies.
@@ -2106,17 +2192,11 @@
// is determined by the nature of the dependency which is determined by the tag.
scopeTag.extractDepInfo(ctx, to, scopePaths)
} else if tag == implLibraryTag {
- if implLibrary, ok := to.(*Library); ok {
- module.implLibraryModule = implLibrary
+ if implInfo, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
+ module.implLibraryInfo = implInfo
} else {
ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to)
}
- } else if tag == xmlPermissionsFileTag {
- if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok {
- module.xmlPermissionsFileModule = xmlPermissionsFileModule
- } else {
- ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
- }
}
})
sdkLibInfo := module.generateCommonBuildActions(ctx)
@@ -2156,12 +2236,21 @@
}
module.setOutputFiles(ctx)
- if module.implLibraryModule != nil {
+ if module.implLibraryInfo != nil {
generatingLibs = append(generatingLibs, module.implLibraryModuleName())
- setOutputFiles(ctx, module.implLibraryModule.Module)
+ setOutputFilesFromJavaInfo(ctx, module.implLibraryInfo)
}
+ javaInfo := &JavaInfo{}
+ if module.implLibraryInfo != nil {
+ javaInfo.JacocoReportClassesFile = module.implLibraryInfo.JacocoReportClassesFile
+ }
+
+ setExtraJavaInfo(ctx, ctx.Module(), javaInfo)
+ android.SetProvider(ctx, JavaInfoProvider, javaInfo)
+
sdkLibInfo.GeneratingLibs = generatingLibs
+ sdkLibInfo.Prebuilt = true
android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo)
}
@@ -2177,10 +2266,10 @@
if module.dexJarFile.IsSet() {
return module.dexJarFile
}
- if module.implLibraryModule == nil {
+ if module.implLibraryInfo == nil {
return makeUnsetDexJarPath()
} else {
- return module.implLibraryModule.DexJarBuildPath(ctx)
+ return module.implLibraryInfo.DexJarFile
}
}
@@ -2196,10 +2285,10 @@
// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
- if module.implLibraryModule == nil {
+ if module.implLibraryInfo == nil {
return nil
} else {
- return module.implLibraryModule.JacocoReportClassesFile()
+ return module.implLibraryInfo.JacocoReportClassesFile
}
}
@@ -2212,19 +2301,19 @@
// to satisfy java.ApexDependency interface
func (module *SdkLibraryImport) HeaderJars() android.Paths {
- if module.implLibraryModule == nil {
+ if module.implLibraryInfo == nil {
return nil
} else {
- return module.implLibraryModule.HeaderJars()
+ return module.implLibraryInfo.HeaderJars
}
}
// to satisfy java.ApexDependency interface
func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths {
- if module.implLibraryModule == nil {
+ if module.implLibraryInfo == nil {
return nil
} else {
- return module.implLibraryModule.ImplementationAndResourcesJars()
+ return module.implLibraryInfo.ImplementationAndResourcesJars
}
}
@@ -2389,8 +2478,7 @@
s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
- implLibrary := sdk.implLibraryModule
- if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
+ if sdk.implLibraryInfo != nil && sdk.implLibraryInfo.ProfileGuided {
s.DexPreoptProfileGuided = proptools.BoolPtr(true)
}
}
diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go
index 768e57a..f5feabe 100644
--- a/java/sdk_library_internal.go
+++ b/java/sdk_library_internal.go
@@ -15,12 +15,13 @@
package java
import (
- "android/soong/android"
- "android/soong/etc"
"fmt"
"path"
"strings"
+ "android/soong/android"
+ "android/soong/etc"
+
"github.com/google/blueprint/proptools"
)
@@ -173,6 +174,20 @@
mctx.CreateModule(LibraryFactory, properties...)
}
+// getApiSurfaceForScope returns the api surface name to use for the apiScope. If one is specified
+// in the corresponding ApiScopeProperties.Api_surface property that is used, otherwise the name of
+// the apiScope is used.
+func (module *SdkLibrary) getApiSurfaceForScope(apiScope *apiScope) *string {
+ scopeProperties := module.scopeToProperties[apiScope]
+
+ apiSurface := scopeProperties.Api_surface
+ if apiSurface == nil {
+ apiSurface = &apiScope.name
+ }
+
+ return apiSurface
+}
+
// Creates the [Droidstubs] module with ".stubs.source.<[apiScope.name]>" that creates stubs
// source files from the given full source files and also updates and checks the API
// specification files (i.e. "*-current.txt", "*-removed.txt" files).
@@ -226,7 +241,7 @@
props.Srcs = append(props.Srcs, module.properties.Srcs...)
props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...)
props.Sdk_version = module.deviceProperties.Sdk_version
- props.Api_surface = &apiScope.name
+ props.Api_surface = module.getApiSurfaceForScope(apiScope)
props.System_modules = module.deviceProperties.System_modules
props.Installable = proptools.BoolPtr(false)
// A droiddoc module has only one Libs property and doesn't distinguish between
@@ -778,7 +793,11 @@
// from android.ApexModule
func (module *sdkLibraryXml) AvailableFor(what string) bool {
- return true
+ return android.CheckAvailableForApex(what, module.ApexAvailableFor())
+}
+
+func (module *sdkLibraryXml) ApexAvailableFor() []string {
+ return []string{android.AvailableToPlatform, android.AvailableToAnyApex}
}
func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -788,10 +807,8 @@
var _ android.ApexModule = (*sdkLibraryXml)(nil)
// Implements android.ApexModule
-func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
- return nil
+func (m *sdkLibraryXml) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
// File path to the runtime implementation library
@@ -919,6 +936,8 @@
ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
+
+ etc.SetCommonPrebuiltEtcInfo(ctx, module)
}
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 6031d72..6d27e54 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -25,6 +25,7 @@
)
func TestJavaSdkLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -114,19 +115,19 @@
`)
// check the existence of the internal modules
- foo := result.ModuleForTests("foo", "android_common")
- result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "")
- result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common")
- result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
- result.ModuleForTests("foo.api.public.28", "")
- result.ModuleForTests("foo.api.system.28", "")
- result.ModuleForTests("foo.api.test.28", "")
+ foo := result.ModuleForTests(t, "foo", "android_common")
+ result.ModuleForTests(t, apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(t, apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(t, apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(t, apiScopePublic.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests(t, apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests(t, apiScopeTest.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests(t, apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "")
+ result.ModuleForTests(t, apiScopePublic.apiLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(t, "foo"+sdkXmlFileSuffix, "android_common")
+ result.ModuleForTests(t, "foo.api.public.28", "")
+ result.ModuleForTests(t, "foo.api.system.28", "")
+ result.ModuleForTests(t, "foo.api.test.28", "")
exportedComponentsInfo, _ := android.OtherModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
expectedFooExportedComponents := []string{
@@ -146,28 +147,28 @@
}
android.AssertArrayString(t, "foo exported components", expectedFooExportedComponents, exportedComponentsInfo.Components)
- bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
+ bazJavac := result.ModuleForTests(t, "baz", "android_common").Rule("javac")
// tests if baz is actually linked to the stubs lib
- android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar")
+ android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.from-text.jar")
// ... and not to the impl lib
android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.jar")
// test if baz is not linked to the system variant of foo
android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.jar")
- bazTestJavac := result.ModuleForTests("baz-test", "android_common").Rule("javac")
+ bazTestJavac := result.ModuleForTests(t, "baz-test", "android_common").Rule("javac")
// tests if baz-test is actually linked to the test stubs lib
- android.AssertStringDoesContain(t, "baz-test javac classpath", bazTestJavac.Args["classpath"], "foo.stubs.test.jar")
+ android.AssertStringDoesContain(t, "baz-test javac classpath", bazTestJavac.Args["classpath"], "foo.stubs.test.from-text.jar")
- baz29Javac := result.ModuleForTests("baz-29", "android_common").Rule("javac")
+ baz29Javac := result.ModuleForTests(t, "baz-29", "android_common").Rule("javac")
// tests if baz-29 is actually linked to the system 29 stubs lib
- android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/sdk_system_29_foo/android_common/combined/sdk_system_29_foo.jar")
+ android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/sdk_system_29_foo/android_common/local-combined/sdk_system_29_foo.jar")
- bazModule30Javac := result.ModuleForTests("baz-module-30", "android_common").Rule("javac")
+ bazModule30Javac := result.ModuleForTests(t, "baz-module-30", "android_common").Rule("javac")
// tests if "baz-module-30" is actually linked to the module 30 stubs lib
- android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/sdk_module-lib_30_foo/android_common/combined/sdk_module-lib_30_foo.jar")
+ android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/sdk_module-lib_30_foo/android_common/local-combined/sdk_module-lib_30_foo.jar")
// test if baz has exported SDK lib names foo and bar to qux
- qux := result.ModuleForTests("qux", "android_common")
+ qux := result.ModuleForTests(t, "qux", "android_common")
if quxLib, ok := qux.Module().(*Library); ok {
requiredSdkLibs, optionalSdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
android.AssertDeepEquals(t, "qux exports (required)", []string{"fred", "quuz", "foo", "bar"}, requiredSdkLibs)
@@ -175,18 +176,19 @@
}
// test if quuz have created the api_contribution module
- result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
+ result.ModuleForTests(t, apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
- fooImplDexJar := result.ModuleForTests("foo.impl", "android_common").Rule("d8")
+ fooImplDexJar := result.ModuleForTests(t, "foo.impl", "android_common").Rule("d8")
// tests if kotlinc generated files are NOT excluded from output of foo.impl.
android.AssertStringDoesNotContain(t, "foo.impl dex", fooImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
- barImplDexJar := result.ModuleForTests("bar.impl", "android_common").Rule("d8")
+ barImplDexJar := result.ModuleForTests(t, "bar.impl", "android_common").Rule("d8")
// tests if kotlinc generated files are excluded from output of bar.impl.
android.AssertStringDoesContain(t, "bar.impl dex", barImplDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
}
func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -218,7 +220,7 @@
`)
// test that updatability attributes are passed on correctly
- fooUpdatable := result.ModuleForTests("fooUpdatable.xml", "android_common").Output("fooUpdatable.xml")
+ fooUpdatable := result.ModuleForTests(t, "fooUpdatable.xml", "android_common").Output("fooUpdatable.xml")
fooUpdatableContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooUpdatable)
android.AssertStringDoesContain(t, "fooUpdatable.xml contents", fooUpdatableContents, `on-bootclasspath-since="U"`)
android.AssertStringDoesContain(t, "fooUpdatable.xml contents", fooUpdatableContents, `on-bootclasspath-before="V"`)
@@ -227,7 +229,7 @@
// double check that updatability attributes are not written if they don't exist in the bp file
// the permissions file for the foo library defined above
- fooPermissions := result.ModuleForTests("foo.xml", "android_common").Output("foo.xml")
+ fooPermissions := result.ModuleForTests(t, "foo.xml", "android_common").Output("foo.xml")
fooPermissionsContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooPermissions)
android.AssertStringDoesNotContain(t, "foo.xml contents", fooPermissionsContents, `on-bootclasspath-since`)
android.AssertStringDoesNotContain(t, "foo.xml contents", fooPermissionsContents, `on-bootclasspath-before`)
@@ -236,6 +238,7 @@
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -263,6 +266,7 @@
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_AtLeastTAttributes(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -292,6 +296,7 @@
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdk(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -319,6 +324,7 @@
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdkAndModuleMinSdk(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -347,6 +353,7 @@
}
func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -363,13 +370,14 @@
}
`)
// test that updatability attributes are passed on correctly
- fooUpdatable := result.ModuleForTests("foo.xml", "android_common").Output("foo.xml")
+ fooUpdatable := result.ModuleForTests(t, "foo.xml", "android_common").Output("foo.xml")
fooUpdatableContents := android.ContentFromFileRuleForTests(t, result.TestContext, fooUpdatable)
android.AssertStringDoesContain(t, "foo.xml contents", fooUpdatableContents, `<apex-library`)
android.AssertStringDoesNotContain(t, "foo.xml contents", fooUpdatableContents, `<library`)
}
func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -409,12 +417,12 @@
{lib: "stub-only-static-lib", in_stub_combined: true},
}
verify := func(sdklib, dep string, cp, combined bool) {
- sdklibCp := result.ModuleForTests(sdklib, "android_common").Rule("javac").Args["classpath"]
+ sdklibCp := result.ModuleForTests(t, sdklib, "android_common").Rule("javac").Args["classpath"]
expected := cp || combined // Every combined jar is also on the classpath.
android.AssertStringContainsEquals(t, "bad classpath for "+sdklib, sdklibCp, "/"+dep+".jar", expected)
- combineJarInputs := result.ModuleForTests(sdklib, "android_common").Rule("combineJar").Inputs.Strings()
- depPath := filepath.Join("out", "soong", ".intermediates", dep, "android_common", "turbine-combined", dep+".jar")
+ combineJarInputs := result.ModuleForTests(t, sdklib, "android_common").Rule("combineJar").Inputs.Strings()
+ depPath := filepath.Join("out", "soong", ".intermediates", dep, "android_common", "turbine", dep+".jar")
android.AssertStringListContainsEquals(t, "bad combined inputs for "+sdklib, combineJarInputs, depPath, combined)
}
for _, expectation := range expectations {
@@ -426,6 +434,7 @@
}
func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -448,13 +457,14 @@
`)
// The bar library should depend on the stubs jar.
- barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ barLibrary := result.ModuleForTests(t, "bar", "android_common").Rule("javac")
+ if expected, actual := `^-classpath .*:out/soong/[^:]*/foo\.stubs\.from-text/foo\.stubs\.from-text\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
func TestJavaSdkLibrary_AccessOutputFiles(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -478,12 +488,13 @@
}
func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".public.annotations.zip"`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported output tag ".public.annotations.zip"`)).
RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -503,12 +514,13 @@
}
func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported module reference tag ".system.stubs.source"`)).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "bar" variant "android_common": unsupported output tag ".system.stubs.source"`)).
RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -527,6 +539,7 @@
}
func TestJavaSdkLibrary_Deps(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -557,6 +570,7 @@
}
func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
+ t.Parallel()
prepareForJavaTest.RunTestWithBp(t, `
java_sdk_library_import {
name: "foo",
@@ -582,6 +596,7 @@
}
func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
+ t.Parallel()
bp := `
java_sdk_library_import {
name: "foo",
@@ -592,6 +607,7 @@
`
t.Run("stubs.source", func(t *testing.T) {
+ t.Parallel()
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.stubs.source"`)).
RunTestWithBp(t, bp+`
@@ -607,6 +623,7 @@
})
t.Run("api.txt", func(t *testing.T) {
+ t.Parallel()
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.api.txt"`)).
RunTestWithBp(t, bp+`
@@ -621,6 +638,7 @@
})
t.Run("removed-api.txt", func(t *testing.T) {
+ t.Parallel()
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo" is not a SourceFileProducer or having valid output file for tag ".public.removed-api.txt"`)).
RunTestWithBp(t, bp+`
@@ -636,6 +654,7 @@
}
func TestJavaSdkLibrary_InvalidScopes(t *testing.T) {
+ t.Parallel()
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": enabled api scope "system" depends on disabled scope "public"`)).
RunTestWithBp(t, `
@@ -656,6 +675,7 @@
}
func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -674,6 +694,7 @@
}
func TestJavaSdkLibrary_ModuleLib(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -694,6 +715,7 @@
}
func TestJavaSdkLibrary_SystemServer(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -714,6 +736,7 @@
}
func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -768,13 +791,13 @@
stubsPath := func(name string, scope *apiScope) string {
name = scope.stubsLibraryModuleName(name)
- return fmt.Sprintf("out/soong/.intermediates/%[1]s/android_common/turbine-combined/%[1]s.jar", name)
+ return fmt.Sprintf("out/soong/.intermediates/%[1]s.from-text/android_common/%[1]s.from-text/%[1]s.from-text.jar", name)
}
// The bar library should depend on the highest (where system server is highest and public is
// lowest) API scopes provided by each of the foo-* modules. The highest API scope provided by the
// foo-<x> module is <x>.
- barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
+ barLibrary := result.ModuleForTests(t, "bar", "android_common").Rule("javac")
stubLibraries := []string{
stubsPath("foo-public", apiScopePublic),
stubsPath("foo-system", apiScopeSystem),
@@ -788,6 +811,7 @@
}
func TestJavaSdkLibraryImport(t *testing.T) {
+ t.Parallel()
result := prepareForJavaTest.RunTestWithBp(t, `
java_library {
name: "foo",
@@ -826,10 +850,10 @@
`)
for _, scope := range []string{"", ".system", ".test"} {
- fooModule := result.ModuleForTests("foo"+scope, "android_common")
+ fooModule := result.ModuleForTests(t, "foo"+scope, "android_common")
javac := fooModule.Rule("javac")
- sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Output("combined/sdklib.stubs" + scope + ".jar").Output
+ sdklibStubsJar := result.ModuleForTests(t, "sdklib.stubs"+scope, "android_common").Output("local-combined/sdklib.stubs" + scope + ".jar").Output
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], sdklibStubsJar.String())
}
@@ -844,6 +868,7 @@
}
func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -968,25 +993,25 @@
CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{
// Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib.
`prebuilt_sdklib`,
- `prebuilt_sdklib`,
- `prebuilt_sdklib`,
`prebuilt_sdklib.stubs`,
`prebuilt_sdklib.stubs.source`,
})
// Make sure that dependencies on sdklib that resolve to one of the child libraries use the
// prebuilt library.
- public := result.ModuleForTests("public", "android_common")
+ public := result.ModuleForTests(t, "public", "android_common")
rule := public.Output("javac/public.jar")
inputs := rule.Implicits.Strings()
- expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar"
+ expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/local-combined/sdklib.stubs.jar"
if !android.InList(expected, inputs) {
t.Errorf("expected %q to contain %q", inputs, expected)
}
}
func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+ t.Parallel()
t.Run("prefer", func(t *testing.T) {
+ t.Parallel()
testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer)
})
}
@@ -994,6 +1019,7 @@
// If a module is listed in `mainline_module_contributions, it should be used
// It will supersede any other source vs prebuilt selection mechanism like `prefer` attribute
func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) {
+ t.Parallel()
bp := `
apex_contributions {
name: "my_mainline_module_contributions",
@@ -1093,17 +1119,17 @@
).RunTestWithBp(t, bp)
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
- public := result.ModuleForTests("public", "android_common")
+ public := result.ModuleForTests(t, "public", "android_common")
rule := public.Output("javac/public.jar")
inputs := rule.Implicits.Strings()
expectedInputs := []string{
// source
- "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.jar",
- "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.jar",
+ "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.from-text/android_common/sdklib.prebuilt_preferred_using_legacy_flags.stubs.from-text/sdklib.prebuilt_preferred_using_legacy_flags.stubs.from-text.jar",
+ "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.from-text/android_common/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.from-text/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.from-text.jar",
// prebuilt
- "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.jar",
- "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs.system/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.system.jar",
+ "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs/android_common/local-combined/sdklib.source_preferred_using_legacy_flags.stubs.jar",
+ "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs.system/android_common/local-combined/sdklib.source_preferred_using_legacy_flags.stubs.system.jar",
}
for _, expected := range expectedInputs {
if !android.InList(expected, inputs) {
@@ -1113,6 +1139,7 @@
}
func TestJavaSdkLibraryDist(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
PrepareForTestWithJavaBuildComponents,
PrepareForTestWithJavaDefaultModules,
@@ -1179,7 +1206,8 @@
for _, tt := range testCases {
t.Run(tt.module, func(t *testing.T) {
- m := result.ModuleForTests(apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library)
+ t.Parallel()
+ m := result.ModuleForTests(t, apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library)
dists := m.Dists()
if len(dists) != 1 {
t.Fatalf("expected exactly 1 dist entry, got %d", len(dists))
@@ -1195,6 +1223,7 @@
}
func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) {
+ t.Parallel()
preparer := android.GroupFixturePreparers(
PrepareForTestWithJavaBuildComponents,
PrepareForTestWithJavaDefaultModules,
@@ -1279,6 +1308,7 @@
}
func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1300,12 +1330,13 @@
`)
// The foo.stubs.source should depend on bar-lib
- fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
+ fooStubsSources := result.ModuleForTests(t, "foo.stubs.source", "android_common").Module().(*Droidstubs)
eval := fooStubsSources.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs.GetOrDefault(eval, nil), "bar-lib")
}
func TestJavaSdkLibrary_Scope_Libs_PassedToDroidstubs(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1327,12 +1358,13 @@
`)
// The foo.stubs.source should depend on bar-lib
- fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
+ fooStubsSources := result.ModuleForTests(t, "foo.stubs.source", "android_common").Module().(*Droidstubs)
eval := fooStubsSources.ConfigurableEvaluator(android.PanickingConfigAndErrorContext(result.TestContext))
android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs.GetOrDefault(eval, nil), "bar-lib")
}
func TestJavaSdkLibrary_ApiLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1377,12 +1409,13 @@
}
for _, c := range testCases {
- m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary)
+ m := result.ModuleForTests(t, c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary)
android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions)
}
}
func TestStaticDepStubLibrariesVisibility(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1412,6 +1445,7 @@
}
func TestSdkLibraryDependency(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1438,12 +1472,13 @@
}
`)
- barPermissions := result.ModuleForTests("bar.xml", "android_common").Output("bar.xml")
+ barPermissions := result.ModuleForTests(t, "bar.xml", "android_common").Output("bar.xml")
barContents := android.ContentFromFileRuleForTests(t, result.TestContext, barPermissions)
android.AssertStringDoesContain(t, "bar.xml java_sdk_xml command", barContents, `dependency="foo"`)
}
func TestSdkLibraryExportableStubsLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1480,8 +1515,8 @@
exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo")
// Check modules generation
- result.ModuleForTests(exportableStubsLibraryModuleName, "android_common")
- result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common")
+ result.ModuleForTests(t, exportableStubsLibraryModuleName, "android_common")
+ result.ModuleForTests(t, exportableSourceStubsLibraryModuleName, "android_common")
// Check static lib dependency
android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+
@@ -1494,6 +1529,7 @@
// For java libraries depending on java_sdk_library(_import) via libs, assert that
// rdep gets stubs of source if source is listed in apex_contributions and prebuilt has prefer (legacy mechanism)
func TestStubResolutionOfJavaSdkLibraryInLibs(t *testing.T) {
+ t.Parallel()
bp := `
apex_contributions {
name: "my_mainline_module_contributions",
@@ -1539,14 +1575,16 @@
result := fixture.RunTestWithBp(t, bp)
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
- public := result.ModuleForTests("mymodule", "android_common")
+ public := result.ModuleForTests(t, "mymodule", "android_common")
rule := public.Output("javac/mymodule.jar")
inputs := rule.Implicits.Strings()
- android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar")
+ android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs,
+ "out/soong/.intermediates/sdklib.stubs.from-text/android_common/sdklib.stubs.from-text/sdklib.stubs.from-text.jar")
}
// test that rdep gets resolved to the correct version of a java_sdk_library (source or a specific prebuilt)
func TestMultipleSdkLibraryPrebuilts(t *testing.T) {
+ t.Parallel()
bp := `
apex_contributions {
name: "my_mainline_module_contributions",
@@ -1599,17 +1637,17 @@
{
desc: "Source library is selected using apex_contributions",
selectedDependencyName: "sdklib",
- expectedStubPath: "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar",
+ expectedStubPath: "out/soong/.intermediates/sdklib.stubs.from-text/android_common/sdklib.stubs.from-text/sdklib.stubs.from-text.jar",
},
{
desc: "Prebuilt library v1 is selected using apex_contributions",
selectedDependencyName: "prebuilt_sdklib.v1",
- expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v1.stubs/android_common/combined/sdklib.stubs.jar",
+ expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v1.stubs/android_common/local-combined/sdklib.stubs.jar",
},
{
desc: "Prebuilt library v2 is selected using apex_contributions",
selectedDependencyName: "prebuilt_sdklib.v2",
- expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v2.stubs/android_common/combined/sdklib.stubs.jar",
+ expectedStubPath: "out/soong/.intermediates/prebuilt_sdklib.v2.stubs/android_common/local-combined/sdklib.stubs.jar",
},
}
@@ -1624,7 +1662,7 @@
result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
- public := result.ModuleForTests("mymodule", "android_common")
+ public := result.ModuleForTests(t, "mymodule", "android_common")
rule := public.Output("javac/mymodule.jar")
inputs := rule.Implicits.Strings()
android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, tc.expectedStubPath)
@@ -1632,6 +1670,7 @@
}
func TestStubLinkType(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1668,6 +1707,7 @@
}
func TestSdkLibDirectDependency(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
@@ -1732,6 +1772,7 @@
}
func TestSdkLibDirectDependencyWithPrebuiltSdk(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 9bfe6a2..6386a00 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -53,6 +53,7 @@
}
func TestClasspath(t *testing.T) {
+ t.Parallel()
const frameworkAidl = "-I" + defaultJavaDir + "/framework/aidl"
var classpathTestcases = []classpathTestCase{
{
@@ -388,22 +389,18 @@
},
}
- t.Parallel()
t.Run("basic", func(t *testing.T) {
t.Parallel()
- testClasspathTestCases(t, classpathTestcases, false, false)
+ testClasspathTestCases(t, classpathTestcases, false)
})
t.Run("Always_use_prebuilt_sdks=true", func(t *testing.T) {
- testClasspathTestCases(t, classpathTestcases, true, false)
- })
-
- t.Run("UseTransitiveJarsInClasspath", func(t *testing.T) {
- testClasspathTestCases(t, classpathTestcases, false, true)
+ t.Parallel()
+ testClasspathTestCases(t, classpathTestcases, true)
})
}
-func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase, alwaysUsePrebuiltSdks, useTransitiveJarsInClasspath bool) {
+func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase, alwaysUsePrebuiltSdks bool) {
for _, testcase := range classpathTestcases {
if testcase.forAlwaysUsePrebuiltSdks != nil && *testcase.forAlwaysUsePrebuiltSdks != alwaysUsePrebuiltSdks {
continue
@@ -444,10 +441,8 @@
switch {
case e == `""`, strings.HasSuffix(e, ".jar"):
ret[i] = e
- case useTransitiveJarsInClasspath:
- ret[i] = filepath.Join("out", "soong", ".intermediates", defaultJavaDir, e, "android_common", "turbine", e+".jar")
default:
- ret[i] = filepath.Join("out", "soong", ".intermediates", defaultJavaDir, e, "android_common", "turbine-combined", e+".jar")
+ ret[i] = filepath.Join("out", "soong", ".intermediates", defaultJavaDir, e, "android_common", "turbine", e+".jar")
}
}
return ret
@@ -499,7 +494,7 @@
}
checkClasspath := func(t *testing.T, result *android.TestResult, isJava8 bool) {
- foo := result.ModuleForTests("foo", variant(result))
+ foo := result.ModuleForTests(t, "foo", variant(result))
javac := foo.Rule("javac")
var deps []string
@@ -542,9 +537,6 @@
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
})
}
- if useTransitiveJarsInClasspath {
- preparer = PrepareForTestWithTransitiveClasspathEnabled
- }
fixtureFactory := android.GroupFixturePreparers(
prepareForJavaTest,
@@ -571,12 +563,13 @@
// Test with legacy javac -source 1.8 -target 1.8
t.Run("Java language level 8", func(t *testing.T) {
+ t.Parallel()
result := fixtureFactory.RunTestWithBp(t, bpJava8)
checkClasspath(t, result, true /* isJava8 */)
if testcase.host != android.Host {
- aidl := result.ModuleForTests("foo", variant(result)).Rule("aidl")
+ aidl := result.ModuleForTests(t, "foo", variant(result)).Rule("aidl")
android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
}
@@ -584,12 +577,13 @@
// Test with default javac -source 9 -target 9
t.Run("Java language level 9", func(t *testing.T) {
+ t.Parallel()
result := fixtureFactory.RunTestWithBp(t, bp)
checkClasspath(t, result, false /* isJava8 */)
if testcase.host != android.Host {
- aidl := result.ModuleForTests("foo", variant(result)).Rule("aidl")
+ aidl := result.ModuleForTests(t, "foo", variant(result)).Rule("aidl")
android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
}
@@ -602,6 +596,7 @@
// Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 8 -target 8
t.Run("REL + Java language level 8", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8)
@@ -610,6 +605,7 @@
// Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 9 -target 9
t.Run("REL + Java language level 9", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bp)
diff --git a/java/sdk_version_test.go b/java/sdk_version_test.go
index 88351d2..03d55f7 100644
--- a/java/sdk_version_test.go
+++ b/java/sdk_version_test.go
@@ -25,6 +25,7 @@
}
func TestSystemSdkFromVendor(t *testing.T) {
+ t.Parallel()
fixtures := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -57,7 +58,7 @@
vendor: true,
sdk_version: "system_current",
}`)
- fooModule := result.ModuleForTests("foo", "android_common")
+ fooModule := result.ModuleForTests(t, "foo", "android_common")
fooClasspath := fooModule.Rule("javac").Args["classpath"]
android.AssertStringDoesContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/34/system/android.jar")
diff --git a/java/support_libraries.go b/java/support_libraries.go
index c483fc1..f76eb11 100644
--- a/java/support_libraries.go
+++ b/java/support_libraries.go
@@ -28,7 +28,7 @@
func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) {
var supportAars, supportJars []string
- ctx.VisitAllModules(func(module android.Module) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
dir := ctx.ModuleDir(module)
switch {
case strings.HasPrefix(dir, "prebuilts/sdk/current/extras"),
@@ -47,11 +47,16 @@
return
}
- switch module.(type) {
- case *AndroidLibrary, *AARImport:
+ _, isAndroidLibrary := android.OtherModuleProvider(ctx, module, AndroidLibraryInfoProvider)
+ _, isAARImport := android.OtherModuleProvider(ctx, module, AARImportInfoProvider)
+ if isAndroidLibrary || isAARImport {
supportAars = append(supportAars, name)
- case *Library, *Import:
- supportJars = append(supportJars, name)
+ } else {
+ _, isJavaLibrary := android.OtherModuleProvider(ctx, module, JavaLibraryInfoProvider)
+ _, isJavaPlugin := android.OtherModuleProvider(ctx, module, JavaPluginInfoProvider)
+ if isJavaLibrary && !isJavaPlugin {
+ supportJars = append(supportJars, name)
+ }
}
})
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index b05b0e4..99301bc 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -51,10 +51,11 @@
`)
func TestJavaSystemModules(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForJavaTest, addSourceSystemModules).RunTest(t)
// check the existence of the source module
- sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
+ sourceSystemModules := result.ModuleForTests(t, "system-modules", "android_common")
sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the source input modules.
@@ -78,10 +79,11 @@
`)
func TestJavaSystemModulesImport(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForJavaTest, addPrebuiltSystemModules).RunTest(t)
// check the existence of the renamed prebuilt module
- prebuiltSystemModules := result.ModuleForTests("system-modules", "android_common")
+ prebuiltSystemModules := result.ModuleForTests(t, "system-modules", "android_common")
prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the renamed prebuilt input modules.
@@ -90,6 +92,7 @@
}
func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForJavaTest,
addSourceSystemModules,
@@ -97,7 +100,7 @@
).RunTest(t)
// check the existence of the source module
- sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
+ sourceSystemModules := result.ModuleForTests(t, "system-modules", "android_common")
sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the source input modules.
@@ -105,7 +108,7 @@
android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, sourceInputs.RelativeToTop().Strings())
// check the existence of the renamed prebuilt module
- prebuiltSystemModules := result.ModuleForTests("prebuilt_system-modules", "android_common")
+ prebuiltSystemModules := result.ModuleForTests(t, "prebuilt_system-modules", "android_common")
prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the renamed prebuilt input modules.
@@ -114,6 +117,7 @@
}
func TestMultipleSystemModulesPrebuilts(t *testing.T) {
+ t.Parallel()
bp := `
// an rdep
java_library {
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 3176ad9..a60f6b8 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -58,6 +58,10 @@
return m
}
+func (m *platformSystemServerClasspathModule) UniqueApexVariations() bool {
+ return true
+}
+
func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) {
return p.classpathFragmentBase().androidMkEntries()
}
@@ -91,8 +95,10 @@
properties systemServerClasspathFragmentProperties
}
-func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
- return nil
+var _ android.ApexModule = (*SystemServerClasspathModule)(nil)
+
+func (m *SystemServerClasspathModule) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
type systemServerClasspathFragmentProperties struct {
@@ -116,6 +122,10 @@
return m
}
+func (m *SystemServerClasspathModule) UniqueApexVariations() bool {
+ return true
+}
+
func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(s.properties.Contents.GetOrDefault(ctx, nil)) == 0 && len(s.properties.Standalone_contents.GetOrDefault(ctx, nil)) == 0 {
ctx.PropertyErrorf("contents", "Either contents or standalone_contents needs to be non-empty")
diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go
index ba328e7..704f5a4 100644
--- a/java/systemserver_classpath_fragment_test.go
+++ b/java/systemserver_classpath_fragment_test.go
@@ -25,6 +25,7 @@
)
func TestPlatformSystemServerClasspathVariant(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(`
@@ -39,6 +40,7 @@
}
func TestPlatformSystemServerClasspath_ClasspathFragmentPaths(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(`
@@ -50,10 +52,11 @@
p := result.Module("platform-systemserverclasspath", "android_common").(*platformSystemServerClasspathModule)
android.AssertStringEquals(t, "output filepath", "systemserverclasspath.pb", p.ClasspathFragmentBase.outputFilepath.Base())
- android.AssertPathRelativeToTopEquals(t, "install filepath", "out/soong/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
+ android.AssertPathRelativeToTopEquals(t, "install filepath", "out/target/product/test_device/system/etc/classpaths", p.ClasspathFragmentBase.installDirPath)
}
func TestPlatformSystemServerClasspathModule_AndroidMkEntries(t *testing.T) {
+ t.Parallel()
preparer := android.GroupFixturePreparers(
prepareForTestWithSystemServerClasspath,
android.FixtureWithRootAndroidBp(`
@@ -97,6 +100,7 @@
}
func TestSystemServerClasspathFragmentWithoutContents(t *testing.T) {
+ t.Parallel()
prepareForTestWithSystemServerClasspath.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
`\QEither contents or standalone_contents needs to be non-empty\E`)).
diff --git a/java/testing.go b/java/testing.go
index ba33d90..a6e72cf 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -18,7 +18,6 @@
"fmt"
"reflect"
"regexp"
- "sort"
"strings"
"testing"
@@ -237,29 +236,6 @@
)
}
-func FixtureWithPrebuiltIncrementalApis(apiLevel2Modules map[string][]string) android.FixturePreparer {
- mockFS := android.MockFS{}
- path := "prebuilts/sdk/Android.bp"
-
- bp := fmt.Sprintf(`
- prebuilt_apis {
- name: "sdk",
- api_dirs: ["%s"],
- allow_incremental_platform_api: true,
- imports_sdk_version: "none",
- imports_compile_dex: true,
- }
- `, strings.Join(android.SortedKeys(apiLevel2Modules), `", "`))
-
- for release, modules := range apiLevel2Modules {
- mockFS.Merge(prebuiltApisFilesForModules([]string{release}, modules))
- }
- return android.GroupFixturePreparers(
- android.FixtureAddTextFile(path, bp),
- android.FixtureMergeMockFs(mockFS),
- )
-}
-
func prebuiltApisFilesForModules(apiLevels []string, modules []string) map[string][]byte {
libs := append([]string{"android"}, modules...)
@@ -378,7 +354,6 @@
RegisterAppBuildComponents(ctx)
RegisterAppImportBuildComponents(ctx)
RegisterAppSetBuildComponents(ctx)
- registerBootclasspathBuildComponents(ctx)
registerBootclasspathFragmentBuildComponents(ctx)
RegisterDexpreoptBootJarsComponents(ctx)
RegisterDocsBuildComponents(ctx)
@@ -611,19 +586,18 @@
func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string {
t.Helper()
- module := ctx.ModuleForTests(name, variant).Module()
+ module := ctx.ModuleForTests(t, name, variant).Module()
deps := []string{}
ctx.VisitDirectDeps(module, func(m blueprint.Module) {
deps = append(deps, m.Name())
})
- sort.Strings(deps)
-
- return deps
+ return android.SortedUniqueStrings(deps)
}
// CheckModuleDependencies checks if the expected dependencies of the module are
// identical to the actual dependencies.
func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+ t.Helper()
deps := getModuleDependencies(t, ctx, name, variant)
if actual := deps; !reflect.DeepEqual(expected, actual) {
@@ -643,7 +617,7 @@
// CheckModuleHasDependency returns true if the module depends on the expected dependency.
func CheckModuleHasDependencyWithTag(t *testing.T, ctx *android.TestContext, name, variant string, desiredTag blueprint.DependencyTag, expected string) bool {
- module := ctx.ModuleForTests(name, variant).Module()
+ module := ctx.ModuleForTests(t, name, variant).Module()
found := false
ctx.VisitDirectDepsWithTags(module, func(m blueprint.Module, tag blueprint.DependencyTag) {
if tag == desiredTag && m.Name() == expected {
@@ -658,7 +632,7 @@
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
- pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules)
+ pairs := apexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules, platformBootclasspath.libraryToApex)
android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs)
}
@@ -673,23 +647,54 @@
android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir)
}
-// ApexNamePairsFromModules returns the apex:module pair for the supplied modules.
-func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string {
+// CheckPlatformBootclasspathDependencies checks the dependencies of the selected module against the expected list.
+//
+// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
+// name of the apex, or platform is it is not part of an apex and <module> is the module name.
+func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+ t.Helper()
+ platformBootclasspath := ctx.ModuleForTests(t, name, variant).Module().(*platformBootclasspathModule)
+ modules := []android.Module{}
+ ctx.VisitDirectDeps(platformBootclasspath, func(m blueprint.Module) {
+ modules = append(modules, m.(android.Module))
+ })
+
+ pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex)
+ android.AssertDeepEquals(t, "module dependencies", expected, pairs)
+}
+
+// apexNamePairsFromModules returns the apex:module pair for the supplied modules.
+func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module, modulesToApex map[android.Module]string) []string {
pairs := []string{}
for _, module := range modules {
- pairs = append(pairs, apexNamePairFromModule(ctx, module))
+ pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex))
}
return pairs
}
-func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
+// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments.
+func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.Module, apexNameToFragment map[string]android.Module) []string {
+ pairs := []string{}
+ for _, fragment := range fragments {
+ found := false
+ for apex, apexFragment := range apexNameToFragment {
+ if apexFragment == fragment {
+ pairs = append(pairs, apex+":"+ctx.ModuleName(fragment))
+ found = true
+ }
+ }
+ if !found {
+ pairs = append(pairs, "platform:"+ctx.ModuleName(fragment))
+ }
+ }
+ return pairs
+}
+
+func apexNamePairFromModule(ctx *android.TestContext, module android.Module, modulesToApex map[android.Module]string) string {
name := module.Name()
- var apex string
- apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
- if apexInfo.IsForPlatform() {
+ apex := modulesToApex[module]
+ if apex == "" {
apex = "platform"
- } else {
- apex = apexInfo.InApexVariants[0]
}
return fmt.Sprintf("%s:%s", apex, name)
@@ -700,7 +705,7 @@
func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
- pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.fragments)
+ pairs := ApexFragmentPairsFromModules(result.TestContext, platformBootclasspath.fragments, platformBootclasspath.apexNameToFragment)
android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs)
}
@@ -723,7 +728,7 @@
// Check that the merged file create by platform_compat_config_singleton has the correct inputs.
func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, message string, expectedPaths ...string) {
- sourceGlobalCompatConfig := result.SingletonForTests("platform_compat_config_singleton")
+ sourceGlobalCompatConfig := result.SingletonForTests(t, "platform_compat_config_singleton")
allOutputs := sourceGlobalCompatConfig.AllOutputs()
android.AssertIntEquals(t, message+": output len", 1, len(allOutputs))
output := sourceGlobalCompatConfig.Output(allOutputs[0])
@@ -801,5 +806,3 @@
config.installDir = installDir
})
}
-
-var PrepareForTestWithTransitiveClasspathEnabled = android.PrepareForTestWithBuildFlag("RELEASE_USE_TRANSITIVE_JARS_IN_CLASSPATH", "true")
diff --git a/java/tracereferences.go b/java/tracereferences.go
new file mode 100644
index 0000000..342b6a6
--- /dev/null
+++ b/java/tracereferences.go
@@ -0,0 +1,54 @@
+// Copyright 2025 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 java
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+var traceReferences = pctx.AndroidStaticRule("traceReferences",
+ blueprint.RuleParams{
+ Command: `${config.TraceReferencesCmd} ` +
+ // Note that we suppress missing def errors, as we're only interested
+ // in the direct deps between the sources and target.
+ `--map-diagnostics:MissingDefinitionsDiagnostic error none ` +
+ `--keep-rules ` +
+ `--output ${out} ` +
+ `--target ${in} ` +
+ // `--source` and `--lib` are already prepended to each
+ // jar reference in the sources and libs joined string args.
+ `${sources} ` +
+ `${libs}`,
+ CommandDeps: []string{"${config.TraceReferencesCmd}"},
+ }, "sources", "libs")
+
+// Generates keep rules in output corresponding to any references from sources
+// (a list of jars) onto target (the referenced jar) that are not included in
+// libs (a list of external jars).
+func TraceReferences(ctx android.ModuleContext, sources android.Paths, target android.Path, libs android.Paths,
+ output android.WritablePath) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: traceReferences,
+ Input: target,
+ Output: output,
+ Implicits: append(sources, libs...),
+ Args: map[string]string{
+ "sources": android.JoinWithPrefix(sources.Strings(), "--source "),
+ "libs": android.JoinWithPrefix(libs.Strings(), "--lib "),
+ },
+ })
+}
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 001a1e7..1225da0 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -67,6 +67,10 @@
// Whether this module is directly installable to one of the partitions. Default is true
Installable *bool
+
+ // Whether debug symbols should be stripped from the *.ko files.
+ // Defaults to true.
+ Strip_debug_symbols *bool
}
// prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory.
@@ -100,7 +104,9 @@
systemModules := android.PathsForModuleSrc(ctx, pkm.properties.System_deps)
depmodOut := pkm.runDepmod(ctx, modules, systemModules)
- strippedModules := stripDebugSymbols(ctx, modules)
+ if proptools.BoolDefault(pkm.properties.Strip_debug_symbols, true) {
+ modules = stripDebugSymbols(ctx, modules)
+ }
installDir := android.PathForModuleInstall(ctx, "lib", "modules")
// Kernel module is installed to vendor_ramdisk/lib/modules regardless of product
@@ -114,7 +120,7 @@
installDir = installDir.Join(ctx, pkm.KernelVersion())
}
- for _, m := range strippedModules {
+ for _, m := range modules {
ctx.InstallFile(installDir, filepath.Base(m.String()), m)
}
ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad)
@@ -165,9 +171,9 @@
}, "stripCmd")
)
-func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths {
+func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.Paths {
dir := android.PathForModuleOut(ctx, "stripped").OutputPath
- var outputs android.OutputPaths
+ var outputs android.Paths
for _, m := range modules {
stripped := dir.Join(ctx, filepath.Base(m.String()))
@@ -241,6 +247,8 @@
return modulesDir.Join(ctx, "vendor", "lib", "modules")
} else if ctx.InstallInOdmDlkm() {
return modulesDir.Join(ctx, "odm", "lib", "modules")
+ } else if ctx.InstallInVendorRamdisk() {
+ return modulesDir.Join(ctx, "lib", "modules")
} else {
// not an android dlkm module.
return modulesDir
@@ -303,9 +311,9 @@
builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName()))
finalModulesDep := modulesDep
- // Add a leading slash to paths in modules.dep of android dlkm
- if ctx.InstallInSystemDlkm() || ctx.InstallInVendorDlkm() || ctx.InstallInOdmDlkm() {
- finalModulesDep := modulesDep.ReplaceExtension(ctx, "intermediates")
+ // Add a leading slash to paths in modules.dep of android dlkm and vendor ramdisk
+ if ctx.InstallInSystemDlkm() || ctx.InstallInVendorDlkm() || ctx.InstallInOdmDlkm() || ctx.InstallInVendorRamdisk() {
+ finalModulesDep = modulesDep.ReplaceExtension(ctx, "intermediates")
ctx.Build(pctx, android.BuildParams{
Rule: addLeadingSlashToPaths,
Input: modulesDep,
diff --git a/kernel/prebuilt_kernel_modules_test.go b/kernel/prebuilt_kernel_modules_test.go
index 7b81869..0fc2720 100644
--- a/kernel/prebuilt_kernel_modules_test.go
+++ b/kernel/prebuilt_kernel_modules_test.go
@@ -50,7 +50,7 @@
var actual []string
for _, ps := range android.OtherModuleProviderOrDefault(
- ctx, ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module(), android.InstallFilesProvider).PackagingSpecs {
+ ctx, ctx.ModuleForTests(t, "foo", "android_arm64_armv8-a").Module(), android.InstallFilesProvider).PackagingSpecs {
actual = append(actual, ps.RelPathInPackage())
}
actual = android.SortedUniqueStrings(actual)
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index d422871..925d7b1 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -76,9 +76,7 @@
input := android.PathForModuleSrc(ctx, android.String(l.properties.Src))
output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath
- builder := android.NewRuleBuilder(pctx, ctx)
- BuildLinkerConfig(ctx, builder, android.Paths{input}, nil, nil, output)
- builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())
+ BuildLinkerConfig(ctx, android.Paths{input}, nil, nil, output)
l.outputFilePath = output
l.installDirPath = android.PathForModuleInstall(ctx, "etc")
@@ -88,12 +86,19 @@
ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath)
ctx.SetOutputFiles(android.Paths{l.outputFilePath}, "")
+
+ etc.SetCommonPrebuiltEtcInfo(ctx, l)
}
-func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder,
- inputs android.Paths, provideModules []android.Module, requireModules []android.Module, output android.OutputPath) {
-
+func BuildLinkerConfig(
+ ctx android.ModuleContext,
+ inputs android.Paths,
+ provideModules []android.ModuleProxy,
+ requireModules []android.ModuleProxy,
+ output android.WritablePath,
+) {
// First, convert the input json to protobuf format
+ builder := android.NewRuleBuilder(pctx, ctx)
interimOutput := android.PathForModuleOut(ctx, "temp.pb")
cmd := builder.Command().
BuiltTool("conv_linker_config").
@@ -107,9 +112,10 @@
// Secondly, if there's provideLibs gathered from provideModules, append them
var provideLibs []string
for _, m := range provideModules {
- if c, ok := m.(*cc.Module); ok && (cc.IsStubTarget(c) || c.HasLlndkStubs()) {
+ ccInfo, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider)
+ if ok && (cc.IsStubTarget(android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider)) || ccInfo.HasLlndkStubs) {
for _, ps := range android.OtherModuleProviderOrDefault(
- ctx, c, android.InstallFilesProvider).PackagingSpecs {
+ ctx, m, android.InstallFilesProvider).PackagingSpecs {
provideLibs = append(provideLibs, ps.FileName())
}
}
@@ -119,8 +125,15 @@
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")
+ if _, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); ok {
+ if android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider).HasStubsVariants &&
+ !android.OtherModulePointerProviderOrDefault(ctx, m, android.CommonModuleInfoProvider).Host {
+ name := ctx.OtherModuleName(m)
+ if ccInfo, ok := android.OtherModuleProvider(ctx, m, cc.CcInfoProvider); ok && ccInfo.LinkerInfo != nil && ccInfo.LinkerInfo.ImplementationModuleName != nil {
+ name = *ccInfo.LinkerInfo.ImplementationModuleName
+ }
+ requireLibs = append(requireLibs, name+".so")
+ }
}
}
@@ -157,6 +170,7 @@
builder.Temporary(interimOutput)
builder.DeleteTemporaryFiles()
+ builder.Build("conv_linker_config_"+output.String(), "Generate linker config protobuf "+output.String())
}
// linker_config generates protobuf file from json file. This protobuf file will be used from
diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go
index 939e4bb..9e08b19 100644
--- a/linkerconfig/linkerconfig_test.go
+++ b/linkerconfig/linkerconfig_test.go
@@ -46,7 +46,7 @@
"LOCAL_INSTALLED_MODULE_STEM": {"linker.config.pb"},
}
- p := result.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+ p := result.ModuleForTests(t, "linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
if p.outputFilePath.Base() != "linker.config.pb" {
t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base())
@@ -79,7 +79,7 @@
expected := []string{"true"}
- p := result.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+ p := result.ModuleForTests(t, "linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)[0]
if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
if !reflect.DeepEqual(value, expected) {
diff --git a/phony/phony.go b/phony/phony.go
index 807b95b..e75f4c8 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -38,9 +38,11 @@
type phony struct {
android.ModuleBase
+
requiredModuleNames []string
hostRequiredModuleNames []string
targetRequiredModuleNames []string
+ outputDeps android.Paths
}
func PhonyFactory() android.Module {
@@ -54,6 +56,14 @@
p.requiredModuleNames = ctx.RequiredModuleNames(ctx)
p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
+
+ ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ if o, ok := android.OtherModuleProvider(ctx, dep, android.OutputFilesProvider); ok {
+ p.outputDeps = append(p.outputDeps, o.DefaultOutputFiles...)
+ }
+ })
+
+ ctx.Phony(p.Name(), p.outputDeps...)
}
func (p *phony) AndroidMk() android.AndroidMkData {
@@ -77,6 +87,10 @@
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=",
strings.Join(p.targetRequiredModuleNames, " "))
}
+ if len(p.outputDeps) > 0 {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=",
+ strings.Join(p.outputDeps.Strings(), " "))
+ }
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
for _, extra := range data.Extra {
extra(w, nil)
@@ -90,8 +104,7 @@
android.ModuleBase
android.DefaultableModuleBase
- phonyDepsModuleNames []string
- properties PhonyProperties
+ properties PhonyProperties
}
type PhonyProperties struct {
@@ -112,18 +125,8 @@
}
func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.phonyDepsModuleNames = p.properties.Phony_deps.GetOrDefault(ctx, nil)
-}
-
-func (p *PhonyRule) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- if len(p.phonyDepsModuleNames) > 0 {
- depModulesStr := strings.Join(p.phonyDepsModuleNames, " ")
- fmt.Fprintln(w, ".PHONY:", name)
- fmt.Fprintln(w, name, ":", depModulesStr)
- }
- },
+ for _, dep := range p.properties.Phony_deps.GetOrDefault(ctx, nil) {
+ ctx.Phony(ctx.ModuleName(), android.PathForPhony(ctx, dep))
}
}
diff --git a/provenance/provenance_metadata_proto/Android.bp b/provenance/provenance_metadata_proto/Android.bp
index 7fc47a9..b4176a5 100644
--- a/provenance/provenance_metadata_proto/Android.bp
+++ b/provenance/provenance_metadata_proto/Android.bp
@@ -20,11 +20,6 @@
python_library_host {
name: "provenance_metadata_proto",
- version: {
- py3: {
- enabled: true,
- },
- },
srcs: [
"provenance_metadata.proto",
],
diff --git a/provenance/provenance_singleton.go b/provenance/provenance_singleton.go
index c372db2..c1bc1c7 100644
--- a/provenance/provenance_singleton.go
+++ b/provenance/provenance_singleton.go
@@ -99,6 +99,7 @@
})
context.Phony("droidcore", android.PathForPhony(context, "provenance_metadata"))
+ context.DistForGoal("droidcore", p.mergedMetaDataFile)
}
func GenerateArtifactProvenanceMetaData(ctx android.ModuleContext, artifactPath android.Path, installedFile android.InstallPath) android.Path {
@@ -116,9 +117,3 @@
return artifactMetaDataFile
}
-
-func (p *provenanceInfoSingleton) MakeVars(ctx android.MakeVarsContext) {
- ctx.DistForGoal("droidcore", p.mergedMetaDataFile)
-}
-
-var _ android.SingletonMakeVarsProvider = (*provenanceInfoSingleton)(nil)
diff --git a/provenance/provenance_singleton_test.go b/provenance/provenance_singleton_test.go
index 0f1eae2..05f3474 100644
--- a/provenance/provenance_singleton_test.go
+++ b/provenance/provenance_singleton_test.go
@@ -28,9 +28,9 @@
PrepareForTestWithProvenanceSingleton,
android.PrepareForTestWithAndroidMk).RunTestWithBp(t, "")
- outputs := result.SingletonForTests("provenance_metadata_singleton").AllOutputs()
+ outputs := result.SingletonForTests(t, "provenance_metadata_singleton").AllOutputs()
for _, output := range outputs {
- testingBuildParam := result.SingletonForTests("provenance_metadata_singleton").Output(output)
+ testingBuildParam := result.SingletonForTests(t, "provenance_metadata_singleton").Output(output)
switch {
case strings.Contains(output, "soong/provenance_metadata.textproto"):
android.AssertStringEquals(t, "Invalid build rule", "android/soong/provenance.mergeProvenanceMetaData", testingBuildParam.Rule.String())
diff --git a/python/binary.go b/python/binary.go
index 5f60761..f894299 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -22,8 +22,15 @@
"strings"
"android/soong/android"
+ "android/soong/cc"
+
+ "github.com/google/blueprint"
)
+type PythonBinaryInfo struct{}
+
+var PythonBinaryInfoProvider = blueprint.NewProvider[PythonBinaryInfo]()
+
func init() {
registerPythonBinaryComponents(android.InitRegistrationContext)
}
@@ -103,12 +110,22 @@
p.buildBinary(ctx)
p.installedDest = ctx.InstallFile(installDir(ctx, "bin", "", ""),
p.installSource.Base(), p.installSource)
+
+ android.SetProvider(ctx, PythonBinaryInfoProvider, PythonBinaryInfo{})
+
ctx.SetOutputFiles(android.Paths{p.installSource}, "")
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, p.androidMkSharedLibs...)
+ moduleInfoJSON.SharedLibs = append(moduleInfoJSON.SharedLibs, p.androidMkSharedLibs...)
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
}
func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
embeddedLauncher := p.isEmbeddedLauncherEnabled()
depsSrcsZips := p.collectPathsFromTransitiveDeps(ctx, embeddedLauncher)
+ bundleSharedLibs := p.collectSharedLibDeps(ctx)
main := ""
if p.autorun() {
main = p.getPyMainFile(ctx, p.srcsPathMappings)
@@ -116,13 +133,13 @@
var launcherPath android.OptionalPath
if embeddedLauncher {
- ctx.VisitDirectDepsWithTag(launcherTag, func(m android.Module) {
- if provider, ok := m.(IntermPathProvider); ok {
+ ctx.VisitDirectDepsProxyWithTag(launcherTag, func(m android.ModuleProxy) {
+ if provider, ok := android.OtherModuleProvider(ctx, m, cc.LinkableInfoProvider); ok {
if launcherPath.Valid() {
panic(fmt.Errorf("launcher path was found before: %q",
launcherPath))
}
- launcherPath = provider.IntermPathForModuleOut()
+ launcherPath = provider.OutputFile
}
})
}
@@ -133,17 +150,25 @@
srcsZips = append(srcsZips, p.srcsZip)
}
srcsZips = append(srcsZips, depsSrcsZips...)
+ if ctx.Host() && len(bundleSharedLibs) > 0 {
+ // only bundle shared libs for host binaries
+ sharedLibZip := p.zipSharedLibs(ctx, bundleSharedLibs)
+ srcsZips = append(srcsZips, sharedLibZip)
+ }
p.installSource = registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
- p.getHostInterpreterName(ctx, p.properties.Actual_version),
- main, p.getStem(ctx), srcsZips)
+ "python3", main, p.getStem(ctx), srcsZips)
var sharedLibs []string
// if embedded launcher is enabled, we need to collect the shared library dependencies of the
// launcher
- for _, dep := range ctx.GetDirectDepsWithTag(launcherSharedLibTag) {
+ for _, dep := range ctx.GetDirectDepsProxyWithTag(launcherSharedLibTag) {
sharedLibs = append(sharedLibs, ctx.OtherModuleName(dep))
}
p.androidMkSharedLibs = sharedLibs
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: p.binaryProperties.Test_suites,
+ })
}
func (p *PythonBinaryModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -196,23 +221,6 @@
return BoolDefault(b.binaryProperties.Autorun, true)
}
-// get host interpreter name.
-func (p *PythonBinaryModule) getHostInterpreterName(ctx android.ModuleContext,
- actualVersion string) string {
- var interp string
- switch actualVersion {
- case pyVersion2:
- interp = "python2.7"
- case pyVersion3:
- interp = "python3"
- default:
- panic(fmt.Errorf("unknown Python actualVersion: %q for module: %q.",
- actualVersion, ctx.ModuleName()))
- }
-
- return interp
-}
-
// find main program path within runfiles tree.
func (p *PythonBinaryModule) getPyMainFile(ctx android.ModuleContext,
srcsPathMappings []pathMapping) string {
diff --git a/python/defaults.go b/python/defaults.go
index 3dc5bc4..b5ee2bc 100644
--- a/python/defaults.go
+++ b/python/defaults.go
@@ -18,10 +18,6 @@
"android/soong/android"
)
-func init() {
- android.RegisterModuleType("python_defaults", DefaultsFactory)
-}
-
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
diff --git a/python/library.go b/python/library.go
index 7cdb80b..c197028 100644
--- a/python/library.go
+++ b/python/library.go
@@ -27,6 +27,7 @@
func registerPythonLibraryComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("python_library_host", PythonLibraryHostFactory)
ctx.RegisterModuleType("python_library", PythonLibraryFactory)
+ ctx.RegisterModuleType("python_defaults", DefaultsFactory)
}
func PythonLibraryHostFactory() android.Module {
diff --git a/python/python.go b/python/python.go
index d3e5743..de21e39 100644
--- a/python/python.go
+++ b/python/python.go
@@ -20,26 +20,28 @@
"fmt"
"path/filepath"
"regexp"
+ "sort"
"strings"
+ "android/soong/cc"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/depset"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
-func init() {
- registerPythonMutators(android.InitRegistrationContext)
+type PythonLibraryInfo struct {
+ SrcsPathMappings []pathMapping
+ DataPathMappings []pathMapping
+ SrcsZip android.Path
+ PrecompiledSrcsZip android.Path
+ PkgPath string
+ BundleSharedLibs android.Paths
}
-func registerPythonMutators(ctx android.RegistrationContext) {
- ctx.PreDepsMutators(RegisterPythonPreDepsMutators)
-}
-
-// Exported to support other packages using Python modules in tests.
-func RegisterPythonPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.Transition("python_version", &versionSplitTransitionMutator{})
-}
+var PythonLibraryInfoProvider = blueprint.NewProvider[PythonLibraryInfo]()
// the version-specific properties that apply to python modules.
type VersionProperties struct {
@@ -95,12 +97,21 @@
// device.
Device_common_data []string `android:"path_device_common"`
+ // Same as data, but will add dependencies on modules via a device os variation and the
+ // device's first supported arch's variation. Useful for a host test that wants to embed a
+ // module built for device.
+ Device_first_data []string `android:"path_device_first"`
+
// list of java modules that provide data that should be installed alongside the test.
Java_data []string
// list of the Python libraries compatible both with Python2 and Python3.
Libs []string `android:"arch_variant"`
+ // TODO: b/403060602 - add unit tests for this property and related code
+ // list of shared libraries that should be packaged with the python code for this module.
+ Shared_libs []string `android:"arch_variant"`
+
Version struct {
// Python2-specific properties, including whether Python2 is supported for this module
// and version-specific sources, exclusions and dependencies.
@@ -111,18 +122,14 @@
Py3 VersionProperties `android:"arch_variant"`
} `android:"arch_variant"`
- // the actual version each module uses after variations created.
- // this property name is hidden from users' perspectives, and soong will populate it during
- // runtime.
- Actual_version string `blueprint:"mutated"`
-
- // whether the module is required to be built with actual_version.
- // this is set by the python version mutator based on version-specific properties
+ // This enabled property is to accept the collapsed enabled property from the VersionProperties.
+ // It is unused now, as all builds should be python3.
Enabled *bool `blueprint:"mutated"`
- // whether the binary is required to be built with embedded launcher for this actual_version.
- // this is set by the python version mutator based on version-specific properties
- Embedded_launcher *bool `blueprint:"mutated"`
+ // whether the binary is required to be built with an embedded python interpreter, defaults to
+ // true. This allows taking the resulting binary outside of the build and running it on machines
+ // that don't have python installed or may have an older version of python.
+ Embedded_launcher *bool
}
// Used to store files of current module after expanding dependencies
@@ -158,6 +165,10 @@
precompiledSrcsZip android.Path
sourceProperties android.SourceProperties
+
+ // The shared libraries that should be bundled with the python code for
+ // any standalone python binaries that depend on this module.
+ bundleSharedLibs android.Paths
}
// newModule generates new Python base module
@@ -168,16 +179,6 @@
}
}
-// interface implemented by Python modules to provide source and data mappings and zip to python
-// modules that depend on it
-type pythonDependency interface {
- getSrcsPathMappings() []pathMapping
- getDataPathMappings() []pathMapping
- getSrcsZip() android.Path
- getPrecompiledSrcsZip() android.Path
- getPkgPath() string
-}
-
// getSrcsPathMappings gets this module's path mapping of src source path : runfiles destination
func (p *PythonLibraryModule) getSrcsPathMappings() []pathMapping {
return p.srcsPathMappings
@@ -207,7 +208,9 @@
return &p.properties
}
-var _ pythonDependency = (*PythonLibraryModule)(nil)
+func (p *PythonLibraryModule) getBundleSharedLibs() android.Paths {
+ return p.bundleSharedLibs
+}
func (p *PythonLibraryModule) init() android.Module {
p.AddProperties(&p.properties, &p.protoProperties, &p.sourceProperties)
@@ -236,6 +239,7 @@
var (
pythonLibTag = dependencyTag{name: "pythonLib"}
javaDataTag = dependencyTag{name: "javaData"}
+ sharedLibTag = dependencyTag{name: "sharedLib"}
// The python interpreter, with soong module name "py3-launcher" or "py3-launcher-autorun".
launcherTag = dependencyTag{name: "launcher"}
launcherSharedLibTag = installDependencyTag{name: "launcherSharedLib"}
@@ -248,8 +252,6 @@
pathComponentRegexp = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
pyExt = ".py"
protoExt = ".proto"
- pyVersion2 = "PY2"
- pyVersion3 = "PY3"
internalPath = "internal"
)
@@ -257,71 +259,6 @@
getBaseProperties() *BaseProperties
}
-type versionSplitTransitionMutator struct{}
-
-func (versionSplitTransitionMutator) Split(ctx android.BaseModuleContext) []string {
- if base, ok := ctx.Module().(basePropertiesProvider); ok {
- props := base.getBaseProperties()
- var variants []string
- // PY3 is first so that we alias the PY3 variant rather than PY2 if both
- // are available
- if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
- variants = append(variants, pyVersion3)
- }
- if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
- if ctx.ModuleName() != "py2-cmd" &&
- ctx.ModuleName() != "py2-stdlib" {
- ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3.")
- }
- variants = append(variants, pyVersion2)
- }
- return variants
- }
- return []string{""}
-}
-
-func (versionSplitTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
- return ""
-}
-
-func (versionSplitTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
- if incomingVariation != "" {
- return incomingVariation
- }
- if base, ok := ctx.Module().(basePropertiesProvider); ok {
- props := base.getBaseProperties()
- if proptools.BoolDefault(props.Version.Py3.Enabled, true) {
- return pyVersion3
- } else {
- return pyVersion2
- }
- }
-
- return ""
-}
-
-func (versionSplitTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
- if variation == "" {
- return
- }
- if base, ok := ctx.Module().(basePropertiesProvider); ok {
- props := base.getBaseProperties()
- props.Actual_version = variation
-
- var versionProps *VersionProperties
- if variation == pyVersion3 {
- versionProps = &props.Version.Py3
- } else if variation == pyVersion2 {
- versionProps = &props.Version.Py2
- }
-
- err := proptools.AppendMatchingProperties([]interface{}{props}, versionProps, nil)
- if err != nil {
- panic(err)
- }
- }
-}
-
func anyHasExt(paths []string, ext string) bool {
for _, p := range paths {
if filepath.Ext(p) == ext {
@@ -341,25 +278,38 @@
// - if required, specifies launcher and adds launcher dependencies,
// - applies python version mutations to Python dependencies
func (p *PythonLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
- android.ProtoDeps(ctx, &p.protoProperties)
+ // Flatten the version.py3 props down into the main property struct. Leftover from when
+ // there was both python2 and 3 in the build, and properties could be different between them.
+ if base, ok := ctx.Module().(basePropertiesProvider); ok {
+ props := base.getBaseProperties()
- versionVariation := []blueprint.Variation{
- {"python_version", p.properties.Actual_version},
+ err := proptools.AppendMatchingProperties([]interface{}{props}, &props.Version.Py3, nil)
+ if err != nil {
+ panic(err)
+ }
}
+ android.ProtoDeps(ctx, &p.protoProperties)
+
// If sources contain a proto file, add dependency on libprotobuf-python
if p.anySrcHasExt(ctx, protoExt) && p.Name() != "libprotobuf-python" {
- ctx.AddVariationDependencies(versionVariation, pythonLibTag, "libprotobuf-python")
+ ctx.AddDependency(ctx.Module(), pythonLibTag, "libprotobuf-python")
}
// Add python library dependencies for this python version variation
- ctx.AddVariationDependencies(versionVariation, pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
+ ctx.AddDependency(ctx.Module(), pythonLibTag, android.LastUniqueStrings(p.properties.Libs)...)
// Emulate the data property for java_data but with the arch variation overridden to "common"
// so that it can point to java modules.
javaDataVariation := []blueprint.Variation{{"arch", android.Common.String()}}
ctx.AddVariationDependencies(javaDataVariation, javaDataTag, p.properties.Java_data...)
+ if ctx.Host() {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), sharedLibTag, p.properties.Shared_libs...)
+ } else if len(p.properties.Shared_libs) > 0 {
+ ctx.PropertyErrorf("shared_libs", "shared_libs is not supported for device builds")
+ }
+
p.AddDepsOnPythonLauncherAndStdlib(ctx, hostStdLibTag, hostLauncherTag, hostlauncherSharedLibTag, false, ctx.Config().BuildOSTarget)
}
@@ -390,55 +340,38 @@
launcherSharedLibDeps = append(launcherSharedLibDeps, "libc_musl")
}
- switch p.properties.Actual_version {
- case pyVersion2:
- stdLib = "py2-stdlib"
-
- launcherModule = "py2-launcher"
- if autorun {
- launcherModule = "py2-launcher-autorun"
- }
-
- launcherSharedLibDeps = append(launcherSharedLibDeps, "libc++")
- case pyVersion3:
- var prebuiltStdLib bool
- if targetForDeps.Os.Bionic() {
- prebuiltStdLib = false
- } else if ctx.Config().VendorConfig("cpython3").Bool("force_build_host") {
- prebuiltStdLib = false
- } else {
- prebuiltStdLib = true
- }
-
- if prebuiltStdLib {
- stdLib = "py3-stdlib-prebuilt"
- } else {
- stdLib = "py3-stdlib"
- }
-
- launcherModule = "py3-launcher"
- if autorun {
- launcherModule = "py3-launcher-autorun"
- }
- if ctx.Config().HostStaticBinaries() && targetForDeps.Os == android.LinuxMusl {
- launcherModule += "-static"
- }
- if ctx.Device() {
- launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
- }
- default:
- panic(fmt.Errorf("unknown Python Actual_version: %q for module: %q.",
- p.properties.Actual_version, ctx.ModuleName()))
+ var prebuiltStdLib bool
+ if targetForDeps.Os.Bionic() {
+ prebuiltStdLib = false
+ } else if ctx.Config().VendorConfig("cpython3").Bool("force_build_host") {
+ prebuiltStdLib = false
+ } else {
+ prebuiltStdLib = true
}
+
+ if prebuiltStdLib {
+ stdLib = "py3-stdlib-prebuilt"
+ } else {
+ stdLib = "py3-stdlib"
+ }
+
+ launcherModule = "py3-launcher"
+ if autorun {
+ launcherModule = "py3-launcher-autorun"
+ }
+ if ctx.Config().HostStaticBinaries() && targetForDeps.Os == android.LinuxMusl {
+ launcherModule += "-static"
+ }
+ if ctx.Device() {
+ launcherSharedLibDeps = append(launcherSharedLibDeps, "liblog")
+ }
+
targetVariations := targetForDeps.Variations()
if ctx.ModuleName() != stdLib {
- stdLibVariations := make([]blueprint.Variation, 0, len(targetVariations)+1)
- stdLibVariations = append(stdLibVariations, blueprint.Variation{Mutator: "python_version", Variation: p.properties.Actual_version})
- stdLibVariations = append(stdLibVariations, targetVariations...)
// Using AddFarVariationDependencies for all of these because they can be for a different
// platform, like if the python module itself was being compiled for device, we may want
// the python interpreter built for host so that we can precompile python sources.
- ctx.AddFarVariationDependencies(stdLibVariations, stdLibTag, stdLib)
+ ctx.AddFarVariationDependencies(targetVariations, stdLibTag, stdLib)
}
ctx.AddFarVariationDependencies(targetVariations, launcherTag, launcherModule)
ctx.AddFarVariationDependencies(targetVariations, launcherSharedLibTag, launcherSharedLibDeps...)
@@ -446,8 +379,10 @@
// GenerateAndroidBuildActions performs build actions common to all Python modules
func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if proptools.BoolDefault(p.properties.Version.Py2.Enabled, false) {
+ ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3.")
+ }
expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs)
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: expandedSrcs.Strings()})
// Keep before any early returns.
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
TestOnly: Bool(p.sourceProperties.Test_only),
@@ -457,12 +392,32 @@
// expand data files from "data" property.
expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_common_data)...)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, p.properties.Device_first_data)...)
// Emulate the data property for java_data dependencies.
- for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) {
+ for _, javaData := range ctx.GetDirectDepsProxyWithTag(javaDataTag) {
expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
}
+ var directImplementationDeps android.Paths
+ var transitiveImplementationDeps []depset.DepSet[android.Path]
+ ctx.VisitDirectDepsProxyWithTag(sharedLibTag, func(dep android.ModuleProxy) {
+ sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
+ if sharedLibInfo.SharedLibrary != nil {
+ expandedData = append(expandedData, android.OutputFilesForModule(ctx, dep, "")...)
+ directImplementationDeps = append(directImplementationDeps, android.OutputFilesForModule(ctx, dep, "")...)
+ if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
+ transitiveImplementationDeps = append(transitiveImplementationDeps, info.ImplementationDeps)
+ p.bundleSharedLibs = append(p.bundleSharedLibs, info.ImplementationDeps.ToList()...)
+ }
+ } else {
+ ctx.PropertyErrorf("shared_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ }
+ })
+ android.SetProvider(ctx, cc.ImplementationDepInfoProvider, &cc.ImplementationDepInfo{
+ ImplementationDeps: depset.New(depset.PREORDER, directImplementationDeps, transitiveImplementationDeps),
+ })
+
// Validate pkg_path property
pkgPath := String(p.properties.Pkg_path)
if pkgPath != "" {
@@ -487,6 +442,15 @@
// generate the zipfile of all source and data files
p.srcsZip = p.createSrcsZip(ctx, pkgPath)
p.precompiledSrcsZip = p.precompileSrcs(ctx)
+
+ android.SetProvider(ctx, PythonLibraryInfoProvider, PythonLibraryInfo{
+ SrcsPathMappings: p.getSrcsPathMappings(),
+ DataPathMappings: p.getDataPathMappings(),
+ SrcsZip: p.getSrcsZip(),
+ PkgPath: p.getPkgPath(),
+ PrecompiledSrcsZip: p.getPrecompiledSrcsZip(),
+ BundleSharedLibs: p.getBundleSharedLibs(),
+ })
}
func isValidPythonPath(path string) error {
@@ -652,16 +616,16 @@
stdLib = p.srcsZip
stdLibPkg = p.getPkgPath()
} else {
- ctx.VisitDirectDepsWithTag(hostStdLibTag, func(module android.Module) {
- if dep, ok := module.(pythonDependency); ok {
- stdLib = dep.getPrecompiledSrcsZip()
- stdLibPkg = dep.getPkgPath()
+ ctx.VisitDirectDepsProxyWithTag(hostStdLibTag, func(module android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, PythonLibraryInfoProvider); ok {
+ stdLib = dep.PrecompiledSrcsZip
+ stdLibPkg = dep.PkgPath
}
})
}
- ctx.VisitDirectDepsWithTag(hostLauncherTag, func(module android.Module) {
- if dep, ok := module.(IntermPathProvider); ok {
- optionalLauncher := dep.IntermPathForModuleOut()
+ ctx.VisitDirectDepsProxyWithTag(hostLauncherTag, func(module android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ optionalLauncher := dep.OutputFile
if optionalLauncher.Valid() {
launcher = optionalLauncher.Path()
}
@@ -669,9 +633,9 @@
})
var launcherSharedLibs android.Paths
var ldLibraryPath []string
- ctx.VisitDirectDepsWithTag(hostlauncherSharedLibTag, func(module android.Module) {
- if dep, ok := module.(IntermPathProvider); ok {
- optionalPath := dep.IntermPathForModuleOut()
+ ctx.VisitDirectDepsProxyWithTag(hostlauncherSharedLibTag, func(module android.ModuleProxy) {
+ if dep, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ optionalPath := dep.OutputFile
if optionalPath.Valid() {
launcherSharedLibs = append(launcherSharedLibs, optionalPath.Path())
ldLibraryPath = append(ldLibraryPath, filepath.Dir(optionalPath.Path().String()))
@@ -702,16 +666,6 @@
return out
}
-// isPythonLibModule returns whether the given module is a Python library PythonLibraryModule or not
-func isPythonLibModule(module blueprint.Module) bool {
- if _, ok := module.(*PythonLibraryModule); ok {
- if _, ok := module.(*PythonBinaryModule); !ok {
- return true
- }
- }
- return false
-}
-
// collectPathsFromTransitiveDeps checks for source/data files for duplicate paths
// for module and its transitive dependencies and collects list of data/source file
// zips for transitive dependencies.
@@ -732,7 +686,7 @@
var result android.Paths
// visit all its dependencies in depth first.
- ctx.WalkDeps(func(child, parent android.Module) bool {
+ ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool {
// we only collect dependencies tagged as python library deps
if ctx.OtherModuleDependencyTag(child) != pythonLibTag {
return false
@@ -742,27 +696,29 @@
}
seen[child] = true
// Python modules only can depend on Python libraries.
- if !isPythonLibModule(child) {
+ dep, isLibrary := android.OtherModuleProvider(ctx, child, PythonLibraryInfoProvider)
+ _, isBinary := android.OtherModuleProvider(ctx, child, PythonBinaryInfoProvider)
+ if !isLibrary || isBinary {
ctx.PropertyErrorf("libs",
"the dependency %q of module %q is not Python library!",
ctx.OtherModuleName(child), ctx.ModuleName())
}
// collect source and data paths, checking that there are no duplicate output file conflicts
- if dep, ok := child.(pythonDependency); ok {
- srcs := dep.getSrcsPathMappings()
+ if isLibrary {
+ srcs := dep.SrcsPathMappings
for _, path := range srcs {
checkForDuplicateOutputPath(ctx, destToPySrcs,
path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))
}
- data := dep.getDataPathMappings()
+ data := dep.DataPathMappings
for _, path := range data {
checkForDuplicateOutputPath(ctx, destToPyData,
path.dest, path.src.String(), ctx.ModuleName(), ctx.OtherModuleName(child))
}
if precompiled {
- result = append(result, dep.getPrecompiledSrcsZip())
+ result = append(result, dep.PrecompiledSrcsZip)
} else {
- result = append(result, dep.getSrcsZip())
+ result = append(result, dep.SrcsZip)
}
}
return true
@@ -770,6 +726,56 @@
return result
}
+func (p *PythonLibraryModule) collectSharedLibDeps(ctx android.ModuleContext) android.Paths {
+ seen := make(map[android.Module]bool)
+
+ var result android.Paths
+
+ ctx.WalkDepsProxy(func(child, _ android.ModuleProxy) bool {
+ // we only collect dependencies tagged as python library deps
+ if ctx.OtherModuleDependencyTag(child) != pythonLibTag {
+ return false
+ }
+ if seen[child] {
+ return false
+ }
+ seen[child] = true
+ dep, isLibrary := android.OtherModuleProvider(ctx, child, PythonLibraryInfoProvider)
+ if isLibrary {
+ result = append(result, dep.BundleSharedLibs...)
+ }
+ return true
+ })
+ return result
+}
+
+func (p *PythonLibraryModule) zipSharedLibs(ctx android.ModuleContext, bundleSharedLibs android.Paths) android.Path {
+ // sort the paths to keep the output deterministic
+ sort.Slice(bundleSharedLibs, func(i, j int) bool {
+ return bundleSharedLibs[i].String() < bundleSharedLibs[j].String()
+ })
+
+ parArgs := []string{"-symlinks=false", "-P lib64"}
+ paths := android.Paths{}
+ for _, path := range bundleSharedLibs {
+ // specify relative root of file in following -f arguments
+ parArgs = append(parArgs, `-C `+filepath.Dir(path.String()))
+ parArgs = append(parArgs, `-f `+path.String())
+ paths = append(paths, path)
+ }
+ srcsZip := android.PathForModuleOut(ctx, ctx.ModuleName()+".sharedlibs.srcszip")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: zip,
+ Description: "bundle shared libraries for python binary",
+ Output: srcsZip,
+ Implicits: paths,
+ Args: map[string]string{
+ "args": strings.Join(parArgs, " "),
+ },
+ })
+ return srcsZip
+}
+
// chckForDuplicateOutputPath checks whether outputPath has already been included in map m, which
// would result in two files being placed in the same location.
// If there is a duplicate path, an error is thrown and true is returned
diff --git a/python/python_test.go b/python/python_test.go
index 6a6bd1d..5f971cd 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -36,10 +36,8 @@
}
var (
- buildNamePrefix = "soong_python_test"
- // We allow maching almost anything before the actual variant so that the os/arch variant
- // is matched.
- moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_]*%s": `
+ buildNamePrefix = "soong_python_test"
+ moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_]*": `
pkgPathErrTemplate = moduleVariantErrTemplate +
"pkg_path: %q must be a relative path contained in par file."
badIdentifierErrTemplate = moduleVariantErrTemplate +
@@ -48,9 +46,8 @@
"found two files to be placed at the same location within zip %q." +
" First file: in module %s at path %q." +
" Second file: in module %s at path %q."
- noSrcFileErr = moduleVariantErrTemplate + "doesn't have any source files!"
- badSrcFileExtErr = moduleVariantErrTemplate + "srcs: found non (.py|.proto) file: %q!"
- badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py) file: %q!"
+ badSrcFileExtErr = moduleVariantErrTemplate + `srcs: found non \(.py\|.proto\) file: %q!`
+ badDataFileExtErr = moduleVariantErrTemplate + `data: found \(.py\) file: %q!`
bpFile = "Android.bp"
data = []struct {
@@ -61,20 +58,6 @@
expectedBinaries []pyModule
}{
{
- desc: "module without any src files",
- mockFiles: map[string][]byte{
- filepath.Join("dir", bpFile): []byte(
- `python_library_host {
- name: "lib1",
- }`,
- ),
- },
- errors: []string{
- fmt.Sprintf(noSrcFileErr,
- "dir/Android.bp:1:1", "lib1", "PY3"),
- },
- },
- {
desc: "module with bad src file ext",
mockFiles: map[string][]byte{
filepath.Join("dir", bpFile): []byte(
@@ -89,7 +72,7 @@
},
errors: []string{
fmt.Sprintf(badSrcFileExtErr,
- "dir/Android.bp:3:11", "lib1", "PY3", "dir/file1.exe"),
+ "dir/Android.bp:3:11", "lib1", "dir/file1.exe"),
},
},
{
@@ -111,7 +94,7 @@
},
errors: []string{
fmt.Sprintf(badDataFileExtErr,
- "dir/Android.bp:6:11", "lib1", "PY3", "dir/file2.py"),
+ "dir/Android.bp:6:11", "lib1", "dir/file2.py"),
},
},
{
@@ -146,9 +129,9 @@
},
errors: []string{
fmt.Sprintf(pkgPathErrTemplate,
- "dir/Android.bp:11:15", "lib2", "PY3", "a/c/../../../"),
+ "dir/Android.bp:11:15", "lib2", "a/c/../../../"),
fmt.Sprintf(pkgPathErrTemplate,
- "dir/Android.bp:19:15", "lib3", "PY3", "/a/c/../../"),
+ "dir/Android.bp:19:15", "lib3", "/a/c/../../"),
},
},
{
@@ -171,11 +154,11 @@
},
errors: []string{
fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
- "lib1", "PY3", "a/b/c/-e/f/file1.py", "-e"),
+ "lib1", "a/b/c/-e/f/file1.py", "-e"),
fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
- "lib1", "PY3", "a/b/c/.file1.py", ".file1"),
+ "lib1", "a/b/c/.file1.py", ".file1"),
fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
- "lib1", "PY3", "a/b/c/123/file1.py", "123"),
+ "lib1", "a/b/c/123/file1.py", "123"),
},
},
{
@@ -219,115 +202,15 @@
},
errors: []string{
fmt.Sprintf(dupRunfileErrTemplate, "dir/Android.bp:20:6",
- "bin", "PY3", "a/b/c/file1.py", "bin", "dir/file1.py",
+ "bin", "a/b/c/file1.py", "bin", "dir/file1.py",
"lib1", "dir/c/file1.py"),
},
},
- {
- desc: "module for testing dependencies",
- mockFiles: map[string][]byte{
- filepath.Join("dir", bpFile): []byte(
- `python_defaults {
- name: "default_lib",
- srcs: [
- "default.py",
- ],
- version: {
- py2: {
- enabled: true,
- srcs: [
- "default_py2.py",
- ],
- },
- py3: {
- enabled: false,
- srcs: [
- "default_py3.py",
- ],
- },
- },
- }
-
- python_library_host {
- name: "lib5",
- pkg_path: "a/b/",
- srcs: [
- "file1.py",
- ],
- version: {
- py2: {
- enabled: true,
- },
- py3: {
- enabled: true,
- },
- },
- }
-
- python_library_host {
- name: "lib6",
- pkg_path: "c/d/",
- srcs: [
- "file2.py",
- ],
- libs: [
- "lib5",
- ],
- }
-
- python_binary_host {
- name: "bin",
- defaults: ["default_lib"],
- pkg_path: "e/",
- srcs: [
- "bin.py",
- ],
- libs: [
- "lib5",
- ],
- version: {
- py3: {
- enabled: true,
- srcs: [
- "file4.py",
- ],
- libs: [
- "lib6",
- ],
- },
- },
- }`,
- ),
- filepath.Join("dir", "default.py"): nil,
- filepath.Join("dir", "default_py2.py"): nil,
- filepath.Join("dir", "default_py3.py"): nil,
- filepath.Join("dir", "file1.py"): nil,
- filepath.Join("dir", "file2.py"): nil,
- filepath.Join("dir", "bin.py"): nil,
- filepath.Join("dir", "file4.py"): nil,
- },
- expectedBinaries: []pyModule{
- {
- name: "bin",
- actualVersion: "PY3",
- pyRunfiles: []string{
- "e/default.py",
- "e/bin.py",
- "e/default_py3.py",
- "e/file4.py",
- },
- srcsZip: "out/soong/.intermediates/dir/bin/PY3/bin.py.srcszip",
- },
- },
- },
}
)
func TestPythonModule(t *testing.T) {
for _, d := range data {
- if d.desc != "module with duplicate runfile path" {
- continue
- }
d.mockFiles[filepath.Join("common", bpFile)] = []byte(`
python_library {
name: "py3-stdlib",
@@ -416,10 +299,6 @@
for i, bp := range testCases {
ctx := android.GroupFixturePreparers(
PrepareForTestWithPythonBuildComponents,
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
-
- ctx.RegisterModuleType("python_defaults", DefaultsFactory)
- }),
android.PrepareForTestWithAllowMissingDependencies).
ExtendWithErrorHandler(android.FixtureIgnoreErrors).
RunTestWithBp(t, bp)
@@ -434,7 +313,7 @@
}
func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles []string) {
- module := ctx.ModuleForTests(name, variant)
+ module := ctx.ModuleForTests(t, name, variant)
base, baseOk := module.Module().(*PythonLibraryModule)
if !baseOk {
diff --git a/python/scripts/main.py b/python/scripts/main.py
index 225dbe4..35cdfc4 100644
--- a/python/scripts/main.py
+++ b/python/scripts/main.py
@@ -1,5 +1,13 @@
+
+import os
import runpy
+import shutil
import sys
+import tempfile
+import zipfile
+
+from pathlib import PurePath
+
sys.argv[0] = __loader__.archive
@@ -9,4 +17,32 @@
# when people try to use it.
sys.executable = None
-runpy._run_module_as_main("ENTRY_POINT", alter_argv=False)
+# Extract the shared libraries from the zip file into a temporary directory.
+# This works around the limitations of dynamic linker. Some Python libraries
+# reference the .so files relatively and so extracting only the .so files
+# does not work, so we extract the entire parent directory of the .so files to a
+# tempdir and then add that to sys.path.
+tempdir = None
+with zipfile.ZipFile(__loader__.archive) as z:
+ # any root so files or root directories that contain so files will be
+ # extracted to the tempdir so the linker load them, this minimizes the
+ # number of files that need to be extracted to a tempdir
+ extract_paths = {}
+ for member in z.infolist():
+ if member.filename.endswith('.so'):
+ extract_paths[PurePath(member.filename).parts[0]] = member.filename
+ if extract_paths:
+ tempdir = tempfile.mkdtemp()
+ for member in z.infolist():
+ if not PurePath(member.filename).parts[0] in extract_paths.keys():
+ continue
+ if member.is_dir():
+ os.makedirs(os.path.join(tempdir, member.filename))
+ else:
+ z.extract(member, tempdir)
+ sys.path.insert(0, tempdir)
+try:
+ runpy._run_module_as_main("ENTRY_POINT", alter_argv=False)
+finally:
+ if tempdir is not None:
+ shutil.rmtree(tempdir)
diff --git a/python/test.go b/python/test.go
index 9f57bea..df62ab7 100644
--- a/python/test.go
+++ b/python/test.go
@@ -68,6 +68,11 @@
// device.
Device_common_data []string `android:"path_device_common"`
+ // Same as data, but will add dependencies on modules via a device os variation and the
+ // device's first supported arch's variation. Useful for a host test that wants to embed a
+ // module built for device.
+ Device_first_data []string `android:"path_device_first"`
+
// list of java modules that provide data that should be installed alongside the test.
Java_data []string
@@ -189,15 +194,18 @@
for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Device_common_data) {
p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
}
+ for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Device_first_data) {
+ p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
+ }
if p.isTestHost() && len(p.testProperties.Data_device_bins_both) > 0 {
- ctx.VisitDirectDepsWithTag(dataDeviceBinsTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataDeviceBinsTag, func(dep android.ModuleProxy) {
p.data = append(p.data, android.DataPath{SrcPath: android.OutputFileForModule(ctx, dep, "")})
})
}
// Emulate the data property for java_data dependencies.
- for _, javaData := range ctx.GetDirectDepsWithTag(javaDataTag) {
+ for _, javaData := range ctx.GetDirectDepsProxyWithTag(javaDataTag) {
for _, javaDataSrcPath := range android.OutputFilesForModule(ctx, javaData, "") {
p.data = append(p.data, android.DataPath{SrcPath: javaDataSrcPath})
}
@@ -206,6 +214,50 @@
installDir := installDir(ctx, "nativetest", "nativetest64", ctx.ModuleName())
installedData := ctx.InstallTestData(installDir, p.data)
p.installedDest = ctx.InstallFile(installDir, p.installSource.Base(), p.installSource, installedData...)
+
+ // TODO: Remove the special case for kati
+ if !ctx.Config().KatiEnabled() {
+ // Install the test config in testcases/ directory for atest.
+ // Install configs in the root of $PRODUCT_OUT/testcases/$module
+ testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName())
+ if ctx.PrimaryArch() {
+ if p.testConfig != nil {
+ ctx.InstallFile(testCases, ctx.ModuleName()+".config", p.testConfig)
+ }
+ dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+ }
+ }
+ // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
+ testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
+ installedData := ctx.InstallTestData(testCases, p.data)
+ ctx.InstallFile(testCases, p.installSource.Base(), p.installSource, installedData...)
+ }
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+ if len(p.binaryProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, p.binaryProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+ if p.testConfig != nil {
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, p.testConfig.String())
+ }
+ if _, ok := p.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestOptionsTags = append(moduleInfoJSON.TestOptionsTags, p.testProperties.Test_options.Tags...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, p.androidMkSharedLibs...)
+ moduleInfoJSON.SharedLibs = append(moduleInfoJSON.Dependencies, p.androidMkSharedLibs...)
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+ if proptools.Bool(p.testProperties.Test_options.Unit_test) {
+ moduleInfoJSON.IsUnitTest = "true"
+ if p.isTestHost() {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
+ }
}
func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/python/testing.go b/python/testing.go
index ce1a5ab..fe53ee5 100644
--- a/python/testing.go
+++ b/python/testing.go
@@ -20,5 +20,4 @@
android.FixtureRegisterWithContext(registerPythonBinaryComponents),
android.FixtureRegisterWithContext(registerPythonLibraryComponents),
android.FixtureRegisterWithContext(registerPythonTestComponents),
- android.FixtureRegisterWithContext(registerPythonMutators),
)
diff --git a/python/tests/runtest.sh b/python/tests/runtest.sh
index c44ec58..9167561 100755
--- a/python/tests/runtest.sh
+++ b/python/tests/runtest.sh
@@ -25,15 +25,9 @@
if [[ ( ! -f $ANDROID_HOST_OUT/nativetest64/par_test/par_test ) ||
( ! -f $ANDROID_HOST_OUT/bin/py3-cmd )]]; then
- echo "Run 'm par_test py2-cmd py3-cmd' first"
+ echo "Run 'm par_test py3-cmd' first"
exit 1
fi
-if [ $(uname -s) = Linux ]; then
- if [[ ! -f $ANDROID_HOST_OUT/bin/py2-cmd ]]; then
- echo "Run 'm par_test py2-cmd py3-cmd' first"
- exit 1
- fi
-fi
export LD_LIBRARY_PATH=$ANDROID_HOST_OUT/lib64
@@ -47,16 +41,8 @@
cd $(dirname ${BASH_SOURCE[0]})
-if [ $(uname -s) = Linux ]; then
- PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py2-cmd py-cmd_test.py
-fi
PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py3-cmd py-cmd_test.py
-if [ $(uname -s) = Linux ]; then
- ARGTEST=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py2-cmd py-cmd_test.py arg1 arg2
- ARGTEST2=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py2-cmd py-cmd_test.py --arg1 arg2
-fi
-
ARGTEST=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py3-cmd py-cmd_test.py arg1 arg2
ARGTEST2=true PYTHONPATH=/extra $ANDROID_HOST_OUT/bin/py3-cmd py-cmd_test.py --arg1 arg2
diff --git a/root.bp b/root.bp
index ee208a0..7e0c1ed 100644
--- a/root.bp
+++ b/root.bp
@@ -2,12 +2,3 @@
// subdirs= and optional_subdirs= are obsolete and this file no longer
// needs a list of the top level directories that may contain Android.bp
// files.
-
-// TODO(b/253827323) Remove this. A module in internal builds needs to disable a new check,
-// IdentifierName, when errorprone is updated. In order to avoid having the update errorprone
-// in internal first, and then aosp, create this variable that we can fill out in internal in the
-// same topic as the errorprone update, then move the flag out of the variable after the update,
-// then remove the variable.
-disable_identifiername_for_errorprone_update = [
- "-Xep:IdentifierName:OFF",
-]
diff --git a/rust/afdo.go b/rust/afdo.go
index 6bd4bae..1bec709 100644
--- a/rust/afdo.go
+++ b/rust/afdo.go
@@ -66,7 +66,7 @@
return flags, deps
}
- ctx.VisitDirectDepsWithTag(cc.FdoProfileTag, func(m android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(cc.FdoProfileTag, func(m android.ModuleProxy) {
if info, ok := android.OtherModuleProvider(ctx, m, cc.FdoProfileProvider); ok {
path := info.Path
profileUseFlag := fmt.Sprintf(afdoFlagFormat, path.String())
diff --git a/rust/afdo_test.go b/rust/afdo_test.go
index 0cdf704..69aa97e 100644
--- a/rust/afdo_test.go
+++ b/rust/afdo_test.go
@@ -50,7 +50,7 @@
rustMockedFiles.AddToFixture(),
).RunTestWithBp(t, bp)
- foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+ foo := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Rule("rustc")
expectedCFlag := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo.afdo")
@@ -96,8 +96,8 @@
rustMockedFiles.AddToFixture(),
).RunTestWithBp(t, bp)
- fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
- fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+ fooArm := result.ModuleForTests(t, "foo", "android_arm_armv7-a-neon").Rule("rustc")
+ fooArm64 := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Rule("rustc")
expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm.afdo")
expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm64.afdo")
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 8de6b60..9894684 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -92,9 +92,6 @@
func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, binary.baseCompiler)
- if binary.distFile.Valid() {
- ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path())
- }
ret.Class = "EXECUTABLES"
}
@@ -143,9 +140,6 @@
} else if library.shared() {
ret.Class = "SHARED_LIBRARIES"
}
- if library.distFile.Valid() {
- ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
- }
ret.ExtraEntries = append(ret.ExtraEntries,
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if library.tocFile.Valid() {
@@ -158,10 +152,6 @@
ctx.SubAndroidMk(ret, procMacro.baseCompiler)
ret.Class = "PROC_MACRO_LIBRARIES"
- if procMacro.distFile.Valid() {
- ret.DistFiles = android.MakeDefaultDistFiles(procMacro.distFile.Path())
- }
-
}
func (sourceProvider *BaseSourceProvider) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
diff --git a/rust/benchmark.go b/rust/benchmark.go
index 8c3e515..3aa2f17 100644
--- a/rust/benchmark.go
+++ b/rust/benchmark.go
@@ -89,7 +89,7 @@
return rlibAutoDep
}
-func (benchmark *benchmarkDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (benchmark *benchmarkDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
}
@@ -130,3 +130,24 @@
benchmark.binaryDecorator.install(ctx)
}
+
+func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ benchmark.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+ if benchmark.testConfig != nil {
+ if _, ok := benchmark.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, benchmark.testConfig.String())
+ }
+
+ if len(benchmark.Properties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, benchmark.Properties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: benchmark.Properties.Test_suites,
+ })
+}
diff --git a/rust/benchmark_test.go b/rust/benchmark_test.go
index 734dda7..c239a09 100644
--- a/rust/benchmark_test.go
+++ b/rust/benchmark_test.go
@@ -28,7 +28,7 @@
srcs: ["foo.rs"],
}`)
- testingModule := ctx.ModuleForTests("my_bench", "linux_glibc_x86_64")
+ testingModule := ctx.ModuleForTests(t, "my_bench", "linux_glibc_x86_64")
expectedOut := "my_bench/linux_glibc_x86_64/my_bench"
outPath := testingModule.Output("my_bench").Output.String()
if !strings.Contains(outPath, expectedOut) {
@@ -43,7 +43,7 @@
srcs: ["foo.rs"],
}`)
- testingModule := ctx.ModuleForTests("my_bench", "android_arm64_armv8-a").Module().(*Module)
+ testingModule := ctx.ModuleForTests(t, "my_bench", "android_arm64_armv8-a").Module().(*Module)
if !android.InList("libcriterion.rlib-std", testingModule.Properties.AndroidMkRlibs) {
t.Errorf("rlib-std variant for libcriterion not detected as a rustlib-defined rlib dependency for device rust_benchmark module")
diff --git a/rust/binary.go b/rust/binary.go
index cba29a0..5a03d91 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -139,7 +139,10 @@
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
- flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.rustLibObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.staticLibObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.wholeStaticLibObjects...)
if binary.stripper.NeedsStrip(ctx) {
strippedOutputFile := outputFile
@@ -165,11 +168,11 @@
}
}
-func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (binary *binaryDecorator) stdLinkage(device bool) RustLinkage {
if binary.preferRlib() {
return RlibLinkage
}
- return binary.baseCompiler.stdLinkage(ctx)
+ return binary.baseCompiler.stdLinkage(device)
}
func (binary *binaryDecorator) binary() bool {
@@ -183,3 +186,8 @@
func (binary *binaryDecorator) testBinary() bool {
return false
}
+
+func (binary *binaryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ binary.baseCompiler.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
+}
diff --git a/rust/binary_test.go b/rust/binary_test.go
index ef93037..33710f9 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -36,7 +36,7 @@
host_supported: true,
}
`)
- fizzBuzz := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+ fizzBuzz := ctx.ModuleForTests(t, "fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
if !android.InList("libfoo.rlib-std", fizzBuzz.Properties.AndroidMkRlibs) {
t.Errorf("rustlibs dependency libfoo should be an rlib dep for host binaries")
}
@@ -65,8 +65,8 @@
host_supported: true,
}`)
- fizzBuzzHost := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
- fizzBuzzDevice := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
+ fizzBuzzHost := ctx.ModuleForTests(t, "fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+ fizzBuzzDevice := ctx.ModuleForTests(t, "fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
if !android.InList("libfoo.rlib-std", fizzBuzzHost.Properties.AndroidMkRlibs) {
t.Errorf("rustlibs dependency libfoo should be an rlib dep for host modules")
@@ -76,7 +76,7 @@
t.Errorf("rustlibs dependency libfoo should be an dylib dep for device modules")
}
- rlibLinkDevice := ctx.ModuleForTests("rlib_linked", "android_arm64_armv8-a").Module().(*Module)
+ rlibLinkDevice := ctx.ModuleForTests(t, "rlib_linked", "android_arm64_armv8-a").Module().(*Module)
if !android.InList("libfoo.rlib-std", rlibLinkDevice.Properties.AndroidMkRlibs) {
t.Errorf("rustlibs dependency libfoo should be an rlib dep for device modules when prefer_rlib is set")
@@ -100,7 +100,7 @@
host_supported: true,
}`)
- mod := ctx.ModuleForTests("rlib_linked", "android_arm64_armv8-a").Module().(*Module)
+ mod := ctx.ModuleForTests(t, "rlib_linked", "android_arm64_armv8-a").Module().(*Module)
if !android.InList("libfoo.rlib-std", mod.Properties.AndroidMkRlibs) {
t.Errorf("rustlibs dependency libfoo should be an rlib dep when prefer_rlib is defined")
@@ -119,7 +119,7 @@
srcs: ["foo.rs"],
}`)
- path := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module).HostToolPath()
+ path := ctx.ModuleForTests(t, "fizz-buzz", "linux_glibc_x86_64").Module().(*Module).HostToolPath()
if g, w := path.String(), "/host/linux-x86/bin/fizz-buzz"; !strings.Contains(g, w) {
t.Errorf("wrong host tool path, expected %q got %q", w, g)
}
@@ -133,7 +133,7 @@
srcs: ["foo.rs"],
}`)
- fizzBuzz := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc")
+ fizzBuzz := ctx.ModuleForTests(t, "fizz-buzz", "linux_glibc_x86_64").Rule("rustc")
flags := fizzBuzz.Args["rustcFlags"]
if strings.Contains(flags, "--test") {
@@ -150,7 +150,7 @@
bootstrap: true,
}`)
- foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+ foo := ctx.ModuleForTests(t, "foo", "android_arm64_armv8-a").Rule("rustc")
flag := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker64"
if !strings.Contains(foo.Args["linkFlags"], flag) {
@@ -166,8 +166,8 @@
static_executable: true,
}`)
- fizzOut := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
- fizzMod := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
+ fizzOut := ctx.ModuleForTests(t, "fizz", "android_arm64_armv8-a").Rule("rustc")
+ fizzMod := ctx.ModuleForTests(t, "fizz", "android_arm64_armv8-a").Module().(*Module)
flags := fizzOut.Args["rustcFlags"]
linkFlags := fizzOut.Args["linkFlags"]
@@ -200,7 +200,7 @@
name: "libfoo",
}`)
- fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustc")
+ fizzBuzz := ctx.ModuleForTests(t, "fizz-buzz", "android_arm64_armv8-a").Rule("rustc")
linkFlags := fizzBuzz.Args["linkFlags"]
if !strings.Contains(linkFlags, "/libfoo.so") {
t.Errorf("missing shared dependency 'libfoo.so' in linkFlags: %#v", linkFlags)
@@ -223,7 +223,7 @@
}
`)
- foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a")
+ foo := ctx.ModuleForTests(t, "foo", "android_arm64_armv8-a")
foo.Output("unstripped/foo")
foo.Output("foo")
@@ -233,7 +233,7 @@
t.Errorf("installed binary not based on stripped version: %v", cp.Input)
}
- fizzBar := ctx.ModuleForTests("bar", "android_arm64_armv8-a").MaybeOutput("unstripped/bar")
+ fizzBar := ctx.ModuleForTests(t, "bar", "android_arm64_armv8-a").MaybeOutput("unstripped/bar")
if fizzBar.Rule != nil {
t.Errorf("unstripped binary exists, so stripped binary has incorrectly been generated")
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 898e792..2f84168 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -309,7 +309,8 @@
var cmd, cmdDesc string
if b.Properties.Custom_bindgen != "" {
- cmd = ctx.GetDirectDepWithTag(b.Properties.Custom_bindgen, customBindgenDepTag).(android.HostToolProvider).HostToolPath().String()
+ m := ctx.GetDirectDepProxyWithTag(b.Properties.Custom_bindgen, customBindgenDepTag)
+ cmd = android.OtherModuleProviderOrDefault(ctx, m, android.HostToolProviderInfoProvider).HostToolPath.String()
cmdDesc = b.Properties.Custom_bindgen
} else {
cmd = "$bindgenCmd"
@@ -397,7 +398,7 @@
//
// This is necessary to avoid a circular dependency between the source variant and the
// dependent cc module.
- deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, String(b.Properties.Static_inline_library))
}
deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs.GetOrDefault(ctx, nil)...)
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 2b7362f..267fb1c 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -67,10 +67,10 @@
cflags: ["--default-flag"],
}
`)
- libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
- libbindgenStatic := ctx.ModuleForTests("libbindgen_staticlib", "android_arm64_armv8-a_source").Output("bindings.rs")
- libbindgenHeader := ctx.ModuleForTests("libbindgen_headerlib", "android_arm64_armv8-a_source").Output("bindings.rs")
- libbindgenHeaderModule := ctx.ModuleForTests("libbindgen_headerlib", "android_arm64_armv8-a_source").Module().(*Module)
+ libbindgen := ctx.ModuleForTests(t, "libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgenStatic := ctx.ModuleForTests(t, "libbindgen_staticlib", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgenHeader := ctx.ModuleForTests(t, "libbindgen_headerlib", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgenHeaderModule := ctx.ModuleForTests(t, "libbindgen_headerlib", "android_arm64_armv8-a_source").Module().(*Module)
// Ensure that the flags are present and escaped
if !strings.Contains(libbindgen.Args["flags"], "'--bindgen-flag.*'") {
t.Errorf("missing bindgen flags in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
@@ -113,7 +113,7 @@
}
`)
- libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgen := ctx.ModuleForTests(t, "libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
// The rule description should contain the custom binary name rather than bindgen, so checking the description
// should be sufficient.
@@ -155,8 +155,8 @@
}
`)
- libbindgen_cstd := ctx.ModuleForTests("libbindgen_cstd", "android_arm64_armv8-a_source").Output("bindings.rs")
- libbindgen_cppstd := ctx.ModuleForTests("libbindgen_cppstd", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgen_cstd := ctx.ModuleForTests(t, "libbindgen_cstd", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgen_cppstd := ctx.ModuleForTests(t, "libbindgen_cppstd", "android_arm64_armv8-a_source").Output("bindings.rs")
if !strings.Contains(libbindgen_cstd.Args["cflags"], "-std=foo") {
t.Errorf("c_std value not passed in to rust_bindgen as a clang flag")
@@ -216,7 +216,7 @@
],
}
`)
- libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgen := ctx.ModuleForTests(t, "libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
if !strings.Contains(libbindgen.Args["flagfiles"], "/dev/null") {
t.Errorf("missing /dev/null in rust_bindgen rule: flags %#v", libbindgen.Args["flagfiles"])
@@ -246,7 +246,7 @@
include_dirs: ["src/"],
}
`)
- libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
+ libbindgen := ctx.ModuleForTests(t, "libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
// Make sure the flag to support `static inline` functions is present
if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns") {
t.Errorf("missing flag to handle static inlining in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
diff --git a/rust/builder.go b/rust/builder.go
index a1e17fc..1b6a6c1 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -30,11 +30,11 @@
rustc = pctx.AndroidStaticRule("rustc",
blueprint.RuleParams{
Command: "$envVars $rustcCmd " +
- "-C linker=${config.RustLinker} " +
- "-C link-args=\"${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
+ "-C linker=${RustcLinkerCmd} " +
+ "-C link-args=\"--android-clang-bin=${config.ClangCmd} ${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
"--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
" && grep ^$out: $out.d.raw > $out.d",
- CommandDeps: []string{"$rustcCmd"},
+ CommandDeps: []string{"$rustcCmd", "${RustcLinkerCmd}", "${config.ClangCmd}"},
// 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.
// Those extra lines cause ninja warning:
@@ -102,10 +102,10 @@
`KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
`$rustExtractor $envVars ` +
`$rustcCmd ` +
- `-C linker=${config.RustLinker} ` +
- `-C link-args="${crtBegin} ${linkFlags} ${crtEnd}" ` +
+ `-C linker=${RustcLinkerCmd} ` +
+ `-C link-args="--android-clang-bin=${config.ClangCmd} ${crtBegin} ${linkFlags} ${crtEnd}" ` +
`$in ${libFlags} $rustcFlags`,
- CommandDeps: []string{"$rustExtractor", "$kytheVnames"},
+ CommandDeps: []string{"$rustExtractor", "$kytheVnames", "${RustcLinkerCmd}", "${config.ClangCmd}"},
Rspfile: "${out}.rsp",
RspfileContent: "$in",
},
@@ -119,6 +119,7 @@
func init() {
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
+ pctx.HostBinToolVariable("RustcLinkerCmd", "rustc_linker")
cc.TransformRlibstoStaticlib = TransformRlibstoStaticlib
}
@@ -170,7 +171,7 @@
return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, getTransformProperties(ctx, "rlib"))
}
-// TransformRlibstoStaticlib is assumed to be called from the cc module, and
+// TransformRlibstoStaticlib is assumed to be callable from the cc module, and
// thus needs to reconstruct the common set of flags which need to be passed
// to the rustc compiler.
func TransformRlibstoStaticlib(ctx android.ModuleContext, mainSrc android.Path, deps []cc.RustRlibDep,
@@ -184,7 +185,7 @@
rustPathDeps.linkDirs = append(rustPathDeps.linkDirs, rlibDep.LinkDirs...)
}
- ccModule := ctx.(cc.ModuleContext).Module().(*cc.Module)
+ mod := ctx.Module().(cc.LinkableInterface)
toolchain := config.FindToolchain(ctx.Os(), ctx.Arch())
t := transformProperties{
// Crate name can be a predefined value as this is a staticlib and
@@ -194,10 +195,10 @@
crateName: "generated_rust_staticlib",
is64Bit: toolchain.Is64Bit(),
targetTriple: toolchain.RustTriple(),
- bootstrap: ccModule.Bootstrap(),
- inRecovery: ccModule.InRecovery(),
- inRamdisk: ccModule.InRamdisk(),
- inVendorRamdisk: ccModule.InVendorRamdisk(),
+ bootstrap: mod.Bootstrap(),
+ inRecovery: mod.InRecovery(),
+ inRamdisk: mod.InRamdisk(),
+ inVendorRamdisk: mod.InVendorRamdisk(),
// crateType indicates what type of crate to build
crateType: "staticlib",
@@ -263,7 +264,7 @@
libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
}
for _, lib := range deps.DyLibs {
- libFlags = append(libFlags, "--extern "+lib.CrateName+"="+lib.Path.String())
+ libFlags = append(libFlags, "--extern force:"+lib.CrateName+"="+lib.Path.String())
}
for _, proc_macro := range deps.ProcMacros {
libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
@@ -401,6 +402,11 @@
linkFlags = append(linkFlags, dynamicLinker)
}
+ if generatedLib := cc.GenerateRustStaticlib(ctx, deps.ccRlibDeps); generatedLib != nil {
+ deps.StaticLibs = append(deps.StaticLibs, generatedLib)
+ linkFlags = append(linkFlags, generatedLib.String())
+ }
+
libFlags := makeLibFlags(deps)
// Collect dependencies
@@ -411,6 +417,7 @@
implicits = append(implicits, deps.SharedLibDeps...)
implicits = append(implicits, deps.srcProviderFiles...)
implicits = append(implicits, deps.AfdoProfiles...)
+ implicits = append(implicits, deps.LinkerDeps...)
implicits = append(implicits, deps.CrtBegin...)
implicits = append(implicits, deps.CrtEnd...)
diff --git a/rust/builder_test.go b/rust/builder_test.go
index ae5ccde..7d6b56a 100644
--- a/rust/builder_test.go
+++ b/rust/builder_test.go
@@ -85,7 +85,7 @@
"out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so",
"out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.clippy",
"out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/unstripped/libfizz_buzz.dylib.so",
- "out/soong/target/product/test_device/system/lib64/libfizz_buzz.dylib.so",
+ "out/target/product/test_device/system/lib64/libfizz_buzz.dylib.so",
"out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/meta_lic",
},
},
@@ -118,7 +118,7 @@
"out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz",
"out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.clippy",
"out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/unstripped/fizz_buzz",
- "out/soong/target/product/test_device/system/bin/fizz_buzz",
+ "out/target/product/test_device/system/bin/fizz_buzz",
"out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/meta_lic",
},
},
@@ -154,13 +154,13 @@
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so.toc",
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/meta_lic",
"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/rustdoc.timestamp",
- "out/soong/target/product/test_device/system/lib64/librust_ffi.so",
+ "out/target/product/test_device/system/lib64/librust_ffi.so",
},
},
}
for _, tc := range testcases {
t.Run(tc.testName, func(t *testing.T) {
- modOutputs := ctx.ModuleForTests(tc.moduleName, tc.variant).AllOutputs()
+ modOutputs := ctx.ModuleForTests(t, tc.moduleName, tc.variant).AllOutputs()
sort.Strings(tc.expectedFiles)
sort.Strings(modOutputs)
android.AssertStringPathsRelativeToTopEquals(
diff --git a/rust/clippy_test.go b/rust/clippy_test.go
index bd3bfb1..3563348 100644
--- a/rust/clippy_test.go
+++ b/rust/clippy_test.go
@@ -62,13 +62,13 @@
android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
).RunTest(t)
- r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ r := result.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
android.AssertStringEquals(t, "libfoo flags", tc.fooFlags, r.Args["clippyFlags"])
- r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ r = result.ModuleForTests(t, "libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
android.AssertStringEquals(t, "libbar flags", "${config.ClippyDefaultLints}", r.Args["clippyFlags"])
- r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ r = result.ModuleForTests(t, "libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
if r.Rule != nil {
t.Errorf("libfoobar is setup to use clippy when explicitly disabled: clippyFlags=%q", r.Args["clippyFlags"])
}
diff --git a/rust/compiler.go b/rust/compiler.go
index fd86917..c3bc937 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -30,9 +30,8 @@
type RustLinkage int
const (
- DefaultLinkage RustLinkage = iota
+ DylibLinkage RustLinkage = iota
RlibLinkage
- DylibLinkage
)
type compiler interface {
@@ -40,6 +39,7 @@
compilerFlags(ctx ModuleContext, flags Flags) Flags
cfgFlags(ctx ModuleContext, flags Flags) Flags
featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags
+ baseCompilerProps() BaseCompilerProperties
compilerProps() []interface{}
compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput
compilerDeps(ctx DepsContext, deps Deps) Deps
@@ -69,7 +69,7 @@
Disabled() bool
SetDisabled()
- stdLinkage(ctx *depsContext) RustLinkage
+ stdLinkage(device bool) RustLinkage
noStdlibs() bool
unstrippedOutputFilePath() android.Path
@@ -78,6 +78,8 @@
checkedCrateRootPath() (android.Path, error)
Aliases() map[string]string
+
+ moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
}
func (compiler *baseCompiler) edition() string {
@@ -150,21 +152,21 @@
Aliases []string
// list of rust rlib crate dependencies
- Rlibs []string `android:"arch_variant"`
+ Rlibs proptools.Configurable[[]string] `android:"arch_variant"`
// list of rust automatic crate dependencies.
// Rustlibs linkage is rlib for host targets and dylib for device targets.
Rustlibs proptools.Configurable[[]string] `android:"arch_variant"`
// list of rust proc_macro crate dependencies
- Proc_macros []string `android:"arch_variant"`
+ Proc_macros proptools.Configurable[[]string] `android:"arch_variant"`
// list of C shared library dependencies
- Shared_libs []string `android:"arch_variant"`
+ Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
// list of C static library dependencies. These dependencies do not normally propagate to dependents
// and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library.
- Static_libs []string `android:"arch_variant"`
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
// Similar to static_libs, but will bundle the static library dependency into a library. This is helpful
// to avoid having to redeclare the dependency for dependents of this library, but in some cases may also
@@ -179,13 +181,13 @@
//
// For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will
// include all of the static libraries symbols in any dylibs or binaries which use this rlib as well.
- Whole_static_libs []string `android:"arch_variant"`
+ Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant"`
// list of Rust system library dependencies.
//
// This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates
// like `core` and `alloc`.
- Stdlibs []string `android:"arch_variant"`
+ Stdlibs proptools.Configurable[[]string] `android:"arch_variant"`
// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
// modules which create library variants (rust_bindgen). This must be the expected extern crate name used in
@@ -255,8 +257,6 @@
location installLocation
sanitize *sanitize
- distFile android.OptionalPath
-
installDeps android.InstallPaths
// unstripped output file.
@@ -316,17 +316,42 @@
return aliases
}
-func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage {
+func (compiler *baseCompiler) stdLinkage(device bool) RustLinkage {
// For devices, we always link stdlibs in as dylibs by default.
if compiler.preferRlib() {
return RlibLinkage
- } else if ctx.Device() {
+ } else if device {
return DylibLinkage
} else {
return RlibLinkage
}
}
+func (compiler *baseCompiler) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ moduleInfoJSON.Class = []string{"ETC"}
+
+ mod := ctx.Module().(*Module)
+
+ moduleInfoJSON.SharedLibs = mod.transitiveAndroidMkSharedLibs.ToList()
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.transitiveAndroidMkSharedLibs.ToList()...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkDylibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkHeaderLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkProcMacroLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkRlibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, mod.Properties.AndroidMkStaticLibs...)
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+ moduleInfoJSON.StaticLibs = mod.Properties.AndroidMkStaticLibs
+
+ if mod.sourceProvider != nil {
+ moduleInfoJSON.SubName += mod.sourceProvider.getSubName()
+ }
+ moduleInfoJSON.SubName += mod.AndroidMkSuffix()
+
+ if mod.Properties.IsSdkVariant {
+ moduleInfoJSON.Uninstallable = true
+ }
+}
+
var _ compiler = (*baseCompiler)(nil)
func (compiler *baseCompiler) inData() bool {
@@ -337,6 +362,10 @@
return []interface{}{&compiler.Properties}
}
+func (compiler *baseCompiler) baseCompilerProps() BaseCompilerProperties {
+ return compiler.Properties
+}
+
func cfgsToFlags(cfgs []string) []string {
flags := make([]string, 0, len(cfgs))
for _, cfg := range cfgs {
@@ -496,13 +525,13 @@
}
func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
- deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
+ deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs.GetOrDefault(ctx, nil)...)
deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs.GetOrDefault(ctx, nil)...)
- deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
- deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
- deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...)
+ deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros.GetOrDefault(ctx, nil)...)
+ deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs.GetOrDefault(ctx, nil)...)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs.GetOrDefault(ctx, nil)...)
+ deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
+ deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs.GetOrDefault(ctx, nil)...)
if !Bool(compiler.Properties.No_stdlibs) {
for _, stdlib := range config.Stdlibs {
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 4caa12b..8805d15 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -34,7 +34,7 @@
],
}`)
- libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"fizz\"'") ||
!strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'feature=\"buzz\"'") {
@@ -55,7 +55,7 @@
],
}`)
- libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
if !strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'std'") ||
!strings.Contains(libfooDylib.Args["rustcFlags"], "cfg 'cfg1=\"one\"'") {
@@ -81,8 +81,8 @@
}
`)
- libfoo := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
- libfooLto := ctx.ModuleForTests("libfoo_lto", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooLto := ctx.ModuleForTests(t, "libfoo_lto", "linux_glibc_x86_64_dylib").Rule("rustc")
if strings.Contains(libfoo.Args["rustcFlags"], "-C lto=thin") {
t.Fatalf("libfoo expected to disable lto -- rustcFlags: %#v", libfoo.Args["rustcFlags"])
@@ -174,7 +174,7 @@
cargo_pkg_version: "1.0.0"
}`)
- fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
+ fizz := ctx.ModuleForTests(t, "fizz", "android_arm64_armv8-a").Rule("rustc")
if !strings.Contains(fizz.Args["envVars"], "CARGO_BIN_NAME=fizz") {
t.Fatalf("expected 'CARGO_BIN_NAME=fizz' in envVars, actual envVars: %#v", fizz.Args["envVars"])
@@ -199,11 +199,11 @@
srcs: ["foo.rs"],
}`)
- install_path_lib64 := ctx.ModuleForTests("libfoo",
+ install_path_lib64 := ctx.ModuleForTests(t, "libfoo",
"android_arm64_armv8-a_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
- install_path_lib32 := ctx.ModuleForTests("libfoo",
+ install_path_lib32 := ctx.ModuleForTests(t, "libfoo",
"android_arm_armv7-a-neon_dylib").Module().(*Module).compiler.(*libraryDecorator).path.String()
- install_path_bin := ctx.ModuleForTests("fizzbuzz",
+ install_path_bin := ctx.ModuleForTests(t, "fizzbuzz",
"android_arm64_armv8-a").Module().(*Module).compiler.(*binaryDecorator).path.String()
if !strings.HasSuffix(install_path_lib64, "system/lib64/libfoo.dylib.so") {
@@ -259,13 +259,13 @@
android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
).RunTest(t)
- r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ r := result.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags)
- r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ r = result.ModuleForTests(t, "libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}")
- r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ r = result.ModuleForTests(t, "libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
})
}
@@ -283,9 +283,9 @@
srcs: ["foo.rs"],
crate_name: "foo",
}`)
- fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
- fooRlib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
- fooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
+ fizz := ctx.ModuleForTests(t, "fizz", "android_arm64_armv8-a").Module().(*Module)
+ fooRlib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
+ fooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
if !android.InList("libstd", fizz.Properties.AndroidMkDylibs) {
t.Errorf("libstd is not linked dynamically for device binaries")
diff --git a/rust/config/OWNERS b/rust/config/OWNERS
index dfff873..e4bf5e6 100644
--- a/rust/config/OWNERS
+++ b/rust/config/OWNERS
@@ -1,2 +1,2 @@
-per-file global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+per-file global.go = srhines@google.com, pirama@google.com, yikong@google.com
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 94a4457..efcd56a 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -45,6 +45,14 @@
"-Z branch-protection=bti,pac-ret",
"-Z stack-protector=none",
},
+ "armv9-3a": []string{
+ "-Z branch-protection=bti,pac-ret",
+ "-Z stack-protector=none",
+ },
+ "armv9-4a": []string{
+ "-Z branch-protection=bti,pac-ret",
+ "-Z stack-protector=none",
+ },
}
)
diff --git a/rust/config/global.go b/rust/config/global.go
index 7b79fca..907316f 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -25,7 +25,7 @@
var (
pctx = android.NewPackageContext("android/soong/rust/config")
- RustDefaultVersion = "1.81.0"
+ RustDefaultVersion = "1.83.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -42,6 +42,8 @@
}
GlobalRustFlags = []string{
+ // Allow `--extern force:foo` for dylib support
+ "-Z unstable-options",
"-Z stack-protector=strong",
"-Z remap-cwd-prefix=.",
"-C debuginfo=2",
@@ -121,7 +123,7 @@
pctx.StaticVariable("RustBin", "${RustPath}/bin")
pctx.ImportAs("cc_config", "android/soong/cc/config")
- pctx.StaticVariable("RustLinker", "${cc_config.ClangBin}/clang++")
+ pctx.StaticVariable("ClangCmd", "${cc_config.ClangBin}/clang++")
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
diff --git a/rust/config/lints.go b/rust/config/lints.go
index 735aa16..715e8aa 100644
--- a/rust/config/lints.go
+++ b/rust/config/lints.go
@@ -55,6 +55,7 @@
defaultClippyLints = []string{
// Let people hack in peace. ;)
"-A clippy::disallowed_names",
+ "-A clippy::empty_line_after_doc_comments",
"-A clippy::type-complexity",
"-A clippy::unnecessary_fallible_conversions",
"-A clippy::unnecessary-wraps",
diff --git a/rust/coverage.go b/rust/coverage.go
index 381fcf1..798b21d 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -15,12 +15,13 @@
package rust
import (
+ "android/soong/android"
+
"github.com/google/blueprint"
"android/soong/cc"
)
-var CovLibraryName = "libprofile-clang-extras"
var ProfilerBuiltins = "libprofiler_builtins.rust_sysroot"
// Add '%c' to default specifier after we resolve http://b/210012154
@@ -37,12 +38,20 @@
return []interface{}{&cov.Properties}
}
+func getClangProfileLibraryName(ctx ModuleContextIntf) string {
+ if ctx.RustModule().UseSdk() {
+ return "libprofile-clang-extras_ndk"
+ } else {
+ return "libprofile-clang-extras"
+ }
+}
+
func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps {
if cov.Properties.NeedCoverageVariant {
if ctx.Device() {
ctx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, cc.CoverageDepTag, CovLibraryName)
+ }, cc.CoverageDepTag, getClangProfileLibraryName(ctx))
}
// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
@@ -65,16 +74,18 @@
flags.RustFlags = append(flags.RustFlags,
"-C instrument-coverage", "-g")
if ctx.Device() {
- coverage := ctx.GetDirectDepWithTag(CovLibraryName, cc.CoverageDepTag).(cc.LinkableInterface)
+ m := ctx.GetDirectDepProxyWithTag(getClangProfileLibraryName(ctx), cc.CoverageDepTag)
+ coverage := android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider)
flags.LinkFlags = append(flags.LinkFlags,
- profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
- deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
+ profileInstrFlag, "-g", coverage.OutputFile.Path().String(), "-Wl,--wrap,open")
+ deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile.Path())
}
// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
- profiler_builtins := ctx.GetDirectDepWithTag(ProfilerBuiltins, rlibDepTag).(*Module)
- deps.RLibs = append(deps.RLibs, RustLibrary{Path: profiler_builtins.OutputFile().Path(), CrateName: profiler_builtins.CrateName()})
+ m := ctx.GetDirectDepProxyWithTag(ProfilerBuiltins, rlibDepTag)
+ profiler_builtins := android.OtherModuleProviderOrDefault(ctx, m, cc.LinkableInfoProvider)
+ deps.RLibs = append(deps.RLibs, RustLibrary{Path: profiler_builtins.OutputFile.Path(), CrateName: profiler_builtins.CrateName})
}
if cc.EnableContinuousCoverage(ctx) {
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 0f599d7..f9198f1 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -51,10 +51,10 @@
}
// Just test the dylib variants unless the library coverage logic changes to distinguish between the types.
- libfooCov := ctx.ModuleForTests("libfoo_cov", "android_arm64_armv8-a_dylib_cov").Rule("rustc")
- libbarNoCov := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustc")
- fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
- buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
+ libfooCov := ctx.ModuleForTests(t, "libfoo_cov", "android_arm64_armv8-a_dylib_cov").Rule("rustc")
+ libbarNoCov := ctx.ModuleForTests(t, "libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustc")
+ fizzCov := ctx.ModuleForTests(t, "fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
+ buzzNoCov := ctx.ModuleForTests(t, "buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
rustcCoverageFlags := []string{"-C instrument-coverage", " -g "}
for _, flag := range rustcCoverageFlags {
@@ -103,7 +103,7 @@
srcs: ["foo.rs"],
}`)
- fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustc")
+ fizz := ctx.ModuleForTests(t, "fizz", "android_arm64_armv8-a_cov").Rule("rustc")
if !strings.Contains(fizz.Args["linkFlags"], "libprofile-clang-extras.a") {
t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
}
diff --git a/rust/doc.go b/rust/doc.go
index fe20523..3616c8e 100644
--- a/rust/doc.go
+++ b/rust/doc.go
@@ -37,14 +37,14 @@
FlagWithArg("-C ", docDir.String()).
FlagWithArg("-D ", docDir.String())
- ctx.VisitAllModules(func(module android.Module) {
- if !module.Enabled(ctx) {
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if !android.OtherModulePointerProviderOrDefault(ctx, module, android.CommonModuleInfoProvider).Enabled {
return
}
- if m, ok := module.(*Module); ok {
- if m.docTimestampFile.Valid() {
- zipCmd.Implicit(m.docTimestampFile.Path())
+ if m, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok {
+ if m.DocTimestampFile.Valid() {
+ zipCmd.Implicit(m.DocTimestampFile.Path())
}
}
})
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 1770d2e..9e8efd7 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -121,7 +121,7 @@
return out
}
-func (fuzzer *fuzzDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (fuzzer *fuzzDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
}
@@ -130,7 +130,7 @@
}
func (fuzz *fuzzDecorator) install(ctx ModuleContext) {
- fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule, pctx)
+ fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule)
installBase := "fuzz"
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index 6cb8b93..f462795 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -41,7 +41,7 @@
`)
// Check that appropriate dependencies are added and that the rustlib linkage is correct.
- fuzz_libtest_mod := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module)
+ fuzz_libtest_mod := ctx.ModuleForTests(t, "fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module)
if !android.InList("liblibfuzzer_sys.rlib-std", fuzz_libtest_mod.Properties.AndroidMkRlibs) {
t.Errorf("liblibfuzzer_sys rlib library dependency missing for rust_fuzz module. %#v", fuzz_libtest_mod.Properties.AndroidMkRlibs)
}
@@ -50,21 +50,21 @@
}
// Check that compiler flags are set appropriately .
- fuzz_libtest := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc")
+ fuzz_libtest := ctx.ModuleForTests(t, "fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc")
if !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-C passes='sancov-module'") ||
!strings.Contains(fuzz_libtest.Args["rustcFlags"], "--cfg fuzzing") {
t.Errorf("rust_fuzz module does not contain the expected flags (sancov-module, cfg fuzzing).")
}
// Check that host modules support fuzzing.
- host_fuzzer := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc")
+ host_fuzzer := ctx.ModuleForTests(t, "fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc")
if !strings.Contains(host_fuzzer.Args["rustcFlags"], "-C passes='sancov-module'") ||
!strings.Contains(host_fuzzer.Args["rustcFlags"], "--cfg fuzzing") {
t.Errorf("rust_fuzz_host module does not contain the expected flags (sancov-module, cfg fuzzing).")
}
// Check that dependencies have 'fuzzer' variants produced for them as well.
- libtest_fuzzer := ctx.ModuleForTests("libtest_fuzzing", "android_arm64_armv8-a_rlib_rlib-std_fuzzer").Output("libtest_fuzzing.rlib")
+ libtest_fuzzer := ctx.ModuleForTests(t, "libtest_fuzzing", "android_arm64_armv8-a_rlib_rlib-std_fuzzer").Output("libtest_fuzzing.rlib")
if !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-C passes='sancov-module'") ||
!strings.Contains(libtest_fuzzer.Args["rustcFlags"], "--cfg fuzzing") {
t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov-module, cfg fuzzing).")
@@ -93,7 +93,7 @@
}
`)
- fuzz_libtest := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module)
+ fuzz_libtest := ctx.ModuleForTests(t, "fuzz_libtest", "android_arm64_armv8-a_fuzzer").Module().(*Module)
if !strings.Contains(fuzz_libtest.FuzzSharedLibraries().String(), ":libcc_direct_dep.so") {
t.Errorf("rust_fuzz does not contain the expected bundled direct shared libs ('libcc_direct_dep'): %#v", fuzz_libtest.FuzzSharedLibraries().String())
@@ -134,17 +134,24 @@
}
`)
- fuzz_shared_libtest := ctx.ModuleForTests("fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
- fuzz_static_libtest := ctx.ModuleForTests("fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
- fuzz_staticffi_libtest := ctx.ModuleForTests("fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
+ fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module()
+ fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module()
+ fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module()
- if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
+ fuzzSharedLibraries := func(module android.Module) string {
+ if info, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+ return info.FuzzSharedLibraries.String()
+ }
+ return ""
}
- if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
+
+ if libs := fuzzSharedLibraries(fuzz_shared_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+ t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", libs)
}
- if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
- t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_rlib ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String())
+ if libs := fuzzSharedLibraries(fuzz_static_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+ t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
+ }
+ if libs := fuzzSharedLibraries(fuzz_staticffi_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+ t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
}
}
diff --git a/rust/image.go b/rust/image.go
index 51b8289..aa10a6d 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -137,7 +137,7 @@
// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
// module. As well as SoC specific modules, vendor variants must be installed to /vendor
// unless they have "odm_available: true".
- return mod.InVendor() && !mod.VendorVariantToOdm()
+ return mod.HasVendorVariant() && mod.InVendor() && !mod.VendorVariantToOdm()
}
func (mod *Module) InstallInOdm() bool {
diff --git a/rust/image_test.go b/rust/image_test.go
index d84eb10..e5ecd79 100644
--- a/rust/image_test.go
+++ b/rust/image_test.go
@@ -22,14 +22,13 @@
"android/soong/cc"
)
-// Test that cc modules can depend on vendor_available rust_ffi_rlib/rust_ffi_static libraries.
+// Test that cc modules can depend on vendor_available rust_ffi_static libraries.
func TestVendorLinkage(t *testing.T) {
ctx := testRust(t, `
cc_binary {
name: "fizz_vendor_available",
static_libs: [
"libfoo_vendor",
- "libfoo_vendor_static"
],
vendor_available: true,
}
@@ -38,24 +37,18 @@
static_libs: ["libfoo_vendor"],
soc_specific: true,
}
- rust_ffi_rlib {
- name: "libfoo_vendor",
- crate_name: "foo",
- srcs: ["foo.rs"],
- vendor_available: true,
- }
rust_ffi_static {
- name: "libfoo_vendor_static",
+ name: "libfoo_vendor",
crate_name: "foo",
srcs: ["foo.rs"],
vendor_available: true,
}
`)
- vendorBinary := ctx.ModuleForTests("fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
+ vendorBinary := ctx.ModuleForTests(t, "fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
- if android.InList("libfoo_vendor_static.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
- t.Errorf("vendorBinary should not have a staticlib dependency on libfoo_vendor_static.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
+ if android.InList("libfoo_vendor.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
+ t.Errorf("vendorBinary should not have a staticlib dependency on libfoo_vendor.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
}
}
@@ -71,7 +64,7 @@
}
`)
- vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Rule("rustc")
+ vendor := ctx.ModuleForTests(t, "libfoo", "android_vendor_arm64_armv8-a_shared").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"])
@@ -83,7 +76,7 @@
t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"])
}
- product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_shared").Rule("rustc")
+ product := ctx.ModuleForTests(t, "libfoo", "android_product_arm64_armv8-a_shared").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"])
}
@@ -94,7 +87,7 @@
t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"])
}
- system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("rustc")
+ system := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Rule("rustc")
if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vndk'") {
t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"])
}
@@ -107,36 +100,29 @@
}
-// Test that cc modules can link against vendor_ramdisk_available rust_ffi_rlib and rust_ffi_static libraries.
+// Test that cc modules can link against vendor_ramdisk_available rust_ffi_static libraries.
func TestVendorRamdiskLinkage(t *testing.T) {
ctx := testRust(t, `
cc_library_shared {
name: "libcc_vendor_ramdisk",
static_libs: [
"libfoo_vendor_ramdisk",
- "libfoo_static_vendor_ramdisk"
],
system_shared_libs: [],
vendor_ramdisk_available: true,
}
- rust_ffi_rlib {
- name: "libfoo_vendor_ramdisk",
- crate_name: "foo",
- srcs: ["foo.rs"],
- vendor_ramdisk_available: true,
- }
rust_ffi_static {
- name: "libfoo_static_vendor_ramdisk",
+ name: "libfoo_vendor_ramdisk",
crate_name: "foo",
srcs: ["foo.rs"],
vendor_ramdisk_available: true,
}
`)
- vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module)
+ vendorRamdiskLibrary := ctx.ModuleForTests(t, "libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module)
- if android.InList("libfoo_static_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
- t.Errorf("libcc_vendor_ramdisk should not have a dependency on the libfoo_static_vendor_ramdisk static library")
+ if android.InList("libfoo_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
+ t.Errorf("libcc_vendor_ramdisk should not have a dependency on the libfoo_vendor_ramdisk static library")
}
}
@@ -158,7 +144,7 @@
}
func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) {
- mod := ctx.ModuleForTests(name, variant).Module().(*Module)
+ mod := ctx.ModuleForTests(t, name, variant).Module().(*Module)
partitionDefined := false
checkPartition := func(specific bool, partition string) {
if specific {
diff --git a/rust/library.go b/rust/library.go
index bd3359b..415785a 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -25,6 +25,7 @@
"android/soong/android"
"android/soong/cc"
+ cc_config "android/soong/cc/config"
)
var (
@@ -40,15 +41,10 @@
android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
android.RegisterModuleType("rust_ffi", RustFFIFactory)
android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
- android.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory)
android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
- android.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
-
- // TODO: Remove when all instances of rust_ffi_static have been switched to rust_ffi_rlib
- // Alias rust_ffi_static to the rust_ffi_rlib factory
- android.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory)
- android.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory)
+ android.RegisterModuleType("rust_ffi_static", RustLibraryRlibFactory)
+ android.RegisterModuleType("rust_ffi_host_static", RustLibraryRlibHostFactory)
}
type VariantLibraryProperties struct {
@@ -69,12 +65,28 @@
// path to include directories to export to cc_* modules, only relevant for static/shared variants.
Export_include_dirs []string `android:"path,arch_variant"`
+ // Version script to pass to the linker. By default this will replace the
+ // implicit rustc emitted version script to mirror expected behavior in CC.
+ // This is only relevant for rust_ffi_shared modules which are exposing a
+ // versioned C API.
+ Version_script *string `android:"path,arch_variant"`
+
+ // A version_script formatted text file with additional symbols to export
+ // for rust shared or dylibs which the rustc compiler does not automatically
+ // export, e.g. additional symbols from whole_static_libs. Unlike
+ // Version_script, this is not meant to imply a stable API.
+ Extra_exported_symbols *string `android:"path,arch_variant"`
+
// Whether this library is part of the Rust toolchain sysroot.
Sysroot *bool
- // Exclude this rust_ffi target from being included in APEXes.
- // TODO(b/362509506): remove this once stubs are properly supported by rust_ffi targets.
+ // Deprecated - exclude this rust_ffi target from being included in APEXes.
+ // TODO(b/362509506): remove this once all apex_exclude uses are switched to stubs.
Apex_exclude *bool
+
+ // Generate stubs to make this library accessible to APEXes.
+ // Can only be set for modules producing shared libraries.
+ Stubs cc.StubsProperties `android:"arch_variant"`
}
type LibraryMutatedProperties struct {
@@ -102,6 +114,15 @@
// Whether this library variant should be link libstd via rlibs
VariantIsStaticStd bool `blueprint:"mutated"`
+
+ // This variant is a stubs lib
+ BuildStubs bool `blueprint:"mutated"`
+ // This variant is the latest version
+ IsLatestVersion bool `blueprint:"mutated"`
+ // Version of the stubs lib
+ StubsVersion string `blueprint:"mutated"`
+ // List of all stubs versions associated with an implementation lib
+ AllStubsVersions []string `blueprint:"mutated"`
}
type libraryDecorator struct {
@@ -114,13 +135,30 @@
includeDirs android.Paths
sourceProvider SourceProvider
- isFFI bool
-
// table-of-contents file for cdylib crates to optimize out relinking when possible
tocFile android.OptionalPath
+
+ // Path to the file containing the APIs exported by this library
+ stubsSymbolFilePath android.Path
+ apiListCoverageXmlPath android.ModuleOutPath
+ versionScriptPath android.OptionalPath
+}
+
+func (library *libraryDecorator) stubs() bool {
+ return library.MutatedProperties.BuildStubs
+}
+
+func (library *libraryDecorator) setAPIListCoverageXMLPath(xml android.ModuleOutPath) {
+ library.apiListCoverageXmlPath = xml
+}
+
+func (library *libraryDecorator) libraryProperties() LibraryCompilerProperties {
+ return library.Properties
}
type libraryInterface interface {
+ cc.VersionedInterface
+
rlib() bool
dylib() bool
static() bool
@@ -157,10 +195,16 @@
toc() android.OptionalPath
- isFFILibrary() bool
+ IsStubsImplementationRequired() bool
+ setAPIListCoverageXMLPath(out android.ModuleOutPath)
+
+ libraryProperties() LibraryCompilerProperties
}
func (library *libraryDecorator) nativeCoverage() bool {
+ if library.BuildStubs() {
+ return false
+ }
return true
}
@@ -262,18 +306,96 @@
}
}
-func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
- if library.static() || library.MutatedProperties.VariantIsStaticStd || (library.rlib() && library.isFFILibrary()) {
+func (library *libraryDecorator) stdLinkage(device bool) RustLinkage {
+ if library.static() || library.MutatedProperties.VariantIsStaticStd {
return RlibLinkage
} else if library.baseCompiler.preferRlib() {
return RlibLinkage
}
- return DefaultLinkage
+ return DylibLinkage
}
var _ compiler = (*libraryDecorator)(nil)
var _ libraryInterface = (*libraryDecorator)(nil)
+var _ cc.VersionedInterface = (*libraryDecorator)(nil)
var _ exportedFlagsProducer = (*libraryDecorator)(nil)
+var _ cc.VersionedInterface = (*libraryDecorator)(nil)
+
+func (library *libraryDecorator) HasLLNDKStubs() bool {
+ // Rust LLNDK is currently unsupported
+ return false
+}
+
+func (library *libraryDecorator) HasVendorPublicLibrary() bool {
+ // Rust does not support vendor_public_library yet.
+ return false
+}
+
+func (library *libraryDecorator) HasLLNDKHeaders() bool {
+ // Rust LLNDK is currently unsupported
+ return false
+}
+
+func (library *libraryDecorator) HasStubsVariants() bool {
+ // Just having stubs.symbol_file is enough to create a stub variant. In that case
+ // the stub for the future API level is created.
+ return library.Properties.Stubs.Symbol_file != nil ||
+ len(library.Properties.Stubs.Versions) > 0
+}
+
+func (library *libraryDecorator) IsStubsImplementationRequired() bool {
+ return BoolDefault(library.Properties.Stubs.Implementation_installable, true)
+}
+
+func (library *libraryDecorator) GetAPIListCoverageXMLPath() android.ModuleOutPath {
+ return library.apiListCoverageXmlPath
+}
+
+func (library *libraryDecorator) AllStubsVersions() []string {
+ return library.MutatedProperties.AllStubsVersions
+}
+
+func (library *libraryDecorator) SetAllStubsVersions(versions []string) {
+ library.MutatedProperties.AllStubsVersions = versions
+}
+
+func (library *libraryDecorator) SetStubsVersion(version string) {
+ library.MutatedProperties.StubsVersion = version
+}
+
+func (library *libraryDecorator) SetBuildStubs(isLatest bool) {
+ library.MutatedProperties.BuildStubs = true
+ library.MutatedProperties.IsLatestVersion = isLatest
+}
+
+func (library *libraryDecorator) BuildStubs() bool {
+ return library.MutatedProperties.BuildStubs
+}
+
+func (library *libraryDecorator) ImplementationModuleName(name string) string {
+ return name
+}
+
+func (library *libraryDecorator) IsLLNDKMovedToApex() bool {
+ // Rust does not support LLNDK.
+ return false
+}
+
+func (library *libraryDecorator) StubsVersion() string {
+ return library.MutatedProperties.StubsVersion
+}
+
+// stubsVersions implements cc.VersionedInterface.
+func (library *libraryDecorator) StubsVersions(ctx android.BaseModuleContext) []string {
+ if !library.HasStubsVariants() {
+ return nil
+ }
+
+ // Future API level is implicitly added if there isn't
+ versions := cc.AddCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
+ cc.NormalizeVersions(ctx, versions)
+ return versions
+}
// rust_library produces all Rust variants (rust_library_dylib and
// rust_library_rlib).
@@ -283,8 +405,7 @@
return module.Init()
}
-// rust_ffi produces all FFI variants (rust_ffi_shared, rust_ffi_static, and
-// rust_ffi_rlib).
+// rust_ffi produces all FFI variants (rust_ffi_shared, rust_ffi_static).
func RustFFIFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyFFI()
@@ -298,7 +419,7 @@
return module.Init()
}
-// rust_library_rlib produces an rlib (Rust crate type "rlib").
+// rust_library_rlib and rust_ffi_static produces an rlib (Rust crate type "rlib").
func RustLibraryRlibFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyRlib()
@@ -322,7 +443,7 @@
}
// rust_ffi_host produces all FFI variants for the host
-// (rust_ffi_rlib_host, rust_ffi_static_host, and rust_ffi_shared_host).
+// (rust_ffi_static_host and rust_ffi_shared_host).
func RustFFIHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyFFI()
@@ -337,8 +458,8 @@
return module.Init()
}
-// rust_library_rlib_host produces an rlib for the host (Rust crate
-// type "rlib").
+// rust_library_rlib_host and rust_ffi_static_host produces an rlib for the host
+// (Rust crate type "rlib").
func RustLibraryRlibHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyRlib()
@@ -353,23 +474,16 @@
return module.Init()
}
-// rust_ffi_rlib_host produces an rlib for the host (Rust crate
-// type "rlib").
-func RustFFIRlibHostFactory() android.Module {
- module, library := NewRustLibrary(android.HostSupported)
- library.BuildOnlyRlib()
+func CheckRustLibraryProperties(mctx android.DefaultableHookContext) {
+ lib := mctx.Module().(*Module).compiler.(libraryInterface)
+ if !lib.buildShared() {
+ if lib.libraryProperties().Stubs.Symbol_file != nil ||
+ lib.libraryProperties().Stubs.Implementation_installable != nil ||
+ len(lib.libraryProperties().Stubs.Versions) > 0 {
- library.isFFI = true
- return module.Init()
-}
-
-// rust_ffi_rlib produces an rlib (Rust crate type "rlib").
-func RustFFIRlibFactory() android.Module {
- module, library := NewRustLibrary(android.HostAndDeviceSupported)
- library.BuildOnlyRlib()
-
- library.isFFI = true
- return module.Init()
+ mctx.PropertyErrorf("stubs", "stubs properties can only be set for rust_ffi or rust_ffi_shared modules")
+ }
+ }
}
func (library *libraryDecorator) BuildOnlyFFI() {
@@ -378,8 +492,6 @@
library.MutatedProperties.BuildRlib = true
library.MutatedProperties.BuildShared = true
library.MutatedProperties.BuildStatic = false
-
- library.isFFI = true
}
func (library *libraryDecorator) BuildOnlyRust() {
@@ -408,8 +520,6 @@
library.MutatedProperties.BuildDylib = false
library.MutatedProperties.BuildShared = false
library.MutatedProperties.BuildStatic = true
-
- library.isFFI = true
}
func (library *libraryDecorator) BuildOnlyShared() {
@@ -417,12 +527,6 @@
library.MutatedProperties.BuildDylib = false
library.MutatedProperties.BuildStatic = false
library.MutatedProperties.BuildShared = true
-
- library.isFFI = true
-}
-
-func (library *libraryDecorator) isFFILibrary() bool {
- return library.isFFI
}
func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
@@ -441,6 +545,7 @@
module.compiler = library
+ module.SetDefaultableHook(CheckRustLibraryProperties)
return module, library
}
@@ -484,13 +589,6 @@
cfgs := library.baseCompiler.Properties.Cfgs.GetOrDefault(ctx, nil)
- if library.dylib() {
- // We need to add a dependency on std in order to link crates as dylibs.
- // The hack to add this dependency is guarded by the following cfg so
- // that we don't force a dependency when it isn't needed.
- cfgs = append(cfgs, "android_dylib")
- }
-
cfgFlags := cfgsToFlags(cfgs)
flags.RustFlags = append(flags.RustFlags, cfgFlags...)
@@ -511,7 +609,9 @@
flags = CommonLibraryCompilerFlags(ctx, flags)
- if library.isFFI {
+ if library.rlib() || library.shared() {
+ // rlibs collect include dirs as well since they are used to
+ // produce staticlibs in the final C linkages
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)...)
}
@@ -574,9 +674,36 @@
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
- flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.rustLibObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.sharedLibObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.staticLibObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.wholeStaticLibObjects...)
+
+ if String(library.Properties.Version_script) != "" {
+ if String(library.Properties.Extra_exported_symbols) != "" {
+ ctx.ModuleErrorf("version_script and extra_exported_symbols cannot both be set.")
+ }
+
+ if library.shared() {
+ // "-Wl,--android-version-script" signals to the rustcLinker script
+ // that the default version script should be removed.
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,--android-version-script="+android.PathForModuleSrc(ctx, String(library.Properties.Version_script)).String())
+ deps.LinkerDeps = append(deps.LinkerDeps, android.PathForModuleSrc(ctx, String(library.Properties.Version_script)))
+ } else if !library.static() && !library.rlib() {
+ // We include rlibs here because rust_ffi produces rlib variants
+ ctx.PropertyErrorf("version_script", "can only be set for rust_ffi modules")
+ }
+ }
+
+ if String(library.Properties.Extra_exported_symbols) != "" {
+ // Passing a second version script (rustc calculates and emits a
+ // default version script) will concatenate the first version script.
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,--version-script="+android.PathForModuleSrc(ctx, String(library.Properties.Extra_exported_symbols)).String())
+ deps.LinkerDeps = append(deps.LinkerDeps, android.PathForModuleSrc(ctx, String(library.Properties.Extra_exported_symbols)))
+ }
if library.dylib() {
+
// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
// https://github.com/rust-lang/rust/issues/19680
// https://github.com/rust-lang/rust/issues/34909
@@ -584,7 +711,11 @@
}
// Call the appropriate builder for this library type
- if library.rlib() {
+ if library.stubs() {
+ ccFlags := library.getApiStubsCcFlags(ctx)
+ stubObjs := library.compileModuleLibApiStubs(ctx, ccFlags)
+ cc.BuildRustStubs(ctx, outputFile, stubObjs, ccFlags)
+ } else if library.rlib() {
ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile
} else if library.dylib() {
ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile
@@ -594,19 +725,36 @@
ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile
}
+ // rlibs and dylibs propagate their shared, whole static, and rustlib dependencies
if library.rlib() || library.dylib() {
library.flagExporter.exportLinkDirs(deps.linkDirs...)
- library.flagExporter.exportLinkObjects(deps.linkObjects...)
+ library.flagExporter.exportRustLibs(deps.rustLibObjects...)
+ library.flagExporter.exportSharedLibs(deps.sharedLibObjects...)
+ library.flagExporter.exportWholeStaticLibs(deps.wholeStaticLibObjects...)
}
+ // rlibs also propagate their staticlibs dependencies
+ if library.rlib() {
+ library.flagExporter.exportStaticLibs(deps.staticLibObjects...)
+ }
// Since we have FFI rlibs, we need to collect their includes as well
- if library.static() || library.shared() || library.rlib() {
- android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+ if library.static() || library.shared() || library.rlib() || library.stubs() {
+ ccExporter := cc.FlagExporterInfo{
IncludeDirs: android.FirstUniquePaths(library.includeDirs),
- })
+ }
+ if library.rlib() {
+ ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedCcRlibDeps...)
+ ccExporter.RustRlibDeps = append(ccExporter.RustRlibDeps, deps.reexportedWholeCcRlibDeps...)
+ }
+ android.SetProvider(ctx, cc.FlagExporterInfoProvider, ccExporter)
}
- if library.shared() {
+ if library.dylib() {
+ // reexport whole-static'd dependencies for dylibs.
+ library.flagExporter.wholeRustRlibDeps = append(library.flagExporter.wholeRustRlibDeps, deps.reexportedWholeCcRlibDeps...)
+ }
+
+ if library.shared() || library.stubs() {
// Optimize out relinking against shared libraries whose interface hasn't changed by
// depending on a table of contents file instead of the library itself.
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc")
@@ -617,9 +765,7 @@
TableOfContents: android.OptionalPathForPath(tocFile),
SharedLibrary: outputFile,
Target: ctx.Target(),
- // TODO: when rust supports stubs uses the stubs state rather than inferring it from
- // apex_exclude.
- IsStubs: Bool(library.Properties.Apex_exclude),
+ IsStubs: library.BuildStubs(),
})
}
@@ -631,8 +777,10 @@
TransitiveStaticLibrariesForOrdering: depSet,
})
}
+ cc.AddStubDependencyProviders(ctx)
- library.flagExporter.setProvider(ctx)
+ // Set our flagexporter provider to export relevant Rust flags
+ library.flagExporter.setRustProvider(ctx)
return ret
}
@@ -650,6 +798,53 @@
}
}
+func (library *libraryDecorator) getApiStubsCcFlags(ctx ModuleContext) cc.Flags {
+ ccFlags := cc.Flags{}
+ toolchain := cc_config.FindToolchain(ctx.Os(), ctx.Arch())
+
+ platformSdkVersion := ""
+ if ctx.Device() {
+ platformSdkVersion = ctx.Config().PlatformSdkVersion().String()
+ }
+ minSdkVersion := cc.MinSdkVersion(ctx.RustModule(), cc.CtxIsForPlatform(ctx), ctx.Device(), platformSdkVersion)
+
+ // Collect common CC compilation flags
+ ccFlags = cc.CommonLinkerFlags(ctx, ccFlags, true, toolchain, false)
+ ccFlags = cc.CommonLibraryLinkerFlags(ctx, ccFlags, toolchain, library.getStem(ctx))
+ ccFlags = cc.AddStubLibraryCompilerFlags(ccFlags)
+ ccFlags = cc.AddTargetFlags(ctx, ccFlags, toolchain, minSdkVersion, false)
+
+ return ccFlags
+}
+
+func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, ccFlags cc.Flags) cc.Objects {
+ mod := ctx.RustModule()
+
+ symbolFile := String(library.Properties.Stubs.Symbol_file)
+ library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile)
+
+ apiParams := cc.ApiStubsParams{
+ NotInPlatform: mod.NotInPlatform(),
+ IsNdk: mod.IsNdk(ctx.Config()),
+ BaseModuleName: mod.BaseModuleName(),
+ ModuleName: ctx.ModuleName(),
+ }
+ flag := cc.GetApiStubsFlags(apiParams)
+
+ nativeAbiResult := cc.ParseNativeAbiDefinition(ctx, symbolFile,
+ android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
+ objs := cc.CompileStubLibrary(ctx, ccFlags, nativeAbiResult.StubSrc, mod.getSharedFlags())
+
+ library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.VersionScript)
+
+ // Parse symbol file to get API list for coverage
+ if library.StubsVersion() == "current" && ctx.PrimaryArch() && !mod.InRecovery() && !mod.InProduct() && !mod.InVendor() {
+ library.apiListCoverageXmlPath = cc.ParseSymbolFileForAPICoverage(ctx, symbolFile)
+ }
+
+ return objs
+}
+
func (library *libraryDecorator) rustdoc(ctx ModuleContext, flags Flags,
deps PathDeps) android.OptionalPath {
// rustdoc has builtin support for documenting config specific information
@@ -687,6 +882,20 @@
library.MutatedProperties.VariantIsDisabled = true
}
+func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ library.baseCompiler.moduleInfoJSON(ctx, moduleInfoJSON)
+
+ if library.rlib() {
+ moduleInfoJSON.Class = []string{"RLIB_LIBRARIES"}
+ } else if library.dylib() {
+ moduleInfoJSON.Class = []string{"DYLIB_LIBRARIES"}
+ } else if library.static() {
+ moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
+ } else if library.shared() {
+ moduleInfoJSON.Class = []string{"SHARED_LIBRARIES"}
+ }
+}
+
var validCrateName = regexp.MustCompile("[^a-zA-Z0-9_]+")
func validateLibraryStem(ctx BaseModuleContext, filename string, crate_name string) {
@@ -745,6 +954,9 @@
}
func (libraryTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
@@ -812,6 +1024,12 @@
},
sourceDepTag, ctx.ModuleName())
}
+
+ if prebuilt, ok := m.compiler.(*prebuiltLibraryDecorator); ok {
+ if Bool(prebuilt.Properties.Force_use_prebuilt) && len(prebuilt.prebuiltSrcs()) > 0 {
+ m.Prebuilt().SetUsePrebuilt(true)
+ }
+ }
}
type libstdTransitionMutator struct{}
@@ -821,11 +1039,7 @@
// Only create a variant if a library is actually being built.
if library, ok := m.compiler.(libraryInterface); ok {
if library.rlib() && !library.sysroot() {
- if library.isFFILibrary() {
- return []string{"rlib-std"}
- } else {
- return []string{"rlib-std", "dylib-std"}
- }
+ return []string{"rlib-std", "dylib-std"}
}
}
}
@@ -833,6 +1047,9 @@
}
func (libstdTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
diff --git a/rust/library_test.go b/rust/library_test.go
index 35a420c..6cc4f25 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -42,10 +42,10 @@
}`)
// Test all variants are being built.
- libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
- libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
- libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
- libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared").Rule("rustc")
+ libfooRlib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
+ libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_shared").Rule("rustc")
rlibCrateType := "rlib"
dylibCrateType := "dylib"
@@ -82,29 +82,13 @@
crate_name: "foo",
}`)
- libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") {
t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
}
}
-// Check that we are passing the android_dylib config flag
-func TestAndroidDylib(t *testing.T) {
- ctx := testRust(t, `
- rust_library_host_dylib {
- name: "libfoo",
- srcs: ["foo.rs"],
- crate_name: "foo",
- }`)
-
- libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
-
- if !strings.Contains(libfooDylib.Args["rustcFlags"], "--cfg 'android_dylib'") {
- t.Errorf("missing android_dylib cfg flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"])
- }
-}
-
func TestValidateLibraryStem(t *testing.T) {
testRustError(t, "crate_name must be defined.", `
rust_library_host {
@@ -150,7 +134,7 @@
crate_name: "foo",
}`)
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared")
libfooOutput := libfoo.Rule("rustc")
if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
@@ -176,7 +160,7 @@
shared_libs: ["libfoo"],
}`)
- fizzbuzz := ctx.ModuleForTests("fizzbuzz", "android_arm64_armv8-a").Rule("ld")
+ fizzbuzz := ctx.ModuleForTests(t, "fizzbuzz", "android_arm64_armv8-a").Rule("ld")
if !android.SuffixInList(fizzbuzz.Implicits.Strings(), "libfoo.so.toc") {
t.Errorf("missing expected libfoo.so.toc implicit dependency, instead found: %#v",
@@ -192,7 +176,7 @@
crate_name: "foo",
}`)
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_rlib-std")
if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) {
t.Errorf("Static libstd rlib expected to be a dependency of Rust rlib libraries. Rlib deps are: %#v",
@@ -202,9 +186,9 @@
func TestNativeDependencyOfRlib(t *testing.T) {
ctx := testRust(t, `
- rust_ffi_rlib {
- name: "libffi_rlib",
- crate_name: "ffi_rlib",
+ rust_ffi_static {
+ name: "libffi_static",
+ crate_name: "ffi_static",
rlibs: ["librust_rlib"],
srcs: ["foo.rs"],
}
@@ -225,9 +209,9 @@
}
`)
- rustRlibRlibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_rlib-std")
- rustRlibDylibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_dylib-std")
- ffiRlib := ctx.ModuleForTests("libffi_rlib", "android_arm64_armv8-a_rlib_rlib-std")
+ rustRlibRlibStd := ctx.ModuleForTests(t, "librust_rlib", "android_arm64_armv8-a_rlib_rlib-std")
+ rustRlibDylibStd := ctx.ModuleForTests(t, "librust_rlib", "android_arm64_armv8-a_rlib_dylib-std")
+ ffiRlib := ctx.ModuleForTests(t, "libffi_static", "android_arm64_armv8-a_rlib_rlib-std")
modules := []android.TestingModule{
rustRlibRlibStd,
@@ -301,10 +285,10 @@
],
}`)
- libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std")
- libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
- libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std")
- libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
+ libfooRlib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_rlib_rlib-std")
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_dylib")
+ libfooFFIRlib := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std")
+ libfooShared := ctx.ModuleForTests(t, "libfoo.ffi", "linux_glibc_x86_64_shared")
for _, static := range []android.TestingModule{libfooRlib, libfooFFIRlib} {
if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) {
@@ -346,7 +330,7 @@
}
`)
- foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib")
+ foo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib")
foo.Output("libfoo.dylib.so")
foo.Output("unstripped/libfoo.dylib.so")
// Check that the `cp` rule is using the stripped version as input.
@@ -355,7 +339,7 @@
t.Errorf("installed library not based on stripped version: %v", cp.Input)
}
- fizzBar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeOutput("unstripped/libbar.dylib.so")
+ fizzBar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_dylib").MaybeOutput("unstripped/libbar.dylib.so")
if fizzBar.Rule != nil {
t.Errorf("unstripped library exists, so stripped library has incorrectly been generated")
}
@@ -388,15 +372,15 @@
prefer_rlib: true,
}`)
- libfooDylib := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
- libfooRlibStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
- libfooRlibDynamic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
+ libfooDylib := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
+ libfooRlibStatic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
+ libfooRlibDynamic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
- libbarShared := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module().(*Module)
- libbarFFIRlib := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
+ libbarShared := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_shared").Module().(*Module)
+ libbarFFIRlib := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
// prefer_rlib works the same for both rust_library and rust_ffi, so a single check is sufficient here.
- libbarRlibStd := ctx.ModuleForTests("libbar.prefer_rlib", "android_arm64_armv8-a_shared").Module().(*Module)
+ libbarRlibStd := ctx.ModuleForTests(t, "libbar.prefer_rlib", "android_arm64_armv8-a_shared").Module().(*Module)
if !android.InList("libstd", libfooRlibStatic.Properties.AndroidMkRlibs) {
t.Errorf("rlib-std variant for device rust_library_rlib does not link libstd as an rlib")
@@ -412,10 +396,10 @@
t.Errorf("Device rust_ffi_shared does not link libstd as an dylib")
}
if !android.InList("libstd", libbarFFIRlib.Properties.AndroidMkRlibs) {
- t.Errorf("Device rust_ffi_rlib does not link libstd as an rlib")
+ t.Errorf("Device rust_ffi_static does not link libstd as an rlib")
}
if !android.InList("libfoo.rlib-std", libbarFFIRlib.Properties.AndroidMkRlibs) {
- t.Errorf("Device rust_ffi_rlib does not link dependent rustlib rlib-std variant")
+ t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant")
}
if !android.InList("libstd", libbarRlibStd.Properties.AndroidMkRlibs) {
t.Errorf("rust_ffi with prefer_rlib does not link libstd as an rlib")
@@ -438,6 +422,388 @@
shared_libs: ["libbar"],
host_supported: true,
}`)
- libfooStatic := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_static").Rule("cc")
+ libfooStatic := ctx.ModuleForTests(t, "libfoo", "linux_glibc_x86_64_static").Rule("cc")
android.AssertStringDoesContain(t, "cFlags for lib module", libfooStatic.Args["cFlags"], " -Irust_includes ")
}
+
+// Make sure cc_rustlibs_for_make has the expected behavior, and that
+// cc_library_static does as well.
+// This is here instead of cc/library_test.go because the test needs to
+// define a rust_ffi module which can't be done in soong-cc to avoid the
+// circular dependency.
+func TestCCRustlibsForMake(t *testing.T) {
+ t.Parallel()
+ result := testRust(t, `
+ rust_ffi_static {
+ name: "libbar",
+ srcs: ["foo.rs"],
+ crate_name: "bar",
+ export_include_dirs: ["rust_includes"],
+ host_supported: true,
+ }
+
+ cc_rustlibs_for_make {
+ name: "libmakerustlibs",
+ whole_static_libs: ["libbar"],
+ }
+
+ cc_library_static {
+ name: "libccstatic",
+ whole_static_libs: ["libbar"],
+ }
+ `)
+
+ libmakerustlibs := result.ModuleForTests(t, "libmakerustlibs", "android_arm64_armv8-a_static").MaybeRule("rustc")
+ libccstatic := result.ModuleForTests(t, "libccstatic", "android_arm64_armv8-a_static").MaybeRule("rustc")
+
+ if libmakerustlibs.Output == nil {
+ t.Errorf("cc_rustlibs_for_make is not generating a Rust staticlib when it should")
+ }
+
+ if libccstatic.Output != nil {
+ t.Errorf("cc_library_static is generating a Rust staticlib when it should not")
+ }
+}
+
+func TestRustVersionScript(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library {
+ name: "librs",
+ srcs: ["bar.rs"],
+ crate_name: "rs",
+ extra_exported_symbols: "librs.map.txt",
+ }
+ rust_ffi {
+ name: "libffi",
+ srcs: ["foo.rs"],
+ crate_name: "ffi",
+ version_script: "libffi.map.txt",
+ }
+ `)
+
+ //linkFlags
+ librs := ctx.ModuleForTests(t, "librs", "android_arm64_armv8-a_dylib").Rule("rustc")
+ libffi := ctx.ModuleForTests(t, "libffi", "android_arm64_armv8-a_shared").Rule("rustc")
+
+ if !strings.Contains(librs.Args["linkFlags"], "-Wl,--version-script=librs.map.txt") {
+ t.Errorf("missing expected -Wl,--version-script= linker flag for libextended shared lib, linkFlags: %#v",
+ librs.Args["linkFlags"])
+ }
+ if strings.Contains(librs.Args["linkFlags"], "-Wl,--android-version-script=librs.map.txt") {
+ t.Errorf("unexpected -Wl,--android-version-script= linker flag for libextended shared lib, linkFlags: %#v",
+ librs.Args["linkFlags"])
+ }
+
+ if !strings.Contains(libffi.Args["linkFlags"], "-Wl,--android-version-script=libffi.map.txt") {
+ t.Errorf("missing -Wl,--android-version-script= linker flag for libreplaced shared lib, linkFlags: %#v",
+ libffi.Args["linkFlags"])
+ }
+ if strings.Contains(libffi.Args["linkFlags"], "-Wl,--version-script=libffi.map.txt") {
+ t.Errorf("unexpected -Wl,--version-script= linker flag for libextended shared lib, linkFlags: %#v",
+ libffi.Args["linkFlags"])
+ }
+}
+
+func TestRustVersionScriptPropertyErrors(t *testing.T) {
+ testRustError(t, "version_script: can only be set for rust_ffi modules", `
+ rust_library {
+ name: "librs",
+ srcs: ["bar.rs"],
+ crate_name: "rs",
+ version_script: "libbar.map.txt",
+ }`)
+ testRustError(t, "version_script and extra_exported_symbols", `
+ rust_ffi {
+ name: "librs",
+ srcs: ["bar.rs"],
+ crate_name: "rs",
+ version_script: "libbar.map.txt",
+ extra_exported_symbols: "libbar.map.txt",
+ }`)
+}
+
+func TestStubsVersions(t *testing.T) {
+ t.Parallel()
+ bp := `
+ rust_ffi {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.rs"],
+ stubs: {
+ versions: ["29", "R", "current"],
+ },
+ }
+ `
+ ctx := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.PrepareForTestWithVisibility,
+ rustMockedFiles.AddToFixture(),
+ android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) {
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+ })).RunTestWithBp(t, bp)
+
+ variants := ctx.ModuleVariantsForTests("libfoo")
+ for _, expectedVer := range []string{"29", "R", "current"} {
+ expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer
+ if !android.InList(expectedVariant, variants) {
+ t.Errorf("missing expected variant: %q", expectedVariant)
+ }
+ }
+}
+
+func TestStubsVersions_NotSorted(t *testing.T) {
+ t.Parallel()
+ bp := `
+ rust_ffi_shared {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.rs"],
+ stubs: {
+ versions: ["29", "current", "R"],
+ },
+ }
+ `
+ fixture := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.PrepareForTestWithVisibility,
+ rustMockedFiles.AddToFixture(),
+
+ android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) {
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+ }))
+
+ fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`"libfoo" .*: versions: not sorted`)).RunTestWithBp(t, bp)
+}
+
+func TestStubsVersions_ParseError(t *testing.T) {
+ t.Parallel()
+ bp := `
+ rust_ffi_shared {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.rs"],
+ stubs: {
+ versions: ["29", "current", "X"],
+ },
+ }
+ `
+ fixture := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.PrepareForTestWithVisibility,
+ rustMockedFiles.AddToFixture(),
+
+ android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) {
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
+ }))
+
+ fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`)).RunTestWithBp(t, bp)
+}
+
+func TestVersionedStubs(t *testing.T) {
+ t.Parallel()
+ bp := `
+ rust_ffi_shared {
+ name: "libFoo",
+ crate_name: "Foo",
+ srcs: ["foo.rs"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+
+ cc_library_shared {
+ name: "libBar",
+ srcs: ["bar.c"],
+ shared_libs: ["libFoo#1"],
+ }
+
+ rust_library {
+ name: "libbar_rs",
+ crate_name: "bar_rs",
+ srcs: ["bar.rs"],
+ shared_libs: ["libFoo#1"],
+ }
+ rust_ffi {
+ name: "libbar_ffi_rs",
+ crate_name: "bar_ffi_rs",
+ srcs: ["bar.rs"],
+ shared_libs: ["libFoo#1"],
+ }
+ `
+
+ ctx := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.PrepareForTestWithVisibility,
+ rustMockedFiles.AddToFixture()).RunTestWithBp(t, bp)
+
+ variants := ctx.ModuleVariantsForTests("libFoo")
+ expectedVariants := []string{
+ "android_arm64_armv8-a_shared",
+ "android_arm64_armv8-a_shared_1",
+ "android_arm64_armv8-a_shared_2",
+ "android_arm64_armv8-a_shared_3",
+ "android_arm64_armv8-a_shared_current",
+ "android_arm_armv7-a-neon_shared",
+ "android_arm_armv7-a-neon_shared_1",
+ "android_arm_armv7-a-neon_shared_2",
+ "android_arm_armv7-a-neon_shared_3",
+ "android_arm_armv7-a-neon_shared_current",
+ }
+ variantsMismatch := false
+ if len(variants) != len(expectedVariants) {
+ variantsMismatch = true
+ } else {
+ for _, v := range expectedVariants {
+ if !android.InList(v, variants) {
+ variantsMismatch = false
+ }
+ }
+ }
+ if variantsMismatch {
+ t.Errorf("variants of libFoo expected:\n")
+ for _, v := range expectedVariants {
+ t.Errorf("%q\n", v)
+ }
+ t.Errorf(", but got:\n")
+ for _, v := range variants {
+ t.Errorf("%q\n", v)
+ }
+ }
+
+ libBarLinkRule := ctx.ModuleForTests(t, "libBar", "android_arm64_armv8-a_shared").Rule("ld")
+ libBarFlags := libBarLinkRule.Args["libFlags"]
+
+ libBarRsRustcRule := ctx.ModuleForTests(t, "libbar_rs", "android_arm64_armv8-a_dylib").Rule("rustc")
+ libBarRsFlags := libBarRsRustcRule.Args["linkFlags"]
+
+ libBarFfiRsRustcRule := ctx.ModuleForTests(t, "libbar_ffi_rs", "android_arm64_armv8-a_shared").Rule("rustc")
+ libBarFfiRsFlags := libBarFfiRsRustcRule.Args["linkFlags"]
+
+ libFoo1StubPath := "libFoo/android_arm64_armv8-a_shared_1/unstripped/libFoo.so"
+ if !strings.Contains(libBarFlags, libFoo1StubPath) {
+ t.Errorf("%q is not found in %q", libFoo1StubPath, libBarFlags)
+ }
+ if !strings.Contains(libBarRsFlags, libFoo1StubPath) {
+ t.Errorf("%q is not found in %q", libFoo1StubPath, libBarRsFlags)
+ }
+ if !strings.Contains(libBarFfiRsFlags, libFoo1StubPath) {
+ t.Errorf("%q is not found in %q", libFoo1StubPath, libBarFfiRsFlags)
+ }
+}
+
+func TestCheckConflictingExplicitVersions(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libbar",
+ srcs: ["bar.c"],
+ shared_libs: ["libfoo", "libfoo#impl"],
+ }
+
+ rust_ffi_shared {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.rs"],
+ stubs: {
+ versions: ["29", "current"],
+ },
+ }
+ `
+ fixture := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.PrepareForTestWithVisibility,
+ rustMockedFiles.AddToFixture())
+
+ fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`duplicate shared libraries with different explicit versions`)).RunTestWithBp(t, bp)
+}
+
+func TestAddnoOverride64GlobalCflags(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libclient",
+ srcs: ["foo.c"],
+ shared_libs: ["libfoo#1"],
+ }
+
+ rust_ffi_shared {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.c"],
+ shared_libs: ["libbar"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ }
+
+ cc_library_shared {
+ name: "libbar",
+ export_include_dirs: ["include/libbar"],
+ srcs: ["foo.c"],
+ }`
+ ctx := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.PrepareForTestWithVisibility,
+ rustMockedFiles.AddToFixture()).RunTestWithBp(t, bp)
+
+ cFlags := ctx.ModuleForTests(t, "libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+
+ if !strings.Contains(cFlags, "${config.NoOverride64GlobalCflags}") {
+ t.Errorf("expected %q in cflags, got %q", "${config.NoOverride64GlobalCflags}", cFlags)
+ }
+}
+
+// Make sure the stubs properties can only be used in modules producing shared libs
+func TestRustStubsFFIOnly(t *testing.T) {
+ testRustError(t, "stubs properties", `
+ rust_library {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.c"],
+ shared_libs: ["libbar"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ },
+ }
+ `)
+
+ testRustError(t, "stubs properties", `
+ rust_library {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.c"],
+ shared_libs: ["libbar"],
+ stubs: {
+ versions: ["1"],
+ },
+ }
+ `)
+
+ testRustError(t, "stubs properties", `
+ rust_ffi_static {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.c"],
+ shared_libs: ["libbar"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ },
+ }
+ `)
+ testRustError(t, "stubs properties", `
+ rust_ffi_static {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.c"],
+ shared_libs: ["libbar"],
+ stubs: {
+ versions: ["1"],
+ },
+ }
+ `)
+}
+
+// TODO: When rust_ffi libraries support export_*_lib_headers,
+// add a test similar to cc.TestStubsLibReexportsHeaders
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index e35e510..7c92dda 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -30,6 +30,8 @@
Srcs []string `android:"path,arch_variant"`
// directories containing associated rlib dependencies
Link_dirs []string `android:"path,arch_variant"`
+
+ Force_use_prebuilt *bool `android:"arch_variant"`
}
type prebuiltLibraryDecorator struct {
@@ -158,7 +160,7 @@
func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
- prebuilt.flagExporter.setProvider(ctx)
+ prebuilt.flagExporter.setRustProvider(ctx)
srcPath := prebuiltPath(ctx, prebuilt)
prebuilt.baseCompiler.unstrippedOutputFile = srcPath
return buildOutput{outputFile: srcPath}
@@ -211,7 +213,7 @@
func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
- prebuilt.flagExporter.setProvider(ctx)
+ prebuilt.flagExporter.setRustProvider(ctx)
srcPath := prebuiltPath(ctx, prebuilt)
prebuilt.baseCompiler.unstrippedOutputFile = srcPath
return buildOutput{outputFile: srcPath}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 1ff6637..837e1a6 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -67,6 +67,7 @@
func (procMacro *procMacroDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = procMacro.baseCompiler.compilerFlags(ctx, flags)
flags.RustFlags = append(flags.RustFlags, "--extern proc_macro")
+ flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
return flags
}
@@ -99,3 +100,9 @@
// Proc_macros are never installed
return false
}
+
+func (library *procMacroDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ library.baseCompiler.moduleInfoJSON(ctx, moduleInfoJSON)
+
+ moduleInfoJSON.Class = []string{"PROC_MACRO_LIBRARIES"}
+}
diff --git a/rust/proc_macro_test.go b/rust/proc_macro_test.go
index cc81938..8a95eb4 100644
--- a/rust/proc_macro_test.go
+++ b/rust/proc_macro_test.go
@@ -28,7 +28,7 @@
}
`)
- libprocmacro := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Rule("rustc")
+ libprocmacro := ctx.ModuleForTests(t, "libprocmacro", "linux_glibc_x86_64").Rule("rustc")
if !strings.Contains(libprocmacro.Args["rustcFlags"], "--extern proc_macro") {
t.Errorf("--extern proc_macro flag not being passed to rustc for proc macro %#v", libprocmacro.Args["rustcFlags"])
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index cae071b..531e034 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -41,13 +41,13 @@
}
`)
// Check that libprotobuf is added as a dependency.
- librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
+ librust_proto := ctx.ModuleForTests(t, "librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
if !android.InList("libprotobuf", librust_proto.Properties.AndroidMkDylibs) {
t.Errorf("libprotobuf dependency missing for rust_protobuf (dependency missing from AndroidMkDylibs)")
}
// Make sure the correct plugin is being used.
- librust_proto_out := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
+ librust_proto_out := ctx.ModuleForTests(t, "librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
cmd := librust_proto_out.RuleParams.Command
if w := "protoc-gen-rust"; !strings.Contains(cmd, w) {
t.Errorf("expected %q in %q", w, cmd)
@@ -62,7 +62,7 @@
}
// Check proto.rs, the second protobuf, is listed as an output
- librust_proto_outputs := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").AllOutputs()
+ librust_proto_outputs := ctx.ModuleForTests(t, "librust_proto", "android_arm64_armv8-a_source").AllOutputs()
if android.InList("proto.rs", librust_proto_outputs) {
t.Errorf("rust_protobuf is not producing multiple outputs; expected 'proto.rs' in list, got: %#v ",
librust_proto_outputs)
@@ -92,7 +92,7 @@
}
`)
// Check that librust_exported_proto is added as additional crate to generate source.
- librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Module().(*Module).sourceProvider.(*protobufDecorator)
+ librust_proto := ctx.ModuleForTests(t, "librust_proto", "android_arm64_armv8-a_source").Module().(*Module).sourceProvider.(*protobufDecorator)
if !android.InList("rust_exported_proto", librust_proto.additionalCrates) {
t.Errorf("librust_proto should have librust_exported_proto included as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates)
}
@@ -111,7 +111,7 @@
}
// Check librust_proto args includes -Iproto
- librust_proto_rule := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("proto.rs")
+ librust_proto_rule := ctx.ModuleForTests(t, "librust_proto", "android_arm64_armv8-a_source").Output("proto.rs")
cmd := librust_proto_rule.RuleParams.Command
if w := "-Iproto"; !strings.Contains(cmd, w) {
t.Errorf("expected %q in %q", w, cmd)
@@ -131,7 +131,7 @@
`)
// Check that libprotobuf is added as a dependency.
- librust_grpcio_module := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_dylib").Module().(*Module)
+ librust_grpcio_module := ctx.ModuleForTests(t, "librust_grpcio", "android_arm64_armv8-a_dylib").Module().(*Module)
// Check that libgrpcio is added as a dependency.
if !android.InList("libgrpcio", librust_grpcio_module.Properties.AndroidMkDylibs) {
@@ -144,7 +144,7 @@
}
// Make sure the correct plugin is being used.
- librust_grpcio_out := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_source").Output("foo_grpc.rs")
+ librust_grpcio_out := ctx.ModuleForTests(t, "librust_grpcio", "android_arm64_armv8-a_source").Output("foo_grpc.rs")
cmd := librust_grpcio_out.RuleParams.Command
if w := "protoc-gen-grpc"; !strings.Contains(cmd, w) {
t.Errorf("expected %q in %q", w, cmd)
@@ -156,7 +156,7 @@
}
// Check proto.rs, the second protobuf, is listed as an output
- librust_grpcio_outputs := ctx.ModuleForTests("librust_grpcio", "android_arm64_armv8-a_source").AllOutputs()
+ librust_grpcio_outputs := ctx.ModuleForTests(t, "librust_grpcio", "android_arm64_armv8-a_source").AllOutputs()
if android.InList("proto_grpc.rs", librust_grpcio_outputs) {
t.Errorf("rust_protobuf is not producing multiple outputs; expected 'proto_grpc.rs' in list, got: %#v ",
librust_grpcio_outputs)
diff --git a/rust/rust.go b/rust/rust.go
index eeb228c..54b5d92 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -34,6 +34,38 @@
var pctx = android.NewPackageContext("android/soong/rust")
+type LibraryInfo struct {
+ Rlib bool
+ Dylib bool
+}
+
+type CompilerInfo struct {
+ StdLinkageForDevice RustLinkage
+ StdLinkageForNonDevice RustLinkage
+ NoStdlibs bool
+ LibraryInfo *LibraryInfo
+}
+
+type ProtobufDecoratorInfo struct{}
+
+type SourceProviderInfo struct {
+ Srcs android.Paths
+ ProtobufDecoratorInfo *ProtobufDecoratorInfo
+}
+
+type RustInfo struct {
+ AndroidMkSuffix string
+ RustSubName string
+ TransitiveAndroidMkSharedLibs depset.DepSet[string]
+ CompilerInfo *CompilerInfo
+ SnapshotInfo *cc.SnapshotInfo
+ SourceProviderInfo *SourceProviderInfo
+ XrefRustFiles android.Paths
+ DocTimestampFile android.OptionalPath
+}
+
+var RustInfoProvider = blueprint.NewProvider[*RustInfo]()
+
func init() {
android.RegisterModuleType("rust_defaults", defaultsFactory)
android.PreDepsMutators(registerPreDepsMutators)
@@ -133,9 +165,36 @@
// Make this module available when building for recovery
Recovery_available *bool
- // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ // The API level that this module is built against. The APIs of this API level will be
+ // visible at build time, but use of any APIs newer than min_sdk_version will render the
+ // module unloadable on older devices. In the future it will be possible to weakly-link new
+ // APIs, making the behavior match Java: such modules will load on older devices, but
+ // calling new APIs on devices that do not support them will result in a crash.
+ //
+ // This property has the same behavior as sdk_version does for Java modules. For those
+ // familiar with Android Gradle, the property behaves similarly to how compileSdkVersion
+ // does for Java code.
+ //
+ // In addition, setting this property causes two variants to be built, one for the platform
+ // and one for apps.
+ Sdk_version *string
+
+ // Minimum OS API level supported by this C or C++ module. This property becomes the value
+ // of the __ANDROID_API__ macro. When the C or C++ module is included in an APEX or an APK,
+ // this property is also used to ensure that the min_sdk_version of the containing module is
+ // not older (i.e. less) than this module's min_sdk_version. When not set, this property
+ // defaults to the value of sdk_version. When this is set to "apex_inherit", this tracks
+ // min_sdk_version of the containing APEX. When the module
+ // is not built for an APEX, "apex_inherit" defaults to sdk_version.
Min_sdk_version *string
+ // Variant is an SDK variant created by sdkMutator
+ IsSdkVariant bool `blueprint:"mutated"`
+
+ // Set by factories of module types that can only be referenced from variants compiled against
+ // the SDK.
+ AlwaysSdk bool `blueprint:"mutated"`
+
HideFromMake bool `blueprint:"mutated"`
PreventInstall bool `blueprint:"mutated"`
@@ -180,6 +239,9 @@
apexSdkVersion android.ApiLevel
transitiveAndroidMkSharedLibs depset.DepSet[string]
+
+ // Shared flags among stubs build rules of this module
+ sharedFlags cc.SharedFlags
}
func (mod *Module) Header() bool {
@@ -345,7 +407,8 @@
}
func (mod *Module) IsVendorPublicLibrary() bool {
- return mod.VendorProperties.IsVendorPublicLibrary
+ // Rust modules do not currently support vendor_public_library
+ return false
}
func (mod *Module) SdkAndPlatformVariantVisibleToMake() bool {
@@ -354,10 +417,12 @@
}
func (c *Module) IsVndkPrivate() bool {
+ // Rust modules do not currently support VNDK variants
return false
}
func (c *Module) IsLlndk() bool {
+ // Rust modules do not currently support LLNDK variants
return false
}
@@ -366,35 +431,34 @@
}
func (m *Module) NeedsLlndkVariants() bool {
+ // Rust modules do not currently support LLNDK variants
return false
}
func (m *Module) NeedsVendorPublicLibraryVariants() bool {
+ // Rust modules do not currently support vendor_public_library
return false
}
func (mod *Module) HasLlndkStubs() bool {
+ // Rust modules do not currently support LLNDK stubs
return false
}
-func (mod *Module) StubsVersion() string {
- panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName()))
-}
-
func (mod *Module) SdkVersion() string {
- return ""
+ return String(mod.Properties.Sdk_version)
}
func (mod *Module) AlwaysSdk() bool {
- return false
+ return mod.Properties.AlwaysSdk
}
func (mod *Module) IsSdkVariant() bool {
- return false
+ return mod.Properties.IsSdkVariant
}
func (mod *Module) SplitPerApiLevel() bool {
- return false
+ return cc.CanUseSdk(mod) && mod.IsCrt()
}
func (mod *Module) XrefRustFiles() android.Paths {
@@ -427,15 +491,24 @@
StaticLibs android.Paths
ProcMacros RustLibraries
AfdoProfiles android.Paths
+ LinkerDeps android.Paths
// depFlags and depLinkFlags are rustc and linker (clang) flags.
depFlags []string
depLinkFlags []string
+ // track cc static-libs that have Rlib dependencies
+ reexportedCcRlibDeps []cc.RustRlibDep
+ reexportedWholeCcRlibDeps []cc.RustRlibDep
+ ccRlibDeps []cc.RustRlibDep
+
// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker
// Both of these are exported and propagate to dependencies.
- linkDirs []string
- linkObjects []string
+ linkDirs []string
+ rustLibObjects []string
+ staticLibObjects []string
+ wholeStaticLibObjects []string
+ sharedLibObjects []string
// exportedLinkDirs are exported linkDirs for direct rlib dependencies to
// cc_library_static dependants of rlibs.
@@ -468,7 +541,10 @@
type exportedFlagsProducer interface {
exportLinkDirs(...string)
- exportLinkObjects(...string)
+ exportRustLibs(...string)
+ exportStaticLibs(...string)
+ exportWholeStaticLibs(...string)
+ exportSharedLibs(...string)
}
type xref interface {
@@ -476,23 +552,43 @@
}
type flagExporter struct {
- linkDirs []string
- ccLinkDirs []string
- linkObjects []string
+ linkDirs []string
+ ccLinkDirs []string
+ rustLibPaths []string
+ staticLibObjects []string
+ sharedLibObjects []string
+ wholeStaticLibObjects []string
+ wholeRustRlibDeps []cc.RustRlibDep
}
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
}
-func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
- flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
+func (flagExporter *flagExporter) exportRustLibs(flags ...string) {
+ flagExporter.rustLibPaths = android.FirstUniqueStrings(append(flagExporter.rustLibPaths, flags...))
}
-func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
- android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
- LinkDirs: flagExporter.linkDirs,
- LinkObjects: flagExporter.linkObjects,
+func (flagExporter *flagExporter) exportStaticLibs(flags ...string) {
+ flagExporter.staticLibObjects = android.FirstUniqueStrings(append(flagExporter.staticLibObjects, flags...))
+}
+
+func (flagExporter *flagExporter) exportSharedLibs(flags ...string) {
+ flagExporter.sharedLibObjects = android.FirstUniqueStrings(append(flagExporter.sharedLibObjects, flags...))
+}
+
+func (flagExporter *flagExporter) exportWholeStaticLibs(flags ...string) {
+ flagExporter.wholeStaticLibObjects = android.FirstUniqueStrings(append(flagExporter.wholeStaticLibObjects, flags...))
+}
+
+func (flagExporter *flagExporter) setRustProvider(ctx ModuleContext) {
+ android.SetProvider(ctx, RustFlagExporterInfoProvider, RustFlagExporterInfo{
+ LinkDirs: flagExporter.linkDirs,
+ RustLibObjects: flagExporter.rustLibPaths,
+ StaticLibObjects: flagExporter.staticLibObjects,
+ WholeStaticLibObjects: flagExporter.wholeStaticLibObjects,
+ SharedLibPaths: flagExporter.sharedLibObjects,
+ WholeRustRlibDeps: flagExporter.wholeRustRlibDeps,
})
}
@@ -502,13 +598,17 @@
return &flagExporter{}
}
-type FlagExporterInfo struct {
- Flags []string
- LinkDirs []string // TODO: this should be android.Paths
- LinkObjects []string // TODO: this should be android.Paths
+type RustFlagExporterInfo struct {
+ Flags []string
+ LinkDirs []string
+ RustLibObjects []string
+ StaticLibObjects []string
+ WholeStaticLibObjects []string
+ SharedLibPaths []string
+ WholeRustRlibDeps []cc.RustRlibDep
}
-var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
+var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]()
func (mod *Module) isCoverageVariant() bool {
return mod.coverage.Properties.IsCoverageVariant
@@ -531,6 +631,9 @@
func (mod *Module) PreventInstall() bool {
return mod.Properties.PreventInstall
}
+func (c *Module) ForceDisableSanitizers() {
+ c.sanitize.Properties.ForceDisable = true
+}
func (mod *Module) MarkAsCoverageVariant(coverage bool) {
mod.coverage.Properties.IsCoverageVariant = coverage
@@ -594,7 +697,7 @@
if mod.compiler != nil {
// use build{Static,Shared}() instead of {static,shared}() here because this might be called before
// VariantIs{Static,Shared} is set.
- if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) {
+ if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic() || lib.buildRlib()) {
return true
}
}
@@ -680,15 +783,6 @@
panic(fmt.Errorf("BuildRlibVariant called on non-library module: %q", mod.BaseModuleName()))
}
-func (mod *Module) IsRustFFI() bool {
- if mod.compiler != nil {
- if library, ok := mod.compiler.(libraryInterface); ok {
- return library.isFFILibrary()
- }
- }
- return false
-}
-
func (mod *Module) BuildSharedVariant() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok {
@@ -722,11 +816,51 @@
return false
}
-func (mod *Module) HasStubsVariants() bool {
+func (mod *Module) IsStubs() bool {
+ if lib, ok := mod.compiler.(libraryInterface); ok {
+ return lib.BuildStubs()
+ }
return false
}
-func (mod *Module) IsStubs() bool {
+func (mod *Module) HasStubsVariants() bool {
+ if lib, ok := mod.compiler.(libraryInterface); ok {
+ return lib.HasStubsVariants()
+ }
+ return false
+}
+
+func (mod *Module) ApexSdkVersion() android.ApiLevel {
+ return mod.apexSdkVersion
+}
+
+func (mod *Module) RustApexExclude() bool {
+ return mod.ApexExclude()
+}
+
+func (mod *Module) getSharedFlags() *cc.SharedFlags {
+ shared := &mod.sharedFlags
+ if shared.FlagsMap == nil {
+ shared.NumSharedFlags = 0
+ shared.FlagsMap = make(map[string]string)
+ }
+ return shared
+}
+
+func (mod *Module) ImplementationModuleNameForMake() string {
+ name := mod.BaseModuleName()
+ if versioned, ok := mod.compiler.(cc.VersionedInterface); ok {
+ name = versioned.ImplementationModuleName(name)
+ }
+ return name
+}
+
+func (mod *Module) Multilib() string {
+ return mod.Arch().ArchType.Multilib
+}
+
+func (mod *Module) IsCrt() bool {
+ // Rust does not currently provide any crt modules.
return false
}
@@ -750,6 +884,7 @@
}
var _ cc.LinkableInterface = (*Module)(nil)
+var _ cc.VersionedLinkableInterface = (*Module)(nil)
func (mod *Module) Init() android.Module {
mod.AddProperties(&mod.Properties)
@@ -860,6 +995,25 @@
return mod.compiler != nil && mod.compiler.nativeCoverage()
}
+func (mod *Module) SetStl(s string) {
+ // STL is a CC concept; do nothing for Rust
+}
+
+func (mod *Module) SetSdkVersion(s string) {
+ mod.Properties.Sdk_version = StringPtr(s)
+}
+
+func (mod *Module) SetMinSdkVersion(s string) {
+ mod.Properties.Min_sdk_version = StringPtr(s)
+}
+
+func (mod *Module) VersionedInterface() cc.VersionedInterface {
+ if _, ok := mod.compiler.(cc.VersionedInterface); ok {
+ return mod.compiler.(cc.VersionedInterface)
+ }
+ return nil
+}
+
func (mod *Module) EverInstallable() bool {
return mod.compiler != nil &&
// Check to see whether the module is actually ever installable.
@@ -949,12 +1103,11 @@
mod.sourceProvider.GenerateSource(ctx, deps)
mod.sourceProvider.setSubName(ctx.ModuleSubDir())
} else {
- sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
- sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
- mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
+ sourceMod := actx.GetDirectDepProxyWithTag(mod.Name(), sourceDepTag)
+ sourceLib := android.OtherModuleProviderOrDefault(ctx, sourceMod, RustInfoProvider).SourceProviderInfo
+ mod.sourceProvider.setOutputFiles(sourceLib.Srcs)
}
ctx.CheckbuildFile(mod.sourceProvider.Srcs()...)
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()})
}
if mod.compiler != nil && !mod.compiler.Disabled() {
@@ -1005,13 +1158,76 @@
ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
}
- android.SetProvider(ctx, cc.LinkableInfoKey, cc.LinkableInfo{
- StaticExecutable: mod.StaticExecutable(),
- })
+ linkableInfo := cc.CreateCommonLinkableInfo(ctx, mod)
+ linkableInfo.Static = mod.Static()
+ linkableInfo.Shared = mod.Shared()
+ linkableInfo.CrateName = mod.CrateName()
+ linkableInfo.ExportedCrateLinkDirs = mod.ExportedCrateLinkDirs()
+ if lib, ok := mod.compiler.(cc.VersionedInterface); ok {
+ linkableInfo.StubsVersion = lib.StubsVersion()
+ }
+
+ android.SetProvider(ctx, cc.LinkableInfoProvider, linkableInfo)
+
+ rustInfo := &RustInfo{
+ AndroidMkSuffix: mod.AndroidMkSuffix(),
+ RustSubName: mod.Properties.RustSubName,
+ TransitiveAndroidMkSharedLibs: mod.transitiveAndroidMkSharedLibs,
+ XrefRustFiles: mod.XrefRustFiles(),
+ DocTimestampFile: mod.docTimestampFile,
+ }
+ if mod.compiler != nil {
+ rustInfo.CompilerInfo = &CompilerInfo{
+ NoStdlibs: mod.compiler.noStdlibs(),
+ StdLinkageForDevice: mod.compiler.stdLinkage(true),
+ StdLinkageForNonDevice: mod.compiler.stdLinkage(false),
+ }
+ if lib, ok := mod.compiler.(libraryInterface); ok {
+ rustInfo.CompilerInfo.LibraryInfo = &LibraryInfo{
+ Dylib: lib.dylib(),
+ Rlib: lib.rlib(),
+ }
+ }
+ if lib, ok := mod.compiler.(cc.SnapshotInterface); ok {
+ rustInfo.SnapshotInfo = &cc.SnapshotInfo{
+ SnapshotAndroidMkSuffix: lib.SnapshotAndroidMkSuffix(),
+ }
+ }
+ }
+ if mod.sourceProvider != nil {
+ rustInfo.SourceProviderInfo = &SourceProviderInfo{
+ Srcs: mod.sourceProvider.Srcs(),
+ }
+ if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
+ rustInfo.SourceProviderInfo.ProtobufDecoratorInfo = &ProtobufDecoratorInfo{}
+ }
+ }
+ android.SetProvider(ctx, RustInfoProvider, rustInfo)
+
+ ccInfo := &cc.CcInfo{
+ IsPrebuilt: mod.IsPrebuilt(),
+ }
+
+ // Define the linker info if compiler != nil because Rust currently
+ // does compilation and linking in one step. If this changes in the future,
+ // move this as appropriate.
+ baseCompilerProps := mod.compiler.baseCompilerProps()
+ ccInfo.LinkerInfo = &cc.LinkerInfo{
+ WholeStaticLibs: baseCompilerProps.Whole_static_libs.GetOrDefault(ctx, nil),
+ StaticLibs: baseCompilerProps.Static_libs.GetOrDefault(ctx, nil),
+ SharedLibs: baseCompilerProps.Shared_libs.GetOrDefault(ctx, nil),
+ }
+
+ android.SetProvider(ctx, cc.CcInfoProvider, ccInfo)
mod.setOutputFiles(ctx)
buildComplianceMetadataInfo(ctx, mod, deps)
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ if mod.compiler != nil {
+ mod.compiler.moduleInfoJSON(ctx, moduleInfoJSON)
+ }
}
func (mod *Module) setOutputFiles(ctx ModuleContext) {
@@ -1034,12 +1250,12 @@
metadataInfo.SetStringValue(android.ComplianceMetadataProp.BUILT_FILES, mod.outputFile.String())
// Static libs
- staticDeps := ctx.GetDirectDepsWithTag(rlibDepTag)
+ staticDeps := ctx.GetDirectDepsProxyWithTag(rlibDepTag)
staticDepNames := make([]string, 0, len(staticDeps))
for _, dep := range staticDeps {
staticDepNames = append(staticDepNames, dep.Name())
}
- ccStaticDeps := ctx.GetDirectDepsWithTag(cc.StaticDepTag(false))
+ ccStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(false))
for _, dep := range ccStaticDeps {
staticDepNames = append(staticDepNames, dep.Name())
}
@@ -1057,7 +1273,7 @@
metadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.FirstUniqueStrings(staticDepPaths))
// C Whole static libs
- ccWholeStaticDeps := ctx.GetDirectDepsWithTag(cc.StaticDepTag(true))
+ ccWholeStaticDeps := ctx.GetDirectDepsProxyWithTag(cc.StaticDepTag(true))
wholeStaticDepNames := make([]string, 0, len(ccWholeStaticDeps))
for _, dep := range ccStaticDeps {
wholeStaticDepNames = append(wholeStaticDepNames, dep.Name())
@@ -1170,6 +1386,21 @@
if mod.sanitize != nil {
mod.sanitize.begin(ctx)
}
+
+ if mod.UseSdk() && mod.IsSdkVariant() {
+ sdkVersion := ""
+ if ctx.Device() {
+ sdkVersion = mod.SdkVersion()
+ }
+ version, err := cc.NativeApiLevelFromUser(ctx, sdkVersion)
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version", err.Error())
+ mod.Properties.Sdk_version = nil
+ } else {
+ mod.Properties.Sdk_version = StringPtr(version.String())
+ }
+ }
+
}
func (mod *Module) Prebuilt() *android.Prebuilt {
@@ -1184,21 +1415,21 @@
return nil
}
-func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string {
- if rustDep, ok := dep.(*Module); ok {
+func rustMakeLibName(rustInfo *RustInfo, linkableInfo *cc.LinkableInfo, commonInfo *android.CommonModuleInfo, depName string) string {
+ if rustInfo != nil {
// Use base module name for snapshots when exporting to Makefile.
- if snapshotPrebuilt, ok := rustDep.compiler.(cc.SnapshotInterface); ok {
- baseName := rustDep.BaseModuleName()
- return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() + rustDep.AndroidMkSuffix()
+ if rustInfo.SnapshotInfo != nil {
+ baseName := commonInfo.BaseModuleName
+ return baseName + rustInfo.SnapshotInfo.SnapshotAndroidMkSuffix + rustInfo.AndroidMkSuffix
}
}
- return cc.MakeLibName(ctx, c, dep, depName)
+ return cc.MakeLibName(nil, linkableInfo, commonInfo, depName)
}
-func collectIncludedProtos(mod *Module, dep *Module) {
+func collectIncludedProtos(mod *Module, rustInfo *RustInfo, linkableInfo *cc.LinkableInfo) {
if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok {
- if _, ok := dep.sourceProvider.(*protobufDecorator); ok {
- protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName())
+ if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil {
+ protoMod.additionalCrates = append(protoMod.additionalCrates, linkableInfo.CrateName)
}
}
}
@@ -1206,13 +1437,13 @@
func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
- directRlibDeps := []*Module{}
- directDylibDeps := []*Module{}
- directProcMacroDeps := []*Module{}
+ directRlibDeps := []*cc.LinkableInfo{}
+ directDylibDeps := []*cc.LinkableInfo{}
+ directProcMacroDeps := []*cc.LinkableInfo{}
directSharedLibDeps := []cc.SharedLibraryInfo{}
- directStaticLibDeps := [](cc.LinkableInterface){}
- directSrcProvidersDeps := []*Module{}
- directSrcDeps := [](android.SourceFileProducer){}
+ directStaticLibDeps := [](*cc.LinkableInfo){}
+ directSrcProvidersDeps := []*android.ModuleProxy{}
+ directSrcDeps := []android.SourceFilesInfo{}
// For the dependency from platform to apex, use the latest stubs
mod.apexSdkVersion = android.FutureApiLevel
@@ -1233,9 +1464,11 @@
var transitiveAndroidMkSharedLibs []depset.DepSet[string]
var directAndroidMkSharedLibs []string
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
+ modStdLinkage := mod.compiler.stdLinkage(ctx.Device())
+
if _, exists := skipModuleList[depName]; exists {
return
}
@@ -1244,18 +1477,22 @@
return
}
- if rustDep, ok := dep.(*Module); ok && !rustDep.Static() && !rustDep.Shared() {
+ rustInfo, hasRustInfo := android.OtherModuleProvider(ctx, dep, RustInfoProvider)
+ ccInfo, _ := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider)
+ linkableInfo, hasLinkableInfo := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
+ if hasRustInfo && !linkableInfo.Static && !linkableInfo.Shared {
//Handle Rust Modules
- makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
+ makeLibName := rustMakeLibName(rustInfo, linkableInfo, commonInfo, depName+rustInfo.RustSubName)
switch {
case depTag == dylibDepTag:
- dylib, ok := rustDep.compiler.(libraryInterface)
- if !ok || !dylib.dylib() {
+ dylib := rustInfo.CompilerInfo.LibraryInfo
+ if dylib == nil || !dylib.Dylib {
ctx.ModuleErrorf("mod %q not an dylib library", depName)
return
}
- directDylibDeps = append(directDylibDeps, rustDep)
+ directDylibDeps = append(directDylibDeps, linkableInfo)
mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))
@@ -1264,35 +1501,64 @@
depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
}
+ if !rustInfo.CompilerInfo.NoStdlibs {
+ rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice
+ if ctx.Device() {
+ rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice
+ }
+ if rustDepStdLinkage != modStdLinkage {
+ ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage)
+ return
+ }
+ }
+
case depTag == rlibDepTag:
- rlib, ok := rustDep.compiler.(libraryInterface)
- if !ok || !rlib.rlib() {
+ rlib := rustInfo.CompilerInfo.LibraryInfo
+ if rlib == nil || !rlib.Rlib {
ctx.ModuleErrorf("mod %q not an rlib library", makeLibName)
return
}
- directRlibDeps = append(directRlibDeps, rustDep)
+ directRlibDeps = append(directRlibDeps, linkableInfo)
mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName)
mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName))
// rust_ffi rlibs may export include dirs, so collect those here.
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
- depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
+ depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path()))
// rlibs are not installed, so don't add the output file to directImplementationDeps
if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
}
+ if !rustInfo.CompilerInfo.NoStdlibs {
+ rustDepStdLinkage := rustInfo.CompilerInfo.StdLinkageForNonDevice
+ if ctx.Device() {
+ rustDepStdLinkage = rustInfo.CompilerInfo.StdLinkageForDevice
+ }
+ if rustDepStdLinkage != modStdLinkage {
+ ctx.ModuleErrorf("Rust dependency %q has the wrong StdLinkage; expected %#v, got %#v", depName, modStdLinkage, rustDepStdLinkage)
+ return
+ }
+ }
+
+ if !mod.Rlib() {
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+ } else {
+ // rlibs need to reexport these
+ depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+ }
+
case depTag == procMacroDepTag:
- directProcMacroDeps = append(directProcMacroDeps, rustDep)
+ directProcMacroDeps = append(directProcMacroDeps, linkableInfo)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
// proc_macro link dirs need to be exported, so collect those here.
- depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
+ depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(linkableInfo.OutputFile.Path()))
case depTag == sourceDepTag:
if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
- collectIncludedProtos(mod, rustDep)
+ collectIncludedProtos(mod, rustInfo, linkableInfo)
}
case cc.IsStaticDepTag(depTag):
// Rust FFI rlibs should not be declared in a Rust modules
@@ -1305,7 +1571,7 @@
}
- transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs)
+ transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustInfo.TransitiveAndroidMkSharedLibs)
if android.IsSourceDepTagWithOutputTag(depTag, "") {
// Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct
@@ -1317,26 +1583,35 @@
helper = "device module defined?"
}
- if dep.Target().Os != ctx.Os() {
+ if commonInfo.Target.Os != ctx.Os() {
ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper)
return
- } else if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
+ } else if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType {
ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper)
return
}
- directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
+ directSrcProvidersDeps = append(directSrcProvidersDeps, &dep)
}
- exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
- //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
+ exportedRustInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
+ //Append the dependencies exported objects, except for proc-macros which target a different arch/OS
if depTag != procMacroDepTag {
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
- depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
+ depPaths.rustLibObjects = append(depPaths.rustLibObjects, exportedInfo.RustLibObjects...)
+ depPaths.sharedLibObjects = append(depPaths.sharedLibObjects, exportedInfo.SharedLibPaths...)
+ depPaths.staticLibObjects = append(depPaths.staticLibObjects, exportedInfo.StaticLibObjects...)
+ depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, exportedInfo.WholeStaticLibObjects...)
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
+
+ depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedRustInfo.WholeRustRlibDeps...)
+ if !mod.Rlib() {
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedRustInfo.WholeRustRlibDeps...)
+ }
}
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
- linkFile := rustDep.UnstrippedOutputFile()
+ linkFile := linkableInfo.UnstrippedOutputFile
linkDir := linkPathFromFilePath(linkFile)
if lib, ok := mod.compiler.(exportedFlagsProducer); ok {
lib.exportLinkDirs(linkDir)
@@ -1345,27 +1620,27 @@
if depTag == sourceDepTag {
if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() {
- if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok {
+ if rustInfo.SourceProviderInfo.ProtobufDecoratorInfo != nil {
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
}
}
}
- } else if ccDep, ok := dep.(cc.LinkableInterface); ok {
+ } else if hasLinkableInfo {
//Handle C dependencies
- makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName)
- if _, ok := ccDep.(*Module); !ok {
- if ccDep.Module().Target().Os != ctx.Os() {
+ makeLibName := cc.MakeLibName(ccInfo, linkableInfo, commonInfo, depName)
+ if !hasRustInfo {
+ if commonInfo.Target.Os != ctx.Os() {
ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
return
}
- if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType {
+ if commonInfo.Target.Arch.ArchType != ctx.Arch().ArchType {
ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
return
}
}
- linkObject := ccDep.OutputFile()
- if !linkObject.Valid() {
+ ccLibPath := linkableInfo.OutputFile
+ if !ccLibPath.Valid() {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
} else {
@@ -1374,7 +1649,7 @@
return
}
- linkPath := linkPathFromFilePath(linkObject.Path())
+ linkPath := linkPathFromFilePath(ccLibPath.Path())
exportDep := false
switch {
@@ -1383,28 +1658,48 @@
// rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail
// if the library is not prefixed by "lib".
if mod.Binary() {
- // Binaries may sometimes need to link whole static libraries that don't start with 'lib'.
// Since binaries don't need to 'rebundle' these like libraries and only use these for the
// final linkage, pass the args directly to the linker to handle these cases.
- depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...)
- } else if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
- depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
+ depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", ccLibPath.Path().String(), "-Wl,--no-whole-archive"}...)
+ } else if libName, ok := libNameFromFilePath(ccLibPath.Path()); ok {
+ depPaths.depFlags = append(depPaths.depFlags, "-lstatic:+whole-archive="+libName)
+ depPaths.depLinkFlags = append(depPaths.depLinkFlags, ccLibPath.Path().String())
} else {
ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
}
}
- // Add this to linkObjects to pass the library directly to the linker as well. This propagates
- // to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
- depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
- depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
-
exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
+ if cc.IsWholeStaticLib(depTag) {
+ // Add whole staticlibs to wholeStaticLibObjects to propagate to Rust all dependents.
+ depPaths.wholeStaticLibObjects = append(depPaths.wholeStaticLibObjects, ccLibPath.String())
+
+ // We also propagate forward whole-static'd cc staticlibs with rust_ffi_rlib dependencies
+ // We don't need to check a hypothetical exportedRustInfo.WholeRustRlibDeps because we
+ // wouldn't expect a rust_ffi_rlib to be listed in `static_libs` (Soong explicitly disallows this)
+ depPaths.reexportedWholeCcRlibDeps = append(depPaths.reexportedWholeCcRlibDeps, exportedInfo.RustRlibDeps...)
+ } else {
+ // If not whole_static, add to staticLibObjects, which only propagate through rlibs to their dependents.
+ depPaths.staticLibObjects = append(depPaths.staticLibObjects, ccLibPath.String())
+
+ if mod.Rlib() {
+ // rlibs propagate their inherited rust_ffi_rlibs forward.
+ depPaths.reexportedCcRlibDeps = append(depPaths.reexportedCcRlibDeps, exportedInfo.RustRlibDeps...)
+ }
+ }
+
+ depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
- directStaticLibDeps = append(directStaticLibDeps, ccDep)
+
+ if !mod.Rlib() {
+ // rlibs don't need to build the generated static library, so they don't need to track these.
+ depPaths.ccRlibDeps = append(depPaths.ccRlibDeps, exportedInfo.RustRlibDeps...)
+ }
+
+ directStaticLibDeps = append(directStaticLibDeps, linkableInfo)
// Record baseLibName for snapshots.
mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName))
@@ -1417,16 +1712,19 @@
sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep)
if !sharedLibraryInfo.IsStubs {
- depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
- if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
- depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ // TODO(b/362509506): remove this additional check once all apex_exclude uses are switched to stubs.
+ if !linkableInfo.RustApexExclude {
+ depPaths.directImplementationDeps = append(depPaths.directImplementationDeps, android.OutputFileForModule(ctx, dep, ""))
+ if info, ok := android.OtherModuleProvider(ctx, dep, cc.ImplementationDepInfoProvider); ok {
+ depPaths.transitiveImplementationDeps = append(depPaths.transitiveImplementationDeps, info.ImplementationDeps)
+ }
}
}
// Re-get linkObject as ChooseStubOrImpl actually tells us which
// object (either from stub or non-stub) to use.
- linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
- if !linkObject.Valid() {
+ ccLibPath = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
+ if !ccLibPath.Valid() {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
} else {
@@ -1434,10 +1732,10 @@
}
return
}
- linkPath = linkPathFromFilePath(linkObject.Path())
+ linkPath = linkPathFromFilePath(ccLibPath.Path())
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+ depPaths.sharedLibObjects = append(depPaths.sharedLibObjects, ccLibPath.String())
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
@@ -1456,15 +1754,15 @@
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
mod.Properties.AndroidMkHeaderLibs = append(mod.Properties.AndroidMkHeaderLibs, makeLibName)
case depTag == cc.CrtBeginDepTag:
- depPaths.CrtBegin = append(depPaths.CrtBegin, linkObject.Path())
+ depPaths.CrtBegin = append(depPaths.CrtBegin, ccLibPath.Path())
case depTag == cc.CrtEndDepTag:
- depPaths.CrtEnd = append(depPaths.CrtEnd, linkObject.Path())
+ depPaths.CrtEnd = append(depPaths.CrtEnd, ccLibPath.Path())
}
- // Make sure these dependencies are propagated
+ // Make sure shared dependencies are propagated
if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
lib.exportLinkDirs(linkPath)
- lib.exportLinkObjects(linkObject.String())
+ lib.exportSharedLibs(ccLibPath.String())
}
} else {
switch {
@@ -1475,7 +1773,7 @@
}
}
- if srcDep, ok := dep.(android.SourceFileProducer); ok {
+ if srcDep, ok := android.OtherModuleProvider(ctx, dep, android.SourceFilesInfoProvider); ok {
if android.IsSourceDepTagWithOutputTag(depTag, "") {
// These are usually genrules which don't have per-target variants.
directSrcDeps = append(directSrcDeps, srcDep)
@@ -1488,32 +1786,32 @@
var rlibDepFiles RustLibraries
aliases := mod.compiler.Aliases()
for _, dep := range directRlibDeps {
- crateName := dep.CrateName()
+ crateName := dep.CrateName
if alias, aliased := aliases[crateName]; aliased {
crateName = alias
}
- rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
+ rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName})
}
var dylibDepFiles RustLibraries
for _, dep := range directDylibDeps {
- crateName := dep.CrateName()
+ crateName := dep.CrateName
if alias, aliased := aliases[crateName]; aliased {
crateName = alias
}
- dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
+ dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName})
}
var procMacroDepFiles RustLibraries
for _, dep := range directProcMacroDeps {
- crateName := dep.CrateName()
+ crateName := dep.CrateName
if alias, aliased := aliases[crateName]; aliased {
crateName = alias
}
- procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: crateName})
+ procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile, CrateName: crateName})
}
var staticLibDepFiles android.Paths
for _, dep := range directStaticLibDeps {
- staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path())
+ staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile.Path())
}
var sharedLibFiles android.Paths
@@ -1529,11 +1827,11 @@
var srcProviderDepFiles android.Paths
for _, dep := range directSrcProvidersDeps {
- srcs := android.OutputFilesForModule(ctx, dep, "")
+ srcs := android.OutputFilesForModule(ctx, *dep, "")
srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
}
for _, dep := range directSrcDeps {
- srcs := dep.Srcs()
+ srcs := dep.Srcs
srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
}
@@ -1547,11 +1845,18 @@
// Dedup exported flags from dependencies
depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
- depPaths.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects)
+ depPaths.rustLibObjects = android.FirstUniqueStrings(depPaths.rustLibObjects)
+ depPaths.staticLibObjects = android.FirstUniqueStrings(depPaths.staticLibObjects)
+ depPaths.wholeStaticLibObjects = android.FirstUniqueStrings(depPaths.wholeStaticLibObjects)
+ depPaths.sharedLibObjects = android.FirstUniqueStrings(depPaths.sharedLibObjects)
depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
+ depPaths.depLinkFlags = android.FirstUniqueStrings(depPaths.depLinkFlags)
+ depPaths.reexportedCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedCcRlibDeps, cc.EqRustRlibDeps)
+ depPaths.reexportedWholeCcRlibDeps = android.FirstUniqueFunc(depPaths.reexportedWholeCcRlibDeps, cc.EqRustRlibDeps)
+ depPaths.ccRlibDeps = android.FirstUniqueFunc(depPaths.ccRlibDeps, cc.EqRustRlibDeps)
return depPaths
}
@@ -1602,7 +1907,7 @@
}
stdLinkage := "dylib-std"
- if mod.compiler.stdLinkage(ctx) == RlibLinkage {
+ if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage {
stdLinkage = "rlib-std"
}
@@ -1669,7 +1974,7 @@
// stdlibs
if deps.Stdlibs != nil {
- if mod.compiler.stdLinkage(ctx) == RlibLinkage {
+ if mod.compiler.stdLinkage(ctx.Device()) == RlibLinkage {
for _, lib := range deps.Stdlibs {
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
rlibDepTag, lib)
@@ -1787,7 +2092,7 @@
var _ android.ApexModule = (*Module)(nil)
// If a module is marked for exclusion from apexes, don't provide apex variants.
-// TODO(b/362509506): remove this once stubs are properly supported by rust_ffi targets.
+// TODO(b/362509506): remove this once all apex_exclude usages are removed.
func (m *Module) CanHaveApexVariants() bool {
if m.ApexExclude() {
return false
@@ -1801,71 +2106,113 @@
}
// Implements android.ApexModule
-func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
+func (mod *Module) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
minSdkVersion := mod.MinSdkVersion()
if minSdkVersion == "apex_inherit" {
- return nil
- }
- if minSdkVersion == "" {
- return fmt.Errorf("min_sdk_version is not specificed")
+ return android.MinApiLevel
}
+ if minSdkVersion == "" {
+ return android.NoneApiLevel
+ }
// Not using nativeApiLevelFromUser because the context here is not
// necessarily a native context.
- ver, err := android.ApiLevelFromUser(ctx, minSdkVersion)
+ ver, err := android.ApiLevelFromUserWithConfig(ctx.Config(), minSdkVersion)
if err != nil {
- return err
+ return android.NoneApiLevel
}
- if ver.GreaterThan(sdkVersion) {
- return fmt.Errorf("newer SDK(%v)", ver)
- }
- return nil
+ return ver
}
// Implements android.ApexModule
-func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- depTag := ctx.OtherModuleDependencyTag(dep)
+func (mod *Module) AlwaysRequiresPlatformApexVariant() bool {
+ // stub libraries and native bridge libraries are always available to platform
+ // TODO(b/362509506): remove the ApexExclude() check once all apex_exclude uses are switched to stubs.
+ return mod.IsStubs() || mod.Target().NativeBridge == android.NativeBridgeEnabled || mod.ApexExclude()
+}
- if ccm, ok := dep.(*cc.Module); ok {
- if ccm.HasStubsVariants() {
- if cc.IsSharedDepTag(depTag) {
- // dynamic dep to a stubs lib crosses APEX boundary
- return false
- }
- if cc.IsRuntimeDepTag(depTag) {
- // runtime dep to a stubs lib also crosses APEX boundary
- return false
- }
+// Implements android.ApexModule
+type RustDepInSameApexChecker struct {
+ Static bool
+ HasStubsVariants bool
+ ApexExclude bool
+ Host bool
+}
- if cc.IsHeaderDepTag(depTag) {
- return false
- }
- }
- if mod.Static() && cc.IsSharedDepTag(depTag) {
- // shared_lib dependency from a static lib is considered as crossing
- // the APEX boundary because the dependency doesn't actually is
- // linked; the dependency is used only during the compilation phase.
- return false
- }
+func (mod *Module) GetDepInSameApexChecker() android.DepInSameApexChecker {
+ return RustDepInSameApexChecker{
+ Static: mod.Static(),
+ HasStubsVariants: mod.HasStubsVariants(),
+ ApexExclude: mod.ApexExclude(),
+ Host: mod.Host(),
}
+}
+func (r RustDepInSameApexChecker) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
if depTag == procMacroDepTag || depTag == customBindgenDepTag {
return false
}
- if rustDep, ok := dep.(*Module); ok && rustDep.ApexExclude() {
+ if r.Static && cc.IsSharedDepTag(depTag) {
+ // shared_lib dependency from a static lib is considered as crossing
+ // the APEX boundary because the dependency doesn't actually is
+ // linked; the dependency is used only during the compilation phase.
+ return false
+ }
+
+ if depTag == cc.StubImplDepTag {
+ // We don't track from an implementation library to its stubs.
+ return false
+ }
+
+ if cc.ExcludeInApexDepTag(depTag) {
+ return false
+ }
+
+ // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
+ if r.ApexExclude {
return false
}
return true
}
+func (r RustDepInSameApexChecker) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if r.Host {
+ return false
+ }
+ // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
+ if r.ApexExclude {
+ return false
+ }
+
+ if r.HasStubsVariants {
+ if cc.IsSharedDepTag(depTag) && !cc.IsExplicitImplSharedDepTag(depTag) {
+ // dynamic dep to a stubs lib crosses APEX boundary
+ return false
+ }
+ if cc.IsRuntimeDepTag(depTag) {
+ // runtime dep to a stubs lib also crosses APEX boundary
+ return false
+ }
+ if cc.IsHeaderDepTag(depTag) {
+ return false
+ }
+ }
+ return true
+}
+
// Overrides ApexModule.IsInstallabeToApex()
func (mod *Module) IsInstallableToApex() bool {
+ // TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
+ if mod.ApexExclude() {
+ return false
+ }
+
if mod.compiler != nil {
- if lib, ok := mod.compiler.(libraryInterface); ok && (lib.shared() || lib.dylib()) {
- return true
+ if lib, ok := mod.compiler.(libraryInterface); ok {
+ return (lib.shared() || lib.dylib()) && !lib.BuildStubs()
}
if _, ok := mod.compiler.(*binaryDecorator); ok {
return true
@@ -1893,9 +2240,9 @@
func (k kytheExtractRustSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var xrefTargets android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- if rustModule, ok := module.(xref); ok {
- xrefTargets = append(xrefTargets, rustModule.XrefRustFiles()...)
+ ctx.VisitAllModuleProxies(func(module android.ModuleProxy) {
+ if rustModule, ok := android.OtherModuleProvider(ctx, module, RustInfoProvider); ok {
+ xrefTargets = append(xrefTargets, rustModule.XrefRustFiles...)
}
})
if len(xrefTargets) > 0 {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 767508d..f634bb5 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -184,8 +184,8 @@
srcs: ["foo.rs"],
}
`)
- module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
- rustc := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
+ module := ctx.ModuleForTests(t, "fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+ rustc := ctx.ModuleForTests(t, "librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
if !android.InList("librlib.rlib-std", module.Properties.AndroidMkRlibs) {
@@ -204,7 +204,7 @@
t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
}
- if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=wholestatic") {
+ if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic:+whole-archive=wholestatic") {
t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.Args["rustcFlags"])
}
@@ -274,7 +274,7 @@
}
`)
- libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Rule("rustc")
+ libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_dylib-std").Rule("rustc")
if !android.SuffixInList(libfoo.Implicits.Strings(), "/out/bindings.rs") {
t.Errorf("rust_bindgen generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings())
}
@@ -282,7 +282,7 @@
t.Errorf("genrule generated source not included as implicit input for libfoo; Implicits %#v", libfoo.Implicits.Strings())
}
- fizzBuzz := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Rule("rustc")
+ fizzBuzz := ctx.ModuleForTests(t, "fizz-buzz-dep", "android_arm64_armv8-a").Rule("rustc")
if !android.SuffixInList(fizzBuzz.Implicits.Strings(), "/out/bindings.rs") {
t.Errorf("rust_bindgen generated source not included as implicit input for fizz-buzz-dep; Implicits %#v", libfoo.Implicits.Strings())
}
@@ -290,7 +290,7 @@
t.Errorf("genrule generated source not included as implicit input for fizz-buzz-dep; Implicits %#v", libfoo.Implicits.Strings())
}
- libprocmacro := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Rule("rustc")
+ libprocmacro := ctx.ModuleForTests(t, "libprocmacro", "linux_glibc_x86_64").Rule("rustc")
if !android.SuffixInList(libprocmacro.Implicits.Strings(), "/out/bindings.rs") {
t.Errorf("rust_bindgen generated source not included as implicit input for libprocmacro; Implicits %#v", libfoo.Implicits.Strings())
}
@@ -299,15 +299,15 @@
}
// Check that our bindings are picked up as crate dependencies as well
- libfooMod := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
+ libfooMod := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_dylib").Module().(*Module)
if !android.InList("libbindings", libfooMod.Properties.AndroidMkRlibs) {
t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
}
- fizzBuzzMod := ctx.ModuleForTests("fizz-buzz-dep", "android_arm64_armv8-a").Module().(*Module)
+ fizzBuzzMod := ctx.ModuleForTests(t, "fizz-buzz-dep", "android_arm64_armv8-a").Module().(*Module)
if !android.InList("libbindings", fizzBuzzMod.Properties.AndroidMkRlibs) {
t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
}
- libprocmacroMod := ctx.ModuleForTests("libprocmacro", "linux_glibc_x86_64").Module().(*Module)
+ libprocmacroMod := ctx.ModuleForTests(t, "libprocmacro", "linux_glibc_x86_64").Module().(*Module)
if !android.InList("libbindings.rlib-std", libprocmacroMod.Properties.AndroidMkRlibs) {
t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
}
@@ -354,7 +354,7 @@
srcs: ["foo.rs"],
}
`)
- rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
+ rustc := ctx.ModuleForTests(t, "libpm", "linux_glibc_x86_64").Rule("rustc")
if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
t.Errorf("Proc_macro is not using host variant of dependent modules.")
@@ -369,7 +369,7 @@
srcs: ["foo.rs"],
no_stdlibs: true,
}`)
- module := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
+ module := ctx.ModuleForTests(t, "fizz-buzz", "android_arm64_armv8-a").Module().(*Module)
if android.InList("libstd", module.Properties.AndroidMkDylibs) {
t.Errorf("no_stdlibs did not suppress dependency on libstd")
@@ -385,8 +385,8 @@
crate_name: "foo",
}`)
- _ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std")
- _ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_rlib_dylib-std")
+ _ = ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_rlib_dylib-std")
+ _ = ctx.ModuleForTests(t, "libfoo", "android_arm_armv7-a-neon_rlib_dylib-std")
}
// Test that library size measurements are generated.
@@ -398,7 +398,7 @@
crate_name: "waldo",
}`)
- m := ctx.SingletonForTests("file_metrics")
+ m := ctx.SingletonForTests(t, "file_metrics")
m.Output("unstripped/libwaldo.dylib.so.bloaty.csv")
m.Output("libwaldo.dylib.so.bloaty.csv")
}
@@ -423,38 +423,66 @@
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"])
+ fooRustc := ctx.ModuleForTests(t, "foo", "android_arm64_armv8-a").Rule("rustc")
+ if !strings.Contains(fooRustc.Args["libFlags"], "--extern force:bar_renamed=out/soong/.intermediates/libbar/android_arm64_armv8-a_dylib/unstripped/libbar.dylib.so") {
+ t.Errorf("--extern force: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"])
+ if !strings.Contains(fooRustc.Args["libFlags"], "--extern force:baz=out/soong/.intermediates/libbaz/android_arm64_armv8-a_dylib/unstripped/libbaz.dylib.so") {
+ t.Errorf("--extern force: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 TestRustRlibs(t *testing.T) {
+func TestRustFFIRlibs(t *testing.T) {
ctx := testRust(t, `
- rust_ffi_rlib {
+ rust_ffi_static {
name: "libbar",
crate_name: "bar",
srcs: ["src/lib.rs"],
export_include_dirs: ["bar_includes"]
}
- rust_ffi_rlib {
+ rust_ffi_static {
name: "libfoo",
crate_name: "foo",
srcs: ["src/lib.rs"],
export_include_dirs: ["foo_includes"]
}
- rust_ffi_rlib {
+ rust_ffi_static {
+ name: "libfoo_from_rlib",
+ crate_name: "foo_from_rlib",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["foo_includes"]
+ }
+
+ rust_ffi_static {
+ name: "libfoo_from_rlib_whole",
+ crate_name: "foo_from_rlib_whole",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["foo_includes"]
+ }
+
+ rust_ffi_static {
name: "libbuzz",
crate_name: "buzz",
srcs: ["src/lib.rs"],
export_include_dirs: ["buzz_includes"]
}
+ rust_ffi_static {
+ name: "libbuzz_from_rlib",
+ crate_name: "buzz_from_rlib",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["buzz_includes"]
+ }
+
+ rust_ffi_static {
+ name: "libbuzz_from_rlib_whole",
+ crate_name: "buzz_from_rlib_whole",
+ srcs: ["src/lib.rs"],
+ export_include_dirs: ["buzz_includes"]
+ }
+
cc_library_shared {
name: "libcc_shared",
srcs:["foo.c"],
@@ -468,20 +496,64 @@
whole_static_libs: ["libfoo"],
}
+ cc_library_static {
+ name: "libcc_static_from_rlib",
+ srcs:["foo.c"],
+ static_libs: ["libbuzz_from_rlib"],
+ whole_static_libs: ["libfoo_from_rlib"],
+ }
+
+ cc_library_static {
+ name: "libcc_whole_static_from_rlib",
+ srcs:["foo.c"],
+ static_libs: ["libbuzz_from_rlib_whole"],
+ whole_static_libs: ["libfoo_from_rlib_whole"],
+ }
+
cc_binary {
name: "ccBin",
srcs:["foo.c"],
static_libs: ["libcc_static", "libbar"],
}
- `)
- libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
- libcc_shared_rustc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
- libcc_shared_ld := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("ld")
- libcc_shared_cc := ctx.ModuleForTests("libcc_shared", "android_arm64_armv8-a_shared").Rule("cc")
- ccbin_rustc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("rustc")
- ccbin_ld := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("ld")
- ccbin_cc := ctx.ModuleForTests("ccBin", "android_arm64_armv8-a").Rule("cc")
+ rust_library {
+ name: "librs",
+ srcs:["src/foo.rs"],
+ crate_name: "rs",
+ static_libs: ["libcc_static_from_rlib"],
+ whole_static_libs: ["libcc_whole_static_from_rlib"],
+ }
+
+ rust_library {
+ name: "librs2",
+ srcs:["src/foo.rs"],
+ crate_name: "rs",
+ rustlibs: ["librs"],
+ }
+
+ rust_binary {
+ name: "rsBin",
+ srcs:["src/foo.rs"],
+ crate_name: "rsBin",
+ rlibs: ["librs", "libbar"],
+ static_libs: ["libcc_static"],
+ }
+ `)
+
+ libbar := ctx.ModuleForTests(t, "libbar", "android_arm64_armv8-a_rlib_rlib-std").Rule("rustc")
+ libcc_shared_rustc := ctx.ModuleForTests(t, "libcc_shared", "android_arm64_armv8-a_shared").Rule("rustc")
+ libcc_shared_ld := ctx.ModuleForTests(t, "libcc_shared", "android_arm64_armv8-a_shared").Rule("ld")
+ libcc_shared_cc := ctx.ModuleForTests(t, "libcc_shared", "android_arm64_armv8-a_shared").Rule("cc")
+ ccbin_rustc := ctx.ModuleForTests(t, "ccBin", "android_arm64_armv8-a").Rule("rustc")
+ ccbin_ld := ctx.ModuleForTests(t, "ccBin", "android_arm64_armv8-a").Rule("ld")
+ ccbin_cc := ctx.ModuleForTests(t, "ccBin", "android_arm64_armv8-a").Rule("cc")
+ rustbin_genlib := ctx.ModuleForTests(t, "rsBin", "android_arm64_armv8-a").Output("generated_rust_staticlib/librustlibs.a")
+ rustbin := ctx.ModuleForTests(t, "rsBin", "android_arm64_armv8-a").Output("unstripped/rsBin")
+ librs_rlib := ctx.ModuleForTests(t, "librs", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
+ librs2_rlib := ctx.ModuleForTests(t, "librs2", "android_arm64_armv8-a_rlib_dylib-std").MaybeOutput("generated_rust_staticlib/librustlibs.a")
+ librs_genlib := ctx.ModuleForTests(t, "librs", "android_arm64_armv8-a_dylib").Output("generated_rust_staticlib/librustlibs.a")
+ librs2_genlib := ctx.ModuleForTests(t, "librs2", "android_arm64_armv8-a_dylib").Output("generated_rust_staticlib/librustlibs.a")
+ librs2_dylib := ctx.ModuleForTests(t, "librs2", "android_arm64_armv8-a_dylib").Output("unstripped/librs2.dylib.so")
if !strings.Contains(libbar.Args["rustcFlags"], "crate-type=rlib") {
t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", "rlib", libbar.Args["rustcFlags"])
@@ -513,7 +585,7 @@
// Make sure the static lib is included in the cc command
if !strings.Contains(ccbin_ld.Args["libFlags"], "generated_rust_staticlib/librustlibs.a") {
t.Errorf("missing generated static library in linker step libFlags, expecting %#v, libFlags: %#v",
- "ccBin.generated_rust_staticlib.a", ccbin_ld.Args["libFlags"])
+ "generated_rust_staticlib/librustlibs.a", ccbin_ld.Args["libFlags"])
}
// Make sure the static lib includes are in the ld command
@@ -534,11 +606,72 @@
t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
}
+ // Make sure the static lib is included in the rustc command
+ if !strings.Contains(rustbin.Args["linkFlags"], "generated_rust_staticlib/librustlibs.a") {
+ t.Errorf("missing generated static library in linker step libFlags in Rust module, expecting %#v, libFlags: %#v",
+ "generated_rust_staticlib/librustlibs.a", rustbin.Args["libFlags"])
+ }
+ if !strings.Contains(librs2_dylib.Args["linkFlags"], "generated_rust_staticlib/librustlibs.a") {
+ t.Errorf("missing generated static library in linker step libFlags in Rust module, expecting %#v, libFlags: %#v",
+ "generated_rust_staticlib/librustlibs.a", librs2_dylib.Args["libFlags"])
+ }
+
+ // Make sure that direct dependencies and indirect whole static dependencies are
+ // propagating correctly for the rlib -> cc_library_static -> rust_* generated library example.
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz=") {
+ t.Errorf("Indirect rlib dependency libbuzz from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern bar=") {
+ t.Errorf("Direct rlib dependency libbar getting included in the generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo_from_rlib=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib from cc static_lib when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+ if strings.Contains(rustbin_genlib.Args["libFlags"], "--extern buzz_from_rlib=") {
+ // While static-libs propagate for rust modules, this is not the
+ // expected behavior for cc modules. Thus, libbuzz_from_rlib would
+ // be expected to have to be re-declared as a direct rlib dependency.
+ t.Errorf("Indirect rlib dependency libbuzz_from_rlib from cc static_lib found when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+
// Test indirect includes propagation
if !strings.Contains(ccbin_cc.Args["cFlags"], "-Ifoo_includes") {
t.Errorf("missing rlibs includes, expecting %#v, cFlags: %#v",
"-Ifoo_includes", ccbin_cc.Args)
}
+
+ // Make sure we're not generating superfluous mto staticlibs.
+ if librs_rlib.Rule != nil {
+ t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
+ }
+ if librs2_rlib.Rule != nil {
+ t.Error("rlibs should not be generating mto staticlibs", "rlib", libbar.Args["rustcFlags"])
+ }
+
+ // Make sure that direct whole static dependencies are propagating correctly downstream
+ // foo_from_rlib_whole --(ws)--> libcc_whole_static_from_rlib --(ws)--> librs
+ if !strings.Contains(librs_genlib.Args["libFlags"], "--extern foo_from_rlib_whole=") {
+ t.Errorf("Missing direct whole_static_lib dependency libfoo_from_rlib_whole from rust dylib when writing generated Rust staticlib: %#v", librs_genlib.Args["libFlags"])
+ }
+
+ // Make sure that indirect whole static dependencies are propagating correctly downstream
+ // foo_from_rlib_whole --(ws)--> libcc_whole_static_from_rlib --(ws)--> librs --> rust_*
+ if !strings.Contains(librs2_genlib.Args["libFlags"], "--extern foo_from_rlib_whole=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib_whole from rust dylib when writing generated Rust staticlib: %#v", librs2_genlib.Args["libFlags"])
+ }
+ if !strings.Contains(rustbin_genlib.Args["libFlags"], "--extern foo_from_rlib_whole=") {
+ t.Errorf("Missing indirect whole_static_lib dependency libfoo_from_rlib_whole from rust dylib in rust binary when writing generated Rust staticlib: %#v", rustbin_genlib.Args["libFlags"])
+ }
+
+ // Make sure that normal static dependencies are not propagating through dylib dependencies
+ // buzz_from_rlib_whole --(s)--> libcc_whole_static_from_rlib --(ws)--> librs --> rust_*
+ if strings.Contains(librs2_genlib.Args["libFlags"], "--extern buzz_from_rlib_whole=") {
+ t.Errorf("dependency from indirect cc staticlib from direct dylib dep found in rust dylib when writing generated Rust staticlib: %#v", librs2_genlib.Args["libFlags"])
+ }
+
}
func assertString(t *testing.T, got, expected string) {
@@ -547,3 +680,204 @@
t.Errorf("expected %q got %q", expected, got)
}
}
+
+func TestStdLinkMismatch(t *testing.T) {
+ // Test that we catch cases where the std linkage mismatches. This leads to
+ // a confusing rustc error where a crate is declared missing despite being
+ // passed in as a rustlib dependency / via the --extern flag. Thus, we want
+ // to make sure we detect it in Soong.
+
+ // libfoo depends on libbar as an rlib, but does not link libstd as an rlib.
+ // libbar only links libstd as an rlib (prefer_rlib).
+ testRustError(t, "wrong StdLinkage", `
+ rust_library {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: [
+ "foo.rs",
+ ],
+ rlibs: ["libbar"],
+ }
+ rust_library {
+ name: "libbar",
+ crate_name: "bar",
+ srcs: [
+ "bar.rs",
+ ],
+ prefer_rlib: true,
+ }
+ `)
+}
+
+func TestRustLinkPropagation(t *testing.T) {
+ // Test static and whole static propagation behavior
+ //
+ // Whole static libs propagate through rlibs and through dylibs to
+ // dependencies further down. rustc does not re-export whole-archived
+ // static libs for dylibs, so this simulates re-exporting those symbols.
+ //
+ // Static libs only propagate through rlibs to some final dylib. We propagate
+ // normal static libs because we allow rustlib dependencies to represent
+ // either rlibs or dylibs. Not propagating static libs through rlibs would
+ // mean we'd need to always redeclare static libs throughout a dependency tree
+ // We don't propagate past dylibs because they represent a final link.
+
+ ctx := testRust(t, `
+ rust_library_rlib {
+ name: "librlib1",
+ crate_name: "rlib1",
+ srcs: ["src/lib.rs"],
+ static_libs: ["libcc_static_rlib1"],
+ whole_static_libs: ["libcc_whole_static_rlib1"],
+ }
+
+ rust_library_dylib {
+ name: "libdylib1",
+ crate_name: "dylib1",
+ static_libs: ["libcc_static_dylib1"],
+ srcs: ["src/lib.rs"],
+ whole_static_libs: ["libcc_whole_static_dylib1"],
+ }
+
+ rust_library_rlib {
+ name: "librlib2",
+ crate_name: "rlib2",
+ srcs: ["src/lib.rs"],
+ rlibs: ["librlib1"],
+ static_libs: ["libcc_static_rlib2"],
+ whole_static_libs: ["libcc_whole_static_rlib2"],
+ }
+
+ rust_library_dylib {
+ name: "libdylib2",
+ crate_name: "dylib2",
+ srcs: ["src/lib.rs"],
+ rlibs: ["librlib1"],
+ rustlibs: ["libdylib1"],
+ static_libs: ["libcc_static_dylib2"],
+ whole_static_libs: ["libcc_whole_static_dylib2"],
+ }
+
+ cc_library_static {
+ name: "libcc_static_rlib1",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_static_rlib2",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_static_dylib1",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_static_dylib2",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_whole_static_rlib1",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_whole_static_rlib2",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_whole_static_dylib1",
+ srcs:["foo.c"],
+ }
+
+ cc_library_static {
+ name: "libcc_whole_static_dylib2",
+ srcs:["foo.c"],
+ }
+
+ rust_library_rlib {
+ name: "librlib3",
+ crate_name: "rlib3",
+ srcs: ["src/lib.rs"],
+ rlibs: ["librlib2"],
+ }
+
+ rust_library_dylib {
+ name: "libdylib3",
+ crate_name: "dylib3",
+ srcs: ["src/lib.rs"],
+ rlibs: ["librlib2"],
+ rustlibs: ["libdylib2"],
+ }
+ `)
+
+ librlib3 := ctx.ModuleForTests(t, "librlib3", "android_arm64_armv8-a_rlib_dylib-std").Rule("rustc")
+ libdylib3 := ctx.ModuleForTests(t, "libdylib3", "android_arm64_armv8-a_dylib").Rule("rustc")
+
+ // Test static lib propagation from:
+ // rlib -> rlib
+ if !strings.Contains(librlib3.Args["linkFlags"], "libcc_static_rlib2.a") {
+ t.Errorf("direct dependency static lib not propagating from rlib to rlib; linkFlags %#v",
+ librlib3.Args["linkFlags"])
+ }
+ // rlib -> rlib -> rlib
+ if !strings.Contains(librlib3.Args["linkFlags"], "libcc_static_rlib1.a") {
+ t.Errorf("indirect dependency static lib not propagating from rlib to rlib: linkFlags %#v",
+ librlib3.Args["linkFlags"])
+ }
+ // rlib -> rlib -> dylib
+ if !strings.Contains(libdylib3.Args["linkFlags"], "libcc_static_rlib1.a") {
+ t.Errorf("indirect dependency static lib not propagating from rlib to dylib: linkFlags %#v",
+ libdylib3.Args["linkFlags"])
+ }
+ // rlib -> dylib
+ if !strings.Contains(libdylib3.Args["linkFlags"], "libcc_static_rlib2.a") {
+ t.Errorf("direct dependency static lib not propagating from rlib to dylib: linkFlags: %#v",
+ libdylib3.Args["linkFlags"])
+ }
+ // dylib -> dylib (negative case, should not propagate)
+ if strings.Contains(libdylib3.Args["linkFlags"], "libcc_static_dylib2.a") {
+ t.Errorf("direct dependency static lib propagating from dylib to dylib: linkFlags: %#v",
+ libdylib3.Args["linkFlags"])
+ }
+ // dylib -> dylib -> dylib (negative case, should not propagate)
+ if strings.Contains(libdylib3.Args["linkFlags"], "libcc_static_dylib1.a") {
+ t.Errorf("indirect dependency static lib propagating from dylib to dylib: linkFlags: %#v",
+ libdylib3.Args["linkFlags"])
+ }
+
+ // Test whole static lib propagation from:
+ // rlib -> rlib
+ if !strings.Contains(librlib3.Args["linkFlags"], "libcc_whole_static_rlib2.a") {
+ t.Errorf("direct dependency whole static lib not propagating from rlib to rlib: linkFlags %#v",
+ librlib3.Args["linkFlags"])
+ }
+ // rlib -> rlib -> rlib
+ if !strings.Contains(librlib3.Args["linkFlags"], "libcc_whole_static_rlib1.a") {
+ t.Errorf("indirect dependency whole static lib not propagating from rlib to rlib: linkFlags %#v",
+ librlib3.Args["linkFlags"])
+ }
+ // rlib -> dylib
+ if !strings.Contains(libdylib3.Args["linkFlags"], "libcc_whole_static_rlib2.a") {
+ t.Errorf("direct dependency whole static lib not propagating from rlib to dylib: linkFlags %#v",
+ libdylib3.Args["linkFlags"])
+ }
+ // rlib -> rlib -> dylib
+ if !strings.Contains(libdylib3.Args["linkFlags"], "libcc_whole_static_rlib1.a") {
+ t.Errorf("indirect dependency whole static lib not propagating from rlib to dylib: linkFlags %#v",
+ libdylib3.Args["linkFlags"])
+ }
+ // dylib -> dylib
+ if !strings.Contains(libdylib3.Args["linkFlags"], "libcc_whole_static_dylib2.a") {
+ t.Errorf("direct dependency whole static lib not propagating from dylib to dylib: linkFlags %#v",
+ libdylib3.Args["linkFlags"])
+ }
+ // dylib -> dylib -> dylib
+ if !strings.Contains(libdylib3.Args["linkFlags"], "libcc_whole_static_dylib1.a") {
+ t.Errorf("indirect dependency whole static lib not propagating from dylib to dylib: linkFlags %#v",
+ libdylib3.Args["linkFlags"])
+ }
+}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index b8f922f..50f55ce 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -53,6 +53,9 @@
// Used when we need to place libraries in their own directory, such as ASAN.
InSanitizerDir bool `blueprint:"mutated"`
+
+ // ForceDisable is set by the version mutator to disable sanitization of stubs variants
+ ForceDisable bool `blueprint:"mutated"`
}
var fuzzerFlags = []string{
@@ -103,6 +106,10 @@
func (sanitize *sanitize) begin(ctx BaseModuleContext) {
s := &sanitize.Properties.Sanitize
+ if sanitize.Properties.ForceDisable {
+ return
+ }
+
// Disable sanitizers for musl x86 modules, rustc does not support any sanitizers.
if ctx.Os() == android.LinuxMusl && ctx.Arch().ArchType == android.X86 {
s.Never = proptools.BoolPtr(true)
@@ -221,6 +228,10 @@
}
func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
+ if sanitize.Properties.ForceDisable {
+ return flags, deps
+ }
+
if !sanitize.Properties.SanitizerEnabled {
return flags, deps
}
@@ -253,6 +264,9 @@
if !mod.Enabled(mctx) {
return
}
+ if mod.sanitize.Properties.ForceDisable {
+ return
+ }
if Bool(mod.sanitize.Properties.Sanitize.Memtag_heap) && mod.Binary() {
noteDep := "note_memtag_heap_async"
@@ -364,7 +378,7 @@
// distinguish between the cases. It isn't needed though - both cases can be
// treated identically.
func (sanitize *sanitize) isSanitizerEnabled(t cc.SanitizerType) bool {
- if sanitize == nil || !sanitize.Properties.SanitizerEnabled {
+ if sanitize == nil || !sanitize.Properties.SanitizerEnabled || sanitize.Properties.ForceDisable {
return false
}
@@ -453,7 +467,7 @@
}
func (mod *Module) SanitizeNever() bool {
- return Bool(mod.sanitize.Properties.Sanitize.Never)
+ return Bool(mod.sanitize.Properties.Sanitize.Never) || mod.sanitize.Properties.ForceDisable
}
var _ cc.PlatformSanitizeable = (*Module)(nil)
diff --git a/rust/sanitize_test.go b/rust/sanitize_test.go
index d6a14b2..a3fe282 100644
--- a/rust/sanitize_test.go
+++ b/rust/sanitize_test.go
@@ -153,65 +153,65 @@
).RunTest(t)
ctx := result.TestContext
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}
func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
@@ -226,67 +226,67 @@
).RunTest(t)
ctx := result.TestContext
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}
func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
@@ -302,64 +302,64 @@
).RunTest(t)
ctx := result.TestContext
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_binary_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_binary_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_no_override", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_async", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("no_memtag_test_override_default_sync", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_no_override", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_async", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "no_memtag_test_override_default_sync", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_binary_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_binary_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_no_override", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_async", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_disable", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_async_test_override_default_sync", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_no_override", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_async", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_disable", variant), Async)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_async_test_override_default_sync", variant), Async)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("set_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "set_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_async", variant), Sync)
// should sanitize: { diag: { memtag: true } } result in Sync instead of None here?
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_memtag_set_sync_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_memtag_set_sync_test_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_disable", variant), None)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_binary_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_disable", variant), None)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_binary_override_default_sync", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_no_override", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_async", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
- checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_no_override", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_async", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_disable", variant), Sync)
+ checkHasMemtagNote(t, ctx.ModuleForTests(t, "unset_test_override_default_sync", variant), Sync)
}
diff --git a/rust/source_provider.go b/rust/source_provider.go
index 3236bce..27c62c2 100644
--- a/rust/source_provider.go
+++ b/rust/source_provider.go
@@ -43,6 +43,7 @@
SourceProviderProps() []interface{}
SourceProviderDeps(ctx DepsContext, deps Deps) Deps
setSubName(subName string)
+ getSubName() string
setOutputFiles(outputFiles android.Paths)
}
@@ -100,6 +101,10 @@
sp.subName = subName
}
+func (sp *BaseSourceProvider) getSubName() string {
+ return sp.subName
+}
+
func (sp *BaseSourceProvider) setOutputFiles(outputFiles android.Paths) {
sp.OutputFiles = outputFiles
}
diff --git a/rust/test.go b/rust/test.go
index 20ccfb3..cedced2 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -46,9 +46,16 @@
// the test
Data []string `android:"path,arch_variant"`
- // Same as data, but will add dependencies on the device's
+ // Same as data, but adds dependencies on modules using the device's os variant, and common
+ // architecture's variant. Can be useful to add device-built apps to the data of a host
+ // test.
Device_common_data []string `android:"path_device_common"`
+ // Same as data, but will add dependencies on modules using the host's os variation and
+ // the common arch variation. Useful for a device test that wants to depend on a host
+ // module, for example to include a custom Tradefed test runner.
+ Host_common_data []string `android:"path_host_common"`
+
// list of shared library modules that should be installed alongside the test
Data_libs []string `android:"arch_variant"`
@@ -147,36 +154,38 @@
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...)
+ dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...)
- ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataLibDepTag, func(dep android.ModuleProxy) {
depName := ctx.OtherModuleName(dep)
- linkableDep, ok := dep.(cc.LinkableInterface)
+ linkableDep, ok := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider)
if !ok {
ctx.ModuleErrorf("data_lib %q is not a linkable module", depName)
}
- if linkableDep.OutputFile().Valid() {
+ if linkableDep.OutputFile.Valid() {
// Copy the output in "lib[64]" so that it's compatible with
// the default rpath values.
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
libDir := "lib"
- if linkableDep.Target().Arch.ArchType.Multilib == "lib64" {
+ if commonInfo.Target.Arch.ArchType.Multilib == "lib64" {
libDir = "lib64"
}
test.data = append(test.data,
- android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
- RelativeInstallPath: filepath.Join(libDir, linkableDep.RelativeInstallPath())})
+ android.DataPath{SrcPath: linkableDep.OutputFile.Path(),
+ RelativeInstallPath: filepath.Join(libDir, linkableDep.RelativeInstallPath)})
}
})
- ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) {
+ ctx.VisitDirectDepsProxyWithTag(dataBinDepTag, func(dep android.ModuleProxy) {
depName := ctx.OtherModuleName(dep)
- linkableDep, ok := dep.(cc.LinkableInterface)
+ linkableDep, ok := android.OtherModuleProvider(ctx, dep, cc.LinkableInfoProvider)
if !ok {
ctx.ModuleErrorf("data_bin %q is not a linkable module", depName)
}
- if linkableDep.OutputFile().Valid() {
+ if linkableDep.OutputFile.Valid() {
test.data = append(test.data,
- android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
- RelativeInstallPath: linkableDep.RelativeInstallPath()})
+ android.DataPath{SrcPath: linkableDep.OutputFile.Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath})
}
})
@@ -194,6 +203,31 @@
if ctx.Host() && test.Properties.Test_options.Unit_test == nil {
test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
}
+
+ if !ctx.Config().KatiEnabled() { // TODO(spandandas): Remove the special case for kati
+ // Install the test config in testcases/ directory for atest.
+ r, ok := ctx.Module().(*Module)
+ if !ok {
+ ctx.ModuleErrorf("Not a rust test module")
+ }
+ // Install configs in the root of $PRODUCT_OUT/testcases/$module
+ testCases := android.PathForModuleInPartitionInstall(ctx, "testcases", ctx.ModuleName()+r.SubName())
+ if ctx.PrimaryArch() {
+ if test.testConfig != nil {
+ ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
+ }
+ dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+ if dynamicConfig.Valid() {
+ ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+ }
+ }
+ // Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
+ testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
+ ctx.InstallTestData(testCases, test.data)
+ testPath := ctx.RustModule().OutputFile().Path()
+ ctx.InstallFile(testCases, testPath.Base(), testPath)
+ }
+
test.binaryDecorator.installTestData(ctx, test.data)
test.binaryDecorator.install(ctx)
}
@@ -202,11 +236,16 @@
flags = test.binaryDecorator.compilerFlags(ctx, flags)
if test.testHarness() {
flags.RustFlags = append(flags.RustFlags, "--test")
+ flags.RustFlags = append(flags.RustFlags, "-A missing-docs")
}
if ctx.Device() {
flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests")
}
+ // Add a default rpath to allow tests to dlopen libraries specified in data_libs.
+ flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, `-Wl,-rpath,\$$ORIGIN/lib64`)
+ flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+
return flags
}
@@ -238,7 +277,7 @@
return module.Init()
}
-func (test *testDecorator) stdLinkage(ctx *depsContext) RustLinkage {
+func (test *testDecorator) stdLinkage(device bool) RustLinkage {
return RlibLinkage
}
@@ -257,6 +296,36 @@
return true
}
+func (test *testDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ test.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+ if Bool(test.Properties.Test_options.Unit_test) {
+ moduleInfoJSON.IsUnitTest = "true"
+ if ctx.Host() {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
+ }
+ moduleInfoJSON.TestOptionsTags = append(moduleInfoJSON.TestOptionsTags, test.Properties.Test_options.Tags...)
+ if test.testConfig != nil {
+ if _, ok := test.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.testConfig.String())
+ }
+
+ moduleInfoJSON.DataDependencies = append(moduleInfoJSON.DataDependencies, test.Properties.Data_bins...)
+
+ if len(test.Properties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.Properties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: test.Properties.Test_suites,
+ })
+}
+
func rustTestHostMultilib(ctx android.LoadHookContext) {
type props struct {
Target struct {
diff --git a/rust/test_test.go b/rust/test_test.go
index 1097da2..076a259 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -29,7 +29,7 @@
data: ["data.txt"],
}`)
- testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64")
+ testingModule := ctx.ModuleForTests(t, "my_test", "linux_glibc_x86_64")
expectedOut := "my_test/linux_glibc_x86_64/my_test"
outPath := testingModule.Output("my_test").Output.String()
if !strings.Contains(outPath, expectedOut) {
@@ -62,7 +62,7 @@
crate_name: "bar",
}`)
- testingModule := ctx.ModuleForTests("my_test", "android_arm64_armv8-a").Module().(*Module)
+ testingModule := ctx.ModuleForTests(t, "my_test", "android_arm64_armv8-a").Module().(*Module)
if !android.InList("libfoo.rlib-std", testingModule.Properties.AndroidMkRlibs) {
t.Errorf("rlib-std variant for libfoo not detected as a rustlib-defined rlib dependency for device rust_test module")
@@ -106,7 +106,7 @@
ctx := testRust(t, bp)
- testingModule := ctx.ModuleForTests("main_test", "android_arm64_armv8-a")
+ testingModule := ctx.ModuleForTests(t, "main_test", "android_arm64_armv8-a")
testBinary := testingModule.Module().(*Module).compiler.(*testDecorator)
outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
@@ -165,7 +165,7 @@
`
ctx := testRust(t, bp)
- testingModule := ctx.ModuleForTests("main_test", "android_arm64_armv8-a")
+ testingModule := ctx.ModuleForTests(t, "main_test", "android_arm64_armv8-a")
module := testingModule.Module()
testBinary := module.(*Module).compiler.(*testDecorator)
outputFiles := testingModule.OutputFiles(ctx, t, "")
diff --git a/rust/testing.go b/rust/testing.go
index 32cc823..2082b52 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -80,7 +80,6 @@
no_libcrt: true,
nocrt: true,
system_shared_libs: [],
- apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
min_sdk_version: "29",
vendor_available: true,
host_supported: true,
@@ -88,6 +87,13 @@
llndk: {
symbol_file: "liblog.map.txt",
},
+ stubs: {
+ symbol_file: "liblog.map.txt",
+ versions: [
+ "29",
+ "30",
+ ],
+ },
}
cc_library {
name: "libprotobuf-cpp-full",
@@ -188,12 +194,10 @@
ctx.RegisterModuleType("rust_fuzz_host", RustFuzzHostFactory)
ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
- ctx.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory)
- ctx.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory)
+ ctx.RegisterModuleType("rust_ffi_static", RustLibraryRlibFactory)
ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
- ctx.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
- ctx.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory)
+ ctx.RegisterModuleType("rust_ffi_host_static", RustLibraryRlibHostFactory)
ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 00b3ca5..b6cac32 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -254,11 +254,6 @@
],
}
-sh_binary_host {
- name: "list_image",
- src: "list_image.sh",
-}
-
filegroup {
name: "rustfmt.toml",
srcs: ["rustfmt.toml"],
@@ -287,16 +282,12 @@
],
}
-sh_binary_host {
- name: "keep-flagged-apis",
- src: "keep-flagged-apis.sh",
-}
-
python_binary_host {
- name: "merge_directories",
- main: "merge_directories.py",
- srcs: [
- "merge_directories.py",
+ name: "aconfig-to-metalava-flags",
+ main: "aconfig-to-metalava-flags.py",
+ srcs: ["aconfig-to-metalava-flags.py"],
+ libs: [
+ "libaconfig_python_proto",
],
}
@@ -319,3 +310,11 @@
main: "extra_install_zips_file_list.py",
srcs: ["extra_install_zips_file_list.py"],
}
+
+python_binary_host {
+ name: "rustc_linker",
+ main: "rustc_linker.py",
+ srcs: [
+ "rustc_linker.py",
+ ],
+}
diff --git a/scripts/aconfig-to-metalava-flags.py b/scripts/aconfig-to-metalava-flags.py
new file mode 100644
index 0000000..efa85ec
--- /dev/null
+++ b/scripts/aconfig-to-metalava-flags.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2025 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.
+
+"""Converts a set of aconfig protobuf flags to a Metalava config file."""
+
+# Formatted using `pyformat -i scripts/aconfig-to-metalava-flags.py`
+
+import argparse
+import sys
+import xml.etree.ElementTree as ET
+
+from protos import aconfig_pb2
+
+_READ_ONLY = aconfig_pb2.flag_permission.READ_ONLY
+_ENABLED = aconfig_pb2.flag_state.ENABLED
+_DISABLED = aconfig_pb2.flag_state.DISABLED
+
+# The namespace of the Metalava config file.
+CONFIG_NS = 'http://www.google.com/tools/metalava/config'
+
+
+def config_name(tag: str):
+ """Create a QName in the config namespace.
+
+ :param:tag the name of the entity in the config namespace.
+ """
+ return f'{{{CONFIG_NS}}}{tag}'
+
+
+def main():
+ """Program entry point."""
+ args_parser = argparse.ArgumentParser(
+ description='Generate Metalava flags config from aconfig protobuf',
+ )
+ args_parser.add_argument(
+ 'input',
+ help='The path to the aconfig protobuf file',
+ )
+ args = args_parser.parse_args(sys.argv[1:])
+
+ # Read the parsed_flags from the protobuf file.
+ with open(args.input, 'rb') as f:
+ parsed_flags = aconfig_pb2.parsed_flags.FromString(f.read())
+
+ # Create the structure of the XML config file.
+ config = ET.Element(config_name('config'))
+ api_flags = ET.SubElement(config, config_name('api-flags'))
+ # Create an <api-flag> element for each parsed_flag.
+ for flag in parsed_flags.parsed_flag:
+ if flag.permission == _READ_ONLY:
+ # Ignore any read only disabled flags as Metalava assumes that as the
+ # default when an <api-flags/> element is provided so this reduces the
+ # size of the file.
+ if flag.state == _DISABLED:
+ continue
+ mutability = 'immutable'
+ else:
+ mutability = 'mutable'
+ if flag.state == _ENABLED:
+ status = 'enabled'
+ else:
+ status = 'disabled'
+ attributes = {
+ 'package': flag.package,
+ 'name': flag.name,
+ 'mutability': mutability,
+ 'status': status,
+ }
+ # Convert the attribute names into qualified names in, what will become, the
+ # default namespace for the XML file. This is needed to ensure that the
+ # attribute will be written in the XML file without a prefix, e.g.
+ # `name="flag_name"`. Without it, a namespace prefix, e.g. `ns1`, will be
+ # synthesized for the attribute when writing the XML file, i.e. it
+ # will be written as `ns1:name="flag_name"`. Strictly speaking, that is
+ # unnecessary as the "Namespaces in XML 1.0 (Third Edition)" specification
+ # says that unprefixed attribute names have no namespace.
+ qualified_attributes = {config_name(k): v for (k, v) in attributes.items()}
+ ET.SubElement(api_flags, config_name('api-flag'), qualified_attributes)
+
+ # Create a tree and add white space so it will pretty print when written out.
+ tree = ET.ElementTree(config)
+ ET.indent(tree)
+
+ # Write the tree using the config namespace as the default.
+ tree.write(sys.stdout, encoding='unicode', default_namespace=CONFIG_NS)
+ sys.stdout.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index ef0f44a..b600443 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -23,9 +23,18 @@
# TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the riscv64
# dependencies exist (currently blocked by http://b/273792258).
# TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports riscv64 (http://b/262192655).
+#
+# LTO is disabled because the NDK compiler is not necessarily in-sync with the
+# compiler used to build the platform sysroot, and the sysroot includes static
+# libraries which would be incompatible with mismatched compilers when built
+# with LTO. Disabling LTO globally for the NDK sysroot is okay because the only
+# compiled code in the sysroot that will end up in apps is those static
+# libraries.
+# https://github.com/android/ndk/issues/1591
TARGET_RELEASE=trunk_staging \
ALLOW_MISSING_DEPENDENCIES=true \
BUILD_BROKEN_DISABLE_BAZEL=1 \
+DISABLE_LTO=true \
TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
if [ -n "${DIST_DIR}" ]; then
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index 2f0907c..2c97ae4 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -265,3 +265,7 @@
omnirom\.platform
org\.omnirom\.omnilib
org\.omnirom\.omnilib\..*
+###################################################
+# Packages used for wear-sdk in Wear OS
+com\.google\.wear
+com\.google\.wear\..*
diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py
index 3e4eb48..2167741 100644
--- a/scripts/gen_build_prop.py
+++ b/scripts/gen_build_prop.py
@@ -134,7 +134,7 @@
def generate_common_build_props(args):
print("####################################")
- print("# from generate_common_build_props")
+ print("# from generate-common-build-props")
print("# These properties identify this partition image.")
print("####################################")
@@ -191,7 +191,7 @@
print(f"ro.{partition}.build.version.release={config['Platform_version_last_stable']}")
print(f"ro.{partition}.build.version.release_or_codename={config['Platform_version_name']}")
print(f"ro.{partition}.build.version.sdk={config['Platform_sdk_version']}")
- print(f"ro.{partition}.build.version.sdk_minor={build_flags['RELEASE_PLATFORM_SDK_MINOR_VERSION']}")
+ print(f"ro.{partition}.build.version.sdk_full={config['Platform_sdk_version_full']}")
def generate_build_info(args):
print()
@@ -227,7 +227,7 @@
print(f"ro.build.display.id?={config['BuildDesc']}")
print(f"ro.build.version.incremental={config['BuildNumber']}")
print(f"ro.build.version.sdk={config['Platform_sdk_version']}")
- print(f"ro.build.version.sdk_minor={build_flags['RELEASE_PLATFORM_SDK_MINOR_VERSION']}")
+ print(f"ro.build.version.sdk_full={config['Platform_sdk_version_full']}")
print(f"ro.build.version.preview_sdk={config['Platform_preview_sdk_version']}")
print(f"ro.build.version.preview_sdk_fingerprint={config['PlatformPreviewSdkFingerprint']}")
print(f"ro.build.version.codename={config['Platform_sdk_codename']}")
@@ -277,9 +277,15 @@
print(f"# end build properties")
def write_properties_from_file(file):
+ # Make and Soong use different intermediate files to build vendor/build.prop.
+ # Although the sysprop contents are same, the absolute paths of these
+ # intermediate files are different.
+ # Print the filename for the intermediate files (files in OUT_DIR).
+ # This helps with validating mk->soong migration of android partitions.
+ filename = os.path.basename(file.name) if file.name.startswith(os.environ.get("OUT_DIR")) else file.name
print()
print("####################################")
- print(f"# from {file.name}")
+ print(f"# from {filename}")
print("####################################")
print(file.read(), end="")
@@ -336,7 +342,15 @@
props.append(f"ro.sanitize.{sanitize_target}=true")
# Sets the default value of ro.postinstall.fstab.prefix to /system.
- # Device board config should override the value to /product when needed by:
+ #
+ # Device board configs can override this to /product to use a
+ # product-specific fstab.postinstall file (installed to
+ # /product/etc/fstab.postinstall). If not overridden, the
+ # system/extras/cppreopts/fstab.postinstall file (installed to
+ # /system/etc/fstab.postinstall) will be used.
+ # Note: The default fstab.postinstall is generic and may be slower
+ # because it tries different mount options line by line to ensure
+ # compatibility across various devices.
#
# PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product
#
@@ -389,9 +403,6 @@
props = list(filter(lambda x: not x.startswith("ro.setupwizard.mode="), props))
props.append("ro.setupwizard.mode=OPTIONAL")
- if not config["SdkBuild"]:
- # To speedup startup of non-preopted builds, don't verify or compile the boot image.
- props.append("dalvik.vm.image-dex2oat-filter=extract")
# b/323566535
props.append("init.svc_debug.no_fatal.zygote=true")
@@ -484,7 +495,7 @@
props.append(f"ro.vendor.build.security_patch={config['VendorSecurityPatch']}")
props.append(f"ro.product.board={config['BootloaderBoardName']}")
props.append(f"ro.board.platform={config['BoardPlatform']}")
- props.append(f"ro.hwui.use_vulkan={'true' if config['UsesVulkan'] else 'false'}")
+ props.append(f"ro.hwui.use_vulkan={config['UsesVulkan']}")
if config["ScreenDensity"]:
props.append(f"ro.sf.lcd_density={config['ScreenDensity']}")
diff --git a/scripts/keep-flagged-apis.sh b/scripts/keep-flagged-apis.sh
deleted file mode 100755
index 48efb7a..0000000
--- a/scripts/keep-flagged-apis.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash -e
-#
-# 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.
-
-# Convert a list of flags in the input file to a list of metalava options
-# that will keep the APIs for those flags will hiding all other flagged
-# APIs.
-
-FLAGS="$1"
-
-FLAGGED="android.annotation.FlaggedApi"
-
-# Convert the list of feature flags in the input file to Metalava options
-# of the form `--revert-annotation !android.annotation.FlaggedApi("<flag>")`
-# to prevent the annotated APIs from being hidden, i.e. include the annotated
-# APIs in the SDK snapshots.
-while read -r line; do
- # Escape and quote the key for sed
- escaped_line=$(echo "$line" | sed "s/'/\\\'/g; s/ /\\ /g")
-
- echo "--revert-annotation '!$FLAGGED(\"$escaped_line\")'"
-done < "$FLAGS"
-
-# Revert all flagged APIs, unless listed above.
-echo "--revert-annotation $FLAGGED"
diff --git a/scripts/list_image.sh b/scripts/list_image.sh
deleted file mode 100755
index 0542fa6..0000000
--- a/scripts/list_image.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#! /bin/bash
-
-# Recursively list Android image directory.
-set -eu
-set -o pipefail
-
-function die() { format=$1; shift; printf "$format\n" "$@"; exit 1; }
-
-# Figure out the filer utility.
-declare filer=
-[[ -z "${ANDROID_HOST_OUT:-}" ]] || filer=${ANDROID_HOST_OUT}/bin/debugfs_static
-if [[ "${1:-}" =~ --debugfs_path=(.*) ]]; then
- filer=${BASH_REMATCH[1]}
- shift
-fi
-if [[ -z "${filer:-}" ]]; then
- maybefiler="$(dirname $0)/debugfs_static"
- [[ ! -x "$maybefiler" ]] || filer="$maybefiler"
-fi
-
-(( $# >0 )) || die "%s [--debugfs_path=<path>] IMAGE" "$0"
-
-[[ -n "${filer:-}" ]] || die "cannot locate 'debugfs' executable: \
---debugfs_path= is missing, ANDROID_HOST_OUT is not set, \
-and 'debugfs_static' is not colocated with this script"
-declare -r image="$1"
-
-function dolevel() {
- printf "%s/\n" "$1"
- # Each line of the file output consists of 6 fields separated with '/'.
- # The second one contains the file's attributes, and the fifth its name.
- $filer -R "ls -l -p $1" "$image" 2>/dev/null |\
- sed -nr 's|^/.*/(.*)/.*/.*/(.+)/.*/$|\2 \1|p' | LANG=C sort | \
- while read name attr; do
- [[ "$name" != '.' && "$name" != '..' ]] || continue
- path="$1/$name"
- # If the second char of the attributes is '4', it is a directory.
- if [[ $attr =~ ^.4 ]]; then
- dolevel "$path"
- else
- printf "%s\n" "$path"
- fi
- done
-}
-
-# The filer always prints its version on stderr, so we are going
-# to redirect it to the bit bucket. On the other hand, the filer's
-# return code on error is still 0. Let's run it once to without
-# redirecting stderr to see that there is at least one entry.
-$filer -R "ls -l -p" "$image" | grep -q -m1 -P '^/.*/.*/.*/.*/.+/.*/$'
-dolevel .
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 175451e..96dc5a6 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -132,7 +132,7 @@
#pylint: disable=line-too-long
errmsg = ''.join([
- 'mismatch in the <uses-library> tags between the build system and the '
+ 'mismatch or misordering in the <uses-library> tags between the build system and the '
'manifest:\n',
'\t- required libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(required), C_OFF),
'\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_required), C_OFF),
diff --git a/scripts/merge_directories.py b/scripts/merge_directories.py
deleted file mode 100755
index 3f8631b..0000000
--- a/scripts/merge_directories.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/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/microfactory.bash b/scripts/microfactory.bash
index ce4a0e4..49988fa 100644
--- a/scripts/microfactory.bash
+++ b/scripts/microfactory.bash
@@ -23,7 +23,14 @@
# Ensure GOROOT is set to the in-tree version.
case $(uname) in
Linux)
- export GOROOT="${TOP}/prebuilts/go/linux-x86/"
+ case $(uname -m) in
+ x86_64)
+ export GOROOT="${TOP}/prebuilts/go/linux-x86/"
+ ;;
+ aarch64)
+ export GOROOT="${TOP}/prebuilts/go/linux-arm64/"
+ ;;
+ esac
;;
Darwin)
export GOROOT="${TOP}/prebuilts/go/darwin-x86/"
diff --git a/scripts/run-soong-tests-with-go-tools.sh b/scripts/run-soong-tests-with-go-tools.sh
index 1fbb1fc..82efaa0 100755
--- a/scripts/run-soong-tests-with-go-tools.sh
+++ b/scripts/run-soong-tests-with-go-tools.sh
@@ -38,6 +38,11 @@
CLANG_VERSION=$(build/soong/scripts/get_clang_version.py)
export CC="${TOP}/prebuilts/clang/host/${OS}-x86/${CLANG_VERSION}/bin/clang"
export CXX="${TOP}/prebuilts/clang/host/${OS}-x86/${CLANG_VERSION}/bin/clang++"
+ glibc_dir="${TOP}/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8"
+ export CGO_CFLAGS="--sysroot ${glibc_dir}/sysroot/"
+ export CGO_CPPFLAGS="--sysroot ${glibc_dir}/sysroot/"
+ export CGO_CXXFLAGS="--sysroot ${glibc_dir}/sysroot/"
+ export CGO_LDFLAGS="--sysroot ${glibc_dir}/sysroot/ -B ${glibc_dir}/lib/gcc/x86_64-linux/4.8.3 -L ${glibc_dir}/lib/gcc/x86_64-linux/4.8.3 -L ${glibc_dir}/x86_64-linux/lib64"
fi
# androidmk_test.go gets confused if ANDROID_BUILD_TOP is set.
diff --git a/scripts/rustc_linker.py b/scripts/rustc_linker.py
new file mode 100755
index 0000000..3f60708
--- /dev/null
+++ b/scripts/rustc_linker.py
@@ -0,0 +1,57 @@
+#!/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.
+#
+
+"""
+This script is used as a replacement for the Rust linker to allow fine-grained
+control over the what gets emitted to the linker.
+"""
+
+import os
+import shutil
+import subprocess
+import sys
+import argparse
+
+replacementVersionScript = None
+
+argparser = argparse.ArgumentParser()
+argparser.add_argument('--android-clang-bin', required=True)
+args = argparser.parse_known_args()
+clang_args = [args[0].android_clang_bin] + args[1]
+
+for i, arg in enumerate(clang_args):
+ if arg.startswith('-Wl,--android-version-script='):
+ replacementVersionScript = arg.split("=")[1]
+ del clang_args[i]
+ break
+
+if replacementVersionScript:
+ versionScriptFound = False
+ for i, arg in enumerate(clang_args):
+ if arg.startswith('-Wl,--version-script='):
+ clang_args[i] ='-Wl,--version-script=' + replacementVersionScript
+ versionScriptFound = True
+ break
+
+ if not versionScriptFound:
+ # If rustc did not emit a version script, just append the arg
+ clang_args.append('-Wl,--version-script=' + replacementVersionScript)
+try:
+ subprocess.run(clang_args, encoding='utf-8', check=True)
+except subprocess.CalledProcessError as e:
+ sys.exit(-1)
+
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 8d69f0d..5320ef6 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -101,7 +101,12 @@
do_strip_keep_mini_debug_info_linux() {
rm -f "${outfile}.mini_debuginfo.xz"
local fail=
- "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
+ if [ -z "${windows}" ]; then
+ "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
+ else
+ # --keep-section not supported for Windows COFF.
+ fail=true
+ fi
if [ -z $fail ]; then
# create_minidebuginfo has issues with compressed debug sections. Just
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 34e11f0..80ced00 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -66,6 +66,7 @@
exported_bootclasspath_fragments: [
"%s",
],
+ prefer: false,
}
`, apex, apexFile, fragment)),
android.FixtureAddFile(filepath.Join(dir, apexFile), nil),
@@ -73,6 +74,7 @@
}
func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithDexpreopt,
@@ -225,8 +227,8 @@
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
- "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_prebuilt_com.android.art/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_prebuilt_com.android.art/deapexer/javalib/core2.jar",
"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,
@@ -270,7 +272,7 @@
// package check rule.
func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModules ...string) {
t.Helper()
- platformBcp := result.ModuleForTests("platform-bootclasspath", "android_common")
+ platformBcp := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
command := bootJarsCheckRule.RuleParams.Command
expectedCommandArgs := " build/soong/scripts/check_boot_jars/package_allowed_list.txt " + strings.Join(expectedModules, " ") + " &&"
@@ -479,7 +481,7 @@
checkAllCopyRules(copyRules),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
- module := result.ModuleForTests("platform-bootclasspath", "android_common")
+ module := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
var rule android.TestingBuildParams
rule = module.Output("out/soong/hiddenapi/hiddenapi-flags.csv")
java.CheckHiddenAPIRuleInputs(t, "monolithic flags", `
@@ -505,7 +507,7 @@
}),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) {
- module := result.ModuleForTests("platform-bootclasspath", "android_common")
+ module := result.ModuleForTests(t, "platform-bootclasspath", "android_common")
rule := module.Output("out/soong/hiddenapi/hiddenapi-flags.csv.valid")
android.AssertStringDoesContain(t, "verify-overlaps", rule.RuleParams.Command, " out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv ")
}),
@@ -514,7 +516,9 @@
}
func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) {
+ t.Parallel()
t.Run("added-directly", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithBootClasspathFragment_Contents(t, `
sdk {
name: "mysdk",
@@ -566,6 +570,7 @@
.intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
`
t.Run("added-via-apex", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithBootClasspathFragment_Contents(t, `
sdk {
name: "mysdk",
@@ -575,6 +580,7 @@
})
t.Run("added-directly-and-indirectly", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithBootClasspathFragment_Contents(t, `
sdk {
name: "mysdk",
@@ -599,6 +605,7 @@
// TestSnapshotWithBootClasspathFragment_Fragments makes sure that the fragments property of a
// bootclasspath_fragment is correctly output to the sdk snapshot.
func TestSnapshotWithBootClasspathFragment_Fragments(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
@@ -734,9 +741,11 @@
// Test that bootclasspath_fragment works with sdk.
func TestBasicSdkWithBootclasspathFragment(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForSdkTestWithApex,
prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
android.FixtureMergeMockFs(android.MockFS{
"java/mybootlib.jar": nil,
"hiddenapi/annotation-flags.csv": nil,
@@ -752,6 +761,13 @@
bootclasspath_fragments: ["mybootclasspathfragment"],
}
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "1",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+
bootclasspath_fragment {
name: "mybootclasspathfragment",
image_name: "art",
@@ -794,7 +810,7 @@
java_import {
name: "mybootlib",
visibility: ["//visibility:public"],
- apex_available: ["com.android.art"],
+ apex_available: ["myapex"],
jars: ["java/mybootlib.jar"],
}
`),
@@ -802,6 +818,7 @@
}
func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
@@ -1116,7 +1133,7 @@
`),
).RunTest(t)
- bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common")
+ bcpf := result.ModuleForTests(t, "mybootclasspathfragment", "android_common")
rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv")
android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", android.SortedUniqueStrings(expectedStubFlagsInputs), android.SortedUniquePaths(rule.Implicits))
@@ -1127,7 +1144,9 @@
}
func TestSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T) {
+ t.Parallel()
t.Run("target S build", func(t *testing.T) {
+ t.Parallel()
expectedSnapshot := `
// This is auto-generated. DO NOT EDIT.
@@ -1184,6 +1203,7 @@
})
t.Run("target-Tiramisu-build", func(t *testing.T) {
+ t.Parallel()
expectedSnapshot := `
// This is auto-generated. DO NOT EDIT.
@@ -1268,6 +1288,7 @@
}
func TestSnapshotWithEmptyBootClasspathFragment(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index c620ac2..d3eaafe 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -73,6 +73,7 @@
}
func TestAddPropertySimple(t *testing.T) {
+ t.Parallel()
set := newPropertySet()
for name, val := range map[string]interface{}{
"x": "taxi",
@@ -91,14 +92,17 @@
}
func TestAddPropertySubset(t *testing.T) {
+ t.Parallel()
getFixtureMap := map[string]func() interface{}{
"property set": propertySetFixture,
"property struct": propertyStructFixture,
}
t.Run("add new subset", func(t *testing.T) {
+ t.Parallel()
for name, getFixture := range getFixtureMap {
t.Run(name, func(t *testing.T) {
+ t.Parallel()
set := propertySetFixture().(*bpPropertySet)
set.AddProperty("new", getFixture())
checkPropertySetFixture(t, set, true)
@@ -108,8 +112,10 @@
})
t.Run("merge existing subset", func(t *testing.T) {
+ t.Parallel()
for name, getFixture := range getFixtureMap {
t.Run(name, func(t *testing.T) {
+ t.Parallel()
set := newPropertySet()
subset := set.AddPropertySet("sub")
subset.AddProperty("flag", false)
@@ -123,12 +129,14 @@
})
t.Run("add conflicting subset", func(t *testing.T) {
+ t.Parallel()
set := propertySetFixture().(*bpPropertySet)
android.AssertPanicMessageContains(t, "adding x again should panic", `Property "x" already exists in property set`,
func() { set.AddProperty("x", propertySetFixture()) })
})
t.Run("add non-pointer struct", func(t *testing.T) {
+ t.Parallel()
set := propertySetFixture().(*bpPropertySet)
str := propertyStructFixture().(*propertyStruct)
android.AssertPanicMessageContains(t, "adding a non-pointer struct should panic", "Value is a struct, not a pointer to one:",
@@ -137,6 +145,7 @@
}
func TestAddPropertySetNew(t *testing.T) {
+ t.Parallel()
set := newPropertySet()
subset := set.AddPropertySet("sub")
subset.AddProperty("new", "d^^b")
@@ -144,6 +153,7 @@
}
func TestAddPropertySetExisting(t *testing.T) {
+ t.Parallel()
set := propertySetFixture().(*bpPropertySet)
subset := set.AddPropertySet("sub")
subset.AddProperty("new", "d^^b")
@@ -176,6 +186,7 @@
}
func TestTransformRemoveProperty(t *testing.T) {
+ t.Parallel()
set := newPropertySet()
set.AddProperty("name", "name")
set.AddProperty("fred", "12")
@@ -188,6 +199,7 @@
}
func TestTransformRemovePropertySet(t *testing.T) {
+ t.Parallel()
set := newPropertySet()
set.AddProperty("name", "name")
set.AddPropertySet("fred")
diff --git a/sdk/build_release.go b/sdk/build_release.go
index 6bb05a3..3656c98 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -101,6 +101,8 @@
buildReleaseS = initBuildRelease("S")
buildReleaseT = initBuildRelease("Tiramisu")
buildReleaseU = initBuildRelease("UpsideDownCake")
+ buildReleaseV = initBuildRelease("VanillaIceCream")
+ buildReleaseB = initBuildRelease("Baklava")
// Add the current build release which is always treated as being more recent than any other
// build release, including those added in tests.
diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go
index 5bf57b5..07f99ee 100644
--- a/sdk/build_release_test.go
+++ b/sdk/build_release_test.go
@@ -42,7 +42,7 @@
android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release)
// Uses a wildcard in the error message to allow for additional build releases to be added to
// the supported set without breaking this test.
- android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,UpsideDownCake,F1,F2,current\]`, []error{err})
+ android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,UpsideDownCake,VanillaIceCream,Baklava,F1,F2,current\]`, []error{err})
})
}
@@ -60,7 +60,7 @@
t.Run("closed range", func(t *testing.T) {
set, err := parseBuildReleaseSet("S-F1")
android.AssertDeepEquals(t, "errors", nil, err)
- android.AssertStringEquals(t, "set", "[S,Tiramisu,UpsideDownCake,F1]", set.String())
+ android.AssertStringEquals(t, "set", "[S,Tiramisu,UpsideDownCake,VanillaIceCream,Baklava,F1]", set.String())
})
invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String()
t.Run("invalid release", func(t *testing.T) {
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 25839b8..bf4ac13 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -58,6 +58,7 @@
// Contains tests for SDK members provided by the cc package.
func TestSingleDeviceOsAssumption(t *testing.T) {
+ t.Parallel()
// Mock a module with DeviceSupported() == true.
s := &sdk{}
android.InitAndroidArchModule(s, android.DeviceSupported, android.MultilibCommon)
@@ -72,6 +73,7 @@
}
func TestSdkIsCompileMultilibBoth(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -102,6 +104,7 @@
}
func TestSdkCompileMultilibOverride(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -161,6 +164,7 @@
// Make sure the sdk can use host specific cc libraries static/shared and both.
func TestHostSdkWithCc(t *testing.T) {
+ t.Parallel()
testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -184,6 +188,7 @@
// Make sure the sdk can use cc libraries static/shared and both.
func TestSdkWithCc(t *testing.T) {
+ t.Parallel()
testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -214,6 +219,7 @@
}
func TestSnapshotWithObject(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -268,6 +274,7 @@
}
func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -305,6 +312,7 @@
}
func TestSnapshotWithCcExportGeneratedHeaders(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -393,6 +401,7 @@
// handling is tested with the sanitize clauses (but note there's a lot of
// built-in logic in sanitize.go that can affect those flags).
func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -475,6 +484,7 @@
}
func TestSnapshotWithCcBinary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "mymodule_exports",
@@ -523,6 +533,7 @@
}
func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
@@ -604,6 +615,7 @@
}
func TestSnapshotWithSingleHostOsType(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTest,
ccTestFs.AddToFixture(),
@@ -721,6 +733,7 @@
// Test that we support the necessary flags for the linker binary, which is
// special in several ways.
func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "mymodule_exports",
@@ -785,19 +798,26 @@
}
func TestSnapshotWithCcSharedLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
native_shared_libs: ["mynativelib"],
}
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "1",
+ }
+
cc_library_shared {
name: "mynativelib",
srcs: [
"Test.cpp",
"aidl/foo/bar/Test.aidl",
],
- apex_available: ["apex1", "apex2"],
+ apex_available: ["myapex"],
export_include_dirs: ["myinclude"],
aidl: {
export_aidl_headers: true,
@@ -807,6 +827,18 @@
`)
CheckSnapshot(t, result, "mysdk", "",
+ snapshotTestPreparer(checkSnapshotWithoutSource,
+ android.FixtureMergeMockFs(android.MockFS{
+ "myapex/Android.bp": []byte(`
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "1",
+ }
+ `),
+ "myapex/apex_manifest.json": nil,
+ }),
+ ),
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -819,10 +851,7 @@
name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
- apex_available: [
- "apex1",
- "apex2",
- ],
+ apex_available: ["myapex"],
stl: "none",
compile_multilib: "both",
export_include_dirs: ["include/myinclude"],
@@ -856,6 +885,7 @@
}
func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -1005,6 +1035,7 @@
}
func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -1085,6 +1116,7 @@
}
func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -1168,6 +1200,7 @@
}
func TestSnapshotWithCcStaticLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
@@ -1232,6 +1265,7 @@
}
func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
@@ -1307,6 +1341,7 @@
}
func TestSnapshotWithCcLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
@@ -1370,12 +1405,11 @@
.intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
`),
- // TODO(b/183315522): Remove this and fix the issue.
- snapshotTestErrorHandler(checkSnapshotPreferredWithSource, android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\Qunrecognized property "arch.arm.shared.export_include_dirs"\E`)),
)
}
func TestSnapshotSameLibraryWithNativeLibsAndNativeSharedLib(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
host_supported: true,
@@ -1477,6 +1511,7 @@
}
func TestSnapshotSameLibraryWithAndroidNativeLibsAndHostNativeSharedLib(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
host_supported: true,
@@ -1578,6 +1613,7 @@
}
func TestSnapshotSameLibraryWithNativeStaticLibsAndNativeSharedLib(t *testing.T) {
+ t.Parallel()
testSdkError(t, "Incompatible member types", `
module_exports {
host_supported: true,
@@ -1609,6 +1645,7 @@
}
func TestHostSnapshotWithMultiLib64(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
@@ -1682,6 +1719,7 @@
}
func TestSnapshotWithCcHeadersLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -1721,6 +1759,7 @@
}
func TestSnapshotWithCcHeadersLibraryAndNativeBridgeSupport(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules,
PrepareForTestWithSdkBuildComponents,
@@ -1778,6 +1817,7 @@
// module that has different output files for a native bridge target requests the native bridge
// variants are copied into the sdk snapshot that it reports an error.
func TestSnapshotWithCcHeadersLibrary_DetectsNativeBridgeSpecificProperties(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules,
PrepareForTestWithSdkBuildComponents,
@@ -1814,6 +1854,7 @@
}
func TestSnapshotWithCcHeadersLibraryAndImageVariants(t *testing.T) {
+ t.Parallel()
testImageVariant := func(t *testing.T, property, trait string) {
result := android.GroupFixturePreparers(
cc.PrepareForTestWithCcDefaultModules,
@@ -1877,6 +1918,7 @@
}
func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -1933,6 +1975,7 @@
}
func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -2002,6 +2045,7 @@
}
func TestSystemSharedLibPropagation(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -2162,6 +2206,7 @@
}
func TestStubsLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -2223,6 +2268,7 @@
}
func TestDeviceAndHostSnapshotWithStubsLibrary(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -2299,6 +2345,7 @@
}
func TestUniqueHostSoname(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
@@ -2364,6 +2411,7 @@
}
func TestNoSanitizerMembers(t *testing.T) {
+ t.Parallel()
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
diff --git a/sdk/compat_config_sdk_test.go b/sdk/compat_config_sdk_test.go
index 75b5229..1737b3a 100644
--- a/sdk/compat_config_sdk_test.go
+++ b/sdk/compat_config_sdk_test.go
@@ -76,6 +76,7 @@
}
func TestSnapshotWithCompatConfig(t *testing.T) {
+ t.Parallel()
testSnapshotWithCompatConfig(t, `
sdk {
name: "mysdk",
@@ -85,6 +86,7 @@
}
func TestSnapshotWithCompatConfig_Apex(t *testing.T) {
+ t.Parallel()
testSnapshotWithCompatConfig(t, `
apex {
name: "myapex",
diff --git a/sdk/exports_test.go b/sdk/exports_test.go
index 9d0a242..5a7ce84 100644
--- a/sdk/exports_test.go
+++ b/sdk/exports_test.go
@@ -20,6 +20,7 @@
// Ensure that module_exports generates a module_exports_snapshot module.
func TestModuleExportsSnapshot(t *testing.T) {
+ t.Parallel()
packageBp := `
module_exports {
name: "myexports",
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 4db163c..1e545ce 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -51,6 +51,7 @@
// Contains tests for SDK members provided by the java package.
func TestSdkDependsOnSourceEvenWhenPrebuiltPreferred(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -77,6 +78,7 @@
}
func TestSnapshotWithJavaHeaderLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -126,6 +128,7 @@
}
func TestHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -178,6 +181,7 @@
}
func TestDeviceAndHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -228,6 +232,7 @@
}
func TestSnapshotWithJavaImplLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -277,6 +282,7 @@
}
func TestSnapshotWithJavaBootLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl", nil),
@@ -328,6 +334,7 @@
}
func TestSnapshotWithJavaBootLibrary_UpdatableMedia(t *testing.T) {
+ t.Parallel()
runTest := func(t *testing.T, targetBuildRelease, expectedJarPath, expectedCopyRule string) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
@@ -385,6 +392,7 @@
}
func TestSnapshotWithJavaLibrary_MinSdkVersion(t *testing.T) {
+ t.Parallel()
runTest := func(t *testing.T, targetBuildRelease, minSdkVersion, expectedMinSdkVersion string) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
@@ -457,6 +465,7 @@
}
func TestSnapshotWithJavaSystemserverLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl", nil),
@@ -509,6 +518,7 @@
}
func TestHostSnapshotWithJavaImplLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
@@ -561,6 +571,7 @@
}
func TestSnapshotWithJavaTest(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
module_exports {
name: "myexports",
@@ -603,6 +614,7 @@
}
func TestHostSnapshotWithJavaTest(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
module_exports {
name: "myexports",
@@ -650,6 +662,7 @@
}
func TestSnapshotWithJavaSystemModules(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
@@ -853,6 +866,7 @@
}
func TestHostSnapshotWithJavaSystemModules(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -911,6 +925,7 @@
}
func TestDeviceAndHostSnapshotWithOsSpecificMembers(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
module_exports {
name: "myexports",
@@ -1004,6 +1019,7 @@
}
func TestSnapshotWithJavaSdkLibrary(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1081,6 +1097,7 @@
}
func TestSnapshotWithJavaSdkLibrary_DistStem(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1136,6 +1153,7 @@
}
func TestSnapshotWithJavaSdkLibrary_UseSrcJar(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
android.FixtureMergeEnv(map[string]string{
@@ -1192,6 +1210,7 @@
}
func TestSnapshotWithJavaSdkLibrary_AnnotationsZip(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1246,6 +1265,7 @@
}
func TestSnapshotWithJavaSdkLibrary_AnnotationsZip_PreT(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
android.FixtureMergeEnv(map[string]string{
@@ -1303,6 +1323,7 @@
}
func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
@@ -1385,6 +1406,7 @@
}
func TestSnapshotWithJavaSdkLibrary_SdkVersion_None(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1435,6 +1457,7 @@
}
func TestSnapshotWithJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1488,6 +1511,7 @@
}
func TestSnapshotWithJavaSdkLibrary_ApiScopes(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1555,6 +1579,7 @@
}
func TestSnapshotWithJavaSdkLibrary_ModuleLib(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1636,6 +1661,7 @@
}
func TestSnapshotWithJavaSdkLibrary_SystemServer(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1703,6 +1729,7 @@
}
func TestSnapshotWithJavaSdkLibrary_DoctagFiles(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
android.FixtureAddFile("docs/known_doctags", nil),
diff --git a/sdk/license_sdk_test.go b/sdk/license_sdk_test.go
index 754f019..eb8112b 100644
--- a/sdk/license_sdk_test.go
+++ b/sdk/license_sdk_test.go
@@ -21,6 +21,7 @@
)
func TestSnapshotWithPackageDefaultLicense(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.PrepareForTestWithLicenses,
diff --git a/sdk/member_trait_test.go b/sdk/member_trait_test.go
index 673d6fb..9b41e9b 100644
--- a/sdk/member_trait_test.go
+++ b/sdk/member_trait_test.go
@@ -116,6 +116,7 @@
}
func TestBasicTrait_WithoutTrait(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureWithRootAndroidBp(`
@@ -154,6 +155,7 @@
}
func TestBasicTrait_MultipleTraits(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureWithRootAndroidBp(`
@@ -262,6 +264,7 @@
}
func TestTraitUnsupportedByMemberType(t *testing.T) {
+ t.Parallel()
android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureWithRootAndroidBp(`
diff --git a/sdk/sdk.go b/sdk/sdk.go
index aa82abb..ab50659 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -178,22 +178,24 @@
s.buildSnapshot(ctx, sdkVariants)
}
+ if s.snapshotFile.Valid() != s.infoFile.Valid() {
+ panic(fmt.Sprintf("Snapshot (%q) and info file (%q) should both be set or neither should be set.", s.snapshotFile, s.infoFile))
+ }
+
if s.snapshotFile.Valid() {
ctx.SetOutputFiles([]android.Path{s.snapshotFile.Path()}, "")
+ ctx.SetOutputFiles([]android.Path{s.snapshotFile.Path(), s.infoFile.Path()}, android.DefaultDistTag)
}
}
func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries {
- if !s.snapshotFile.Valid() != !s.infoFile.Valid() {
- panic("Snapshot (%q) and info file (%q) should both be set or neither should be set.")
- } else if !s.snapshotFile.Valid() {
+ if !s.snapshotFile.Valid() {
return []android.AndroidMkEntries{}
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "FAKE",
OutputFile: s.snapshotFile,
- DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path(), s.infoFile.Path()),
Include: "$(BUILD_PHONY_PACKAGE)",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 2532a25..985641e 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -40,6 +40,7 @@
// Ensure that prebuilt modules have the same effective visibility as the source
// modules.
func TestSnapshotVisibility(t *testing.T) {
+ t.Parallel()
packageBp := `
package {
default_visibility: ["//other/foo"],
@@ -160,6 +161,7 @@
}
func TestSdkInstall(t *testing.T) {
+ t.Parallel()
sdk := `
sdk {
name: "mysdk",
@@ -326,6 +328,7 @@
// Ensure that sdk snapshot related environment variables work correctly.
func TestSnapshot_EnvConfiguration(t *testing.T) {
+ t.Parallel()
bp := `
sdk {
name: "mysdk",
@@ -347,11 +350,12 @@
)
checkZipFile := func(t *testing.T, result *android.TestResult, expected string) {
- zipRule := result.ModuleForTests("mysdk", "common_os").Rule("SnapshotZipFiles")
+ zipRule := result.ModuleForTests(t, "mysdk", "common_os").Rule("SnapshotZipFiles")
android.AssertStringEquals(t, "snapshot zip file", expected, zipRule.Output.String())
}
t.Run("no env variables", func(t *testing.T) {
+ t.Parallel()
result := preparer.RunTest(t)
checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
@@ -377,6 +381,7 @@
})
t.Run("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
@@ -468,6 +473,7 @@
})
t.Run("test replacing exportable module", func(t *testing.T) {
+ t.Parallel()
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index fd6c4e7..7ebdcd4 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -87,10 +87,23 @@
CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(expectedSdkSnapshot),
+ snapshotTestPreparer(checkSnapshotWithoutSource,
+ android.FixtureMergeMockFs(android.MockFS{
+ "myapex/Android.bp": []byte(`
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "1",
+ }
+ `),
+ "myapex/apex_manifest.json": nil,
+ }),
+ ),
)
}
func TestSnapshotWithPartialSystemServerClasspathFragment(t *testing.T) {
+ t.Parallel()
commonSdk := `
apex {
name: "myapex",
@@ -185,6 +198,7 @@
}
func TestSnapshotWithEmptySystemServerClasspathFragment(t *testing.T) {
+ t.Parallel()
commonSdk := `
apex {
name: "myapex",
@@ -231,6 +245,7 @@
}
func TestSnapshotWithSystemServerClasspathFragment(t *testing.T) {
+ t.Parallel()
commonSdk := `
sdk {
@@ -298,6 +313,7 @@
`
t.Run("target-s", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "S", `
// This is auto-generated. DO NOT EDIT.
@@ -319,6 +335,7 @@
})
t.Run("target-t", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "Tiramisu", `
// This is auto-generated. DO NOT EDIT.
@@ -361,6 +378,7 @@
})
t.Run("target-u", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "UpsideDownCake", `
// This is auto-generated. DO NOT EDIT.
@@ -409,10 +427,12 @@
})
t.Run("added-directly", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithSystemServerClasspathFragment(t, commonSdk, `latest`, expectedLatestSnapshot)
})
t.Run("added-via-apex", func(t *testing.T) {
+ t.Parallel()
testSnapshotWithSystemServerClasspathFragment(t, `
sdk {
name: "mysdk",
diff --git a/sdk/testing.go b/sdk/testing.go
index f4e2b03..cd7bbf5 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -128,12 +128,11 @@
// generated, etc.
func getSdkSnapshotBuildInfo(t *testing.T, result *android.TestResult, sdk *sdk) *snapshotBuildInfo {
info := &snapshotBuildInfo{
- t: t,
- r: result,
- androidBpContents: sdk.GetAndroidBpContentsForTests(),
- infoContents: sdk.GetInfoContentsForTests(),
- snapshotTestCustomizations: map[snapshotTest]*snapshotTestCustomization{},
- targetBuildRelease: sdk.builderForTests.targetBuildRelease,
+ t: t,
+ r: result,
+ androidBpContents: sdk.GetAndroidBpContentsForTests(),
+ infoContents: sdk.GetInfoContentsForTests(),
+ targetBuildRelease: sdk.builderForTests.targetBuildRelease,
}
buildParams := sdk.BuildParamsForTests()
@@ -144,7 +143,7 @@
seenBuildNumberFile := false
for _, bp := range buildParams {
switch bp.Rule.String() {
- case android.Cp.String():
+ case android.Cp.String(), android.CpWithBash.String():
output := bp.Output
// Get destination relative to the snapshot root
dest := output.Rel()
@@ -282,7 +281,7 @@
// Run the snapshot with the snapshot preparer and the extra preparer, which must come after as
// it may need to modify parts of the MockFS populated by the snapshot preparer.
- result := android.GroupFixturePreparers(snapshotPreparer, extraPreparer, customizedPreparers).
+ result := android.GroupFixturePreparers(snapshotPreparer, customizedPreparers, extraPreparer).
ExtendWithErrorHandler(customization.errorHandler).
RunTest(t)
@@ -293,6 +292,7 @@
}
t.Run("snapshot without source", func(t *testing.T) {
+ t.Parallel()
// Remove the source Android.bp file to make sure it works without.
removeSourceAndroidBp := android.FixtureModifyMockFS(func(fs android.MockFS) {
delete(fs, "Android.bp")
@@ -302,16 +302,23 @@
})
t.Run("snapshot with source preferred", func(t *testing.T) {
+ t.Parallel()
runSnapshotTestWithCheckers(t, checkSnapshotWithSourcePreferred, android.NullFixturePreparer)
})
t.Run("snapshot preferred with source", func(t *testing.T) {
+ t.Parallel()
// Replace the snapshot/Android.bp file with one where "prefer: false," has been replaced with
// "prefer: true,"
preferPrebuilts := android.FixtureModifyMockFS(func(fs android.MockFS) {
snapshotBpFile := filepath.Join(snapshotSubDir, "Android.bp")
unpreferred := string(fs[snapshotBpFile])
fs[snapshotBpFile] = []byte(strings.ReplaceAll(unpreferred, "prefer: false,", "prefer: true,"))
+
+ prebuiltApexBpFile := "prebuilts/apex/Android.bp"
+ if prebuiltApexBp, ok := fs[prebuiltApexBpFile]; ok {
+ fs[prebuiltApexBpFile] = []byte(strings.ReplaceAll(string(prebuiltApexBp), "prefer: false,", "prefer: true,"))
+ }
})
runSnapshotTestWithCheckers(t, checkSnapshotPreferredWithSource, preferPrebuilts)
@@ -469,19 +476,40 @@
targetBuildRelease *buildRelease
// The test specific customizations for each snapshot test.
- snapshotTestCustomizations map[snapshotTest]*snapshotTestCustomization
+ snapshotTestCustomizations snapshotTestCustomizationSet
+}
+
+type snapshotTestCustomizationSet struct {
+ snapshotWithoutSource *snapshotTestCustomization
+ snapshotWithSourcePreferred *snapshotTestCustomization
+ snapshotPreferredWithSource *snapshotTestCustomization
+}
+
+func (s *snapshotTestCustomizationSet) customization(snapshotTest snapshotTest) **snapshotTestCustomization {
+ var customization **snapshotTestCustomization
+ switch snapshotTest {
+ case checkSnapshotWithoutSource:
+
+ customization = &s.snapshotWithoutSource
+ case checkSnapshotWithSourcePreferred:
+ customization = &s.snapshotWithSourcePreferred
+ case checkSnapshotPreferredWithSource:
+ customization = &s.snapshotPreferredWithSource
+ default:
+ panic(fmt.Errorf("unsupported snapshotTest %v", snapshotTest))
+ }
+ return customization
}
// snapshotTestCustomization gets the test specific customization for the specified snapshotTest.
//
// If no customization was created previously then it creates a default customization.
func (i *snapshotBuildInfo) snapshotTestCustomization(snapshotTest snapshotTest) *snapshotTestCustomization {
- customization := i.snapshotTestCustomizations[snapshotTest]
- if customization == nil {
- customization = &snapshotTestCustomization{
+ customization := i.snapshotTestCustomizations.customization(snapshotTest)
+ if *customization == nil {
+ *customization = &snapshotTestCustomization{
errorHandler: android.FixtureExpectsNoErrors,
}
- i.snapshotTestCustomizations[snapshotTest] = customization
}
- return customization
+ return *customization
}
diff --git a/sdk/update.go b/sdk/update.go
index 5a899a2..00352cb 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -1145,7 +1145,7 @@
// The licenses are the same for all variants.
mctx := s.ctx
- licenseInfo, _ := android.OtherModuleProvider(mctx, variant, android.LicenseInfoProvider)
+ licenseInfo, _ := android.OtherModuleProvider(mctx, variant, android.LicensesInfoProvider)
if len(licenseInfo.Licenses) > 0 {
m.AddPropertyWithTag("licenses", licenseInfo.Licenses, s.OptionalSdkMemberReferencePropertyTag())
}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 7f5a426..57f5ad1 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -41,6 +41,14 @@
registerShBuildComponents(android.InitRegistrationContext)
}
+type ShBinaryInfo struct {
+ SubDir string
+ OutputFile android.Path
+ Symlinks []string
+}
+
+var ShBinaryInfoProvider = blueprint.NewProvider[ShBinaryInfo]()
+
func registerShBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("sh_binary", ShBinaryFactory)
ctx.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
@@ -130,6 +138,11 @@
// host test.
Device_first_data []string `android:"path_device_first"`
+ // Same as data, but will add dependencies on modules using the host's os variation and
+ // the common arch variation. Useful for a device test that wants to depend on a host
+ // module, for example to include a custom Tradefed test runner.
+ Host_common_data []string `android:"path_host_common"`
+
// Add RootTargetPreparer to auto generated test config. This guarantees the test to run
// with root permission.
Require_root *bool
@@ -314,7 +327,11 @@
s.properties.SubName = s.GetSubname(ctx)
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: []string{s.sourceFilePath.String()}})
+ android.SetProvider(ctx, ShBinaryInfoProvider, ShBinaryInfo{
+ SubDir: s.SubDir(),
+ OutputFile: s.OutputFile(),
+ Symlinks: s.Symlinks(),
+ })
ctx.SetOutputFiles(android.Paths{s.outputFilePath}, "")
}
@@ -339,6 +356,8 @@
for _, symlink := range s.Symlinks() {
ctx.InstallSymlink(installDir, symlink, s.installedFile)
}
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
}
func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries {
@@ -424,8 +443,9 @@
expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data)
expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_common_data)...)
expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_first_data)...)
+ expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Host_common_data)...)
// Emulate the data property for java_data dependencies.
- for _, javaData := range ctx.GetDirectDepsWithTag(shTestJavaDataTag) {
+ for _, javaData := range ctx.GetDirectDepsProxyWithTag(shTestJavaDataTag) {
expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
}
for _, d := range expandedData {
@@ -478,21 +498,24 @@
s.extraTestConfigs = android.PathsForModuleSrc(ctx, s.testProperties.Extra_test_configs)
s.dataModules = make(map[string]android.Path)
- ctx.VisitDirectDeps(func(dep android.Module) {
+ ctx.VisitDirectDepsProxy(func(dep android.ModuleProxy) {
depTag := ctx.OtherModuleDependencyTag(dep)
switch depTag {
case shTestDataBinsTag, shTestDataDeviceBinsTag:
path := android.OutputFileForModule(ctx, dep, "")
s.addToDataModules(ctx, path.Base(), path)
case shTestDataLibsTag, shTestDataDeviceLibsTag:
- if cc, isCc := dep.(*cc.Module); isCc {
+ if _, isCc := android.OtherModuleProvider(ctx, dep, cc.CcInfoProvider); isCc {
// Copy to an intermediate output directory to append "lib[64]" to the path,
// so that it's compatible with the default rpath values.
var relPath string
- if cc.Arch().ArchType.Multilib == "lib64" {
- relPath = filepath.Join("lib64", cc.OutputFile().Path().Base())
+ linkableInfo := android.OtherModuleProviderOrDefault(ctx, dep, cc.LinkableInfoProvider)
+ commonInfo := android.OtherModulePointerProviderOrDefault(ctx, dep, android.CommonModuleInfoProvider)
+
+ if commonInfo.Target.Arch.ArchType.Multilib == "lib64" {
+ relPath = filepath.Join("lib64", linkableInfo.OutputFile.Path().Base())
} else {
- relPath = filepath.Join("lib", cc.OutputFile().Path().Base())
+ relPath = filepath.Join("lib", linkableInfo.OutputFile.Path().Base())
}
if _, exist := s.dataModules[relPath]; exist {
return
@@ -500,7 +523,7 @@
relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
- Input: cc.OutputFile().Path(),
+ Input: linkableInfo.OutputFile.Path(),
Output: relocatedLib,
})
s.addToDataModules(ctx, relPath, relocatedLib)
@@ -529,6 +552,32 @@
MkAppClass: mkEntries.Class,
InstallDir: s.installDir,
})
+
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+ if len(s.testProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, s.testProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+ if proptools.Bool(s.testProperties.Test_options.Unit_test) {
+ moduleInfoJSON.IsUnitTest = "true"
+ if ctx.Host() {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
+ }
+ moduleInfoJSON.DataDependencies = append(moduleInfoJSON.DataDependencies, s.testProperties.Data_bins...)
+ if s.testConfig != nil {
+ if _, ok := s.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.testConfig.String())
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, s.extraTestConfigs.Strings()...)
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: s.testProperties.Test_suites,
+ })
}
func addArch(archType string, paths android.Paths) []string {
@@ -564,6 +613,8 @@
entries.AddStrings("LOCAL_EXTRA_FULL_TEST_CONFIGS", s.extraTestConfigs.Strings()...)
}
+ entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !proptools.BoolDefault(s.testProperties.Auto_gen_config, true))
+
s.testProperties.Test_options.SetAndroidMkEntries(entries)
},
},
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 28f997d..c2e2d2b 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -58,7 +58,7 @@
}
`)
- mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
+ mod := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Module().(*ShTest)
entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
@@ -83,7 +83,7 @@
}
`)
- mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
+ mod := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Module().(*ShTest)
entries := android.AndroidMkEntriesForTest(t, result.TestContext, mod)[0]
@@ -129,7 +129,7 @@
buildOS := config.BuildOS.String()
arches := []string{"android_arm64_armv8-a", buildOS + "_x86_64"}
for _, arch := range arches {
- variant := ctx.ModuleForTests("foo", arch)
+ variant := ctx.ModuleForTests(t, "foo", arch)
libExt := ".so"
if arch == "darwin_x86_64" {
@@ -167,7 +167,7 @@
`)
buildOS := ctx.Config().BuildOS.String()
- mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest)
+ mod := ctx.ModuleForTests(t, "foo", buildOS+"_x86_64").Module().(*ShTest)
if !mod.Host() {
t.Errorf("host bit is not set for a sh_test_host module.")
}
@@ -186,7 +186,7 @@
}
`)
- mod := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
+ mod := result.ModuleForTests(t, "foo", "android_arm64_armv8-a").Module().(*ShTest)
entries := android.AndroidMkEntriesForTest(t, result, mod)[0]
actualData := entries.EntryMap["LOCAL_EXTRA_FULL_TEST_CONFIGS"]
android.AssertStringPathsRelativeToTopEquals(t, "extra_configs", result.Config(), []string{"config1.xml", "config2.xml"}, actualData)
@@ -221,7 +221,7 @@
buildOS := config.BuildOS.String()
variant := buildOS + "_x86_64"
- foo := ctx.ModuleForTests("foo", variant)
+ foo := ctx.ModuleForTests(t, "foo", variant)
relocated := foo.Output(filepath.Join("out/soong/.intermediates/foo", variant, "relocated/lib64/libbar.so"))
expectedInput := "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so"
@@ -266,7 +266,7 @@
`)
buildOS := config.BuildOS.String()
- fooModule := ctx.ModuleForTests("foo", buildOS+"_x86_64")
+ fooModule := ctx.ModuleForTests(t, "foo", buildOS+"_x86_64")
expectedBinAutogenConfig := `<option name="push-file" key="bar" value="/data/local/tests/unrestricted/foo/bar" />`
autogen := fooModule.Rule("autogen")
@@ -296,7 +296,7 @@
}
`)
buildOS := ctx.Config().BuildOS.String()
- mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest)
+ mod := ctx.ModuleForTests(t, "foo", buildOS+"_x86_64").Module().(*ShTest)
if !mod.Host() {
t.Errorf("host bit is not set for a sh_test_host module.")
}
@@ -345,7 +345,7 @@
`)
buildOS := ctx.Config().BuildOS.String()
- mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest)
+ mod := ctx.ModuleForTests(t, "foo", buildOS+"_x86_64").Module().(*ShTest)
if !mod.Host() {
t.Errorf("host bit is not set for a sh_test_host module.")
}
@@ -365,7 +365,7 @@
":testdata/data1",
":testdata/sub/data2",
}
- mod = ctx.ModuleForTests("sh-test", "android_arm64_armv8-a").Module().(*ShTest)
+ mod = ctx.ModuleForTests(t, "sh-test", "android_arm64_armv8-a").Module().(*ShTest)
entries = android.AndroidMkEntriesForTest(t, ctx, mod)[0]
actualData = entries.EntryMap["LOCAL_TEST_DATA"]
android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData)
@@ -388,7 +388,7 @@
}
`)
buildOS := ctx.Config().BuildOS.String()
- mod := ctx.ModuleForTests("the-host-binary", buildOS+"_x86_64").Module().(*ShBinary)
+ mod := ctx.ModuleForTests(t, "the-host-binary", buildOS+"_x86_64").Module().(*ShBinary)
if !mod.Host() {
t.Errorf("host bit is not set for a sh_binary_host module.")
}
@@ -396,6 +396,6 @@
expectedFilename := "test.sh"
android.AssertStringEquals(t, "Filename", expectedFilename, *mod.properties.Filename)
- mod = ctx.ModuleForTests("the-binary", "android_arm64_armv8-a").Module().(*ShBinary)
+ mod = ctx.ModuleForTests(t, "the-binary", "android_arm64_armv8-a").Module().(*ShBinary)
android.AssertStringEquals(t, "Filename", expectedFilename, *mod.properties.Filename)
}
diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go
index 6bf3c87..510e9cf 100644
--- a/snapshot/snapshot_base.go
+++ b/snapshot/snapshot_base.go
@@ -45,14 +45,3 @@
LicenseKinds []string `json:",omitempty"`
LicenseTexts []string `json:",omitempty"`
}
-
-func (prop *SnapshotJsonFlags) InitBaseSnapshotPropsWithName(m android.Module, name string) {
- prop.ModuleName = name
-
- prop.LicenseKinds = m.EffectiveLicenseKinds()
- prop.LicenseTexts = m.EffectiveLicenseFiles().Strings()
-}
-
-func (prop *SnapshotJsonFlags) InitBaseSnapshotProps(m android.Module) {
- prop.InitBaseSnapshotPropsWithName(m, m.Name())
-}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 84f20c5..a398cbc 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -226,6 +226,9 @@
// Make this module available when building for ramdisk
Ramdisk_available *bool
+ // Make this module available when building for vendor ramdisk
+ Vendor_ramdisk_available *bool
+
// Make this module available when building for recovery
Recovery_available *bool
@@ -346,7 +349,6 @@
ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
}
}
- android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
if ctx.Failed() {
return
@@ -460,9 +462,8 @@
var _ android.ApexModule = (*syspropLibrary)(nil)
// Implements android.ApexModule
-func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
- return fmt.Errorf("sysprop_library is not supposed to be part of apex modules")
+func (m *syspropLibrary) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
+ return android.MinApiLevel
}
// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
@@ -502,17 +503,18 @@
Static_libs []string
}
}
- Required []string
- Recovery *bool
- Recovery_available *bool
- Vendor_available *bool
- Product_available *bool
- Ramdisk_available *bool
- Host_supported *bool
- Apex_available []string
- Min_sdk_version *string
- Cflags []string
- Ldflags []string
+ Required []string
+ Recovery *bool
+ Recovery_available *bool
+ Vendor_available *bool
+ Product_available *bool
+ Ramdisk_available *bool
+ Vendor_ramdisk_available *bool
+ Host_supported *bool
+ Apex_available []string
+ Min_sdk_version *string
+ Cflags []string
+ Ldflags []string
}
type javaLibraryProperties struct {
@@ -605,6 +607,7 @@
ccProps.Vendor_available = m.properties.Vendor_available
ccProps.Product_available = m.properties.Product_available
ccProps.Ramdisk_available = m.properties.Ramdisk_available
+ ccProps.Vendor_ramdisk_available = m.properties.Vendor_ramdisk_available
ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
@@ -680,7 +683,7 @@
Sysprop_srcs: m.properties.Srcs,
Scope: scope,
Check_api: proptools.StringPtr(ctx.ModuleName()),
- Installable: proptools.BoolPtr(false),
+ Installable: m.properties.Installable,
Crate_name: m.rustCrateName(),
Rustlibs: []string{
"liblog_rust",
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 7d4e69d..b2cfaa7 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -261,9 +261,9 @@
"android_vendor_arm64_armv8-a_shared",
"android_vendor_arm64_armv8-a_static",
} {
- result.ModuleForTests("libsysprop-platform", variant)
- result.ModuleForTests("libsysprop-vendor", variant)
- result.ModuleForTests("libsysprop-odm", variant)
+ result.ModuleForTests(t, "libsysprop-platform", variant)
+ result.ModuleForTests(t, "libsysprop-vendor", variant)
+ result.ModuleForTests(t, "libsysprop-odm", variant)
}
// product variant of vendor-owned sysprop_library
@@ -273,7 +273,7 @@
"android_product_arm64_armv8-a_shared",
"android_product_arm64_armv8-a_static",
} {
- result.ModuleForTests("libsysprop-vendor-on-product", variant)
+ result.ModuleForTests(t, "libsysprop-vendor-on-product", variant)
}
for _, variant := range []string{
@@ -282,15 +282,15 @@
"android_arm64_armv8-a_shared",
"android_arm64_armv8-a_static",
} {
- library := result.ModuleForTests("libsysprop-platform", variant).Module().(*cc.Module)
+ library := result.ModuleForTests(t, "libsysprop-platform", variant).Module().(*cc.Module)
expectedApexAvailableOnLibrary := []string{"//apex_available:platform"}
android.AssertDeepEquals(t, "apex available property on libsysprop-platform", expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
}
- result.ModuleForTests("sysprop-platform", "android_common")
- result.ModuleForTests("sysprop-platform_public", "android_common")
- result.ModuleForTests("sysprop-vendor", "android_common")
- result.ModuleForTests("sysprop-vendor-on-product", "android_common")
+ result.ModuleForTests(t, "sysprop-platform", "android_common")
+ result.ModuleForTests(t, "sysprop-platform_public", "android_common")
+ result.ModuleForTests(t, "sysprop-vendor", "android_common")
+ result.ModuleForTests(t, "sysprop-vendor-on-product", "android_common")
// Check for exported includes
coreVariant := "android_arm64_armv8-a_static"
@@ -305,19 +305,19 @@
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)
+ platformClient := result.ModuleForTests(t, "cc-client-platform", coreVariant)
platformFlags := platformClient.Rule("cc").Args["cFlags"]
// platform should use platform's internal header
android.AssertStringDoesContain(t, "flags for platform", platformFlags, platformInternalPath)
- platformStaticClient := result.ModuleForTests("cc-client-platform-static", coreVariant)
+ platformStaticClient := result.ModuleForTests(t, "cc-client-platform-static", coreVariant)
platformStaticFlags := platformStaticClient.Rule("cc").Args["cFlags"]
// platform-static should use platform's internal header
android.AssertStringDoesContain(t, "flags for platform-static", platformStaticFlags, platformInternalPath)
- productClient := result.ModuleForTests("cc-client-product", productVariant)
+ productClient := result.ModuleForTests(t, "cc-client-product", productVariant)
productFlags := productClient.Rule("cc").Args["cFlags"]
// Product should use platform's and vendor's public headers
@@ -327,7 +327,7 @@
platformOnProductPath, vendorOnProductPath, productFlags)
}
- vendorClient := result.ModuleForTests("cc-client-vendor", vendorVariant)
+ vendorClient := result.ModuleForTests(t, "cc-client-vendor", vendorVariant)
vendorFlags := vendorClient.Rule("cc").Args["cFlags"]
// Vendor should use platform's public header and vendor's internal header
@@ -338,8 +338,8 @@
}
// Java modules linking against system API should use public stub
- javaSystemApiClient := result.ModuleForTests("java-platform", "android_common").Rule("javac")
- syspropPlatformPublic := result.ModuleForTests("sysprop-platform_public", "android_common").Description("for turbine")
+ javaSystemApiClient := result.ModuleForTests(t, "java-platform", "android_common").Rule("javac")
+ syspropPlatformPublic := result.ModuleForTests(t, "sysprop-platform_public", "android_common").Description("turbine")
if g, w := javaSystemApiClient.Implicits.Strings(), syspropPlatformPublic.Output.String(); !android.InList(w, g) {
t.Errorf("system api client should use public stub %q, got %q", w, g)
}
@@ -358,15 +358,15 @@
expected := []string{"//apex_available:platform"}
- ccModule := result.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ ccModule := result.ModuleForTests(t, "libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
propFromCc := ccModule.ApexProperties.Apex_available
android.AssertDeepEquals(t, "apex_available forwarding to cc module", expected, propFromCc)
- javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ javaModule := result.ModuleForTests(t, "sysprop-platform", "android_common").Module().(*java.Library)
propFromJava := javaModule.ApexProperties.Apex_available
android.AssertDeepEquals(t, "apex_available forwarding to java module", expected, propFromJava)
- rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
+ rustModule := result.ModuleForTests(t, "libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
propFromRust := rustModule.ApexProperties.Apex_available
android.AssertDeepEquals(t, "apex_available forwarding to rust module", expected, propFromRust)
}
@@ -390,15 +390,15 @@
}
`)
- ccModule := result.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ ccModule := result.ModuleForTests(t, "libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
propFromCc := proptools.String(ccModule.Properties.Min_sdk_version)
android.AssertStringEquals(t, "min_sdk_version forwarding to cc module", "29", propFromCc)
- javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ javaModule := result.ModuleForTests(t, "sysprop-platform", "android_common").Module().(*java.Library)
propFromJava := javaModule.MinSdkVersionString()
android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava)
- rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
+ rustModule := result.ModuleForTests(t, "libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
propFromRust := proptools.String(rustModule.Properties.Min_sdk_version)
android.AssertStringEquals(t, "min_sdk_version forwarding to rust module", "29", propFromRust)
}
diff --git a/systemfeatures/system_features.go b/systemfeatures/system_features.go
index 0c1a566..b8dacfb 100644
--- a/systemfeatures/system_features.go
+++ b/systemfeatures/system_features.go
@@ -20,6 +20,8 @@
"android/soong/android"
"android/soong/genrule"
+
+ "github.com/google/blueprint/proptools"
)
var (
@@ -39,6 +41,11 @@
properties struct {
// The fully qualified class name for the generated code, e.g., com.android.Foo
Full_class_name string
+ // Whether to generate only a simple metadata class with details about the full API surface.
+ // This is useful for tools that rely on the mapping from feature names to their generated
+ // method names, but don't want the fully generated API class (e.g., for linting).
+
+ Metadata_only *bool
}
outputFiles android.WritablePaths
}
@@ -72,6 +79,7 @@
Flag(m.properties.Full_class_name).
FlagForEachArg("--feature=", features).
FlagWithArg("--readonly=", fmt.Sprint(ctx.Config().ReleaseUseSystemFeatureBuildFlags())).
+ FlagWithArg("--metadata-only=", fmt.Sprint(proptools.Bool(m.properties.Metadata_only))).
FlagWithOutput(" > ", outputFile)
rule.Build(ctx.ModuleName(), "Generating systemfeatures srcs filegroup")
@@ -97,6 +105,7 @@
func JavaSystemFeaturesSrcsFactory() android.Module {
module := &javaSystemFeaturesSrcs{}
module.AddProperties(&module.properties)
+ module.properties.Metadata_only = proptools.BoolPtr(false)
android.InitAndroidModule(module)
return module
}
diff --git a/systemfeatures/system_features_test.go b/systemfeatures/system_features_test.go
index 558bb95..58e6a06 100644
--- a/systemfeatures/system_features_test.go
+++ b/systemfeatures/system_features_test.go
@@ -36,7 +36,7 @@
android.PrepareForTestWithBuildFlag("RELEASE_NOT_SYSTEM_FEATURE_FOO", "BAR"),
).RunTestWithBp(t, bp)
- module := res.ModuleForTests("system-features-srcs", "")
+ module := res.ModuleForTests(t, "system-features-srcs", "")
cmd := module.Rule("system-features-srcs").RuleParams.Command
android.AssertStringDoesContain(t, "Expected fully class name", cmd, " com.android.test.RoSystemFeatures ")
android.AssertStringDoesContain(t, "Expected readonly flag", cmd, "--readonly=true")
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 0471853..2ef9e37 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -83,6 +83,12 @@
dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
lz4=$out_dir/host/linux-x86/bin/lz4
+ declare -A diff_excludes
+ diff_excludes[system]="\
+ -I /etc/NOTICE.xml.gz \
+ -I /odm_dlkm/etc \
+ -I /vendor_dlkm/etc"
+
# Example output of dump.erofs is as below, and the data used in the test start
# at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
# Each line is captured in variable "entry", awk is used to get type and name.
@@ -155,7 +161,11 @@
sort -n -o "$files_in_soong_spdx_file" "$files_in_soong_spdx_file"
echo ============ Diffing files in $f and SBOM created by Soong
- diff_files "$file_list_file" "$files_in_soong_spdx_file" "$partition_name" ""
+ exclude=
+ if [ -v 'diff_excludes[$partition_name]' ]; then
+ exclude=${diff_excludes[$partition_name]}
+ fi
+ diff_files "$file_list_file" "$files_in_soong_spdx_file" "$partition_name" "$exclude"
done
RAMDISK_IMAGES="$product_out/ramdisk.img"
@@ -230,10 +240,10 @@
exit 1
fi
- # PRODUCT and 7 prebuilt packages have "PackageLicenseDeclared: NOASSERTION"
+ # PRODUCT and 6 prebuilt packages have "PackageLicenseDeclared: NOASSERTION"
# All other packages have declared licenses
num_of_packages_with_noassertion_license=$(grep 'PackageLicenseDeclared: NOASSERTION' $sbom_file | wc -l)
- if [ $num_of_packages_with_noassertion_license = 15 ]
+ if [ $num_of_packages_with_noassertion_license = 13 ]
then
echo "Number of packages with NOASSERTION license is correct."
else
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index e230795..89c69bd 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -160,6 +160,7 @@
DeviceTemplate string
HostTemplate string
HostUnitTestTemplate string
+ StandaloneTest *bool
}
func AutoGenTestConfig(ctx android.ModuleContext, options AutoGenTestConfigOptions) android.Path {
@@ -178,6 +179,12 @@
autogenTemplate(ctx, name, autogenPath, templatePath.String(), configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
} else {
if ctx.Device() {
+ if Bool(options.StandaloneTest) {
+ options.TestRunnerOptions = append(options.TestRunnerOptions, Option{
+ Name: "ld-library-path",
+ Value: "{TEST_INSTALL_BASE}/" + name + "/" + ctx.Arch().ArchType.String() + "/standalone-libs",
+ })
+ }
autogenTemplate(ctx, name, autogenPath, options.DeviceTemplate, configs, options.TestRunnerOptions, options.OutputFileName, options.TestInstallBase)
} else {
if Bool(options.UnitTest) {
@@ -190,7 +197,10 @@
return autogenPath
}
if len(options.OptionsForAutogenerated) > 0 {
- ctx.ModuleErrorf("Extra tradefed configurations were provided for an autogenerated xml file, but the autogenerated xml file was not used.")
+ ctx.ModuleErrorf("You likely need to delete your soong modules local AndroidTest.xml file. Extra tradefed configurations (%v) were provided for an autogenerated xml file, but the autogenerated xml file was not used.", options.OptionsForAutogenerated)
+ }
+ if len(options.TestRunnerOptions) > 0 {
+ ctx.ModuleErrorf("You likely need to delete your soong modules local AndroidTest.xml file. Extra test runner options (%v) were provided for an autogenerated xml file, but the autogenerated xml file was not used.", options.TestRunnerOptions)
}
return path
}
diff --git a/tradefed_modules/Android.bp b/tradefed_modules/Android.bp
index a765a05..37bae39 100644
--- a/tradefed_modules/Android.bp
+++ b/tradefed_modules/Android.bp
@@ -14,11 +14,9 @@
],
srcs: [
"test_module_config.go",
- "test_suite.go",
],
testSrcs: [
"test_module_config_test.go",
- "test_suite_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
index 988352c..e833df2 100644
--- a/tradefed_modules/test_module_config.go
+++ b/tradefed_modules/test_module_config.go
@@ -1,14 +1,15 @@
package tradefed_modules
import (
- "android/soong/android"
- "android/soong/tradefed"
"encoding/json"
"fmt"
"io"
"slices"
"strings"
+ "android/soong/android"
+ "android/soong/tradefed"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -162,6 +163,26 @@
m.validateBase(ctx, &testModuleConfigTag, "android_test", false)
m.generateManifestAndConfig(ctx)
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ moduleInfoJSON.Class = []string{m.provider.MkAppClass}
+ if m.provider.MkAppClass != "NATIVE_TESTS" {
+ moduleInfoJSON.Tags = append(moduleInfoJSON.Tags, "tests")
+ }
+ if m.provider.IsUnitTest {
+ moduleInfoJSON.IsUnitTest = "true"
+ }
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, m.tradefedProperties.Test_suites...)
+ moduleInfoJSON.SystemSharedLibs = []string{"none"}
+ moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, m.provider.RequiredModuleNames...)
+ moduleInfoJSON.ExtraRequired = append(moduleInfoJSON.ExtraRequired, *m.Base)
+ moduleInfoJSON.ExtraHostRequired = append(moduleInfoJSON.ExtraRequired, m.provider.HostRequiredModuleNames...)
+ moduleInfoJSON.TestConfig = []string{m.testConfig.String()}
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ moduleInfoJSON.TestModuleConfigBase = proptools.String(m.Base)
+
+ android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{
+ SupportFiles: m.supportFiles,
+ })
}
// Ensure at least one test_suite is listed. Ideally it should be general-tests
@@ -311,6 +332,9 @@
func (m *testModuleConfigHostModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
m.validateBase(ctx, &testModuleConfigHostTag, "java_test_host", true)
m.generateManifestAndConfig(ctx)
+ android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{
+ SupportFiles: m.supportFiles,
+ })
}
// Ensure the base listed is the right type by checking that we get the expected provider data.
@@ -410,6 +434,10 @@
LocalCertificate: m.provider.LocalCertificate,
IsUnitTest: m.provider.IsUnitTest,
})
+
+ android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
+ TestSuites: m.tradefedProperties.Test_suites,
+ })
}
var _ android.AndroidMkEntriesProvider = (*testModuleConfigHostModule)(nil)
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
index efd4a04..302f9a9 100644
--- a/tradefed_modules/test_module_config_test.go
+++ b/tradefed_modules/test_module_config_test.go
@@ -65,21 +65,21 @@
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
).RunTestWithBp(t, bp)
- derived := ctx.ModuleForTests("derived_test", variant)
+ derived := ctx.ModuleForTests(t, "derived_test", variant)
// 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")
+ ctx.ModuleForTests(t, "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.
// Do not use LOCAL_COMPATIBILITY_SUPPORT_FILES, but instead use LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES
android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
- []string{"out/soong/target/product/test_device/testcases/derived_test/arm64/base.apk",
- "out/soong/target/product/test_device/testcases/derived_test/HelperApp.apk",
- "out/soong/target/product/test_device/testcases/derived_test/data/testfile"},
+ []string{"out/target/product/test_device/testcases/derived_test/arm64/base.apk",
+ "out/target/product/test_device/testcases/derived_test/HelperApp.apk",
+ "out/target/product/test_device/testcases/derived_test/data/testfile"},
entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{})
@@ -97,15 +97,15 @@
convertedActual := make([]string, 5)
for i, e := range entries.FooterLinesForTests() {
// AssertStringPathsRelativeToTop doesn't replace both instances
- convertedActual[i] = strings.Replace(e, ctx.Config.SoongOutDir(), "", 2)
+ convertedActual[i] = strings.Replace(e, ctx.Config.OutDir(), "", 2)
}
- android.AssertArrayString(t, fmt.Sprintf("%s", ctx.Config.SoongOutDir()), convertedActual, []string{
+ android.AssertArrayString(t, fmt.Sprintf("%s", ctx.Config.OutDir()), []string{
"include $(BUILD_SYSTEM)/soong_app_prebuilt.mk",
"/target/product/test_device/testcases/derived_test/arm64/base.apk: /target/product/test_device/testcases/base/arm64/base.apk",
"/target/product/test_device/testcases/derived_test/HelperApp.apk: /target/product/test_device/testcases/base/HelperApp.apk",
"/target/product/test_device/testcases/derived_test/data/testfile: /target/product/test_device/testcases/base/data/testfile",
"",
- })
+ }, convertedActual)
}
func TestModuleConfigShTest(t *testing.T) {
@@ -136,7 +136,7 @@
options: [{name: "SomeName", value: "OptionValue"}],
}
`)
- derived := ctx.ModuleForTests("conch", variant) //
+ derived := ctx.ModuleForTests(t, "conch", variant) //
conch := derived.Module().(*testModuleConfigModule)
android.AssertArrayString(t, "TestcaseRelDataFiles", []string{"arm64/testdata/data1", "arm64/testdata/sub/data2"}, conch.provider.TestcaseRelDataFiles)
android.AssertStringEquals(t, "Rel OutputFile", "test.sh", conch.provider.OutputFile.Rel())
@@ -151,8 +151,8 @@
// Ensure some entries from base are there, specifically support files for data and helper apps.
// Do not use LOCAL_COMPATIBILITY_SUPPORT_FILES, but instead use LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES
android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
- []string{"out/soong/target/product/test_device/testcases/conch/arm64/testdata/data1",
- "out/soong/target/product/test_device/testcases/conch/arm64/testdata/sub/data2"},
+ []string{"out/target/product/test_device/testcases/conch/arm64/testdata/data1",
+ "out/target/product/test_device/testcases/conch/arm64/testdata/sub/data2"},
entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{})
@@ -171,14 +171,14 @@
convertedActual := make([]string, 4)
for i, e := range entries.FooterLinesForTests() {
// AssertStringPathsRelativeToTop doesn't replace both instances
- convertedActual[i] = strings.Replace(e, ctx.Config.SoongOutDir(), "", 2)
+ convertedActual[i] = strings.Replace(e, ctx.Config.OutDir(), "", 2)
}
- android.AssertArrayString(t, fmt.Sprintf("%s", ctx.Config.SoongOutDir()), convertedActual, []string{
+ android.AssertArrayString(t, fmt.Sprintf("%s", ctx.Config.OutDir()), []string{
"include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
"/target/product/test_device/testcases/conch/arm64/testdata/data1: /target/product/test_device/testcases/shell_test/arm64/testdata/data1",
"/target/product/test_device/testcases/conch/arm64/testdata/sub/data2: /target/product/test_device/testcases/shell_test/arm64/testdata/sub/data2",
"",
- })
+ }, convertedActual)
}
@@ -191,7 +191,7 @@
).RunTestWithBp(t, bp)
// Check that we generate a rule to make a new AndroidTest.xml/Module.config file.
- derived := ctx.ModuleForTests("derived_test", variant)
+ derived := ctx.ModuleForTests(t, "derived_test", variant)
rule_cmd := derived.Rule("fix_test_config").RuleParams.Command
android.AssertStringDoesContain(t, "Bad FixConfig rule inputs", rule_cmd,
`--test-runner-options='[{"Name":"exclude-filter","Key":"","Value":"android.test.example.devcodelab.DevCodelabTest#testHelloFail"},{"Name":"include-annotation","Key":"","Value":"android.platform.test.annotations.LargeTest"}]'`)
@@ -288,7 +288,7 @@
).ExtendWithErrorHandler(
android.FixtureExpectsAtLeastOneErrorMatchingPattern("Test options must be given")).
RunTestWithBp(t, badBp)
- ctx.ModuleForTests("derived_test", variant)
+ ctx.ModuleForTests(t, "derived_test", variant)
}
func TestModuleConfigMultipleDerivedTestsWriteDistinctMakeEntries(t *testing.T) {
@@ -326,13 +326,13 @@
).RunTestWithBp(t, multiBp)
{
- derived := ctx.ModuleForTests("derived_test", variant)
+ derived := ctx.ModuleForTests(t, "derived_test", variant)
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
// All these should be the same in both derived tests
android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
- []string{"out/soong/target/product/test_device/testcases/derived_test/arm64/base.apk",
- "out/soong/target/product/test_device/testcases/derived_test/HelperApp.apk",
- "out/soong/target/product/test_device/testcases/derived_test/data/testfile"},
+ []string{"out/target/product/test_device/testcases/derived_test/arm64/base.apk",
+ "out/target/product/test_device/testcases/derived_test/HelperApp.apk",
+ "out/target/product/test_device/testcases/derived_test/data/testfile"},
entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
// Except this one, which points to the updated tradefed xml file.
@@ -342,13 +342,13 @@
}
{
- derived := ctx.ModuleForTests("another_derived_test", variant)
+ derived := ctx.ModuleForTests(t, "another_derived_test", variant)
entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, derived.Module())[0]
// All these should be the same in both derived tests
android.AssertStringPathsRelativeToTopEquals(t, "support-files", ctx.Config,
- []string{"out/soong/target/product/test_device/testcases/another_derived_test/arm64/base.apk",
- "out/soong/target/product/test_device/testcases/another_derived_test/HelperApp.apk",
- "out/soong/target/product/test_device/testcases/another_derived_test/data/testfile"},
+ []string{"out/target/product/test_device/testcases/another_derived_test/arm64/base.apk",
+ "out/target/product/test_device/testcases/another_derived_test/HelperApp.apk",
+ "out/target/product/test_device/testcases/another_derived_test/data/testfile"},
entries.EntryMap["LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES"])
// Except this one, which points to the updated tradefed xml file.
android.AssertStringMatches(t, "", entries.EntryMap["LOCAL_FULL_TEST_CONFIG"][0],
@@ -381,7 +381,7 @@
).RunTestWithBp(t, bp)
variant := ctx.Config.BuildOS.String() + "_common"
- derived := ctx.ModuleForTests("derived_test", variant)
+ derived := ctx.ModuleForTests(t, "derived_test", variant)
mod := derived.Module().(*testModuleConfigHostModule)
allEntries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)
entries := allEntries[0]
diff --git a/tradefed_modules/test_suite.go b/tradefed_modules/test_suite.go
deleted file mode 100644
index 00585f5..0000000
--- a/tradefed_modules/test_suite.go
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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 (
- "encoding/json"
- "path"
- "path/filepath"
-
- "android/soong/android"
- "android/soong/tradefed"
- "github.com/google/blueprint"
-)
-
-const testSuiteModuleType = "test_suite"
-
-type testSuiteTag struct{
- blueprint.BaseDependencyTag
-}
-
-type testSuiteManifest struct {
- Name string `json:"name"`
- Files []string `json:"files"`
-}
-
-func init() {
- RegisterTestSuiteBuildComponents(android.InitRegistrationContext)
-}
-
-func RegisterTestSuiteBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType(testSuiteModuleType, TestSuiteFactory)
-}
-
-var PrepareForTestWithTestSuiteBuildComponents = android.GroupFixturePreparers(
- android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents),
-)
-
-type testSuiteProperties struct {
- Description string
- Tests []string `android:"path,arch_variant"`
-}
-
-type testSuiteModule struct {
- android.ModuleBase
- android.DefaultableModuleBase
- testSuiteProperties
-}
-
-func (t *testSuiteModule) DepsMutator(ctx android.BottomUpMutatorContext) {
- for _, test := range t.Tests {
- if ctx.OtherModuleDependencyVariantExists(ctx.Config().BuildOSCommonTarget.Variations(), test) {
- // Host tests.
- ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), testSuiteTag{}, test)
- } else {
- // Target tests.
- ctx.AddDependency(ctx.Module(), testSuiteTag{}, test)
- }
- }
-}
-
-func (t *testSuiteModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- suiteName := ctx.ModuleName()
- modulesByName := make(map[string]android.Module)
- ctx.WalkDeps(func(child, parent android.Module) bool {
- // Recurse into test_suite dependencies.
- if ctx.OtherModuleType(child) == testSuiteModuleType {
- ctx.Phony(suiteName, android.PathForPhony(ctx, child.Name()))
- return true
- }
-
- // Only write out top level test suite dependencies here.
- if _, ok := ctx.OtherModuleDependencyTag(child).(testSuiteTag); !ok {
- return false
- }
-
- if !child.InstallInTestcases() {
- ctx.ModuleErrorf("test_suite only supports modules installed in testcases. %q is not installed in testcases.", child.Name())
- return false
- }
-
- modulesByName[child.Name()] = child
- return false
- })
-
- var files []string
- for name, module := range modulesByName {
- // Get the test provider data from the child.
- tp, ok := android.OtherModuleProvider(ctx, module, tradefed.BaseTestProviderKey)
- if !ok {
- // TODO: Consider printing out a list of all module types.
- ctx.ModuleErrorf("%q is not a test module.", name)
- continue
- }
-
- files = append(files, packageModuleFiles(ctx, suiteName, module, tp)...)
- ctx.Phony(suiteName, android.PathForPhony(ctx, name))
- }
-
- manifestPath := android.PathForSuiteInstall(ctx, suiteName, suiteName+".json")
- b, err := json.Marshal(testSuiteManifest{Name: suiteName, Files: files})
- if err != nil {
- ctx.ModuleErrorf("Failed to marshal manifest: %v", err)
- return
- }
- android.WriteFileRule(ctx, manifestPath, string(b))
-
- ctx.Phony(suiteName, manifestPath)
-}
-
-func TestSuiteFactory() android.Module {
- module := &testSuiteModule{}
- module.AddProperties(&module.testSuiteProperties)
-
- android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
- android.InitDefaultableModule(module)
-
- return module
-}
-
-func packageModuleFiles(ctx android.ModuleContext, suiteName string, module android.Module, tp tradefed.BaseTestProviderData) []string {
-
- hostOrTarget := "target"
- if tp.IsHost {
- hostOrTarget = "host"
- }
-
- // suiteRoot at out/soong/packaging/<suiteName>.
- suiteRoot := android.PathForSuiteInstall(ctx, suiteName)
-
- var installed android.InstallPaths
- // Install links to installed files from the module.
- if installFilesInfo, ok := android.OtherModuleProvider(ctx, module, android.InstallFilesProvider); ok {
- for _, f := range installFilesInfo.InstallFiles {
- // rel is anything under .../<partition>, normally under .../testcases.
- rel := android.Rel(ctx, f.PartitionDir(), f.String())
-
- // Install the file under <suiteRoot>/<host|target>/<partition>.
- installDir := suiteRoot.Join(ctx, hostOrTarget, f.Partition(), path.Dir(rel))
- linkTo, err := filepath.Rel(installDir.String(), f.String())
- if err != nil {
- ctx.ModuleErrorf("Failed to get relative path from %s to %s: %v", installDir.String(), f.String(), err)
- continue
- }
- installed = append(installed, ctx.InstallAbsoluteSymlink(installDir, path.Base(rel), linkTo))
- }
- }
-
- // Install config file.
- if tp.TestConfig != nil {
- moduleRoot := suiteRoot.Join(ctx, hostOrTarget, "testcases", module.Name())
- installed = append(installed, ctx.InstallFile(moduleRoot, module.Name() + ".config", tp.TestConfig))
- }
-
- // Add to phony and manifest, manifestpaths are relative to suiteRoot.
- var manifestEntries []string
- for _, f := range installed {
- manifestEntries = append(manifestEntries, android.Rel(ctx, suiteRoot.String(), f.String()))
- ctx.Phony(suiteName, f)
- }
- return manifestEntries
-}
diff --git a/tradefed_modules/test_suite_test.go b/tradefed_modules/test_suite_test.go
deleted file mode 100644
index 3c0a9eb..0000000
--- a/tradefed_modules/test_suite_test.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// 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"
- "encoding/json"
- "slices"
- "testing"
-)
-
-func TestTestSuites(t *testing.T) {
- t.Parallel()
- ctx := android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents),
- ).RunTestWithBp(t, `
- android_test {
- name: "TestModule1",
- sdk_version: "current",
- }
-
- android_test {
- name: "TestModule2",
- sdk_version: "current",
- }
-
- test_suite {
- name: "my-suite",
- description: "a test suite",
- tests: [
- "TestModule1",
- "TestModule2",
- ]
- }
- `)
- manifestPath := ctx.ModuleForTests("my-suite", "android_common").Output("out/soong/test_suites/my-suite/my-suite.json")
- var actual testSuiteManifest
- if err := json.Unmarshal([]byte(android.ContentFromFileRuleForTests(t, ctx.TestContext, manifestPath)), &actual); err != nil {
- t.Errorf("failed to unmarshal manifest: %v", err)
- }
- slices.Sort(actual.Files)
-
- expected := testSuiteManifest{
- Name: "my-suite",
- Files: []string{
- "target/testcases/TestModule1/TestModule1.config",
- "target/testcases/TestModule1/arm64/TestModule1.apk",
- "target/testcases/TestModule2/TestModule2.config",
- "target/testcases/TestModule2/arm64/TestModule2.apk",
- },
- }
-
- android.AssertDeepEquals(t, "manifests differ", expected, actual)
-}
-
-func TestTestSuitesWithNested(t *testing.T) {
- t.Parallel()
- ctx := android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents),
- ).RunTestWithBp(t, `
- android_test {
- name: "TestModule1",
- sdk_version: "current",
- }
-
- android_test {
- name: "TestModule2",
- sdk_version: "current",
- }
-
- android_test {
- name: "TestModule3",
- sdk_version: "current",
- }
-
- test_suite {
- name: "my-child-suite",
- description: "a child test suite",
- tests: [
- "TestModule1",
- "TestModule2",
- ]
- }
-
- test_suite {
- name: "my-all-tests-suite",
- description: "a parent test suite",
- tests: [
- "TestModule1",
- "TestModule3",
- "my-child-suite",
- ]
- }
- `)
- manifestPath := ctx.ModuleForTests("my-all-tests-suite", "android_common").Output("out/soong/test_suites/my-all-tests-suite/my-all-tests-suite.json")
- var actual testSuiteManifest
- if err := json.Unmarshal([]byte(android.ContentFromFileRuleForTests(t, ctx.TestContext, manifestPath)), &actual); err != nil {
- t.Errorf("failed to unmarshal manifest: %v", err)
- }
- slices.Sort(actual.Files)
-
- expected := testSuiteManifest{
- Name: "my-all-tests-suite",
- Files: []string{
- "target/testcases/TestModule1/TestModule1.config",
- "target/testcases/TestModule1/arm64/TestModule1.apk",
- "target/testcases/TestModule2/TestModule2.config",
- "target/testcases/TestModule2/arm64/TestModule2.apk",
- "target/testcases/TestModule3/TestModule3.config",
- "target/testcases/TestModule3/arm64/TestModule3.apk",
- },
- }
-
- android.AssertDeepEquals(t, "manifests differ", expected, actual)
-}
-
-func TestTestSuitesNotInstalledInTestcases(t *testing.T) {
- t.Parallel()
- android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- android.FixtureRegisterWithContext(RegisterTestSuiteBuildComponents),
- ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{
- `"SomeHostTest" is not installed in testcases`,
- })).RunTestWithBp(t, `
- java_test_host {
- name: "SomeHostTest",
- srcs: ["a.java"],
- }
- test_suite {
- name: "my-suite",
- description: "a test suite",
- tests: [
- "SomeHostTest",
- ]
- }
- `)
-}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index dc1abd9..a868d6a 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -41,6 +41,7 @@
"soong-remoteexec",
"soong-shared",
"soong-ui-build-paths",
+ "soong-ui-execution-metrics",
"soong-ui-logger",
"soong-ui-metrics",
"soong-ui-status",
@@ -54,6 +55,7 @@
"config.go",
"context.go",
"staging_snapshot.go",
+ "source_inputs.go",
"dumpvars.go",
"environment.go",
"exec.go",
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index 6f57cb1..8266654 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -15,20 +15,29 @@
package build
import (
+ "os"
+ "slices"
"strings"
)
var androidmk_denylist []string = []string{
+ "art/",
"bionic/",
- "chained_build_config/",
+ "bootable/",
+ "build/",
"cts/",
"dalvik/",
"developers/",
"development/",
"device/common/",
+ "device/generic/",
+ "device/google/",
"device/google_car/",
"device/sample/",
+ "external/",
"frameworks/",
+ "hardware/google/",
+ "hardware/interfaces/",
"hardware/libhardware/",
"hardware/libhardware_legacy/",
"hardware/ril/",
@@ -45,24 +54,48 @@
"sdk/",
"system/",
"test/",
+ "tools/",
"trusty/",
- // Add back toolchain/ once defensive Android.mk files are removed
- //"toolchain/",
- "vendor/google_contexthub/",
- "vendor/google_data/",
- "vendor/google_elmyra/",
- "vendor/google_mhl/",
- "vendor/google_pdk/",
- "vendor/google_testing/",
- "vendor/partner_testing/",
- "vendor/partner_tools/",
- "vendor/pdk/",
+ "toolchain/",
+}
+
+var androidmk_allowlist []string = []string{
+ "art/Android.mk",
+ "bootable/deprecated-ota/updater/Android.mk",
+ "tools/vendor/google_prebuilts/arc/Android.mk",
+}
+
+func getAllLines(ctx Context, filename string) []string {
+ bytes, err := os.ReadFile(filename)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return []string{}
+ } else {
+ ctx.Fatalf("Could not read %s: %v", filename, err)
+ }
+ }
+ return strings.Split(strings.Trim(string(bytes), " \n"), "\n")
}
func blockAndroidMks(ctx Context, androidMks []string) {
+ allowlist_files := []string{
+ "vendor/google/build/androidmk/allowlist.txt",
+ "device/google/clockwork/build/androidmk/allowlist.txt",
+ "device/google/sdv/androidmk/allowlist.txt",
+ }
+ for _, allowlist_file := range allowlist_files {
+ allowlist := getAllLines(ctx, allowlist_file)
+ androidmk_allowlist = append(androidmk_allowlist, allowlist...)
+ }
+ slices.Sort(androidmk_allowlist)
+ androidmk_allowlist = slices.Compact(androidmk_allowlist)
+
+ denylist := getAllLines(ctx, "vendor/google/build/androidmk/denylist.txt")
+ androidmk_denylist = append(androidmk_denylist, denylist...)
+
for _, mkFile := range androidMks {
for _, d := range androidmk_denylist {
- if strings.HasPrefix(mkFile, d) {
+ if strings.HasPrefix(mkFile, d) && !slices.Contains(androidmk_allowlist, mkFile) {
ctx.Fatalf("Found blocked Android.mk file: %s. "+
"Please see androidmk_denylist.go for the blocked directories and contact build system team if the file should not be blocked.", mkFile)
}
@@ -70,8 +103,8 @@
}
}
-// The Android.mk files in these directories are for NDK build system.
-var external_ndk_androidmks []string = []string{
+var external_androidmks []string = []string{
+ // The Android.mk files in these directories are for NDK build system.
"external/fmtlib/",
"external/google-breakpad/",
"external/googletest/",
@@ -83,12 +116,29 @@
"external/vulkan-validation-layers/",
"external/walt/",
"external/webp/",
+ // These directories hold the published Android SDK, used in Unbundled Gradle builds.
+ "prebuilts/fullsdk-darwin",
+ "prebuilts/fullsdk-linux",
+ // wpa_supplicant_8 has been converted to Android.bp and Android.mk files are kept for troubleshooting.
+ "external/wpa_supplicant_8/",
+ // Empty Android.mk in package's top directory
+ "external/proguard/",
+ "external/swig/",
+ "toolchain/",
}
-func ignoreNdkAndroidMks(androidMks []string) (filtered []string) {
- filter := func(s string) bool {
- for _, d := range external_ndk_androidmks {
- if strings.HasPrefix(s, d) {
+var art_androidmks = []string{
+ //"art/",
+}
+
+func ignoreSomeAndroidMks(androidMks []string) (filtered []string) {
+ ignore_androidmks := make([]string, 0, len(external_androidmks)+len(art_androidmks))
+ ignore_androidmks = append(ignore_androidmks, external_androidmks...)
+ ignore_androidmks = append(ignore_androidmks, art_androidmks...)
+
+ shouldKeep := func(androidmk string) bool {
+ for _, prefix := range ignore_androidmks {
+ if strings.HasPrefix(androidmk, prefix) {
return false
}
}
@@ -96,10 +146,9 @@
}
for _, l := range androidMks {
- if filter(l) {
+ if shouldKeep(l) {
filtered = append(filtered, l)
}
}
-
return
}
diff --git a/ui/build/build.go b/ui/build/build.go
index d5a20b4..781ca18 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -33,26 +33,13 @@
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
ensureEmptyDirectoriesExist(ctx, config.TempDir())
- // Potentially write a marker file for whether kati is enabled. This is used by soong_build to
- // potentially run the AndroidMk singleton and postinstall commands.
- // Note that the absence of the file does not not preclude running Kati for product
- // configuration purposes.
- katiEnabledMarker := filepath.Join(config.SoongOutDir(), ".soong.kati_enabled")
- if config.SkipKatiNinja() {
- os.Remove(katiEnabledMarker)
- // Note that we can not remove the file for SkipKati builds yet -- some continuous builds
- // --skip-make builds rely on kati targets being defined.
- } else if !config.SkipKati() {
- ensureEmptyFileExists(ctx, katiEnabledMarker)
- }
-
// The ninja_build file is used by our buildbots to understand that the output
// can be parsed as ninja output.
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), ".out-dir"))
if buildDateTimeFile, ok := config.environ.Get("BUILD_DATETIME_FILE"); ok {
- err := ioutil.WriteFile(buildDateTimeFile, []byte(config.buildDateTime), 0666) // a+rw
+ err := os.WriteFile(buildDateTimeFile, []byte(config.buildDateTime), 0666) // a+rw
if err != nil {
ctx.Fatalln("Failed to write BUILD_DATETIME to file:", err)
}
@@ -87,6 +74,32 @@
// without changing the command line every time. Avoids rebuilds
// when using ninja.
writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber)
+
+ hostname, ok := config.environ.Get("BUILD_HOSTNAME")
+ if !ok {
+ var err error
+ hostname, err = os.Hostname()
+ if err != nil {
+ ctx.Println("Failed to read hostname:", err)
+ hostname = "unknown"
+ }
+ }
+ writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname)
+}
+
+// SetupKatiEnabledMarker creates or delets a file that tells soong_build if we're running with
+// kati.
+func SetupKatiEnabledMarker(ctx Context, config Config) {
+ // Potentially write a marker file for whether kati is enabled. This is used by soong_build to
+ // potentially run the AndroidMk singleton and postinstall commands.
+ // Note that the absence of the file does not preclude running Kati for product
+ // configuration purposes.
+ katiEnabledMarker := filepath.Join(config.SoongOutDir(), ".soong.kati_enabled")
+ if config.SkipKati() || config.SkipKatiNinja() {
+ os.Remove(katiEnabledMarker)
+ } else {
+ ensureEmptyFileExists(ctx, katiEnabledMarker)
+ }
}
var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
@@ -96,8 +109,11 @@
{{end -}}
pool highmem_pool
depth = {{.HighmemParallel}}
-{{if and (not .SkipKatiNinja) .HasKatiSuffix}}subninja {{.KatiBuildNinjaFile}}
+{{if and (not .SkipKatiNinja) .HasKatiSuffix}}
+subninja {{.KatiBuildNinjaFile}}
subninja {{.KatiPackageNinjaFile}}
+{{else}}
+subninja {{.KatiSoongOnlyPackageNinjaFile}}
{{end -}}
subninja {{.SoongNinjaFile}}
`))
@@ -315,10 +331,16 @@
if what&RunProductConfig != 0 {
runMakeProductConfig(ctx, config)
+
+ // Re-evaluate what to run because there are product variables that control how
+ // soong and make are run.
+ what = evaluateWhatToRun(config, ctx.Verboseln)
}
// Everything below here depends on product config.
+ SetupKatiEnabledMarker(ctx, config)
+
if inList("installclean", config.Arguments()) ||
inList("install-clean", config.Arguments()) {
logArgsOtherThan("installclean", "install-clean")
@@ -335,25 +357,31 @@
return
}
+ // Still generate the kati suffix in soong-only builds because soong-only still uses kati for
+ // the packaging step. Also, the kati suffix is used for the combined ninja file.
+ genKatiSuffix(ctx, config)
+
if what&RunSoong != 0 {
runSoong(ctx, config)
}
if what&RunKati != 0 {
- genKatiSuffix(ctx, config)
runKatiCleanSpec(ctx, config)
runKatiBuild(ctx, config)
- runKatiPackage(ctx, config)
+ runKatiPackage(ctx, config, false)
- ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
} else if what&RunKatiNinja != 0 {
// Load last Kati Suffix if it exists
- if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
+ if katiSuffix, err := os.ReadFile(config.LastKatiSuffixFile()); err == nil {
ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
config.SetKatiSuffix(string(katiSuffix))
}
+ } else if what&RunSoong != 0 {
+ runKatiPackage(ctx, config, true)
}
+ os.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
+
// Write combined ninja file
createCombinedBuildNinjaFile(ctx, config)
@@ -373,6 +401,7 @@
if what&RunKati != 0 {
installCleanIfNecessary(ctx, config)
}
+ partialCompileCleanIfNecessary(ctx, config)
runNinjaForBuild(ctx, config)
updateBuildIdDir(ctx, config)
}
@@ -399,6 +428,9 @@
if config.Checkbuild() {
what |= RunBuildTests
}
+ if value, ok := config.environ.Get("RUN_BUILD_TESTS"); ok && value == "true" {
+ what |= RunBuildTests
+ }
if !config.SkipConfig() {
what |= RunProductConfig
} else {
@@ -502,4 +534,5 @@
// Be careful, anything added here slows down EVERY CI build
func runDistActions(ctx Context, config Config) {
runStagingSnapshot(ctx, config)
+ runSourceInputs(ctx, config)
}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 46e38c9..3df8b7a 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -219,6 +219,52 @@
writeConfig()
}
+// When SOONG_USE_PARTIAL_COMPILE transitions from on to off, we need to remove
+// all files which were potentially built with partial compile, so that they
+// get rebuilt with that turned off.
+func partialCompileCleanIfNecessary(ctx Context, config Config) {
+ configFile := config.DevicePreviousUsePartialCompile()
+ currentValue, _ := config.Environment().Get("SOONG_USE_PARTIAL_COMPILE")
+
+ ensureDirectoriesExist(ctx, filepath.Dir(configFile))
+
+ writeValue := func() {
+ err := ioutil.WriteFile(configFile, []byte(currentValue), 0666) // a+rw
+ if err != nil {
+ ctx.Fatalln("Failed to write use partial compile config:", err)
+ }
+ }
+
+ previousValueBytes, err := ioutil.ReadFile(configFile)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // Just write the new config file, no old config file to worry about.
+ writeValue()
+ return
+ } else {
+ ctx.Fatalln("Failed to read previous use partial compile config:", err)
+ }
+ }
+
+ previousValue := string(previousValueBytes)
+ switch previousValue {
+ case currentValue:
+ // Same value as before - nothing left to do here.
+ return
+ case "true":
+ // Transitioning from on to off. Build (phony) target: partialcompileclean.
+ ctx.BeginTrace(metrics.PrimaryNinja, "partialcompileclean")
+ defer ctx.EndTrace()
+
+ ctx.Printf("SOONG_USE_PARTIAL_COMPILE turned off, forcing partialcompileclean\n")
+
+ runNinja(ctx, config, []string{"partialcompileclean"})
+ default:
+ // Transitioning from off to on. Nothing to do in this case.
+ }
+ writeValue()
+}
+
// cleanOldFiles takes an input file (with all paths relative to basePath), and removes files from
// the filesystem if they were removed from the input file since the last execution.
func cleanOldFiles(ctx Context, basePath, newFile string) {
diff --git a/ui/build/config.go b/ui/build/config.go
index 209404e..94b0781 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -63,6 +63,7 @@
NINJA_NINJA
NINJA_N2
NINJA_SISO
+ NINJA_NINJAGO
)
type Config struct{ *configImpl }
@@ -77,26 +78,31 @@
logsPrefix string
// From the arguments
- parallel int
- keepGoing int
- verbose bool
- checkbuild bool
- dist bool
- jsonModuleGraph bool
- reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
- soongDocs bool
- skipConfig bool
- skipKati bool
- skipKatiNinja bool
- skipSoong bool
- skipNinja bool
- skipSoongTests bool
- searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
- skipMetricsUpload bool
- buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
- buildFromSourceStub bool
- incrementalBuildActions bool
- ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
+ parallel int
+ keepGoing int
+ verbose bool
+ checkbuild bool
+ dist bool
+ jsonModuleGraph bool
+ reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
+ soongDocs bool
+ skipConfig bool
+ // Either the user or product config requested that we skip soong (for the banner). The other
+ // skip flags tell whether *this* soong_ui invocation will skip kati - which will be true
+ // during lunch.
+ soongOnlyRequested bool
+ skipKati bool
+ skipKatiControlledByFlags bool
+ skipKatiNinja bool
+ skipSoong bool
+ skipNinja bool
+ skipSoongTests bool
+ searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
+ skipMetricsUpload bool
+ buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
+ buildFromSourceStub bool
+ incrementalBuildActions bool
+ ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
// From the product config
katiArgs []string
@@ -250,6 +256,19 @@
}
ret.parseArgs(ctx, args)
+ if value, ok := ret.environ.Get("SOONG_ONLY"); ok && !ret.skipKatiControlledByFlags {
+ if value == "true" || value == "1" || value == "y" || value == "yes" {
+ ret.soongOnlyRequested = true
+ ret.skipKatiControlledByFlags = true
+ ret.skipKati = true
+ ret.skipKatiNinja = true
+ } else {
+ ret.skipKatiControlledByFlags = true
+ ret.skipKati = false
+ ret.skipKatiNinja = false
+ }
+ }
+
if ret.ninjaWeightListSource == HINT_FROM_SOONG {
ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "always")
} else if ret.ninjaWeightListSource == DEFAULT {
@@ -308,16 +327,13 @@
// If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
// This simplifies the generated Ninja rules, so that they only need to check for the empty string.
- if value, ok := os.LookupEnv("SOONG_USE_PARTIAL_COMPILE"); ok {
+ if value, ok := ret.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
if value == "true" || value == "1" || value == "y" || value == "yes" {
value = "true"
} else {
value = ""
}
- err = os.Setenv("SOONG_USE_PARTIAL_COMPILE", value)
- if err != nil {
- ctx.Fatalln("Failed to set SOONG_USE_PARTIAL_COMPILE: %v", err)
- }
+ ret.environ.Set("SOONG_USE_PARTIAL_COMPILE", value)
}
ret.ninjaCommand = NINJA_NINJA
@@ -326,6 +342,8 @@
ret.ninjaCommand = NINJA_N2
case "siso":
ret.ninjaCommand = NINJA_SISO
+ case "ninjago":
+ ret.ninjaCommand = NINJA_NINJAGO
default:
if os.Getenv("SOONG_USE_N2") == "true" {
ret.ninjaCommand = NINJA_N2
@@ -392,6 +410,9 @@
// Use config.ninjaCommand instead.
"SOONG_NINJA",
"SOONG_USE_N2",
+
+ // Already incorporated into the config object
+ "SOONG_ONLY",
)
if ret.UseGoma() || ret.ForceUseGoma() {
@@ -598,11 +619,27 @@
}
func buildConfig(config Config) *smpb.BuildConfig {
+ var soongEnvVars *smpb.SoongEnvVars
+ ensure := func() *smpb.SoongEnvVars {
+ // Create soongEnvVars if it doesn't already exist.
+ if soongEnvVars == nil {
+ soongEnvVars = &smpb.SoongEnvVars{}
+ }
+ return soongEnvVars
+ }
+ if value, ok := config.environ.Get("SOONG_PARTIAL_COMPILE"); ok {
+ ensure().PartialCompile = proto.String(value)
+ }
+ if value, ok := config.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
+ ensure().UsePartialCompile = proto.String(value)
+ }
c := &smpb.BuildConfig{
ForceUseGoma: proto.Bool(config.ForceUseGoma()),
UseGoma: proto.Bool(config.UseGoma()),
UseRbe: proto.Bool(config.UseRBE()),
NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
+ SoongEnvVars: soongEnvVars,
+ SoongOnly: proto.Bool(config.soongOnlyRequested),
}
c.Targets = append(c.Targets, config.arguments...)
@@ -831,15 +868,21 @@
c.emptyNinjaFile = true
} else if arg == "--skip-ninja" {
c.skipNinja = true
- } else if arg == "--skip-make" {
- // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
- // but it does run a Kati ninja file if the .kati_enabled marker file was created
- // by a previous build.
- c.skipConfig = true
- c.skipKati = true
} else if arg == "--soong-only" {
+ if c.skipKatiControlledByFlags {
+ ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
+ }
+ c.soongOnlyRequested = true
+ c.skipKatiControlledByFlags = true
c.skipKati = true
c.skipKatiNinja = true
+ } else if arg == "--no-soong-only" {
+ if c.skipKatiControlledByFlags {
+ ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
+ }
+ c.skipKatiControlledByFlags = true
+ c.skipKati = false
+ c.skipKatiNinja = false
} else if arg == "--config-only" {
c.skipKati = true
c.skipKatiNinja = true
@@ -1058,7 +1101,7 @@
func (c *configImpl) NinjaArgs() []string {
if c.skipKati {
- return c.arguments
+ return append(c.arguments, c.ninjaArgs...)
}
return c.ninjaArgs
}
@@ -1074,11 +1117,18 @@
func (c *configImpl) PrebuiltOS() string {
switch runtime.GOOS {
case "linux":
- return "linux-x86"
+ switch runtime.GOARCH {
+ case "amd64":
+ return "linux-x86"
+ case "arm64":
+ return "linux-arm64"
+ default:
+ panic(fmt.Errorf("Unknown GOARCH %s", runtime.GOARCH))
+ }
case "darwin":
return "darwin-x86"
default:
- panic("Unknown GOOS")
+ panic(fmt.Errorf("Unknown GOOS %s", runtime.GOOS))
}
}
@@ -1327,6 +1377,10 @@
}
func (c *configImpl) UseABFS() bool {
+ if c.ninjaCommand == NINJA_NINJAGO {
+ return true
+ }
+
if v, ok := c.environ.Get("NO_ABFS"); ok {
v = strings.ToLower(strings.TrimSpace(v))
if v == "true" || v == "1" {
@@ -1580,6 +1634,10 @@
return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
}
+func (c *configImpl) KatiSoongOnlyPackageNinjaFile() string {
+ return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiSoongOnlyPackageSuffix+".ninja")
+}
+
func (c *configImpl) SoongVarsFile() string {
targetProduct, err := c.TargetProductOrErr()
if err != nil {
@@ -1634,8 +1692,12 @@
return filepath.Join(c.ProductOut(), "previous_build_config.mk")
}
+func (c *configImpl) DevicePreviousUsePartialCompile() string {
+ return filepath.Join(c.ProductOut(), "previous_use_partial_compile.txt")
+}
+
func (c *configImpl) KatiPackageMkDir() string {
- return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
+ return filepath.Join(c.SoongOutDir(), "kati_packaging"+c.KatiSuffix())
}
func (c *configImpl) hostOutRoot() string {
@@ -1656,13 +1718,7 @@
}
func (c *configImpl) HostPrebuiltTag() string {
- if runtime.GOOS == "linux" {
- return "linux-x86"
- } else if runtime.GOOS == "darwin" {
- return "darwin-x86"
- } else {
- panic("Unsupported OS")
- }
+ return c.PrebuiltOS()
}
func (c *configImpl) KatiBin() string {
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index b42edb0..10de1ad 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -30,8 +30,6 @@
smpb "android/soong/ui/metrics/metrics_proto"
"android/soong/ui/status"
- "google.golang.org/protobuf/encoding/prototext"
-
"google.golang.org/protobuf/proto"
)
@@ -1006,6 +1004,12 @@
}
}
+func assertEquals[T ~bool | ~int32](t *testing.T, name string, expected, actual T) {
+ if expected != actual {
+ t.Errorf("Expected %s: %#v\nActual %s: %#v", name, expected, name, actual)
+ }
+}
+
func TestBuildConfig(t *testing.T) {
tests := []struct {
name string
@@ -1063,12 +1067,11 @@
arguments: tc.arguments,
}
config := Config{c}
- actualBuildConfig := buildConfig(config)
- if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
- t.Errorf("Build config mismatch.\n"+
- "Expected build config: %#v\n"+
- "Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig))
- }
+ actual := buildConfig(config)
+ assertEquals(t, "ForceUseGoma", *tc.expectedBuildConfig.ForceUseGoma, *actual.ForceUseGoma)
+ assertEquals(t, "UseGoma", *tc.expectedBuildConfig.UseGoma, *actual.UseGoma)
+ assertEquals(t, "UseRbe", *tc.expectedBuildConfig.UseRbe, *actual.UseRbe)
+ assertEquals(t, "NinjaWeightListSource", *tc.expectedBuildConfig.NinjaWeightListSource, *actual.NinjaWeightListSource)
})
}
}
diff --git a/ui/build/context.go b/ui/build/context.go
index fd20e26..69e5f96 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -18,6 +18,7 @@
"context"
"io"
+ "android/soong/ui/execution_metrics"
"android/soong/ui/logger"
"android/soong/ui/metrics"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -33,7 +34,8 @@
context.Context
logger.Logger
- Metrics *metrics.Metrics
+ Metrics *metrics.Metrics
+ ExecutionMetrics *execution_metrics.ExecutionMetrics
Writer io.Writer
Status *status.Status
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 06b1185..0f1a3dd 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -137,6 +137,12 @@
}
}
if ctx.Metrics != nil {
+ // Also include TARGET_RELEASE in the metrics. Do this first
+ // so that it gets overwritten if dumpvars ever spits it out.
+ if release, found := os.LookupEnv("TARGET_RELEASE"); found {
+ ctx.Metrics.SetMetadataMetrics(
+ map[string]string{"TARGET_RELEASE": release})
+ }
ctx.Metrics.SetMetadataMetrics(ret)
}
@@ -167,7 +173,7 @@
"ROM_BUILDTYPE",
}
-func Banner(make_vars map[string]string) string {
+func Banner(config Config, make_vars map[string]string) string {
b := &bytes.Buffer{}
fmt.Fprintln(b, "============================================")
@@ -176,6 +182,12 @@
fmt.Fprintf(b, "%s=%s\n", name, make_vars[name])
}
}
+ if config.skipKatiControlledByFlags {
+ fmt.Fprintf(b, "SOONG_ONLY=%t\n", config.soongOnlyRequested)
+ } else { // default for this product
+ fmt.Fprintf(b, "SOONG_ONLY=%t\n", make_vars["PRODUCT_SOONG_ONLY"] == "true")
+ }
+
fmt.Fprint(b, "============================================")
return b.String()
@@ -241,6 +253,8 @@
// `true` will relegate missing outputs to warnings.
"BUILD_BROKEN_MISSING_OUTPUTS",
+ "PRODUCT_SOONG_ONLY",
+
// Not used, but useful to be in the soong.log
"TARGET_BUILD_TYPE",
"HOST_ARCH",
@@ -274,6 +288,7 @@
"BUILD_BROKEN_USES_BUILD_SHARED_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
+ "RELEASE_BUILD_EXECUTION_METRICS",
}, exportEnvVars...), BannerVars...)
makeVars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
@@ -281,13 +296,8 @@
ctx.Fatalln("Error dumping make vars:", err)
}
- env := config.Environment()
- // Print the banner like make does
- if !env.IsEnvTrue("ANDROID_QUIET_BUILD") {
- fmt.Fprintln(ctx.Writer, Banner(makeVars))
- }
-
// Populate the environment
+ env := config.Environment()
for _, name := range exportEnvVars {
if makeVars[name] == "" {
env.Unset(name)
@@ -308,4 +318,17 @@
config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(makeVars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
config.SetSourceRootDirs(strings.Fields(makeVars["PRODUCT_SOURCE_ROOT_DIRS"]))
config.SetBuildBrokenMissingOutputs(makeVars["BUILD_BROKEN_MISSING_OUTPUTS"] == "true")
+
+ if !config.skipKatiControlledByFlags {
+ if makeVars["PRODUCT_SOONG_ONLY"] == "true" {
+ config.soongOnlyRequested = true
+ config.skipKati = true
+ config.skipKatiNinja = true
+ }
+ }
+
+ // Print the banner like make did
+ if !env.IsEnvTrue("ANDROID_QUIET_BUILD") {
+ fmt.Fprintln(ctx.Writer, Banner(config, makeVars))
+ }
}
diff --git a/ui/build/finder.go b/ui/build/finder.go
index da7f255..ff8908b 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -84,8 +84,14 @@
// METADATA file of packages
"METADATA",
},
- // .mk files for product/board configuration.
- IncludeSuffixes: []string{".mk"},
+ IncludeSuffixes: []string{
+ // .mk files for product/board configuration.
+ ".mk",
+ // otatools cert files
+ ".pk8",
+ ".pem",
+ ".avbpubkey",
+ },
}
dumpDir := config.FileListDir()
f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
@@ -118,6 +124,18 @@
return entries.DirNames, matches
}
+func findOtaToolsCertFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
+ matches := []string{}
+ for _, foundName := range entries.FileNames {
+ if strings.HasSuffix(foundName, ".pk8") ||
+ strings.HasSuffix(foundName, ".pem") ||
+ strings.HasSuffix(foundName, ".avbpubkey") {
+ matches = append(matches, foundName)
+ }
+ }
+ return entries.DirNames, matches
+}
+
// FindSources searches for source files known to <f> and writes them to the filesystem for
// use later.
func FindSources(ctx Context, config Config, f *finder.Finder) {
@@ -128,7 +146,7 @@
// Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
- androidMks = ignoreNdkAndroidMks(androidMks)
+ androidMks = ignoreSomeAndroidMks(androidMks)
blockAndroidMks(ctx, androidMks)
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
@@ -184,6 +202,17 @@
ctx.Fatalf("Could not find TEST_MAPPING: %v", err)
}
+ // Recursively look for all otatools cert files.
+ otatools_cert_files := f.FindMatching("build/make/target/product/security", findOtaToolsCertFiles)
+ otatools_cert_files = append(otatools_cert_files, f.FindMatching("device", findOtaToolsCertFiles)...)
+ otatools_cert_files = append(otatools_cert_files, f.FindMatching("external/avb/test/data", findOtaToolsCertFiles)...)
+ otatools_cert_files = append(otatools_cert_files, f.FindMatching("packages/modules", findOtaToolsCertFiles)...)
+ otatools_cert_files = append(otatools_cert_files, f.FindMatching("vendor", findOtaToolsCertFiles)...)
+ err = dumpListToFile(ctx, config, otatools_cert_files, filepath.Join(dumpDir, "OtaToolsCertFiles.list"))
+ if err != nil {
+ ctx.Fatalf("Could not find otatools cert files: %v", err)
+ }
+
// Recursively look for all Android.bp files
androidBps := f.FindNamedAt(".", "Android.bp")
if len(androidBps) == 0 {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 4dfb710..6519573 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -31,6 +31,7 @@
const katiBuildSuffix = ""
const katiCleanspecSuffix = "-cleanspec"
const katiPackageSuffix = "-package"
+const katiSoongOnlyPackageSuffix = "-soong-only-package"
// genKatiSuffix creates a filename suffix for kati-generated files so that we
// can cache them based on their inputs. Such files include the generated Ninja
@@ -40,8 +41,12 @@
// Currently that includes the TARGET_PRODUCT and kati-processed command line
// arguments.
func genKatiSuffix(ctx Context, config Config) {
+ targetProduct := "unknown"
+ if p, err := config.TargetProductOrErr(); err == nil {
+ targetProduct = p
+ }
// Construct the base suffix.
- katiSuffix := "-" + config.TargetProduct() + config.CoverageSuffix()
+ katiSuffix := "-" + targetProduct + config.CoverageSuffix()
// Append kati arguments to the suffix.
if args := config.KatiArgs(); len(args) > 0 {
@@ -68,13 +73,13 @@
func writeValueIfChanged(ctx Context, config Config, dir string, filename string, value string) {
filePath := filepath.Join(dir, filename)
previousValue := ""
- rawPreviousValue, err := ioutil.ReadFile(filePath)
+ rawPreviousValue, err := os.ReadFile(filePath)
if err == nil {
previousValue = string(rawPreviousValue)
}
if previousValue != value {
- if err = ioutil.WriteFile(filePath, []byte(value), 0666); err != nil {
+ if err = os.WriteFile(filePath, []byte(value), 0666); err != nil {
ctx.Fatalf("Failed to write: %v", err)
}
}
@@ -200,18 +205,10 @@
// fi
cmd.Environment.Unset("SOONG_USE_PARTIAL_COMPILE")
- hostname, ok := cmd.Environment.Get("BUILD_HOSTNAME")
// Unset BUILD_HOSTNAME during kati run to avoid kati rerun, kati will use BUILD_HOSTNAME from a file.
cmd.Environment.Unset("BUILD_HOSTNAME")
- if !ok {
- hostname, err = os.Hostname()
- if err != nil {
- ctx.Println("Failed to read hostname:", err)
- hostname = "unknown"
- }
- }
- writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname)
- _, ok = cmd.Environment.Get("BUILD_NUMBER")
+
+ _, ok := cmd.Environment.Get("BUILD_NUMBER")
// Unset BUILD_NUMBER during kati run to avoid kati rerun, kati will use BUILD_NUMBER from a file.
cmd.Environment.Unset("BUILD_NUMBER")
if ok {
@@ -342,10 +339,19 @@
// Generate the Ninja file containing the packaging command lines for the dist
// dir.
-func runKatiPackage(ctx Context, config Config) {
+func runKatiPackage(ctx Context, config Config, soongOnly bool) {
ctx.BeginTrace(metrics.RunKati, "kati package")
defer ctx.EndTrace()
+ entryPoint := "build/make/packaging/main.mk"
+ suffix := katiPackageSuffix
+ ninjaFile := config.KatiPackageNinjaFile()
+ if soongOnly {
+ entryPoint = "build/make/packaging/main_soong_only.mk"
+ suffix = katiSoongOnlyPackageSuffix
+ ninjaFile = config.KatiSoongOnlyPackageNinjaFile()
+ }
+
args := []string{
// Mark the dist dir as writable.
"--writable", config.DistDir() + "/",
@@ -354,14 +360,14 @@
// Fail when redefining / duplicating a target.
"--werror_overriding_commands",
// Entry point.
- "-f", "build/make/packaging/main.mk",
+ "-f", entryPoint,
// Directory containing .mk files for packaging purposes, such as
// the dist.mk file, containing dist-for-goals data.
"KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(),
}
// Run Kati against a restricted set of environment variables.
- runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) {
+ runKati(ctx, config, suffix, args, func(env *Environment) {
env.Allow([]string{
// Some generic basics
"LANG",
@@ -389,7 +395,7 @@
})
// Compress and dist the packaging Ninja file.
- distGzipFile(ctx, config, config.KatiPackageNinjaFile())
+ distGzipFile(ctx, config, ninjaFile)
}
// Run Kati on the cleanspec files to clean the build.
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index f5f637f..e2a568f 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -17,6 +17,7 @@
import (
"fmt"
"os"
+ "os/exec"
"path/filepath"
"sort"
"strconv"
@@ -35,10 +36,16 @@
ninjaWeightListFileName = ".ninja_weight_list"
)
+// Runs ninja with the arguments from the command line, as found in
+// config.NinjaArgs().
+func runNinjaForBuild(ctx Context, config Config) {
+ runNinja(ctx, config, config.NinjaArgs())
+}
+
// Constructs and runs the Ninja command line with a restricted set of
// environment variables. It's important to restrict the environment Ninja runs
// for hermeticity reasons, and to avoid spurious rebuilds.
-func runNinjaForBuild(ctx Context, config Config) {
+func runNinja(ctx Context, config Config, ninjaArgs []string) {
ctx.BeginTrace(metrics.PrimaryNinja, "ninja")
defer ctx.EndTrace()
@@ -75,7 +82,7 @@
//"--frontend-file", fifo,
}
default:
- // NINJA_NINJA is the default.
+ // NINJA_NINJA or NINJA_NINJAGO.
executable = config.NinjaBin()
args = []string{
"-d", "keepdepfile",
@@ -87,7 +94,7 @@
"-w", "missingdepfile=err",
}
}
- args = append(args, config.NinjaArgs()...)
+ args = append(args, ninjaArgs...)
var parallel int
if config.UseRemoteBuild() {
@@ -243,7 +250,12 @@
"RUST_LOG",
// SOONG_USE_PARTIAL_COMPILE only determines which half of the rule we execute.
+ // When it transitions true => false, we build phony target "partialcompileclean",
+ // which removes all files that could have been created while it was true.
"SOONG_USE_PARTIAL_COMPILE",
+
+ // Directory for ExecutionMetrics
+ "SOONG_METRICS_AGGREGATION_DIR",
}, config.BuildBrokenNinjaUsesEnvVars()...)...)
}
@@ -256,6 +268,10 @@
// Only set RUST_BACKTRACE for n2.
}
+ // Set up the metrics aggregation directory.
+ ctx.ExecutionMetrics.SetDir(filepath.Join(config.OutDir(), "soong", "metrics_aggregation"))
+ cmd.Environment.Set("SOONG_METRICS_AGGREGATION_DIR", ctx.ExecutionMetrics.MetricsAggregationDir)
+
// Print the environment variables that Ninja is operating in.
ctx.Verboseln("Ninja environment: ")
envVars := cmd.Environment.Environ()
@@ -300,6 +316,8 @@
}
}()
+ ctx.ExecutionMetrics.Start()
+ defer ctx.ExecutionMetrics.Finish(ctx)
ctx.Status.Status("Starting ninja...")
cmd.RunAndStreamOrFatal()
}
@@ -339,3 +357,46 @@
}
c.prevModTime = newModTime
}
+
+// Constructs and runs the Ninja command line to get the inputs of a goal.
+// For n2 and siso, this will always run ninja, because they don't have the
+// `-t inputs` command. This command will use the inputs command's -d option,
+// to use the dep file iff ninja was the executor. For other executors, the
+// results will be wrong.
+func runNinjaInputs(ctx Context, config Config, goal string) ([]string, error) {
+ var executable string
+ switch config.ninjaCommand {
+ case NINJA_N2, NINJA_SISO:
+ executable = config.PrebuiltBuildTool("ninja")
+ default:
+ executable = config.NinjaBin()
+ }
+
+ args := []string{
+ "-f",
+ config.CombinedNinjaFile(),
+ "-t",
+ "inputs",
+ }
+ // Add deps file arg for ninja
+ // TODO: Update as inputs command is implemented
+ if config.ninjaCommand == NINJA_NINJA && !config.UseABFS() {
+ args = append(args, "-d")
+ }
+ args = append(args, goal)
+
+ // This is just ninja -t inputs, so we won't bother running it in the sandbox,
+ // so use exec.Command, not soong_ui's command.
+ cmd := exec.Command(executable, args...)
+
+ cmd.Stdin = os.Stdin
+ cmd.Stderr = os.Stderr
+
+ out, err := cmd.Output()
+ if err != nil {
+ fmt.Printf("Error getting goal inputs for %s: %s\n", goal, err)
+ return nil, err
+ }
+
+ return strings.Split(strings.TrimSpace(string(out)), "\n"), nil
+}
diff --git a/ui/build/path.go b/ui/build/path.go
index cc1d7e9..b92d799 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -20,7 +20,6 @@
"os"
"os/exec"
"path/filepath"
- "runtime"
"strings"
"github.com/google/blueprint/microfactory"
@@ -122,7 +121,7 @@
myPath, _ = filepath.Abs(myPath)
// Set up the checked-in prebuilts path directory for the current host OS.
- prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
+ prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + config.PrebuiltOS())
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
// Set $PATH to be the directories containing the host tool symlinks, and
@@ -258,7 +257,7 @@
// We put some prebuilts in $PATH, since it's infeasible to add dependencies
// for all of them.
- prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
+ prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + config.PrebuiltOS())
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
// Replace the $PATH variable with the path_interposer symlinks, and
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index a532e6d..bd7f3d0 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -42,7 +42,7 @@
}
// This tool is specifically disallowed and calling it will result in an
-// "executable no found" error.
+// "executable not found" error.
var Forbidden = PathConfig{
Symlink: false,
Log: true,
@@ -124,6 +124,10 @@
"ld.bfd": Forbidden,
"ld.gold": Forbidden,
"pkg-config": Forbidden,
+ "python": Forbidden,
+ "python2": Forbidden,
+ "python2.7": Forbidden,
+ "python3": Forbidden,
// These are toybox tools that only work on Linux.
"pgrep": LinuxOnlyPrebuilt,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 0963f76..58334a9 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -197,6 +197,8 @@
func (pb PrimaryBuilderFactory) primaryBuilderInvocation(config Config) bootstrap.PrimaryBuilderInvocation {
commonArgs := make([]string, 0, 0)
+ commonArgs = append(commonArgs, "--kati_suffix", config.KatiSuffix())
+
if !pb.config.skipSoongTests {
commonArgs = append(commonArgs, "-t")
}
@@ -501,7 +503,7 @@
tf := filepath.Join(outDir, ".top")
defer func() {
if err := os.WriteFile(tf, []byte(cwd), 0644); err != nil {
- fmt.Fprintf(os.Stderr, fmt.Sprintf("Unable to log CWD: %v", err))
+ fmt.Fprintf(os.Stderr, "Unable to log CWD: %v", err)
}
}()
diff --git a/ui/build/source_inputs.go b/ui/build/source_inputs.go
new file mode 100644
index 0000000..d1cc1a2
--- /dev/null
+++ b/ui/build/source_inputs.go
@@ -0,0 +1,100 @@
+package build
+
+import (
+ "compress/gzip"
+ "fmt"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "android/soong/shared"
+ "android/soong/ui/metrics"
+)
+
+func sortedStringSetKeys(m map[string]bool) []string {
+ result := make([]string, 0, len(m))
+ for key := range m {
+ result = append(result, key)
+ }
+ sort.Strings(result)
+ return result
+}
+
+func addSlash(str string) string {
+ if len(str) == 0 {
+ return ""
+ }
+ if str[len(str)-1] == '/' {
+ return str
+ }
+ return str + "/"
+}
+
+func hasPrefixStrings(str string, prefixes []string) bool {
+ for _, prefix := range prefixes {
+ if strings.HasPrefix(str, prefix) {
+ return true
+ }
+ }
+ return false
+}
+
+// Output DIST_DIR/source_inputs.txt.gz, which will contain a listing of the files
+// in the source tree (not including in the out directory) that were declared as ninja
+// inputs to the build that was just done.
+func runSourceInputs(ctx Context, config Config) {
+ ctx.BeginTrace(metrics.RunSoong, "runSourceInputs")
+ defer ctx.EndTrace()
+
+ success := false
+ outputFilename := shared.JoinPath(config.RealDistDir(), "source_inputs.txt.gz")
+
+ outputFile, err := os.Create(outputFilename)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "source_files_used: unable to open file for write: %s\n", outputFilename)
+ return
+ }
+ defer func() {
+ outputFile.Close()
+ if !success {
+ os.Remove(outputFilename)
+ }
+ }()
+
+ output := gzip.NewWriter(outputFile)
+ defer output.Close()
+
+ // Skip out dir, both absolute and relative. There are some files
+ // generated during analysis that ninja thinks are inputs not intermediates.
+ absOut, _ := filepath.Abs(config.OutDir())
+ excludes := []string{
+ addSlash(config.OutDir()),
+ addSlash(absOut),
+ }
+
+ goals := config.NinjaArgs()
+
+ result := make(map[string]bool)
+ for _, goal := range goals {
+ inputs, err := runNinjaInputs(ctx, config, goal)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "source_files_used: %v\n", err)
+ return
+ }
+
+ for _, filename := range inputs {
+ if !hasPrefixStrings(filename, excludes) {
+ result[filename] = true
+ }
+ }
+ }
+
+ for _, filename := range sortedStringSetKeys(result) {
+ output.Write([]byte(filename))
+ output.Write([]byte("\n"))
+ }
+
+ output.Flush()
+ success = true
+}
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index ba53119..87bec93 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -76,8 +76,10 @@
// treated as an source file.
dexpreoptConfigFilePath := filepath.Join(outDir, "soong", "dexpreopt.config")
- // out/build_date.txt is considered a "source file"
+ // out/build_(date|hostname|number).txt is considered a "source file"
buildDatetimeFilePath := filepath.Join(outDir, "build_date.txt")
+ buildHostnameFilePath := filepath.Join(outDir, "soong", "build_hostname.txt")
+ buildNumberFilePath := filepath.Join(outDir, "soong", "build_number.txt")
// release-config files are generated from the initial lunch or Kati phase
// before running soong and ninja.
@@ -102,6 +104,8 @@
line == extraVariablesFilePath ||
line == dexpreoptConfigFilePath ||
line == buildDatetimeFilePath ||
+ line == buildHostnameFilePath ||
+ line == buildNumberFilePath ||
strings.HasPrefix(line, releaseConfigDir) ||
buildFingerPrintFilePattern.MatchString(line) {
// Leaf node is in one of Soong's bootstrap directories, which do not have
@@ -151,7 +155,7 @@
ts.FinishAction(status.ActionResult{
Action: action,
- Error: fmt.Errorf(title),
+ Error: fmt.Errorf("%s", title),
Output: sb.String(),
})
ctx.Fatal("stopping")
diff --git a/ui/execution_metrics/Android.bp b/ui/execution_metrics/Android.bp
new file mode 100644
index 0000000..542e550
--- /dev/null
+++ b/ui/execution_metrics/Android.bp
@@ -0,0 +1,35 @@
+// Copyright 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-ui-execution-metrics",
+ pkgPath: "android/soong/ui/execution_metrics",
+ deps: [
+ "golang-protobuf-proto",
+ "soong-shared",
+ "soong-ui-logger",
+ "soong-ui-execution_metrics_proto",
+ "soong-ui-metrics_proto",
+ "soong-cmd-find_input_delta-proto",
+ ],
+ srcs: [
+ "execution_metrics.go",
+ ],
+ testSrcs: [
+ ],
+}
diff --git a/ui/execution_metrics/execution_metrics.go b/ui/execution_metrics/execution_metrics.go
new file mode 100644
index 0000000..db78449
--- /dev/null
+++ b/ui/execution_metrics/execution_metrics.go
@@ -0,0 +1,279 @@
+// 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 execution_metrics represents the metrics system for Android Platform Build Systems.
+package execution_metrics
+
+// This is the main heart of the metrics system for Android Platform Build Systems.
+// The starting of the soong_ui (cmd/soong_ui/main.go), the metrics system is
+// initialized by the invocation of New and is then stored in the context
+// (ui/build/context.go) to be used throughout the system. During the build
+// initialization phase, several functions in this file are invoked to store
+// information such as the environment, build configuration and build metadata.
+// There are several scoped code that has Begin() and defer End() functions
+// that captures the metrics and is them added as a perfInfo into the set
+// of the collected metrics. Finally, when soong_ui has finished the build,
+// the defer Dump function is invoked to store the collected metrics to the
+// raw protobuf file in the $OUT directory and this raw protobuf file will be
+// uploaded to the destination. See ui/build/upload.go for more details. The
+// filename of the raw protobuf file and the list of files to be uploaded is
+// defined in cmd/soong_ui/main.go. See ui/metrics/event.go for the explanation
+// of what an event is and how the metrics system is a stack based system.
+
+import (
+ "context"
+ "io/fs"
+ "maps"
+ "os"
+ "path/filepath"
+ "slices"
+ "sync"
+
+ "android/soong/ui/logger"
+
+ fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
+ "android/soong/ui/metrics"
+ soong_execution_proto "android/soong/ui/metrics/execution_metrics_proto"
+ soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
+ "google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/proto"
+)
+
+type ExecutionMetrics struct {
+ MetricsAggregationDir string
+ ctx context.Context
+ logger logger.Logger
+ waitGroup sync.WaitGroup
+ fileList *fileList
+}
+
+type fileList struct {
+ totalChanges uint32
+ changes fileChanges
+ seenFiles map[string]bool
+}
+
+type fileChanges struct {
+ additions changeInfo
+ deletions changeInfo
+ modifications changeInfo
+}
+
+type fileChangeCounts struct {
+ additions uint32
+ deletions uint32
+ modifications uint32
+}
+
+type changeInfo struct {
+ total uint32
+ list []string
+ byExtension map[string]uint32
+}
+
+var MAXIMUM_FILES uint32 = 50
+
+// Setup the handler for SoongExecutionMetrics.
+func NewExecutionMetrics(log logger.Logger) *ExecutionMetrics {
+ return &ExecutionMetrics{
+ logger: log,
+ fileList: &fileList{seenFiles: make(map[string]bool)},
+ }
+}
+
+// Save the path for ExecutionMetrics communications.
+func (c *ExecutionMetrics) SetDir(path string) {
+ c.MetricsAggregationDir = path
+}
+
+// Start collecting SoongExecutionMetrics.
+func (c *ExecutionMetrics) Start() {
+ if c.MetricsAggregationDir == "" {
+ return
+ }
+
+ tmpDir := c.MetricsAggregationDir + ".rm"
+ if _, err := fs.Stat(os.DirFS("."), c.MetricsAggregationDir); err == nil {
+ if err = os.RemoveAll(tmpDir); err != nil {
+ c.logger.Fatalf("Failed to remove %s: %v", tmpDir, err)
+ }
+ if err = os.Rename(c.MetricsAggregationDir, tmpDir); err != nil {
+ c.logger.Fatalf("Failed to rename %s to %s: %v", c.MetricsAggregationDir, tmpDir)
+ }
+ }
+ if err := os.MkdirAll(c.MetricsAggregationDir, 0777); err != nil {
+ c.logger.Fatalf("Failed to create %s: %v", c.MetricsAggregationDir)
+ }
+
+ c.waitGroup.Add(1)
+ go func(d string) {
+ defer c.waitGroup.Done()
+ os.RemoveAll(d)
+ }(tmpDir)
+
+ c.logger.Verbosef("ExecutionMetrics running\n")
+}
+
+type hasTrace interface {
+ BeginTrace(name, desc string)
+ EndTrace()
+}
+
+// Aggregate any execution metrics.
+func (c *ExecutionMetrics) Finish(ctx hasTrace) {
+ ctx.BeginTrace(metrics.RunSoong, "execution_metrics.Finish")
+ defer ctx.EndTrace()
+ if c.MetricsAggregationDir == "" {
+ return
+ }
+ c.waitGroup.Wait()
+
+ // Find and process all of the metrics files.
+ aggFs := os.DirFS(c.MetricsAggregationDir)
+ fs.WalkDir(aggFs, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ c.logger.Fatalf("ExecutionMetrics.Finish: Error walking %s: %v", c.MetricsAggregationDir, err)
+ }
+ if d.IsDir() {
+ return nil
+ }
+ path = filepath.Join(c.MetricsAggregationDir, path)
+ r, err := os.ReadFile(path)
+ if err != nil {
+ c.logger.Fatalf("ExecutionMetrics.Finish: Failed to read %s: %v", path, err)
+ }
+ msg := &soong_execution_proto.SoongExecutionMetrics{}
+ err = proto.Unmarshal(r, msg)
+ if err != nil {
+ c.logger.Verbosef("ExecutionMetrics.Finish: Error unmarshalling SoongExecutionMetrics message: %v\n", err)
+ return nil
+ }
+ switch {
+ case msg.GetFileList() != nil:
+ if err := c.fileList.aggregateFileList(msg.GetFileList()); err != nil {
+ c.logger.Verbosef("ExecutionMetrics.Finish: Error processing SoongExecutionMetrics message: %v\n", err)
+ }
+ // Status update for all others.
+ default:
+ tag, _ := protowire.ConsumeVarint(r)
+ id, _ := protowire.DecodeTag(tag)
+ c.logger.Verbosef("ExecutionMetrics.Finish: Unexpected SoongExecutionMetrics submessage id=%d\n", id)
+ }
+ return nil
+ })
+}
+
+func (fl *fileList) aggregateFileList(msg *fid_proto.FileList) error {
+ fl.updateChangeInfo(msg.GetAdditions(), &fl.changes.additions)
+ fl.updateChangeInfo(msg.GetDeletions(), &fl.changes.deletions)
+ fl.updateChangeInfo(msg.GetChanges(), &fl.changes.modifications)
+ return nil
+}
+
+func (fl *fileList) updateChangeInfo(list []string, info *changeInfo) {
+ for _, filename := range list {
+ if fl.seenFiles[filename] {
+ continue
+ }
+ fl.seenFiles[filename] = true
+ if info.total < MAXIMUM_FILES {
+ info.list = append(info.list, filename)
+ }
+ ext := filepath.Ext(filename)
+ if info.byExtension == nil {
+ info.byExtension = make(map[string]uint32)
+ }
+ info.byExtension[ext] += 1
+ info.total += 1
+ fl.totalChanges += 1
+ }
+}
+
+func (c *ExecutionMetrics) Dump(path string, args []string) error {
+ if c.MetricsAggregationDir == "" {
+ return nil
+ }
+ msg := c.GetMetrics(args)
+
+ if _, err := os.Stat(filepath.Dir(path)); err != nil {
+ if err = os.MkdirAll(filepath.Dir(path), 0775); err != nil {
+ return err
+ }
+ }
+ data, err := proto.Marshal(msg)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(path, data, 0644)
+}
+
+func (c *ExecutionMetrics) GetMetrics(args []string) *soong_metrics_proto.ExecutionMetrics {
+ return &soong_metrics_proto.ExecutionMetrics{
+ CommandArgs: args,
+ ChangedFiles: c.getChangedFiles(),
+ }
+}
+
+func (c *ExecutionMetrics) getChangedFiles() *soong_metrics_proto.AggregatedFileList {
+ fl := c.fileList
+ if fl == nil {
+ return nil
+ }
+ var count uint32
+ fileCounts := make(map[string]*soong_metrics_proto.FileCount)
+ ret := &soong_metrics_proto.AggregatedFileList{TotalDelta: proto.Uint32(c.fileList.totalChanges)}
+
+ // MAXIMUM_FILES is the upper bound on total file names reported.
+ if limit := min(MAXIMUM_FILES-min(MAXIMUM_FILES, count), fl.changes.additions.total); limit > 0 {
+ ret.Additions = fl.changes.additions.list[:limit]
+ count += limit
+ }
+ if limit := min(MAXIMUM_FILES-min(MAXIMUM_FILES, count), fl.changes.modifications.total); limit > 0 {
+ ret.Changes = fl.changes.modifications.list[:limit]
+ count += limit
+ }
+ if limit := min(MAXIMUM_FILES-min(MAXIMUM_FILES, count), fl.changes.deletions.total); limit > 0 {
+ ret.Deletions = fl.changes.deletions.list[:limit]
+ count += limit
+ }
+
+ addExt := func(key string) *soong_metrics_proto.FileCount {
+ // Create the fileCounts map entry if needed, and return the address to the caller.
+ if _, ok := fileCounts[key]; !ok {
+ fileCounts[key] = &soong_metrics_proto.FileCount{Extension: proto.String(key)}
+ }
+ return fileCounts[key]
+ }
+ addCount := func(loc **uint32, count uint32) {
+ if *loc == nil {
+ *loc = proto.Uint32(0)
+ }
+ **loc += count
+ }
+ for k, v := range fl.changes.additions.byExtension {
+ addCount(&addExt(k).Additions, v)
+ }
+ for k, v := range fl.changes.modifications.byExtension {
+ addCount(&addExt(k).Modifications, v)
+ }
+ for k, v := range fl.changes.deletions.byExtension {
+ addCount(&addExt(k).Deletions, v)
+ }
+
+ keys := slices.Sorted(maps.Keys(fileCounts))
+ for _, k := range keys {
+ ret.Counts = append(ret.Counts, fileCounts[k])
+ }
+ return ret
+}
diff --git a/ui/execution_metrics/execution_metrics_test.go b/ui/execution_metrics/execution_metrics_test.go
new file mode 100644
index 0000000..28fa973
--- /dev/null
+++ b/ui/execution_metrics/execution_metrics_test.go
@@ -0,0 +1,63 @@
+// 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 execution_metrics represents the metrics system for Android Platform Build Systems.
+package execution_metrics
+
+import (
+ "reflect"
+ "testing"
+
+ fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
+)
+
+func TestUpdateChangeInfo(t *testing.T) {
+ testCases := []struct {
+ Name string
+ Message *fid_proto.FileList
+ FileList *fileList
+ Expected *fileList
+ }{
+ {
+ Name: "various",
+ Message: &fid_proto.FileList{
+ Additions: []string{"file1", "file2", "file3", "file2"},
+ Deletions: []string{"file5.go", "file6"},
+ },
+ FileList: &fileList{seenFiles: make(map[string]bool)},
+ Expected: &fileList{
+ seenFiles: map[string]bool{"file1": true, "file2": true, "file3": true, "file5.go": true, "file6": true},
+ totalChanges: 5,
+ changes: fileChanges{
+ additions: changeInfo{
+ total: 3,
+ list: []string{"file1", "file2", "file3"},
+ byExtension: map[string]uint32{"": 3},
+ },
+ deletions: changeInfo{
+ total: 2,
+ list: []string{"file5.go", "file6"},
+ byExtension: map[string]uint32{"": 1, ".go": 1},
+ },
+ },
+ },
+ },
+ }
+ for _, tc := range testCases {
+ tc.FileList.aggregateFileList(tc.Message)
+ if !reflect.DeepEqual(tc.FileList, tc.Expected) {
+ t.Errorf("Expected: %v, Actual: %v", tc.Expected, tc.FileList)
+ }
+ }
+}
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 591e3cc..2e19f7a 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -26,7 +26,7 @@
"soong-ui-metrics_proto",
"soong-ui-mk_metrics_proto",
"soong-shared",
- "soong-ui-metrics_combined_proto",
+ "soong-ui-execution_metrics_proto",
],
srcs: [
"hostinfo.go",
@@ -64,15 +64,15 @@
}
bootstrap_go_package {
- name: "soong-ui-metrics_combined_proto",
- pkgPath: "android/soong/ui/metrics/combined_metrics_proto",
+ name: "soong-ui-execution_metrics_proto",
+ pkgPath: "android/soong/ui/metrics/execution_metrics_proto",
deps: [
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
"soong-cmd-find_input_delta-proto",
],
srcs: [
- "metrics_proto/metrics.pb.go",
+ "execution_metrics_proto/execution_metrics.pb.go",
],
}
diff --git a/ui/metrics/execution_metrics_proto/execution_metrics.pb.go b/ui/metrics/execution_metrics_proto/execution_metrics.pb.go
new file mode 100644
index 0000000..a065dbd
--- /dev/null
+++ b/ui/metrics/execution_metrics_proto/execution_metrics.pb.go
@@ -0,0 +1,240 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: execution_metrics.proto
+
+package execution_metrics_proto
+
+import (
+ find_input_delta_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// These field numbers are also found in the inner message declarations.
+// We verify that the values are the same, and that every enum value is checked
+// in execution_metrics_test.go.
+// Do not change this enum without also updating:
+// - the submessage's .proto file
+// - execution_metrics_test.go
+type FieldNumbers int32
+
+const (
+ FieldNumbers_FIELD_NUMBERS_UNSPECIFIED FieldNumbers = 0
+ FieldNumbers_FIELD_NUMBERS_FILE_LIST FieldNumbers = 1
+)
+
+// Enum value maps for FieldNumbers.
+var (
+ FieldNumbers_name = map[int32]string{
+ 0: "FIELD_NUMBERS_UNSPECIFIED",
+ 1: "FIELD_NUMBERS_FILE_LIST",
+ }
+ FieldNumbers_value = map[string]int32{
+ "FIELD_NUMBERS_UNSPECIFIED": 0,
+ "FIELD_NUMBERS_FILE_LIST": 1,
+ }
+)
+
+func (x FieldNumbers) Enum() *FieldNumbers {
+ p := new(FieldNumbers)
+ *p = x
+ return p
+}
+
+func (x FieldNumbers) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FieldNumbers) Descriptor() protoreflect.EnumDescriptor {
+ return file_execution_metrics_proto_enumTypes[0].Descriptor()
+}
+
+func (FieldNumbers) Type() protoreflect.EnumType {
+ return &file_execution_metrics_proto_enumTypes[0]
+}
+
+func (x FieldNumbers) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FieldNumbers) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FieldNumbers(num)
+ return nil
+}
+
+// Deprecated: Use FieldNumbers.Descriptor instead.
+func (FieldNumbers) EnumDescriptor() ([]byte, []int) {
+ return file_execution_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+type SoongExecutionMetrics struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // cmd/find_input_delta/find_input_delta_proto.FileList
+ FileList *find_input_delta_proto.FileList `protobuf:"bytes,1,opt,name=file_list,json=fileList" json:"file_list,omitempty"`
+}
+
+func (x *SoongExecutionMetrics) Reset() {
+ *x = SoongExecutionMetrics{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_execution_metrics_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SoongExecutionMetrics) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SoongExecutionMetrics) ProtoMessage() {}
+
+func (x *SoongExecutionMetrics) ProtoReflect() protoreflect.Message {
+ mi := &file_execution_metrics_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SoongExecutionMetrics.ProtoReflect.Descriptor instead.
+func (*SoongExecutionMetrics) Descriptor() ([]byte, []int) {
+ return file_execution_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *SoongExecutionMetrics) GetFileList() *find_input_delta_proto.FileList {
+ if x != nil {
+ return x.FileList
+ }
+ return nil
+}
+
+var File_execution_metrics_proto protoreflect.FileDescriptor
+
+var file_execution_metrics_proto_rawDesc = []byte{
+ 0x0a, 0x17, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0x3b,
+ 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x69, 0x6c, 0x65,
+ 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5e, 0x0a, 0x15, 0x53,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73,
+ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73,
+ 0x74, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2a, 0x4a, 0x0a, 0x0c, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46,
+ 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49,
+ 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45,
+ 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x42, 0x32, 0x5a, 0x30, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_execution_metrics_proto_rawDescOnce sync.Once
+ file_execution_metrics_proto_rawDescData = file_execution_metrics_proto_rawDesc
+)
+
+func file_execution_metrics_proto_rawDescGZIP() []byte {
+ file_execution_metrics_proto_rawDescOnce.Do(func() {
+ file_execution_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_execution_metrics_proto_rawDescData)
+ })
+ return file_execution_metrics_proto_rawDescData
+}
+
+var file_execution_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_execution_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_execution_metrics_proto_goTypes = []interface{}{
+ (FieldNumbers)(0), // 0: soong_build_metrics.FieldNumbers
+ (*SoongExecutionMetrics)(nil), // 1: soong_build_metrics.SoongExecutionMetrics
+ (*find_input_delta_proto.FileList)(nil), // 2: android.find_input_delta_proto.FileList
+}
+var file_execution_metrics_proto_depIdxs = []int32{
+ 2, // 0: soong_build_metrics.SoongExecutionMetrics.file_list:type_name -> android.find_input_delta_proto.FileList
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_execution_metrics_proto_init() }
+func file_execution_metrics_proto_init() {
+ if File_execution_metrics_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_execution_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SoongExecutionMetrics); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_execution_metrics_proto_rawDesc,
+ NumEnums: 1,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_execution_metrics_proto_goTypes,
+ DependencyIndexes: file_execution_metrics_proto_depIdxs,
+ EnumInfos: file_execution_metrics_proto_enumTypes,
+ MessageInfos: file_execution_metrics_proto_msgTypes,
+ }.Build()
+ File_execution_metrics_proto = out.File
+ file_execution_metrics_proto_rawDesc = nil
+ file_execution_metrics_proto_goTypes = nil
+ file_execution_metrics_proto_depIdxs = nil
+}
diff --git a/ui/metrics/metrics_proto/combined_metrics.proto b/ui/metrics/execution_metrics_proto/execution_metrics.proto
similarity index 83%
rename from ui/metrics/metrics_proto/combined_metrics.proto
rename to ui/metrics/execution_metrics_proto/execution_metrics.proto
index 3cd9a53..381dcd1 100644
--- a/ui/metrics/metrics_proto/combined_metrics.proto
+++ b/ui/metrics/execution_metrics_proto/execution_metrics.proto
@@ -1,4 +1,4 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
+// 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.
@@ -15,22 +15,22 @@
syntax = "proto2";
package soong_build_metrics;
-option go_package = "android/soong/ui/metrics/metrics_proto";
+option go_package = "android/soong/ui/metrics/execution_metrics_proto";
import "cmd/find_input_delta/find_input_delta_proto/file_list.proto";
// These field numbers are also found in the inner message declarations.
// We verify that the values are the same, and that every enum value is checked
-// in combined_metrics_test.go.
+// in execution_metrics_test.go.
// Do not change this enum without also updating:
// - the submessage's .proto file
-// - combined_metrics_test.go
+// - execution_metrics_test.go
enum FieldNumbers {
FIELD_NUMBERS_UNSPECIFIED = 0;
FIELD_NUMBERS_FILE_LIST = 1;
}
-message SoongCombinedMetrics {
+message SoongExecutionMetrics {
// cmd/find_input_delta/find_input_delta_proto.FileList
optional android.find_input_delta_proto.FileList file_list = 1;
}
diff --git a/ui/metrics/metrics_proto/combined_metrics_test.go b/ui/metrics/execution_metrics_proto/execution_metrics_test.go
similarity index 89%
rename from ui/metrics/metrics_proto/combined_metrics_test.go
rename to ui/metrics/execution_metrics_proto/execution_metrics_test.go
index eedb12a..2f71c21 100644
--- a/ui/metrics/metrics_proto/combined_metrics_test.go
+++ b/ui/metrics/execution_metrics_proto/execution_metrics_test.go
@@ -1,4 +1,4 @@
-package metrics_proto
+package execution_metrics_proto
import (
"testing"
@@ -6,7 +6,7 @@
find_input_delta_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
)
-func TestCombinedMetricsMessageNums(t *testing.T) {
+func TestExecutionMetricsMessageNums(t *testing.T) {
testCases := []struct {
Name string
FieldNumbers map[string]int32
diff --git a/ui/metrics/execution_metrics_proto/regen.sh b/ui/metrics/execution_metrics_proto/regen.sh
new file mode 100755
index 0000000..5339a9a
--- /dev/null
+++ b/ui/metrics/execution_metrics_proto/regen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Generates the golang source file of metrics.proto protobuf file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. -I .:../../.. execution_metrics.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 4a275a8..8d29cfc 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -161,7 +161,7 @@
}
// SetMetadataMetrics sets information about the build such as the target
-// product, host architecture and out directory.
+// product, host architecture and out directory. May be called multiple times.
func (m *Metrics) SetMetadataMetrics(metadata map[string]string) {
for k, v := range metadata {
switch k {
@@ -171,6 +171,8 @@
m.metrics.PlatformVersionCodename = proto.String(v)
case "TARGET_PRODUCT":
m.metrics.TargetProduct = proto.String(v)
+ case "TARGET_RELEASE":
+ m.metrics.TargetRelease = proto.String(v)
case "TARGET_BUILD_VARIANT":
switch v {
case "user":
diff --git a/ui/metrics/metrics_proto/combined_metrics.pb.go b/ui/metrics/metrics_proto/combined_metrics.pb.go
deleted file mode 100644
index f49d64d..0000000
--- a/ui/metrics/metrics_proto/combined_metrics.pb.go
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2018 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.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// protoc-gen-go v1.33.0
-// protoc v3.21.12
-// source: combined_metrics.proto
-
-package metrics_proto
-
-import (
- find_input_delta_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
- protoreflect "google.golang.org/protobuf/reflect/protoreflect"
- protoimpl "google.golang.org/protobuf/runtime/protoimpl"
- reflect "reflect"
- sync "sync"
-)
-
-const (
- // Verify that this generated code is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
- // Verify that runtime/protoimpl is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// These field numbers are also found in the inner message declarations.
-// We verify that the values are the same, and that every enum value is checked
-// in combined_metrics_test.go.
-// Do not change this enum without also updating:
-// - the submessage's .proto file
-// - combined_metrics_test.go
-type FieldNumbers int32
-
-const (
- FieldNumbers_FIELD_NUMBERS_UNSPECIFIED FieldNumbers = 0
- FieldNumbers_FIELD_NUMBERS_FILE_LIST FieldNumbers = 1
-)
-
-// Enum value maps for FieldNumbers.
-var (
- FieldNumbers_name = map[int32]string{
- 0: "FIELD_NUMBERS_UNSPECIFIED",
- 1: "FIELD_NUMBERS_FILE_LIST",
- }
- FieldNumbers_value = map[string]int32{
- "FIELD_NUMBERS_UNSPECIFIED": 0,
- "FIELD_NUMBERS_FILE_LIST": 1,
- }
-)
-
-func (x FieldNumbers) Enum() *FieldNumbers {
- p := new(FieldNumbers)
- *p = x
- return p
-}
-
-func (x FieldNumbers) String() string {
- return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (FieldNumbers) Descriptor() protoreflect.EnumDescriptor {
- return file_combined_metrics_proto_enumTypes[0].Descriptor()
-}
-
-func (FieldNumbers) Type() protoreflect.EnumType {
- return &file_combined_metrics_proto_enumTypes[0]
-}
-
-func (x FieldNumbers) Number() protoreflect.EnumNumber {
- return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Do not use.
-func (x *FieldNumbers) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
- if err != nil {
- return err
- }
- *x = FieldNumbers(num)
- return nil
-}
-
-// Deprecated: Use FieldNumbers.Descriptor instead.
-func (FieldNumbers) EnumDescriptor() ([]byte, []int) {
- return file_combined_metrics_proto_rawDescGZIP(), []int{0}
-}
-
-type SoongCombinedMetrics struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // cmd/find_input_delta/find_input_delta_proto.FileList
- FileList *find_input_delta_proto.FileList `protobuf:"bytes,1,opt,name=file_list,json=fileList" json:"file_list,omitempty"`
-}
-
-func (x *SoongCombinedMetrics) Reset() {
- *x = SoongCombinedMetrics{}
- if protoimpl.UnsafeEnabled {
- mi := &file_combined_metrics_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SoongCombinedMetrics) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SoongCombinedMetrics) ProtoMessage() {}
-
-func (x *SoongCombinedMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_combined_metrics_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SoongCombinedMetrics.ProtoReflect.Descriptor instead.
-func (*SoongCombinedMetrics) Descriptor() ([]byte, []int) {
- return file_combined_metrics_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *SoongCombinedMetrics) GetFileList() *find_input_delta_proto.FileList {
- if x != nil {
- return x.FileList
- }
- return nil
-}
-
-var File_combined_metrics_proto protoreflect.FileDescriptor
-
-var file_combined_metrics_proto_rawDesc = []byte{
- 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0x3b, 0x63,
- 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64,
- 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x5f,
- 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x14, 0x53, 0x6f,
- 0x6f, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
- 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
- 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52,
- 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2a, 0x4a, 0x0a, 0x0c, 0x46, 0x69, 0x65,
- 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x49, 0x45,
- 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
- 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x45, 0x4c,
- 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4c,
- 0x49, 0x53, 0x54, 0x10, 0x01, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-}
-
-var (
- file_combined_metrics_proto_rawDescOnce sync.Once
- file_combined_metrics_proto_rawDescData = file_combined_metrics_proto_rawDesc
-)
-
-func file_combined_metrics_proto_rawDescGZIP() []byte {
- file_combined_metrics_proto_rawDescOnce.Do(func() {
- file_combined_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_combined_metrics_proto_rawDescData)
- })
- return file_combined_metrics_proto_rawDescData
-}
-
-var file_combined_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_combined_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_combined_metrics_proto_goTypes = []interface{}{
- (FieldNumbers)(0), // 0: soong_build_metrics.FieldNumbers
- (*SoongCombinedMetrics)(nil), // 1: soong_build_metrics.SoongCombinedMetrics
- (*find_input_delta_proto.FileList)(nil), // 2: android.find_input_delta_proto.FileList
-}
-var file_combined_metrics_proto_depIdxs = []int32{
- 2, // 0: soong_build_metrics.SoongCombinedMetrics.file_list:type_name -> android.find_input_delta_proto.FileList
- 1, // [1:1] is the sub-list for method output_type
- 1, // [1:1] is the sub-list for method input_type
- 1, // [1:1] is the sub-list for extension type_name
- 1, // [1:1] is the sub-list for extension extendee
- 0, // [0:1] is the sub-list for field type_name
-}
-
-func init() { file_combined_metrics_proto_init() }
-func file_combined_metrics_proto_init() {
- if File_combined_metrics_proto != nil {
- return
- }
- if !protoimpl.UnsafeEnabled {
- file_combined_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SoongCombinedMetrics); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
- type x struct{}
- out := protoimpl.TypeBuilder{
- File: protoimpl.DescBuilder{
- GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_combined_metrics_proto_rawDesc,
- NumEnums: 1,
- NumMessages: 1,
- NumExtensions: 0,
- NumServices: 0,
- },
- GoTypes: file_combined_metrics_proto_goTypes,
- DependencyIndexes: file_combined_metrics_proto_depIdxs,
- EnumInfos: file_combined_metrics_proto_enumTypes,
- MessageInfos: file_combined_metrics_proto_msgTypes,
- }.Build()
- File_combined_metrics_proto = out.File
- file_combined_metrics_proto_rawDesc = nil
- file_combined_metrics_proto_goTypes = nil
- file_combined_metrics_proto_depIdxs = nil
-}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 72fdbe8..1ebe911 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -14,7 +14,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: metrics.proto
@@ -279,7 +279,7 @@
// Deprecated: Use ModuleTypeInfo_BuildSystem.Descriptor instead.
func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{10, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{11, 0}
}
type ExpConfigFetcher_ConfigStatus int32
@@ -341,7 +341,7 @@
// Deprecated: Use ExpConfigFetcher_ConfigStatus.Descriptor instead.
func (ExpConfigFetcher_ConfigStatus) EnumDescriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{14, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{15, 0}
}
type MetricsBase struct {
@@ -427,6 +427,8 @@
ChangedEnvironmentVariable []string `protobuf:"bytes,34,rep,name=changed_environment_variable,json=changedEnvironmentVariable" json:"changed_environment_variable,omitempty"`
// Metrics related to optimized builds.
OptimizedBuildMetrics *OptimizedBuildMetrics `protobuf:"bytes,35,opt,name=optimized_build_metrics,json=optimizedBuildMetrics" json:"optimized_build_metrics,omitempty"`
+ // The target release information. e.g., trunk_staging.
+ TargetRelease *string `protobuf:"bytes,36,opt,name=target_release,json=targetRelease" json:"target_release,omitempty"`
}
// Default values for MetricsBase fields.
@@ -715,6 +717,13 @@
return nil
}
+func (x *MetricsBase) GetTargetRelease() string {
+ if x != nil && x.TargetRelease != nil {
+ return *x.TargetRelease
+ }
+ return ""
+}
+
type BuildConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -739,6 +748,11 @@
// EXTERNAL_FILE - ninja uses an external custom weight list
// HINT_FROM_SOONG - ninja uses a prioritized module list from Soong
NinjaWeightListSource *BuildConfig_NinjaWeightListSource `protobuf:"varint,8,opt,name=ninja_weight_list_source,json=ninjaWeightListSource,enum=soong_build_metrics.BuildConfig_NinjaWeightListSource,def=0" json:"ninja_weight_list_source,omitempty"`
+ // Values of some build-affecting environment variables.
+ SoongEnvVars *SoongEnvVars `protobuf:"bytes,9,opt,name=soong_env_vars,json=soongEnvVars" json:"soong_env_vars,omitempty"`
+ // Whether this build uses soong-only (no kati) mode (either via environment variable,
+ // command line flag or product config.
+ SoongOnly *bool `protobuf:"varint,10,opt,name=soong_only,json=soongOnly" json:"soong_only,omitempty"`
}
// Default values for BuildConfig fields.
@@ -834,6 +848,77 @@
return Default_BuildConfig_NinjaWeightListSource
}
+func (x *BuildConfig) GetSoongEnvVars() *SoongEnvVars {
+ if x != nil {
+ return x.SoongEnvVars
+ }
+ return nil
+}
+
+func (x *BuildConfig) GetSoongOnly() bool {
+ if x != nil && x.SoongOnly != nil {
+ return *x.SoongOnly
+ }
+ return false
+}
+
+type SoongEnvVars struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // SOONG_PARTIAL_COMPILE
+ PartialCompile *string `protobuf:"bytes,1,opt,name=partial_compile,json=partialCompile" json:"partial_compile,omitempty"`
+ // SOONG_USE_PARTIAL_COMPILE
+ UsePartialCompile *string `protobuf:"bytes,2,opt,name=use_partial_compile,json=usePartialCompile" json:"use_partial_compile,omitempty"`
+}
+
+func (x *SoongEnvVars) Reset() {
+ *x = SoongEnvVars{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SoongEnvVars) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SoongEnvVars) ProtoMessage() {}
+
+func (x *SoongEnvVars) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SoongEnvVars.ProtoReflect.Descriptor instead.
+func (*SoongEnvVars) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *SoongEnvVars) GetPartialCompile() string {
+ if x != nil && x.PartialCompile != nil {
+ return *x.PartialCompile
+ }
+ return ""
+}
+
+func (x *SoongEnvVars) GetUsePartialCompile() string {
+ if x != nil && x.UsePartialCompile != nil {
+ return *x.UsePartialCompile
+ }
+ return ""
+}
+
type SystemResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -852,7 +937,7 @@
func (x *SystemResourceInfo) Reset() {
*x = SystemResourceInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[2]
+ mi := &file_metrics_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -865,7 +950,7 @@
func (*SystemResourceInfo) ProtoMessage() {}
func (x *SystemResourceInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[2]
+ mi := &file_metrics_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -878,7 +963,7 @@
// Deprecated: Use SystemResourceInfo.ProtoReflect.Descriptor instead.
func (*SystemResourceInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{2}
+ return file_metrics_proto_rawDescGZIP(), []int{3}
}
func (x *SystemResourceInfo) GetTotalPhysicalMemory() uint64 {
@@ -927,7 +1012,7 @@
func (x *SystemCpuInfo) Reset() {
*x = SystemCpuInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[3]
+ mi := &file_metrics_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -940,7 +1025,7 @@
func (*SystemCpuInfo) ProtoMessage() {}
func (x *SystemCpuInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[3]
+ mi := &file_metrics_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -953,7 +1038,7 @@
// Deprecated: Use SystemCpuInfo.ProtoReflect.Descriptor instead.
func (*SystemCpuInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{3}
+ return file_metrics_proto_rawDescGZIP(), []int{4}
}
func (x *SystemCpuInfo) GetVendorId() string {
@@ -1000,7 +1085,7 @@
func (x *SystemMemInfo) Reset() {
*x = SystemMemInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[4]
+ mi := &file_metrics_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1013,7 +1098,7 @@
func (*SystemMemInfo) ProtoMessage() {}
func (x *SystemMemInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[4]
+ mi := &file_metrics_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1026,7 +1111,7 @@
// Deprecated: Use SystemMemInfo.ProtoReflect.Descriptor instead.
func (*SystemMemInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{4}
+ return file_metrics_proto_rawDescGZIP(), []int{5}
}
func (x *SystemMemInfo) GetMemTotal() uint64 {
@@ -1081,7 +1166,7 @@
func (x *PerfInfo) Reset() {
*x = PerfInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[5]
+ mi := &file_metrics_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1094,7 +1179,7 @@
func (*PerfInfo) ProtoMessage() {}
func (x *PerfInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[5]
+ mi := &file_metrics_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1107,7 +1192,7 @@
// Deprecated: Use PerfInfo.ProtoReflect.Descriptor instead.
func (*PerfInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{5}
+ return file_metrics_proto_rawDescGZIP(), []int{6}
}
func (x *PerfInfo) GetDescription() string {
@@ -1181,7 +1266,7 @@
func (x *PerfCounters) Reset() {
*x = PerfCounters{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[6]
+ mi := &file_metrics_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1194,7 +1279,7 @@
func (*PerfCounters) ProtoMessage() {}
func (x *PerfCounters) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[6]
+ mi := &file_metrics_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1207,7 +1292,7 @@
// Deprecated: Use PerfCounters.ProtoReflect.Descriptor instead.
func (*PerfCounters) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{6}
+ return file_metrics_proto_rawDescGZIP(), []int{7}
}
func (x *PerfCounters) GetTime() uint64 {
@@ -1238,7 +1323,7 @@
func (x *PerfCounterGroup) Reset() {
*x = PerfCounterGroup{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[7]
+ mi := &file_metrics_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1251,7 +1336,7 @@
func (*PerfCounterGroup) ProtoMessage() {}
func (x *PerfCounterGroup) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[7]
+ mi := &file_metrics_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1264,7 +1349,7 @@
// Deprecated: Use PerfCounterGroup.ProtoReflect.Descriptor instead.
func (*PerfCounterGroup) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{7}
+ return file_metrics_proto_rawDescGZIP(), []int{8}
}
func (x *PerfCounterGroup) GetName() string {
@@ -1295,7 +1380,7 @@
func (x *PerfCounter) Reset() {
*x = PerfCounter{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[8]
+ mi := &file_metrics_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1308,7 +1393,7 @@
func (*PerfCounter) ProtoMessage() {}
func (x *PerfCounter) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[8]
+ mi := &file_metrics_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1321,7 +1406,7 @@
// Deprecated: Use PerfCounter.ProtoReflect.Descriptor instead.
func (*PerfCounter) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{8}
+ return file_metrics_proto_rawDescGZIP(), []int{9}
}
func (x *PerfCounter) GetName() string {
@@ -1368,7 +1453,7 @@
func (x *ProcessResourceInfo) Reset() {
*x = ProcessResourceInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[9]
+ mi := &file_metrics_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1381,7 +1466,7 @@
func (*ProcessResourceInfo) ProtoMessage() {}
func (x *ProcessResourceInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[9]
+ mi := &file_metrics_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1394,7 +1479,7 @@
// Deprecated: Use ProcessResourceInfo.ProtoReflect.Descriptor instead.
func (*ProcessResourceInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{9}
+ return file_metrics_proto_rawDescGZIP(), []int{10}
}
func (x *ProcessResourceInfo) GetName() string {
@@ -1488,7 +1573,7 @@
func (x *ModuleTypeInfo) Reset() {
*x = ModuleTypeInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[10]
+ mi := &file_metrics_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1501,7 +1586,7 @@
func (*ModuleTypeInfo) ProtoMessage() {}
func (x *ModuleTypeInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[10]
+ mi := &file_metrics_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1514,7 +1599,7 @@
// Deprecated: Use ModuleTypeInfo.ProtoReflect.Descriptor instead.
func (*ModuleTypeInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{10}
+ return file_metrics_proto_rawDescGZIP(), []int{11}
}
func (x *ModuleTypeInfo) GetBuildSystem() ModuleTypeInfo_BuildSystem {
@@ -1552,7 +1637,7 @@
func (x *CriticalUserJourneyMetrics) Reset() {
*x = CriticalUserJourneyMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[11]
+ mi := &file_metrics_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1565,7 +1650,7 @@
func (*CriticalUserJourneyMetrics) ProtoMessage() {}
func (x *CriticalUserJourneyMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[11]
+ mi := &file_metrics_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1578,7 +1663,7 @@
// Deprecated: Use CriticalUserJourneyMetrics.ProtoReflect.Descriptor instead.
func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{11}
+ return file_metrics_proto_rawDescGZIP(), []int{12}
}
func (x *CriticalUserJourneyMetrics) GetName() string {
@@ -1607,7 +1692,7 @@
func (x *CriticalUserJourneysMetrics) Reset() {
*x = CriticalUserJourneysMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[12]
+ mi := &file_metrics_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1620,7 +1705,7 @@
func (*CriticalUserJourneysMetrics) ProtoMessage() {}
func (x *CriticalUserJourneysMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[12]
+ mi := &file_metrics_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1633,7 +1718,7 @@
// Deprecated: Use CriticalUserJourneysMetrics.ProtoReflect.Descriptor instead.
func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{12}
+ return file_metrics_proto_rawDescGZIP(), []int{13}
}
func (x *CriticalUserJourneysMetrics) GetCujs() []*CriticalUserJourneyMetrics {
@@ -1669,7 +1754,7 @@
func (x *SoongBuildMetrics) Reset() {
*x = SoongBuildMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[13]
+ mi := &file_metrics_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1682,7 +1767,7 @@
func (*SoongBuildMetrics) ProtoMessage() {}
func (x *SoongBuildMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[13]
+ mi := &file_metrics_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1695,7 +1780,7 @@
// Deprecated: Use SoongBuildMetrics.ProtoReflect.Descriptor instead.
func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{13}
+ return file_metrics_proto_rawDescGZIP(), []int{14}
}
func (x *SoongBuildMetrics) GetModules() uint32 {
@@ -1773,7 +1858,7 @@
func (x *ExpConfigFetcher) Reset() {
*x = ExpConfigFetcher{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[14]
+ mi := &file_metrics_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1786,7 +1871,7 @@
func (*ExpConfigFetcher) ProtoMessage() {}
func (x *ExpConfigFetcher) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[14]
+ mi := &file_metrics_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1799,7 +1884,7 @@
// Deprecated: Use ExpConfigFetcher.ProtoReflect.Descriptor instead.
func (*ExpConfigFetcher) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{14}
+ return file_metrics_proto_rawDescGZIP(), []int{15}
}
func (x *ExpConfigFetcher) GetStatus() ExpConfigFetcher_ConfigStatus {
@@ -1837,7 +1922,7 @@
func (x *MixedBuildsInfo) Reset() {
*x = MixedBuildsInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[15]
+ mi := &file_metrics_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1850,7 +1935,7 @@
func (*MixedBuildsInfo) ProtoMessage() {}
func (x *MixedBuildsInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[15]
+ mi := &file_metrics_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1863,7 +1948,7 @@
// Deprecated: Use MixedBuildsInfo.ProtoReflect.Descriptor instead.
func (*MixedBuildsInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{15}
+ return file_metrics_proto_rawDescGZIP(), []int{16}
}
func (x *MixedBuildsInfo) GetMixedBuildEnabledModules() []string {
@@ -1900,7 +1985,7 @@
func (x *CriticalPathInfo) Reset() {
*x = CriticalPathInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[16]
+ mi := &file_metrics_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1913,7 +1998,7 @@
func (*CriticalPathInfo) ProtoMessage() {}
func (x *CriticalPathInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[16]
+ mi := &file_metrics_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1926,7 +2011,7 @@
// Deprecated: Use CriticalPathInfo.ProtoReflect.Descriptor instead.
func (*CriticalPathInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{16}
+ return file_metrics_proto_rawDescGZIP(), []int{17}
}
func (x *CriticalPathInfo) GetElapsedTimeMicros() uint64 {
@@ -1971,7 +2056,7 @@
func (x *JobInfo) Reset() {
*x = JobInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[17]
+ mi := &file_metrics_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1984,7 +2069,7 @@
func (*JobInfo) ProtoMessage() {}
func (x *JobInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[17]
+ mi := &file_metrics_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1997,7 +2082,7 @@
// Deprecated: Use JobInfo.ProtoReflect.Descriptor instead.
func (*JobInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{17}
+ return file_metrics_proto_rawDescGZIP(), []int{18}
}
func (x *JobInfo) GetElapsedTimeMicros() uint64 {
@@ -2030,7 +2115,7 @@
func (x *OptimizedBuildMetrics) Reset() {
*x = OptimizedBuildMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[18]
+ mi := &file_metrics_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2043,7 +2128,7 @@
func (*OptimizedBuildMetrics) ProtoMessage() {}
func (x *OptimizedBuildMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[18]
+ mi := &file_metrics_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2056,7 +2141,7 @@
// Deprecated: Use OptimizedBuildMetrics.ProtoReflect.Descriptor instead.
func (*OptimizedBuildMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{18}
+ return file_metrics_proto_rawDescGZIP(), []int{19}
}
func (x *OptimizedBuildMetrics) GetAnalysisPerf() *PerfInfo {
@@ -2080,6 +2165,226 @@
return nil
}
+// This is created by soong_ui from SoongExexcutionMetrics files.
+type ExecutionMetrics struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The arguments provided on the command line.
+ CommandArgs []string `protobuf:"bytes,1,rep,name=command_args,json=commandArgs" json:"command_args,omitempty"`
+ // Changed files detected by the build.
+ ChangedFiles *AggregatedFileList `protobuf:"bytes,2,opt,name=changed_files,json=changedFiles" json:"changed_files,omitempty"`
+}
+
+func (x *ExecutionMetrics) Reset() {
+ *x = ExecutionMetrics{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ExecutionMetrics) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ExecutionMetrics) ProtoMessage() {}
+
+func (x *ExecutionMetrics) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ExecutionMetrics.ProtoReflect.Descriptor instead.
+func (*ExecutionMetrics) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *ExecutionMetrics) GetCommandArgs() []string {
+ if x != nil {
+ return x.CommandArgs
+ }
+ return nil
+}
+
+func (x *ExecutionMetrics) GetChangedFiles() *AggregatedFileList {
+ if x != nil {
+ return x.ChangedFiles
+ }
+ return nil
+}
+
+// This is created by soong_ui from the various
+// android.find_input_delta_proto.FileList metrics provided to it by
+// find_input_delta.
+type AggregatedFileList struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The (possibly truncated list of) added files.
+ Additions []string `protobuf:"bytes,2,rep,name=additions" json:"additions,omitempty"`
+ // The (possibly truncated list of) changed files.
+ Changes []string `protobuf:"bytes,3,rep,name=changes" json:"changes,omitempty"`
+ // The (possibly truncated list of) deleted files.
+ Deletions []string `protobuf:"bytes,4,rep,name=deletions" json:"deletions,omitempty"`
+ // Count of files added/changed/deleted.
+ TotalDelta *uint32 `protobuf:"varint,5,opt,name=total_delta,json=totalDelta" json:"total_delta,omitempty"`
+ // Counts by extension.
+ Counts []*FileCount `protobuf:"bytes,6,rep,name=counts" json:"counts,omitempty"`
+}
+
+func (x *AggregatedFileList) Reset() {
+ *x = AggregatedFileList{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[21]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AggregatedFileList) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AggregatedFileList) ProtoMessage() {}
+
+func (x *AggregatedFileList) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[21]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AggregatedFileList.ProtoReflect.Descriptor instead.
+func (*AggregatedFileList) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{21}
+}
+
+func (x *AggregatedFileList) GetAdditions() []string {
+ if x != nil {
+ return x.Additions
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetChanges() []string {
+ if x != nil {
+ return x.Changes
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetDeletions() []string {
+ if x != nil {
+ return x.Deletions
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetTotalDelta() uint32 {
+ if x != nil && x.TotalDelta != nil {
+ return *x.TotalDelta
+ }
+ return 0
+}
+
+func (x *AggregatedFileList) GetCounts() []*FileCount {
+ if x != nil {
+ return x.Counts
+ }
+ return nil
+}
+
+type FileCount struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The file extension
+ Extension *string `protobuf:"bytes,1,opt,name=extension" json:"extension,omitempty"`
+ // Number of added files with this extension.
+ Additions *uint32 `protobuf:"varint,2,opt,name=additions" json:"additions,omitempty"`
+ // Number of modified files with this extension.
+ Modifications *uint32 `protobuf:"varint,3,opt,name=modifications" json:"modifications,omitempty"`
+ // Number of deleted files with this extension.
+ Deletions *uint32 `protobuf:"varint,4,opt,name=deletions" json:"deletions,omitempty"`
+}
+
+func (x *FileCount) Reset() {
+ *x = FileCount{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[22]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FileCount) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileCount) ProtoMessage() {}
+
+func (x *FileCount) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[22]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FileCount.ProtoReflect.Descriptor instead.
+func (*FileCount) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{22}
+}
+
+func (x *FileCount) GetExtension() string {
+ if x != nil && x.Extension != nil {
+ return *x.Extension
+ }
+ return ""
+}
+
+func (x *FileCount) GetAdditions() uint32 {
+ if x != nil && x.Additions != nil {
+ return *x.Additions
+ }
+ return 0
+}
+
+func (x *FileCount) GetModifications() uint32 {
+ if x != nil && x.Modifications != nil {
+ return *x.Modifications
+ }
+ return 0
+}
+
+func (x *FileCount) GetDeletions() uint32 {
+ if x != nil && x.Deletions != nil {
+ return *x.Deletions
+ }
+ return 0
+}
+
type OptimizedBuildMetrics_TargetOptimizationResult struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -2101,7 +2406,7 @@
func (x *OptimizedBuildMetrics_TargetOptimizationResult) Reset() {
*x = OptimizedBuildMetrics_TargetOptimizationResult{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[19]
+ mi := &file_metrics_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2114,7 +2419,7 @@
func (*OptimizedBuildMetrics_TargetOptimizationResult) ProtoMessage() {}
func (x *OptimizedBuildMetrics_TargetOptimizationResult) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[19]
+ mi := &file_metrics_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2127,7 +2432,7 @@
// Deprecated: Use OptimizedBuildMetrics_TargetOptimizationResult.ProtoReflect.Descriptor instead.
func (*OptimizedBuildMetrics_TargetOptimizationResult) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{18, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{19, 0}
}
func (x *OptimizedBuildMetrics_TargetOptimizationResult) GetName() string {
@@ -2181,7 +2486,7 @@
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) Reset() {
*x = OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[20]
+ mi := &file_metrics_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2194,7 +2499,7 @@
func (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoMessage() {}
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[20]
+ mi := &file_metrics_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2207,7 +2512,7 @@
// Deprecated: Use OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact.ProtoReflect.Descriptor instead.
func (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{18, 0, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{19, 0, 0}
}
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) GetName() string {
@@ -2236,7 +2541,7 @@
var file_metrics_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x22, 0xb0, 0x10, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x22, 0xd7, 0x10, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x42, 0x61, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x61,
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
@@ -2360,287 +2665,332 @@
0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d,
0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64,
- 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10,
- 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01,
- 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63,
- 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07,
- 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34,
- 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58,
- 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22, 0x8a, 0x04, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67,
- 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f,
- 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66,
- 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d,
- 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69,
- 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c,
- 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c,
- 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75,
- 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06,
- 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x44, 0x0a,
- 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62,
- 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
- 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x44, 0x69, 0x73,
- 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75,
- 0x69, 0x6c, 0x64, 0x12, 0x79, 0x0a, 0x18, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x77, 0x65, 0x69,
- 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
- 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69,
- 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x08, 0x4e,
- 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x52, 0x15, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65,
- 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x74,
- 0x0a, 0x15, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73,
- 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55,
- 0x53, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x4e, 0x4a, 0x41, 0x5f, 0x4c,
- 0x4f, 0x47, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x45, 0x56, 0x45, 0x4e, 0x4c, 0x59, 0x5f, 0x44,
- 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d,
- 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x12,
- 0x13, 0x0a, 0x0f, 0x48, 0x49, 0x4e, 0x54, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x4f,
- 0x4e, 0x47, 0x10, 0x04, 0x22, 0xed, 0x01, 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52,
- 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61,
- 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12,
- 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
- 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x12, 0x3d, 0x0a, 0x08, 0x63, 0x70, 0x75, 0x5f, 0x69, 0x6e,
- 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x63, 0x70,
- 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x08, 0x6d, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66,
- 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79,
- 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x6d, 0x65, 0x6d,
- 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x7e, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70,
- 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f,
- 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72,
- 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d,
- 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x70, 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x14,
- 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66,
- 0x6c, 0x61, 0x67, 0x73, 0x22, 0x6c, 0x0a, 0x0d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65,
- 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x74, 0x6f, 0x74,
- 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x54, 0x6f, 0x74,
- 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65, 0x6d, 0x5f, 0x66, 0x72, 0x65, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x46, 0x72, 0x65, 0x65, 0x12, 0x23, 0x0a,
- 0x0d, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x65, 0x6d, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
- 0x6c, 0x65, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12,
- 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74,
- 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d,
- 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d,
- 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
- 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
- 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
- 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52,
- 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65,
- 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e,
- 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72,
- 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
- 0x61, 0x0a, 0x0c, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12,
- 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74,
- 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x02, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f,
- 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75,
- 0x70, 0x73, 0x22, 0x64, 0x0a, 0x10, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
- 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65,
+ 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x30,
+ 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08,
+ 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52,
+ 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02,
+ 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
+ 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09,
+ 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36,
+ 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22, 0xf2,
+ 0x04, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19,
+ 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65,
+ 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52,
+ 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f,
+ 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63,
+ 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65,
+ 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a,
+ 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c,
+ 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61,
+ 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69,
+ 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65,
+ 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66,
+ 0x6f, 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c,
+ 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x79, 0x0a, 0x18, 0x6e, 0x69,
+ 0x6e, 0x6a, 0x61, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x73,
0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x08,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0x37, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x66,
- 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a,
- 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d,
- 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65,
- 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d,
- 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73,
- 0x5f, 0x6b, 0x62, 0x18, 0x04, 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, 0x05, 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, 0x06, 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, 0x07, 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, 0x08, 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, 0x09, 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, 0x0a, 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, 0x22, 0xe5, 0x01,
- 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f,
- 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
- 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a,
- 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24,
- 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73,
- 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
- 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d,
- 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
- 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55,
- 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55,
- 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0x94, 0x03, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e,
- 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a,
- 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
- 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61,
- 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61,
- 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c,
- 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f,
- 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
- 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73,
- 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c,
- 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78,
- 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a,
- 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
+ 0x63, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4e,
+ 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x3a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x52, 0x15,
+ 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x47, 0x0a, 0x0e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x65,
+ 0x6e, 0x76, 0x5f, 0x76, 0x61, 0x72, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76,
- 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
- 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x0d, 0x70, 0x65, 0x72, 0x66, 0x5f, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e,
+ 0x69, 0x63, 0x73, 0x2e, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73,
+ 0x52, 0x0c, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 0x73, 0x12, 0x1d,
+ 0x0a, 0x0a, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x0a, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x09, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x74, 0x0a,
+ 0x15, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74,
+ 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53,
+ 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x4e, 0x4a, 0x41, 0x5f, 0x4c, 0x4f,
+ 0x47, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x45, 0x56, 0x45, 0x4e, 0x4c, 0x59, 0x5f, 0x44, 0x49,
+ 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45,
+ 0x58, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13,
+ 0x0a, 0x0f, 0x48, 0x49, 0x4e, 0x54, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x4f, 0x4e,
+ 0x47, 0x10, 0x04, 0x22, 0x67, 0x0a, 0x0c, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x6e, 0x76, 0x56,
+ 0x61, 0x72, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63,
+ 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61,
+ 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x13,
+ 0x75, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
+ 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x50, 0x61,
+ 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x22, 0xed, 0x01, 0x0a,
+ 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
+ 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79,
+ 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61,
+ 0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c,
+ 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x12, 0x3d,
+ 0x0a, 0x08, 0x63, 0x70, 0x75, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x22, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x63, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a,
+ 0x08, 0x6d, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x22, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49,
+ 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x7e, 0x0a, 0x0d,
+ 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, 0x70, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a,
+ 0x09, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x08, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f,
+ 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75,
+ 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x70,
+ 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x6c, 0x0a, 0x0d,
+ 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a,
+ 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65,
+ 0x6d, 0x5f, 0x66, 0x72, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65,
+ 0x6d, 0x46, 0x72, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x61,
+ 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x65,
+ 0x6d, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50,
+ 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09,
+ 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18,
+ 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
- 0x52, 0x0c, 0x70, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0xdb,
- 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63,
- 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
- 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d,
- 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63,
- 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61,
- 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47,
- 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09,
- 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53,
- 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a,
- 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f,
- 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
- 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12,
- 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64,
- 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
- 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74,
- 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64,
- 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d,
- 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
- 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72,
- 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63,
- 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
- 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74,
- 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f,
- 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50,
- 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e,
- 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c,
+ 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22,
+ 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78,
+ 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x61, 0x0a, 0x0c, 0x50, 0x65, 0x72, 0x66, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x67,
+ 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f,
+ 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x64, 0x0a, 0x10, 0x50, 0x65,
+ 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12,
+ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
+ 0x22, 0x37, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66,
+ 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12,
+ 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d,
+ 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a,
+ 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 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, 0x05, 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, 0x06, 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, 0x07, 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, 0x08, 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, 0x09, 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, 0x0a, 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, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f,
0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6c, 0x6f,
- 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x62, 0x0a,
- 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70,
- 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69,
- 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6a, 0x6f, 0x62, 0x5f,
- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x22, 0xb9, 0x05, 0x0a, 0x15, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42,
- 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x61,
- 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
- 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66,
- 0x6f, 0x52, 0x0c, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x50, 0x65, 0x72, 0x66, 0x12,
- 0x44, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72,
- 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65,
- 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e,
- 0x67, 0x50, 0x65, 0x72, 0x66, 0x12, 0x68, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
- 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49,
+ 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a,
+ 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53,
+ 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66,
+ 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c,
+ 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b,
+ 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55,
+ 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e,
+ 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a,
+ 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75,
+ 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+ 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61,
+ 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e,
+ 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75,
+ 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e,
+ 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22,
+ 0x94, 0x03, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12,
+ 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74,
+ 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c,
+ 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a,
+ 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69,
+ 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61,
+ 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18,
+ 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11,
+ 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66,
+ 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69,
+ 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46,
+ 0x0a, 0x0d, 0x70, 0x65, 0x72, 0x66, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18,
+ 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0c, 0x70, 0x65, 0x72, 0x66, 0x43, 0x6f,
+ 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68,
+ 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52,
+ 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e,
+ 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f,
+ 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10,
+ 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45,
+ 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75,
+ 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65,
+ 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
+ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+ 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a,
+ 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69,
+ 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70,
+ 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a,
+ 0x19, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74,
+ 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x16, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69,
+ 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73,
+ 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e,
+ 0x67, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f,
+ 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65,
+ 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
+ 0x12, 0x27, 0x0a, 0x0f, 0x6a, 0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x05, 0x0a, 0x15, 0x4f, 0x70,
+ 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x12, 0x42, 0x0a, 0x0d, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x5f,
+ 0x70, 0x65, 0x72, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x61, 0x6e, 0x61, 0x6c, 0x79,
+ 0x73, 0x69, 0x73, 0x50, 0x65, 0x72, 0x66, 0x12, 0x44, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61,
+ 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d,
+ 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x66, 0x12, 0x68, 0x0a,
+ 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d,
+ 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65,
+ 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0xab, 0x03, 0x0a, 0x18, 0x54, 0x61, 0x72, 0x67,
+ 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x69,
+ 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x70, 0x74,
+ 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x16, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69,
+ 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x12, 0x44, 0x0a,
+ 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50,
+ 0x65, 0x72, 0x66, 0x12, 0x7b, 0x0a, 0x0f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x61, 0x72,
+ 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x52, 0x2e, 0x73,
0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f,
0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c,
- 0x74, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a,
- 0xab, 0x03, 0x0a, 0x18, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69,
- 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x35,
- 0x0a, 0x16, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15,
- 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x12, 0x44, 0x0a, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x69,
- 0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
- 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x70, 0x61,
- 0x63, 0x6b, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x66, 0x12, 0x7b, 0x0a, 0x0f, 0x6f,
- 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x05,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x52, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d,
- 0x69, 0x7a, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
- 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
- 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x1a, 0x63, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x70,
- 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12,
- 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69,
- 0x7a, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x5f, 0x6d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e,
- 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x28, 0x5a,
- 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75,
- 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+ 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
+ 0x1a, 0x63, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
+ 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e,
+ 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x4d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+ 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, 0x12, 0x4c, 0x0a,
+ 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65,
+ 0x67, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x63,
+ 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x12,
+ 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69,
+ 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+ 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
+ 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65,
+ 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64,
+ 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61,
+ 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74,
+ 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
+ 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
+ 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+ 0x73, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73,
+ 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -2656,7 +3006,7 @@
}
var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
-var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
var file_metrics_proto_goTypes = []interface{}{
(MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
(MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
@@ -2665,68 +3015,75 @@
(ExpConfigFetcher_ConfigStatus)(0), // 4: soong_build_metrics.ExpConfigFetcher.ConfigStatus
(*MetricsBase)(nil), // 5: soong_build_metrics.MetricsBase
(*BuildConfig)(nil), // 6: soong_build_metrics.BuildConfig
- (*SystemResourceInfo)(nil), // 7: soong_build_metrics.SystemResourceInfo
- (*SystemCpuInfo)(nil), // 8: soong_build_metrics.SystemCpuInfo
- (*SystemMemInfo)(nil), // 9: soong_build_metrics.SystemMemInfo
- (*PerfInfo)(nil), // 10: soong_build_metrics.PerfInfo
- (*PerfCounters)(nil), // 11: soong_build_metrics.PerfCounters
- (*PerfCounterGroup)(nil), // 12: soong_build_metrics.PerfCounterGroup
- (*PerfCounter)(nil), // 13: soong_build_metrics.PerfCounter
- (*ProcessResourceInfo)(nil), // 14: soong_build_metrics.ProcessResourceInfo
- (*ModuleTypeInfo)(nil), // 15: soong_build_metrics.ModuleTypeInfo
- (*CriticalUserJourneyMetrics)(nil), // 16: soong_build_metrics.CriticalUserJourneyMetrics
- (*CriticalUserJourneysMetrics)(nil), // 17: soong_build_metrics.CriticalUserJourneysMetrics
- (*SoongBuildMetrics)(nil), // 18: soong_build_metrics.SoongBuildMetrics
- (*ExpConfigFetcher)(nil), // 19: soong_build_metrics.ExpConfigFetcher
- (*MixedBuildsInfo)(nil), // 20: soong_build_metrics.MixedBuildsInfo
- (*CriticalPathInfo)(nil), // 21: soong_build_metrics.CriticalPathInfo
- (*JobInfo)(nil), // 22: soong_build_metrics.JobInfo
- (*OptimizedBuildMetrics)(nil), // 23: soong_build_metrics.OptimizedBuildMetrics
- (*OptimizedBuildMetrics_TargetOptimizationResult)(nil), // 24: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
- (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact)(nil), // 25: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
+ (*SoongEnvVars)(nil), // 7: soong_build_metrics.SoongEnvVars
+ (*SystemResourceInfo)(nil), // 8: soong_build_metrics.SystemResourceInfo
+ (*SystemCpuInfo)(nil), // 9: soong_build_metrics.SystemCpuInfo
+ (*SystemMemInfo)(nil), // 10: soong_build_metrics.SystemMemInfo
+ (*PerfInfo)(nil), // 11: soong_build_metrics.PerfInfo
+ (*PerfCounters)(nil), // 12: soong_build_metrics.PerfCounters
+ (*PerfCounterGroup)(nil), // 13: soong_build_metrics.PerfCounterGroup
+ (*PerfCounter)(nil), // 14: soong_build_metrics.PerfCounter
+ (*ProcessResourceInfo)(nil), // 15: soong_build_metrics.ProcessResourceInfo
+ (*ModuleTypeInfo)(nil), // 16: soong_build_metrics.ModuleTypeInfo
+ (*CriticalUserJourneyMetrics)(nil), // 17: soong_build_metrics.CriticalUserJourneyMetrics
+ (*CriticalUserJourneysMetrics)(nil), // 18: soong_build_metrics.CriticalUserJourneysMetrics
+ (*SoongBuildMetrics)(nil), // 19: soong_build_metrics.SoongBuildMetrics
+ (*ExpConfigFetcher)(nil), // 20: soong_build_metrics.ExpConfigFetcher
+ (*MixedBuildsInfo)(nil), // 21: soong_build_metrics.MixedBuildsInfo
+ (*CriticalPathInfo)(nil), // 22: soong_build_metrics.CriticalPathInfo
+ (*JobInfo)(nil), // 23: soong_build_metrics.JobInfo
+ (*OptimizedBuildMetrics)(nil), // 24: soong_build_metrics.OptimizedBuildMetrics
+ (*ExecutionMetrics)(nil), // 25: soong_build_metrics.ExecutionMetrics
+ (*AggregatedFileList)(nil), // 26: soong_build_metrics.AggregatedFileList
+ (*FileCount)(nil), // 27: soong_build_metrics.FileCount
+ (*OptimizedBuildMetrics_TargetOptimizationResult)(nil), // 28: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
+ (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact)(nil), // 29: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
}
var file_metrics_proto_depIdxs = []int32{
0, // 0: soong_build_metrics.MetricsBase.target_build_variant:type_name -> soong_build_metrics.MetricsBase.BuildVariant
1, // 1: soong_build_metrics.MetricsBase.target_arch:type_name -> soong_build_metrics.MetricsBase.Arch
1, // 2: soong_build_metrics.MetricsBase.host_arch:type_name -> soong_build_metrics.MetricsBase.Arch
1, // 3: soong_build_metrics.MetricsBase.host_2nd_arch:type_name -> soong_build_metrics.MetricsBase.Arch
- 10, // 4: soong_build_metrics.MetricsBase.setup_tools:type_name -> soong_build_metrics.PerfInfo
- 10, // 5: soong_build_metrics.MetricsBase.kati_runs:type_name -> soong_build_metrics.PerfInfo
- 10, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
- 10, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
- 10, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
- 18, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
+ 11, // 4: soong_build_metrics.MetricsBase.setup_tools:type_name -> soong_build_metrics.PerfInfo
+ 11, // 5: soong_build_metrics.MetricsBase.kati_runs:type_name -> soong_build_metrics.PerfInfo
+ 11, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
+ 11, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
+ 11, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
+ 19, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
6, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
- 7, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
- 10, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
- 19, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
- 21, // 14: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
- 23, // 15: soong_build_metrics.MetricsBase.optimized_build_metrics:type_name -> soong_build_metrics.OptimizedBuildMetrics
+ 8, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
+ 11, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
+ 20, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
+ 22, // 14: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
+ 24, // 15: soong_build_metrics.MetricsBase.optimized_build_metrics:type_name -> soong_build_metrics.OptimizedBuildMetrics
2, // 16: soong_build_metrics.BuildConfig.ninja_weight_list_source:type_name -> soong_build_metrics.BuildConfig.NinjaWeightListSource
- 8, // 17: soong_build_metrics.SystemResourceInfo.cpu_info:type_name -> soong_build_metrics.SystemCpuInfo
- 9, // 18: soong_build_metrics.SystemResourceInfo.mem_info:type_name -> soong_build_metrics.SystemMemInfo
- 14, // 19: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
- 12, // 20: soong_build_metrics.PerfCounters.groups:type_name -> soong_build_metrics.PerfCounterGroup
- 13, // 21: soong_build_metrics.PerfCounterGroup.counters:type_name -> soong_build_metrics.PerfCounter
- 3, // 22: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
- 5, // 23: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
- 16, // 24: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
- 10, // 25: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
- 20, // 26: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
- 11, // 27: soong_build_metrics.SoongBuildMetrics.perf_counters:type_name -> soong_build_metrics.PerfCounters
- 4, // 28: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
- 22, // 29: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
- 22, // 30: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
- 10, // 31: soong_build_metrics.OptimizedBuildMetrics.analysis_perf:type_name -> soong_build_metrics.PerfInfo
- 10, // 32: soong_build_metrics.OptimizedBuildMetrics.packaging_perf:type_name -> soong_build_metrics.PerfInfo
- 24, // 33: soong_build_metrics.OptimizedBuildMetrics.target_result:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
- 10, // 34: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.packaging_perf:type_name -> soong_build_metrics.PerfInfo
- 25, // 35: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.output_artifact:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
- 36, // [36:36] is the sub-list for method output_type
- 36, // [36:36] is the sub-list for method input_type
- 36, // [36:36] is the sub-list for extension type_name
- 36, // [36:36] is the sub-list for extension extendee
- 0, // [0:36] is the sub-list for field type_name
+ 7, // 17: soong_build_metrics.BuildConfig.soong_env_vars:type_name -> soong_build_metrics.SoongEnvVars
+ 9, // 18: soong_build_metrics.SystemResourceInfo.cpu_info:type_name -> soong_build_metrics.SystemCpuInfo
+ 10, // 19: soong_build_metrics.SystemResourceInfo.mem_info:type_name -> soong_build_metrics.SystemMemInfo
+ 15, // 20: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
+ 13, // 21: soong_build_metrics.PerfCounters.groups:type_name -> soong_build_metrics.PerfCounterGroup
+ 14, // 22: soong_build_metrics.PerfCounterGroup.counters:type_name -> soong_build_metrics.PerfCounter
+ 3, // 23: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
+ 5, // 24: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
+ 17, // 25: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
+ 11, // 26: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
+ 21, // 27: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
+ 12, // 28: soong_build_metrics.SoongBuildMetrics.perf_counters:type_name -> soong_build_metrics.PerfCounters
+ 4, // 29: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ 23, // 30: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
+ 23, // 31: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
+ 11, // 32: soong_build_metrics.OptimizedBuildMetrics.analysis_perf:type_name -> soong_build_metrics.PerfInfo
+ 11, // 33: soong_build_metrics.OptimizedBuildMetrics.packaging_perf:type_name -> soong_build_metrics.PerfInfo
+ 28, // 34: soong_build_metrics.OptimizedBuildMetrics.target_result:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
+ 26, // 35: soong_build_metrics.ExecutionMetrics.changed_files:type_name -> soong_build_metrics.AggregatedFileList
+ 27, // 36: soong_build_metrics.AggregatedFileList.counts:type_name -> soong_build_metrics.FileCount
+ 11, // 37: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.packaging_perf:type_name -> soong_build_metrics.PerfInfo
+ 29, // 38: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.output_artifact:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
+ 39, // [39:39] is the sub-list for method output_type
+ 39, // [39:39] is the sub-list for method input_type
+ 39, // [39:39] is the sub-list for extension type_name
+ 39, // [39:39] is the sub-list for extension extendee
+ 0, // [0:39] is the sub-list for field type_name
}
func init() { file_metrics_proto_init() }
@@ -2760,7 +3117,7 @@
}
}
file_metrics_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SystemResourceInfo); i {
+ switch v := v.(*SoongEnvVars); i {
case 0:
return &v.state
case 1:
@@ -2772,7 +3129,7 @@
}
}
file_metrics_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SystemCpuInfo); i {
+ switch v := v.(*SystemResourceInfo); i {
case 0:
return &v.state
case 1:
@@ -2784,7 +3141,7 @@
}
}
file_metrics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SystemMemInfo); i {
+ switch v := v.(*SystemCpuInfo); i {
case 0:
return &v.state
case 1:
@@ -2796,7 +3153,7 @@
}
}
file_metrics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PerfInfo); i {
+ switch v := v.(*SystemMemInfo); i {
case 0:
return &v.state
case 1:
@@ -2808,7 +3165,7 @@
}
}
file_metrics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PerfCounters); i {
+ switch v := v.(*PerfInfo); i {
case 0:
return &v.state
case 1:
@@ -2820,7 +3177,7 @@
}
}
file_metrics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PerfCounterGroup); i {
+ switch v := v.(*PerfCounters); i {
case 0:
return &v.state
case 1:
@@ -2832,7 +3189,7 @@
}
}
file_metrics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PerfCounter); i {
+ switch v := v.(*PerfCounterGroup); i {
case 0:
return &v.state
case 1:
@@ -2844,7 +3201,7 @@
}
}
file_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ProcessResourceInfo); i {
+ switch v := v.(*PerfCounter); i {
case 0:
return &v.state
case 1:
@@ -2856,7 +3213,7 @@
}
}
file_metrics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ModuleTypeInfo); i {
+ switch v := v.(*ProcessResourceInfo); i {
case 0:
return &v.state
case 1:
@@ -2868,7 +3225,7 @@
}
}
file_metrics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalUserJourneyMetrics); i {
+ switch v := v.(*ModuleTypeInfo); i {
case 0:
return &v.state
case 1:
@@ -2880,7 +3237,7 @@
}
}
file_metrics_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalUserJourneysMetrics); i {
+ switch v := v.(*CriticalUserJourneyMetrics); i {
case 0:
return &v.state
case 1:
@@ -2892,7 +3249,7 @@
}
}
file_metrics_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SoongBuildMetrics); i {
+ switch v := v.(*CriticalUserJourneysMetrics); i {
case 0:
return &v.state
case 1:
@@ -2904,7 +3261,7 @@
}
}
file_metrics_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ExpConfigFetcher); i {
+ switch v := v.(*SoongBuildMetrics); i {
case 0:
return &v.state
case 1:
@@ -2916,7 +3273,7 @@
}
}
file_metrics_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*MixedBuildsInfo); i {
+ switch v := v.(*ExpConfigFetcher); i {
case 0:
return &v.state
case 1:
@@ -2928,7 +3285,7 @@
}
}
file_metrics_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalPathInfo); i {
+ switch v := v.(*MixedBuildsInfo); i {
case 0:
return &v.state
case 1:
@@ -2940,7 +3297,7 @@
}
}
file_metrics_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*JobInfo); i {
+ switch v := v.(*CriticalPathInfo); i {
case 0:
return &v.state
case 1:
@@ -2952,7 +3309,7 @@
}
}
file_metrics_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OptimizedBuildMetrics); i {
+ switch v := v.(*JobInfo); i {
case 0:
return &v.state
case 1:
@@ -2964,7 +3321,7 @@
}
}
file_metrics_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult); i {
+ switch v := v.(*OptimizedBuildMetrics); i {
case 0:
return &v.state
case 1:
@@ -2976,6 +3333,54 @@
}
}
file_metrics_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ExecutionMetrics); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AggregatedFileList); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FileCount); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact); i {
case 0:
return &v.state
@@ -2994,7 +3399,7 @@
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_metrics_proto_rawDesc,
NumEnums: 5,
- NumMessages: 21,
+ NumMessages: 25,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 3fbe97c..7ff389a 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -140,6 +140,9 @@
// Metrics related to optimized builds.
optional OptimizedBuildMetrics optimized_build_metrics = 35;
+
+ // The target release information. e.g., trunk_staging.
+ optional string target_release = 36;
}
message BuildConfig {
@@ -177,6 +180,21 @@
// EXTERNAL_FILE - ninja uses an external custom weight list
// HINT_FROM_SOONG - ninja uses a prioritized module list from Soong
optional NinjaWeightListSource ninja_weight_list_source = 8 [default = NOT_USED];
+
+ // Values of some build-affecting environment variables.
+ optional SoongEnvVars soong_env_vars = 9;
+
+ // Whether this build uses soong-only (no kati) mode (either via environment variable,
+ // command line flag or product config.
+ optional bool soong_only = 10;
+}
+
+message SoongEnvVars {
+ // SOONG_PARTIAL_COMPILE
+ optional string partial_compile = 1;
+
+ // SOONG_USE_PARTIAL_COMPILE
+ optional string use_partial_compile = 2;
}
message SystemResourceInfo {
@@ -451,3 +469,48 @@
}
}
}
+
+// This is created by soong_ui from SoongExexcutionMetrics files.
+message ExecutionMetrics {
+ // The arguments provided on the command line.
+ repeated string command_args = 1;
+
+ // Changed files detected by the build.
+ optional AggregatedFileList changed_files = 2;
+}
+
+// This is created by soong_ui from the various
+// android.find_input_delta_proto.FileList metrics provided to it by
+// find_input_delta.
+message AggregatedFileList {
+ // The (possibly truncated list of) added files.
+ repeated string additions = 2;
+
+ // The (possibly truncated list of) changed files.
+ repeated string changes = 3;
+
+ // The (possibly truncated list of) deleted files.
+ repeated string deletions = 4;
+
+ // Count of files added/changed/deleted.
+ optional uint32 total_delta = 5;
+
+ // Counts by extension.
+ repeated FileCount counts = 6;
+
+ reserved 1;
+}
+
+message FileCount {
+ // The file extension
+ optional string extension = 1;
+
+ // Number of added files with this extension.
+ optional uint32 additions = 2;
+
+ // Number of modified files with this extension.
+ optional uint32 modifications = 3;
+
+ // Number of deleted files with this extension.
+ optional uint32 deletions = 4;
+}
diff --git a/ui/metrics/metrics_proto/regen.sh b/ui/metrics/metrics_proto/regen.sh
index 5e5f9b8..8eb2d74 100755
--- a/ui/metrics/metrics_proto/regen.sh
+++ b/ui/metrics/metrics_proto/regen.sh
@@ -12,6 +12,6 @@
die "could not find aprotoc. ${error_msg}"
fi
-if ! aprotoc --go_out=paths=source_relative:. -I .:../../.. metrics.proto combined_metrics.proto; then
+if ! aprotoc --go_out=paths=source_relative:. metrics.proto; then
die "build failed. ${error_msg}"
fi
diff --git a/ui/metrics/proc/status_linux_test.go b/ui/metrics/proc/status_linux_test.go
index 6709850..0edc400 100644
--- a/ui/metrics/proc/status_linux_test.go
+++ b/ui/metrics/proc/status_linux_test.go
@@ -1,7 +1,6 @@
package proc
import (
- "fmt"
"path/filepath"
"reflect"
"strconv"
@@ -29,7 +28,6 @@
t.Fatalf("got %v, want nil for error", err)
}
- fmt.Printf("%d %d\b", status.VmPeak, expectedStatus.VmPeak)
if !reflect.DeepEqual(status, expectedStatus) {
t.Errorf("got %v, expecting %v for ProcStatus", status, expectedStatus)
}
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 8c3ff29..73edbf6 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -46,6 +46,7 @@
forceClose: make(chan bool),
done: make(chan bool),
cancelOpen: make(chan bool),
+ running: make(map[uint32]*Action),
}
go n.run()
@@ -59,6 +60,7 @@
forceClose chan bool
done chan bool
cancelOpen chan bool
+ running map[uint32]*Action
}
const NINJA_READER_CLOSE_TIMEOUT = 5 * time.Second
@@ -68,32 +70,47 @@
// Signal the goroutine to stop if it is blocking opening the fifo.
close(n.cancelOpen)
+ closed := false
+
// Ninja should already have exited or been killed, wait 5 seconds for the FIFO to be closed and any
// remaining messages to be processed through the NinjaReader.run goroutine.
timeoutCh := time.After(NINJA_READER_CLOSE_TIMEOUT)
select {
case <-n.done:
- return
+ closed = true
case <-timeoutCh:
// Channel is not closed yet
}
- n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+ if !closed {
+ n.status.Error(fmt.Sprintf("ninja fifo didn't finish after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
- // Force close the reader even if the FIFO didn't close.
- close(n.forceClose)
+ // Force close the reader even if the FIFO didn't close.
+ close(n.forceClose)
- // Wait again for the reader thread to acknowledge the close before giving up and assuming it isn't going
- // to send anything else.
- timeoutCh = time.After(NINJA_READER_CLOSE_TIMEOUT)
- select {
- case <-n.done:
- return
- case <-timeoutCh:
- // Channel is not closed yet
+ // Wait again for the reader thread to acknowledge the close before giving up and assuming it isn't going
+ // to send anything else.
+ timeoutCh = time.After(NINJA_READER_CLOSE_TIMEOUT)
+ select {
+ case <-n.done:
+ closed = true
+ case <-timeoutCh:
+ // Channel is not closed yet
+ }
}
- n.status.Verbose(fmt.Sprintf("ninja fifo didn't finish even after force closing after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+ if !closed {
+ n.status.Verbose(fmt.Sprintf("ninja fifo didn't finish even after force closing after %s", NINJA_READER_CLOSE_TIMEOUT.String()))
+ }
+
+ err := fmt.Errorf("error: action cancelled when ninja exited")
+ for _, action := range n.running {
+ n.status.FinishAction(ActionResult{
+ Action: action,
+ Output: err.Error(),
+ Error: err,
+ })
+ }
}
func (n *NinjaReader) run() {
@@ -125,8 +142,6 @@
r := bufio.NewReader(f)
- running := map[uint32]*Action{}
-
msgChan := make(chan *ninja_frontend.Status)
// Read from the ninja fifo and decode the protobuf in a goroutine so the main NinjaReader.run goroutine
@@ -213,11 +228,11 @@
ChangedInputs: msg.EdgeStarted.ChangedInputs,
}
n.status.StartAction(action)
- running[msg.EdgeStarted.GetId()] = action
+ n.running[msg.EdgeStarted.GetId()] = action
}
if msg.EdgeFinished != nil {
- if started, ok := running[msg.EdgeFinished.GetId()]; ok {
- delete(running, msg.EdgeFinished.GetId())
+ if started, ok := n.running[msg.EdgeFinished.GetId()]; ok {
+ delete(n.running, msg.EdgeFinished.GetId())
var err error
exitCode := int(msg.EdgeFinished.GetStatus())
diff --git a/vnames.json b/vnames.json
index 096260f..9e006bb 100644
--- a/vnames.json
+++ b/vnames.json
@@ -1,5 +1,17 @@
[
{
+ "pattern": "out/(.*)/srcjars.xref/frameworks/base/services/core/(.*)/android/server/am/(.*)",
+ "vname": {
+ "path": "frameworks/base/services/core/@2@/android/server/am/@3@"
+ }
+ },
+ {
+ "pattern": "out/(.*)/srcjars.xref/frameworks/base/services/core/(.*)/android/server/wm/(.*)",
+ "vname": {
+ "path": "frameworks/base/services/core/@2@/android/server/wm/@3@"
+ }
+ },
+ {
"pattern": "out/(.*)",
"vname": {
"root": "out",
diff --git a/xml/xml_test.go b/xml/xml_test.go
index a59a293..212b0c5 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -71,7 +71,7 @@
{rule: "xmllint-minimal", input: "baz.xml"},
} {
t.Run(tc.schemaType, func(t *testing.T) {
- rule := result.ModuleForTests(tc.input, "android_arm64_armv8-a").Rule(tc.rule)
+ rule := result.ModuleForTests(t, tc.input, "android_arm64_armv8-a").Rule(tc.rule)
android.AssertStringEquals(t, "input", tc.input, rule.Input.String())
if tc.schemaType != "" {
android.AssertStringEquals(t, "schema", tc.schema, rule.Args[tc.schemaType])
@@ -79,6 +79,6 @@
})
}
- m := result.ModuleForTests("foo.xml", "android_arm64_armv8-a").Module().(*prebuiltEtcXml)
- android.AssertPathRelativeToTopEquals(t, "installDir", "out/soong/target/product/test_device/system/etc", m.InstallDirPath())
+ m := result.ModuleForTests(t, "foo.xml", "android_arm64_armv8-a").Module().(*prebuiltEtcXml)
+ android.AssertPathRelativeToTopEquals(t, "installDir", "out/target/product/test_device/system/etc", m.InstallDirPath())
}
diff --git a/zip/zip.go b/zip/zip.go
index f91a5f2..22b7704 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -475,13 +475,50 @@
return nil
}
+func (z *ZipWriter) moveJavaFileBasedOnPackage(mapping *pathMapping) error {
+ src := mapping.src
+ var s os.FileInfo
+ var err error
+ if z.followSymlinks {
+ s, err = z.fs.Stat(src)
+ } else {
+ s, err = z.fs.Lstat(src)
+ }
+ if err != nil {
+ if os.IsNotExist(err) && z.ignoreMissingFiles {
+ return nil
+ }
+ return err
+ }
+ if !s.Mode().IsRegular() {
+ return nil
+ }
+ r, err := z.fs.Open(src)
+ if err != nil {
+ return err
+ }
+ // rewrite the destination using the package path if it can be determined
+ pkg, err := jar.JavaPackage(r, src)
+ err2 := r.Close()
+ if err2 != nil {
+ return err2
+ }
+ if err != nil {
+ // ignore errors for now, leaving the file at in its original location in the zip
+ } else {
+ mapping.dest = filepath.Join(filepath.Join(strings.Split(pkg, ".")...), filepath.Base(src))
+ }
+ return nil
+}
+
func jarSort(mappings []pathMapping) {
sort.SliceStable(mappings, func(i int, j int) bool {
return jar.EntryNamesLess(mappings[i].dest, mappings[j].dest)
})
}
-func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string, emulateJar, srcJar bool,
+func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string,
+ emulateJar, srcJar bool,
parallelJobs int) error {
z.errors = make(chan error)
@@ -511,11 +548,41 @@
return errors.New("must specify --jar when specifying a manifest via -m")
}
+ // move java source files to the correct folder based on the package statement inside of them.
+ // This is done before the entry sorting so that they're still in the right order.
+ if srcJar {
+ var javaMoveErrors []error
+ var javaMoveErrorsLock sync.Mutex
+ var wg sync.WaitGroup
+ for i := range pathMappings {
+ if filepath.Ext(pathMappings[i].src) == ".java" {
+ wg.Add(1)
+ go func() {
+ err := z.moveJavaFileBasedOnPackage(&pathMappings[i])
+ if err != nil {
+ javaMoveErrorsLock.Lock()
+ javaMoveErrors = append(javaMoveErrors, err)
+ javaMoveErrorsLock.Unlock()
+ }
+ wg.Done()
+ }()
+ }
+ }
+ wg.Wait()
+ if len(javaMoveErrors) > 0 {
+ return errors.Join(javaMoveErrors...)
+ }
+ }
+
if emulateJar {
// manifest may be empty, in which case addManifest will fill in a default
pathMappings = append(pathMappings, pathMapping{jar.ManifestFile, manifest, zip.Deflate})
jarSort(pathMappings)
+ } else {
+ sort.SliceStable(pathMappings, func(i int, j int) bool {
+ return pathMappings[i].dest < pathMappings[j].dest
+ })
}
go func() {
@@ -526,7 +593,7 @@
if emulateJar && ele.dest == jar.ManifestFile {
err = z.addManifest(ele.dest, ele.src, ele.zipMethod)
} else {
- err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar, srcJar)
+ err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar)
}
if err != nil {
z.errors <- err
@@ -625,7 +692,7 @@
}
// imports (possibly with compression) <src> into the zip at sub-path <dest>
-func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar, srcJar bool) error {
+func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar bool) error {
var fileSize int64
var executable bool
@@ -699,21 +766,6 @@
return err
}
- if srcJar && filepath.Ext(src) == ".java" {
- // rewrite the destination using the package path if it can be determined
- pkg, err := jar.JavaPackage(r, src)
- if err != nil {
- // ignore errors for now, leaving the file at in its original location in the zip
- } else {
- dest = filepath.Join(filepath.Join(strings.Split(pkg, ".")...), filepath.Base(src))
- }
-
- _, err = r.Seek(0, io.SeekStart)
- if err != nil {
- return err
- }
- }
-
fileSize = s.Size()
executable = s.Mode()&0100 != 0
diff --git a/zip/zip_test.go b/zip/zip_test.go
index c64c3f4..8f100d8 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -159,10 +159,10 @@
compressionLevel: 9,
files: []zip.FileHeader{
+ fh("[", fileEmpty, zip.Store),
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
fh("c", fileC, zip.Deflate),
- fh("[", fileEmpty, zip.Store),
},
},
{
@@ -261,10 +261,10 @@
compressionLevel: 9,
files: []zip.FileHeader{
+ fh("[", fileEmpty, zip.Store),
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
fh("c", fileC, zip.Deflate),
- fh("[", fileEmpty, zip.Store),
},
},
{
@@ -274,10 +274,10 @@
compressionLevel: 9,
files: []zip.FileHeader{
+ fh("[", fileEmpty, zip.Store),
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
fh("c", fileC, zip.Deflate),
- fh("[", fileEmpty, zip.Store),
},
},
{
@@ -287,11 +287,11 @@
compressionLevel: 9,
files: []zip.FileHeader{
+ fh("@", fileC, zip.Deflate),
+ fh("[", fileEmpty, zip.Store),
fh("a/a/a", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
- fh("@", fileC, zip.Deflate),
fh("foo'bar", fileC, zip.Deflate),
- fh("[", fileEmpty, zip.Store),
},
},
{
@@ -463,8 +463,8 @@
compressionLevel: 9,
files: []zip.FileHeader{
- fh("foo", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
+ fh("foo", fileA, zip.Deflate),
},
},
{
@@ -477,8 +477,8 @@
compressionLevel: 9,
files: []zip.FileHeader{
- fh("prefix/foo", fileA, zip.Deflate),
fh("prefix/a/a/b", fileB, zip.Deflate),
+ fh("prefix/foo", fileA, zip.Deflate),
},
},
{
@@ -490,8 +490,8 @@
compressionLevel: 9,
files: []zip.FileHeader{
- fh("foo", fileA, zip.Deflate),
fh("a/a/b", fileB, zip.Deflate),
+ fh("foo", fileA, zip.Deflate),
},
},
{
@@ -504,8 +504,8 @@
compressionLevel: 9,
files: []zip.FileHeader{
- fh("foo/bar", fileA, zip.Deflate),
fh("b", fileB, zip.Deflate),
+ fh("foo/bar", fileA, zip.Deflate),
},
},
@@ -688,8 +688,8 @@
want := []string{
"foo/",
- "foo/wrong_package.java",
"foo/correct_package.java",
+ "foo/wrong_package.java",
"no_package.java",
"src2/",
"src2/parse_error.java",