Merge "Revert "Add product variable SelinuxIgnoreNeverallows for sepolicy"" into main
diff --git a/Android.bp b/Android.bp
index 0d1ff02..d71bcec 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,9 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_visibility: [
+ "//build/soong:__subpackages__",
+ ],
+ default_team: "trendy_team_build",
}
subdirs = [
@@ -23,6 +27,8 @@
srcs: [
"doc.go",
],
+ // Used by plugins, though probably shouldn't be.
+ visibility: ["//visibility:public"],
}
//
@@ -40,6 +46,7 @@
enabled: true,
},
},
+ defaults_visibility: ["//visibility:public"],
}
//
@@ -51,6 +58,7 @@
vendor: true,
recovery_available: true,
min_sdk_version: "apex_inherit",
+ visibility: ["//visibility:public"],
}
cc_genrule {
@@ -75,6 +83,7 @@
cmd: "$(location) -s $(out) $(in)",
srcs: [":linker"],
out: ["linker.s"],
+ visibility: ["//bionic/libc"],
}
cc_genrule {
@@ -99,12 +108,18 @@
cmd: "$(location) -T $(out) $(in)",
srcs: [":linker"],
out: ["linker.script"],
+ visibility: ["//visibility:public"],
}
// Instantiate the dex_bootjars singleton module.
dex_bootjars {
name: "dex_bootjars",
- no_full_install: true,
+ visibility: ["//visibility:public"],
+}
+
+art_boot_images {
+ name: "art_boot_images",
+ visibility: ["//art:__subpackages__"],
}
// Pseudo-test that's run on checkbuilds to ensure that get_clang_version can
@@ -121,26 +136,53 @@
name: "dexpreopt_systemserver_check",
}
-// buildinfo.prop contains common properties for system/build.prop, like ro.build.version.*
-// TODO(b/322090587): merge this to gen_build_prop.py script.
-buildinfo_prop {
- name: "buildinfo.prop",
-
- // not installable because this will be included to system/build.prop
- installable: false,
-
- product_config: ":product_config",
-
- // Currently, only microdroid can refer to buildinfo.prop
- visibility: ["//packages/modules/Virtualization/build/microdroid"],
-}
-
// container for apex_contributions selected using build flags
all_apex_contributions {
name: "all_apex_contributions",
+ visibility: ["//visibility:public"],
}
product_config {
name: "product_config",
- visibility: ["//device/google/cuttlefish/system_image"],
+ visibility: [
+ "//build/make/target/product/generic",
+ ],
+}
+
+build_prop {
+ name: "system-build.prop",
+ stem: "build.prop",
+ product_config: ":product_config",
+ // Currently, only microdroid and cf system image can refer to system-build.prop
+ visibility: [
+ "//build/make/target/product/generic",
+ "//packages/modules/Virtualization/build/microdroid",
+ ],
+}
+
+build_prop {
+ name: "system_ext-build.prop",
+ stem: "build.prop",
+ system_ext_specific: true,
+ product_config: ":product_config",
+ relative_install_path: "etc", // system_ext/etc/build.prop
+ visibility: ["//visibility:private"],
+}
+
+build_prop {
+ name: "product-build.prop",
+ stem: "build.prop",
+ product_specific: true,
+ product_config: ":product_config",
+ relative_install_path: "etc", // product/etc/build.prop
+ visibility: ["//visibility:private"],
+}
+
+build_prop {
+ name: "odm-build.prop",
+ stem: "build.prop",
+ device_specific: true,
+ product_config: ":product_config",
+ relative_install_path: "etc", // odm/etc/build.prop
+ visibility: ["//visibility:private"],
}
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 9e3d291..d9a862c 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -88,6 +88,13 @@
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.
@@ -219,16 +226,4 @@
android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData)
}
-func (module *DeclarationsModule) BuildActionProviderKeys() []blueprint.AnyProviderKey {
- return []blueprint.AnyProviderKey{android.AconfigDeclarationsProviderKey}
-}
-
-func (module *DeclarationsModule) PackageContextPath() string {
- return pkgPath
-}
-
-func (module *DeclarationsModule) CachedRules() []blueprint.Rule {
- return []blueprint.Rule{aconfigRule, aconfigTextRule}
-}
-
var _ blueprint.Incremental = &DeclarationsModule{}
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index 5483295..e89cd31 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -40,7 +40,7 @@
module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
// Check that the provider has the right contents
- depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
+ depData, _ := android.OtherModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
android.AssertStringEquals(t, "container", depData.Container, "com.android.foo")
android.AssertBoolEquals(t, "exportable", depData.Exportable, true)
@@ -67,7 +67,7 @@
result := runTest(t, android.FixtureExpectsNoErrors, bp)
module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
- depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
+ depData, _ := android.OtherModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
android.AssertBoolEquals(t, "exportable", depData.Exportable, false)
}
@@ -205,7 +205,7 @@
}
result := fixture.RunTestWithBp(t, test.bp)
module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
- depData, _ := android.SingletonModuleProvider(result, module, android.AconfigReleaseDeclarationsProviderKey)
+ depData, _ := android.OtherModuleProvider(result, module, android.AconfigReleaseDeclarationsProviderKey)
expectedKeys := []string{""}
for _, rc := range strings.Split(test.buildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"], " ") {
expectedKeys = append(expectedKeys, rc)
diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go
index 7ba76c0..d72ec48 100644
--- a/aconfig/aconfig_value_set.go
+++ b/aconfig/aconfig_value_set.go
@@ -16,6 +16,9 @@
import (
"android/soong/android"
+ "fmt"
+ "strings"
+
"github.com/google/blueprint"
)
@@ -27,6 +30,9 @@
properties struct {
// aconfig_values modules
Values []string
+
+ // Paths to the Android.bp files where the aconfig_values modules are defined.
+ Srcs []string
}
}
@@ -56,7 +62,35 @@
var valueSetProviderKey = blueprint.NewProvider[valueSetProviderData]()
+func (module *ValueSetModule) FindAconfigValuesFromSrc(ctx android.BottomUpMutatorContext) map[string]android.Path {
+ moduleDir := ctx.ModuleDir()
+ srcs := android.PathsForModuleSrcExcludes(ctx, module.properties.Srcs, []string{ctx.BlueprintsFile()})
+
+ aconfigValuesPrefix := strings.Replace(module.Name(), "aconfig_value_set", "aconfig-values", 1)
+ moduleNamesSrcMap := make(map[string]android.Path)
+ for _, src := range srcs {
+ subDir := strings.TrimPrefix(src.String(), moduleDir+"/")
+ packageName, _, found := strings.Cut(subDir, "/")
+ if found {
+ moduleName := fmt.Sprintf("%s-%s-all", aconfigValuesPrefix, packageName)
+ moduleNamesSrcMap[moduleName] = src
+ }
+ }
+ return moduleNamesSrcMap
+}
+
func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+
+ // TODO: b/366285733 - Replace the file path based solution with more robust solution.
+ aconfigValuesMap := module.FindAconfigValuesFromSrc(ctx)
+ for _, moduleName := range android.SortedKeys(aconfigValuesMap) {
+ if ctx.OtherModuleExists(moduleName) {
+ ctx.AddDependency(ctx.Module(), valueSetTag, moduleName)
+ } else {
+ ctx.ModuleErrorf("module %q not found. Rename the aconfig_values module defined in %q to %q", moduleName, aconfigValuesMap[moduleName], moduleName)
+ }
+ }
+
deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
for _, dep := range deps {
_, ok := dep.(*ValuesModule)
diff --git a/aconfig/aconfig_value_set_test.go b/aconfig/aconfig_value_set_test.go
index 7d18999..3b7281e 100644
--- a/aconfig/aconfig_value_set_test.go
+++ b/aconfig/aconfig_value_set_test.go
@@ -18,6 +18,8 @@
"testing"
"android/soong/android"
+
+ "github.com/google/blueprint"
)
func TestAconfigValueSet(t *testing.T) {
@@ -38,6 +40,115 @@
module := result.ModuleForTests("module_name", "").Module().(*ValueSetModule)
// Check that the provider has the right contents
- depData, _ := android.SingletonModuleProvider(result, module, valueSetProviderKey)
+ depData, _ := android.OtherModuleProvider(result, module, valueSetProviderKey)
android.AssertStringEquals(t, "AvailablePackages", "blah.aconfig_values", depData.AvailablePackages["foo.package"][0].String())
}
+
+func TestAconfigValueSetBpGlob(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ // .../some_release/android.foo/
+ "some_release/android.foo/Android.bp": []byte(`
+ aconfig_values {
+ name: "aconfig-values-platform_build_release-some_release-android.foo-all",
+ package: "android.foo",
+ srcs: [
+ "*.textproto",
+ ],
+ }
+ `),
+ "some_release/android.foo/flag.textproto": nil,
+
+ // .../some_release/android.bar/
+ "some_release/android.bar/Android.bp": []byte(`
+ aconfig_values {
+ name: "aconfig-values-platform_build_release-some_release-android.bar-all",
+ package: "android.bar",
+ srcs: [
+ "*.textproto",
+ ],
+ }
+ `),
+ "some_release/android.bar/flag.textproto": nil,
+
+ // .../some_release/
+ "some_release/Android.bp": []byte(`
+ aconfig_value_set {
+ name: "aconfig_value_set-platform_build_release-some_release",
+ srcs: [
+ "*/Android.bp",
+ ],
+ }
+ `),
+ },
+ ),
+ ).RunTest(t)
+
+ checkModuleHasDependency := func(name, variant, dep string) bool {
+ t.Helper()
+ module := result.ModuleForTests(name, variant).Module()
+ depFound := false
+ result.VisitDirectDeps(module, func(m blueprint.Module) {
+ if m.Name() == dep {
+ depFound = true
+ }
+ })
+ return depFound
+ }
+ android.AssertBoolEquals(t,
+ "aconfig_value_set expected to depend on aconfig_value via srcs",
+ true,
+ checkModuleHasDependency(
+ "aconfig_value_set-platform_build_release-some_release",
+ "",
+ "aconfig-values-platform_build_release-some_release-android.foo-all",
+ ),
+ )
+ android.AssertBoolEquals(t,
+ "aconfig_value_set expected to depend on aconfig_value via srcs",
+ true,
+ checkModuleHasDependency(
+ "aconfig_value_set-platform_build_release-some_release",
+ "",
+ "aconfig-values-platform_build_release-some_release-android.bar-all",
+ ),
+ )
+}
+
+func TestAconfigValueSetBpGlobError(t *testing.T) {
+ android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ // .../some_release/android.bar/
+ "some_release/android.bar/Android.bp": []byte(`
+ aconfig_values {
+ name: "aconfig-values-platform_build_release-some_release-android_bar-all",
+ package: "android.bar",
+ srcs: [
+ "*.textproto",
+ ],
+ }
+ `),
+ "some_release/android.bar/flag.textproto": nil,
+
+ // .../some_release/
+ "some_release/Android.bp": []byte(`
+ aconfig_value_set {
+ name: "aconfig_value_set-platform_build_release-some_release",
+ srcs: [
+ "*/Android.bp",
+ ],
+ }
+ `),
+ },
+ ),
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `module "aconfig_value_set-platform_build_release-some_release": module ` +
+ `"aconfig-values-platform_build_release-some_release-android.bar-all" not found. ` +
+ `Rename the aconfig_values module defined in "some_release/android.bar/Android.bp" ` +
+ `to "aconfig-values-platform_build_release-some_release-android.bar-all"`),
+ ).RunTest(t)
+}
diff --git a/aconfig/aconfig_values_test.go b/aconfig/aconfig_values_test.go
index 526579c..ddbea57 100644
--- a/aconfig/aconfig_values_test.go
+++ b/aconfig/aconfig_values_test.go
@@ -33,7 +33,7 @@
module := result.ModuleForTests("module_name", "").Module().(*ValuesModule)
// Check that the provider has the right contents
- depData, _ := android.SingletonModuleProvider(result, module, valuesProviderKey)
+ depData, _ := android.OtherModuleProvider(result, module, valuesProviderKey)
android.AssertStringEquals(t, "package", "foo.package", depData.Package)
android.AssertPathsEndWith(t, "srcs", []string{"blah.aconfig_values"}, depData.Values)
}
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index 0437c26..6ad54da 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -15,9 +15,10 @@
package aconfig
import (
- "android/soong/android"
"fmt"
"slices"
+
+ "android/soong/android"
)
// A singleton module that collects all of the aconfig flags declared in the
@@ -55,7 +56,7 @@
var packages = make(map[string]int)
var cacheFiles android.Paths
ctx.VisitAllModules(func(module android.Module) {
- decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey)
+ decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey)
if !ok {
return
}
diff --git a/aconfig/build_flags/Android.bp b/aconfig/build_flags/Android.bp
index b3c7339..139aeac 100644
--- a/aconfig/build_flags/Android.bp
+++ b/aconfig/build_flags/Android.bp
@@ -13,10 +13,11 @@
"soong-android",
],
srcs: [
- "all_build_flag_declarations.go",
"build_flags.go",
+ "build_flags_singleton.go",
"declarations.go",
"init.go",
+ "release_configs.go",
],
testSrcs: [
],
diff --git a/aconfig/build_flags/all_build_flag_declarations.go b/aconfig/build_flags/all_build_flag_declarations.go
deleted file mode 100644
index 282c9dc..0000000
--- a/aconfig/build_flags/all_build_flag_declarations.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2023 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package build_flags
-
-import (
- "android/soong/android"
-)
-
-// A singleton module that collects all of the build flags declared in the
-// tree into a single combined file for export to the external flag setting
-// server (inside Google it's Gantry).
-//
-// Note that this is ALL build_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 AllBuildFlagDeclarationsFactory() android.Singleton {
- return &allBuildFlagDeclarationsSingleton{}
-}
-
-type allBuildFlagDeclarationsSingleton struct {
- intermediateBinaryProtoPath android.OutputPath
- intermediateTextProtoPath android.OutputPath
-}
-
-func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- // Find all of the build_flag_declarations modules
- var intermediateFiles android.Paths
- ctx.VisitAllModules(func(module android.Module) {
- decl, ok := android.SingletonModuleProvider(ctx, module, BuildFlagDeclarationsProviderKey)
- if !ok {
- return
- }
- intermediateFiles = append(intermediateFiles, decl.IntermediateCacheOutputPath)
- })
-
- // Generate build action for build_flag (binary proto output)
- this.intermediateBinaryProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.pb")
- ctx.Build(pctx, android.BuildParams{
- Rule: allDeclarationsRule,
- Inputs: intermediateFiles,
- Output: this.intermediateBinaryProtoPath,
- Description: "all_build_flag_declarations",
- Args: map[string]string{
- "intermediates": android.JoinPathsWithPrefix(intermediateFiles, "--intermediate "),
- },
- })
- ctx.Phony("all_build_flag_declarations", this.intermediateBinaryProtoPath)
-
- // Generate build action for build_flag (text proto output)
- this.intermediateTextProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.textproto")
- ctx.Build(pctx, android.BuildParams{
- Rule: allDeclarationsRuleTextProto,
- Input: this.intermediateBinaryProtoPath,
- Output: this.intermediateTextProtoPath,
- Description: "all_build_flag_declarations_textproto",
- })
- ctx.Phony("all_build_flag_declarations_textproto", this.intermediateTextProtoPath)
-}
-
-func (this *allBuildFlagDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
- ctx.DistForGoal("droid", this.intermediateBinaryProtoPath)
- for _, goal := range []string{"docs", "droid", "sdk"} {
- ctx.DistForGoalWithFilename(goal, this.intermediateBinaryProtoPath, "build_flags/all_flags.pb")
- ctx.DistForGoalWithFilename(goal, this.intermediateTextProtoPath, "build_flags/all_flags.textproto")
- }
-}
diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go
new file mode 100644
index 0000000..3b40755
--- /dev/null
+++ b/aconfig/build_flags/build_flags_singleton.go
@@ -0,0 +1,123 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build_flags
+
+import (
+ "android/soong/android"
+)
+
+// A singleton module that collects all of the build flags declared in the
+// tree into a single combined file for export to the external flag setting
+// server (inside Google it's Gantry).
+//
+// Note that this is ALL build_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 AllBuildFlagDeclarationsFactory() android.Singleton {
+ return &allBuildFlagDeclarationsSingleton{}
+}
+
+type allBuildFlagDeclarationsSingleton struct {
+ flagsBinaryProtoPath android.OutputPath
+ flagsTextProtoPath android.OutputPath
+ configsBinaryProtoPath android.OutputPath
+ configsTextProtoPath android.OutputPath
+}
+
+func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // Find all of the build_flag_declarations modules
+ var flagsFiles android.Paths
+ // Find all of the release_config_contribution modules
+ var contributionDirs android.Paths
+ ctx.VisitAllModules(func(module android.Module) {
+ decl, ok := android.OtherModuleProvider(ctx, module, BuildFlagDeclarationsProviderKey)
+ if ok {
+ flagsFiles = append(flagsFiles, decl.IntermediateCacheOutputPath)
+ }
+
+ contrib, ok := android.OtherModuleProvider(ctx, module, ReleaseConfigContributionsProviderKey)
+ if ok {
+ contributionDirs = append(contributionDirs, contrib.ContributionDir)
+ }
+ })
+
+ // Generate build action for build_flag (binary proto output)
+ this.flagsBinaryProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.pb")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allDeclarationsRule,
+ Inputs: flagsFiles,
+ Output: this.flagsBinaryProtoPath,
+ Description: "all_build_flag_declarations",
+ Args: map[string]string{
+ "intermediates": android.JoinPathsWithPrefix(flagsFiles, "--intermediate "),
+ },
+ })
+ ctx.Phony("all_build_flag_declarations", this.flagsBinaryProtoPath)
+
+ // Generate build action for build_flag (text proto output)
+ this.flagsTextProtoPath = android.PathForIntermediates(ctx, "all_build_flag_declarations.textproto")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allDeclarationsRuleTextProto,
+ Input: this.flagsBinaryProtoPath,
+ Output: this.flagsTextProtoPath,
+ Description: "all_build_flag_declarations_textproto",
+ })
+ ctx.Phony("all_build_flag_declarations_textproto", this.flagsTextProtoPath)
+
+ // Generate build action for release_configs (binary proto output)
+ this.configsBinaryProtoPath = android.PathForIntermediates(ctx, "all_release_config_contributions.pb")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allReleaseConfigContributionsRule,
+ Inputs: contributionDirs,
+ Output: this.configsBinaryProtoPath,
+ Description: "all_release_config_contributions",
+ Args: map[string]string{
+ "dirs": android.JoinPathsWithPrefix(contributionDirs, "--dir "),
+ "format": "pb",
+ },
+ })
+ ctx.Phony("all_release_config_contributions", this.configsBinaryProtoPath)
+
+ this.configsTextProtoPath = android.PathForIntermediates(ctx, "all_release_config_contributions.textproto")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: allReleaseConfigContributionsRule,
+ Inputs: contributionDirs,
+ Output: this.configsTextProtoPath,
+ Description: "all_release_config_contributions_textproto",
+ Args: map[string]string{
+ "dirs": android.JoinPathsWithPrefix(contributionDirs, "--dir "),
+ "format": "textproto",
+ },
+ })
+ ctx.Phony("all_release_config_contributions_textproto", this.configsTextProtoPath)
+
+ // Add a simple target for ci/build_metadata to use.
+ ctx.Phony("release_config_metadata",
+ this.flagsBinaryProtoPath,
+ this.flagsTextProtoPath,
+ 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")
+ ctx.DistForGoalWithFilename(goal, this.flagsTextProtoPath, "build_flags/all_flags.textproto")
+ ctx.DistForGoalWithFilename(goal, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb")
+ ctx.DistForGoalWithFilename(goal, this.configsTextProtoPath, "build_flags/all_release_config_contributions.textproto")
+ }
+}
diff --git a/aconfig/build_flags/declarations.go b/aconfig/build_flags/declarations.go
index e927db2..4a54269 100644
--- a/aconfig/build_flags/declarations.go
+++ b/aconfig/build_flags/declarations.go
@@ -35,7 +35,7 @@
// Properties for "aconfig_declarations"
properties struct {
- // aconfig files, relative to this Android.bp file
+ // build flag declaration files, relative to this Android.bp file
Srcs []string `android:"path"`
}
}
diff --git a/aconfig/build_flags/init.go b/aconfig/build_flags/init.go
index dc1369c..a7575e8 100644
--- a/aconfig/build_flags/init.go
+++ b/aconfig/build_flags/init.go
@@ -65,15 +65,32 @@
"${buildFlagDeclarations}",
},
})
+
+ allReleaseConfigContributionsRule = pctx.AndroidStaticRule("all-release-config-contributions-dump",
+ blueprint.RuleParams{
+ Command: `${releaseConfigContributions} ${dirs} --format ${format} --output ${out}`,
+ CommandDeps: []string{
+ "${releaseConfigContributions}",
+ },
+ }, "dirs", "format")
+ allReleaseConfigContributionsRuleText = pctx.AndroidStaticRule("all-release-config-contributions-dumptext",
+ blueprint.RuleParams{
+ Command: `${releaseConfigContributions} ${dirs} --format ${format} --output ${out}`,
+ CommandDeps: []string{
+ "${releaseConfigContributions}",
+ },
+ }, "dirs", "format")
)
func init() {
RegisterBuildComponents(android.InitRegistrationContext)
pctx.Import("android/soong/android")
pctx.HostBinToolVariable("buildFlagDeclarations", "build-flag-declarations")
+ pctx.HostBinToolVariable("releaseConfigContributions", "release-config-contributions")
}
func RegisterBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("build_flag_declarations", DeclarationsFactory)
+ ctx.RegisterModuleType("release_config_contributions", ReleaseConfigContributionsFactory)
ctx.RegisterParallelSingletonType("all_build_flag_declarations", AllBuildFlagDeclarationsFactory)
}
diff --git a/aconfig/build_flags/release_configs.go b/aconfig/build_flags/release_configs.go
new file mode 100644
index 0000000..3fa8a7c
--- /dev/null
+++ b/aconfig/build_flags/release_configs.go
@@ -0,0 +1,78 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package build_flags
+
+import (
+ "path/filepath"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+type ReleaseConfigContributionsProviderData struct {
+ ContributionDir android.SourcePath
+}
+
+var ReleaseConfigContributionsProviderKey = blueprint.NewProvider[ReleaseConfigContributionsProviderData]()
+
+// Soong uses `release_config_contributions` modules to produce the
+// `build_flags/all_release_config_contributions.*` artifacts, listing *all* of
+// the directories in the source tree that contribute to each release config,
+// whether or not they are actually used for the lunch product.
+//
+// This artifact helps flagging automation determine in which directory a flag
+// should be placed by default.
+type ReleaseConfigContributionsModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ // Properties for "release_config_contributions"
+ properties struct {
+ // The `release_configs/*.textproto` files provided by this
+ // directory, relative to this Android.bp file
+ Srcs []string `android:"path"`
+ }
+}
+
+func ReleaseConfigContributionsFactory() android.Module {
+ module := &ReleaseConfigContributionsModule{}
+
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+
+ return module
+}
+
+func (module *ReleaseConfigContributionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ srcs := android.PathsForModuleSrc(ctx, module.properties.Srcs)
+ if len(srcs) == 0 {
+ return
+ }
+ contributionDir := filepath.Dir(filepath.Dir(srcs[0].String()))
+ for _, file := range srcs {
+ if filepath.Dir(filepath.Dir(file.String())) != contributionDir {
+ ctx.ModuleErrorf("Cannot include %s with %s contributions", file, contributionDir)
+ }
+ if filepath.Base(filepath.Dir(file.String())) != "release_configs" || file.Ext() != ".textproto" {
+ ctx.ModuleErrorf("Invalid contribution file %s", file)
+ }
+ }
+ android.SetProvider(ctx, ReleaseConfigContributionsProviderKey, ReleaseConfigContributionsProviderData{
+ ContributionDir: android.PathForSource(ctx, contributionDir),
+ })
+
+}
diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
index ec0a6b6..8c4bfe6 100644
--- a/aconfig/codegen/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -63,7 +63,7 @@
callbacks := &CcAconfigLibraryCallbacks{
properties: &CcAconfigLibraryProperties{},
}
- return cc.GeneratedCcLibraryModuleFactory("cc_aconfig_library", callbacks)
+ return cc.GeneratedCcLibraryModuleFactory(callbacks)
}
func (this *CcAconfigLibraryCallbacks) GeneratorInit(ctx cc.BaseModuleContext) {
@@ -156,7 +156,7 @@
Args: map[string]string{
"gendir": this.generatedDir.String(),
"mode": mode,
- "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorageCc()),
+ "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
},
})
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index 6182e14..ed0b3ed 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -32,6 +32,7 @@
` --mode ${mode}` +
` --cache ${in}` +
` --out ${out}.tmp` +
+ ` --allow-instrumentation ${debug}` +
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
` && rm -rf ${out}.tmp`,
CommandDeps: []string{
@@ -39,7 +40,7 @@
"$soong_zip",
},
Restat: true,
- }, "mode")
+ }, "mode", "debug")
// For cc_aconfig_library: Generate C++ library
cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
@@ -64,11 +65,12 @@
` && ${aconfig} create-rust-lib` +
` --mode ${mode}` +
` --cache ${in}` +
+ ` --allow-instrumentation ${debug}` +
` --out ${gendir}`,
CommandDeps: []string{
"$aconfig",
},
- }, "gendir", "mode")
+ }, "gendir", "mode", "debug")
)
func init() {
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index 673ac2a..ebca413 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -20,6 +20,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "strconv"
)
type declarationsTagType struct {
@@ -71,6 +72,7 @@
module.AddSharedLibrary("aconfig-annotations-lib")
// TODO(b/303773055): Remove the annotation after access issue is resolved.
module.AddSharedLibrary("unsupportedappusage")
+ module.AddSharedLibrary("aconfig_storage_reader_java")
}
}
@@ -102,7 +104,8 @@
Output: srcJarPath,
Description: "aconfig.srcjar",
Args: map[string]string{
- "mode": mode,
+ "mode": mode,
+ "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
},
})
diff --git a/aconfig/codegen/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
index 87b54a4..d8372f3 100644
--- a/aconfig/codegen/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -260,7 +260,7 @@
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package.bar",
- container: "system_ext",
+ container: "vendor",
srcs: ["bar.aconfig"],
}
diff --git a/aconfig/codegen/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
index ad8d632..4b896c3 100644
--- a/aconfig/codegen/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -2,6 +2,7 @@
import (
"fmt"
+ "strconv"
"android/soong/android"
"android/soong/rust"
@@ -82,6 +83,7 @@
Args: map[string]string{
"gendir": generatedDir.String(),
"mode": mode,
+ "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
},
})
a.BaseSourceProvider.OutputFiles = android.Paths{generatedSource}
diff --git a/aconfig/exported_java_aconfig_library.go b/aconfig/exported_java_aconfig_library.go
index 291938f..a64cac8 100644
--- a/aconfig/exported_java_aconfig_library.go
+++ b/aconfig/exported_java_aconfig_library.go
@@ -30,7 +30,7 @@
// Find all of the aconfig_declarations modules
var cacheFiles android.Paths
ctx.VisitAllModules(func(module android.Module) {
- decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
+ decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
if !ok {
return
}
diff --git a/aconfig/init.go b/aconfig/init.go
index de155ab..6f91d8e 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -15,16 +15,13 @@
package aconfig
import (
- "encoding/gob"
-
"android/soong/android"
"github.com/google/blueprint"
)
var (
- pkgPath = "android/soong/aconfig"
- pctx = android.NewPackageContext(pkgPath)
+ pctx = android.NewPackageContext("android/soong/aconfig")
// For aconfig_declarations: Generate cache file
aconfigRule = pctx.AndroidStaticRule("aconfig",
@@ -109,9 +106,6 @@
RegisterBuildComponents(android.InitRegistrationContext)
pctx.HostBinToolVariable("aconfig", "aconfig")
pctx.HostBinToolVariable("soong_zip", "soong_zip")
-
- gob.Register(android.AconfigDeclarationsProviderData{})
- gob.Register(android.ModuleOutPath{})
}
func RegisterBuildComponents(ctx android.RegistrationContext) {
diff --git a/aidl_library/Android.bp b/aidl_library/Android.bp
index ec21504..07472a4 100644
--- a/aidl_library/Android.bp
+++ b/aidl_library/Android.bp
@@ -29,4 +29,5 @@
"aidl_library_test.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/aidl_library/aidl_library_test.go b/aidl_library/aidl_library_test.go
index 01eab0e..1660456 100644
--- a/aidl_library/aidl_library_test.go
+++ b/aidl_library/aidl_library_test.go
@@ -15,8 +15,9 @@
package aidl_library
import (
- "android/soong/android"
"testing"
+
+ "android/soong/android"
)
func TestAidlLibrary(t *testing.T) {
@@ -46,7 +47,7 @@
).RunTest(t).TestContext
foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
- actualInfo, _ := android.SingletonModuleProvider(ctx, foo, AidlLibraryProvider)
+ actualInfo, _ := android.OtherModuleProvider(ctx, foo, AidlLibraryProvider)
android.AssertArrayString(
t,
@@ -95,7 +96,7 @@
).RunTest(t).TestContext
foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
- actualInfo, _ := android.SingletonModuleProvider(ctx, foo, AidlLibraryProvider)
+ actualInfo, _ := android.OtherModuleProvider(ctx, foo, AidlLibraryProvider)
android.AssertArrayString(
t,
diff --git a/android/Android.bp b/android/Android.bp
index ce27241..c2bef0b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -39,9 +39,9 @@
"arch_module_context.go",
"base_module_context.go",
"build_prop.go",
- "buildinfo_prop.go",
"compliance_metadata.go",
"config.go",
+ "container_violations.go",
"container.go",
"test_config.go",
"configurable_properties.go",
@@ -59,6 +59,7 @@
"gen_notice.go",
"hooks.go",
"image.go",
+ "init.go",
"license.go",
"license_kind.go",
"license_metadata.go",
@@ -87,6 +88,7 @@
"prebuilt.go",
"prebuilt_build_tool.go",
"product_config.go",
+ "product_config_to_bp.go",
"proto.go",
"provider.go",
"raw_files.go",
@@ -104,9 +106,9 @@
"test_asserts.go",
"test_suites.go",
"testing.go",
- "updatable_modules.go",
"util.go",
"variable.go",
+ "vintf_fragment.go",
"visibility.go",
],
testSrcs: [
@@ -149,6 +151,9 @@
"test_suites_test.go",
"util_test.go",
"variable_test.go",
+ "vintf_fragment_test.go",
"visibility_test.go",
],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index a47e80f..b902f8b 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -107,7 +107,7 @@
mergedAconfigFiles := make(map[string]Paths)
mergedModeInfos := make(map[string]ModeInfo)
- ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
+ ctx.VisitDirectDeps(func(module Module) {
if aconfig_dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok && len(aconfig_dep.ModeInfos) > 0 {
maps.Copy(mergedModeInfos, aconfig_dep.ModeInfos)
}
@@ -136,12 +136,12 @@
AconfigFiles: mergedAconfigFiles,
ModeInfos: mergedModeInfos,
})
- ctx.Module().base().aconfigFilePaths = getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles)
+ ctx.setAconfigPaths(getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles))
}
}
func aconfigUpdateAndroidMkData(ctx fillInEntriesContext, mod Module, data *AndroidMkData) {
- info, ok := SingletonModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
+ info, ok := OtherModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
// If there is no aconfigPropagatingProvider, or there are no AconfigFiles, then we are done.
if !ok || len(info.AconfigFiles) == 0 {
return
@@ -172,7 +172,7 @@
if len(*entries) == 0 {
return
}
- info, ok := SingletonModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
+ info, ok := OtherModuleProvider(ctx, mod, AconfigPropagatingProviderKey)
if !ok || len(info.AconfigFiles) == 0 {
return
}
@@ -187,6 +187,20 @@
}
}
+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))
+ if len(infos.ExtraInfo) > 0 {
+ for _, ei := range (*infos).ExtraInfo {
+ ei.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles))
+ }
+ }
+}
+
func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, generateRule bool) Paths {
inputs = SortedUniquePaths(inputs)
if len(inputs) == 1 {
@@ -219,7 +233,8 @@
} else if m.ProductSpecific() {
container = "product"
} else if m.SystemExtSpecific() {
- container = "system_ext"
+ // system_ext and system partitions should be treated as one container
+ container = "system"
}
paths = append(paths, aconfigFiles[container]...)
diff --git a/android/all_teams.go b/android/all_teams.go
index d4bf7d0..01be396 100644
--- a/android/all_teams.go
+++ b/android/all_teams.go
@@ -1,9 +1,11 @@
package android
import (
- "android/soong/android/team_proto"
+ "path"
"path/filepath"
+ "android/soong/android/team_proto"
+
"google.golang.org/protobuf/proto"
)
@@ -93,7 +95,7 @@
}
testModInfo := TestModuleInformation{}
- if tmi, ok := SingletonModuleProvider(ctx, module, TestOnlyProviderKey); ok {
+ if tmi, ok := OtherModuleProvider(ctx, module, TestOnlyProviderKey); ok {
testModInfo = tmi
}
@@ -152,6 +154,11 @@
} else {
teamProperties, found = t.lookupDefaultTeam(m.bpFile)
}
+ // Deal with one blueprint file including another by looking up the default
+ // in the main Android.bp rather than one listed with "build = [My.bp]"
+ if !found {
+ teamProperties, found = t.lookupDefaultTeam(path.Join(path.Dir(m.bpFile), "Android.bp"))
+ }
trendy_team_id := ""
if found {
diff --git a/android/all_teams_test.go b/android/all_teams_test.go
index 96ed92f..fa8c048 100644
--- a/android/all_teams_test.go
+++ b/android/all_teams_test.go
@@ -264,6 +264,84 @@
AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
}
+func TestPackageLookupForIncludedBlueprintFiles(t *testing.T) {
+ t.Parallel()
+ rootBp := `
+ package { default_team: "team_top"}
+ team {
+ name: "team_top",
+ trendy_team_id: "trendy://team_top",
+ }
+ build = ["include.bp"]
+ `
+ includeBp := `
+ fake {
+ name: "IncludedModule",
+ } `
+
+ ctx := GroupFixturePreparers(
+ prepareForTestWithTeamAndFakes,
+ PrepareForTestWithPackageModule,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+ }),
+ FixtureAddTextFile("Android.bp", rootBp),
+ FixtureAddTextFile("include.bp", includeBp),
+ ).RunTest(t)
+
+ var teams *team_proto.AllTeams
+ teams = getTeamProtoOutput(t, ctx)
+
+ // map of module name -> trendy team name.
+ actualTeams := make(map[string]*string)
+ for _, teamProto := range teams.Teams {
+ actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+ }
+ expectedTeams := map[string]*string{
+ "IncludedModule": proto.String("trendy://team_top"),
+ }
+ AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
+
+func TestPackageLookupForIncludedBlueprintFilesWithPackageInChildBlueprint(t *testing.T) {
+ t.Parallel()
+ rootBp := `
+ team {
+ name: "team_top",
+ trendy_team_id: "trendy://team_top",
+ }
+ build = ["include.bp"]
+ `
+ includeBp := `
+ package { default_team: "team_top"}
+ fake {
+ name: "IncludedModule",
+ } `
+
+ ctx := GroupFixturePreparers(
+ prepareForTestWithTeamAndFakes,
+ PrepareForTestWithPackageModule,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+ }),
+ FixtureAddTextFile("Android.bp", rootBp),
+ FixtureAddTextFile("include.bp", includeBp),
+ ).RunTest(t)
+
+ var teams *team_proto.AllTeams
+ teams = getTeamProtoOutput(t, ctx)
+
+ // map of module name -> trendy team name.
+ actualTeams := make(map[string]*string)
+ for _, teamProto := range teams.Teams {
+ actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+ }
+ expectedTeams := map[string]*string{
+ "IncludedModule": proto.String("trendy://team_top"),
+ }
+ AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
+
type fakeForTests struct {
ModuleBase
diff --git a/android/androidmk.go b/android/androidmk.go
index 9699ce5..cac2cfe 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -34,7 +34,6 @@
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
@@ -157,6 +156,7 @@
}
type AndroidMkEntriesContext interface {
+ OtherModuleProviderContext
Config() Config
}
@@ -170,7 +170,7 @@
}
func (a *androidMkExtraEntriesContext) Provider(provider blueprint.AnyProviderKey) (any, bool) {
- return a.ctx.moduleProvider(a.mod, provider)
+ return a.ctx.otherModuleProvider(a.mod, provider)
}
type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries)
@@ -354,14 +354,15 @@
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 := amod.distFiles[DefaultDistTag]; ok {
+ if _, ok := info.DistFiles[DefaultDistTag]; ok {
delete(availableTaggedDists, DefaultDistTag)
}
// Finally, merge the distFiles created by GenerateTaggedDistFiles.
- availableTaggedDists = availableTaggedDists.merge(amod.distFiles)
+ availableTaggedDists = availableTaggedDists.merge(info.DistFiles)
if len(availableTaggedDists) == 0 {
// Nothing dist-able for this module.
@@ -372,7 +373,7 @@
distContributions := &distContributions{}
if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
- distContributions.licenseMetadataFile = amod.licenseMetadataFile
+ distContributions.licenseMetadataFile = info.LicenseMetadataFile
}
// Iterate over this module's dist structs, merged from the dist and dists properties.
@@ -497,9 +498,10 @@
ModuleDir(module blueprint.Module) string
ModuleSubDir(module blueprint.Module) string
Config() Config
- moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+ otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
ModuleType(module blueprint.Module) string
OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ HasMutatorFinished(mutatorName string) bool
}
func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
@@ -516,6 +518,7 @@
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()...)
@@ -536,13 +539,14 @@
a.AddStrings("LOCAL_SOONG_MODULE_TYPE", ctx.ModuleType(amod))
// If the install rule was generated by Soong tell Make about it.
- if len(base.katiInstalls) > 0 {
+ info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
+ if len(info.KatiInstalls) > 0 {
// Assume the primary install file is last since it probably needs to depend on any other
// installed files. If that is not the case we can add a method to specify the primary
// installed file.
- a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to)
- a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled())
- a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
+ a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to)
+ a.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled())
+ a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths())
} else {
// 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
@@ -550,8 +554,16 @@
a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install))
}
- if len(base.testData) > 0 {
- a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(base.testData)...)
+ if info.UncheckedModule {
+ a.SetBool("LOCAL_DONT_CHECK_MODULE", true)
+ } else if info.CheckbuildTarget != nil {
+ a.SetPath("LOCAL_CHECKED_MODULE", info.CheckbuildTarget)
+ } else {
+ a.SetOptionalPath("LOCAL_CHECKED_MODULE", a.OutputFile)
+ }
+
+ if len(info.TestData) > 0 {
+ a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
}
if am, ok := mod.(ApexModule); ok {
@@ -588,10 +600,10 @@
}
if !base.InVendorRamdisk() {
- a.AddPaths("LOCAL_FULL_INIT_RC", base.initRcPaths)
+ a.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths)
}
- if len(base.vintfFragmentsPaths) > 0 {
- a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", base.vintfFragmentsPaths)
+ if len(info.VintfFragmentsPaths) > 0 {
+ a.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths)
}
a.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary))
if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) {
@@ -633,11 +645,11 @@
}
}
- if licenseMetadata, ok := SingletonModuleProvider(ctx, mod, LicenseMetadataProvider); ok {
+ if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok {
a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
}
- if _, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
a.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true)
}
@@ -794,15 +806,19 @@
// Additional cases here require review for correct license propagation to make.
var err error
- switch x := mod.(type) {
- case AndroidMkDataProvider:
- err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
- case bootstrap.GoBinaryTool:
- err = translateGoBinaryModule(ctx, w, mod, x)
- case AndroidMkEntriesProvider:
- err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
- default:
- // Not exported to make so no make variables to set.
+
+ if info, ok := ctx.otherModuleProvider(mod, AndroidMkInfoProvider); ok {
+ androidMkEntriesInfos := info.(*AndroidMkProviderInfo)
+ err = translateAndroidMkEntriesInfoModule(ctx, w, moduleInfoJSONs, mod, androidMkEntriesInfos)
+ } else {
+ switch x := mod.(type) {
+ case AndroidMkDataProvider:
+ err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
+ case AndroidMkEntriesProvider:
+ err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
+ default:
+ // Not exported to make so no make variables to set.
+ }
}
if err != nil {
@@ -812,23 +828,6 @@
return err
}
-// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
-// m by making them phony targets.
-func translateGoBinaryModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
- goBinary bootstrap.GoBinaryTool) error {
-
- name := ctx.ModuleName(mod)
- fmt.Fprintln(w, ".PHONY:", name)
- fmt.Fprintln(w, name+":", goBinary.InstallPath())
- fmt.Fprintln(w, "")
- // Assuming no rules in make include go binaries in distributables.
- // If the assumption is wrong, make will fail to build without the necessary .meta_lic and .meta_module files.
- // In that case, add the targets and rules here to build a .meta_lic file for `name` and a .meta_module for
- // `goBinary.InstallPath()` pointing to the `name`.meta_lic file.
-
- return nil
-}
-
func (data *AndroidMkData) fillInData(ctx fillInEntriesContext, mod blueprint.Module) {
// Get the preamble content through AndroidMkEntries logic.
data.Entries = AndroidMkEntries{
@@ -861,6 +860,7 @@
}
data := provider.AndroidMk()
+
if data.Include == "" {
data.Include = "$(BUILD_PREBUILT)"
}
@@ -900,6 +900,7 @@
case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
case "*apex.apexBundle": // license properties written
case "*bpf.bpf": // license properties written (both for module and objs)
+ case "*libbpf_prog.libbpfProg": // license properties written (both for module and objs)
case "*genrule.Module": // writes non-custom before adding .phony
case "*java.SystemModules": // doesn't go through base_rules
case "*java.systemModulesImport": // doesn't go through base_rules
@@ -907,6 +908,7 @@
case "*phony.PhonyRule": // writes phony deps and acts like `.PHONY`
case "*selinux.selinuxContextsModule": // license properties written
case "*sysprop.syspropLibrary": // license properties written
+ case "*vintf.vintfCompatibilityMatrixRule": // use case like phony
default:
if !ctx.Config().IsEnvFalse("ANDROID_REQUIRE_LICENSES") {
return fmt.Errorf("custom make rules not allowed for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), ctx.ModuleName(mod))
@@ -918,7 +920,7 @@
}
if !data.Entries.disabled() {
- if moduleInfoJSON, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
*moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
}
}
@@ -960,7 +962,7 @@
}
if len(entriesList) > 0 && !entriesList[0].disabled() {
- if moduleInfoJSON, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
*moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
}
}
@@ -968,11 +970,11 @@
return nil
}
-func ShouldSkipAndroidMkProcessing(ctx ConfigAndErrorContext, module Module) bool {
+func ShouldSkipAndroidMkProcessing(ctx ConfigurableEvaluatorContext, module Module) bool {
return shouldSkipAndroidMkProcessing(ctx, module.base())
}
-func shouldSkipAndroidMkProcessing(ctx ConfigAndErrorContext, module *ModuleBase) bool {
+func shouldSkipAndroidMkProcessing(ctx ConfigurableEvaluatorContext, module *ModuleBase) bool {
if !module.commonProperties.NamespaceExportedToMake {
// TODO(jeffrygaston) do we want to validate that there are no modules being
// exported to Kati that depend on this module?
@@ -1048,3 +1050,564 @@
}
fmt.Fprintln(w)
}
+
+type AndroidMkProviderInfo struct {
+ PrimaryInfo AndroidMkInfo
+ ExtraInfo []AndroidMkInfo
+}
+
+type AndroidMkInfo struct {
+ // Android.mk class string, e.g. EXECUTABLES, JAVA_LIBRARIES, ETC
+ Class string
+ // Optional suffix to append to the module name. Useful when a module wants to return multiple
+ // AndroidMkEntries objects. For example, when a java_library returns an additional entry for
+ // its hostdex sub-module, this SubName field is set to "-hostdex" so that it can have a
+ // different name than the parent's.
+ 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
+ // file. Useful when a module needs to be skipped conditionally.
+ Disabled bool
+ // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk
+ // If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
+ Include string
+ // Required modules that need to be built and included in the final build output when building
+ // this module.
+ Required []string
+ // Required host modules that need to be built and included in the final build output when
+ // building this module.
+ Host_required []string
+ // Required device modules that need to be built and included in the final build output when
+ // building this module.
+ Target_required []string
+
+ HeaderStrings []string
+ FooterStrings []string
+
+ // A map that holds the up-to-date Make variable values. Can be accessed from tests.
+ EntryMap map[string][]string
+ // A list of EntryMap keys in insertion order. This serves a few purposes:
+ // 1. Prevents churns. Golang map doesn't provide consistent iteration order, so without this,
+ // the outputted Android-*.mk file may change even though there have been no content changes.
+ // 2. Allows modules to refer to other variables, like LOCAL_BAR_VAR := $(LOCAL_FOO_VAR),
+ // without worrying about the variables being mixed up in the actual mk file.
+ // 3. Makes troubleshooting and spotting errors easier.
+ EntryOrder []string
+}
+
+// TODO: rename it to AndroidMkEntriesProvider after AndroidMkEntriesProvider interface is gone.
+var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]()
+
+func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
+ mod blueprint.Module, providerInfo *AndroidMkProviderInfo) error {
+ if shouldSkipAndroidMkProcessing(ctx, mod.(Module).base()) {
+ return nil
+ }
+
+ // Deep copy the provider info since we need to modify the info later
+ info := deepCopyAndroidMkProviderInfo(providerInfo)
+
+ aconfigUpdateAndroidMkInfos(ctx, mod.(Module), &info)
+
+ // Any new or special cases here need review to verify correct propagation of license information.
+ info.PrimaryInfo.fillInEntries(ctx, mod)
+ info.PrimaryInfo.write(w)
+ if len(info.ExtraInfo) > 0 {
+ for _, ei := range info.ExtraInfo {
+ ei.fillInEntries(ctx, mod)
+ ei.write(w)
+ }
+ }
+
+ if !info.PrimaryInfo.disabled() {
+ if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ }
+ }
+
+ return nil
+}
+
+// Utility funcs to manipulate Android.mk variable entries.
+
+// SetString sets a Make variable with the given name to the given value.
+func (a *AndroidMkInfo) SetString(name, value string) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = []string{value}
+}
+
+// SetPath sets a Make variable with the given name to the given path string.
+func (a *AndroidMkInfo) SetPath(name string, path Path) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = []string{path.String()}
+}
+
+// SetOptionalPath sets a Make variable with the given name to the given path string if it is valid.
+// It is a no-op if the given path is invalid.
+func (a *AndroidMkInfo) SetOptionalPath(name string, path OptionalPath) {
+ if path.Valid() {
+ a.SetPath(name, path.Path())
+ }
+}
+
+// AddPath appends the given path string to a Make variable with the given name.
+func (a *AndroidMkInfo) AddPath(name string, path Path) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = append(a.EntryMap[name], path.String())
+}
+
+// AddOptionalPath appends the given path string to a Make variable with the given name if it is
+// valid. It is a no-op if the given path is invalid.
+func (a *AndroidMkInfo) AddOptionalPath(name string, path OptionalPath) {
+ if path.Valid() {
+ a.AddPath(name, path.Path())
+ }
+}
+
+// SetPaths sets a Make variable with the given name to a slice of the given path strings.
+func (a *AndroidMkInfo) SetPaths(name string, paths Paths) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = paths.Strings()
+}
+
+// SetOptionalPaths sets a Make variable with the given name to a slice of the given path strings
+// only if there are a non-zero amount of paths.
+func (a *AndroidMkInfo) SetOptionalPaths(name string, paths Paths) {
+ if len(paths) > 0 {
+ a.SetPaths(name, paths)
+ }
+}
+
+// AddPaths appends the given path strings to a Make variable with the given name.
+func (a *AndroidMkInfo) AddPaths(name string, paths Paths) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = append(a.EntryMap[name], paths.Strings()...)
+}
+
+// SetBoolIfTrue sets a Make variable with the given name to true if the given flag is true.
+// It is a no-op if the given flag is false.
+func (a *AndroidMkInfo) SetBoolIfTrue(name string, flag bool) {
+ if flag {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = []string{"true"}
+ }
+}
+
+// SetBool sets a Make variable with the given name to if the given bool flag value.
+func (a *AndroidMkInfo) SetBool(name string, flag bool) {
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ if flag {
+ a.EntryMap[name] = []string{"true"}
+ } else {
+ a.EntryMap[name] = []string{"false"}
+ }
+}
+
+// AddStrings appends the given strings to a Make variable with the given name.
+func (a *AndroidMkInfo) AddStrings(name string, value ...string) {
+ if len(value) == 0 {
+ return
+ }
+ if _, ok := a.EntryMap[name]; !ok {
+ a.EntryOrder = append(a.EntryOrder, name)
+ }
+ a.EntryMap[name] = append(a.EntryMap[name], value...)
+}
+
+// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling
+// for partial MTS and MCTS test suites.
+func (a *AndroidMkInfo) AddCompatibilityTestSuites(suites ...string) {
+ // 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.
+ if PrefixInList(suites, "mts-") && !InList("mts", suites) {
+ suites = append(suites, "mts")
+ }
+ if PrefixInList(suites, "mcts-") && !InList("mcts", suites) {
+ suites = append(suites, "mcts")
+ }
+ a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...)
+}
+
+func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
+ helperInfo := AndroidMkInfo{
+ EntryMap: make(map[string][]string),
+ }
+
+ amod := mod.(Module)
+ base := amod.base()
+ name := base.BaseModuleName()
+ if a.OverrideName != "" {
+ name = a.OverrideName
+ }
+
+ 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()...)
+
+ for _, distString := range a.GetDistForGoals(ctx, mod) {
+ a.HeaderStrings = append(a.HeaderStrings, distString)
+ }
+
+ a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s\n", 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)
+ helperInfo.SetString("LOCAL_MODULE_CLASS", a.Class)
+ helperInfo.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
+ 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))
+
+ // If the install rule was generated by Soong tell Make about it.
+ info := OtherModuleProviderOrDefault(ctx, mod, InstallFilesProvider)
+ if len(info.KatiInstalls) > 0 {
+ // Assume the primary install file is last since it probably needs to depend on any other
+ // installed files. If that is not the case we can add a method to specify the primary
+ // installed file.
+ helperInfo.SetPath("LOCAL_SOONG_INSTALLED_MODULE", info.KatiInstalls[len(info.KatiInstalls)-1].to)
+ helperInfo.SetString("LOCAL_SOONG_INSTALL_PAIRS", info.KatiInstalls.BuiltInstalled())
+ helperInfo.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", info.KatiSymlinks.InstallPaths().Paths())
+ } else {
+ // 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))
+ }
+
+ if len(info.TestData) > 0 {
+ helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...)
+ }
+
+ if am, ok := mod.(ApexModule); ok {
+ helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
+ }
+
+ archStr := base.Arch().ArchType.String()
+ host := false
+ switch base.Os().Class {
+ case Host:
+ if base.Target().HostCross {
+ // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common.
+ if base.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 {
+ 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 hostArchStr != "" {
+ helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr)
+ }
+ } else {
+ helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", archStr)
+ }
+ }
+
+ if !base.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.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)
+ }
+ }
+
+ if host {
+ makeOs := base.Os().String()
+ if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl {
+ makeOs = "linux"
+ }
+ helperInfo.SetString("LOCAL_MODULE_HOST_OS", makeOs)
+ helperInfo.SetString("LOCAL_IS_HOST_MODULE", "true")
+ }
+
+ prefix := ""
+ if base.ArchSpecific() {
+ switch base.Os().Class {
+ case Host:
+ if base.Target().HostCross {
+ prefix = "HOST_CROSS_"
+ } else {
+ prefix = "HOST_"
+ }
+ case Device:
+ prefix = "TARGET_"
+
+ }
+
+ if base.Arch().ArchType != ctx.Config().Targets[base.Os()][0].Arch.ArchType {
+ prefix = "2ND_" + prefix
+ }
+ }
+
+ if licenseMetadata, ok := OtherModuleProvider(ctx, mod, LicenseMetadataProvider); ok {
+ helperInfo.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
+ }
+
+ if _, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ helperInfo.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true)
+ }
+
+ a.mergeEntries(&helperInfo)
+
+ // Write to footer.
+ a.FooterStrings = append([]string{"include " + a.Include}, a.FooterStrings...)
+}
+
+// This method merges the entries to helperInfo, then replaces a's EntryMap and
+// EntryOrder with helperInfo's
+func (a *AndroidMkInfo) mergeEntries(helperInfo *AndroidMkInfo) {
+ for _, extraEntry := range a.EntryOrder {
+ if v, ok := helperInfo.EntryMap[extraEntry]; ok {
+ v = append(v, a.EntryMap[extraEntry]...)
+ } else {
+ helperInfo.EntryMap[extraEntry] = a.EntryMap[extraEntry]
+ helperInfo.EntryOrder = append(helperInfo.EntryOrder, extraEntry)
+ }
+ }
+ a.EntryOrder = helperInfo.EntryOrder
+ a.EntryMap = helperInfo.EntryMap
+}
+
+func (a *AndroidMkInfo) disabled() bool {
+ return a.Disabled || !a.OutputFile.Valid()
+}
+
+// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
+// given Writer object.
+func (a *AndroidMkInfo) write(w io.Writer) {
+ if a.disabled() {
+ return
+ }
+
+ combinedHeaderString := strings.Join(a.HeaderStrings, "\n")
+ combinedFooterString := strings.Join(a.FooterStrings, "\n")
+ w.Write([]byte(combinedHeaderString))
+ for _, name := range a.EntryOrder {
+ AndroidMkEmitAssignList(w, name, a.EntryMap[name])
+ }
+ w.Write([]byte(combinedFooterString))
+}
+
+// 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)
+ if distContributions == nil {
+ return nil
+ }
+
+ 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),
+ }
+ if len(providerInfo.ExtraInfo) > 0 {
+ for _, i := range providerInfo.ExtraInfo {
+ info.ExtraInfo = append(info.ExtraInfo, deepCopyAndroidMkInfo(&i))
+ }
+ }
+ return info
+}
+
+func deepCopyAndroidMkInfo(mkinfo *AndroidMkInfo) AndroidMkInfo {
+ info := AndroidMkInfo{
+ Class: mkinfo.Class,
+ SubName: mkinfo.SubName,
+ OverrideName: mkinfo.OverrideName,
+ // There is no modification on DistFiles or OutputFile, so no need to
+ // make their deep copy.
+ DistFiles: mkinfo.DistFiles,
+ OutputFile: mkinfo.OutputFile,
+ Disabled: mkinfo.Disabled,
+ Include: mkinfo.Include,
+ Required: deepCopyStringSlice(mkinfo.Required),
+ Host_required: deepCopyStringSlice(mkinfo.Host_required),
+ Target_required: deepCopyStringSlice(mkinfo.Target_required),
+ HeaderStrings: deepCopyStringSlice(mkinfo.HeaderStrings),
+ FooterStrings: deepCopyStringSlice(mkinfo.FooterStrings),
+ EntryOrder: deepCopyStringSlice(mkinfo.EntryOrder),
+ }
+ info.EntryMap = make(map[string][]string)
+ for k, v := range mkinfo.EntryMap {
+ info.EntryMap[k] = deepCopyStringSlice(v)
+ }
+
+ return info
+}
+
+func deepCopyStringSlice(original []string) []string {
+ result := make([]string, len(original))
+ copy(result, original)
+ return result
+}
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 72b8654..c37eeab 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -46,7 +46,6 @@
func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- m.base().licenseMetadataFile = PathForOutput(ctx, "meta_lic")
var defaultDistPaths Paths
// If the dist_output_file: true then create an output file that is stored in
@@ -276,7 +275,8 @@
)
}
for idx, line := range androidMkLines {
- expectedLine := strings.ReplaceAll(expectedAndroidMkLines[idx], "meta_lic", module.base().licenseMetadataFile.String())
+ expectedLine := strings.ReplaceAll(expectedAndroidMkLines[idx], "meta_lic",
+ OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).LicenseMetadataFile.String())
if line != expectedLine {
t.Errorf(
"Expected AndroidMk line to be '%s', got '%s'",
diff --git a/android/apex.go b/android/apex.go
index ecab8e3..79ab13c 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "reflect"
"slices"
"sort"
"strconv"
@@ -87,6 +88,9 @@
// Returns the name of the overridden apex (com.android.foo)
BaseApexName string
+
+ // Returns the value of `apex_available_name`
+ ApexAvailableName string
}
// AllApexInfo holds the ApexInfo of all apexes that include this module.
@@ -145,6 +149,17 @@
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 &&
+ reflect.DeepEqual(i.InApexVariants, otherApexInfo.InApexVariants) &&
+ reflect.DeepEqual(i.InApexModules, otherApexInfo.InApexModules)
+}
+
// ApexTestForInfo stores the contents of APEXes for which this module is a test - although this
// module is not part of the APEX - and thus has access to APEX internals.
type ApexTestForInfo struct {
@@ -280,7 +295,7 @@
//
// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
// "//apex_available:platform" refers to non-APEX partitions like "system.img".
- // "com.android.gki.*" matches any APEX module name with the prefix "com.android.gki.".
+ // Prefix pattern (com.foo.*) can be used to match with any APEX name with the prefix(com.foo.).
// Default is ["//apex_available:platform"].
Apex_available []string
@@ -473,15 +488,6 @@
const (
AvailableToPlatform = "//apex_available:platform"
AvailableToAnyApex = "//apex_available:anyapex"
- AvailableToGkiApex = "com.android.gki.*"
-)
-
-var (
- AvailableToRecognziedWildcards = []string{
- AvailableToPlatform,
- AvailableToAnyApex,
- AvailableToGkiApex,
- }
)
// CheckAvailableForApex provides the default algorithm for checking the apex availability. When the
@@ -494,11 +500,27 @@
if len(apex_available) == 0 {
return what == AvailableToPlatform
}
- return InList(what, apex_available) ||
- (what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
- (strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available)) ||
- (what == "com.google.mainline.primary.libs") || // TODO b/248601389
- (what == "com.google.mainline.go.primary.libs") // TODO b/248601389
+
+ // TODO b/248601389
+ if what == "com.google.mainline.primary.libs" || what == "com.google.mainline.go.primary.libs" {
+ return true
+ }
+
+ for _, apex_name := range apex_available {
+ // exact match.
+ if apex_name == what {
+ return true
+ }
+ // //apex_available:anyapex matches with any apex name, but not //apex_available:platform
+ if apex_name == AvailableToAnyApex && what != AvailableToPlatform {
+ return true
+ }
+ // prefix match.
+ if strings.HasSuffix(apex_name, ".*") && strings.HasPrefix(what, strings.TrimSuffix(apex_name, "*")) {
+ return true
+ }
+ }
+ return false
}
// Implements ApexModule
@@ -524,7 +546,20 @@
// This function makes sure that the apex_available property is valid
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
for _, n := range m.ApexProperties.Apex_available {
- if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
+ if n == AvailableToPlatform || n == AvailableToAnyApex {
+ continue
+ }
+ // Prefix pattern should end with .* and has at least two components.
+ if strings.Contains(n, "*") {
+ if !strings.HasSuffix(n, ".*") {
+ mctx.PropertyErrorf("apex_available", "Wildcard should end with .* like com.foo.*")
+ }
+ if strings.Count(n, ".") < 2 {
+ mctx.PropertyErrorf("apex_available", "Wildcard requires two or more components like com.foo.*")
+ }
+ if strings.Count(n, "*") != 1 {
+ mctx.PropertyErrorf("apex_available", "Wildcard is not allowed in the middle.")
+ }
continue
}
if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
@@ -680,7 +715,7 @@
base.ApexProperties.InAnyApex = true
base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex
- if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) {
+ 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
@@ -954,8 +989,8 @@
// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
-type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
-type WalkPayloadDepsFunc func(ctx ModuleContext, do PayloadDepsCallback)
+type PayloadDepsCallback func(ctx BaseModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
+type WalkPayloadDepsFunc func(ctx BaseModuleContext, do PayloadDepsCallback)
// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
type ModuleWithMinSdkVersionCheck interface {
@@ -982,7 +1017,7 @@
return
}
- walk(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
+ walk(ctx, func(ctx BaseModuleContext, from blueprint.Module, to ApexModule, 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
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index 8b72f8e..4cd8dda 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -119,7 +119,10 @@
func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
for _, content := range m.Contents() {
- if !ctx.OtherModuleExists(content) && !ctx.Config().AllowMissingDependencies() {
+ // Verify that the module listed in contents exists in the tree
+ // Remove the prebuilt_ prefix to account for partner worksapces where the source module does not
+ // exist, and PrebuiltRenameMutator renames `prebuilt_foo` to `foo`
+ if !ctx.OtherModuleExists(content) && !ctx.OtherModuleExists(RemoveOptionalPrebuiltPrefix(content)) && !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
}
pi := &PrebuiltSelectionInfo{
diff --git a/android/api_levels.go b/android/api_levels.go
index dc17238..2b1d01d 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -444,26 +444,27 @@
func getApiLevelsMapReleasedVersions() (map[string]int, error) {
return map[string]int{
- "G": 9,
- "I": 14,
- "J": 16,
- "J-MR1": 17,
- "J-MR2": 18,
- "K": 19,
- "L": 21,
- "L-MR1": 22,
- "M": 23,
- "N": 24,
- "N-MR1": 25,
- "O": 26,
- "O-MR1": 27,
- "P": 28,
- "Q": 29,
- "R": 30,
- "S": 31,
- "S-V2": 32,
- "Tiramisu": 33,
- "UpsideDownCake": 34,
+ "G": 9,
+ "I": 14,
+ "J": 16,
+ "J-MR1": 17,
+ "J-MR2": 18,
+ "K": 19,
+ "L": 21,
+ "L-MR1": 22,
+ "M": 23,
+ "N": 24,
+ "N-MR1": 25,
+ "O": 26,
+ "O-MR1": 27,
+ "P": 28,
+ "Q": 29,
+ "R": 30,
+ "S": 31,
+ "S-V2": 32,
+ "Tiramisu": 33,
+ "UpsideDownCake": 34,
+ "VanillaIceCream": 35,
}, nil
}
diff --git a/android/arch.go b/android/arch.go
index 6d896e5..1ec971d 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -23,7 +23,6 @@
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
)
@@ -139,6 +138,16 @@
return a.Name
}
+func (a ArchType) Bitness() string {
+ if a.Multilib == "lib32" {
+ return "32"
+ }
+ if a.Multilib == "lib64" {
+ return "64"
+ }
+ panic("Bitness is not defined for the common variant")
+}
+
const COMMON_VARIANT = "common"
var (
@@ -397,45 +406,21 @@
// device_supported and host_supported properties to determine which OsTypes are enabled for this
// module, then searches through the Targets to determine which have enabled Targets for this
// module.
-func osMutator(bpctx blueprint.BottomUpMutatorContext) {
- var module Module
- var ok bool
- if module, ok = bpctx.Module().(Module); !ok {
- // The module is not a Soong module, it is a Blueprint module.
- if bootstrap.IsBootstrapModule(bpctx.Module()) {
- // Bootstrap Go modules are always the build OS or linux bionic.
- config := bpctx.Config().(Config)
- osNames := []string{config.BuildOSTarget.OsVariation()}
- for _, hostCrossTarget := range config.Targets[LinuxBionic] {
- if hostCrossTarget.Arch.ArchType == config.BuildOSTarget.Arch.ArchType {
- osNames = append(osNames, hostCrossTarget.OsVariation())
- }
- }
- osNames = FirstUniqueStrings(osNames)
- bpctx.CreateVariations(osNames...)
- }
- return
- }
+type osTransitionMutator struct{}
- // Bootstrap Go module support above requires this mutator to be a
- // blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
- // filters out non-Soong modules. Now that we've handled them, create a
- // normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false)
- defer bottomUpMutatorContextPool.Put(mctx)
+type allOsInfo struct {
+ Os map[string]OsType
+ Variations []string
+}
- base := module.base()
+var allOsProvider = blueprint.NewMutatorProvider[*allOsInfo]("os_propagate")
- // Nothing to do for modules that are not architecture specific (e.g. a genrule).
- if !base.ArchSpecific() {
- return
- }
-
- // Collect a list of OSTypes supported by this module based on the HostOrDevice value
- // passed to InitAndroidArchModule and the device_supported and host_supported properties.
+// moduleOSList collects a list of OSTypes supported by this module based on the HostOrDevice
+// value passed to InitAndroidArchModule and the device_supported and host_supported properties.
+func moduleOSList(ctx ConfigContext, base *ModuleBase) []OsType {
var moduleOSList []OsType
for _, os := range osTypeList {
- for _, t := range mctx.Config().Targets[os] {
+ for _, t := range ctx.Config().Targets[os] {
if base.supportsTarget(t) {
moduleOSList = append(moduleOSList, os)
break
@@ -443,53 +428,91 @@
}
}
- createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
+ if base.commonProperties.CreateCommonOSVariant {
+ // A CommonOS variant was requested so add it to the list of OS variants to
+ // create. It needs to be added to the end because it needs to depend on the
+ // the other variants and inter variant dependencies can only be created from a
+ // later variant in that list to an earlier one. That is because variants are
+ // always processed in the order in which they are created.
+ moduleOSList = append(moduleOSList, CommonOS)
+ }
+
+ return moduleOSList
+}
+
+func (o *osTransitionMutator) Split(ctx BaseModuleContext) []string {
+ module := ctx.Module()
+ base := module.base()
+
+ // Nothing to do for modules that are not architecture specific (e.g. a genrule).
+ if !base.ArchSpecific() {
+ return []string{""}
+ }
+
+ moduleOSList := moduleOSList(ctx, base)
// If there are no supported OSes then disable the module.
- if len(moduleOSList) == 0 && !createCommonOSVariant {
+ if len(moduleOSList) == 0 {
base.Disable()
- return
+ return []string{""}
}
// Convert the list of supported OsTypes to the variation names.
osNames := make([]string, len(moduleOSList))
+ osMapping := make(map[string]OsType, len(moduleOSList))
for i, os := range moduleOSList {
osNames[i] = os.String()
+ osMapping[osNames[i]] = os
}
- if createCommonOSVariant {
- // A CommonOS variant was requested so add it to the list of OS variants to
- // create. It needs to be added to the end because it needs to depend on the
- // the other variants in the list returned by CreateVariations(...) and inter
- // variant dependencies can only be created from a later variant in that list to
- // an earlier one. That is because variants are always processed in the order in
- // which they are returned from CreateVariations(...).
- osNames = append(osNames, CommonOS.Name)
- moduleOSList = append(moduleOSList, CommonOS)
+ SetProvider(ctx, allOsProvider, &allOsInfo{
+ Os: osMapping,
+ Variations: osNames,
+ })
+
+ return osNames
+}
+
+func (o *osTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (o *osTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ module := ctx.Module()
+ base := module.base()
+
+ if !base.ArchSpecific() {
+ return ""
}
- // Create the variations, annotate each one with which OS it was created for, and
+ return incomingVariation
+}
+
+func (o *osTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ module := ctx.Module()
+ base := module.base()
+
+ if variation == "" {
+ return
+ }
+
+ allOsInfo, ok := ModuleProvider(ctx, allOsProvider)
+ if !ok {
+ panic(fmt.Errorf("missing allOsProvider"))
+ }
+
+ // Annotate this variant with which OS it was created for, and
// squash the appropriate OS-specific properties into the top level properties.
- modules := mctx.CreateVariations(osNames...)
- for i, m := range modules {
- m.base().commonProperties.CompileOS = moduleOSList[i]
- m.base().setOSProperties(mctx)
- }
+ base.commonProperties.CompileOS = allOsInfo.Os[variation]
+ base.setOSProperties(ctx)
- if createCommonOSVariant {
+ if variation == CommonOS.String() {
// A CommonOS variant was requested so add dependencies from it (the last one in
// the list) to the OS type specific variants.
- last := len(modules) - 1
- commonOSVariant := modules[last]
- commonOSVariant.base().commonProperties.CommonOSVariant = true
- for _, module := range modules[0:last] {
- // Ignore modules that are enabled. Note, this will only avoid adding
- // dependencies on OsType variants that are explicitly disabled in their
- // properties. The CommonOS variant will still depend on disabled variants
- // if they are disabled afterwards, e.g. in archMutator if
- if module.Enabled(mctx) {
- mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
- }
+ osList := allOsInfo.Variations[:len(allOsInfo.Variations)-1]
+ for _, os := range osList {
+ variation := []blueprint.Variation{{"os", os}}
+ ctx.AddVariationDependencies(variation, commonOsToOsSpecificVariantTag, ctx.ModuleName())
}
}
}
@@ -522,7 +545,7 @@
var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"}
-// archMutator splits a module into a variant for each Target requested by the module. Target selection
+// archTransitionMutator splits a module into a variant for each Target requested by the module. Target selection
// for a module is in three levels, OsClass, multilib, and then Target.
// OsClass selection is determined by:
// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
@@ -553,41 +576,32 @@
//
// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
-func archMutator(bpctx blueprint.BottomUpMutatorContext) {
- var module Module
- var ok bool
- if module, ok = bpctx.Module().(Module); !ok {
- if bootstrap.IsBootstrapModule(bpctx.Module()) {
- // Bootstrap Go modules are always the build architecture.
- bpctx.CreateVariations(bpctx.Config().(Config).BuildOSTarget.ArchVariation())
- }
- return
- }
+type archTransitionMutator struct{}
- // Bootstrap Go module support above requires this mutator to be a
- // blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
- // filters out non-Soong modules. Now that we've handled them, create a
- // normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false)
- defer bottomUpMutatorContextPool.Put(mctx)
+type allArchInfo struct {
+ Targets map[string]Target
+ MultiTargets []Target
+ Primary string
+ Multilib string
+}
+var allArchProvider = blueprint.NewMutatorProvider[*allArchInfo]("arch_propagate")
+
+func (a *archTransitionMutator) Split(ctx BaseModuleContext) []string {
+ module := ctx.Module()
base := module.base()
if !base.ArchSpecific() {
- return
+ return []string{""}
}
os := base.commonProperties.CompileOS
if os == CommonOS {
- // Make sure that the target related properties are initialized for the
- // CommonOS variant.
- addTargetProperties(module, commonTargetMap[os.Name], nil, true)
-
// Do not create arch specific variants for the CommonOS variant.
- return
+ return []string{""}
}
- osTargets := mctx.Config().Targets[os]
+ osTargets := ctx.Config().Targets[os]
image := base.commonProperties.ImageVariation
// Filter NativeBridge targets unless they are explicitly supported.
@@ -614,19 +628,18 @@
prefer32 := os == Windows
// Determine the multilib selection for this module.
- ignorePrefer32OnDevice := mctx.Config().IgnorePrefer32OnDevice()
- multilib, extraMultilib := decodeMultilib(base, os, ignorePrefer32OnDevice)
+ multilib, extraMultilib := decodeMultilib(ctx, base)
// Convert the multilib selection into a list of Targets.
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
if err != nil {
- mctx.ModuleErrorf("%s", err.Error())
+ ctx.ModuleErrorf("%s", err.Error())
}
// If there are no supported targets disable the module.
if len(targets) == 0 {
base.Disable()
- return
+ return []string{""}
}
// If the module is using extraMultilib, decode the extraMultilib selection into
@@ -635,7 +648,7 @@
if extraMultilib != "" {
multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
if err != nil {
- mctx.ModuleErrorf("%s", err.Error())
+ ctx.ModuleErrorf("%s", err.Error())
}
multiTargets = filterHostCross(multiTargets, targets[0].HostCross)
}
@@ -643,7 +656,7 @@
// Recovery is always the primary architecture, filter out any other architectures.
// Common arch is also allowed
if image == RecoveryVariation {
- primaryArch := mctx.Config().DevicePrimaryArchType()
+ primaryArch := ctx.Config().DevicePrimaryArchType()
targets = filterToArch(targets, primaryArch, Common)
multiTargets = filterToArch(multiTargets, primaryArch, Common)
}
@@ -651,37 +664,109 @@
// If there are no supported targets disable the module.
if len(targets) == 0 {
base.Disable()
- return
+ return []string{""}
}
// Convert the targets into a list of arch variation names.
targetNames := make([]string, len(targets))
+ targetMapping := make(map[string]Target, len(targets))
for i, target := range targets {
targetNames[i] = target.ArchVariation()
+ targetMapping[targetNames[i]] = targets[i]
}
- // Create the variations, annotate each one with which Target it was created for, and
- // squash the appropriate arch-specific properties into the top level properties.
- modules := mctx.CreateVariations(targetNames...)
- for i, m := range modules {
- addTargetProperties(m, targets[i], multiTargets, i == 0)
- m.base().setArchProperties(mctx)
+ SetProvider(ctx, allArchProvider, &allArchInfo{
+ Targets: targetMapping,
+ MultiTargets: multiTargets,
+ Primary: targetNames[0],
+ Multilib: multilib,
+ })
+ return targetNames
+}
- // Install support doesn't understand Darwin+Arm64
- if os == Darwin && targets[i].HostCross {
- m.base().commonProperties.SkipInstall = true
+func (a *archTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (a *archTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ module := ctx.Module()
+ base := module.base()
+
+ if !base.ArchSpecific() {
+ return ""
+ }
+
+ os := base.commonProperties.CompileOS
+ if os == CommonOS {
+ // Do not create arch specific variants for the CommonOS variant.
+ return ""
+ }
+
+ if incomingVariation == "" {
+ multilib, _ := decodeMultilib(ctx, base)
+ if multilib == "common" {
+ return "common"
}
}
+ return incomingVariation
+}
+
+func (a *archTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ module := ctx.Module()
+ base := module.base()
+ os := base.commonProperties.CompileOS
+
+ if os == CommonOS {
+ // Make sure that the target related properties are initialized for the
+ // CommonOS variant.
+ addTargetProperties(module, commonTargetMap[os.Name], nil, true)
+ return
+ }
+
+ if variation == "" {
+ return
+ }
+
+ if !base.ArchSpecific() {
+ panic(fmt.Errorf("found variation %q for non arch specifc module", variation))
+ }
+
+ allArchInfo, ok := ModuleProvider(ctx, allArchProvider)
+ if !ok {
+ return
+ }
+
+ target, ok := allArchInfo.Targets[variation]
+ if !ok {
+ panic(fmt.Errorf("missing Target for %q", variation))
+ }
+ primary := variation == allArchInfo.Primary
+ multiTargets := allArchInfo.MultiTargets
+
+ // Annotate the new variant with which Target it was created for, and
+ // squash the appropriate arch-specific properties into the top level properties.
+ addTargetProperties(ctx.Module(), target, multiTargets, primary)
+ base.setArchProperties(ctx)
+
+ // Install support doesn't understand Darwin+Arm64
+ if os == Darwin && target.HostCross {
+ base.commonProperties.SkipInstall = true
+ }
// Create a dependency for Darwin Universal binaries from the primary to secondary
// architecture. The module itself will be responsible for calling lipo to merge the outputs.
if os == Darwin {
- if multilib == "darwin_universal" && len(modules) == 2 {
- mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[1], modules[0])
- } else if multilib == "darwin_universal_common_first" && len(modules) == 3 {
- mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[2], modules[1])
+ isUniversalBinary := (allArchInfo.Multilib == "darwin_universal" && len(allArchInfo.Targets) == 2) ||
+ allArchInfo.Multilib == "darwin_universal_common_first" && len(allArchInfo.Targets) == 3
+ isPrimary := variation == ctx.Config().BuildArch.String()
+ hasSecondaryConfigured := len(ctx.Config().Targets[Darwin]) > 1
+ if isUniversalBinary && isPrimary && hasSecondaryConfigured {
+ secondaryArch := ctx.Config().Targets[Darwin][1].Arch.String()
+ variation := []blueprint.Variation{{"arch", secondaryArch}}
+ ctx.AddVariationDependencies(variation, DarwinUniversalVariantTag, ctx.ModuleName())
}
}
+
}
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
@@ -698,7 +783,9 @@
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
// the actual multilib in extraMultilib.
-func decodeMultilib(base *ModuleBase, os OsType, ignorePrefer32OnDevice bool) (multilib, extraMultilib string) {
+func decodeMultilib(ctx ConfigContext, base *ModuleBase) (multilib, extraMultilib string) {
+ os := base.commonProperties.CompileOS
+ ignorePrefer32OnDevice := ctx.Config().IgnorePrefer32OnDevice()
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
switch os.Class {
case Device:
diff --git a/android/arch_list.go b/android/arch_list.go
index f1289a3..389f194 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -26,8 +26,10 @@
"armv8-2a",
"armv8-2a-dotprod",
"armv9-a",
+ "armv9-2a",
},
X86: {
+ "alderlake",
"amberlake",
"atom",
"broadwell",
@@ -52,6 +54,7 @@
"x86_64",
},
X86_64: {
+ "alderlake",
"amberlake",
"broadwell",
"goldmont",
@@ -109,9 +112,6 @@
}
var archFeatures = map[ArchType][]string{
- Arm: {
- "neon",
- },
Arm64: {
"dotprod",
},
@@ -141,17 +141,6 @@
}
var androidArchFeatureMap = map[ArchType]map[string][]string{
- Arm: {
- "armv7-a-neon": {
- "neon",
- },
- "armv8-a": {
- "neon",
- },
- "armv8-2a": {
- "neon",
- },
- },
Arm64: {
"armv8-2a-dotprod": {
"dotprod",
@@ -159,8 +148,21 @@
"armv9-a": {
"dotprod",
},
+ "armv9-2a": {
+ "dotprod",
+ },
},
X86: {
+ "alderlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
"amberlake": {
"ssse3",
"sse4",
@@ -337,6 +339,16 @@
"sse4_2",
"popcnt",
},
+ "alderlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
"amberlake": {
"ssse3",
"sse4",
diff --git a/android/arch_test.go b/android/arch_test.go
index 6134a06..57c9010 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -451,7 +451,7 @@
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
- if tt.goOS != runtime.GOOS {
+ if tt.goOS != "" && tt.goOS != runtime.GOOS {
t.Skipf("requries runtime.GOOS %s", tt.goOS)
}
diff --git a/android/base_module_context.go b/android/base_module_context.go
index 5506000..c7d7573 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -113,31 +113,22 @@
// the first DependencyTag.
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
- // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
+ // 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
+ // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
+ // dependencies are disabled.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
+ VisitDirectDeps(visit func(Module))
+
+ // 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
// and OtherModuleDependencyTag will return a different tag for each.
//
// The Module passed to the visit function should not be retained outside of the visit
// function, it may be invalidated by future mutators.
- VisitDirectDepsBlueprint(visit func(blueprint.Module))
-
- // VisitDirectDepsIgnoreBlueprint 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
- // and OtherModuleDependencyTag will return a different tag for each. It silently ignores any
- // dependencies that are not an android.Module.
- //
- // The Module passed to the visit function should not be retained outside of the visit
- // function, it may be invalidated by future mutators.
- VisitDirectDepsIgnoreBlueprint(visit func(Module))
-
- // 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
- // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
- // dependencies are not an android.Module.
- //
- // The Module passed to the visit function should not be retained outside of the visit
- // function, it may be invalidated by future mutators.
- VisitDirectDeps(visit func(Module))
+ VisitDirectDepsAllowDisabled(visit func(Module))
VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
@@ -164,17 +155,6 @@
// invalidated by future mutators.
WalkDeps(visit func(child, parent Module) bool)
- // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
- // tree in top down order. visit may be called multiple times for the same (child, parent)
- // pair if there are multiple direct dependencies between the child and parent with different
- // tags. OtherModuleDependencyTag will return the tag for the currently visited
- // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
- // to child.
- //
- // The Modules passed to the visit function should not be retained outside of the visit function, they may be
- // invalidated by future mutators.
- WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
-
// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
@@ -311,7 +291,7 @@
return true
}
-func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
+func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
aModule, _ := module.(Module)
if !strict {
@@ -319,10 +299,7 @@
}
if aModule == nil {
- if !ignoreBlueprint {
- b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
- }
- return nil
+ panic(fmt.Errorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag))
}
if !aModule.Enabled(b) {
@@ -345,15 +322,8 @@
func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
var deps []dep
- b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil {
- if aModule.base().BaseModuleName() == name {
- returnedTag := b.bp.OtherModuleDependencyTag(aModule)
- if tag == nil || returnedTag == tag {
- deps = append(deps, dep{aModule, returnedTag})
- }
- }
- } else if b.bp.OtherModuleName(module) == name {
+ 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})
@@ -396,11 +366,9 @@
func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
var deps []Module
- b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil {
- if b.bp.OtherModuleDependencyTag(aModule) == tag {
- deps = append(deps, aModule)
- }
+ b.VisitDirectDeps(func(module Module) {
+ if b.bp.OtherModuleDependencyTag(module) == tag {
+ deps = append(deps, module)
}
})
return deps
@@ -413,30 +381,24 @@
return b.getDirectDepFirstTag(name)
}
-func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
- b.bp.VisitDirectDeps(visit)
-}
-
func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
- b.visitDirectDeps(visit, false)
-}
-
-func (b *baseModuleContext) VisitDirectDepsIgnoreBlueprint(visit func(Module)) {
- b.visitDirectDeps(visit, true)
-}
-
-func (b *baseModuleContext) visitDirectDeps(visit func(Module), ignoreBlueprint bool) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, ignoreBlueprint); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
}
+func (b *baseModuleContext) VisitDirectDepsAllowDisabled(visit func(Module)) {
+ b.bp.VisitDirectDeps(func(module blueprint.Module) {
+ visit(module.(Module))
+ })
+}
+
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
if b.bp.OtherModuleDependencyTag(module) == tag {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
}
@@ -447,7 +409,7 @@
b.bp.VisitDirectDepsIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -461,7 +423,7 @@
func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
visit(aModule)
}
})
@@ -471,7 +433,7 @@
b.bp.VisitDepsDepthFirstIf(
// pred
func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
return pred(aModule)
} else {
return false
@@ -483,10 +445,6 @@
})
}
-func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
- b.bp.WalkDeps(visit)
-}
-
func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
b.walkPath = []Module{b.Module()}
b.tagPath = []blueprint.DependencyTag{}
diff --git a/android/build_prop.go b/android/build_prop.go
index 45c17c3..ede93ed 100644
--- a/android/build_prop.go
+++ b/android/build_prop.go
@@ -31,16 +31,15 @@
// properties in prop_files.
Block_list []string
- // Path to the input prop files. The contents of the files are directly
- // emitted to the output
- Prop_files []string `android:"path"`
-
// Files to be appended at the end of build.prop. These files are appended after
// post_process_props without any further checking.
Footer_files []string `android:"path"`
// Path to a JSON file containing product configs.
Product_config *string `android:"path"`
+
+ // Optional subdirectory under which this file is installed into
+ Relative_install_path *string
}
type buildPropModule struct {
@@ -56,16 +55,68 @@
return proptools.StringDefault(p.properties.Stem, "build.prop")
}
+func (p *buildPropModule) propFiles(ctx ModuleContext) Paths {
+ partition := p.partition(ctx.DeviceConfig())
+ if partition == "system" {
+ return ctx.Config().SystemPropFiles(ctx)
+ } else if partition == "system_ext" {
+ return ctx.Config().SystemExtPropFiles(ctx)
+ } else if partition == "product" {
+ return ctx.Config().ProductPropFiles(ctx)
+ } else if partition == "odm" {
+ return ctx.Config().OdmPropFiles(ctx)
+ }
+ return nil
+}
+
+func shouldAddBuildThumbprint(config Config) bool {
+ knownOemProperties := []string{
+ "ro.product.brand",
+ "ro.product.name",
+ "ro.product.device",
+ }
+
+ for _, knownProp := range knownOemProperties {
+ if InList(knownProp, config.OemProperties()) {
+ return true
+ }
+ }
+ return false
+}
+
+// Can't use PartitionTag() because PartitionTag() returns the partition this module is actually
+// installed (e.g. odm module's partition tag can be either "odm" or "vendor")
+func (p *buildPropModule) partition(config DeviceConfig) string {
+ if p.SocSpecific() {
+ return "vendor"
+ } else if p.DeviceSpecific() {
+ return "odm"
+ } else if p.ProductSpecific() {
+ return "product"
+ } else if p.SystemExtSpecific() {
+ return "system_ext"
+ }
+ return "system"
+}
+
+var validPartitions = []string{
+ "system",
+ "system_ext",
+ "product",
+ "odm",
+}
+
func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath
if !ctx.Config().KatiEnabled() {
WriteFileRule(ctx, p.outputFilePath, "# no build.prop if kati is disabled")
+ ctx.SetOutputFiles(Paths{p.outputFilePath}, "")
return
}
- partition := p.PartitionTag(ctx.DeviceConfig())
- if partition != "system" {
- ctx.PropertyErrorf("partition", "unsupported partition %q: only \"system\" is supported", partition)
+ partition := p.partition(ctx.DeviceConfig())
+ if !InList(partition, validPartitions) {
+ ctx.PropertyErrorf("partition", "unsupported partition %q: only %q are supported", partition, validPartitions)
return
}
@@ -93,6 +144,7 @@
cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx))
cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config)))
cmd.FlagWithArg("--partition=", partition)
+ cmd.FlagForEachInput("--prop-files=", p.propFiles(ctx))
cmd.FlagWithOutput("--out=", p.outputFilePath)
postProcessCmd := rule.Command().BuiltTool("post_process_props")
@@ -100,7 +152,12 @@
postProcessCmd.Flag("--allow-dup")
}
postProcessCmd.FlagWithArg("--sdk-version ", config.PlatformSdkVersion().String())
- postProcessCmd.FlagWithInput("--kernel-version-file-for-uffd-gc ", PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt"))
+ if ctx.Config().EnableUffdGc() == "default" {
+ postProcessCmd.FlagWithInput("--kernel-version-file-for-uffd-gc ", PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt"))
+ } else {
+ // still need to pass an empty string to kernel-version-file-for-uffd-gc
+ postProcessCmd.FlagWithArg("--kernel-version-file-for-uffd-gc ", `""`)
+ }
postProcessCmd.Text(p.outputFilePath.String())
postProcessCmd.Flags(p.properties.Block_list)
@@ -108,12 +165,25 @@
rule.Build(ctx.ModuleName(), "generating build.prop")
- p.installPath = PathForModuleInstall(ctx)
+ p.installPath = PathForModuleInstall(ctx, proptools.String(p.properties.Relative_install_path))
ctx.InstallFile(p.installPath, p.stem(), p.outputFilePath)
ctx.SetOutputFiles(Paths{p.outputFilePath}, "")
}
+func (p *buildPropModule) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: OptionalPathForPath(p.outputFilePath),
+ ExtraEntries: []AndroidMkExtraEntriesFunc{
+ func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", p.installPath.String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
+ },
+ },
+ }}
+}
+
// build_prop module generates {partition}/build.prop file. At first common build properties are
// printed based on Soong config variables. And then prop_files are printed as-is. Finally,
// post_process_props tool is run to check if the result build.prop is valid or not.
diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go
deleted file mode 100644
index bba4c0d..0000000
--- a/android/buildinfo_prop.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2022 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() {
- ctx := InitRegistrationContext
- ctx.RegisterModuleType("buildinfo_prop", buildinfoPropFactory)
-}
-
-type buildinfoPropProperties struct {
- // Whether this module is directly installable to one of the partitions. Default: true.
- Installable *bool
-
- Product_config *string `android:"path"`
-}
-
-type buildinfoPropModule struct {
- ModuleBase
-
- properties buildinfoPropProperties
-
- outputFilePath OutputPath
- installPath InstallPath
-}
-
-func (p *buildinfoPropModule) installable() bool {
- return proptools.BoolDefault(p.properties.Installable, true)
-}
-
-func shouldAddBuildThumbprint(config Config) bool {
- knownOemProperties := []string{
- "ro.product.brand",
- "ro.product.name",
- "ro.product.device",
- }
-
- for _, knownProp := range knownOemProperties {
- if InList(knownProp, config.OemProperties()) {
- return true
- }
- }
- return false
-}
-
-func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- if ctx.ModuleName() != "buildinfo.prop" || ctx.ModuleDir() != "build/soong" {
- ctx.ModuleErrorf("There can only be one buildinfo_prop module in build/soong")
- return
- }
- p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath
- ctx.SetOutputFiles(Paths{p.outputFilePath}, "")
-
- if !ctx.Config().KatiEnabled() {
- WriteFileRule(ctx, p.outputFilePath, "# no buildinfo.prop if kati is disabled")
- return
- }
-
- rule := NewRuleBuilder(pctx, ctx)
-
- config := ctx.Config()
-
- cmd := rule.Command().BuiltTool("buildinfo")
-
- cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx))
- // Note: depending on BuildNumberFile will cause the build.prop file to be rebuilt
- // every build, but that's intentional.
- cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx))
- // Export build thumbprint only if the product has specified at least one oem fingerprint property
- // b/17888863
- if shouldAddBuildThumbprint(config) {
- // In the previous make implementation, a dependency was not added on the thumbprint file
- cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String())
- }
- cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME"))
- // Technically we should also have a dependency on BUILD_DATETIME_FILE,
- // but it can be either an absolute or relative path, which is hard to turn into
- // a Path object. So just rely on the BuildNumberFile always changing to cause
- // us to rebuild.
- cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE"))
- cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx))
- cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config)))
- cmd.FlagWithOutput("--out=", p.outputFilePath)
-
- rule.Build(ctx.ModuleName(), "generating buildinfo props")
-
- if !p.installable() {
- p.SkipInstall()
- }
-
- p.installPath = PathForModuleInstall(ctx)
- ctx.InstallFile(p.installPath, p.Name(), p.outputFilePath)
-}
-
-func (p *buildinfoPropModule) AndroidMkEntries() []AndroidMkEntries {
- return []AndroidMkEntries{{
- Class: "ETC",
- OutputFile: OptionalPathForPath(p.outputFilePath),
- ExtraEntries: []AndroidMkExtraEntriesFunc{
- func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", p.installPath.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
- entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
- },
- },
- }}
-}
-
-// buildinfo_prop module generates a build.prop file, which contains a set of common
-// system/build.prop properties, such as ro.build.version.*. Not all properties are implemented;
-// currently this module is only for microdroid.
-func buildinfoPropFactory() Module {
- module := &buildinfoPropModule{}
- module.AddProperties(&module.properties)
- InitAndroidModule(module)
- return module
-}
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 6ea6654..38f1382 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -17,6 +17,7 @@
import (
"bytes"
"encoding/csv"
+ "encoding/gob"
"fmt"
"slices"
"strconv"
@@ -131,6 +132,28 @@
}
}
+func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
+ w := new(bytes.Buffer)
+ encoder := gob.NewEncoder(w)
+ err := encoder.Encode(c.properties)
+ if err != nil {
+ return nil, err
+ }
+
+ return w.Bytes(), nil
+}
+
+func (c *ComplianceMetadataInfo) GobDecode(data []byte) error {
+ r := bytes.NewBuffer(data)
+ decoder := gob.NewDecoder(r)
+ err := decoder.Decode(&c.properties)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
func (c *ComplianceMetadataInfo) SetStringValue(propertyName string, value string) {
if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
@@ -160,7 +183,7 @@
// buildComplianceMetadataProvider starts with the ModuleContext.ComplianceMetadataInfo() and fills in more common metadata
// for different module types without accessing their private fields but through android.Module interface
// and public/private fields of package android. The final metadata is stored to a module's ComplianceMetadataProvider.
-func buildComplianceMetadataProvider(ctx ModuleContext, m *ModuleBase) {
+func buildComplianceMetadataProvider(ctx *moduleContext, m *ModuleBase) {
complianceMetadataInfo := ctx.ComplianceMetadataInfo()
complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.NAME, m.Name())
complianceMetadataInfo.SetStringValue(ComplianceMetadataProp.PACKAGE, ctx.ModuleDir())
@@ -186,11 +209,11 @@
}
var installed InstallPaths
- installed = append(installed, m.module.FilesToInstall()...)
- installed = append(installed, m.katiInstalls.InstallPaths()...)
- installed = append(installed, m.katiSymlinks.InstallPaths()...)
- installed = append(installed, m.katiInitRcInstalls.InstallPaths()...)
- installed = append(installed, m.katiVintfInstalls.InstallPaths()...)
+ installed = append(installed, ctx.installFiles...)
+ installed = append(installed, ctx.katiInstalls.InstallPaths()...)
+ installed = append(installed, ctx.katiSymlinks.InstallPaths()...)
+ installed = append(installed, ctx.katiInitRcInstalls.InstallPaths()...)
+ installed = append(installed, ctx.katiVintfInstalls.InstallPaths()...)
complianceMetadataInfo.SetListValue(ComplianceMetadataProp.INSTALLED_FILES, FirstUniqueStrings(installed.Strings()))
}
ctx.setProvider(ComplianceMetadataProvider, complianceMetadataInfo)
@@ -267,7 +290,7 @@
writerToCsv(csvWriter, metadata)
return
}
- if provider, ok := ctx.moduleProvider(module, ComplianceMetadataProvider); ok {
+ if provider, ok := ctx.otherModuleProvider(module, ComplianceMetadataProvider); ok {
metadataInfo := provider.(*ComplianceMetadataInfo)
rowId = rowId + 1
metadata := []string{strconv.Itoa(rowId)}
diff --git a/android/config.go b/android/config.go
index cadc929..e519760 100644
--- a/android/config.go
+++ b/android/config.go
@@ -173,6 +173,13 @@
return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || c.ReleaseDisableVerifyOverlaps() || !c.ReleaseDefaultModuleBuildFromSource()
}
+func (c Config) CoverageSuffix() string {
+ if v := c.IsEnvTrue("EMMA_INSTRUMENT"); v {
+ return "coverage."
+ }
+ return ""
+}
+
// MaxPageSizeSupported returns the max page size supported by the device. This
// value will define the ELF segment alignment for binaries (executables and
// shared libraries).
@@ -231,6 +238,11 @@
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 {
@@ -238,6 +250,13 @@
Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
}
+func (c Config) ReleaseDefaultUpdatableModuleVersion() string {
+ if val, exists := c.GetBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION"); exists {
+ return val
+ }
+ panic("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION is missing from build flags.")
+}
+
func (c Config) ReleaseDisableVerifyOverlaps() bool {
return c.config.productVariables.GetBuildFlagBool("RELEASE_DISABLE_VERIFY_OVERLAPS_CHECK")
}
@@ -263,6 +282,11 @@
Bool(c.config.productVariables.HiddenapiExportableStubs)
}
+// Enable read flag from new storage
+func (c Config) ReleaseReadFromNewStorage() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE")
+}
+
// 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.
@@ -343,9 +367,6 @@
// modules that aren't mixed-built for at least one variant will cause a build
// failure
ensureAllowlistIntegrity bool
-
- // List of Api libraries that contribute to Api surfaces.
- apiLibraries map[string]struct{}
}
type deviceConfig struct {
@@ -595,40 +616,6 @@
setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
setBuildMode(cmdArgs.DocFile, GenerateDocFile)
- // TODO(b/276958307): Replace the hardcoded list to a sdk_library local prop.
- config.apiLibraries = map[string]struct{}{
- "android.net.ipsec.ike": {},
- "art.module.public.api": {},
- "conscrypt.module.public.api": {},
- "framework-adservices": {},
- "framework-appsearch": {},
- "framework-bluetooth": {},
- "framework-configinfrastructure": {},
- "framework-connectivity": {},
- "framework-connectivity-t": {},
- "framework-devicelock": {},
- "framework-graphics": {},
- "framework-healthfitness": {},
- "framework-location": {},
- "framework-media": {},
- "framework-mediaprovider": {},
- "framework-nfc": {},
- "framework-ondevicepersonalization": {},
- "framework-pdf": {},
- "framework-pdf-v": {},
- "framework-permission": {},
- "framework-permission-s": {},
- "framework-scheduling": {},
- "framework-sdkextensions": {},
- "framework-statsd": {},
- "framework-sdksandbox": {},
- "framework-tethering": {},
- "framework-uwb": {},
- "framework-virtualization": {},
- "framework-wifi": {},
- "i18n.module.public.api": {},
- }
-
config.productVariables.Build_from_text_stub = boolPtr(config.BuildFromTextStub())
return Config{config}, err
@@ -1272,7 +1259,7 @@
}
func (c *config) LibartImgHostBaseAddress() string {
- return "0x60000000"
+ return "0x70000000"
}
func (c *config) LibartImgDeviceBaseAddress() string {
@@ -1298,6 +1285,7 @@
}
return false
}
+
func (c *config) EnforceRROExcludedOverlay(path string) bool {
excluded := c.productVariables.EnforceRROExcludedOverlays
if len(excluded) > 0 {
@@ -1306,6 +1294,11 @@
return false
}
+func (c *config) EnforceRROGlobally() bool {
+ enforceList := c.productVariables.EnforceRROTargets
+ return InList("*", enforceList)
+}
+
func (c *config) ExportedNamespaces() []string {
return append([]string(nil), c.productVariables.NamespacesToExport...)
}
@@ -1520,11 +1513,6 @@
}
}
if coverage && len(c.config.productVariables.NativeCoverageExcludePaths) > 0 {
- // Workaround coverage boot failure.
- // http://b/269981180
- if strings.HasPrefix(path, "external/protobuf") {
- coverage = false
- }
if HasAnyPrefix(path, c.config.productVariables.NativeCoverageExcludePaths) {
coverage = false
}
@@ -1693,6 +1681,17 @@
return Bool(c.productVariables.TrimmedApex)
}
+func (c *config) UseSoongSystemImage() bool {
+ return Bool(c.productVariables.UseSoongSystemImage)
+}
+
+func (c *config) SoongDefinedSystemImage() string {
+ if c.UseSoongSystemImage() {
+ return String(c.productVariables.ProductSoongDefinedSystemImage)
+ }
+ return ""
+}
+
func (c *config) EnforceSystemCertificate() bool {
return Bool(c.productVariables.EnforceSystemCertificate)
}
@@ -1705,14 +1704,6 @@
return Bool(c.productVariables.EnforceProductPartitionInterface)
}
-func (c *config) EnforceInterPartitionJavaSdkLibrary() bool {
- return Bool(c.productVariables.EnforceInterPartitionJavaSdkLibrary)
-}
-
-func (c *config) InterPartitionJavaLibraryAllowList() []string {
- return c.productVariables.InterPartitionJavaLibraryAllowList
-}
-
func (c *config) ProductHiddenAPIStubs() []string {
return c.productVariables.ProductHiddenAPIStubs
}
@@ -1858,10 +1849,6 @@
return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow
}
-func (c *deviceConfig) BuildBrokenUsesSoongPython2Modules() bool {
- return c.config.productVariables.BuildBrokenUsesSoongPython2Modules
-}
-
func (c *deviceConfig) BuildDebugfsRestrictionsEnabled() bool {
return c.config.productVariables.BuildDebugfsRestrictionsEnabled
}
@@ -1979,17 +1966,6 @@
c.productVariables.Build_from_text_stub = boolPtr(b)
}
-func (c *config) SetApiLibraries(libs []string) {
- c.apiLibraries = make(map[string]struct{})
- for _, lib := range libs {
- c.apiLibraries[lib] = struct{}{}
- }
-}
-
-func (c *config) GetApiLibraries() map[string]struct{} {
- return c.apiLibraries
-}
-
func (c *deviceConfig) CheckVendorSeappViolations() bool {
return Bool(c.config.productVariables.CheckVendorSeappViolations)
}
@@ -1999,46 +1975,54 @@
return val, ok
}
+func (c *config) UseOptimizedResourceShrinkingByDefault() bool {
+ 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) UseTransitiveJarsInClasspath() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_USE_TRANSITIVE_JARS_IN_CLASSPATH")
+}
+
var (
- mainlineApexContributionBuildFlags = []string{
- "RELEASE_APEX_CONTRIBUTIONS_ADBD",
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES",
- "RELEASE_APEX_CONTRIBUTIONS_APPSEARCH",
- "RELEASE_APEX_CONTRIBUTIONS_ART",
- "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH",
- "RELEASE_APEX_CONTRIBUTIONS_CAPTIVEPORTALLOGIN",
- "RELEASE_APEX_CONTRIBUTIONS_CELLBROADCAST",
- "RELEASE_APEX_CONTRIBUTIONS_CONFIGINFRASTRUCTURE",
- "RELEASE_APEX_CONTRIBUTIONS_CONNECTIVITY",
- "RELEASE_APEX_CONTRIBUTIONS_CONSCRYPT",
- "RELEASE_APEX_CONTRIBUTIONS_CRASHRECOVERY",
- "RELEASE_APEX_CONTRIBUTIONS_DEVICELOCK",
- "RELEASE_APEX_CONTRIBUTIONS_DOCUMENTSUIGOOGLE",
- "RELEASE_APEX_CONTRIBUTIONS_EXTSERVICES",
- "RELEASE_APEX_CONTRIBUTIONS_HEALTHFITNESS",
- "RELEASE_APEX_CONTRIBUTIONS_IPSEC",
- "RELEASE_APEX_CONTRIBUTIONS_MEDIA",
- "RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER",
- "RELEASE_APEX_CONTRIBUTIONS_MODULE_METADATA",
- "RELEASE_APEX_CONTRIBUTIONS_NETWORKSTACKGOOGLE",
- "RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS",
- "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION",
- "RELEASE_APEX_CONTRIBUTIONS_PERMISSION",
- "RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS",
- "RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING",
- "RELEASE_APEX_CONTRIBUTIONS_RESOLV",
- "RELEASE_APEX_CONTRIBUTIONS_SCHEDULING",
- "RELEASE_APEX_CONTRIBUTIONS_SDKEXTENSIONS",
- "RELEASE_APEX_CONTRIBUTIONS_SWCODEC",
- "RELEASE_APEX_CONTRIBUTIONS_STATSD",
- "RELEASE_APEX_CONTRIBUTIONS_TELEMETRY_TVP",
- "RELEASE_APEX_CONTRIBUTIONS_TZDATA",
- "RELEASE_APEX_CONTRIBUTIONS_UWB",
- "RELEASE_APEX_CONTRIBUTIONS_WIFI",
+ mainlineApexContributionBuildFlagsToApexNames = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADBD": "com.android.adbd",
+ "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_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_DEVICELOCK": "com.android.devicelock",
+ "RELEASE_APEX_CONTRIBUTIONS_DOCUMENTSUIGOOGLE": "",
+ "RELEASE_APEX_CONTRIBUTIONS_EXTSERVICES": "com.android.extservices",
+ "RELEASE_APEX_CONTRIBUTIONS_HEALTHFITNESS": "com.android.healthfitness",
+ "RELEASE_APEX_CONTRIBUTIONS_IPSEC": "com.android.ipsec",
+ "RELEASE_APEX_CONTRIBUTIONS_MEDIA": "com.android.media",
+ "RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER": "com.android.mediaprovider",
+ "RELEASE_APEX_CONTRIBUTIONS_MODULE_METADATA": "",
+ "RELEASE_APEX_CONTRIBUTIONS_NETWORKSTACKGOOGLE": "",
+ "RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS": "com.android.neuralnetworks",
+ "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION": "com.android.ondevicepersonalization",
+ "RELEASE_APEX_CONTRIBUTIONS_PERMISSION": "com.android.permission",
+ "RELEASE_APEX_CONTRIBUTIONS_PRIMARY_LIBS": "",
+ "RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING": "com.android.rkpd",
+ "RELEASE_APEX_CONTRIBUTIONS_RESOLV": "com.android.resolv",
+ "RELEASE_APEX_CONTRIBUTIONS_SCHEDULING": "com.android.scheduling",
+ "RELEASE_APEX_CONTRIBUTIONS_SDKEXTENSIONS": "com.android.sdkext",
+ "RELEASE_APEX_CONTRIBUTIONS_SWCODEC": "com.android.media.swcodec",
+ "RELEASE_APEX_CONTRIBUTIONS_STATSD": "com.android.os.statsd",
+ "RELEASE_APEX_CONTRIBUTIONS_TELEMETRY_TVP": "",
+ "RELEASE_APEX_CONTRIBUTIONS_TZDATA": "com.android.tzdata",
+ "RELEASE_APEX_CONTRIBUTIONS_UWB": "com.android.uwb",
+ "RELEASE_APEX_CONTRIBUTIONS_WIFI": "com.android.wifi",
}
)
@@ -2046,7 +2030,7 @@
// Each mainline module will have one entry in the list
func (c *config) AllApexContributions() []string {
ret := []string{}
- for _, f := range mainlineApexContributionBuildFlags {
+ for _, f := range SortedKeys(mainlineApexContributionBuildFlagsToApexNames) {
if val, exists := c.GetBuildFlag(f); exists && val != "" {
ret = append(ret, val)
}
@@ -2054,6 +2038,10 @@
return ret
}
+func (c *config) AllMainlineApexNames() []string {
+ return SortedStringValues(mainlineApexContributionBuildFlagsToApexNames)
+}
+
func (c *config) BuildIgnoreApexContributionContents() *bool {
return c.productVariables.BuildIgnoreApexContributionContents
}
@@ -2081,3 +2069,46 @@
return Bool(c.productVariables.Eng)
}
+
+func (c *config) SystemPropFiles(ctx PathContext) Paths {
+ return PathsForSource(ctx, c.productVariables.SystemPropFiles)
+}
+
+func (c *config) SystemExtPropFiles(ctx PathContext) Paths {
+ return PathsForSource(ctx, c.productVariables.SystemExtPropFiles)
+}
+
+func (c *config) ProductPropFiles(ctx PathContext) Paths {
+ return PathsForSource(ctx, c.productVariables.ProductPropFiles)
+}
+
+func (c *config) OdmPropFiles(ctx PathContext) Paths {
+ return PathsForSource(ctx, c.productVariables.OdmPropFiles)
+}
+
+func (c *config) EnableUffdGc() string {
+ return String(c.productVariables.EnableUffdGc)
+}
+
+func (c *config) DeviceFrameworkCompatibilityMatrixFile() []string {
+ return c.productVariables.DeviceFrameworkCompatibilityMatrixFile
+}
+
+func (c *config) DeviceProductCompatibilityMatrixFile() []string {
+ return c.productVariables.DeviceProductCompatibilityMatrixFile
+}
+
+func (c *config) BoardAvbEnable() bool {
+ return Bool(c.productVariables.BoardAvbEnable)
+}
+
+func (c *config) BoardAvbSystemAddHashtreeFooterArgs() []string {
+ return c.productVariables.BoardAvbSystemAddHashtreeFooterArgs
+}
+
+// Returns true if RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION is set to true.
+// If true, dexpreopt files of apex system server jars will be installed in the same partition as the parent apex.
+// If false, all these files will be installed in /system partition.
+func (c Config) InstallApexSystemServerDexpreoptSamePartition() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION")
+}
diff --git a/android/config_test.go b/android/config_test.go
index ca7c7f8..7732168 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -150,12 +150,7 @@
for _, tc := range testCases {
fixture := GroupFixturePreparers(
- FixtureModifyProductVariables(func(vars FixtureProductVariables) {
- if vars.BuildFlags == nil {
- vars.BuildFlags = make(map[string]string)
- }
- vars.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"] = tc.flag
- }),
+ PrepareForTestWithBuildFlag("RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS", tc.flag),
)
actual := fixture.RunTest(t).Config.ReleaseAconfigExtraReleaseConfigs()
AssertArrayString(t, tc.name, tc.expected, actual)
diff --git a/android/configurable_properties.go b/android/configurable_properties.go
index dad42fa..2c794a1 100644
--- a/android/configurable_properties.go
+++ b/android/configurable_properties.go
@@ -26,3 +26,9 @@
resultCases,
)
}
+
+func NewSimpleConfigurable[T proptools.ConfigurableElements](value T) proptools.Configurable[T] {
+ return proptools.NewConfigurable(nil, []proptools.ConfigurableCase[T]{
+ proptools.NewConfigurableCase(nil, &value),
+ })
+}
diff --git a/android/container.go b/android/container.go
index c4fdd9c..2a3777b 100644
--- a/android/container.go
+++ b/android/container.go
@@ -15,41 +15,222 @@
package android
import (
+ "fmt"
"reflect"
"slices"
+ "strings"
"github.com/google/blueprint"
)
+// ----------------------------------------------------------------------------
+// Start of the definitions of exception functions and the lookup table.
+//
+// Functions cannot be used as a value passed in providers, because functions are not
+// hashable. As a workaround, the [exceptionHandleFuncLabel] enum values are passed using providers,
+// and the corresponding functions are called from [exceptionHandleFunctionsTable] map.
+// ----------------------------------------------------------------------------
+
+type exceptionHandleFunc func(ModuleContext, Module, Module) bool
+
type StubsAvailableModule interface {
IsStubsModule() bool
}
// Returns true if the dependency module is a stubs module
-var depIsStubsModule = func(_ ModuleContext, _, dep Module) bool {
+var depIsStubsModule exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool {
if stubsModule, ok := dep.(StubsAvailableModule); ok {
return stubsModule.IsStubsModule()
}
return false
}
+// Returns true if the dependency module belongs to any of the apexes.
+var depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _, dep Module) 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 {
+ mContainersInfo, _ := getContainerModuleInfo(mctx, m)
+ depContainersInfo, _ := getContainerModuleInfo(mctx, dep)
+
+ return HasIntersection(mContainersInfo.ApexNames(), depContainersInfo.ApexNames())
+}
+
+// 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 {
+ mContainersInfo, _ := getContainerModuleInfo(mctx, m)
+
+ return !mContainersInfo.UpdatableApex()
+}
+
+// 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 {
+ mInstallable, _ := m.(InstallableModule)
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ return !InList(depTag, mInstallable.DynamicDependencyTags())
+}
+
+// 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 {
+ mInstallable, _ := m.(InstallableModule)
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ return !InList(depTag, append(mInstallable.StaticDependencyTags(), mInstallable.DynamicDependencyTags()...))
+}
+
+var globallyAllowlistedDependencies = []string{
+ // Modules that provide annotations used within the platform and apexes.
+ "aconfig-annotations-lib",
+ "framework-annotations-lib",
+ "unsupportedappusage",
+
+ // TODO(b/363016634): Remove from the allowlist when the module is converted
+ // to java_sdk_library and the java_aconfig_library modules depend on the stub.
+ "aconfig_storage_reader_java",
+
+ // framework-res provides core resources essential for building apps and system UI.
+ // This module is implicitly added as a dependency for java modules even when the
+ // dependency specifies sdk_version.
+ "framework-res",
+
+ // jacocoagent is implicitly added as a dependency in coverage builds, and is not installed
+ // on the device.
+ "jacocoagent",
+}
+
+// Returns true when the dependency is globally allowlisted for inter-container dependency
+var depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool {
+ return InList(dep.Name(), globallyAllowlistedDependencies)
+}
+
// Labels of exception functions, which are used to determine special dependencies that allow
// otherwise restricted inter-container dependencies
type exceptionHandleFuncLabel int
const (
checkStubs exceptionHandleFuncLabel = iota
+ checkApexModule
+ checkInCommonApexes
+ checkApexIsNonUpdatable
+ checkNotDynamicDepTag
+ checkNotStaticOrDynamicDepTag
+ checkGlobalAllowlistedDep
)
-// Functions cannot be used as a value passed in providers, because functions are not
-// hashable. As a workaround, the exceptionHandleFunc enum values are passed using providers,
-// and the corresponding functions are called from this map.
-var exceptionHandleFunctionsTable = map[exceptionHandleFuncLabel]func(ModuleContext, Module, Module) bool{
- checkStubs: depIsStubsModule,
+// Map of [exceptionHandleFuncLabel] to the [exceptionHandleFunc]
+var exceptionHandleFunctionsTable = map[exceptionHandleFuncLabel]exceptionHandleFunc{
+ checkStubs: depIsStubsModule,
+ checkApexModule: depIsApexModule,
+ checkInCommonApexes: belongsToCommonApexes,
+ checkApexIsNonUpdatable: belongsToNonUpdatableApex,
+ checkNotDynamicDepTag: depIsNotDynamicDepTag,
+ checkNotStaticOrDynamicDepTag: depIsNotStaticOrDynamicDepTag,
+ checkGlobalAllowlistedDep: depIsGloballyAllowlisted,
}
+// ----------------------------------------------------------------------------
+// Start of the definitions of container determination functions.
+//
+// Similar to the above section, below defines the functions used to determine
+// the container of each modules.
+// ----------------------------------------------------------------------------
+
+type containerBoundaryFunc func(mctx ModuleContext) bool
+
+var vendorContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+ m, ok := mctx.Module().(ImageInterface)
+ return mctx.Module().InstallInVendor() || (ok && m.VendorVariantNeeded(mctx))
+}
+
+var systemContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+ module := mctx.Module()
+
+ return !module.InstallInTestcases() &&
+ !module.InstallInData() &&
+ !module.InstallInRamdisk() &&
+ !module.InstallInVendorRamdisk() &&
+ !module.InstallInDebugRamdisk() &&
+ !module.InstallInRecovery() &&
+ !module.InstallInVendor() &&
+ !module.InstallInOdm() &&
+ !module.InstallInProduct() &&
+ determineModuleKind(module.base(), mctx.blueprintBaseModuleContext()) == platformModule
+}
+
+var productContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+ m, ok := mctx.Module().(ImageInterface)
+ return mctx.Module().InstallInProduct() || (ok && m.ProductVariantNeeded(mctx))
+}
+
+var apexContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+ _, ok := ModuleProvider(mctx, AllApexInfoProvider)
+ return ok
+}
+
+var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+ props := mctx.Module().GetProperties()
+ for _, prop := range props {
+ val := reflect.ValueOf(prop).Elem()
+ if val.Kind() == reflect.Struct {
+ testSuites := val.FieldByName("Test_suites")
+ if testSuites.IsValid() && testSuites.Kind() == reflect.Slice && slices.Contains(testSuites.Interface().([]string), "cts") {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+type unstableInfo struct {
+ // Determines if the module contains the private APIs of the platform.
+ ContainsPlatformPrivateApis bool
+}
+
+var unstableInfoProvider = blueprint.NewProvider[unstableInfo]()
+
+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) {
+ if unstableInfo, ok := OtherModuleProvider(mctx, dep, unstableInfoProvider); ok {
+ unstableModule = unstableModule || unstableInfo.ContainsPlatformPrivateApis
+ }
+ })
+ }
+ }
+ return unstableModule
+}
+
+var unstableContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
+ return determineUnstableModule(mctx)
+}
+
+// Map of [*container] to the [containerBoundaryFunc]
+var containerBoundaryFunctionsTable = map[*container]containerBoundaryFunc{
+ VendorContainer: vendorContainerBoundaryFunc,
+ SystemContainer: systemContainerBoundaryFunc,
+ ProductContainer: productContainerBoundaryFunc,
+ ApexContainer: apexContainerBoundaryFunc,
+ CtsContainer: ctsContainerBoundaryFunc,
+ UnstableContainer: unstableContainerBoundaryFunc,
+}
+
+// ----------------------------------------------------------------------------
+// End of the definitions of container determination functions.
+// ----------------------------------------------------------------------------
+
type InstallableModule interface {
- EnforceApiContainerChecks() bool
+ StaticDependencyTags() []blueprint.DependencyTag
+ DynamicDependencyTags() []blueprint.DependencyTag
}
type restriction struct {
@@ -77,6 +258,7 @@
name: VendorVariation,
restricted: nil,
}
+
SystemContainer = &container{
name: "system",
restricted: []restriction{
@@ -86,10 +268,15 @@
"not allowed to depend on the vendor partition module, in order to support " +
"independent development/update cycles and to support the Generic System " +
"Image. Try depending on HALs, VNDK or AIDL instead.",
- allowedExceptions: []exceptionHandleFuncLabel{},
+ allowedExceptions: []exceptionHandleFuncLabel{
+ checkStubs,
+ checkNotDynamicDepTag,
+ checkGlobalAllowlistedDep,
+ },
},
},
}
+
ProductContainer = &container{
name: ProductVariation,
restricted: []restriction{
@@ -98,24 +285,50 @@
errorMessage: "Module belonging to the product partition is not allowed to " +
"depend on the vendor partition module, as this may lead to security " +
"vulnerabilities. Try depending on the HALs or utilize AIDL instead.",
- allowedExceptions: []exceptionHandleFuncLabel{},
+ allowedExceptions: []exceptionHandleFuncLabel{
+ checkStubs,
+ checkNotDynamicDepTag,
+ checkGlobalAllowlistedDep,
+ },
},
},
}
+
ApexContainer = initializeApexContainer()
- CtsContainer = &container{
+
+ CtsContainer = &container{
name: "cts",
restricted: []restriction{
{
- dependency: SystemContainer,
- errorMessage: "CTS module should not depend on the modules belonging to the " +
- "system partition, including \"framework\". Depending on the system " +
- "partition may lead to disclosure of implementation details and regression " +
- "due to API changes across platform versions. Try depending on the stubs instead.",
- allowedExceptions: []exceptionHandleFuncLabel{checkStubs},
+ dependency: UnstableContainer,
+ errorMessage: "CTS module should not depend on the modules that contain the " +
+ "platform implementation details, including \"framework\". Depending on these " +
+ "modules may lead to disclosure of implementation details and regression " +
+ "due to API changes across platform versions. Try depending on the stubs instead " +
+ "and ensure that the module sets an appropriate 'sdk_version'.",
+ allowedExceptions: []exceptionHandleFuncLabel{
+ checkStubs,
+ checkNotStaticOrDynamicDepTag,
+ checkGlobalAllowlistedDep,
+ },
},
},
}
+
+ // Container signifying that the module contains unstable platform private APIs
+ UnstableContainer = &container{
+ name: "unstable",
+ restricted: nil,
+ }
+
+ allContainers = []*container{
+ VendorContainer,
+ SystemContainer,
+ ProductContainer,
+ ApexContainer,
+ CtsContainer,
+ UnstableContainer,
+ }
)
func initializeApexContainer() *container {
@@ -128,7 +341,14 @@
"modules belonging to the system partition. Either statically depend on the " +
"module or convert the depending module to java_sdk_library and depend on " +
"the stubs.",
- allowedExceptions: []exceptionHandleFuncLabel{checkStubs},
+ allowedExceptions: []exceptionHandleFuncLabel{
+ checkStubs,
+ checkApexModule,
+ checkInCommonApexes,
+ checkApexIsNonUpdatable,
+ checkNotStaticOrDynamicDepTag,
+ checkGlobalAllowlistedDep,
+ },
},
},
}
@@ -139,7 +359,12 @@
"modules belonging to other Apex(es). Either include the depending " +
"module in the Apex or convert the depending module to java_sdk_library " +
"and depend on its stubs.",
- allowedExceptions: []exceptionHandleFuncLabel{checkStubs},
+ allowedExceptions: []exceptionHandleFuncLabel{
+ checkStubs,
+ checkInCommonApexes,
+ checkNotStaticOrDynamicDepTag,
+ checkGlobalAllowlistedDep,
+ },
})
return apexContainer
@@ -155,68 +380,72 @@
return c.belongingContainers
}
+func (c *ContainersInfo) ApexNames() (ret []string) {
+ for _, apex := range c.belongingApexes {
+ ret = append(ret, apex.InApexModules...)
+ }
+ slices.Sort(ret)
+ return ret
+}
+
+// Returns true if any of the apex the module belongs to is updatable.
+func (c *ContainersInfo) UpdatableApex() bool {
+ for _, apex := range c.belongingApexes {
+ if apex.Updatable {
+ return true
+ }
+ }
+ return false
+}
+
var ContainersInfoProvider = blueprint.NewProvider[ContainersInfo]()
-// Determines if the module can be installed in the system partition or not.
-// Logic is identical to that of modulePartition(...) defined in paths.go
-func installInSystemPartition(ctx ModuleContext) bool {
- module := ctx.Module()
- return !module.InstallInTestcases() &&
- !module.InstallInData() &&
- !module.InstallInRamdisk() &&
- !module.InstallInVendorRamdisk() &&
- !module.InstallInDebugRamdisk() &&
- !module.InstallInRecovery() &&
- !module.InstallInVendor() &&
- !module.InstallInOdm() &&
- !module.InstallInProduct() &&
- determineModuleKind(module.base(), ctx.blueprintBaseModuleContext()) == platformModule
+func satisfyAllowedExceptions(ctx ModuleContext, allowedExceptionLabels []exceptionHandleFuncLabel, m, dep Module) bool {
+ for _, label := range allowedExceptionLabels {
+ if exceptionHandleFunctionsTable[label](ctx, m, dep) {
+ return true
+ }
+ }
+ return false
+}
+
+func (c *ContainersInfo) GetViolations(mctx ModuleContext, m, dep Module, depInfo ContainersInfo) []string {
+ var violations []string
+
+ // Any containers that the module belongs to but the dependency does not belong to must be examined.
+ _, containersUniqueToModule, _ := ListSetDifference(c.belongingContainers, depInfo.belongingContainers)
+
+ // Apex container should be examined even if both the module and the dependency belong to
+ // the apex container to check that the two modules belong to the same apex.
+ if InList(ApexContainer, c.belongingContainers) && !InList(ApexContainer, containersUniqueToModule) {
+ containersUniqueToModule = append(containersUniqueToModule, ApexContainer)
+ }
+
+ for _, containerUniqueToModule := range containersUniqueToModule {
+ for _, restriction := range containerUniqueToModule.restricted {
+ if InList(restriction.dependency, depInfo.belongingContainers) {
+ if !satisfyAllowedExceptions(mctx, restriction.allowedExceptions, m, dep) {
+ violations = append(violations, restriction.errorMessage)
+ }
+ }
+ }
+ }
+
+ return violations
}
func generateContainerInfo(ctx ModuleContext) ContainersInfo {
- inSystem := installInSystemPartition(ctx)
- inProduct := ctx.Module().InstallInProduct()
- inVendor := ctx.Module().InstallInVendor()
- inCts := false
- inApex := false
+ var containers []*container
- if m, ok := ctx.Module().(ImageInterface); ok {
- inProduct = inProduct || m.ProductVariantNeeded(ctx)
- inVendor = inVendor || m.VendorVariantNeeded(ctx)
- }
-
- props := ctx.Module().GetProperties()
- for _, prop := range props {
- val := reflect.ValueOf(prop).Elem()
- if val.Kind() == reflect.Struct {
- testSuites := val.FieldByName("Test_suites")
- if testSuites.IsValid() && testSuites.Kind() == reflect.Slice && slices.Contains(testSuites.Interface().([]string), "cts") {
- inCts = true
- }
+ for _, cnt := range allContainers {
+ if containerBoundaryFunctionsTable[cnt](ctx) {
+ containers = append(containers, cnt)
}
}
var belongingApexes []ApexInfo
if apexInfo, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
belongingApexes = apexInfo.ApexInfos
- inApex = true
- }
-
- containers := []*container{}
- if inSystem {
- containers = append(containers, SystemContainer)
- }
- if inProduct {
- containers = append(containers, ProductContainer)
- }
- if inVendor {
- containers = append(containers, VendorContainer)
- }
- if inCts {
- containers = append(containers, CtsContainer)
- }
- if inApex {
- containers = append(containers, ApexContainer)
}
return ContainersInfo{
@@ -225,9 +454,53 @@
}
}
+func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) {
+ if ctx.Module() == module {
+ return ctx.getContainersInfo(), true
+ }
+
+ return OtherModuleProvider(ctx, module, ContainersInfoProvider)
+}
+
func setContainerInfo(ctx ModuleContext) {
+ // Required to determine the unstable container. This provider is set here instead of the
+ // unstableContainerBoundaryFunc in order to prevent setting the provider multiple times.
+ SetProvider(ctx, unstableInfoProvider, unstableInfo{
+ ContainsPlatformPrivateApis: determineUnstableModule(ctx),
+ })
+
if _, ok := ctx.Module().(InstallableModule); ok {
containersInfo := generateContainerInfo(ctx)
+ ctx.setContainersInfo(containersInfo)
SetProvider(ctx, ContainersInfoProvider, containersInfo)
}
}
+
+func checkContainerViolations(ctx ModuleContext) {
+ if _, ok := ctx.Module().(InstallableModule); ok {
+ containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module())
+ ctx.VisitDirectDeps(func(dep Module) {
+ if !dep.Enabled(ctx) {
+ return
+ }
+
+ // Pre-existing violating dependencies are tracked in containerDependencyViolationAllowlist.
+ // If this dependency is allowlisted, do not check for violation.
+ // If not, check if this dependency matches any restricted dependency and
+ // satisfies any exception functions, which allows bypassing the
+ // restriction. If all of the exceptions are not satisfied, throw an error.
+ if depContainersInfo, ok := getContainerModuleInfo(ctx, dep); ok {
+ if allowedViolations, ok := ContainerDependencyViolationAllowlist[ctx.ModuleName()]; ok && InList(dep.Name(), allowedViolations) {
+ return
+ } else {
+ violations := containersInfo.GetViolations(ctx, ctx.Module(), dep, depContainersInfo)
+ if len(violations) > 0 {
+ errorMessage := fmt.Sprintf("%s cannot depend on %s. ", ctx.ModuleName(), dep.Name())
+ errorMessage += strings.Join(violations, " ")
+ ctx.ModuleErrorf(errorMessage)
+ }
+ }
+ }
+ })
+ }
+}
diff --git a/android/container_violations.go b/android/container_violations.go
new file mode 100644
index 0000000..4251484
--- /dev/null
+++ b/android/container_violations.go
@@ -0,0 +1,1123 @@
+// 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
+
+var ContainerDependencyViolationAllowlist = map[string][]string{
+ "android.car-module.impl": {
+ "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]
+ },
+
+ "AppInstalledOnMultipleUsers": {
+ "framework", // cts -> unstable
+ },
+
+ "art-aconfig-flags-java-lib": {
+ "framework-api-annotations-lib", // apex [com.android.art, com.android.art.debug, com.android.art.testing, test_imgdiag_com.android.art, test_jitzygote_com.android.art] -> system
+ },
+
+ "Bluetooth": {
+ "app-compat-annotations", // apex [com.android.btservices] -> system
+ "framework-bluetooth-pre-jarjar", // apex [com.android.btservices] -> system
+ },
+
+ "bluetooth-nano-protos": {
+ "libprotobuf-java-nano", // apex [com.android.btservices] -> apex [com.android.wifi, test_com.android.wifi]
+ },
+
+ "bluetooth.change-ids": {
+ "app-compat-annotations", // apex [com.android.btservices] -> 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]
+ },
+
+ "connectivity-net-module-utils-bpf": {
+ "net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
+ },
+
+ "conscrypt-aconfig-flags-lib": {
+ "aconfig-annotations-lib-sdk-none", // apex [com.android.conscrypt, test_com.android.conscrypt] -> system
+ },
+
+ "cronet_aml_base_base_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ "jsr305", // apex [com.android.tethering] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
+ },
+
+ "cronet_aml_build_android_build_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_base_feature_overrides_java_proto": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_cronet_api_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_cronet_impl_common_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_cronet_impl_native_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ "jsr305", // apex [com.android.tethering] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
+ },
+
+ "cronet_aml_components_cronet_android_cronet_jni_registration_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_cronet_shared_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_cronet_stats_log_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_cronet_urlconnection_impl_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_flags_java_proto": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_components_cronet_android_request_context_config_java_proto": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_net_android_net_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ "jsr305", // apex [com.android.tethering] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
+ },
+
+ "cronet_aml_net_android_net_thread_stats_uid_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_third_party_jni_zero_jni_zero_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "cronet_aml_url_url_java": {
+ "framework-connectivity-pre-jarjar-without-cronet", // apex [com.android.tethering] -> system
+ },
+
+ "CtsAdservicesHostTestApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAdServicesNotInAllowListEndToEndTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAdServicesPermissionsAppOptOutEndToEndTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAdServicesPermissionsNoPermEndToEndTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAdServicesPermissionsValidEndToEndTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAlarmManagerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAndroidAppTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppExitTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppFgsStartTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppFgsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppOpsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppSearchTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppStartTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAppTestStubsApp2": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsAudioHostTestApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsBackgroundActivityAppAllowCrossUidFlagDefault": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsBatterySavingTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsBluetoothTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsBootDisplayModeApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsBroadcastTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsBRSTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCompanionDeviceManagerCoreTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCompanionDeviceManagerMultiProcessTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCompanionDeviceManagerUiAutomationTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsContentSuggestionsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsContentTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCredentialManagerBackupRestoreApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCrossProfileEnabledApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCrossProfileEnabledNoPermsApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCrossProfileNotEnabledApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsCrossProfileUserEnabledApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDeviceAndProfileOwnerApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDeviceAndProfileOwnerApp23": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDeviceAndProfileOwnerApp25": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDeviceAndProfileOwnerApp30": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDeviceLockTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDeviceOwnerApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDevicePolicySimTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDevicePolicyTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDocumentContentTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDreamsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsDrmTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsEmptyTestApp_RejectedByVerifier": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsEphemeralTestsEphemeralApp1": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFgsBootCompletedTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFgsBootCompletedTestCasesApi35": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFgsStartTestHelperApi34": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFgsStartTestHelperCurrent": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFgsTimeoutTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFileDescriptorTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsFingerprintTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsHostsideCompatChangeTestsApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsHostsideNetworkPolicyTestsApp2": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsIdentityTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsIkeTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsInstalledLoadingProgressDeviceTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsInstantAppTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsIntentSenderApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsJobSchedulerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsKeystoreTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLegacyNotification27TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLibcoreTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLibcoreWycheproofConscryptTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsListeningPortsTest": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLocationCoarseTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLocationFineTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLocationNoneTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsLocationPrivilegedTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsManagedProfileApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaAudioTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaBetterTogetherTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaCodecTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaDecoderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaDrmFrameworkTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaEncoderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaExtractorTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaMiscTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaMuxerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaPerformanceClassTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaPlayerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaProjectionSDK33TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaProjectionSDK34TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaProjectionTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaProviderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaProviderTranscodeTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaRecorderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaRouterHostSideTestBluetoothPermissionsApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaRouterHostSideTestMediaRoutingControlApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaRouterHostSideTestModifyAudioRoutingApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMediaV2TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMimeMapTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsModifyQuietModeEnabledApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsMusicRecognitionTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNativeMediaAAudioTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNetTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNetTestCasesLegacyApi22": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNetTestCasesMaxTargetSdk30": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNetTestCasesMaxTargetSdk31": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNetTestCasesMaxTargetSdk33": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNetTestCasesUpdateStatsPermission": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsNfcTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsOnDeviceIntelligenceServiceTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsOnDevicePersonalizationTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPackageInstallerApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPackageManagerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPackageSchemeTestsWithoutVisibility": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPackageSchemeTestsWithVisibility": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPackageWatchdogTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPermissionsSyncTestApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsPreservedSettingsApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsProtoTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsProviderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsProxyMediaRouterTestHelperApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsRebootReadinessTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsResourcesLoaderTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsResourcesTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSandboxedAdIdManagerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSandboxedAppSetIdManagerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSandboxedFledgeManagerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSandboxedMeasurementManagerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSandboxedTopicsManagerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSdkExtensionsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSdkSandboxInprocessTests": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSecureElementTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSecurityTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxEphemeralTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxTargetSdk25TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxTargetSdk27TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxTargetSdk28TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxTargetSdk29TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxTargetSdk30TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSelinuxTargetSdkCurrentTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSettingsDeviceOwnerApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSharedUserMigrationTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsShortFgsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSimRestrictedApisTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSliceTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSpeechTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsStatsSecurityApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSuspendAppsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsSystemUiTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsTareTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsTelephonyTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsTetheringTest": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsThreadNetworkTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsTvTunerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsUsageStatsTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsUsbManagerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsUserRestrictionTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsUtilTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsUwbTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVcnTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVideoCodecTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVideoTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsViewReceiveContentTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVirtualDevicesAppLaunchTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVirtualDevicesAudioTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVirtualDevicesCameraTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVirtualDevicesSensorTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsVirtualDevicesTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWearableSensingServiceTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWebViewCompatChangeApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWidgetTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWidgetTestCases29": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWifiNonUpdatableTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWifiTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWindowManagerExternalApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsWindowManagerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "CtsZipValidateApp": {
+ "framework", // cts -> unstable
+ },
+
+ "CVE-2021-0965": {
+ "framework", // cts -> unstable
+ },
+
+ "device_config_reboot_flags_java_lib": {
+ "ext", // apex [com.android.configinfrastructure] -> system
+ "framework", // apex [com.android.configinfrastructure] -> system
+ },
+
+ "devicelockcontroller-lib": {
+ "modules-utils-expresslog", // apex [com.android.devicelock] -> apex [com.android.btservices, com.android.car.framework]
+ },
+
+ "FederatedCompute": {
+ "auto_value_annotations", // apex [com.android.ondevicepersonalization] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "framework-adservices.impl": {
+ "adservices_flags_lib", // apex [com.android.adservices, com.android.extservices] -> system
+ },
+
+ "framework-bluetooth.impl": {
+ "app-compat-annotations", // apex [com.android.btservices] -> system
+ },
+
+ "framework-connectivity-t.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
+ },
+
+ "framework-ondevicepersonalization.impl": {
+ "ondevicepersonalization_flags_lib", // apex [com.android.ondevicepersonalization] -> system
+ },
+
+ "framework-pdf-v.impl": {
+ "app-compat-annotations", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> system
+ "modules-utils-preconditions", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> 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]
+ },
+
+ "framework-pdf.impl": {
+ "modules-utils-preconditions", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> 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]
+ },
+
+ "framework-permission-s.impl": {
+ "app-compat-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "framework-wifi.impl": {
+ "aconfig_storage_reader_java", // apex [com.android.wifi, test_com.android.wifi] -> system
+ "app-compat-annotations", // apex [com.android.wifi, test_com.android.wifi] -> system
+ },
+
+ "grpc-java-core-internal": {
+ "gson", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> apex [com.android.virt]
+ "perfmark-api-lib", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> system
+ },
+
+ "httpclient_impl": {
+ "httpclient_api", // apex [com.android.tethering] -> system
+ },
+
+ "IncrementalTestAppValidator": {
+ "framework", // cts -> unstable
+ },
+
+ "libcore-aconfig-flags-lib": {
+ "framework-api-annotations-lib", // apex [com.android.art, com.android.art.debug, com.android.art.testing, test_imgdiag_com.android.art, test_jitzygote_com.android.art] -> system
+ },
+
+ "loadlibrarytest_product_app": {
+ "libnativeloader_vendor_shared_lib", // product -> vendor
+ },
+
+ "loadlibrarytest_testlib": {
+ "libnativeloader_vendor_shared_lib", // system -> vendor
+ },
+
+ "MctsMediaBetterTogetherTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaCodecTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaDecoderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaDrmFrameworkTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaEncoderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaExtractorTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaMiscTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaMuxerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaPlayerTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaRecorderTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaTranscodingTestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MctsMediaV2TestCases": {
+ "framework", // cts -> unstable
+ },
+
+ "MediaProvider": {
+ "app-compat-annotations", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> system
+ },
+
+ "mediaprovider_flags_java_lib": {
+ "ext", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> system
+ "framework", // apex [com.android.mediaprovider, test_com.android.mediaprovider] -> system
+ },
+
+ "MockSatelliteGatewayServiceApp": {
+ "framework", // cts -> unstable
+ },
+
+ "MockSatelliteServiceApp": {
+ "framework", // cts -> unstable
+ },
+
+ "net-utils-device-common-netlink": {
+ "net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
+ },
+
+ "net-utils-device-common-struct": {
+ "net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
+ },
+
+ "NfcNciApex": {
+ "android.permission.flags-aconfig-java", // apex [com.android.nfcservices] -> apex [com.android.permission, test_com.android.permission]
+ },
+
+ "okhttp-norepackage": {
+ "okhttp-android-util-log", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> system
+ },
+
+ "ondevicepersonalization-plugin-lib": {
+ "auto_value_annotations", // apex [com.android.ondevicepersonalization] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "opencensus-java-api": {
+ "auto_value_annotations", // apex [com.android.devicelock] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "PermissionController-lib": {
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "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
+ },
+
+ "safety-center-config": {
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "safety-center-internal-data": {
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "safety-center-pending-intents": {
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "safety-center-persistence": {
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "safety-center-resources-lib": {
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "SdkSandboxManagerDisabledTests": {
+ "framework", // cts -> unstable
+ },
+
+ "SdkSandboxManagerTests": {
+ "framework", // cts -> unstable
+ },
+
+ "service-art.impl": {
+ "auto_value_annotations", // apex [com.android.art, com.android.art.debug, com.android.art.testing, test_imgdiag_com.android.art, test_jitzygote_com.android.art] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "service-bluetooth-pre-jarjar": {
+ "framework-bluetooth-pre-jarjar", // apex [com.android.btservices] -> system
+ "service-bluetooth.change-ids", // apex [com.android.btservices] -> system
+ },
+
+ "service-connectivity": {
+ "libprotobuf-java-nano", // apex [com.android.tethering] -> apex [com.android.wifi, test_com.android.wifi]
+ },
+
+ "service-connectivity-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
+ "service-connectivity-protos": {
+ "libprotobuf-java-nano", // apex [com.android.tethering] -> apex [com.android.wifi, test_com.android.wifi]
+ },
+
+ "service-connectivity-tiramisu-pre-jarjar": {
+ "framework-connectivity-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]
+ },
+
+ "service-entitlement-api": {
+ "auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "service-entitlement-data": {
+ "auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "service-entitlement-impl": {
+ "auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "service-healthfitness.impl": {
+ "modules-utils-preconditions", // apex [com.android.healthfitness] -> 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]
+ },
+
+ "service-networksecurity-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
+ "service-permission.impl": {
+ "jsr305", // apex [com.android.permission, test_com.android.permission] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
+ "safety-center-annotations", // apex [com.android.permission, test_com.android.permission] -> system
+ },
+
+ "service-remoteauth-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
+ "service-thread-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
+ "service-uwb-pre-jarjar": {
+ "framework-uwb-pre-jarjar", // apex [com.android.uwb] -> system
+ },
+
+ "service-wifi": {
+ "auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ },
+
+ "TelephonyDeviceTest": {
+ "framework", // cts -> unstable
+ },
+
+ "tensorflowlite_java": {
+ "android-support-annotations", // apex [com.android.adservices, com.android.extservices, com.android.ondevicepersonalization] -> system
+ },
+
+ "TestExternalImsServiceApp": {
+ "framework", // cts -> unstable
+ },
+
+ "TestSmsRetrieverApp": {
+ "framework", // cts -> unstable
+ },
+
+ "TetheringApiCurrentLib": {
+ "connectivity-internal-api-util", // apex [com.android.tethering] -> system
+ },
+
+ "TetheringNext": {
+ "connectivity-internal-api-util", // apex [com.android.tethering] -> system
+ },
+
+ "tetheringstatsprotos": {
+ "ext", // apex [com.android.tethering] -> system
+ "framework", // apex [com.android.tethering] -> system
+ },
+
+ "uwb_aconfig_flags_lib": {
+ "ext", // apex [com.android.uwb] -> system
+ "framework", // apex [com.android.uwb] -> system
+ },
+
+ "uwb_androidx_backend": {
+ "android-support-annotations", // apex [com.android.tethering] -> system
+ },
+
+ "wifi-service-pre-jarjar": {
+ "app-compat-annotations", // apex [com.android.wifi, test_com.android.wifi] -> system
+ "auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
+ "framework-wifi-pre-jarjar", // apex [com.android.wifi, test_com.android.wifi] -> system
+ "jsr305", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.devicelock, com.android.extservices, com.android.healthfitness, com.android.media, com.android.mediaprovider, test_com.android.media, test_com.android.mediaprovider]
+ },
+}
diff --git a/android/deapexer.go b/android/deapexer.go
index 61ae64e..4049d2b 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -15,7 +15,6 @@
package android
import (
- "fmt"
"strings"
"github.com/google/blueprint"
@@ -109,10 +108,6 @@
return i.exportedModuleNames
}
-// Provider that can be used from within the `GenerateAndroidBuildActions` of a module that depends
-// on a `deapexer` module to retrieve its `DeapexerInfo`.
-var DeapexerProvider = blueprint.NewProvider[DeapexerInfo]()
-
// NewDeapexerInfo creates and initializes a DeapexerInfo that is suitable
// for use with a prebuilt_apex module.
//
@@ -169,41 +164,6 @@
RequiresFilesFromPrebuiltApex()
}
-// FindDeapexerProviderForModule searches through the direct dependencies of the current context
-// module for a DeapexerTag dependency and returns its DeapexerInfo. If a single nonambiguous
-// deapexer module isn't found then it returns it an error
-// clients should check the value of error and call ctx.ModuleErrof if a non nil error is received
-func FindDeapexerProviderForModule(ctx ModuleContext) (*DeapexerInfo, error) {
- var di *DeapexerInfo
- var err error
- ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
- if err != nil {
- // An err has been found. Do not visit further.
- return
- }
- c, _ := OtherModuleProvider(ctx, m, DeapexerProvider)
- p := &c
- if di != nil {
- // If two DeapexerInfo providers have been found then check if they are
- // equivalent. If they are then use the selected one, otherwise fail.
- if selected := equivalentDeapexerInfoProviders(di, p); selected != nil {
- di = selected
- return
- }
- err = fmt.Errorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", di.ApexModuleName(), p.ApexModuleName())
- }
- di = p
- })
- if err != nil {
- return nil, err
- }
- if di != nil {
- return di, nil
- }
- ai, _ := ModuleProvider(ctx, ApexInfoProvider)
- return nil, fmt.Errorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
-}
-
// removeCompressedApexSuffix removes the _compressed suffix from the name if present.
func removeCompressedApexSuffix(name string) string {
return strings.TrimSuffix(name, "_compressed")
diff --git a/android/defaults.go b/android/defaults.go
index ba26e00..3d06c69 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -28,7 +28,7 @@
var DefaultsDepTag defaultsDependencyTag
type defaultsProperties struct {
- Defaults proptools.Configurable[[]string]
+ Defaults []string
}
type DefaultableModuleBase struct {
@@ -69,7 +69,7 @@
// Apply defaults from the supplied Defaults to the property structures supplied to
// setProperties(...).
- applyDefaults(TopDownMutatorContext, []Defaults)
+ applyDefaults(BottomUpMutatorContext, []Defaults)
// Set the hook to be called after any defaults have been applied.
//
@@ -101,6 +101,7 @@
// A restricted subset of context methods, similar to LoadHookContext.
type DefaultableHookContext interface {
EarlyModuleContext
+ OtherModuleProviderContext
CreateModule(ModuleFactory, ...interface{}) Module
AddMissingDependencies(missingDeps []string)
@@ -209,7 +210,7 @@
var _ Defaults = (*DefaultsModuleBase)(nil)
-func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
+func (defaultable *DefaultableModuleBase) applyDefaults(ctx BottomUpMutatorContext,
defaultsList []Defaults) {
for _, defaults := range defaultsList {
@@ -226,7 +227,7 @@
// Product variable properties need special handling, the type of the filtered product variable
// property struct may not be identical between the defaults module and the defaultable module.
// Use PrependMatchingProperties to apply whichever properties match.
-func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
+func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx BottomUpMutatorContext,
defaults Defaults, defaultableProp interface{}) {
if defaultableProp == nil {
return
@@ -254,7 +255,7 @@
}
}
-func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
+func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx BottomUpMutatorContext,
defaults Defaults, defaultableProp interface{}) {
for _, def := range defaults.properties() {
@@ -273,18 +274,22 @@
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
- ctx.TopDown("defaults", defaultsMutator).Parallel()
+ ctx.BottomUp("defaults", defaultsMutator).Parallel()
}
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
if defaultable, ok := ctx.Module().(Defaultable); ok {
- ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults.GetOrDefault(ctx.Module().ConfigurableEvaluator(ctx), nil)...)
+ ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
}
}
-func defaultsMutator(ctx TopDownMutatorContext) {
+func defaultsMutator(ctx BottomUpMutatorContext) {
if defaultable, ok := ctx.Module().(Defaultable); ok {
- defaults := defaultable.defaults().Defaults.GetOrDefault(ctx.Module().ConfigurableEvaluator(ctx), nil)
+ if _, isDefaultsModule := ctx.Module().(Defaults); isDefaultsModule {
+ // Don't squash transitive defaults into defaults modules
+ return
+ }
+ defaults := defaultable.defaults().Defaults
if len(defaults) > 0 {
var defaultsList []Defaults
seen := make(map[Defaults]bool)
@@ -295,7 +300,7 @@
if !seen[defaults] {
seen[defaults] = true
defaultsList = append(defaultsList, defaults)
- return len(defaults.defaults().Defaults.GetOrDefault(ctx.Module().ConfigurableEvaluator(ctx), nil)) > 0
+ return len(defaults.defaults().Defaults) > 0
}
} else {
ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
diff --git a/android/defs.go b/android/defs.go
index 78cdea2..9f3fb1e 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -16,7 +16,6 @@
import (
"github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
)
var (
@@ -120,8 +119,3 @@
return ctx.Config().RBEWrapper()
})
}
-
-// GlobToListFileRule creates a rule that writes a list of files matching a pattern to a file.
-func GlobToListFileRule(ctx ModuleContext, pattern string, excludes []string, file WritablePath) {
- bootstrap.GlobFile(ctx.blueprintModuleContext(), pattern, excludes, file.String())
-}
diff --git a/android/depset_generic.go b/android/depset_generic.go
index 45c1937..690987a 100644
--- a/android/depset_generic.go
+++ b/android/depset_generic.go
@@ -15,6 +15,9 @@
package android
import (
+ "bytes"
+ "encoding/gob"
+ "errors"
"fmt"
)
@@ -65,6 +68,30 @@
transitive []*DepSet[T]
}
+func (d *DepSet[T]) GobEncode() ([]byte, error) {
+ w := new(bytes.Buffer)
+ encoder := gob.NewEncoder(w)
+ err := errors.Join(encoder.Encode(d.preorder), encoder.Encode(d.reverse),
+ encoder.Encode(d.order), encoder.Encode(d.direct), encoder.Encode(d.transitive))
+ if err != nil {
+ return nil, err
+ }
+
+ return w.Bytes(), nil
+}
+
+func (d *DepSet[T]) GobDecode(data []byte) error {
+ r := bytes.NewBuffer(data)
+ decoder := gob.NewDecoder(r)
+ err := errors.Join(decoder.Decode(&d.preorder), decoder.Decode(&d.reverse),
+ decoder.Decode(&d.order), decoder.Decode(&d.direct), decoder.Decode(&d.transitive))
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
// NewDepSet returns an immutable DepSet with the given order, direct and transitive contents.
func NewDepSet[T depSettableType](order DepSetOrder, direct []T, transitive []*DepSet[T]) *DepSet[T] {
var directCopy []T
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 23f4c90..11de771 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -93,6 +93,10 @@
// Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
// default SimpleNameInterface if Context.SetNameInterface was not called.
Namespace() *Namespace
+
+ // HasMutatorFinished returns true if the given mutator has finished running.
+ // It will panic if given an invalid mutator name.
+ HasMutatorFinished(mutatorName string) bool
}
// Deprecated: use EarlyModuleContext instead
@@ -175,3 +179,7 @@
func (e *earlyModuleContext) OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) {
e.EarlyModuleContext.OtherModulePropertyErrorf(module, property, fmt, args...)
}
+
+func (e *earlyModuleContext) HasMutatorFinished(mutatorName string) bool {
+ return e.EarlyModuleContext.HasMutatorFinished(mutatorName)
+}
diff --git a/android/hooks.go b/android/hooks.go
index 2ad3b5f..bd2fa5e 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -95,10 +95,17 @@
type createModuleContext interface {
Module() Module
+ HasMutatorFinished(mutatorName string) bool
createModule(blueprint.ModuleFactory, string, ...interface{}) blueprint.Module
}
func createModule(ctx createModuleContext, factory ModuleFactory, ext string, props ...interface{}) Module {
+ if ctx.HasMutatorFinished("defaults") {
+ // Creating modules late is oftentimes problematic, because they don't have earlier
+ // mutators run on them. Prevent making modules after the defaults mutator has run.
+ panic("Cannot create a module after the defaults mutator has finished")
+ }
+
inherited := []interface{}{&ctx.Module().base().commonProperties}
var typeName string
diff --git a/android/image.go b/android/image.go
index 0f03107..6e5a551 100644
--- a/android/image.go
+++ b/android/image.go
@@ -14,7 +14,7 @@
package android
-// ImageInterface is implemented by modules that need to be split by the imageMutator.
+// ImageInterface is implemented by modules that need to be split by the imageTransitionMutator.
type ImageInterface interface {
// ImageMutatorBegin is called before any other method in the ImageInterface.
ImageMutatorBegin(ctx BaseModuleContext)
@@ -81,18 +81,16 @@
DebugRamdiskVariation string = "debug_ramdisk"
)
-// imageMutator creates variants for modules that implement the ImageInterface that
+// imageTransitionMutator creates variants for modules that implement the ImageInterface that
// allow them to build differently for each partition (recovery, core, vendor, etc.).
-func imageMutator(ctx BottomUpMutatorContext) {
- if ctx.Os() != Android {
- return
- }
+type imageTransitionMutator struct{}
- if m, ok := ctx.Module().(ImageInterface); ok {
+func (imageTransitionMutator) Split(ctx BaseModuleContext) []string {
+ var variations []string
+
+ if m, ok := ctx.Module().(ImageInterface); ctx.Os() == Android && ok {
m.ImageMutatorBegin(ctx)
- var variations []string
-
if m.CoreVariantNeeded(ctx) {
variations = append(variations, CoreVariation)
}
@@ -117,15 +115,29 @@
extraVariations := m.ExtraImageVariations(ctx)
variations = append(variations, extraVariations...)
+ }
- if len(variations) == 0 {
- return
- }
+ if len(variations) == 0 {
+ variations = append(variations, "")
+ }
- mod := ctx.CreateVariations(variations...)
- for i, v := range variations {
- mod[i].base().setImageVariation(v)
- mod[i].(ImageInterface).SetImageVariation(ctx, v)
- }
+ return variations
+}
+
+func (imageTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (imageTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ if _, ok := ctx.Module().(ImageInterface); ctx.Os() != Android || !ok {
+ return CoreVariation
+ }
+ return incomingVariation
+}
+
+func (imageTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ ctx.Module().base().setImageVariation(variation)
+ if m, ok := ctx.Module().(ImageInterface); ok {
+ m.SetImageVariation(ctx, variation)
}
}
diff --git a/android/init.go b/android/init.go
new file mode 100644
index 0000000..b462292
--- /dev/null
+++ b/android/init.go
@@ -0,0 +1,23 @@
+// 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 "encoding/gob"
+
+func init() {
+ gob.Register(ModuleOutPath{})
+ gob.Register(PhonyPath{})
+ gob.Register(unstableInfo{})
+}
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 8056189..f925638 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -33,7 +33,7 @@
}, "args")
)
-func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
+func buildLicenseMetadata(ctx *moduleContext, licenseMetadataFile WritablePath) {
base := ctx.Module().base()
if !base.Enabled(ctx) {
@@ -52,8 +52,8 @@
// Only pass the last installed file to isContainerFromFileExtensions so a *.zip file in test data
// doesn't mark the whole module as a container.
var installFiles InstallPaths
- if len(base.installFiles) > 0 {
- installFiles = InstallPaths{base.installFiles[len(base.installFiles)-1]}
+ if len(ctx.installFiles) > 0 {
+ installFiles = InstallPaths{ctx.installFiles[len(ctx.installFiles)-1]}
}
isContainer := isContainerFromFileExtensions(installFiles, outputFiles)
@@ -63,11 +63,7 @@
var allDepOutputFiles Paths
var allDepMetadataDepSets []*DepSet[Path]
- ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
- dep, _ := bpdep.(Module)
- if dep == nil {
- return
- }
+ ctx.VisitDirectDeps(func(dep Module) {
if !dep.Enabled(ctx) {
return
}
@@ -92,7 +88,7 @@
allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
- if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
+ if depInstallFiles := OtherModuleProviderOrDefault(ctx, dep, InstallFilesProvider).InstallFiles; len(depInstallFiles) > 0 {
allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
} else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
depOutputFiles = PathsIfNonNil(depOutputFiles...)
@@ -152,7 +148,7 @@
// Install map
args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.licenseInstallMap), "-m "))
// Built files
if len(outputFiles) > 0 {
@@ -162,7 +158,7 @@
// Installed files
args = append(args,
- JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(ctx.installFiles.Strings()), "-i "))
if isContainer {
args = append(args, "--is_container")
diff --git a/android/logtags.go b/android/logtags.go
index d11cccf..7929057 100644
--- a/android/logtags.go
+++ b/android/logtags.go
@@ -42,7 +42,7 @@
if !module.ExportedToMake() {
return
}
- if logtagsInfo, ok := SingletonModuleProvider(ctx, module, LogtagsProviderKey); ok {
+ if logtagsInfo, ok := OtherModuleProvider(ctx, module, LogtagsProviderKey); ok {
allLogtags = append(allLogtags, logtagsInfo.Logtags...)
}
})
diff --git a/android/makevars.go b/android/makevars.go
index f92f458..8305d8e 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -94,7 +94,7 @@
ModuleDir(module blueprint.Module) string
ModuleSubDir(module blueprint.Module) string
ModuleType(module blueprint.Module) string
- moduleProvider(module blueprint.Module, key blueprint.AnyProviderKey) (any, bool)
+ otherModuleProvider(module blueprint.Module, key blueprint.AnyProviderKey) (any, bool)
BlueprintFile(module blueprint.Module) string
ModuleErrorf(module blueprint.Module, format string, args ...interface{})
@@ -279,10 +279,11 @@
}
if m.ExportedToMake() {
- katiInstalls = append(katiInstalls, m.base().katiInstalls...)
- katiInitRcInstalls = append(katiInitRcInstalls, m.base().katiInitRcInstalls...)
- katiVintfManifestInstalls = append(katiVintfManifestInstalls, m.base().katiVintfInstalls...)
- katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...)
+ 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...)
}
})
diff --git a/android/module.go b/android/module.go
index 39c257c..a1a9a4a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -15,6 +15,9 @@
package android
import (
+ "bytes"
+ "encoding/gob"
+ "errors"
"fmt"
"net/url"
"path/filepath"
@@ -55,7 +58,7 @@
base() *ModuleBase
Disable()
- Enabled(ctx ConfigAndErrorContext) bool
+ Enabled(ctx ConfigurableEvaluatorContext) bool
Target() Target
MultiTargets() []Target
@@ -78,6 +81,7 @@
InstallInOdm() bool
InstallInProduct() bool
InstallInVendor() bool
+ InstallInSystemExt() bool
InstallForceOS() (*OsType, *ArchType)
PartitionTag(DeviceConfig) string
HideFromMake()
@@ -87,8 +91,6 @@
ReplacedByPrebuilt()
IsReplacedByPrebuilt() bool
ExportedToMake() bool
- InitRc() Paths
- VintfFragments() Paths
EffectiveLicenseKinds() []string
EffectiveLicenseFiles() Paths
@@ -108,18 +110,12 @@
// Get information about the properties that can contain visibility rules.
visibilityProperties() []visibilityProperty
- RequiredModuleNames(ctx ConfigAndErrorContext) []string
+ RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
+ VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string
- FilesToInstall() InstallPaths
- PackagingSpecs() []PackagingSpec
-
- // TransitivePackagingSpecs returns the PackagingSpecs for this module and any transitive
- // dependencies with dependency tags for which IsInstallDepNeeded() returns true.
- TransitivePackagingSpecs() []PackagingSpec
-
- ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator
+ ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator
}
// Qualified id for a module
@@ -386,7 +382,7 @@
Native_bridge_supported *bool `android:"arch_variant"`
// init.rc files to be installed if this module is installed
- Init_rc []string `android:"arch_variant,path"`
+ Init_rc proptools.Configurable[[]string] `android:"arch_variant,path"`
// VINTF manifest fragments to be installed if this module is installed
Vintf_fragments proptools.Configurable[[]string] `android:"path"`
@@ -448,12 +444,6 @@
// Set at module initialization time by calling InitCommonOSAndroidMultiTargetsArchModule
CreateCommonOSVariant bool `blueprint:"mutated"`
- // If set to true then this variant is the CommonOS variant that has dependencies on its
- // OsType specific variants.
- //
- // Set by osMutator.
- CommonOSVariant bool `blueprint:"mutated"`
-
// 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.
@@ -497,6 +487,13 @@
// The team (defined by the owner/vendor) who owns the property.
Team *string `android:"path"`
+
+ // vintf_fragment Modules required from this module.
+ Vintf_fragment_modules proptools.Configurable[[]string] `android:"path"`
+
+ // List of module names that are prevented from being installed when this module gets
+ // installed.
+ Overrides []string
}
type distProperties struct {
@@ -831,30 +828,7 @@
// The primary licenses property, may be nil, records license metadata for the module.
primaryLicensesProperty applicableLicensesProperty
- noAddressSanitizer bool
- installFiles InstallPaths
- installFilesDepSet *DepSet[InstallPath]
- checkbuildFiles Paths
- packagingSpecs []PackagingSpec
- packagingSpecsDepSet *DepSet[PackagingSpec]
- // katiInstalls tracks the install rules that were created by Soong but are being exported
- // to Make to convert to ninja rules so that Make can add additional dependencies.
- katiInstalls katiInstalls
- // katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
- // allowed to have duplicates across modules and variants.
- katiInitRcInstalls katiInstalls
- katiVintfInstalls katiInstalls
- katiSymlinks katiInstalls
- testData []DataPath
-
- // The files to copy to the dist as explicitly specified in the .bp file.
- distFiles TaggedDistFiles
-
- // Used by buildTargetSingleton to create checkbuild and per-directory build targets
- // Only set on the final variant of each module
- installTarget WritablePath
- checkbuildTarget WritablePath
- blueprintDir string
+ noAddressSanitizer bool
hooks hooks
@@ -864,34 +838,6 @@
buildParams []BuildParams
ruleParams map[blueprint.Rule]blueprint.RuleParams
variables map[string]string
-
- initRcPaths Paths
- vintfFragmentsPaths Paths
-
- installedInitRcPaths InstallPaths
- installedVintfFragmentsPaths InstallPaths
-
- // Merged Aconfig files for all transitive deps.
- aconfigFilePaths Paths
-
- // set of dependency module:location mappings used to populate the license metadata for
- // apex containers.
- licenseInstallMap []string
-
- // The path to the generated license metadata file for the module.
- licenseMetadataFile WritablePath
-
- // 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
-
- // outputFiles stores the output of a module by tag and is used to set
- // the OutputFilesProvider in GenerateBuildActions
- outputFiles OutputFilesInfo
-
- // complianceMetadataInfo is for different module types to dump metadata.
- // See android.ModuleContext interface.
- complianceMetadataInfo *ComplianceMetadataInfo
}
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
@@ -1028,6 +974,7 @@
fullManifest := pv.DeviceArch != nil && pv.DeviceName != nil
if fullManifest {
addRequiredDeps(ctx)
+ addVintfFragmentDeps(ctx)
}
}
@@ -1059,6 +1006,14 @@
return
}
+ // Do not create a dependency from common variant to arch variant for `common_first` modules
+ if multilib, _ := decodeMultilib(ctx, ctx.Module().base()); multilib == string(MultilibCommonFirst) {
+ commonVariant := ctx.Arch().ArchType.Multilib == ""
+ if bothInAndroid && commonVariant && InList(target.Arch.ArchType.Multilib, []string{"lib32", "lib64"}) {
+ return
+ }
+ }
+
variation := target.Variations()
if ctx.OtherModuleFarDependencyVariantExists(variation, depName) {
ctx.AddFarVariationDependencies(variation, RequiredDepTag, depName)
@@ -1105,6 +1060,37 @@
}
}
+var vintfDepTag = struct {
+ blueprint.BaseDependencyTag
+ InstallAlwaysNeededDependencyTag
+}{}
+
+func addVintfFragmentDeps(ctx BottomUpMutatorContext) {
+ // Vintf manifests in the recovery partition will be ignored.
+ if !ctx.Device() || ctx.Module().InstallInRecovery() {
+ return
+ }
+
+ deviceConfig := ctx.DeviceConfig()
+
+ mod := ctx.Module()
+ vintfModules := ctx.AddDependency(mod, vintfDepTag, mod.VintfFragmentModuleNames(ctx)...)
+
+ modPartition := mod.PartitionTag(deviceConfig)
+ for _, vintf := range vintfModules {
+ 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.",
+ mod.Name(), modPartition,
+ vintfModule.Name(), vintfPartition)
+ }
+ } else {
+ ctx.ModuleErrorf("Only vintf_fragment type module should be listed in vintf_fragment_modules : %q", vintf.Name())
+ }
+ }
+}
+
// AddProperties "registers" the provided props
// each value in props MUST be a pointer to a struct
func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -1259,7 +1245,7 @@
// True if the current variant is a CommonOS variant, false otherwise.
func (m *ModuleBase) IsCommonOSVariant() bool {
- return m.commonProperties.CommonOSVariant
+ return m.commonProperties.CompileOS == CommonOS
}
// supportsTarget returns true if the given Target is supported by the current module.
@@ -1377,13 +1363,21 @@
return partition
}
-func (m *ModuleBase) Enabled(ctx ConfigAndErrorContext) bool {
+func (m *ModuleBase) Enabled(ctx ConfigurableEvaluatorContext) bool {
if m.commonProperties.ForcedDisabled {
return false
}
return m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
}
+// Returns a copy of the enabled property, useful for passing it on to sub-modules
+func (m *ModuleBase) EnabledProperty() proptools.Configurable[bool] {
+ if m.commonProperties.ForcedDisabled {
+ return proptools.NewSimpleConfigurable(false)
+ }
+ return m.commonProperties.Enabled.Clone()
+}
+
func (m *ModuleBase) Disable() {
m.commonProperties.ForcedDisabled = true
}
@@ -1453,12 +1447,13 @@
if isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(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() {
- installDeps = append(installDeps, dep.base().installFilesDepSet)
+ installDeps = append(installDeps, info.TransitiveInstallFiles)
}
// Add packaging deps even when the dependency is not installed so that uninstallable
// modules can still be packaged. Often the package will be installed instead.
- packagingSpecs = append(packagingSpecs, dep.base().packagingSpecsDepSet)
+ packagingSpecs = append(packagingSpecs, info.TransitivePackagingSpecs)
}
})
@@ -1476,18 +1471,6 @@
return IsInstallDepNeededTag(tag)
}
-func (m *ModuleBase) FilesToInstall() InstallPaths {
- return m.installFiles
-}
-
-func (m *ModuleBase) PackagingSpecs() []PackagingSpec {
- return m.packagingSpecs
-}
-
-func (m *ModuleBase) TransitivePackagingSpecs() []PackagingSpec {
- return m.packagingSpecsDepSet.ToList()
-}
-
func (m *ModuleBase) NoAddressSanitizer() bool {
return m.noAddressSanitizer
}
@@ -1532,6 +1515,10 @@
return Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Soc_specific) || Bool(m.commonProperties.Proprietary)
}
+func (m *ModuleBase) InstallInSystemExt() bool {
+ return Bool(m.commonProperties.System_ext_specific)
+}
+
func (m *ModuleBase) InstallInRoot() bool {
return false
}
@@ -1585,7 +1572,7 @@
return m.base().commonProperties.ImageVariation == RecoveryVariation
}
-func (m *ModuleBase) RequiredModuleNames(ctx ConfigAndErrorContext) []string {
+func (m *ModuleBase) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
return m.base().commonProperties.Required.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
@@ -1597,58 +1584,71 @@
return m.base().commonProperties.Target_required
}
-func (m *ModuleBase) InitRc() Paths {
- return append(Paths{}, m.initRcPaths...)
+func (m *ModuleBase) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string {
+ return m.base().commonProperties.Vintf_fragment_modules.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
}
-func (m *ModuleBase) VintfFragments() Paths {
- return append(Paths{}, m.vintfFragmentsPaths...)
-}
-
-func (m *ModuleBase) CompileMultilib() *string {
- return m.base().commonProperties.Compile_multilib
-}
-
-// SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
-// apex container for use when generation the license metadata file.
-func (m *ModuleBase) SetLicenseInstallMap(installMap []string) {
- m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
-}
-
-func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
- var allInstalledFiles InstallPaths
- var allCheckbuildFiles Paths
- ctx.VisitAllModuleVariants(func(module Module) {
- a := module.base()
- allInstalledFiles = append(allInstalledFiles, a.installFiles...)
- // 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, a) {
- allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
- }
- })
-
- var deps Paths
-
+func (m *ModuleBase) generateVariantTarget(ctx *moduleContext) {
namespacePrefix := ctx.Namespace().id
if namespacePrefix != "" {
namespacePrefix = namespacePrefix + "-"
}
+ if !ctx.uncheckedModule {
+ name := namespacePrefix + ctx.ModuleName() + "-" + ctx.ModuleSubDir() + "-checkbuild"
+ ctx.Phony(name, ctx.checkbuildFiles...)
+ ctx.checkbuildTarget = PathForPhony(ctx, name)
+ }
+
+}
+
+func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
+ var allInstalledFiles InstallPaths
+ var allCheckbuildTargets Paths
+ ctx.VisitAllModuleVariants(func(module Module) {
+ a := module.base()
+ var checkbuildTarget Path
+ var uncheckedModule bool
+ if a == m {
+ allInstalledFiles = append(allInstalledFiles, ctx.installFiles...)
+ checkbuildTarget = ctx.checkbuildTarget
+ uncheckedModule = ctx.uncheckedModule
+ } else {
+ info := OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider)
+ allInstalledFiles = append(allInstalledFiles, info.InstallFiles...)
+ checkbuildTarget = info.CheckbuildTarget
+ uncheckedModule = info.UncheckedModule
+ }
+ // 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, a)) && !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
+
if len(allInstalledFiles) > 0 {
name := namespacePrefix + ctx.ModuleName() + "-install"
ctx.Phony(name, allInstalledFiles.Paths()...)
- m.installTarget = PathForPhony(ctx, name)
- deps = append(deps, m.installTarget)
+ info.InstallTarget = PathForPhony(ctx, name)
+ deps = append(deps, info.InstallTarget)
}
- if len(allCheckbuildFiles) > 0 {
+ if len(allCheckbuildTargets) > 0 {
name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
- ctx.Phony(name, allCheckbuildFiles...)
- m.checkbuildTarget = PathForPhony(ctx, name)
- deps = append(deps, m.checkbuildTarget)
+ ctx.Phony(name, allCheckbuildTargets...)
+ deps = append(deps, PathForPhony(ctx, name))
}
if len(deps) > 0 {
@@ -1659,7 +1659,8 @@
ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
- m.blueprintDir = ctx.ModuleDir()
+ info.BlueprintDir = ctx.ModuleDir()
+ SetProvider(ctx, FinalModuleBuildTargetsProvider, info)
}
}
@@ -1763,23 +1764,69 @@
}
+type InstallFilesInfo struct {
+ InstallFiles InstallPaths
+ CheckbuildFiles Paths
+ CheckbuildTarget Path
+ UncheckedModule bool
+ PackagingSpecs []PackagingSpec
+ // katiInstalls tracks the install rules that were created by Soong but are being exported
+ // to Make to convert to ninja rules so that Make can add additional dependencies.
+ KatiInstalls katiInstalls
+ KatiSymlinks katiInstalls
+ TestData []DataPath
+ TransitivePackagingSpecs *DepSet[PackagingSpec]
+ LicenseMetadataFile WritablePath
+
+ // The following fields are private before, make it private again once we have
+ // better solution.
+ TransitiveInstallFiles *DepSet[InstallPath]
+ // katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
+ // allowed to have duplicates across modules and variants.
+ KatiInitRcInstalls katiInstalls
+ KatiVintfInstalls katiInstalls
+ InitRcPaths Paths
+ VintfFragmentsPaths Paths
+ InstalledInitRcPaths InstallPaths
+ InstalledVintfFragmentsPaths InstallPaths
+
+ // The files to copy to the dist as explicitly specified in the .bp file.
+ DistFiles TaggedDistFiles
+}
+
+var InstallFilesProvider = blueprint.NewProvider[InstallFilesInfo]()
+
+type FinalModuleBuildTargetsInfo struct {
+ // Used by buildTargetSingleton to create checkbuild and per-directory build targets
+ // Only set on the final variant of each module
+ InstallTarget WritablePath
+ CheckbuildTarget WritablePath
+ BlueprintDir string
+}
+
+var FinalModuleBuildTargetsProvider = blueprint.NewProvider[FinalModuleBuildTargetsInfo]()
+
func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
ctx := &moduleContext{
module: m.module,
bp: blueprintCtx,
baseModuleContext: m.baseModuleContextFactory(blueprintCtx),
variables: make(map[string]string),
+ phonies: make(map[string]Paths),
}
setContainerInfo(ctx)
+ if ctx.Config().Getenv("DISABLE_CONTAINER_CHECK") != "true" {
+ checkContainerViolations(ctx)
+ }
- m.licenseMetadataFile = PathForModuleOut(ctx, "meta_lic")
+ ctx.licenseMetadataFile = PathForModuleOut(ctx, "meta_lic")
dependencyInstallFiles, dependencyPackagingSpecs := m.computeInstallDeps(ctx)
- // set m.installFilesDepSet to only the transitive dependencies to be used as the dependencies
+ // set the TransitiveInstallFiles to only the transitive dependencies to be used as the dependencies
// of installed files of this module. It will be replaced by a depset including the installed
// files of this module at the end for use by modules that depend on this one.
- m.installFilesDepSet = NewDepSet[InstallPath](TOPOLOGICAL, nil, dependencyInstallFiles)
+ ctx.TransitiveInstallFiles = NewDepSet[InstallPath](TOPOLOGICAL, nil, dependencyInstallFiles)
// Temporarily continue to call blueprintCtx.GetMissingDependencies() to maintain the previous behavior of never
// reporting missing dependency errors in Blueprint when AllowMissingDependencies == true.
@@ -1823,12 +1870,12 @@
checkDistProperties(ctx, fmt.Sprintf("dists[%d]", i), &m.distProperties.Dists[i])
}
+ var installFiles InstallFilesInfo
+
if m.Enabled(ctx) {
// ensure all direct android.Module deps are enabled
- ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) {
- if m, ok := bm.(Module); ok {
- ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps, false)
- }
+ ctx.VisitDirectDeps(func(m Module) {
+ ctx.validateAndroidModule(m, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps)
})
if m.Device() {
@@ -1840,30 +1887,36 @@
// so only a single rule is created for each init.rc or vintf fragment file.
if !m.InVendorRamdisk() {
- m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ ctx.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc.GetOrDefault(ctx, nil))
rcDir := PathForModuleInstall(ctx, "etc", "init")
- for _, src := range m.initRcPaths {
+ for _, src := range ctx.initRcPaths {
installedInitRc := rcDir.Join(ctx, src.Base())
- m.katiInitRcInstalls = append(m.katiInitRcInstalls, katiInstall{
+ ctx.katiInitRcInstalls = append(ctx.katiInitRcInstalls, katiInstall{
from: src,
to: installedInitRc,
})
ctx.PackageFile(rcDir, src.Base(), src)
- m.installedInitRcPaths = append(m.installedInitRcPaths, installedInitRc)
+ ctx.installedInitRcPaths = append(ctx.installedInitRcPaths, installedInitRc)
}
+ installFiles.InitRcPaths = ctx.initRcPaths
+ installFiles.KatiInitRcInstalls = ctx.katiInitRcInstalls
+ installFiles.InstalledInitRcPaths = ctx.installedInitRcPaths
}
- m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments.GetOrDefault(m.ConfigurableEvaluator(ctx), nil))
+ ctx.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments.GetOrDefault(ctx, nil))
vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
- for _, src := range m.vintfFragmentsPaths {
+ for _, src := range ctx.vintfFragmentsPaths {
installedVintfFragment := vintfDir.Join(ctx, src.Base())
- m.katiVintfInstalls = append(m.katiVintfInstalls, katiInstall{
+ ctx.katiVintfInstalls = append(ctx.katiVintfInstalls, katiInstall{
from: src,
to: installedVintfFragment,
})
ctx.PackageFile(vintfDir, src.Base(), src)
- m.installedVintfFragmentsPaths = append(m.installedVintfFragmentsPaths, installedVintfFragment)
+ ctx.installedVintfFragmentsPaths = append(ctx.installedVintfFragmentsPaths, installedVintfFragment)
}
+ installFiles.VintfFragmentsPaths = ctx.vintfFragmentsPaths
+ installFiles.KatiVintfInstalls = ctx.katiVintfInstalls
+ installFiles.InstalledVintfFragmentsPaths = ctx.installedVintfFragmentsPaths
}
licensesPropertyFlattener(ctx)
@@ -1885,71 +1938,38 @@
return
}
- incrementalAnalysis := false
- incrementalEnabled := false
- var cacheKey *blueprint.BuildActionCacheKey = nil
- var incrementalModule *blueprint.Incremental = nil
- if ctx.bp.GetIncrementalEnabled() {
- if im, ok := m.module.(blueprint.Incremental); ok {
- incrementalModule = &im
- incrementalEnabled = im.IncrementalSupported()
- incrementalAnalysis = ctx.bp.GetIncrementalAnalysis() && incrementalEnabled
- }
- }
- if incrementalEnabled {
- hash, err := proptools.CalculateHash(m.GetProperties())
- if err != nil {
- ctx.ModuleErrorf("failed to calculate properties hash: %s", err)
- return
- }
- cacheInput := new(blueprint.BuildActionCacheInput)
- cacheInput.PropertiesHash = hash
- ctx.VisitDirectDeps(func(module Module) {
- cacheInput.ProvidersHash =
- append(cacheInput.ProvidersHash, ctx.bp.OtherModuleProviderInitialValueHashes(module))
- })
- hash, err = proptools.CalculateHash(&cacheInput)
- if err != nil {
- ctx.ModuleErrorf("failed to calculate cache input hash: %s", err)
- return
- }
- cacheKey = &blueprint.BuildActionCacheKey{
- Id: ctx.bp.ModuleId(),
- InputHash: hash,
- }
+ m.module.GenerateAndroidBuildActions(ctx)
+ if ctx.Failed() {
+ return
}
- restored := false
- if incrementalAnalysis && cacheKey != nil {
- restored = ctx.bp.RestoreBuildActions(cacheKey, incrementalModule)
- }
-
- if !restored {
- m.module.GenerateAndroidBuildActions(ctx)
- if ctx.Failed() {
- return
- }
- }
-
- if incrementalEnabled && cacheKey != nil {
- ctx.bp.CacheBuildActions(cacheKey, incrementalModule)
+ if x, ok := m.module.(IDEInfo); ok {
+ var result IdeInfo
+ x.IDEInfo(ctx, &result)
+ result.BaseModuleName = x.BaseModuleName()
+ SetProvider(ctx, IdeInfoProviderKey, result)
}
// Create the set of tagged dist files after calling GenerateAndroidBuildActions
// as GenerateTaggedDistFiles() calls OutputFiles(tag) and so relies on the
// output paths being set which must be done before or during
// GenerateAndroidBuildActions.
- m.distFiles = m.GenerateTaggedDistFiles(ctx)
+ installFiles.DistFiles = m.GenerateTaggedDistFiles(ctx)
if ctx.Failed() {
return
}
- m.installFiles = append(m.installFiles, ctx.installFiles...)
- m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
- m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
- m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...)
- m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...)
- m.testData = append(m.testData, ctx.testData...)
+ m.generateVariantTarget(ctx)
+
+ installFiles.LicenseMetadataFile = ctx.licenseMetadataFile
+ installFiles.InstallFiles = ctx.installFiles
+ installFiles.CheckbuildFiles = ctx.checkbuildFiles
+ installFiles.CheckbuildTarget = ctx.checkbuildTarget
+ installFiles.UncheckedModule = ctx.uncheckedModule
+ installFiles.PackagingSpecs = ctx.packagingSpecs
+ installFiles.KatiInstalls = ctx.katiInstalls
+ installFiles.KatiSymlinks = ctx.katiSymlinks
+ installFiles.TestData = ctx.testData
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -1965,17 +1985,19 @@
}
}
- m.installFilesDepSet = NewDepSet[InstallPath](TOPOLOGICAL, m.installFiles, dependencyInstallFiles)
- m.packagingSpecsDepSet = NewDepSet[PackagingSpec](TOPOLOGICAL, m.packagingSpecs, dependencyPackagingSpecs)
+ ctx.TransitiveInstallFiles = NewDepSet[InstallPath](TOPOLOGICAL, ctx.installFiles, dependencyInstallFiles)
+ installFiles.TransitiveInstallFiles = ctx.TransitiveInstallFiles
+ installFiles.TransitivePackagingSpecs = NewDepSet[PackagingSpec](TOPOLOGICAL, ctx.packagingSpecs, dependencyPackagingSpecs)
- buildLicenseMetadata(ctx, m.licenseMetadataFile)
+ SetProvider(ctx, InstallFilesProvider, installFiles)
+ buildLicenseMetadata(ctx, ctx.licenseMetadataFile)
- if m.moduleInfoJSON != nil {
+ if ctx.moduleInfoJSON != nil {
var installed InstallPaths
- installed = append(installed, m.katiInstalls.InstallPaths()...)
- installed = append(installed, m.katiSymlinks.InstallPaths()...)
- installed = append(installed, m.katiInitRcInstalls.InstallPaths()...)
- installed = append(installed, m.katiVintfInstalls.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
@@ -1986,42 +2008,48 @@
}
var data []string
- for _, d := range m.testData {
+ for _, d := range ctx.testData {
data = append(data, d.ToRelativeInstallPath())
}
- if m.moduleInfoJSON.Uninstallable {
+ if ctx.moduleInfoJSON.Uninstallable {
installedStrings = nil
- if len(m.moduleInfoJSON.CompatibilitySuites) == 1 && m.moduleInfoJSON.CompatibilitySuites[0] == "null-suite" {
- m.moduleInfoJSON.CompatibilitySuites = nil
- m.moduleInfoJSON.TestConfig = nil
- m.moduleInfoJSON.AutoTestConfig = 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
}
}
- m.moduleInfoJSON.core = CoreModuleInfoJSON{
- RegisterName: m.moduleInfoRegisterName(ctx, m.moduleInfoJSON.SubName),
+ ctx.moduleInfoJSON.core = CoreModuleInfoJSON{
+ RegisterName: m.moduleInfoRegisterName(ctx, ctx.moduleInfoJSON.SubName),
Path: []string{ctx.ModuleDir()},
Installed: installedStrings,
- ModuleName: m.BaseModuleName() + m.moduleInfoJSON.SubName,
+ ModuleName: m.BaseModuleName() + ctx.moduleInfoJSON.SubName,
SupportedVariants: []string{m.moduleInfoVariant(ctx)},
TargetDependencies: targetRequired,
HostDependencies: hostRequired,
Data: data,
- Required: m.RequiredModuleNames(ctx),
+ Required: append(m.RequiredModuleNames(ctx), m.VintfFragmentModuleNames(ctx)...),
}
- SetProvider(ctx, ModuleInfoJSONProvider, m.moduleInfoJSON)
+ SetProvider(ctx, ModuleInfoJSONProvider, ctx.moduleInfoJSON)
}
m.buildParams = ctx.buildParams
m.ruleParams = ctx.ruleParams
m.variables = ctx.variables
- if m.outputFiles.DefaultOutputFiles != nil || m.outputFiles.TaggedOutputFiles != nil {
- SetProvider(ctx, OutputFilesProvider, m.outputFiles)
+ outputFiles := ctx.GetOutputFiles()
+ if outputFiles.DefaultOutputFiles != nil || outputFiles.TaggedOutputFiles != nil {
+ SetProvider(ctx, OutputFilesProvider, outputFiles)
}
+ if len(ctx.phonies) > 0 {
+ SetProvider(ctx, ModulePhonyProvider, ModulePhonyInfo{
+ Phonies: ctx.phonies,
+ })
+ }
buildComplianceMetadataProvider(ctx, m)
}
@@ -2106,11 +2134,61 @@
absFrom string
}
+func (p *katiInstall) GobEncode() ([]byte, error) {
+ w := new(bytes.Buffer)
+ encoder := gob.NewEncoder(w)
+ err := errors.Join(encoder.Encode(p.from), encoder.Encode(p.to),
+ encoder.Encode(p.implicitDeps), encoder.Encode(p.orderOnlyDeps),
+ encoder.Encode(p.executable), encoder.Encode(p.extraFiles),
+ encoder.Encode(p.absFrom))
+ if err != nil {
+ return nil, err
+ }
+
+ return w.Bytes(), nil
+}
+
+func (p *katiInstall) GobDecode(data []byte) error {
+ r := bytes.NewBuffer(data)
+ decoder := gob.NewDecoder(r)
+ err := errors.Join(decoder.Decode(&p.from), decoder.Decode(&p.to),
+ decoder.Decode(&p.implicitDeps), decoder.Decode(&p.orderOnlyDeps),
+ decoder.Decode(&p.executable), decoder.Decode(&p.extraFiles),
+ decoder.Decode(&p.absFrom))
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
type extraFilesZip struct {
zip Path
dir InstallPath
}
+func (p *extraFilesZip) GobEncode() ([]byte, error) {
+ w := new(bytes.Buffer)
+ encoder := gob.NewEncoder(w)
+ err := errors.Join(encoder.Encode(p.zip), encoder.Encode(p.dir))
+ if err != nil {
+ return nil, err
+ }
+
+ return w.Bytes(), nil
+}
+
+func (p *extraFilesZip) GobDecode(data []byte) error {
+ r := bytes.NewBuffer(data)
+ decoder := gob.NewDecoder(r)
+ err := errors.Join(decoder.Decode(&p.zip), decoder.Decode(&p.dir))
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
type katiInstalls []katiInstall
// BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a
@@ -2160,17 +2238,23 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
-type ConfigAndErrorContext interface {
+type ConfigContext interface {
+ Config() Config
+}
+
+type ConfigurableEvaluatorContext interface {
+ OtherModuleProviderContext
Config() Config
OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+ HasMutatorFinished(mutatorName string) bool
}
type configurationEvalutor struct {
- ctx ConfigAndErrorContext
+ ctx ConfigurableEvaluatorContext
m Module
}
-func (m *ModuleBase) ConfigurableEvaluator(ctx ConfigAndErrorContext) proptools.ConfigurableEvaluator {
+func (m *ModuleBase) ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator {
return configurationEvalutor{
ctx: ctx,
m: m.module,
@@ -2184,6 +2268,12 @@
func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue {
ctx := e.ctx
m := e.m
+
+ if !ctx.HasMutatorFinished("defaults") {
+ ctx.OtherModulePropertyErrorf(m, property, "Cannot evaluate configurable property before the defaults mutator has run")
+ return proptools.ConfigurableValueUndefined()
+ }
+
switch condition.FunctionName() {
case "release_flag":
if condition.NumArgs() != 1 {
@@ -2211,6 +2301,8 @@
}
variable := condition.Arg(0)
switch variable {
+ case "build_from_text_stub":
+ return proptools.ConfigurableValueBool(ctx.Config().BuildFromTextStub())
case "debuggable":
return proptools.ConfigurableValueBool(ctx.Config().Debuggable())
case "use_debug_art":
@@ -2509,17 +2601,18 @@
type OutputFilesProviderModuleContext interface {
OtherModuleProviderContext
Module() Module
+ GetOutputFiles() OutputFilesInfo
}
if mctx, isMctx := ctx.(OutputFilesProviderModuleContext); isMctx {
if mctx.Module() != module {
outputFiles, _ = OtherModuleProvider(mctx, module, OutputFilesProvider)
} else {
- outputFiles = mctx.Module().base().outputFiles
+ outputFiles = mctx.GetOutputFiles()
fromProperty = true
}
} else if cta, isCta := ctx.(*singletonContextAdaptor); isCta {
- providerData, _ := cta.moduleProvider(module, OutputFilesProvider)
+ providerData, _ := cta.otherModuleProvider(module, OutputFilesProvider)
outputFiles, _ = providerData.(OutputFilesInfo)
} else {
return nil, fmt.Errorf("unsupported context %q in method outputFilesForModuleFromProvider", reflect.TypeOf(ctx))
@@ -2621,17 +2714,15 @@
modulesInDir := make(map[string]Paths)
ctx.VisitAllModules(func(module Module) {
- blueprintDir := module.base().blueprintDir
- installTarget := module.base().installTarget
- checkbuildTarget := module.base().checkbuildTarget
+ info := OtherModuleProviderOrDefault(ctx, module, FinalModuleBuildTargetsProvider)
- if checkbuildTarget != nil {
- checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
- modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], checkbuildTarget)
+ if info.CheckbuildTarget != nil {
+ checkbuildDeps = append(checkbuildDeps, info.CheckbuildTarget)
+ modulesInDir[info.BlueprintDir] = append(modulesInDir[info.BlueprintDir], info.CheckbuildTarget)
}
- if installTarget != nil {
- modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget)
+ if info.InstallTarget != nil {
+ modulesInDir[info.BlueprintDir] = append(modulesInDir[info.BlueprintDir], info.InstallTarget)
}
})
@@ -2666,7 +2757,7 @@
ctx.VisitAllModules(func(module Module) {
if module.Enabled(ctx) {
key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross}
- osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...)
+ osDeps[key] = append(osDeps[key], OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).CheckbuildFiles...)
}
})
@@ -2701,7 +2792,7 @@
// Collect information for opening IDE project files in java/jdeps.go.
type IDEInfo interface {
- IDEInfo(ideInfo *IdeInfo)
+ IDEInfo(ctx BaseModuleContext, ideInfo *IdeInfo)
BaseModuleName() string
}
@@ -2713,7 +2804,9 @@
IDECustomizedModuleName() string
}
+// Collect information for opening IDE project files in java/jdeps.go.
type IdeInfo struct {
+ BaseModuleName string `json:"-"`
Deps []string `json:"dependencies,omitempty"`
Srcs []string `json:"srcs,omitempty"`
Aidl_include_dirs []string `json:"aidl_include_dirs,omitempty"`
@@ -2727,6 +2820,31 @@
Libs []string `json:"libs,omitempty"`
}
+// Merge merges two IdeInfos and produces a new one, leaving the origional unchanged
+func (i IdeInfo) Merge(other IdeInfo) IdeInfo {
+ return IdeInfo{
+ Deps: mergeStringLists(i.Deps, other.Deps),
+ Srcs: mergeStringLists(i.Srcs, other.Srcs),
+ Aidl_include_dirs: mergeStringLists(i.Aidl_include_dirs, other.Aidl_include_dirs),
+ Jarjar_rules: mergeStringLists(i.Jarjar_rules, other.Jarjar_rules),
+ Jars: mergeStringLists(i.Jars, other.Jars),
+ Classes: mergeStringLists(i.Classes, other.Classes),
+ Installed_paths: mergeStringLists(i.Installed_paths, other.Installed_paths),
+ SrcJars: mergeStringLists(i.SrcJars, other.SrcJars),
+ Paths: mergeStringLists(i.Paths, other.Paths),
+ Static_libs: mergeStringLists(i.Static_libs, other.Static_libs),
+ Libs: mergeStringLists(i.Libs, other.Libs),
+ }
+}
+
+// mergeStringLists appends the two string lists together and returns a new string list,
+// leaving the originals unchanged. Duplicate strings will be deduplicated.
+func mergeStringLists(a, b []string) []string {
+ return FirstUniqueStrings(Concat(a, b))
+}
+
+var IdeInfoProviderKey = blueprint.NewProvider[IdeInfo]()
+
func CheckBlueprintSyntax(ctx BaseModuleContext, filename string, contents string) []error {
bpctx := ctx.blueprintBaseModuleContext()
return blueprint.CheckBlueprintSyntax(bpctx.ModuleFactories(), filename, contents)
diff --git a/android/module_context.go b/android/module_context.go
index 253bebd..2bf2a8f 100644
--- a/android/module_context.go
+++ b/android/module_context.go
@@ -85,7 +85,9 @@
type ModuleContext interface {
BaseModuleContext
- blueprintModuleContext() blueprint.ModuleContext
+ // BlueprintModuleContext returns the blueprint.ModuleContext that the ModuleContext wraps. It may only be
+ // used by the golang module types that need to call into the bootstrap module types.
+ BlueprintModuleContext() blueprint.ModuleContext
// Deprecated: use ModuleContext.Build instead.
ModuleBuild(pctx PackageContext, params ModuleBuildParams)
@@ -107,68 +109,79 @@
// InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
// with the given additional dependencies. The file is marked executable after copying.
//
- // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
+ // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
+ // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
// InstallFile creates a rule to copy srcPath to name in the installPath directory,
// with the given additional dependencies.
//
+ // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
+ // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
+ InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
+
+ // InstallFileWithoutCheckbuild creates a rule to copy srcPath to name in the installPath directory,
+ // with the given additional dependencies, but does not add the file to the list of files to build
+ // during `m checkbuild`.
+ //
// The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
// installed file will be returned by PackagingSpecs() on this module or by
// TransitivePackagingSpecs() on modules that depend on this module through dependency tags
// for which IsInstallDepNeeded returns true.
- InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
+ InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
// InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
// directory, and also unzip a zip file containing extra files to install into the same
// directory.
//
- // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
+ // The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
+ // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath
// InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
// directory.
//
- // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
+ // The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
+ // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
// InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
// in the installPath directory.
//
- // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
+ // The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
+ // for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
// InstallTestData creates rules to install test data (e.g. data files used during a test) into
// the installPath directory.
//
- // The installed files will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed files will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
+ // The installed files can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
+ // for the installed files can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
InstallTestData(installPath InstallPath, data []DataPath) InstallPaths
// PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
// the rule to copy the file. This is useful to define how a module would be packaged
// without installing it into the global installation directories.
//
- // The created PackagingSpec for the will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
+ // The created PackagingSpec can be accessed by InstallFilesInfo.PackagingSpecs on this module
+ // or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
+ // dependency tags for which IsInstallDepNeeded returns true.
PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
- CheckbuildFile(srcPath Path)
+ CheckbuildFile(srcPaths ...Path)
+ UncheckedModule()
InstallInData() bool
InstallInTestcases() bool
@@ -183,7 +196,7 @@
InstallInVendor() bool
InstallForceOS() (*OsType, *ArchType)
- RequiredModuleNames(ctx ConfigAndErrorContext) []string
+ RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
@@ -216,23 +229,57 @@
// to set the OutputFilesProvider later.
SetOutputFiles(outputFiles Paths, tag string)
+ GetOutputFiles() OutputFilesInfo
+
+ // SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
+ // apex container for use when generation the license metadata file.
+ SetLicenseInstallMap(installMap []string)
+
// ComplianceMetadataInfo returns a ComplianceMetadataInfo instance for different module types to dump metadata,
// which usually happens in GenerateAndroidBuildActions() of a module type.
// See android.ModuleBase.complianceMetadataInfo
ComplianceMetadataInfo() *ComplianceMetadataInfo
+
+ // Get the information about the containers this module belongs to.
+ getContainersInfo() ContainersInfo
+ setContainersInfo(info ContainersInfo)
+
+ setAconfigPaths(paths Paths)
}
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
- packagingSpecs []PackagingSpec
- installFiles InstallPaths
- checkbuildFiles Paths
- module Module
- phonies map[string]Paths
+ packagingSpecs []PackagingSpec
+ installFiles InstallPaths
+ checkbuildFiles Paths
+ checkbuildTarget Path
+ uncheckedModule bool
+ module Module
+ phonies map[string]Paths
+ // outputFiles stores the output of a module by tag and is used to set
+ // the OutputFilesProvider in GenerateBuildActions
+ outputFiles OutputFilesInfo
- katiInstalls []katiInstall
- katiSymlinks []katiInstall
+ TransitiveInstallFiles *DepSet[InstallPath]
+
+ // set of dependency module:location mappings used to populate the license metadata for
+ // apex containers.
+ licenseInstallMap []string
+
+ // The path to the generated license metadata file for the module.
+ licenseMetadataFile WritablePath
+
+ katiInstalls katiInstalls
+ katiSymlinks katiInstalls
+ // katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
+ // allowed to have duplicates across modules and variants.
+ katiInitRcInstalls katiInstalls
+ katiVintfInstalls katiInstalls
+ initRcPaths Paths
+ vintfFragmentsPaths Paths
+ installedInitRcPaths InstallPaths
+ installedVintfFragmentsPaths InstallPaths
testData []DataPath
@@ -240,6 +287,21 @@
buildParams []BuildParams
ruleParams map[blueprint.Rule]blueprint.RuleParams
variables map[string]string
+
+ // 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
+
+ // containersInfo stores the information about the containers and the information of the
+ // apexes the module belongs to.
+ containersInfo ContainersInfo
+
+ // Merged Aconfig files for all transitive deps.
+ aconfigFilePaths Paths
+
+ // complianceMetadataInfo is for different module types to dump metadata.
+ // See android.ModuleContext interface.
+ complianceMetadataInfo *ComplianceMetadataInfo
}
var _ ModuleContext = &moduleContext{}
@@ -361,7 +423,7 @@
}
func (m *moduleContext) Phony(name string, deps ...Path) {
- addPhony(m.config, name, deps...)
+ m.phonies[name] = append(m.phonies[name], deps...)
}
func (m *moduleContext) GetMissingDependencies() []string {
@@ -465,17 +527,22 @@
func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
deps ...InstallPath) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, false, true, nil)
+ return m.installFile(installPath, name, srcPath, deps, false, true, true, nil)
+}
+
+func (m *moduleContext) InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path,
+ deps ...InstallPath) InstallPath {
+ return m.installFile(installPath, name, srcPath, deps, false, true, false, nil)
}
func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
deps ...InstallPath) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, true, true, nil)
+ return m.installFile(installPath, name, srcPath, deps, true, true, true, nil)
}
func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
extraZip Path, deps ...InstallPath) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, false, true, &extraFilesZip{
+ return m.installFile(installPath, name, srcPath, deps, false, true, true, &extraFilesZip{
zip: extraZip,
dir: installPath,
})
@@ -487,11 +554,16 @@
}
func (m *moduleContext) getAconfigPaths() *Paths {
- return &m.module.base().aconfigFilePaths
+ return &m.aconfigFilePaths
+}
+
+func (m *moduleContext) setAconfigPaths(paths Paths) {
+ m.aconfigFilePaths = paths
}
func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
licenseFiles := m.Module().EffectiveLicenseFiles()
+ overrides := CopyOf(m.Module().base().commonProperties.Overrides)
spec := PackagingSpec{
relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
srcPath: srcPath,
@@ -502,13 +574,15 @@
skipInstall: m.skipInstall(),
aconfigPaths: m.getAconfigPaths(),
archType: m.target.Arch.ArchType,
+ overrides: &overrides,
+ owner: m.ModuleName(),
}
m.packagingSpecs = append(m.packagingSpecs, spec)
return spec
}
func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
- executable bool, hooks bool, extraZip *extraFilesZip) InstallPath {
+ executable bool, hooks bool, checkbuild bool, extraZip *extraFilesZip) InstallPath {
fullInstallPath := installPath.Join(m, name)
if hooks {
@@ -516,9 +590,9 @@
}
if m.requiresFullInstall() {
- deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList())...)
- deps = append(deps, m.module.base().installedInitRcPaths...)
- deps = append(deps, m.module.base().installedVintfFragmentsPaths...)
+ deps = append(deps, InstallPaths(m.TransitiveInstallFiles.ToList())...)
+ deps = append(deps, m.installedInitRcPaths...)
+ deps = append(deps, m.installedVintfFragmentsPaths...)
var implicitDeps, orderOnlyDeps Paths
@@ -575,7 +649,9 @@
m.packageFile(fullInstallPath, srcPath, executable)
- m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+ if checkbuild {
+ m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+ }
return fullInstallPath
}
@@ -616,9 +692,9 @@
}
m.installFiles = append(m.installFiles, fullInstallPath)
- m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
+ overrides := CopyOf(m.Module().base().commonProperties.Overrides)
m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
srcPath: nil,
@@ -628,6 +704,8 @@
skipInstall: m.skipInstall(),
aconfigPaths: m.getAconfigPaths(),
archType: m.target.Arch.ArchType,
+ overrides: &overrides,
+ owner: m.ModuleName(),
})
return fullInstallPath
@@ -663,6 +741,7 @@
m.installFiles = append(m.installFiles, fullInstallPath)
}
+ overrides := CopyOf(m.Module().base().commonProperties.Overrides)
m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
srcPath: nil,
@@ -672,6 +751,8 @@
skipInstall: m.skipInstall(),
aconfigPaths: m.getAconfigPaths(),
archType: m.target.Arch.ArchType,
+ overrides: &overrides,
+ owner: m.ModuleName(),
})
return fullInstallPath
@@ -683,59 +764,71 @@
ret := make(InstallPaths, 0, len(data))
for _, d := range data {
relPath := d.ToRelativeInstallPath()
- installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, nil)
+ installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, true, nil)
ret = append(ret, installed)
}
return ret
}
-func (m *moduleContext) CheckbuildFile(srcPath Path) {
- m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+// CheckbuildFile specifies the output files that should be built by checkbuild.
+func (m *moduleContext) CheckbuildFile(srcPaths ...Path) {
+ m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...)
}
-func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
+// UncheckedModule marks the current module has having no files that should be built by checkbuild.
+func (m *moduleContext) UncheckedModule() {
+ m.uncheckedModule = true
+}
+
+func (m *moduleContext) BlueprintModuleContext() blueprint.ModuleContext {
return m.bp
}
func (m *moduleContext) LicenseMetadataFile() Path {
- return m.module.base().licenseMetadataFile
+ return m.licenseMetadataFile
}
func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
- if moduleInfoJSON := m.module.base().moduleInfoJSON; moduleInfoJSON != nil {
+ if moduleInfoJSON := m.moduleInfoJSON; moduleInfoJSON != nil {
return moduleInfoJSON
}
moduleInfoJSON := &ModuleInfoJSON{}
- m.module.base().moduleInfoJSON = moduleInfoJSON
+ m.moduleInfoJSON = moduleInfoJSON
return moduleInfoJSON
}
func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) {
if tag == "" {
- if len(m.module.base().outputFiles.DefaultOutputFiles) > 0 {
+ if len(m.outputFiles.DefaultOutputFiles) > 0 {
m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName())
}
- m.module.base().outputFiles.DefaultOutputFiles = outputFiles
+ m.outputFiles.DefaultOutputFiles = outputFiles
} else {
- if m.module.base().outputFiles.TaggedOutputFiles == nil {
- m.module.base().outputFiles.TaggedOutputFiles = make(map[string]Paths)
+ if m.outputFiles.TaggedOutputFiles == nil {
+ m.outputFiles.TaggedOutputFiles = make(map[string]Paths)
}
- if _, exists := m.module.base().outputFiles.TaggedOutputFiles[tag]; exists {
+ if _, exists := m.outputFiles.TaggedOutputFiles[tag]; exists {
m.ModuleErrorf("Module %s OutputFiles at tag %s cannot be overwritten", m.ModuleName(), tag)
} else {
- m.module.base().outputFiles.TaggedOutputFiles[tag] = outputFiles
+ m.outputFiles.TaggedOutputFiles[tag] = outputFiles
}
}
}
+func (m *moduleContext) GetOutputFiles() OutputFilesInfo {
+ return m.outputFiles
+}
+
+func (m *moduleContext) SetLicenseInstallMap(installMap []string) {
+ m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
+}
+
func (m *moduleContext) ComplianceMetadataInfo() *ComplianceMetadataInfo {
- if complianceMetadataInfo := m.module.base().complianceMetadataInfo; complianceMetadataInfo != nil {
- return complianceMetadataInfo
+ if m.complianceMetadataInfo == nil {
+ m.complianceMetadataInfo = NewComplianceMetadataInfo()
}
- complianceMetadataInfo := NewComplianceMetadataInfo()
- m.module.base().complianceMetadataInfo = complianceMetadataInfo
- return complianceMetadataInfo
+ return m.complianceMetadataInfo
}
// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
@@ -764,7 +857,7 @@
return OptionalPath{}
}
-func (m *moduleContext) RequiredModuleNames(ctx ConfigAndErrorContext) []string {
+func (m *moduleContext) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
return m.module.RequiredModuleNames(ctx)
}
@@ -775,3 +868,11 @@
func (m *moduleContext) TargetRequiredModuleNames() []string {
return m.module.TargetRequiredModuleNames()
}
+
+func (m *moduleContext) getContainersInfo() ContainersInfo {
+ return m.containersInfo
+}
+
+func (m *moduleContext) setContainersInfo(info ContainersInfo) {
+ m.containersInfo = info
+}
diff --git a/android/module_test.go b/android/module_test.go
index 829c079..d76d9b3 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -722,6 +722,7 @@
propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "x86_64 a"},
propInfo{Name: "B", Type: "bool", Value: "true"},
propInfo{Name: "C", Type: "string slice", Values: []string{"default_c", "c"}},
+ propInfo{Name: "Defaults", Type: "string slice", Values: []string{"foo_defaults"}},
propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
propInfo{Name: "Name", Type: "string", Value: "foo"},
propInfo{Name: "Nested.E", Type: "string", Value: "nested e"},
@@ -993,6 +994,10 @@
func (p *pathContextAddMissingDependenciesWrapper) Module() Module { return nil }
+func (p *pathContextAddMissingDependenciesWrapper) GetOutputFiles() OutputFilesInfo {
+ return OutputFilesInfo{}
+}
+
func TestOutputFileForModule(t *testing.T) {
testcases := []struct {
name string
@@ -1075,3 +1080,29 @@
})
}
}
+
+func TestVintfFragmentModulesChecksPartition(t *testing.T) {
+ bp := `
+ vintf_fragment {
+ name: "vintfModA",
+ src: "test_vintf_file",
+ vendor: true,
+ }
+ deps {
+ name: "modA",
+ vintf_fragment_modules: [
+ "vintfModA",
+ ]
+ }
+ `
+
+ testPreparer := GroupFixturePreparers(
+ PrepareForTestWithAndroidBuildComponents,
+ prepareForModuleTests,
+ )
+
+ testPreparer.
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(
+ "Module .+ and Vintf_fragment .+ are installed to different partitions.")).
+ RunTestWithBp(t, bp)
+}
diff --git a/android/mutator.go b/android/mutator.go
index b81dd12..8265458 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -26,17 +26,17 @@
// run Pre-deps mutators
// run depsMutator
// run PostDeps mutators
-// run FinalDeps mutators (CreateVariations disallowed in this phase)
+// run FinalDeps mutators (TransitionMutators disallowed in this phase)
// continue on to GenerateAndroidBuildActions
// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
// with the InitRegistrationContext and will be used at runtime.
func collateGloballyRegisteredMutators() sortableComponents {
- return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps)
+ return collateRegisteredMutators(preArch, preDeps, postDeps, postApex, finalDeps)
}
// collateRegisteredMutators constructs a single list of mutators from the separate lists.
-func collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) sortableComponents {
+func collateRegisteredMutators(preArch, preDeps, postDeps, postApex, finalDeps []RegisterMutatorFunc) sortableComponents {
mctx := ®isterMutatorsContext{}
register := func(funcs []RegisterMutatorFunc) {
@@ -53,6 +53,8 @@
register(postDeps)
+ register(postApex)
+
mctx.finalPhase = true
register(finalDeps)
@@ -148,9 +150,9 @@
}
func registerArchMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUpBlueprint("os", osMutator).Parallel()
- ctx.BottomUp("image", imageMutator).Parallel()
- ctx.BottomUpBlueprint("arch", archMutator).Parallel()
+ ctx.Transition("os", &osTransitionMutator{})
+ ctx.Transition("image", &imageTransitionMutator{})
+ ctx.Transition("arch", &archTransitionMutator{})
}
var preDeps = []RegisterMutatorFunc{
@@ -166,6 +168,8 @@
RegisterOverridePostDepsMutators,
}
+var postApex = []RegisterMutatorFunc{}
+
var finalDeps = []RegisterMutatorFunc{}
func PreArchMutators(f RegisterMutatorFunc) {
@@ -180,6 +184,10 @@
postDeps = append(postDeps, f)
}
+func PostApexMutators(f RegisterMutatorFunc) {
+ postApex = append(postApex, f)
+}
+
func FinalDepsMutators(f RegisterMutatorFunc) {
finalDeps = append(finalDeps, f)
}
@@ -193,16 +201,16 @@
// Rename all variants of a module. The new name is not visible to calls to ModuleName,
// AddDependency or OtherModuleName until after this mutator pass is complete.
Rename(name string)
+
+ // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
+ // the specified property structs to it as if the properties were set in a blueprint file.
+ CreateModule(ModuleFactory, ...interface{}) Module
}
type TopDownMutator func(TopDownMutatorContext)
type TopDownMutatorContext interface {
BaseMutatorContext
-
- // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
- // the specified property structs to it as if the properties were set in a blueprint file.
- CreateModule(ModuleFactory, ...interface{}) Module
}
type topDownMutatorContext struct {
@@ -231,36 +239,6 @@
// module's dependency list.
AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
- // CreateVariations splits a module into multiple variants, one for each name in the variationNames
- // parameter. It returns a list of new modules in the same order as the variationNames
- // list.
- //
- // If any of the dependencies of the module being operated on were already split
- // by calling CreateVariations with the same name, the dependency will automatically
- // be updated to point the matching variant.
- //
- // If a module is split, and then a module depending on the first module is not split
- // when the Mutator is later called on it, the dependency of the depending module will
- // automatically be updated to point to the first variant.
- CreateVariations(...string) []Module
-
- // CreateLocationVariations splits a module into multiple variants, one for each name in the variantNames
- // parameter. It returns a list of new modules in the same order as the variantNames
- // list.
- //
- // Local variations do not affect automatic dependency resolution - dependencies added
- // to the split module via deps or DynamicDependerModule must exactly match a variant
- // that contains all the non-local variations.
- CreateLocalVariations(...string) []Module
-
- // SetDependencyVariation sets all dangling dependencies on the current module to point to the variation
- // with given name. This function ignores the default variation set by SetDefaultDependencyVariation.
- SetDependencyVariation(string)
-
- // SetDefaultDependencyVariation sets the default variation when a dangling reference is detected
- // during the subsequent calls on Create*Variations* functions. To reset, set it to nil.
- SetDefaultDependencyVariation(*string)
-
// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
// argument to select which variant of the dependency to use. It returns a slice of modules for
// each dependency (some entries may be nil). A variant of the dependency must exist that matches
@@ -272,6 +250,16 @@
// be ordered correctly for all future mutator passes.
AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module
+ // AddReverseVariationDependencies 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
+ // result will be used to find the correct variation of the depending module, which must exist.
+ //
+ // Does not affect the ordering of the current mutator pass, but will be ordered
+ // correctly for all future mutator passes. All reverse dependencies for a destination module are
+ // collected until the end of the mutator pass, sorted by name, and then appended to the destination
+ // module's dependency list.
+ AddReverseVariationDependency([]blueprint.Variation, blueprint.DependencyTag, string)
+
// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
// variations argument to select which variant of the dependency to use. It returns a slice of
// modules for each dependency (some entries may be nil). A variant of the dependency must
@@ -287,12 +275,6 @@
// be ordered correctly for all future mutator passes.
AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module
- // AddInterVariantDependency adds a dependency between two variants of the same module. Variants are always
- // ordered in the same orderas they were listed in CreateVariations, and AddInterVariantDependency does not change
- // that ordering, but it associates a DependencyTag with the dependency and makes it visible to VisitDirectDeps,
- // WalkDeps, etc.
- AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.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.
// Replacements don't take effect until after the mutator pass is finished.
@@ -303,30 +285,6 @@
// as long as the supplied predicate returns true.
// Replacements don't take effect until after the mutator pass is finished.
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
-
- // AliasVariation takes a variationName that was passed to CreateVariations for this module,
- // and creates an alias from the current variant (before the mutator has run) to the new
- // variant. The alias will be valid until the next time a mutator calls CreateVariations or
- // CreateLocalVariations on this module without also calling AliasVariation. The alias can
- // be used to add dependencies on the newly created variant using the variant map from
- // before CreateVariations was run.
- AliasVariation(variationName string)
-
- // CreateAliasVariation takes a toVariationName that was passed to CreateVariations for this
- // module, and creates an alias from a new fromVariationName variant the toVariationName
- // variant. The alias will be valid until the next time a mutator calls CreateVariations or
- // CreateLocalVariations on this module without also calling AliasVariation. The alias can
- // be used to add dependencies on the toVariationName variant using the fromVariationName
- // variant.
- CreateAliasVariation(fromVariationName, toVariationName string)
-
- // SetVariationProvider sets the value for a provider for the given newly created variant of
- // the current module, i.e. one of the Modules returned by CreateVariations.. 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 module is not a newly created
- // variant of the current module. The value should not be modified after being passed to
- // SetVariationProvider.
- SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{})
}
// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
@@ -516,6 +474,9 @@
}
func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
+ if a.finalPhase {
+ panic("TransitionMutator not allowed in FinalDepsMutators")
+ }
if m, ok := ctx.Module().(Module); ok {
moduleContext := m.base().baseModuleContextFactory(ctx)
return a.mutator.Split(&moduleContext)
@@ -739,6 +700,14 @@
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 ModuleFactory, props ...interface{}) Module {
+ return createModule(b, factory, "_bottomUpMutatorModule", props...)
+}
+
func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module {
if b.baseModuleContext.checkedMissingDeps() {
panic("Adding deps not allowed after checking for missing deps")
@@ -753,48 +722,11 @@
b.bp.AddReverseDependency(module, tag, name)
}
-func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []Module {
- if b.finalPhase {
- panic("CreateVariations not allowed in FinalDepsMutators")
+func (b *bottomUpMutatorContext) AddReverseVariationDependency(variations []blueprint.Variation, tag blueprint.DependencyTag, name string) {
+ if b.baseModuleContext.checkedMissingDeps() {
+ panic("Adding deps not allowed after checking for missing deps")
}
-
- modules := b.bp.CreateVariations(variations...)
-
- aModules := make([]Module, len(modules))
- for i := range variations {
- aModules[i] = modules[i].(Module)
- base := aModules[i].base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
- }
-
- return aModules
-}
-
-func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []Module {
- if b.finalPhase {
- panic("CreateLocalVariations not allowed in FinalDepsMutators")
- }
-
- modules := b.bp.CreateLocalVariations(variations...)
-
- aModules := make([]Module, len(modules))
- for i := range variations {
- aModules[i] = modules[i].(Module)
- base := aModules[i].base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, b.MutatorName())
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variations[i])
- }
-
- return aModules
-}
-
-func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) {
- b.bp.SetDependencyVariation(variation)
-}
-
-func (b *bottomUpMutatorContext) SetDefaultDependencyVariation(variation *string) {
- b.bp.SetDefaultDependencyVariation(variation)
+ b.bp.AddReverseVariationDependency(variations, tag, name)
}
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
@@ -814,10 +746,6 @@
return b.bp.AddFarVariationDependencies(variations, tag, names...)
}
-func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) {
- b.bp.AddInterVariantDependency(tag, from, to)
-}
-
func (b *bottomUpMutatorContext) ReplaceDependencies(name string) {
if b.baseModuleContext.checkedMissingDeps() {
panic("Adding deps not allowed after checking for missing deps")
@@ -831,15 +759,3 @@
}
b.bp.ReplaceDependenciesIf(name, predicate)
}
-
-func (b *bottomUpMutatorContext) AliasVariation(variationName string) {
- b.bp.AliasVariation(variationName)
-}
-
-func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) {
- b.bp.CreateAliasVariation(fromVariationName, toVariationName)
-}
-
-func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{}) {
- b.bp.SetVariationProvider(module, provider, value)
-}
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 21eebd2..5d4074a 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -81,6 +81,40 @@
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 {
@@ -94,9 +128,11 @@
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pre_arch", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateVariations("a", "b")
+ ctx.Transition("pre_arch", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"a", "b"}
+ },
})
ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
@@ -105,16 +141,23 @@
})
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("pre_deps", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateVariations("c", "d")
+ 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.BottomUp("post_deps", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.CreateLocalVariations("e", "f")
+ 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())
@@ -138,15 +181,15 @@
"foo{pre_arch:b}",
"foo{pre_arch:a}",
- // After rename_top_down.
- "foo_renamed1{pre_arch:a}",
+ // After rename_top_down (reversed because pre_deps TransitionMutator.Split is TopDown).
"foo_renamed1{pre_arch:b}",
+ "foo_renamed1{pre_arch:a}",
- // After pre_deps.
- "foo_renamed1{pre_arch:a,pre_deps:c}",
- "foo_renamed1{pre_arch:a,pre_deps:d}",
- "foo_renamed1{pre_arch:b,pre_deps:c}",
+ // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
"foo_renamed1{pre_arch:b,pre_deps:d}",
+ "foo_renamed1{pre_arch:b,pre_deps:c}",
+ "foo_renamed1{pre_arch:a,pre_deps:d}",
+ "foo_renamed1{pre_arch:a,pre_deps:c}",
// After post_deps.
"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
@@ -202,8 +245,10 @@
ctx.AddFarVariationDependencies([]blueprint.Variation{}, dep1Tag, "common_dep_1")
}
})
- ctx.BottomUp("variant", func(ctx BottomUpMutatorContext) {
- ctx.CreateLocalVariations("a", "b")
+ ctx.Transition("variant", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
})
})
@@ -242,28 +287,21 @@
AssertDeepEquals(t, "final", finalWant, finalGot)
}
-func TestNoCreateVariationsInFinalDeps(t *testing.T) {
- checkErr := func() {
- if err := recover(); err == nil || !strings.Contains(fmt.Sprintf("%s", err), "not allowed in FinalDepsMutators") {
- panic("Expected FinalDepsMutators consistency check to fail")
- }
- }
-
+func TestTransitionMutatorInFinalDeps(t *testing.T) {
GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("vars", func(ctx BottomUpMutatorContext) {
- defer checkErr()
- ctx.CreateVariations("a", "b")
- })
- ctx.BottomUp("local_vars", func(ctx BottomUpMutatorContext) {
- defer checkErr()
- ctx.CreateLocalVariations("a", "b")
+ ctx.Transition("vars", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
})
})
ctx.RegisterModuleType("test", mutatorTestModuleFactory)
}),
FixtureWithRootAndroidBp(`test {name: "foo"}`),
- ).RunTest(t)
+ ).
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
+ RunTest(t)
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 0f363e7..e135f57 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -58,8 +58,8 @@
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
AddNeverAllowRules(createCcStubsRule())
- AddNeverAllowRules(createJavaExcludeStaticLibsRule())
AddNeverAllowRules(createProhibitHeaderOnlyRule())
+ AddNeverAllowRules(createLimitNdkExportRule()...)
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -182,6 +182,7 @@
"packages/modules/SdkExtensions/derive_sdk",
// These are for apps and shouldn't be used by non-SDK variant modules.
"prebuilts/ndk",
+ "frameworks/native/libs/binder/ndk",
"tools/test/graphicsbenchmark/apps/sample_app",
"tools/test/graphicsbenchmark/functional_tests/java",
"vendor/xts/gts-tests/hostsidetests/gamedevicecert/apps/javatests",
@@ -251,14 +252,6 @@
}
}
-func createJavaExcludeStaticLibsRule() Rule {
- return NeverAllow().
- NotIn("build/soong", "libcore", "frameworks/base/api").
- ModuleType("java_library").
- WithMatcher("exclude_static_libs", isSetMatcherInstance).
- Because("exclude_static_libs property is only allowed for java modules defined in build/soong, libcore, and frameworks/base/api")
-}
-
func createProhibitHeaderOnlyRule() Rule {
return NeverAllow().
Without("name", "framework-minus-apex-headers").
@@ -266,6 +259,22 @@
Because("headers_only can only be used for generating framework-minus-apex headers for non-updatable modules")
}
+func createLimitNdkExportRule() []Rule {
+ reason := "If the headers you're trying to export are meant to be a part of the NDK, they should be exposed by an ndk_headers module. If the headers shouldn't be a part of the NDK, the headers should instead be exposed from a separate `cc_library_headers` which consumers depend on."
+ // DO NOT ADD HERE - please consult danalbert@
+ // b/357711733
+ return []Rule{
+ NeverAllow().
+ NotIn("frameworks/native/libs/binder/ndk").
+ ModuleType("ndk_library").
+ WithMatcher("export_header_libs", isSetMatcherInstance).Because(reason),
+ NeverAllow().ModuleType("ndk_library").WithMatcher("export_generated_headers", isSetMatcherInstance).Because(reason),
+ NeverAllow().ModuleType("ndk_library").WithMatcher("export_include_dirs", isSetMatcherInstance).Because(reason),
+ NeverAllow().ModuleType("ndk_library").WithMatcher("export_shared_lib_headers", isSetMatcherInstance).Because(reason),
+ NeverAllow().ModuleType("ndk_library").WithMatcher("export_static_lib_headers", isSetMatcherInstance).Because(reason),
+ }
+}
+
func neverallowMutator(ctx BottomUpMutatorContext) {
m, ok := ctx.Module().(Module)
if !ok {
@@ -287,7 +296,7 @@
continue
}
- if !n.appliesToProperties(properties) {
+ if !n.appliesToProperties(ctx, properties) {
continue
}
@@ -604,9 +613,9 @@
return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
}
-func (r *rule) appliesToProperties(properties []interface{}) bool {
- includeProps := hasAllProperties(properties, r.props)
- excludeProps := hasAnyProperty(properties, r.unlessProps)
+func (r *rule) appliesToProperties(ctx BottomUpMutatorContext, properties []interface{}) bool {
+ includeProps := hasAllProperties(ctx, properties, r.props)
+ excludeProps := hasAnyProperty(ctx, properties, r.unlessProps)
return includeProps && !excludeProps
}
@@ -644,25 +653,25 @@
return names
}
-func hasAnyProperty(properties []interface{}, props []ruleProperty) bool {
+func hasAnyProperty(ctx BottomUpMutatorContext, properties []interface{}, props []ruleProperty) bool {
for _, v := range props {
- if hasProperty(properties, v) {
+ if hasProperty(ctx, properties, v) {
return true
}
}
return false
}
-func hasAllProperties(properties []interface{}, props []ruleProperty) bool {
+func hasAllProperties(ctx BottomUpMutatorContext, properties []interface{}, props []ruleProperty) bool {
for _, v := range props {
- if !hasProperty(properties, v) {
+ if !hasProperty(ctx, properties, v) {
return false
}
}
return true
}
-func hasProperty(properties []interface{}, prop ruleProperty) bool {
+func hasProperty(ctx BottomUpMutatorContext, properties []interface{}, prop ruleProperty) bool {
for _, propertyStruct := range properties {
propertiesValue := reflect.ValueOf(propertyStruct).Elem()
for _, v := range prop.fields {
@@ -679,14 +688,14 @@
return prop.matcher.Test(value)
}
- if matchValue(propertiesValue, check) {
+ if matchValue(ctx, propertiesValue, check) {
return true
}
}
return false
}
-func matchValue(value reflect.Value, check func(string) bool) bool {
+func matchValue(ctx BottomUpMutatorContext, value reflect.Value, check func(string) bool) bool {
if !value.IsValid() {
return false
}
@@ -698,19 +707,26 @@
value = value.Elem()
}
- switch value.Kind() {
- case reflect.String:
- return check(value.String())
- case reflect.Bool:
- return check(strconv.FormatBool(value.Bool()))
- case reflect.Int:
- return check(strconv.FormatInt(value.Int(), 10))
- case reflect.Slice:
- slice, ok := value.Interface().([]string)
- if !ok {
- panic("Can only handle slice of string")
+ switch v := value.Interface().(type) {
+ case string:
+ return check(v)
+ case bool:
+ return check(strconv.FormatBool(v))
+ case int:
+ return check(strconv.FormatInt((int64)(v), 10))
+ case []string:
+ for _, v := range v {
+ if check(v) {
+ return true
+ }
}
- for _, v := range slice {
+ return false
+ case proptools.Configurable[string]:
+ return check(v.GetOrDefault(ctx, ""))
+ case proptools.Configurable[bool]:
+ return check(strconv.FormatBool(v.GetOrDefault(ctx, false)))
+ case proptools.Configurable[[]string]:
+ for _, v := range v.GetOrDefault(ctx, nil) {
if check(v) {
return true
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index b2620ef..192c924 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -344,23 +344,6 @@
`module "outside_allowed_list": violates neverallow`,
},
},
- // Test for the rule restricting use of exclude_static_libs
- {
- name: `"exclude_static_libs" outside allowed directory`,
- fs: map[string][]byte{
- "a/b/Android.bp": []byte(`
- java_library {
- name: "baz",
- exclude_static_libs: [
- "bar",
- ],
- }
- `),
- },
- expectedErrors: []string{
- `exclude_static_libs property is only allowed for java modules defined in build/soong, libcore, and frameworks/base/api`,
- },
- },
// Test for only allowing headers_only for framework-minus-apex-headers
{
name: `"headers_only" outside framework-minus-apex-headers modules`,
diff --git a/android/notices.go b/android/notices.go
index b9c1682..3c41d92 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -36,10 +36,22 @@
return SortedUniqueStrings(dirs)
}
-func modulesLicenseMetadata(ctx BuilderContext, modules ...Module) Paths {
+type BuilderAndOtherModuleProviderContext interface {
+ BuilderContext
+ OtherModuleProviderContext
+}
+
+func modulesLicenseMetadata(ctx OtherModuleProviderContext, modules ...Module) Paths {
result := make(Paths, 0, len(modules))
+ mctx, isMctx := ctx.(ModuleContext)
for _, module := range modules {
- if mf := module.base().licenseMetadataFile; mf != nil {
+ var mf Path
+ if isMctx && mctx.Module() == module {
+ mf = mctx.LicenseMetadataFile()
+ } else {
+ mf = OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider).LicenseMetadataFile
+ }
+ if mf != nil {
result = append(result, mf)
}
}
@@ -48,7 +60,7 @@
// buildNoticeOutputFromLicenseMetadata writes out a notice file.
func buildNoticeOutputFromLicenseMetadata(
- ctx BuilderContext, tool, ruleName string, outputFile WritablePath,
+ ctx BuilderAndOtherModuleProviderContext, tool, ruleName string, outputFile WritablePath,
libraryName string, stripPrefix []string, modules ...Module) {
depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", "."))
rule := NewRuleBuilder(pctx, ctx)
@@ -84,7 +96,7 @@
// on the license metadata files for the input `modules` defaulting to the
// current context module if none given.
func BuildNoticeTextOutputFromLicenseMetadata(
- ctx BuilderContext, outputFile WritablePath, ruleName, libraryName string,
+ ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string,
stripPrefix []string, modules ...Module) {
buildNoticeOutputFromLicenseMetadata(ctx, "textnotice", "text_notice_"+ruleName,
outputFile, libraryName, stripPrefix, modules...)
@@ -94,7 +106,7 @@
// on the license metadata files for the input `modules` defaulting to the
// current context module if none given.
func BuildNoticeHtmlOutputFromLicenseMetadata(
- ctx BuilderContext, outputFile WritablePath, ruleName, libraryName string,
+ ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string,
stripPrefix []string, modules ...Module) {
buildNoticeOutputFromLicenseMetadata(ctx, "htmlnotice", "html_notice_"+ruleName,
outputFile, libraryName, stripPrefix, modules...)
@@ -104,7 +116,7 @@
// on the license metadata files for the input `modules` defaulting to the
// current context module if none given.
func BuildNoticeXmlOutputFromLicenseMetadata(
- ctx BuilderContext, outputFile WritablePath, ruleName, libraryName string,
+ ctx BuilderAndOtherModuleProviderContext, outputFile WritablePath, ruleName, libraryName string,
stripPrefix []string, modules ...Module) {
buildNoticeOutputFromLicenseMetadata(ctx, "xmlnotice", "xml_notice_"+ruleName,
outputFile, libraryName, stripPrefix, modules...)
diff --git a/android/packaging.go b/android/packaging.go
index c247ed2..0909936 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -15,6 +15,9 @@
package android
import (
+ "bytes"
+ "encoding/gob"
+ "errors"
"fmt"
"path/filepath"
"sort"
@@ -56,6 +59,42 @@
// ArchType of the module which produced this packaging spec
archType ArchType
+
+ // List of module names that this packaging spec overrides
+ overrides *[]string
+
+ // Name of the module where this packaging spec is output of
+ owner string
+}
+
+func (p *PackagingSpec) GobEncode() ([]byte, error) {
+ w := new(bytes.Buffer)
+ encoder := gob.NewEncoder(w)
+ err := errors.Join(encoder.Encode(p.relPathInPackage), encoder.Encode(p.srcPath),
+ encoder.Encode(p.symlinkTarget), encoder.Encode(p.executable),
+ encoder.Encode(p.effectiveLicenseFiles), encoder.Encode(p.partition),
+ encoder.Encode(p.skipInstall), encoder.Encode(p.aconfigPaths),
+ encoder.Encode(p.archType))
+ if err != nil {
+ return nil, err
+ }
+
+ return w.Bytes(), nil
+}
+
+func (p *PackagingSpec) GobDecode(data []byte) error {
+ r := bytes.NewBuffer(data)
+ decoder := gob.NewDecoder(r)
+ err := errors.Join(decoder.Decode(&p.relPathInPackage), decoder.Decode(&p.srcPath),
+ decoder.Decode(&p.symlinkTarget), decoder.Decode(&p.executable),
+ decoder.Decode(&p.effectiveLicenseFiles), decoder.Decode(&p.partition),
+ decoder.Decode(&p.skipInstall), decoder.Decode(&p.aconfigPaths),
+ decoder.Decode(&p.archType))
+ if err != nil {
+ return err
+ }
+
+ return nil
}
func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
@@ -325,7 +364,10 @@
}
func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
- m := make(map[string]PackagingSpec)
+ // all packaging specs gathered from the dep.
+ var all []PackagingSpec
+ // list of module names overridden
+ var overridden []string
var arches []ArchType
for _, target := range getSupportedTargets(ctx) {
@@ -346,7 +388,8 @@
if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
return
}
- for _, ps := range child.TransitivePackagingSpecs() {
+ for _, ps := range OtherModuleProviderOrDefault(
+ ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
if !filterArch(ps) {
continue
}
@@ -356,17 +399,33 @@
continue
}
}
- dstPath := ps.relPathInPackage
- if existingPs, ok := m[dstPath]; ok {
- if !existingPs.Equals(&ps) {
- ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
- }
- continue
+ all = append(all, ps)
+ if ps.overrides != nil {
+ overridden = append(overridden, *ps.overrides...)
}
-
- m[dstPath] = ps
}
})
+
+ // all minus packaging specs that are overridden
+ var filtered []PackagingSpec
+ for _, ps := range all {
+ if ps.owner != "" && InList(ps.owner, overridden) {
+ continue
+ }
+ filtered = append(filtered, ps)
+ }
+
+ m := make(map[string]PackagingSpec)
+ for _, ps := range filtered {
+ dstPath := ps.relPathInPackage
+ if existingPs, ok := m[dstPath]; ok {
+ if !existingPs.Equals(&ps) {
+ ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
+ }
+ continue
+ }
+ m[dstPath] = ps
+ }
return m
}
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 19b46fe..f5b1020 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -28,6 +28,7 @@
props struct {
Deps []string
Skip_install *bool
+ Overrides []string
}
}
@@ -117,6 +118,7 @@
}
result := GroupFixturePreparers(
+ PrepareForTestWithDefaults,
PrepareForTestWithArchMutator,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("component", componentTestModuleFactory)
@@ -650,3 +652,64 @@
runPackagingTest(t, config, bp, tc.expected)
}
}
+
+func TestOverrides(t *testing.T) {
+ bpTemplate := `
+ component {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ component {
+ name: "bar",
+ }
+
+ component {
+ name: "bar_override",
+ overrides: ["bar"],
+ }
+
+ component {
+ name: "baz",
+ deps: ["bar_override"],
+ }
+
+ package_module {
+ name: "package",
+ deps: %DEPS%,
+ }
+ `
+ testcases := []struct {
+ deps []string
+ expected []string
+ }{
+ {
+ deps: []string{"foo"},
+ expected: []string{"lib64/foo", "lib64/bar"},
+ },
+ {
+ deps: []string{"foo", "bar_override"},
+ expected: []string{"lib64/foo", "lib64/bar_override"},
+ },
+ {
+ deps: []string{"foo", "bar", "bar_override"},
+ expected: []string{"lib64/foo", "lib64/bar_override"},
+ },
+ {
+ deps: []string{"bar", "bar_override"},
+ expected: []string{"lib64/bar_override"},
+ },
+ {
+ deps: []string{"foo", "baz"},
+ expected: []string{"lib64/foo", "lib64/baz", "lib64/bar_override"},
+ },
+ }
+ for _, tc := range testcases {
+ config := testConfig{
+ multiTarget: true,
+ depsCollectFirstTargetOnly: false,
+ }
+ bp := strings.Replace(bpTemplate, "%DEPS%", `["`+strings.Join(tc.deps, `", "`)+`"]`, -1)
+ runPackagingTest(t, config, bp, tc.expected)
+ }
+}
diff --git a/android/paths.go b/android/paths.go
index dda48dd..1c8258e 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -27,7 +27,6 @@
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/pathtools"
)
@@ -92,8 +91,10 @@
// the Path methods that rely on module dependencies having been resolved.
type ModuleWithDepsPathContext interface {
EarlyModulePathContext
- VisitDirectDepsBlueprint(visit func(blueprint.Module))
+ OtherModuleProviderContext
+ VisitDirectDeps(visit func(Module))
OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+ HasMutatorFinished(mutatorName string) bool
}
// ModuleMissingDepsPathContext is a subset of *ModuleContext methods required by
@@ -237,6 +238,9 @@
// directory, and OutputPath.Join("foo").Rel() would return "foo".
Rel() string
+ // WithoutRel returns a new Path with no relative path, i.e. Rel() will return the same value as Base().
+ WithoutRel() Path
+
// RelativeToTop returns a new path relative to the top, it is provided solely for use in tests.
//
// It is guaranteed to always return the same type as it is called on, e.g. if called on an
@@ -245,13 +249,13 @@
// A standard build has the following structure:
// ../top/
// out/ - make install files go here.
- // out/soong - this is the soongOutDir passed to NewTestConfig()
+ // out/soong - this is the outDir passed to NewTestConfig()
// ... - the source files
//
// This function converts a path so that it appears relative to the ../top/ directory, i.e.
- // * Make install paths, which have the pattern "soongOutDir/../<path>" are converted into the top
+ // * Make install paths, which have the pattern "outDir/../<path>" are converted into the top
// relative path "out/<path>"
- // * Soong install paths and other writable paths, which have the pattern "soongOutDir/<path>" are
+ // * Soong install paths and other writable paths, which have the pattern "outDir/soong/<path>" are
// converted into the top relative path "out/soong/<path>".
// * Source paths are already relative to the top.
// * Phony paths are not relative to anything.
@@ -261,8 +265,9 @@
}
const (
- OutDir = "out"
- OutSoongDir = OutDir + "/soong"
+ testOutDir = "out"
+ testOutSoongSubDir = "/soong"
+ TestOutSoongDir = testOutDir + testOutSoongSubDir
)
// WritablePath is a type of path that can be used as an output for build rules.
@@ -550,13 +555,6 @@
return ret
}
-// PathForGoBinary returns the path to the installed location of a bootstrap_go_binary module.
-func PathForGoBinary(ctx PathContext, goBinary bootstrap.GoBinaryTool) Path {
- goBinaryInstallDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin")
- rel := Rel(ctx, goBinaryInstallDir.String(), goBinary.InstallPath())
- return goBinaryInstallDir.Join(ctx, rel)
-}
-
// Expands Paths to a SourceFileProducer or OutputFileProducer module dependency referenced via ":name" or ":name{.tag}" syntax.
// If the dependency is not found, a missingErrorDependency is returned.
// If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
@@ -568,10 +566,6 @@
if aModule, ok := module.(Module); ok && !aModule.Enabled(ctx) {
return nil, missingDependencyError{[]string{moduleName}}
}
- if goBinary, ok := module.(bootstrap.GoBinaryTool); ok && tag == "" {
- goBinaryPath := PathForGoBinary(ctx, goBinary)
- return Paths{goBinaryPath}, nil
- }
outputFiles, err := outputFilesForModule(ctx, module, tag)
if outputFiles != nil && err == nil {
return outputFiles, nil
@@ -604,7 +598,7 @@
// create the tag here as was supplied to create the tag when the dependency was added so that
// this finds the matching dependency module.
expectedTag := sourceOrOutputDepTag(moduleName, tag)
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDeps(func(module Module) {
depTag := ctx.OtherModuleDependencyTag(module)
if depTag == expectedTag {
found = module
@@ -1118,8 +1112,8 @@
return p
}
-func (p basePath) RelativeToTop() Path {
- ensureTestOnly()
+func (p basePath) withoutRel() basePath {
+ p.rel = filepath.Base(p.path)
return p
}
@@ -1135,6 +1129,11 @@
return p
}
+func (p SourcePath) RelativeToTop() Path {
+ ensureTestOnly()
+ return p
+}
+
// safePathForSource is for paths that we expect are safe -- only for use by go
// code that is embedding ninja variables in paths
func safePathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error) {
@@ -1218,11 +1217,13 @@
// 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 {
- p, err := validatePath(pathComponents...)
+ path, err := validatePath(pathComponents...)
if err != nil {
reportPathError(ctx, err)
}
- return basePath{path: filepath.Join(ctx.Config().OutDir(), p)}
+ fullPath := filepath.Join(ctx.Config().OutDir(), path)
+ path = fullPath[len(fullPath)-len(path):]
+ return OutputPath{basePath{path, ""}, ctx.Config().OutDir(), fullPath}
}
// MaybeExistentPathForSource joins the provided path components and validates that the result
@@ -1275,6 +1276,11 @@
return p.path
}
+func (p SourcePath) WithoutRel() Path {
+ p.basePath = p.basePath.withoutRel()
+ return p
+}
+
// Join creates a new SourcePath with paths... joined with the current path. The
// provided paths... may not use '..' to escape from the current path.
func (p SourcePath) Join(ctx PathContext, paths ...string) SourcePath {
@@ -1325,8 +1331,8 @@
type OutputPath struct {
basePath
- // The soong build directory, i.e. Config.SoongOutDir()
- soongOutDir string
+ // The base out directory for this path, either Config.SoongOutDir() or Config.OutDir()
+ outDir string
fullPath string
}
@@ -1334,7 +1340,7 @@
func (p OutputPath) GobEncode() ([]byte, error) {
w := new(bytes.Buffer)
encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.basePath), encoder.Encode(p.soongOutDir), encoder.Encode(p.fullPath))
+ err := errors.Join(encoder.Encode(p.basePath), encoder.Encode(p.outDir), encoder.Encode(p.fullPath))
if err != nil {
return nil, err
}
@@ -1345,7 +1351,7 @@
func (p *OutputPath) GobDecode(data []byte) error {
r := bytes.NewBuffer(data)
decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.basePath), decoder.Decode(&p.soongOutDir), decoder.Decode(&p.fullPath))
+ err := errors.Join(decoder.Decode(&p.basePath), decoder.Decode(&p.outDir), decoder.Decode(&p.fullPath))
if err != nil {
return err
}
@@ -1359,13 +1365,13 @@
return p
}
-func (p OutputPath) WithoutRel() OutputPath {
- p.basePath.rel = filepath.Base(p.basePath.path)
+func (p OutputPath) WithoutRel() Path {
+ p.basePath = p.basePath.withoutRel()
return p
}
func (p OutputPath) getSoongOutDir() string {
- return p.soongOutDir
+ return p.outDir
}
func (p OutputPath) RelativeToTop() Path {
@@ -1373,8 +1379,13 @@
}
func (p OutputPath) outputPathRelativeToTop() OutputPath {
- p.fullPath = StringPathRelativeToTop(p.soongOutDir, p.fullPath)
- p.soongOutDir = OutSoongDir
+ p.fullPath = StringPathRelativeToTop(p.outDir, p.fullPath)
+ if strings.HasSuffix(p.outDir, testOutSoongSubDir) {
+ p.outDir = TestOutSoongDir
+ } else {
+ // Handle the PathForArbitraryOutput case
+ p.outDir = testOutDir
+ }
return p
}
@@ -1391,6 +1402,11 @@
basePath
}
+func (t toolDepPath) WithoutRel() Path {
+ t.basePath = t.basePath.withoutRel()
+ return t
+}
+
func (t toolDepPath) RelativeToTop() Path {
ensureTestOnly()
return t
@@ -1420,7 +1436,7 @@
return OutputPath{basePath{path, ""}, ctx.Config().soongOutDir, fullPath}
}
-// PathsForOutput returns Paths rooted from soongOutDir
+// PathsForOutput returns Paths rooted from outDir
func PathsForOutput(ctx PathContext, paths []string) WritablePaths {
ret := make(WritablePaths, len(paths))
for i, path := range paths {
@@ -1740,6 +1756,32 @@
fullPath string
}
+func (p *InstallPath) GobEncode() ([]byte, error) {
+ w := new(bytes.Buffer)
+ encoder := gob.NewEncoder(w)
+ err := errors.Join(encoder.Encode(p.basePath), encoder.Encode(p.soongOutDir),
+ encoder.Encode(p.partitionDir), encoder.Encode(p.partition),
+ encoder.Encode(p.makePath), encoder.Encode(p.fullPath))
+ if err != nil {
+ return nil, err
+ }
+
+ return w.Bytes(), nil
+}
+
+func (p *InstallPath) GobDecode(data []byte) error {
+ r := bytes.NewBuffer(data)
+ decoder := gob.NewDecoder(r)
+ err := errors.Join(decoder.Decode(&p.basePath), decoder.Decode(&p.soongOutDir),
+ decoder.Decode(&p.partitionDir), decoder.Decode(&p.partition),
+ decoder.Decode(&p.makePath), decoder.Decode(&p.fullPath))
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
// Will panic if called from outside a test environment.
func ensureTestOnly() {
if PrefixInList(os.Args, "-test.") {
@@ -1751,14 +1793,19 @@
func (p InstallPath) RelativeToTop() Path {
ensureTestOnly()
if p.makePath {
- p.soongOutDir = OutDir
+ p.soongOutDir = testOutDir
} else {
- p.soongOutDir = OutSoongDir
+ p.soongOutDir = TestOutSoongDir
}
p.fullPath = filepath.Join(p.soongOutDir, p.path)
return p
}
+func (p InstallPath) WithoutRel() Path {
+ p.basePath = p.basePath.withoutRel()
+ return p
+}
+
func (p InstallPath) getSoongOutDir() string {
return p.soongOutDir
}
@@ -2079,6 +2126,11 @@
return p
}
+func (p PhonyPath) WithoutRel() Path {
+ p.basePath = p.basePath.withoutRel()
+ return p
+}
+
func (p PhonyPath) ReplaceExtension(ctx PathContext, ext string) OutputPath {
panic("Not implemented")
}
@@ -2095,6 +2147,11 @@
return p
}
+func (p testPath) WithoutRel() Path {
+ p.basePath = p.basePath.withoutRel()
+ return p
+}
+
func (p testPath) String() string {
return p.path
}
diff --git a/android/phony.go b/android/phony.go
index 814a9e3..f8db88d 100644
--- a/android/phony.go
+++ b/android/phony.go
@@ -26,14 +26,20 @@
var phonyMapLock sync.Mutex
-func getPhonyMap(config Config) phonyMap {
+type ModulePhonyInfo struct {
+ Phonies map[string]Paths
+}
+
+var ModulePhonyProvider = blueprint.NewProvider[ModulePhonyInfo]()
+
+func getSingletonPhonyMap(config Config) phonyMap {
return config.Once(phonyMapOnceKey, func() interface{} {
return make(phonyMap)
}).(phonyMap)
}
-func addPhony(config Config, name string, deps ...Path) {
- phonyMap := getPhonyMap(config)
+func addSingletonPhony(config Config, name string, deps ...Path) {
+ phonyMap := getSingletonPhonyMap(config)
phonyMapLock.Lock()
defer phonyMapLock.Unlock()
phonyMap[name] = append(phonyMap[name], deps...)
@@ -47,7 +53,15 @@
var _ SingletonMakeVarsProvider = (*phonySingleton)(nil)
func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
- p.phonyMap = getPhonyMap(ctx.Config())
+ p.phonyMap = getSingletonPhonyMap(ctx.Config())
+ ctx.VisitAllModules(func(m Module) {
+ if info, ok := OtherModuleProvider(ctx, m, ModulePhonyProvider); ok {
+ for k, v := range info.Phonies {
+ p.phonyMap[k] = append(p.phonyMap[k], v...)
+ }
+ }
+ })
+
p.phonyList = SortedKeys(p.phonyMap)
for _, phony := range p.phonyList {
p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 51b86a5..4f04d05 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -61,7 +61,7 @@
type UserSuppliedPrebuiltProperties struct {
// When prefer is set to true the prebuilt will be used instead of any source module with
// a matching name.
- Prefer *bool `android:"arch_variant"`
+ Prefer proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`
// When specified this names a Soong config variable that controls the prefer property.
//
@@ -148,11 +148,7 @@
}
func (p *Prebuilt) ForcePrefer() {
- p.properties.Prefer = proptools.BoolPtr(true)
-}
-
-func (p *Prebuilt) Prefer() bool {
- return proptools.Bool(p.properties.Prefer)
+ p.properties.Prefer = NewSimpleConfigurable(true)
}
// SingleSourcePathFromSupplier invokes the supplied supplier for the current module in the
@@ -248,6 +244,8 @@
p.srcsPropertyName = srcsPropertyName
}
+// InitPrebuiltModule is the same as InitPrebuiltModuleWithSrcSupplier, but uses the
+// provided list of strings property as the source provider.
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
if srcs == nil {
panic(fmt.Errorf("srcs must not be nil"))
@@ -260,6 +258,20 @@
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
}
+// InitConfigurablePrebuiltModule is the same as InitPrebuiltModule, but uses a
+// Configurable list of strings property instead of a regular list of strings.
+func InitConfigurablePrebuiltModule(module PrebuiltInterface, srcs *proptools.Configurable[[]string]) {
+ if srcs == nil {
+ panic(fmt.Errorf("srcs must not be nil"))
+ }
+
+ srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
+ return srcs.GetOrDefault(ctx, nil)
+ }
+
+ InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
+}
+
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
srcPropsValue := reflect.ValueOf(srcProps).Elem()
srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
@@ -347,8 +359,8 @@
//
// This function is for use on dependencies after PrebuiltPostDepsMutator has
// run - any dependency that is registered before that will already reference
-// the right module. This function is only safe to call after all mutators that
-// may call CreateVariations, e.g. in GenerateAndroidBuildActions.
+// 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 !module.IsReplacedByPrebuilt() {
return module
@@ -423,15 +435,7 @@
// The metadata will be used for source vs prebuilts selection
func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
- // If this module is a prebuilt, is enabled and has not been renamed to source then add a
- // dependency onto the source if it is present.
- if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource {
- bmn, _ := m.(baseModuleName)
- name := bmn.BaseModuleName()
- if ctx.OtherModuleReverseDependencyVariantExists(name) {
- ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
- p.properties.SourceExists = true
- }
+ if p := GetEmbeddedPrebuilt(m); p != nil {
// Add a dependency from the prebuilt to the `all_apex_contributions`
// metadata module
// TODO: When all branches contain this singleton module, make this strict
@@ -439,7 +443,16 @@
if ctx.OtherModuleExists("all_apex_contributions") {
ctx.AddDependency(m, AcDepTag, "all_apex_contributions")
}
-
+ if m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource {
+ // If this module is a prebuilt, is enabled and has not been renamed to source then add a
+ // dependency onto the source if it is present.
+ bmn, _ := m.(baseModuleName)
+ name := bmn.BaseModuleName()
+ if ctx.OtherModuleReverseDependencyVariantExists(name) {
+ ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
+ p.properties.SourceExists = true
+ }
+ }
}
}
@@ -668,12 +681,37 @@
return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0
}
+type apexVariationName interface {
+ ApexVariationName() string
+}
+
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool {
+ isMainlinePrebuilt := func(prebuilt Module) bool {
+ apex, ok := prebuilt.(apexVariationName)
+ if !ok {
+ return false
+ }
+ // Prebuilts of aosp apexes in prebuilts/runtime
+ // Used in minimal art branches
+ if prebuilt.base().BaseModuleName() == apex.ApexVariationName() {
+ return false
+ }
+ return InList(apex.ApexVariationName(), ctx.Config().AllMainlineApexNames())
+ }
+
// Use `all_apex_contributions` for source vs prebuilt selection.
psi := PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) {
+ var psiDepTag blueprint.DependencyTag
+ if p := GetEmbeddedPrebuilt(ctx.Module()); p != nil {
+ // This is a prebuilt module, visit all_apex_contributions to get the info
+ psiDepTag = AcDepTag
+ } else {
+ // This is a source module, visit any of its prebuilts to get the info
+ psiDepTag = PrebuiltDepTag
+ }
+ ctx.VisitDirectDepsWithTag(psiDepTag, func(am Module) {
psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
})
@@ -686,6 +724,11 @@
return true
}
+ // If this is a mainline prebuilt, but has not been flagged, hide it.
+ if isMainlinePrebuilt(prebuilt) {
+ return false
+ }
+
// If the baseModuleName could not be found in the metadata module,
// fall back to the existing source vs prebuilt selection.
// TODO: Drop the fallback mechanisms
@@ -707,7 +750,7 @@
}
// TODO: use p.Properties.Name and ctx.ModuleDir to override preference
- return Bool(p.properties.Prefer)
+ return p.properties.Prefer.GetOrDefault(ctx, false)
}
func (p *Prebuilt) SourceExists() bool {
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 6e4fc0c..5e4af0b 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -574,11 +574,7 @@
func TestPrebuiltErrorCannotListBothSourceAndPrebuiltInContributions(t *testing.T) {
selectMainlineModuleContritbutions := GroupFixturePreparers(
- FixtureModifyProductVariables(func(variables FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_apex_contributions",
- }
- }),
+ PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "my_apex_contributions"),
)
testPrebuiltErrorWithFixture(t, `Found duplicate variations of the same module in apex_contributions: foo and prebuilt_foo. Please remove one of these`, `
source {
diff --git a/android/product_config.go b/android/product_config.go
index 20b29a7..ce3acc9 100644
--- a/android/product_config.go
+++ b/android/product_config.go
@@ -14,7 +14,9 @@
package android
-import "github.com/google/blueprint/proptools"
+import (
+ "github.com/google/blueprint/proptools"
+)
func init() {
ctx := InitRegistrationContext
@@ -37,8 +39,10 @@
if targetProduct != "" {
targetProduct += "."
}
- soongVariablesPath := PathForOutput(ctx, "soong."+targetProduct+"variables")
- extraVariablesPath := PathForOutput(ctx, "soong."+targetProduct+"extra.variables")
+
+ coverageSuffix := ctx.Config().CoverageSuffix()
+ soongVariablesPath := PathForOutput(ctx, "soong."+targetProduct+coverageSuffix+"variables")
+ extraVariablesPath := PathForOutput(ctx, "soong."+targetProduct+coverageSuffix+"extra.variables")
rule := NewRuleBuilder(pctx, ctx)
rule.Command().BuiltTool("merge_json").
diff --git a/android/product_config_to_bp.go b/android/product_config_to_bp.go
new file mode 100644
index 0000000..680328f
--- /dev/null
+++ b/android/product_config_to_bp.go
@@ -0,0 +1,35 @@
+// 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
+
+func init() {
+ ctx := InitRegistrationContext
+ ctx.RegisterParallelSingletonType("product_config_to_bp_singleton", productConfigToBpSingletonFactory)
+}
+
+type productConfigToBpSingleton struct{}
+
+func (s *productConfigToBpSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // TODO: update content from make-based product config
+ var content string
+ generatedBp := PathForOutput(ctx, "soong_generated_product_config.bp")
+ WriteFileRule(ctx, generatedBp, content)
+ ctx.Phony("product_config_to_bp", generatedBp)
+}
+
+// productConfigToBpSingleton generates a bp file from make-based product config
+func productConfigToBpSingletonFactory() Singleton {
+ return &productConfigToBpSingleton{}
+}
diff --git a/android/provider.go b/android/provider.go
index 3b9c5d2..5ded4cc 100644
--- a/android/provider.go
+++ b/android/provider.go
@@ -14,6 +14,8 @@
var _ OtherModuleProviderContext = ModuleContext(nil)
var _ OtherModuleProviderContext = BottomUpMutatorContext(nil)
var _ OtherModuleProviderContext = TopDownMutatorContext(nil)
+var _ OtherModuleProviderContext = SingletonContext(nil)
+var _ OtherModuleProviderContext = (*TestContext)(nil)
// 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
@@ -30,6 +32,11 @@
return value.(K), ok
}
+func OtherModuleProviderOrDefault[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) K {
+ value, _ := OtherModuleProvider(ctx, module, provider)
+ return value
+}
+
// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext for use in ModuleProvider.
type ModuleProviderContext interface {
@@ -56,26 +63,6 @@
return value.(K), ok
}
-type SingletonModuleProviderContext interface {
- moduleProvider(blueprint.Module, blueprint.AnyProviderKey) (any, bool)
-}
-
-var _ SingletonModuleProviderContext = SingletonContext(nil)
-var _ SingletonModuleProviderContext = (*TestContext)(nil)
-
-// SingletonModuleProvider wraps blueprint.SingletonModuleProvider to provide a type-safe method to retrieve the value
-// of the given provider from a module using a SingletonContext. If the provider has not been set the first return
-// value will be the zero value of the provider's type, and the second return value will be false. If the provider has
-// been set the second return value will be true.
-func SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
- value, ok := ctx.moduleProvider(module, provider)
- if !ok {
- var k K
- return k, false
- }
- return value.(K), ok
-}
-
// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext for use in SetProvider.
type SetProviderContext interface {
diff --git a/android/register.go b/android/register.go
index eb6a35e..2ce6025 100644
--- a/android/register.go
+++ b/android/register.go
@@ -235,6 +235,7 @@
PreDepsMutators(f RegisterMutatorFunc)
PostDepsMutators(f RegisterMutatorFunc)
+ PostApexMutators(f RegisterMutatorFunc)
FinalDepsMutators(f RegisterMutatorFunc)
}
@@ -326,6 +327,10 @@
PostDepsMutators(f)
}
+func (ctx *initRegistrationContext) PostApexMutators(f RegisterMutatorFunc) {
+ PostApexMutators(f)
+}
+
func (ctx *initRegistrationContext) FinalDepsMutators(f RegisterMutatorFunc) {
FinalDepsMutators(f)
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 8b03124..56de9cd 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -38,6 +38,9 @@
const sboxToolsSubDir = "tools"
const sboxOutDir = sboxSandboxBaseDir + "/" + sboxOutSubDir
+const nsjailToolsSubDir = "tools"
+const nsjailOutDir = "out"
+
// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
// graph.
type RuleBuilder struct {
@@ -59,6 +62,9 @@
sboxManifestPath WritablePath
missingDeps []string
args map[string]string
+ nsjail bool
+ nsjailBasePath WritablePath
+ nsjailImplicits Paths
}
// NewRuleBuilder returns a newly created RuleBuilder.
@@ -165,12 +171,43 @@
if len(r.commands) > 0 {
panic("Sbox() may not be called after Command()")
}
+ if r.nsjail {
+ panic("Sbox() may not be called after Nsjail()")
+ }
r.sbox = true
r.outDir = outputDir
r.sboxManifestPath = manifestPath
return r
}
+// Nsjail marks the rule as needing to be wrapped by nsjail. The outputDir should point to the
+// output directory that nsjail will mount to out/. It should not be written to by any other rule.
+// baseDir should point to a location where nsjail will mount to /nsjail_build_sandbox, which will
+// be the working directory of the command.
+func (r *RuleBuilder) Nsjail(outputDir WritablePath, baseDir WritablePath) *RuleBuilder {
+ if len(r.commands) > 0 {
+ panic("Nsjail() may not be called after Command()")
+ }
+ if r.sbox {
+ panic("Nsjail() may not be called after Sbox()")
+ }
+ r.nsjail = true
+ r.outDir = outputDir
+ r.nsjailBasePath = baseDir
+ return r
+}
+
+// NsjailImplicits adds implicit inputs that are not directly mounted. This is useful when
+// the rule mounts directories, as files within those directories can be globbed and
+// tracked as dependencies with NsjailImplicits().
+func (r *RuleBuilder) NsjailImplicits(inputs Paths) *RuleBuilder {
+ if !r.nsjail {
+ panic("NsjailImplicits() must be called after Nsjail()")
+ }
+ r.nsjailImplicits = append(r.nsjailImplicits, inputs...)
+ return r
+}
+
// SandboxTools enables tool sandboxing for the rule by copying any referenced tools into the
// sandbox.
func (r *RuleBuilder) SandboxTools() *RuleBuilder {
@@ -463,6 +500,8 @@
r.build(name, desc, true)
}
+var sandboxEnvOnceKey = NewOnceKey("sandbox_environment_variables")
+
func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString bool) {
name = ninjaNameEscape(name)
@@ -512,7 +551,73 @@
commandString := strings.Join(commands, " && ")
- if r.sbox {
+ if !r.sbox {
+ // If not using sbox the rule will run the command directly, put the hash of the
+ // list of input files in a comment at the end of the command line to ensure ninja
+ // reruns the rule when the list of input files changes.
+ commandString += " # hash of input list: " + hashSrcFiles(inputs)
+ }
+
+ if r.nsjail {
+ var nsjailCmd strings.Builder
+ nsjailPath := r.ctx.Config().PrebuiltBuildTool(r.ctx, "nsjail")
+ nsjailCmd.WriteString("mkdir -p ")
+ nsjailCmd.WriteString(r.nsjailBasePath.String())
+ nsjailCmd.WriteString(" && ")
+ nsjailCmd.WriteString(nsjailPath.String())
+ nsjailCmd.WriteRune(' ')
+ nsjailCmd.WriteString("-B $PWD/")
+ nsjailCmd.WriteString(r.nsjailBasePath.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox")
+
+ // out is mounted to $(genDir).
+ nsjailCmd.WriteString(" -B $PWD/")
+ nsjailCmd.WriteString(r.outDir.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/out")
+
+ for _, input := range inputs {
+ nsjailCmd.WriteString(" -R $PWD/")
+ nsjailCmd.WriteString(input.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/")
+ nsjailCmd.WriteString(r.nsjailPathForInputRel(input))
+ }
+ for _, tool := range tools {
+ nsjailCmd.WriteString(" -R $PWD/")
+ nsjailCmd.WriteString(tool.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/")
+ nsjailCmd.WriteString(nsjailPathForToolRel(r.ctx, tool))
+ }
+ inputs = append(inputs, tools...)
+ for _, c := range r.commands {
+ for _, tool := range c.packagedTools {
+ nsjailCmd.WriteString(" -R $PWD/")
+ nsjailCmd.WriteString(tool.srcPath.String())
+ nsjailCmd.WriteString(":nsjail_build_sandbox/")
+ nsjailCmd.WriteString(nsjailPathForPackagedToolRel(tool))
+ inputs = append(inputs, tool.srcPath)
+ }
+ }
+
+ // These five directories are necessary to run native host tools like /bin/bash and py3-cmd.
+ nsjailCmd.WriteString(" -R /bin")
+ nsjailCmd.WriteString(" -R /lib")
+ nsjailCmd.WriteString(" -R /lib64")
+ nsjailCmd.WriteString(" -R /dev")
+ nsjailCmd.WriteString(" -R /usr")
+
+ nsjailCmd.WriteString(" -m none:/tmp:tmpfs:size=1073741824") // 1GB, should be enough
+ nsjailCmd.WriteString(" -D nsjail_build_sandbox")
+ nsjailCmd.WriteString(" --disable_rlimits")
+ nsjailCmd.WriteString(" -q")
+ nsjailCmd.WriteString(" -- ")
+ nsjailCmd.WriteString("/bin/bash -c ")
+ nsjailCmd.WriteString(proptools.ShellEscape(commandString))
+
+ commandString = nsjailCmd.String()
+
+ inputs = append(inputs, nsjailPath)
+ inputs = append(inputs, r.nsjailImplicits...)
+ } else if r.sbox {
// If running the command inside sbox, write the rule data out to an sbox
// manifest.textproto.
manifest := sbox_proto.Manifest{}
@@ -554,6 +659,12 @@
To: proto.String(r.sboxPathForInputRel(input)),
})
}
+ for _, input := range r.OrderOnlys() {
+ command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{
+ From: proto.String(input.String()),
+ To: proto.String(r.sboxPathForInputRel(input)),
+ })
+ }
// If using rsp files copy them and their contents into the sbox directory with
// the appropriate path mappings.
@@ -574,6 +685,44 @@
})
}
+ // Only allow the build to access certain environment variables
+ command.DontInheritEnv = proto.Bool(true)
+ command.Env = r.ctx.Config().Once(sandboxEnvOnceKey, func() interface{} {
+ // The list of allowed variables was found by running builds of all
+ // genrules and seeing what failed
+ var result []*sbox_proto.EnvironmentVariable
+ inheritedVars := []string{
+ "PATH",
+ "JAVA_HOME",
+ "TMPDIR",
+ // Allow RBE variables because the art tests invoke RBE manually
+ "RBE_log_dir",
+ "RBE_platform",
+ "RBE_server_address",
+ // TODO: RBE_exec_root is set to the absolute path to the root of the source
+ // tree, which we don't want sandboxed actions to find. Remap it to ".".
+ "RBE_exec_root",
+ }
+ for _, v := range inheritedVars {
+ result = append(result, &sbox_proto.EnvironmentVariable{
+ Name: proto.String(v),
+ State: &sbox_proto.EnvironmentVariable_Inherit{
+ Inherit: true,
+ },
+ })
+ }
+ // Set OUT_DIR to the relative path of the sandboxed out directory.
+ // Otherwise, OUT_DIR will be inherited from the rest of the build,
+ // which will allow scripts to escape the sandbox if OUT_DIR is an
+ // absolute path.
+ result = append(result, &sbox_proto.EnvironmentVariable{
+ Name: proto.String("OUT_DIR"),
+ State: &sbox_proto.EnvironmentVariable_Value{
+ Value: sboxOutSubDir,
+ },
+ })
+ return result
+ }).([]*sbox_proto.EnvironmentVariable)
command.Chdir = proto.Bool(true)
}
@@ -688,11 +837,6 @@
rewrapperCommand := r.rbeParams.NoVarTemplate(r.ctx.Config().RBEWrapper())
commandString = rewrapperCommand + " bash -c '" + strings.ReplaceAll(commandString, `'`, `'\''`) + "'"
}
- } else {
- // If not using sbox the rule will run the command directly, put the hash of the
- // list of input files in a comment at the end of the command line to ensure ninja
- // reruns the rule when the list of input files changes.
- commandString += " # hash of input list: " + hashSrcFiles(inputs)
}
// Ninja doesn't like multiple outputs when depfiles are enabled, move all but the first output to
@@ -823,6 +967,8 @@
rel = filepath.Join(sboxSandboxBaseDir, rel)
}
return rel
+ } else if c.rule.nsjail {
+ return c.rule.nsjailPathForInputRel(path)
}
return path.String()
}
@@ -848,6 +994,10 @@
// Errors will be handled in RuleBuilder.Build where we have a context to report them
rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String())
return filepath.Join(sboxOutDir, rel)
+ } else if c.rule.nsjail {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String())
+ return filepath.Join(nsjailOutDir, rel)
}
return path.String()
}
@@ -899,15 +1049,49 @@
return filepath.Join(sboxToolsSubDir, "out", spec.relPathInPackage)
}
+func nsjailPathForToolRel(ctx BuilderContext, path Path) string {
+ // Errors will be handled in RuleBuilder.Build where we have a context to report them
+ toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "")
+ relOutSoong, isRelOutSoong, _ := maybeRelErr(toolDir.String(), path.String())
+ if isRelOutSoong {
+ // The tool is in the Soong output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
+ return filepath.Join(nsjailToolsSubDir, "out", relOutSoong)
+ }
+ // The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src
+ return filepath.Join(nsjailToolsSubDir, "src", path.String())
+}
+
+func (r *RuleBuilder) nsjailPathForInputRel(path Path) string {
+ rel, isRelSboxOut, _ := maybeRelErr(r.outDir.String(), path.String())
+ if isRelSboxOut {
+ return filepath.Join(nsjailOutDir, rel)
+ }
+ return path.String()
+}
+
+func (r *RuleBuilder) nsjailPathsForInputsRel(paths Paths) []string {
+ ret := make([]string, len(paths))
+ for i, path := range paths {
+ ret[i] = r.nsjailPathForInputRel(path)
+ }
+ return ret
+}
+
+func nsjailPathForPackagedToolRel(spec PackagingSpec) string {
+ return filepath.Join(nsjailToolsSubDir, "out", spec.relPathInPackage)
+}
+
// PathForPackagedTool takes a PackageSpec for a tool and returns the corresponding path for the
// tool after copying it into the sandbox. This can be used on the RuleBuilder command line to
// reference the tool.
func (c *RuleBuilderCommand) PathForPackagedTool(spec PackagingSpec) string {
- if !c.rule.sboxTools {
- panic("PathForPackagedTool() requires SandboxTools()")
+ if c.rule.sboxTools {
+ return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec))
+ } else if c.rule.nsjail {
+ return nsjailPathForPackagedToolRel(spec)
+ } else {
+ panic("PathForPackagedTool() requires SandboxTools() or Nsjail()")
}
-
- return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec))
}
// PathForTool takes a path to a tool, which may be an output file or a source file, and returns
@@ -916,6 +1100,8 @@
func (c *RuleBuilderCommand) PathForTool(path Path) string {
if c.rule.sbox && c.rule.sboxTools {
return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path))
+ } else if c.rule.nsjail {
+ return nsjailPathForToolRel(c.rule.ctx, path)
}
return path.String()
}
@@ -930,6 +1116,12 @@
ret = append(ret, filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path)))
}
return ret
+ } else if c.rule.nsjail {
+ var ret []string
+ for _, path := range paths {
+ ret = append(ret, nsjailPathForToolRel(c.rule.ctx, path))
+ }
+ return ret
}
return paths.Strings()
}
@@ -937,20 +1129,22 @@
// PackagedTool adds the specified tool path to the command line. It can only be used with tool
// sandboxing enabled by SandboxTools(), and will copy the tool into the sandbox.
func (c *RuleBuilderCommand) PackagedTool(spec PackagingSpec) *RuleBuilderCommand {
- if !c.rule.sboxTools {
- panic("PackagedTool() requires SandboxTools()")
- }
-
c.packagedTools = append(c.packagedTools, spec)
- c.Text(sboxPathForPackagedToolRel(spec))
+ if c.rule.sboxTools {
+ c.Text(sboxPathForPackagedToolRel(spec))
+ } else if c.rule.nsjail {
+ c.Text(nsjailPathForPackagedToolRel(spec))
+ } else {
+ panic("PackagedTool() requires SandboxTools() or Nsjail()")
+ }
return c
}
// ImplicitPackagedTool copies the specified tool into the sandbox without modifying the command
// line. It can only be used with tool sandboxing enabled by SandboxTools().
func (c *RuleBuilderCommand) ImplicitPackagedTool(spec PackagingSpec) *RuleBuilderCommand {
- if !c.rule.sboxTools {
- panic("ImplicitPackagedTool() requires SandboxTools()")
+ if !c.rule.sboxTools && !c.rule.nsjail {
+ panic("ImplicitPackagedTool() requires SandboxTools() or Nsjail()")
}
c.packagedTools = append(c.packagedTools, spec)
@@ -960,8 +1154,8 @@
// ImplicitPackagedTools copies the specified tools into the sandbox without modifying the command
// line. It can only be used with tool sandboxing enabled by SandboxTools().
func (c *RuleBuilderCommand) ImplicitPackagedTools(specs []PackagingSpec) *RuleBuilderCommand {
- if !c.rule.sboxTools {
- panic("ImplicitPackagedTools() requires SandboxTools()")
+ if !c.rule.sboxTools && !c.rule.nsjail {
+ panic("ImplicitPackagedTools() requires SandboxTools() or Nsjail()")
}
c.packagedTools = append(c.packagedTools, specs...)
diff --git a/android/sbom.go b/android/sbom.go
index dd2d2fa..2a5499e 100644
--- a/android/sbom.go
+++ b/android/sbom.go
@@ -42,7 +42,9 @@
}
// sbomSingleton is used to generate build actions of generating SBOM of products.
-type sbomSingleton struct{}
+type sbomSingleton struct {
+ sbomFile OutputPath
+}
func sbomSingletonFactory() Singleton {
return &sbomSingleton{}
@@ -77,12 +79,12 @@
implicits = append(implicits, installedFilesStamp)
metadataDb := PathForOutput(ctx, "compliance-metadata", ctx.Config().DeviceProduct(), "compliance-metadata.db")
- sbomFile := PathForOutput(ctx, "sbom", ctx.Config().DeviceProduct(), "sbom.spdx.json")
+ this.sbomFile = PathForOutput(ctx, "sbom", ctx.Config().DeviceProduct(), "sbom.spdx.json")
ctx.Build(pctx, BuildParams{
Rule: genSbomRule,
Input: metadataDb,
Implicits: implicits,
- Output: sbomFile,
+ Output: this.sbomFile,
Args: map[string]string{
"productOut": filepath.Join(ctx.Config().OutDir(), "target", "product", String(prodVars.DeviceName)),
"soongOut": ctx.Config().soongOutDir,
@@ -91,10 +93,19 @@
},
})
- // Phony rule "soong-sbom". "m soong-sbom" to generate product SBOM in Soong.
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Inputs: []Path{sbomFile},
- Output: PathForPhony(ctx, "soong-sbom"),
- })
+ if !ctx.Config().UnbundledBuildApps() {
+ // When building SBOM of products, phony rule "sbom" is for generating product SBOM in Soong.
+ ctx.Build(pctx, BuildParams{
+ Rule: blueprint.Phony,
+ 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.go b/android/sdk.go
index 4bcbe2e..ab9a91c 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -813,7 +813,6 @@
// SdkMemberContext provides access to information common to a specific member.
type SdkMemberContext interface {
-
// SdkModuleContext returns the module context of the sdk common os variant which is creating the
// snapshot.
//
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 01b55d0..a9b88fb 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -93,6 +93,15 @@
}
}
+func ToSdkKind(s string) SdkKind {
+ for kind := SdkNone; kind <= SdkPrivate; kind++ {
+ if s == kind.String() {
+ return kind
+ }
+ }
+ return SdkInvalid
+}
+
func (k SdkKind) DefaultJavaLibraryName() string {
switch k {
case SdkPublic:
diff --git a/android/selects_test.go b/android/selects_test.go
index fc020a4..90d7091 100644
--- a/android/selects_test.go
+++ b/android/selects_test.go
@@ -1009,6 +1009,28 @@
},
expectedError: `variable already set in inherited scope, previous assignment:`,
},
+ {
+ name: "Basic string list postprocessor",
+ bp: `
+my_defaults {
+ name: "defaults_a",
+ my_string_list: ["a", "b", "c"],
+ string_list_postprocessor_add_to_elements: "1",
+}
+my_defaults {
+ name: "defaults_b",
+ my_string_list: ["d", "e", "f"],
+ string_list_postprocessor_add_to_elements: "2",
+}
+my_module_type {
+ name: "foo",
+ defaults: ["defaults_a", "defaults_b"],
+}
+`,
+ provider: selectsTestProvider{
+ my_string_list: &[]string{"d2", "e2", "f2", "a1", "b1", "c1"},
+ },
+ },
}
for _, tc := range testCases {
@@ -1161,9 +1183,15 @@
return m
}
+type selectsMockDefaultsProperties struct {
+ String_list_postprocessor_add_to_elements string
+}
+
type selectsMockModuleDefaults struct {
ModuleBase
DefaultsModuleBase
+ myProperties selectsMockModuleProperties
+ defaultsProperties selectsMockDefaultsProperties
}
func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
@@ -1173,10 +1201,22 @@
module := &selectsMockModuleDefaults{}
module.AddProperties(
- &selectsMockModuleProperties{},
+ &module.myProperties,
+ &module.defaultsProperties,
)
InitDefaultsModule(module)
+ AddLoadHook(module, func(lhc LoadHookContext) {
+ if module.defaultsProperties.String_list_postprocessor_add_to_elements != "" {
+ module.myProperties.My_string_list.AddPostProcessor(func(x []string) []string {
+ for i := range x {
+ x[i] = x[i] + module.defaultsProperties.String_list_postprocessor_add_to_elements
+ }
+ return x
+ })
+ }
+ })
+
return module
}
diff --git a/android/singleton.go b/android/singleton.go
index d364384..913bf6a 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -35,7 +35,7 @@
// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
ModuleVariantsFromName(referer Module, name string) []Module
- moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+ otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
ModuleErrorf(module blueprint.Module, format string, args ...interface{})
Errorf(format string, args ...interface{})
@@ -90,6 +90,10 @@
// OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})
+
+ // HasMutatorFinished returns true if the given mutator has finished running.
+ // It will panic if given an invalid mutator name.
+ HasMutatorFinished(mutatorName string) bool
}
type singletonAdaptor struct {
@@ -177,7 +181,7 @@
}
func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
- addPhony(s.Config(), name, deps...)
+ addSingletonPhony(s.Config(), name, deps...)
}
func (s *singletonContextAdaptor) SetOutDir(pctx PackageContext, value string) {
@@ -279,10 +283,14 @@
return result
}
-func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+func (s *singletonContextAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
return s.SingletonContext.ModuleProvider(module, provider)
}
func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) {
s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args...)
}
+
+func (s *singletonContextAdaptor) HasMutatorFinished(mutatorName string) bool {
+ return s.blueprintSingletonContext().HasMutatorFinished(mutatorName)
+}
diff --git a/android/singleton_module.go b/android/singleton_module.go
index 2351738..43028e8 100644
--- a/android/singleton_module.go
+++ b/android/singleton_module.go
@@ -68,7 +68,7 @@
func (smb *SingletonModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
smb.lock.Lock()
if smb.variant != "" {
- ctx.ModuleErrorf("GenerateAndroidBuildActions already called for variant %q, SingletonModules can only have one variant", smb.variant)
+ ctx.ModuleErrorf("GenerateAndroidBuildActions already called for variant %q, SingletonModules can only have one variant", smb.variant)
}
smb.variant = ctx.ModuleSubDir()
smb.lock.Unlock()
diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go
index 3b1bf39..3b8c6b2 100644
--- a/android/singleton_module_test.go
+++ b/android/singleton_module_test.go
@@ -96,12 +96,6 @@
}
}
-func testVariantSingletonModuleMutator(ctx BottomUpMutatorContext) {
- if _, ok := ctx.Module().(*testSingletonModule); ok {
- ctx.CreateVariations("a", "b")
- }
-}
-
func TestVariantSingletonModule(t *testing.T) {
if testing.Short() {
t.Skip("test fails with data race enabled")
@@ -116,7 +110,11 @@
prepareForSingletonModuleTest,
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("test_singleton_module_mutator", testVariantSingletonModuleMutator)
+ ctx.Transition("test_singleton_module_mutator", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
+ })
})
}),
).
diff --git a/android/team_proto/Android.bp b/android/team_proto/Android.bp
index 7e2a4c1..5faaaf1 100644
--- a/android/team_proto/Android.bp
+++ b/android/team_proto/Android.bp
@@ -40,4 +40,8 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//tools/asuite/team_build_scripts",
+ ],
}
diff --git a/android/test_suites.go b/android/test_suites.go
index ff75f26..936d2b6 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -47,7 +47,8 @@
files[testSuite] = make(map[string]InstallPaths)
}
name := ctx.ModuleName(m)
- files[testSuite][name] = append(files[testSuite][name], tsm.FilesToInstall()...)
+ files[testSuite][name] = append(files[testSuite][name],
+ OtherModuleProviderOrDefault(ctx, tsm, InstallFilesProvider).InstallFiles...)
}
}
})
diff --git a/android/testing.go b/android/testing.go
index e39a1a7..7440869 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -126,6 +126,10 @@
ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
})
+var PrepareForTestVintfFragmentModules = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ registerVintfFragmentComponents(ctx)
+})
+
// Test fixture preparer that will register most java build components.
//
// Singletons and mutators should only be added here if they are needed for a majority of java
@@ -149,6 +153,7 @@
PrepareForTestWithPackageModule,
PrepareForTestWithPrebuilts,
PrepareForTestWithVisibility,
+ PrepareForTestVintfFragmentModules,
)
// Prepares an integration test with all build components from the android package.
@@ -174,6 +179,16 @@
config.TestAllowNonExistentPaths = false
})
+// PrepareForTestWithBuildFlag returns a FixturePreparer that sets the given flag to the given value.
+func PrepareForTestWithBuildFlag(flag, value string) FixturePreparer {
+ return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ if variables.BuildFlags == nil {
+ variables.BuildFlags = make(map[string]string)
+ }
+ variables.BuildFlags[flag] = value
+ })
+}
+
func NewTestArchContext(config Config) *TestContext {
ctx := NewTestContext(config)
ctx.preDeps = append(ctx.preDeps, registerArchMutator)
@@ -182,8 +197,8 @@
type TestContext struct {
*Context
- preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
- NameResolver *NameResolver
+ preArch, preDeps, postDeps, postApex, finalDeps []RegisterMutatorFunc
+ NameResolver *NameResolver
// The list of singletons registered for the test.
singletons sortableComponents
@@ -202,7 +217,7 @@
ctx.PreArchMutators(f)
}
-func (ctx *TestContext) moduleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
+func (ctx *TestContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
return ctx.Context.ModuleProvider(m, p)
}
@@ -214,13 +229,17 @@
ctx.postDeps = append(ctx.postDeps, f)
}
+func (ctx *TestContext) PostApexMutators(f RegisterMutatorFunc) {
+ ctx.postApex = append(ctx.postApex, f)
+}
+
func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) {
ctx.finalDeps = append(ctx.finalDeps, f)
}
func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext {
return NewOtherModuleProviderAdaptor(func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
- return ctx.moduleProvider(module, provider)
+ return ctx.otherModuleProvider(module, provider)
})
}
@@ -434,7 +453,7 @@
func (ctx *TestContext) Register() {
globalOrder := globallyRegisteredComponentsOrder()
- mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+ mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.postApex, ctx.finalDeps)
// Ensure that the mutators used in the test are in the same order as they are used at runtime.
globalOrder.mutatorOrder.enforceOrdering(mutators)
mutators.registerAll(ctx.Context)
@@ -822,15 +841,15 @@
// containing at most one instance of the temporary build directory at the start of the path while
// this assumes that there can be any number at any position.
func normalizeStringRelativeToTop(config Config, s string) string {
- // The soongOutDir usually looks something like: /tmp/testFoo2345/001
+ // The outDir usually looks something like: /tmp/testFoo2345/001
//
- // Replace any usage of the soongOutDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
+ // Replace any usage of the outDir with out/soong, e.g. replace "/tmp/testFoo2345/001" with
// "out/soong".
outSoongDir := filepath.Clean(config.soongOutDir)
re := regexp.MustCompile(`\Q` + outSoongDir + `\E\b`)
s = re.ReplaceAllString(s, "out/soong")
- // Replace any usage of the soongOutDir/.. with out, e.g. replace "/tmp/testFoo2345" with
+ // Replace any usage of the outDir/.. with out, e.g. replace "/tmp/testFoo2345" with
// "out". This must come after the previous replacement otherwise this would replace
// "/tmp/testFoo2345/001" with "out/001" instead of "out/soong".
outDir := filepath.Dir(outSoongDir)
@@ -1023,8 +1042,8 @@
// Exits the test immediately if there is an error and
// otherwise returns the result of calling Paths.RelativeToTop
// on the returned Paths.
-func (m TestingModule) OutputFiles(t *testing.T, tag string) Paths {
- outputFiles := m.Module().base().outputFiles
+func (m TestingModule) OutputFiles(ctx *TestContext, t *testing.T, tag string) Paths {
+ outputFiles := OtherModuleProviderOrDefault(ctx.OtherModuleProviderAdaptor(), m.Module(), OutputFilesProvider)
if tag == "" && outputFiles.DefaultOutputFiles != nil {
return outputFiles.DefaultOutputFiles.RelativeToTop()
} else if taggedOutputFiles, hasTag := outputFiles.TaggedOutputFiles[tag]; hasTag {
@@ -1234,8 +1253,14 @@
}
if isRel {
- // The path is in the soong out dir so indicate that in the relative path.
- return filepath.Join("out/soong", rel)
+ if strings.HasSuffix(soongOutDir, testOutSoongSubDir) {
+ // The path is in the soong out dir so indicate that in the relative path.
+ return filepath.Join(TestOutSoongDir, rel)
+ } else {
+ // Handle the PathForArbitraryOutput case
+ return filepath.Join(testOutDir, rel)
+
+ }
}
// Check to see if the path is relative to the top level out dir.
@@ -1305,7 +1330,15 @@
return ctx.ctx.Config()
}
-func PanickingConfigAndErrorContext(ctx *TestContext) ConfigAndErrorContext {
+func (ctx *panickingConfigAndErrorContext) HasMutatorFinished(mutatorName string) bool {
+ return ctx.ctx.HasMutatorFinished(mutatorName)
+}
+
+func (ctx *panickingConfigAndErrorContext) otherModuleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
+ return ctx.ctx.otherModuleProvider(m, p)
+}
+
+func PanickingConfigAndErrorContext(ctx *TestContext) ConfigurableEvaluatorContext {
return &panickingConfigAndErrorContext{
ctx: ctx,
}
diff --git a/android/updatable_modules.go b/android/updatable_modules.go
deleted file mode 100644
index dd7dc2c..0000000
--- a/android/updatable_modules.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-// This file contains branch specific constants. They are stored in a separate
-// file to minimise the potential of merge conflicts between branches when
-// the code from the package is changed.
-
-// The default manifest version for all the modules on this branch.
-// This version code will be used only if there is no version field in the
-// module's apex_manifest.json. Release branches have their version injected
-// into apex_manifest.json by the tooling and will not use the version set
-// here. Developers can also set the version field locally in the
-// apex_manifest.json to build a module with a specific version.
-//
-// The value follows the schema from go/mainline-version-codes, and is chosen
-// based on the branch such that the builds from testing and development
-// branches will have a version higher than the prebuilts.
-// Versions per branch:
-// * x-dev - xx0090000 (where xx is the branch SDK level)
-// * AOSP - xx9990000
-// * x-mainline-prod - xx9990000
-// * master - 990090000
-const DefaultUpdatableModuleVersion = "350090000"
diff --git a/android/util.go b/android/util.go
index 3c0af2f..2d269b7 100644
--- a/android/util.go
+++ b/android/util.go
@@ -177,6 +177,41 @@
return m
}
+// PrettyConcat returns the formatted concatenated string suitable for displaying user-facing
+// messages.
+func PrettyConcat(list []string, quote bool, lastSep string) string {
+ if len(list) == 0 {
+ return ""
+ }
+
+ quoteStr := func(v string) string {
+ if !quote {
+ return v
+ }
+ return fmt.Sprintf("%q", v)
+ }
+
+ if len(list) == 1 {
+ return quoteStr(list[0])
+ }
+
+ var sb strings.Builder
+ for i, val := range list {
+ if i > 0 {
+ sb.WriteString(", ")
+ }
+ if i == len(list)-1 {
+ sb.WriteString(lastSep)
+ if lastSep != "" {
+ sb.WriteString(" ")
+ }
+ }
+ sb.WriteString(quoteStr(val))
+ }
+
+ return sb.String()
+}
+
// 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
// that are in l1 but not l2, and l2 but not l1.
diff --git a/android/util_test.go b/android/util_test.go
index 6537d69..b76ffcf 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -867,3 +867,51 @@
})
}
}
+
+var prettyConcatTestCases = []struct {
+ name string
+ list []string
+ quote bool
+ lastSeparator string
+ expected string
+}{
+ {
+ name: "empty",
+ list: []string{},
+ quote: false,
+ lastSeparator: "and",
+ expected: ``,
+ },
+ {
+ name: "single",
+ list: []string{"a"},
+ quote: true,
+ lastSeparator: "and",
+ expected: `"a"`,
+ },
+ {
+ name: "with separator",
+ list: []string{"a", "b", "c"},
+ quote: true,
+ lastSeparator: "or",
+ expected: `"a", "b", or "c"`,
+ },
+ {
+ name: "without separator",
+ list: []string{"a", "b", "c"},
+ quote: false,
+ lastSeparator: "",
+ expected: `a, b, c`,
+ },
+}
+
+func TestPrettyConcat(t *testing.T) {
+ for _, testCase := range prettyConcatTestCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ concatString := PrettyConcat(testCase.list, testCase.quote, testCase.lastSeparator)
+ if !reflect.DeepEqual(concatString, testCase.expected) {
+ t.Errorf("expected %#v, got %#v", testCase.expected, concatString)
+ }
+ })
+ }
+}
diff --git a/android/variable.go b/android/variable.go
index df0e59c..1aaa70a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -121,6 +121,7 @@
// are used for dogfooding and performance testing, and should be as similar to user builds
// as possible.
Debuggable struct {
+ Apk *string
Cflags []string
Cppflags []string
Init_rc []string
@@ -187,10 +188,10 @@
// release_aidl_use_unfrozen is "true" when a device can
// use the unfrozen versions of AIDL interfaces.
Release_aidl_use_unfrozen struct {
- Cflags []string
- Cmd *string
- Required []string
- Vintf_fragments []string
+ Cflags []string
+ Cmd *string
+ Required []string
+ Vintf_fragment_modules []string
}
} `android:"arch_variant"`
}
@@ -380,6 +381,7 @@
SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
BoardSepolicyM4Defs []string `json:",omitempty"`
+ BoardPlatform *string `json:",omitempty"`
BoardSepolicyVers *string `json:",omitempty"`
PlatformSepolicyVersion *string `json:",omitempty"`
@@ -421,10 +423,10 @@
TargetFSConfigGen []string `json:",omitempty"`
- EnforceProductPartitionInterface *bool `json:",omitempty"`
+ UseSoongSystemImage *bool `json:",omitempty"`
+ ProductSoongDefinedSystemImage *string `json:",omitempty"`
- EnforceInterPartitionJavaSdkLibrary *bool `json:",omitempty"`
- InterPartitionJavaLibraryAllowList []string `json:",omitempty"`
+ EnforceProductPartitionInterface *bool `json:",omitempty"`
BoardUsesRecoveryAsBoot *bool `json:",omitempty"`
@@ -444,7 +446,6 @@
GenruleSandboxing *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"`
- BuildBrokenUsesSoongPython2Modules bool `json:",omitempty"`
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
BuildBrokenIncorrectPartitionImages bool `json:",omitempty"`
BuildBrokenInputDirModules []string `json:",omitempty"`
@@ -507,6 +508,20 @@
OemProperties []string `json:",omitempty"`
ArtTargetIncludeDebugBuild *bool `json:",omitempty"`
+
+ SystemPropFiles []string `json:",omitempty"`
+ SystemExtPropFiles []string `json:",omitempty"`
+ ProductPropFiles []string `json:",omitempty"`
+ OdmPropFiles []string `json:",omitempty"`
+
+ EnableUffdGc *string `json:",omitempty"`
+
+ BoardAvbEnable *bool `json:",omitempty"`
+ BoardAvbSystemAddHashtreeFooterArgs []string `json:",omitempty"`
+ DeviceFrameworkCompatibilityMatrixFile []string `json:",omitempty"`
+ DeviceProductCompatibilityMatrixFile []string `json:",omitempty"`
+
+ PartitionVarsForSoongMigrationOnlyDoNotUse PartitionVariables
}
type PartitionQualifiedVariablesType struct {
@@ -563,7 +578,8 @@
BoardAvbEnable bool `json:",omitempty"`
- ProductPackages []string `json:",omitempty"`
+ ProductPackages []string `json:",omitempty"`
+ ProductPackagesDebug []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/android/variable_test.go b/android/variable_test.go
index 928bca6..73dc052 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -199,9 +199,7 @@
ctx.RegisterModuleType("module3", testProductVariableModuleFactoryFactory(&struct {
Foo []string
}{}))
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("variable", VariableMutator).Parallel()
- })
+ registerVariableBuildComponents(ctx)
}),
FixtureWithRootAndroidBp(bp),
).RunTest(t)
@@ -210,14 +208,14 @@
var testProductVariableDefaultsProperties = struct {
Product_variables struct {
Eng struct {
- Foo []string
+ Foo []string `android:"arch_variant"`
Bar []string
- }
- }
+ } `android:"arch_variant"`
+ } `android:"arch_variant"`
}{}
type productVariablesDefaultsTestProperties struct {
- Foo []string
+ Foo []string `android:"arch_variant"`
}
type productVariablesDefaultsTestProperties2 struct {
@@ -242,7 +240,7 @@
module := &productVariablesDefaultsTestModule{}
module.AddProperties(&module.properties)
module.variableProperties = testProductVariableDefaultsProperties
- InitAndroidModule(module)
+ InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
InitDefaultableModule(module)
return module
}
@@ -324,3 +322,46 @@
})
}
}
+
+// Test a defaults module that supports more product variable properties than the target module.
+func TestProductVariablesArch(t *testing.T) {
+ bp := `
+ test {
+ name: "foo",
+ arch: {
+ arm: {
+ product_variables: {
+ eng: {
+ foo: ["arm"],
+ },
+ },
+ },
+ arm64: {
+ product_variables: {
+ eng: {
+ foo: ["arm64"],
+ },
+ },
+ },
+ },
+ foo: ["module"],
+ }
+ `
+
+ result := GroupFixturePreparers(
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.Eng = boolPtr(true)
+ }),
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithVariables,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*productVariablesDefaultsTestModule)
+
+ want := []string{"module", "arm64"}
+ AssertDeepEquals(t, "foo", want, foo.properties.Foo)
+}
diff --git a/android/vintf_fragment.go b/android/vintf_fragment.go
new file mode 100644
index 0000000..329eac9
--- /dev/null
+++ b/android/vintf_fragment.go
@@ -0,0 +1,84 @@
+// 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
+
+type vintfFragmentProperties struct {
+ // Vintf fragment XML file.
+ Src string `android:"path"`
+}
+
+type vintfFragmentModule struct {
+ ModuleBase
+
+ properties vintfFragmentProperties
+
+ installDirPath InstallPath
+ outputFilePath OutputPath
+}
+
+func init() {
+ registerVintfFragmentComponents(InitRegistrationContext)
+}
+
+func registerVintfFragmentComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("vintf_fragment", vintfLibraryFactory)
+}
+
+// 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.AddProperties(
+ &m.properties,
+ )
+ InitAndroidArchModule(m, DeviceSupported, MultilibFirst)
+
+ return m
+}
+
+func (m *vintfFragmentModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ builder := NewRuleBuilder(pctx, ctx)
+ srcVintfFragment := PathForModuleSrc(ctx, m.properties.Src)
+ processedVintfFragment := PathForModuleOut(ctx, srcVintfFragment.Base())
+
+ // Process vintf fragment source file with assemble_vintf tool
+ builder.Command().
+ Flag("VINTF_IGNORE_TARGET_FCM_VERSION=true").
+ BuiltTool("assemble_vintf").
+ FlagWithInput("-i ", srcVintfFragment).
+ FlagWithOutput("-o ", processedVintfFragment)
+
+ builder.Build("assemble_vintf", "Process vintf fragment "+processedVintfFragment.String())
+
+ m.installDirPath = PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+ m.outputFilePath = processedVintfFragment.OutputPath
+
+ ctx.InstallFile(m.installDirPath, processedVintfFragment.Base(), processedVintfFragment)
+}
+
+// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files
+func (m *vintfFragmentModule) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: OptionalPathForPath(m.outputFilePath),
+ ExtraEntries: []AndroidMkExtraEntriesFunc{
+ func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", m.installDirPath.String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", m.outputFilePath.Base())
+ },
+ },
+ }}
+}
diff --git a/android/vintf_fragment_test.go b/android/vintf_fragment_test.go
new file mode 100644
index 0000000..8be534c
--- /dev/null
+++ b/android/vintf_fragment_test.go
@@ -0,0 +1,36 @@
+// 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"
+ "testing"
+)
+
+func TestVintfManifestBuildAction(t *testing.T) {
+ bp := `
+ vintf_fragment {
+ name: "test_vintf_fragment",
+ src: "test_vintf_file",
+ }
+ `
+
+ testResult := PrepareForTestWithAndroidBuildComponents.RunTestWithBp(t, bp)
+
+ vintfFragmentBuild := testResult.TestContext.ModuleForTests("test_vintf_fragment", "android_arm64_armv8-a").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)
+ }
+}
diff --git a/android/visibility.go b/android/visibility.go
index 89c0adc..61f2200 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -283,7 +283,7 @@
// This must be registered after the deps have been resolved.
func RegisterVisibilityRuleEnforcer(ctx RegisterMutatorsContext) {
- ctx.TopDown("visibilityRuleEnforcer", visibilityRuleEnforcer).Parallel()
+ ctx.BottomUp("visibilityRuleEnforcer", visibilityRuleEnforcer).Parallel()
}
// Checks the per-module visibility rule lists before defaults expansion.
@@ -507,7 +507,7 @@
return true, pkg, name
}
-func visibilityRuleEnforcer(ctx TopDownMutatorContext) {
+func visibilityRuleEnforcer(ctx BottomUpMutatorContext) {
qualified := createVisibilityModuleReference(ctx.ModuleName(), ctx.ModuleDir(), ctx.Module())
// Visit all the dependencies making sure that this module has access to them all.
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index 373e883..a2486fd 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -46,6 +46,9 @@
outputBaseName string
outputFile android.OptionalPath
+
+ // TODO(b/357908583): Temp field, remove this once we support Android Mk providers
+ installFile android.InstallPath
}
type remapProperties struct {
@@ -234,14 +237,18 @@
s.outputBaseName = name
s.outputFile = android.OptionalPathForPath(outputZipFile)
- ctx.InstallFile(android.PathForModuleInstall(ctx, "sdk-repo"), name+".zip", outputZipFile)
+ installPath := android.PathForModuleInstall(ctx, "sdk-repo")
+ name = name + ".zip"
+ ctx.InstallFile(installPath, name, outputZipFile)
+ // TODO(b/357908583): Temp field, remove this once we support Android Mk providers
+ s.installFile = installPath.Join(ctx, name)
}
func (s *sdkRepoHost) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
fmt.Fprintln(w, ".PHONY:", name, "sdk_repo", "sdk-repo-"+name)
- fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", strings.Join(s.FilesToInstall().Strings(), " "))
+ fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", s.installFile.String())
fmt.Fprintf(w, "$(call dist-for-goals,sdk_repo sdk-repo-%s,%s:%s-FILE_NAME_TAG_PLACEHOLDER.zip)\n\n", s.BaseModuleName(), s.outputFile.String(), s.outputBaseName)
},
diff --git a/androidmk/parser/ast.go b/androidmk/parser/ast.go
index d5d1354..c3d198f 100644
--- a/androidmk/parser/ast.go
+++ b/androidmk/parser/ast.go
@@ -84,6 +84,7 @@
Prerequisites *MakeString
RecipePos Pos
Recipe string
+ RecipeEndPos Pos
}
func (x *Rule) Dump() string {
@@ -95,7 +96,7 @@
}
func (x *Rule) Pos() Pos { return x.Target.Pos() }
-func (x *Rule) End() Pos { return Pos(int(x.RecipePos) + len(x.Recipe)) }
+func (x *Rule) End() Pos { return x.RecipeEndPos }
type Variable struct {
Name *MakeString
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index 8a20bb0..f2477db 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -448,6 +448,7 @@
Prerequisites: prerequisites,
Recipe: recipe,
RecipePos: recipePos,
+ RecipeEndPos: p.pos(),
})
}
}
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
index fb03c23..e238f8b 100644
--- a/androidmk/parser/parser_test.go
+++ b/androidmk/parser/parser_test.go
@@ -124,3 +124,25 @@
})
}
}
+
+func TestRuleEnd(t *testing.T) {
+ name := "ruleEndTest"
+ in := `all:
+ifeq (A, A)
+ echo foo
+ echo foo
+ echo foo
+ echo foo
+endif
+ echo bar
+`
+ p := NewParser(name, bytes.NewBufferString(in))
+ got, errs := p.Parse()
+ if len(errs) != 0 {
+ t.Fatalf("Unexpected errors while parsing: %v", errs)
+ }
+
+ if got[0].End() < got[len(got) -1].Pos() {
+ t.Errorf("Rule's end (%d) is smaller than directive that inside of rule's start (%v)\n", got[0].End(), got[len(got) -1].Pos())
+ }
+}
diff --git a/apex/Android.bp b/apex/Android.bp
index 17fdfc3..4848513 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -15,7 +15,6 @@
"soong-cc",
"soong-filesystem",
"soong-java",
- "soong-multitree",
"soong-provenance",
"soong-python",
"soong-rust",
@@ -43,4 +42,6 @@
"systemserver_classpath_fragment_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/apex/aconfig_test.go b/apex/aconfig_test.go
index 14c0b63..bb811f5 100644
--- a/apex/aconfig_test.go
+++ b/apex/aconfig_test.go
@@ -74,6 +74,8 @@
apex_available: [
"myapex",
],
+ sdk_version: "none",
+ system_modules: "none",
}`,
},
{
@@ -122,6 +124,8 @@
apex_available: [
"myapex",
],
+ sdk_version: "none",
+ system_modules: "none",
}`,
},
{
@@ -345,6 +349,8 @@
apex_available: [
"myapex",
],
+ sdk_version: "none",
+ system_modules: "none",
}`,
expectedError: `.*my_java_library_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
@@ -392,6 +398,8 @@
apex_available: [
"myapex",
],
+ sdk_version: "none",
+ system_modules: "none",
}`,
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
@@ -693,6 +701,8 @@
apex_available: [
"myapex",
],
+ sdk_version: "none",
+ system_modules: "none",
}`,
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
@@ -769,6 +779,8 @@
apex_available: [
"myapex",
],
+ sdk_version: "none",
+ system_modules: "none",
}`,
},
}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 4112108..933682a 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -136,6 +136,11 @@
fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", filepath.Join(modulePath, fi.stem()))
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", fi.builtFile.String()+":"+filepath.Join(modulePath, fi.stem()))
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
+ if fi.checkbuildTarget != nil {
+ fmt.Fprintln(w, "LOCAL_CHECKED_MODULE :=", fi.checkbuildTarget.String())
+ } else {
+ fmt.Fprintln(w, "LOCAL_CHECKED_MODULE :=", fi.builtFile.String())
+ }
fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.nameInMake())
if fi.module != nil {
// This apexFile's module comes from Soong
diff --git a/apex/apex.go b/apex/apex.go
index 4c36458..d7dc6d7 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -32,7 +32,6 @@
prebuilt_etc "android/soong/etc"
"android/soong/filesystem"
"android/soong/java"
- "android/soong/multitree"
"android/soong/rust"
"android/soong/sh"
)
@@ -50,17 +49,11 @@
ctx.RegisterModuleType("override_apex", OverrideApexFactory)
ctx.RegisterModuleType("apex_set", apexSetFactory)
- ctx.PreArchMutators(registerPreArchMutators)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
}
-func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel()
-}
-
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
}
@@ -75,8 +68,6 @@
ctx.Transition("apex", &apexTransitionMutator{})
ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
- // Register after apex_info mutator so that it can use ApexVariationName
- ctx.TopDown("apex_strict_updatability_lint", apexStrictUpdatibilityLintMutator).Parallel()
}
type apexBundleProperties struct {
@@ -213,6 +204,50 @@
type ApexNativeDependencies struct {
// List of native libraries that are embedded inside this APEX.
+ Native_shared_libs proptools.Configurable[[]string]
+
+ // List of JNI libraries that are embedded inside this APEX.
+ Jni_libs proptools.Configurable[[]string]
+
+ // List of rust dyn libraries that are embedded inside this APEX.
+ Rust_dyn_libs []string
+
+ // List of native executables that are embedded inside this APEX.
+ Binaries proptools.Configurable[[]string]
+
+ // List of native tests that are embedded inside this APEX.
+ Tests []string
+
+ // List of filesystem images that are embedded inside this APEX bundle.
+ Filesystems []string
+
+ // List of prebuilt_etcs that are embedded inside this APEX bundle.
+ Prebuilts proptools.Configurable[[]string]
+
+ // List of native libraries to exclude from this APEX.
+ Exclude_native_shared_libs []string
+
+ // List of JNI libraries to exclude from this APEX.
+ Exclude_jni_libs []string
+
+ // List of rust dyn libraries to exclude from this APEX.
+ Exclude_rust_dyn_libs []string
+
+ // List of native executables to exclude from this APEX.
+ Exclude_binaries []string
+
+ // List of native tests to exclude from this APEX.
+ Exclude_tests []string
+
+ // List of filesystem images to exclude from this APEX bundle.
+ Exclude_filesystems []string
+
+ // List of prebuilt_etcs to exclude from this APEX bundle.
+ Exclude_prebuilts []string
+}
+
+type ResolvedApexNativeDependencies struct {
+ // List of native libraries that are embedded inside this APEX.
Native_shared_libs []string
// List of JNI libraries that are embedded inside this APEX.
@@ -222,8 +257,7 @@
Rust_dyn_libs []string
// List of native executables that are embedded inside this APEX.
- Binaries proptools.Configurable[[]string]
- ResolvedBinaries []string `blueprint:"mutated"`
+ Binaries []string
// List of native tests that are embedded inside this APEX.
Tests []string
@@ -232,8 +266,7 @@
Filesystems []string
// List of prebuilt_etcs that are embedded inside this APEX bundle.
- Prebuilts proptools.Configurable[[]string]
- ResolvedPrebuilts []string `blueprint:"mutated"`
+ Prebuilts []string
// List of native libraries to exclude from this APEX.
Exclude_native_shared_libs []string
@@ -258,14 +291,14 @@
}
// Merge combines another ApexNativeDependencies into this one
-func (a *ApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
- a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
- a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
+func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
+ a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs.GetOrDefault(ctx, nil)...)
+ a.Jni_libs = append(a.Jni_libs, b.Jni_libs.GetOrDefault(ctx, nil)...)
a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
- a.ResolvedBinaries = append(a.ResolvedBinaries, b.Binaries.GetOrDefault(ctx.Module().ConfigurableEvaluator(ctx), nil)...)
+ a.Binaries = append(a.Binaries, b.Binaries.GetOrDefault(ctx, nil)...)
a.Tests = append(a.Tests, b.Tests...)
a.Filesystems = append(a.Filesystems, b.Filesystems...)
- a.ResolvedPrebuilts = append(a.ResolvedPrebuilts, b.Prebuilts.GetOrDefault(ctx.Module().ConfigurableEvaluator(ctx), nil)...)
+ a.Prebuilts = append(a.Prebuilts, b.Prebuilts.GetOrDefault(ctx, nil)...)
a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
@@ -362,7 +395,7 @@
// Apex Container package name. Override value for attribute package:name in
// AndroidManifest.xml
- Package_name string
+ Package_name proptools.Configurable[string]
// A txt file containing list of files that are allowed to be included in this APEX.
Allowed_files *string `android:"path"`
@@ -396,7 +429,6 @@
android.ModuleBase
android.DefaultableModuleBase
android.OverridableModuleBase
- multitree.ExportableModuleBase
// Properties
properties apexBundleProperties
@@ -535,6 +567,8 @@
customStem string
symlinks []string // additional symlinks
+ checkbuildTarget android.Path
+
// 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>]
@@ -547,7 +581,7 @@
dataPaths []android.DataPath // becomes LOCAL_TEST_DATA
jacocoReportClassesFile android.Path // only for javalibs and apps
- lintDepSets java.LintDepSets // only for javalibs and apps
+ lintInfo *java.LintInfo // only for javalibs and apps
certificate java.Certificate // only for apps
overriddenPackageName string // only for apps
@@ -570,6 +604,9 @@
module: module,
}
if module != nil {
+ if installFilesInfo, ok := android.OtherModuleProvider(ctx, module, android.InstallFilesProvider); ok {
+ ret.checkbuildTarget = installFilesInfo.CheckbuildTarget
+ }
ret.moduleDir = ctx.OtherModuleDir(module)
ret.partition = module.PartitionTag(ctx.DeviceConfig())
ret.requiredModuleNames = module.RequiredModuleNames(ctx)
@@ -657,6 +694,8 @@
// If not-nil and an APEX is a member of an SDK then dependencies of that APEX with this tag will
// also be added as exported members of that SDK.
memberType android.SdkMemberType
+
+ installable bool
}
func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
@@ -675,18 +714,23 @@
return !d.sourceOnly
}
+func (d *dependencyTag) InstallDepNeeded() bool {
+ return d.installable
+}
+
var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{}
var _ android.SdkMemberDependencyTag = &dependencyTag{}
var (
- androidAppTag = &dependencyTag{name: "androidApp", payload: true}
- bpfTag = &dependencyTag{name: "bpf", payload: true}
- certificateTag = &dependencyTag{name: "certificate"}
- dclaTag = &dependencyTag{name: "dcla"}
- executableTag = &dependencyTag{name: "executable", payload: true}
- fsTag = &dependencyTag{name: "filesystem", payload: true}
- bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType}
- sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType}
+ androidAppTag = &dependencyTag{name: "androidApp", payload: true}
+ bpfTag = &dependencyTag{name: "bpf", payload: true}
+ certificateTag = &dependencyTag{name: "certificate"}
+ dclaTag = &dependencyTag{name: "dcla"}
+ executableTag = &dependencyTag{name: "executable", payload: true}
+ fsTag = &dependencyTag{name: "filesystem", payload: true}
+ bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType}
+ // The dexpreopt artifacts of apex system server jars are installed onto system image.
+ sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType, installable: true}
compatConfigTag = &dependencyTag{name: "compatConfig", payload: true, sourceOnly: true, memberType: java.CompatConfigSdkMemberType}
javaLibTag = &dependencyTag{name: "javaLib", payload: true}
jniLibTag = &dependencyTag{name: "jniLib", payload: true}
@@ -700,7 +744,7 @@
)
// TODO(jiyong): shorten this function signature
-func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ApexNativeDependencies, target android.Target, imageVariation string) {
+func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ResolvedApexNativeDependencies, target android.Target, imageVariation string) {
binVariations := target.Variations()
libVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
rustLibVariations := append(
@@ -718,7 +762,7 @@
// this module. This is required since arch variant of an APEX bundle is 'common' but it is
// 'arm' or 'arm64' for native shared libs.
ctx.AddFarVariationDependencies(binVariations, executableTag,
- android.RemoveListFromList(nativeModules.ResolvedBinaries, nativeModules.Exclude_binaries)...)
+ android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
ctx.AddFarVariationDependencies(binVariations, testTag,
android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
ctx.AddFarVariationDependencies(libVariations, jniLibTag,
@@ -730,7 +774,7 @@
ctx.AddFarVariationDependencies(target.Variations(), fsTag,
android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
ctx.AddFarVariationDependencies(target.Variations(), prebuiltTag,
- android.RemoveListFromList(nativeModules.ResolvedPrebuilts, nativeModules.Exclude_prebuilts)...)
+ android.RemoveListFromList(nativeModules.Prebuilts, nativeModules.Exclude_prebuilts)...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -781,7 +825,7 @@
}
}
for i, target := range targets {
- var deps ApexNativeDependencies
+ var deps ResolvedApexNativeDependencies
// Add native modules targeting both ABIs. When multilib.* is omitted for
// native_shared_libs/jni_libs/tests, it implies multilib.both
@@ -798,9 +842,9 @@
if isPrimaryAbi {
deps.Merge(ctx, a.properties.Multilib.First)
deps.Merge(ctx, ApexNativeDependencies{
- Native_shared_libs: nil,
+ Native_shared_libs: proptools.NewConfigurable[[]string](nil, nil),
Tests: nil,
- Jni_libs: nil,
+ Jni_libs: proptools.NewConfigurable[[]string](nil, nil),
Binaries: a.properties.Binaries,
})
}
@@ -842,7 +886,7 @@
}
}
- a.properties.ResolvedSystemserverclasspathFragments = a.properties.Systemserverclasspath_fragments.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
+ a.properties.ResolvedSystemserverclasspathFragments = a.properties.Systemserverclasspath_fragments.GetOrDefault(ctx, nil)
// Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
@@ -861,9 +905,9 @@
}
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
- ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)...)
+ ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps.GetOrDefault(ctx, nil)...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
- if prebuilts := a.overridableProperties.Prebuilts.GetOrDefault(a.ConfigurableEvaluator(ctx), nil); len(prebuilts) > 0 {
+ if prebuilts := a.overridableProperties.Prebuilts.GetOrDefault(ctx, nil); len(prebuilts) > 0 {
// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
// regardless of the TARGET_PREFER_* setting. See b/144532908
arches := ctx.DeviceConfig().Arches()
@@ -1024,6 +1068,7 @@
ApexContents: []*android.ApexContents{apexContents},
TestApexes: testApexes,
BaseApexName: mctx.ModuleName(),
+ ApexAvailableName: proptools.String(a.properties.Apex_available_name),
}
mctx.WalkDeps(func(child, parent android.Module) bool {
if !continueApexDepsWalk(child, parent) {
@@ -1035,7 +1080,7 @@
if a.dynamic_common_lib_apex() {
android.SetProvider(mctx, DCLAInfoProvider, DCLAInfo{
- ProvidedLibs: a.properties.Native_shared_libs,
+ ProvidedLibs: a.properties.Native_shared_libs.GetOrDefault(mctx, nil),
})
}
}
@@ -1065,51 +1110,6 @@
if am, ok := mctx.Module().(android.ApexModule); ok {
android.ApexInfoMutator(mctx, am)
}
- enforceAppUpdatability(mctx)
-}
-
-// apexStrictUpdatibilityLintMutator propagates strict_updatability_linting to transitive deps of a mainline module
-// This check is enforced for updatable modules
-func apexStrictUpdatibilityLintMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
- if apex, ok := mctx.Module().(*apexBundle); ok && apex.checkStrictUpdatabilityLinting(mctx) {
- mctx.WalkDeps(func(child, parent android.Module) bool {
- // b/208656169 Do not propagate strict updatability linting to libcore/
- // These libs are available on the classpath during compilation
- // These libs are transitive deps of the sdk. See java/sdk.go:decodeSdkDep
- // Only skip libraries defined in libcore root, not subdirectories
- if mctx.OtherModuleDir(child) == "libcore" {
- // Do not traverse transitive deps of libcore/ libs
- return false
- }
- if android.InList(child.Name(), skipLintJavalibAllowlist) {
- return false
- }
- if lintable, ok := child.(java.LintDepSetsIntf); ok {
- lintable.SetStrictUpdatabilityLinting(true)
- }
- // visit transitive deps
- return true
- })
- }
-}
-
-// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
-func enforceAppUpdatability(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
- if apex, ok := mctx.Module().(*apexBundle); ok && apex.Updatable() {
- // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
- mctx.VisitDirectDeps(func(module android.Module) {
- // ignore android_test_app
- if app, ok := module.(*java.AndroidApp); ok {
- app.SetUpdatable(true)
- }
- })
- }
}
// TODO: b/215736885 Whittle the denylist
@@ -1156,20 +1156,9 @@
"test_jitzygote_com.android.art",
// go/keep-sorted end
}
-
- // TODO: b/215736885 Remove this list
- skipLintJavalibAllowlist = []string{
- "conscrypt.module.platform.api.stubs",
- "conscrypt.module.public.api.stubs",
- "conscrypt.module.public.api.stubs.system",
- "conscrypt.module.public.api.stubs.module_lib",
- "framework-media.stubs",
- "framework-media.stubs.system",
- "framework-media.stubs.module_lib",
- }
)
-func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.TopDownMutatorContext) bool {
+func (a *apexBundle) checkStrictUpdatabilityLinting(mctx android.ModuleContext) bool {
// The allowlist contains the base apex name, so use that instead of the ApexVariationName
return a.Updatable() && !android.InList(mctx.ModuleName(), skipStrictUpdatabilityLintAllowlist)
}
@@ -1351,8 +1340,6 @@
return true
}
-var _ multitree.Exportable = (*apexBundle)(nil)
-
func (a *apexBundle) Exportable() bool {
return true
}
@@ -1492,7 +1479,7 @@
imageVariation := a.getImageVariation()
for _, target := range ctx.MultiTargets() {
if target.Arch.ArchType.Multilib == "lib64" {
- addDependenciesForNativeModules(ctx, ApexNativeDependencies{
+ addDependenciesForNativeModules(ctx, ResolvedApexNativeDependencies{
Native_shared_libs: []string{"libclang_rt.hwasan"},
Tests: nil,
Jni_libs: nil,
@@ -1617,7 +1604,6 @@
BaseModuleName() string
DexJarBuildPath(ctx android.ModuleErrorfContext) java.OptionalDexJarPath
JacocoReportClassesFile() android.Path
- LintDepSets() java.LintDepSets
Stem() string
}
@@ -1637,19 +1623,19 @@
dirInApex := "javalib"
af := newApexFile(ctx, dexImplementationJar, module.BaseModuleName(), dirInApex, javaSharedLib, module)
af.jacocoReportClassesFile = module.JacocoReportClassesFile()
- af.lintDepSets = module.LintDepSets()
+ if lintInfo, ok := android.OtherModuleProvider(ctx, module, java.LintProvider); ok {
+ af.lintInfo = lintInfo
+ }
af.customStem = module.Stem() + ".jar"
// 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())
- install.PackageFile(ctx)
}
} else if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() {
af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
- install.PackageFile(ctx)
}
}
return af
@@ -1677,7 +1663,6 @@
JacocoReportClassesFile() android.Path
Certificate() java.Certificate
BaseModuleName() string
- LintDepSets() java.LintDepSets
PrivAppAllowlist() android.OptionalPath
}
@@ -1713,7 +1698,9 @@
af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
- af.lintDepSets = aapp.LintDepSets()
+ if lintInfo, ok := android.OtherModuleProvider(ctx, aapp, java.LintProvider); ok {
+ af.lintInfo = lintInfo
+ }
af.certificate = aapp.Certificate()
if app, ok := aapp.(interface {
@@ -1764,7 +1751,7 @@
// visited module, the `do` callback is executed. Returning true in the callback continues the visit
// 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.ModuleContext, do android.PayloadDepsCallback) {
+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() {
@@ -1868,6 +1855,7 @@
a.CheckMinSdkVersion(ctx)
a.checkStaticLinkingToStubLibraries(ctx)
a.checkStaticExecutables(ctx)
+ a.enforceAppUpdatability(ctx)
if len(a.properties.Tests) > 0 && !a.testApex {
ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
return false
@@ -1890,8 +1878,6 @@
// visitor skips these from this list of module names
unwantedTransitiveDeps []string
-
- aconfigFiles []android.Path
}
func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) {
@@ -1933,12 +1919,12 @@
})
}
-func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent blueprint.Module) bool {
+func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent android.Module) bool {
depTag := ctx.OtherModuleDependencyTag(child)
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
return false
}
- if mod, ok := child.(android.Module); ok && !mod.Enabled(ctx) {
+ if !child.Enabled(ctx) {
return false
}
depName := ctx.OtherModuleName(child)
@@ -1958,7 +1944,6 @@
fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
fi.isJniLib = isJniLib
vctx.filesInfo = append(vctx.filesInfo, fi)
- addAconfigFiles(vctx, ctx, child)
// Collect the list of stub-providing libs except:
// - VNDK libs are only for vendors
// - bootstrap bionic libs are treated as provided by system
@@ -1970,7 +1955,6 @@
fi := apexFileForRustLibrary(ctx, ch)
fi.isJniLib = isJniLib
vctx.filesInfo = append(vctx.filesInfo, fi)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
@@ -1979,11 +1963,9 @@
switch ch := child.(type) {
case *cc.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
case *rust.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("binaries",
@@ -2023,7 +2005,6 @@
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
@@ -2032,14 +2013,11 @@
switch ap := child.(type) {
case *java.AndroidApp:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
case *java.AndroidAppImport:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
- addAconfigFiles(vctx, ctx, child)
case *java.AndroidTestHelperApp:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
- addAconfigFiles(vctx, ctx, child)
case *java.AndroidAppSet:
appDir := "app"
if ap.Privileged() {
@@ -2053,7 +2031,6 @@
af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
af.certificate = java.PresignedCertificate
vctx.filesInfo = append(vctx.filesInfo, af)
- addAconfigFiles(vctx, ctx, child)
default:
ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
}
@@ -2085,7 +2062,6 @@
for _, etcFile := range filesToCopy {
vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
}
- addAconfigFiles(vctx, ctx, child)
} else {
ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
}
@@ -2100,7 +2076,6 @@
af := apexFileForExecutable(ctx, ccTest)
af.class = nativeTest
vctx.filesInfo = append(vctx.filesInfo, af)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
} else {
ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
@@ -2180,13 +2155,15 @@
}
vctx.filesInfo = append(vctx.filesInfo, af)
- addAconfigFiles(vctx, ctx, child)
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)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
}
} else if cc.IsHeaderDepTag(depTag) {
@@ -2202,10 +2179,13 @@
}
} else if rust.IsDylibDepTag(depTag) {
if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
+ if !android.IsDepInSameApex(ctx, am, am) {
+ return false
+ }
+
af := apexFileForRustLibrary(ctx, rustm)
af.transitiveDep = true
vctx.filesInfo = append(vctx.filesInfo, af)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
}
} else if rust.IsRlibDepTag(depTag) {
@@ -2224,7 +2204,6 @@
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("bootclasspath_fragments",
@@ -2239,7 +2218,6 @@
if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil {
vctx.filesInfo = append(vctx.filesInfo, *profileAf)
}
- addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("systemserverclasspath_fragments",
@@ -2257,19 +2235,6 @@
return false
}
-func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) {
- if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigPropagatingProviderKey); ok {
- if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
- vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
- }
- }
-
- validationFlag := ctx.DeviceConfig().AconfigContainerValidation()
- if validationFlag == "error" || validationFlag == "warning" {
- android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), module, validationFlag == "error")
- }
-}
-
func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool {
// TODO(b/263308293) remove this
if a.properties.IsCoverageVariant {
@@ -2303,7 +2268,7 @@
checkDuplicate: a.shouldCheckDuplicate(ctx),
unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps,
}
- ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
+ ctx.WalkDeps(func(child, parent android.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
vctx.normalizeFileInfo(ctx)
if a.privateKeyFile == nil {
if ctx.Config().AllowMissingDependencies() {
@@ -2351,13 +2316,16 @@
// 3) some fields in apexBundle struct are configured
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = vctx.filesInfo
- a.aconfigFiles = android.FirstUniquePaths(vctx.aconfigFiles)
a.setPayloadFsType(ctx)
a.setSystemLibLink(ctx)
a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
////////////////////////////////////////////////////////////////////////////////////////////
+ // 3.a) some artifacts are generated from the collected files
+ a.filesInfo = append(a.filesInfo, a.buildAconfigFiles(ctx)...)
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
// 4) generate the build rules to create the APEX. This is done in builder.go.
a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs)
a.buildApex(ctx)
@@ -2370,6 +2338,7 @@
a.providePrebuiltInfo(ctx)
a.required = a.RequiredModuleNames(ctx)
+ a.required = append(a.required, a.VintfFragmentModuleNames(ctx)...)
a.setOutputFiles(ctx)
}
@@ -2412,6 +2381,24 @@
}
}
+// enforceAppUpdatability propagates updatable=true to apps of updatable apexes
+func (a *apexBundle) enforceAppUpdatability(mctx android.ModuleContext) {
+ if !a.Enabled(mctx) {
+ return
+ }
+ if a.Updatable() {
+ // checking direct deps is sufficient since apex->apk is a direct edge, even when inherited via apex_defaults
+ mctx.VisitDirectDeps(func(module android.Module) {
+ if appInfo, ok := android.OtherModuleProvider(mctx, module, java.AppInfoProvider); ok {
+ // ignore android_test_app
+ if !appInfo.TestHelperApp && !appInfo.Updatable {
+ mctx.ModuleErrorf("app dependency %s must have updatable: true", mctx.OtherModuleName(module))
+ }
+ }
+ })
+ }
+}
+
// 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 {
@@ -2506,7 +2493,6 @@
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableProperties.Overrides)
- multitree.InitExportableModule(module)
return module
}
@@ -2630,7 +2616,7 @@
abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider)
- a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if ccm, ok := to.(*cc.Module); ok {
apexName := ctx.ModuleName()
fromName := ctx.OtherModuleName(from)
@@ -2701,7 +2687,7 @@
func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
// Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs,
// java's checkLinkType guarantees correct usage for transitive deps
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
switch tag {
case javaLibTag, androidAppTag:
@@ -2729,6 +2715,12 @@
return
}
+ // Temporarily bypass /product APEXes with a specific prefix.
+ // TODO: b/352818241 - Remove this after APEX availability is enforced for /product APEXes.
+ if a.ProductSpecific() && strings.HasPrefix(a.ApexVariationName(), "com.sdv.") {
+ return
+ }
+
// Coverage build adds additional dependencies for the coverage-only runtime libraries.
// Requiring them and their transitive depencies with apex_available is not right
// because they just add noise.
@@ -2736,7 +2728,7 @@
return
}
- a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
if externalDep {
return false
@@ -2763,13 +2755,24 @@
return false
}
- if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
+ if to.AvailableFor(apexName) {
return true
}
+
+ // Let's give some hint for apex_available
+ hint := fmt.Sprintf("%q", apexName)
+
+ if strings.HasPrefix(apexName, "com.") && !strings.HasPrefix(apexName, "com.android.") && strings.Count(apexName, ".") >= 2 {
+ // In case of a partner APEX, prefix format might be an option.
+ components := strings.Split(apexName, ".")
+ components[len(components)-1] = "*"
+ hint += fmt.Sprintf(" or %q", strings.Join(components, "."))
+ }
+
ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
"\n\nDependency path:%s\n\n"+
- "Consider adding %q to 'apex_available' property of %q",
- fromName, toName, ctx.GetPathString(true), apexName, toName)
+ "Consider adding %s to 'apex_available' property of %q",
+ fromName, toName, ctx.GetPathString(true), hint, toName)
// Visit this module's dependencies to check and report any issues with their availability.
return true
})
@@ -2777,7 +2780,7 @@
// checkStaticExecutable ensures that executables in an APEX are not static.
func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) {
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDeps(func(module android.Module) {
if ctx.OtherModuleDependencyTag(module) != executableTag {
return
}
@@ -2806,80 +2809,12 @@
}
// Collect information for opening IDE project files in java/jdeps.go.
-func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) {
+func (a *apexBundle) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...)
dpInfo.Deps = append(dpInfo.Deps, a.properties.ResolvedSystemserverclasspathFragments...)
}
-var (
- apexAvailBaseline = makeApexAvailableBaseline()
- inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline)
-)
-
-func baselineApexAvailable(apex, moduleName string) bool {
- key := apex
- moduleName = normalizeModuleName(moduleName)
-
- if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
- return true
- }
-
- key = android.AvailableToAnyApex
- if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
- return true
- }
-
- return false
-}
-
-func normalizeModuleName(moduleName string) string {
- // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
- // system. Trim the prefix for the check since they are confusing
- moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName)
- if strings.HasPrefix(moduleName, "libclang_rt.") {
- // This module has many arch variants that depend on the product being built.
- // We don't want to list them all
- moduleName = "libclang_rt"
- }
- if strings.HasPrefix(moduleName, "androidx.") {
- // TODO(b/156996905) Set apex_available/min_sdk_version for androidx support libraries
- moduleName = "androidx"
- }
- return moduleName
-}
-
-// Transform the map of apex -> modules to module -> apexes.
-func invertApexBaseline(m map[string][]string) map[string][]string {
- r := make(map[string][]string)
- for apex, modules := range m {
- for _, module := range modules {
- r[module] = append(r[module], apex)
- }
- }
- return r
-}
-
-// Retrieve the baseline of apexes to which the supplied module belongs.
-func BaselineApexAvailable(moduleName string) []string {
- return inverseApexAvailBaseline[normalizeModuleName(moduleName)]
-}
-
-// This is a map from apex to modules, which overrides the apex_available setting for that
-// particular module to make it available for the apex regardless of its setting.
-// TODO(b/147364041): remove this
-func makeApexAvailableBaseline() map[string][]string {
- // The "Module separator"s below are employed to minimize merge conflicts.
- m := make(map[string][]string)
- //
- // Module separator
- //
- m["com.android.runtime"] = []string{
- "libz",
- }
- return m
-}
-
func init() {
android.AddNeverAllowRules(createBcpPermittedPackagesRules(qBcpPackages())...)
android.AddNeverAllowRules(createBcpPermittedPackagesRules(rBcpPackages())...)
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index a8d89b1..f405cb2 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -88,7 +88,7 @@
updatableFlatLists := android.Paths{}
ctx.VisitAllModules(func(module android.Module) {
if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
- apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
+ apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
if path := binaryInfo.FlatListPath(); path != nil {
if binaryInfo.Updatable() || apexInfo.Updatable {
updatableFlatLists = append(updatableFlatLists, path)
@@ -155,7 +155,7 @@
prebuiltInfos := []android.PrebuiltInfo{}
ctx.VisitAllModules(func(m android.Module) {
- prebuiltInfo, exists := android.SingletonModuleProvider(ctx, m, android.PrebuiltInfoProvider)
+ 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() {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 261d2ce..da6214d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -267,6 +267,7 @@
}
func ensureMatches(t *testing.T, result string, expectedRex string) {
+ t.Helper()
ok, err := regexp.MatchString(expectedRex, result)
if err != nil {
t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", result, expectedRex, err)
@@ -277,6 +278,14 @@
}
}
+func ensureListContainsMatch(t *testing.T, result []string, expectedRex string) {
+ t.Helper()
+ p := regexp.MustCompile(expectedRex)
+ if android.IndexListPred(func(s string) bool { return p.MatchString(s) }, result) == -1 {
+ t.Errorf("%q is not found in %v", expectedRex, result)
+ }
+}
+
func ensureListContains(t *testing.T, result []string, expected string) {
t.Helper()
if !android.InList(expected, result) {
@@ -384,7 +393,7 @@
symlink_preferred_arch: true,
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex", "com.android.gki.*" ],
+ apex_available: [ "myapex" ],
}
rust_binary {
@@ -432,14 +441,6 @@
apex_available: ["myapex"],
}
- apex {
- name: "com.android.gki.fake",
- binaries: ["foo"],
- key: "myapex.key",
- file_contexts: ":myapex-file_contexts",
- updatable: false,
- }
-
cc_library_shared {
name: "mylib2",
srcs: ["mylib.cpp"],
@@ -914,7 +915,7 @@
cc_library {
name: "mylib",
srcs: ["mylib.cpp"],
- shared_libs: ["mylib2", "mylib3"],
+ shared_libs: ["mylib2", "mylib3", "my_prebuilt_platform_lib", "my_prebuilt_platform_stub_only_lib"],
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
@@ -927,6 +928,7 @@
system_shared_libs: [],
stl: "none",
stubs: {
+ symbol_file: "mylib2.map.txt",
versions: ["1", "2", "3"],
},
}
@@ -938,6 +940,7 @@
system_shared_libs: [],
stl: "none",
stubs: {
+ symbol_file: "mylib3.map.txt",
versions: ["10", "11", "12"],
},
apex_available: [ "myapex" ],
@@ -951,6 +954,24 @@
apex_available: [ "myapex" ],
}
+ cc_prebuilt_library_shared {
+ name: "my_prebuilt_platform_lib",
+ stubs: {
+ symbol_file: "my_prebuilt_platform_lib.map.txt",
+ versions: ["1", "2", "3"],
+ },
+ srcs: ["foo.so"],
+ }
+
+ // Similar to my_prebuilt_platform_lib, but this library only provides stubs, i.e. srcs is empty
+ cc_prebuilt_library_shared {
+ name: "my_prebuilt_platform_stub_only_lib",
+ stubs: {
+ symbol_file: "my_prebuilt_platform_stub_only_lib.map.txt",
+ versions: ["1", "2", "3"],
+ }
+ }
+
rust_binary {
name: "foo.rust",
srcs: ["foo.rs"],
@@ -1030,6 +1051,20 @@
apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.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")
+
+ // 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")
}
func TestApexShouldNotEmbedStubVariant(t *testing.T) {
@@ -1164,6 +1199,7 @@
system_shared_libs: [],
stl: "none",
stubs: {
+ symbol_file: "mylib2.map.txt",
versions: ["28", "29", "30", "current"],
},
min_sdk_version: "28",
@@ -1176,6 +1212,7 @@
system_shared_libs: [],
stl: "none",
stubs: {
+ symbol_file: "mylib3.map.txt",
versions: ["28", "29", "30", "current"],
},
apex_available: [ "myapex" ],
@@ -3648,7 +3685,7 @@
}
func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) {
- deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Description("deapex")
+ deapexer := ctx.ModuleForTests(moduleName, variant).Description("deapex")
outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
if deapexer.Output != nil {
outputs = append(outputs, deapexer.Output.String())
@@ -4848,200 +4885,6 @@
func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
}
-// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
-// propagation of paths to dex implementation jars from the former to the latter.
-func TestPrebuiltExportDexImplementationJars(t *testing.T) {
- transform := android.NullFixturePreparer
-
- checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) {
- t.Helper()
- // Make sure the import has been given the correct path to the dex jar.
- p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
- dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil()
- stem := android.RemoveOptionalPrebuiltPrefix(name)
- android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
- ".intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
- android.NormalizePathForTesting(dexJarBuildPath))
- }
-
- checkDexJarInstallPath := func(t *testing.T, ctx *android.TestContext, name string) {
- t.Helper()
- // Make sure the import has been given the correct path to the dex jar.
- p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
- dexJarBuildPath := p.DexJarInstallPath()
- stem := android.RemoveOptionalPrebuiltPrefix(name)
- android.AssertStringEquals(t, "DexJarInstallPath should be apex-related path.",
- "target/product/test_device/apex/myapex/javalib/"+stem+".jar",
- android.NormalizePathForTesting(dexJarBuildPath))
- }
-
- ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext, name string) {
- t.Helper()
- // Make sure that an apex variant is not created for the source module.
- android.AssertArrayString(t, "Check if there is no source variant",
- []string{"android_common"},
- ctx.ModuleVariantsForTests(name))
- }
-
- t.Run("prebuilt only", func(t *testing.T) {
- bp := `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo", "libbar"],
- }
-
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- }
-
- java_sdk_library_import {
- name: "libbar",
- public: {
- jars: ["libbar.jar"],
- },
- }
- `
-
- // Make sure that dexpreopt can access dex implementation files from the prebuilt.
- ctx := testDexpreoptWithApexes(t, bp, "", transform)
-
- deapexerName := deapexerModuleName("prebuilt_myapex")
- android.AssertStringEquals(t, "APEX module name from deapexer name", "prebuilt_myapex", apexModuleName(deapexerName))
-
- // Make sure that the deapexer has the correct input APEX.
- deapexer := ctx.ModuleForTests(deapexerName, "android_common")
- rule := deapexer.Rule("deapexer")
- if expected, actual := []string{"myapex-arm64.apex"}, android.NormalizePathsForTesting(rule.Implicits); !reflect.DeepEqual(expected, actual) {
- t.Errorf("expected: %q, found: %q", expected, actual)
- }
-
- // Make sure that the prebuilt_apex has the correct input APEX.
- prebuiltApex := ctx.ModuleForTests("myapex", "android_common_myapex")
- rule = prebuiltApex.Rule("android/soong/android.Cp")
- if expected, actual := "myapex-arm64.apex", android.NormalizePathForTesting(rule.Input); !reflect.DeepEqual(expected, actual) {
- t.Errorf("expected: %q, found: %q", expected, actual)
- }
-
- checkDexJarBuildPath(t, ctx, "libfoo")
- checkDexJarInstallPath(t, ctx, "libfoo")
-
- checkDexJarBuildPath(t, ctx, "libbar")
- checkDexJarInstallPath(t, ctx, "libbar")
- })
-
- t.Run("prebuilt with source preferred", func(t *testing.T) {
-
- bp := `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo", "libbar"],
- }
-
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- }
-
- java_library {
- name: "libfoo",
- }
-
- java_sdk_library_import {
- name: "libbar",
- public: {
- jars: ["libbar.jar"],
- },
- }
-
- java_sdk_library {
- name: "libbar",
- srcs: ["foo/bar/MyClass.java"],
- unsafe_ignore_missing_latest_api: true,
- }
- `
-
- // Make sure that dexpreopt can access dex implementation files from the prebuilt.
- ctx := testDexpreoptWithApexes(t, bp, "", transform)
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
- checkDexJarInstallPath(t, ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(t, ctx, "libfoo")
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
- checkDexJarInstallPath(t, ctx, "prebuilt_libbar")
- ensureNoSourceVariant(t, ctx, "libbar")
- })
-
- t.Run("prebuilt preferred with source", func(t *testing.T) {
- bp := `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["libfoo", "libbar"],
- }
-
- java_import {
- name: "libfoo",
- prefer: true,
- jars: ["libfoo.jar"],
- }
-
- java_library {
- name: "libfoo",
- }
-
- java_sdk_library_import {
- name: "libbar",
- prefer: true,
- public: {
- jars: ["libbar.jar"],
- },
- }
-
- java_sdk_library {
- name: "libbar",
- srcs: ["foo/bar/MyClass.java"],
- unsafe_ignore_missing_latest_api: true,
- }
- `
-
- // Make sure that dexpreopt can access dex implementation files from the prebuilt.
- ctx := testDexpreoptWithApexes(t, bp, "", transform)
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
- checkDexJarInstallPath(t, ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(t, ctx, "libfoo")
-
- checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
- checkDexJarInstallPath(t, ctx, "prebuilt_libbar")
- ensureNoSourceVariant(t, ctx, "libbar")
- })
-}
-
func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
preparer := android.GroupFixturePreparers(
java.FixtureConfigureApexBootJars("myapex:libfoo", "myapex:libbar"),
@@ -5064,23 +4907,6 @@
}),
)
- checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
- t.Helper()
- s := ctx.ModuleForTests("dex_bootjars", "android_common")
- foundLibfooJar := false
- base := stem + ".jar"
- for _, output := range s.AllOutputs() {
- if filepath.Base(output) == base {
- foundLibfooJar = true
- buildRule := s.Output(output)
- android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String())
- }
- }
- if !foundLibfooJar {
- t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().SoongOutDir(), s.AllOutputs()))
- }
- }
-
checkHiddenAPIIndexFromClassesInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
t.Helper()
platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
@@ -5133,10 +4959,13 @@
},
}
- java_import {
+ java_sdk_library_import {
name: "libfoo",
- jars: ["libfoo.jar"],
+ public: {
+ jars: ["libfoo.jar"],
+ },
apex_available: ["myapex"],
+ shared_library: false,
permitted_packages: ["foo"],
}
@@ -5152,8 +4981,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5169,18 +4996,10 @@
apex_set {
name: "myapex",
set: "myapex.apks",
- exported_java_libs: ["myjavalib"],
exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
exported_systemserverclasspath_fragments: ["my-systemserverclasspath-fragment"],
}
- java_import {
- name: "myjavalib",
- jars: ["myjavalib.jar"],
- apex_available: ["myapex"],
- permitted_packages: ["javalib"],
- }
-
prebuilt_bootclasspath_fragment {
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
@@ -5201,13 +5020,17 @@
apex_available: ["myapex"],
}
- java_import {
+ java_sdk_library_import {
name: "libfoo",
- jars: ["libfoo.jar"],
+ public: {
+ jars: ["libfoo.jar"],
+ },
apex_available: ["myapex"],
- permitted_packages: ["foo"],
+ shared_library: false,
+ permitted_packages: ["libfoo"],
}
+
java_sdk_library_import {
name: "libbar",
public: {
@@ -5230,8 +5053,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5292,12 +5113,14 @@
name: "libfoo",
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ sdk_version: "core_current",
}
java_library {
name: "libfoo",
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
+ sdk_version: "core_current",
}
java_sdk_library_import {
@@ -5383,12 +5206,15 @@
},
}
- java_import {
+ java_sdk_library_import {
name: "libfoo",
prefer: true,
- jars: ["libfoo.jar"],
+ public: {
+ jars: ["libfoo.jar"],
+ },
apex_available: ["myapex"],
- permitted_packages: ["foo"],
+ shared_library: false,
+ permitted_packages: ["libfoo"],
}
java_library {
@@ -5396,6 +5222,7 @@
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
installable: true,
+ sdk_version: "core_current",
}
java_sdk_library_import {
@@ -5419,8 +5246,6 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5486,6 +5311,7 @@
name: "libfoo",
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ sdk_version: "core_current",
}
java_library {
@@ -5494,6 +5320,7 @@
apex_available: ["myapex"],
permitted_packages: ["foo"],
installable: true,
+ sdk_version: "core_current",
}
java_sdk_library_import {
@@ -5512,12 +5339,11 @@
apex_available: ["myapex"],
permitted_packages: ["bar"],
compile_dex: true,
+ sdk_version: "core_current",
}
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -5603,11 +5429,11 @@
apex_available: ["myapex"],
shared_library: false,
permitted_packages: ["bar"],
+ prefer: true,
}
java_sdk_library {
name: "libbar",
- enabled: false,
srcs: ["foo/bar/MyClass.java"],
unsafe_ignore_missing_latest_api: true,
apex_available: ["myapex"],
@@ -5624,13 +5450,11 @@
android.PrepareForTestWithAllowMissingDependencies,
android.FixtureMergeMockFs(map[string][]byte{
"build/soong/scripts/check_boot_jars/package_allowed_list.txt": nil,
- "frameworks/base/config/boot-profile.txt": nil,
+ "frameworks/base/boot/boot-profile.txt": nil,
}),
)
ctx := testDexpreoptWithApexes(t, bp, "", preparer2, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
@@ -6106,6 +5930,7 @@
name: "TesterHelpAppFoo",
srcs: ["foo/bar/MyClass.java"],
apex_available: [ "myapex" ],
+ sdk_version: "test_current",
}
`)
@@ -6188,6 +6013,87 @@
system_shared_libs: [],
apex_available: ["otherapex"],
}`)
+
+ // 'apex_available' check is bypassed for /product apex with a specific prefix.
+ // TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes.
+ testApex(t, `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ product_specific: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "com.any.otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["com.any.otherapex"],
+ product_specific: true,
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ "system/sepolicy/apex/com.any.otherapex-file_contexts": nil,
+ }))
+
+ // 'apex_available' check is not bypassed for non-product apex with a specific prefix.
+ testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ apex {
+ name: "com.any.otherapex",
+ key: "otherapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "otherapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["com.any.otherapex"],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ "system/sepolicy/apex/com.any.otherapex-file_contexts": nil,
+ }))
}
func TestApexAvailable_IndirectDep(t *testing.T) {
@@ -6233,6 +6139,91 @@
stl: "none",
system_shared_libs: [],
}`)
+
+ // 'apex_available' check is bypassed for /product apex with a specific prefix.
+ // TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes.
+ testApex(t, `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ product_specific: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ product_specific: true,
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ shared_libs: ["libbaz"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ product_specific: true,
+ }
+
+ cc_library {
+ name: "libbaz",
+ stl: "none",
+ system_shared_libs: [],
+ product_specific: true,
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ }))
+
+ // 'apex_available' check is not bypassed for non-product apex with a specific prefix.
+ testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.`, `
+ apex {
+ name: "com.sdv.myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ shared_libs: ["libbaz"],
+ system_shared_libs: [],
+ apex_available: ["com.sdv.myapex"],
+ }
+
+ cc_library {
+ name: "libbaz",
+ stl: "none",
+ system_shared_libs: [],
+ }`,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
+ }))
}
func TestApexAvailable_IndirectStaticDep(t *testing.T) {
@@ -6434,14 +6425,14 @@
`)
fooManifestRule := result.ModuleForTests("foo", "android_common_foo").Rule("apexManifestRule")
- fooExpectedDefaultVersion := android.DefaultUpdatableModuleVersion
+ 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")
- defaultVersionInt, _ := strconv.Atoi(android.DefaultUpdatableModuleVersion)
+ defaultVersionInt, _ := strconv.Atoi(testDefaultUpdatableModuleVersion)
barExpectedDefaultVersion := fmt.Sprint(defaultVersionInt + 3)
barActualDefaultVersion := barManifestRule.Args["default_version"]
if barActualDefaultVersion != barExpectedDefaultVersion {
@@ -6730,6 +6721,99 @@
}
}
+func TestApexAvailable_PrefixMatch(t *testing.T) {
+
+ for _, tc := range []struct {
+ name string
+ apexAvailable string
+ expectedError string
+ }{
+ {
+ name: "prefix matches correctly",
+ apexAvailable: "com.foo.*",
+ },
+ {
+ name: "prefix doesn't match",
+ apexAvailable: "com.bar.*",
+ expectedError: `Consider .* "com.foo\.\*"`,
+ },
+ {
+ name: "short prefix",
+ apexAvailable: "com.*",
+ expectedError: "requires two or more components",
+ },
+ {
+ name: "wildcard not in the end",
+ apexAvailable: "com.*.foo",
+ expectedError: "should end with .*",
+ },
+ {
+ name: "wildcard in the middle",
+ apexAvailable: "com.foo*.*",
+ expectedError: "not allowed in the middle",
+ },
+ {
+ name: "hint with prefix pattern",
+ apexAvailable: "//apex_available:platform",
+ expectedError: "Consider adding \"com.foo.bar\" or \"com.foo.*\"",
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ errorHandler := android.FixtureExpectsNoErrors
+ if tc.expectedError != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
+ }
+ context := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.foo.bar-file_contexts": nil,
+ }),
+ ).ExtendWithErrorHandler(errorHandler)
+
+ context.RunTestWithBp(t, `
+ apex {
+ name: "com.foo.bar",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ apex_available: ["`+tc.apexAvailable+`"],
+ }`)
+ })
+ }
+ testApexError(t, `Consider adding "com.foo" to`, `
+ apex {
+ name: "com.foo", // too short for a partner apex
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ system_shared_libs: [],
+ }
+ `)
+}
+
func TestOverrideApex(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -7164,7 +7248,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo"],
+ libs: ["foo.impl"],
apex_available: ["myapex"],
sdk_version: "none",
system_modules: "none",
@@ -7217,7 +7301,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo"],
+ libs: ["foo.stubs"],
sdk_version: "none",
system_modules: "none",
}
@@ -7271,7 +7355,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo"],
+ libs: ["foo.impl"],
apex_available: ["myapex"],
sdk_version: "none",
system_modules: "none",
@@ -7615,7 +7699,7 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
- libs: ["myotherjar"],
+ static_libs: ["myotherjar"],
apex_available: [
"myapex",
"myapex.updatable",
@@ -7944,9 +8028,9 @@
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
- extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
@@ -7971,10 +8055,10 @@
}
`)
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -8036,189 +8120,6 @@
return result.TestContext
}
-func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
- preparers := android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- prepareForTestWithBootclasspathFragment,
- dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:libfoo"),
- PrepareForTestWithApexBuildComponents,
- ).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art"))
-
- bpBase := `
- apex_set {
- name: "com.android.art",
- installable: true,
- exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
- set: "myapex.apks",
- }
-
- apex_set {
- name: "com.mycompany.android.art",
- apex_name: "com.android.art",
- installable: true,
- exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
- set: "company-myapex.apks",
- }
-
- prebuilt_bootclasspath_fragment {
- name: "art-bootclasspath-fragment",
- apex_available: ["com.android.art"],
- hidden_api: {
- annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
- metadata: "my-bootclasspath-fragment/metadata.csv",
- index: "my-bootclasspath-fragment/index.csv",
- stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
- all_flags: "my-bootclasspath-fragment/all-flags.csv",
- },
- %s
- }
- `
-
- t.Run("java_import", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- apex_available: ["com.android.art"],
- }
- `)
- })
-
- t.Run("java_sdk_library_import", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- shared_library: false,
- apex_available: ["com.android.art"],
- }
- `)
- })
-
- t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
- image_name: "art",
- contents: ["libfoo"],
- `)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- shared_library: false,
- apex_available: ["com.android.art"],
- }
- `)
- })
-}
-
-func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
- preparers := android.GroupFixturePreparers(
- java.PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithApexBuildComponents,
- )
-
- errCtx := moduleErrorfTestCtx{}
-
- bpBase := `
- apex_set {
- name: "com.android.myapex",
- installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
- set: "myapex.apks",
- }
-
- apex_set {
- name: "com.android.myapex_compressed",
- apex_name: "com.android.myapex",
- installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
- set: "myapex_compressed.apks",
- }
-
- prebuilt_bootclasspath_fragment {
- name: "my-bootclasspath-fragment",
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- hidden_api: {
- annotation_flags: "annotation-flags.csv",
- metadata: "metadata.csv",
- index: "index.csv",
- signature_patterns: "signature_patterns.csv",
- },
- %s
- }
- `
-
- t.Run("java_import", func(t *testing.T) {
- result := preparers.RunTestWithBp(t,
- fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_import {
- name: "libfoo",
- jars: ["libfoo.jar"],
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- }
- `)
-
- module := result.Module("libfoo", "android_common_com.android.myapex")
- usesLibraryDep := module.(java.UsesLibraryDependency)
- android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath(errCtx).Path())
- })
-
- t.Run("java_sdk_library_import", func(t *testing.T) {
- result := preparers.RunTestWithBp(t,
- fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- compile_dex: true,
- }
- `)
-
- module := result.Module("libfoo", "android_common_com.android.myapex")
- usesLibraryDep := module.(java.UsesLibraryDependency)
- android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath(errCtx).Path())
- })
-
- t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
- _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
- image_name: "art",
- contents: ["libfoo"],
- `)+`
- java_sdk_library_import {
- name: "libfoo",
- public: {
- jars: ["libbar.jar"],
- },
- apex_available: [
- "com.android.myapex",
- "com.android.myapex_compressed",
- ],
- compile_dex: true,
- }
- `)
- })
-}
-
func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
apex {
@@ -8276,6 +8177,7 @@
apex_available: [
"myapex",
],
+ sdk_version: "current",
}
systemserverclasspath_fragment {
@@ -8329,12 +8231,16 @@
},
}
- java_import {
- name: "libfoo",
+ java_sdk_library_import {
+ name: "libfoo",
+ prefer: true,
+ public: {
jars: ["libfoo.jar"],
- apex_available: ["myapex"],
- permitted_packages: ["libfoo"],
- }
+ },
+ apex_available: ["myapex"],
+ shared_library: false,
+ permitted_packages: ["libfoo"],
+ }
`, "", preparer, fragment)
})
}
@@ -8714,7 +8620,7 @@
}),
)
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -8755,7 +8661,7 @@
}),
)
- m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("myapex", "android_common_myapex")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -8993,6 +8899,30 @@
ensureContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.capex\n")
}
+func TestApexSet_ShouldRespectCompressedApexFlag(t *testing.T) {
+ for _, compressionEnabled := range []bool{true, false} {
+ t.Run(fmt.Sprintf("compressionEnabled=%v", compressionEnabled), func(t *testing.T) {
+ ctx := testApex(t, `
+ apex_set {
+ name: "com.company.android.myapex",
+ apex_name: "com.android.myapex",
+ set: "company-myapex.apks",
+ }
+ `, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.CompressedApex = proptools.BoolPtr(compressionEnabled)
+ }),
+ )
+
+ build := ctx.ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex").Output("com.company.android.myapex.apex")
+ if compressionEnabled {
+ ensureEquals(t, build.Rule.String(), "android/soong/android.Cp")
+ } else {
+ ensureEquals(t, build.Rule.String(), "android/apex.decompressApex")
+ }
+ })
+ }
+}
+
func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -9294,6 +9224,7 @@
srcs: ["mybootclasspathlib.java"],
apex_available: ["myapex"],
compile_dex: true,
+ sdk_version: "current",
}
systemserverclasspath_fragment {
@@ -9417,42 +9348,6 @@
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")
}
-func TestAndroidMk_DexpreoptBuiltInstalledForApex_Prebuilt(t *testing.T) {
- ctx := testApex(t, `
- prebuilt_apex {
- name: "myapex",
- arch: {
- arm64: {
- src: "myapex-arm64.apex",
- },
- arm: {
- src: "myapex-arm.apex",
- },
- },
- exported_java_libs: ["foo"],
- }
-
- java_import {
- name: "foo",
- jars: ["foo.jar"],
- apex_available: ["myapex"],
- }
- `,
- dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
- )
-
- prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
- entriesList := android.AndroidMkEntriesForTest(t, ctx, prebuilt)
- mainModuleEntries := entriesList[0]
- android.AssertArrayString(t,
- "LOCAL_REQUIRED_MODULES",
- mainModuleEntries.EntryMap["LOCAL_REQUIRED_MODULES"],
- []string{
- "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex",
- "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex",
- })
-}
-
func TestAndroidMk_RequiredModules(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -9609,6 +9504,7 @@
unsafe_ignore_missing_latest_api: true,
min_sdk_version: "31",
static_libs: ["util"],
+ sdk_version: "core_current",
}
java_library {
@@ -9617,6 +9513,7 @@
apex_available: ["myapex"],
min_sdk_version: "31",
static_libs: ["another_util"],
+ sdk_version: "core_current",
}
java_library {
@@ -9624,6 +9521,7 @@
srcs: ["a.java"],
min_sdk_version: "31",
apex_available: ["myapex"],
+ sdk_version: "core_current",
}
`)
})
@@ -9679,7 +9577,7 @@
})
t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
- preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mybootclasspathlib".*must set min_sdk_version`)).
+ preparer.
RunTestWithBp(t, `
apex {
name: "myapex",
@@ -9710,6 +9608,8 @@
apex_available: ["myapex"],
compile_dex: true,
unsafe_ignore_missing_latest_api: true,
+ sdk_version: "current",
+ min_sdk_version: "30",
}
`)
})
@@ -9793,120 +9693,84 @@
}
testCases := []struct {
- testCaseName string
- apexUpdatable bool
- javaStrictUpdtabilityLint bool
- lintFileExists bool
- disallowedFlagExpected bool
+ testCaseName string
+ apexUpdatable bool
+ javaStrictUpdtabilityLint bool
+ lintFileExists bool
+ disallowedFlagExpectedOnApex bool
+ disallowedFlagExpectedOnJavalib bool
}{
{
- testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
- apexUpdatable: true,
- javaStrictUpdtabilityLint: true,
- lintFileExists: false,
- disallowedFlagExpected: false,
+ testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
+ apexUpdatable: true,
+ javaStrictUpdtabilityLint: true,
+ lintFileExists: false,
+ disallowedFlagExpectedOnApex: false,
+ disallowedFlagExpectedOnJavalib: false,
},
{
- testCaseName: "non-updatable apex respects strict_updatability of javalib",
- apexUpdatable: false,
- javaStrictUpdtabilityLint: false,
- lintFileExists: true,
- disallowedFlagExpected: false,
+ testCaseName: "non-updatable apex respects strict_updatability of javalib",
+ apexUpdatable: false,
+ javaStrictUpdtabilityLint: false,
+ lintFileExists: true,
+ disallowedFlagExpectedOnApex: false,
+ disallowedFlagExpectedOnJavalib: false,
},
{
- testCaseName: "non-updatable apex respects strict updatability of javalib",
- apexUpdatable: false,
- javaStrictUpdtabilityLint: true,
- lintFileExists: true,
- disallowedFlagExpected: true,
+ testCaseName: "non-updatable apex respects strict updatability of javalib",
+ apexUpdatable: false,
+ javaStrictUpdtabilityLint: true,
+ lintFileExists: true,
+ disallowedFlagExpectedOnApex: false,
+ disallowedFlagExpectedOnJavalib: true,
},
{
- testCaseName: "updatable apex sets strict updatability of javalib to true",
- apexUpdatable: true,
- javaStrictUpdtabilityLint: false, // will be set to true by mutator
- lintFileExists: true,
- disallowedFlagExpected: true,
+ testCaseName: "updatable apex checks strict updatability of javalib",
+ apexUpdatable: true,
+ javaStrictUpdtabilityLint: false,
+ lintFileExists: true,
+ disallowedFlagExpectedOnApex: true,
+ disallowedFlagExpectedOnJavalib: false,
},
}
for _, testCase := range testCases {
- fixtures := []android.FixturePreparer{}
- baselineProperty := ""
- if testCase.lintFileExists {
- fixtures = append(fixtures, fs.AddToFixture())
- baselineProperty = "baseline_filename: \"lint-baseline.xml\""
- }
- bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
-
- result := testApex(t, bp, fixtures...)
- myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
- disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi")
-
- if disallowedFlagActual != testCase.disallowedFlagExpected {
- t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
- }
- }
-}
-
-func TestUpdatabilityLintSkipLibcore(t *testing.T) {
- bp := `
- apex {
- name: "myapex",
- key: "myapex.key",
- java_libs: ["myjavalib"],
- updatable: true,
- min_sdk_version: "29",
- }
- apex_key {
- name: "myapex.key",
- }
- java_library {
- name: "myjavalib",
- srcs: ["MyClass.java"],
- apex_available: [ "myapex" ],
- sdk_version: "current",
- min_sdk_version: "29",
- lint: {
- baseline_filename: "lint-baseline.xml",
+ t.Run(testCase.testCaseName, func(t *testing.T) {
+ fixtures := []android.FixturePreparer{}
+ baselineProperty := ""
+ if testCase.lintFileExists {
+ fixtures = append(fixtures, fs.AddToFixture())
+ baselineProperty = "baseline_filename: \"lint-baseline.xml\""
}
- }
- `
+ bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
- testCases := []struct {
- testCaseName string
- moduleDirectory string
- disallowedFlagExpected bool
- }{
- {
- testCaseName: "lintable module defined outside libcore",
- moduleDirectory: "",
- disallowedFlagExpected: true,
- },
- {
- testCaseName: "lintable module defined in libcore root directory",
- moduleDirectory: "libcore/",
- disallowedFlagExpected: false,
- },
- {
- testCaseName: "lintable module defined in libcore child directory",
- moduleDirectory: "libcore/childdir/",
- disallowedFlagExpected: true,
- },
- }
+ result := testApex(t, bp, fixtures...)
- for _, testCase := range testCases {
- lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "")
- bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp)
- result := testApex(t, "", lintFileCreator, bpFileCreator)
- myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
- cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory)
- disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags)
+ checkModule := func(m android.TestingBuildParams, name string, expectStrictUpdatability bool) {
+ if expectStrictUpdatability {
+ if m.Rule == nil {
+ t.Errorf("expected strict updatability check rule on %s", name)
+ } else {
+ android.AssertStringDoesContain(t, fmt.Sprintf("strict updatability check rule for %s", name),
+ m.RuleParams.Command, "--disallowed_issues NewApi")
+ android.AssertStringListContains(t, fmt.Sprintf("strict updatability check baselines for %s", name),
+ m.Inputs.Strings(), "lint-baseline.xml")
+ }
+ } else {
+ if m.Rule != nil {
+ t.Errorf("expected no strict updatability check rule on %s", name)
+ }
+ }
+ }
- if disallowedFlagActual != testCase.disallowedFlagExpected {
- t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
- }
+ myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
+ apex := result.ModuleForTests("myapex", "android_common_myapex")
+ apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp")
+ javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp")
+
+ checkModule(apexStrictUpdatabilityCheck, "myapex", testCase.disallowedFlagExpectedOnApex)
+ checkModule(javalibStrictUpdatabilityCheck, "myjavalib", testCase.disallowedFlagExpectedOnJavalib)
+ })
}
}
@@ -9948,11 +9812,12 @@
}
result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
- myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") {
- t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command)
- }
+ apex := result.ModuleForTests("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")
+ android.AssertStringListContains(t, "strict updatability check baselines for myapex",
+ apexStrictUpdatabilityCheck.Inputs.Strings(), "lint-baseline.xml")
}
func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) {
@@ -9962,6 +9827,9 @@
key: "myapex.key",
bootclasspath_fragments: ["mybootclasspathfragment"],
min_sdk_version: "29",
+ java_libs: [
+ "jacocoagent",
+ ],
}
apex_key {
name: "myapex.key",
@@ -9992,9 +9860,6 @@
java.PrepareForTestWithJavaSdkLibraryFiles,
java.PrepareForTestWithJacocoInstrumentation,
java.FixtureWithLastReleaseApis("foo"),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
android.FixtureMergeMockFs(fs),
).RunTestWithBp(t, bp)
@@ -10011,7 +9876,7 @@
apex {
name: "myapex",
key: "myapex.key",
- updatable: %v,
+ updatable: true,
apps: [
"myapp",
],
@@ -10022,7 +9887,6 @@
}
android_app {
name: "myapp",
- updatable: %v,
apex_available: [
"myapex",
],
@@ -10030,244 +9894,10 @@
min_sdk_version: "30",
}
`
- testCases := []struct {
- name string
- apex_is_updatable_bp bool
- app_is_updatable_bp bool
- app_is_updatable_expected bool
- }{
- {
- name: "Non-updatable apex respects updatable property of non-updatable app",
- apex_is_updatable_bp: false,
- app_is_updatable_bp: false,
- app_is_updatable_expected: false,
- },
- {
- name: "Non-updatable apex respects updatable property of updatable app",
- apex_is_updatable_bp: false,
- app_is_updatable_bp: true,
- app_is_updatable_expected: true,
- },
- {
- name: "Updatable apex respects updatable property of updatable app",
- apex_is_updatable_bp: true,
- app_is_updatable_bp: true,
- app_is_updatable_expected: true,
- },
- {
- name: "Updatable apex sets updatable=true on non-updatable app",
- apex_is_updatable_bp: true,
- app_is_updatable_bp: false,
- app_is_updatable_expected: true,
- },
- }
- for _, testCase := range testCases {
- result := testApex(t, fmt.Sprintf(bp, testCase.apex_is_updatable_bp, testCase.app_is_updatable_bp))
- myapp := result.ModuleForTests("myapp", "android_common").Module().(*java.AndroidApp)
- android.AssertBoolEquals(t, testCase.name, testCase.app_is_updatable_expected, myapp.Updatable())
- }
-}
-
-func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
- bp := `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["libbaz"],
- binaries: ["binfoo"],
- min_sdk_version: "29",
- }
- apex_key {
- name: "myapex.key",
- }
- cc_binary {
- name: "binfoo",
- shared_libs: ["libbar", "libbaz", "libqux",],
- apex_available: ["myapex"],
- min_sdk_version: "29",
- recovery_available: false,
- }
- cc_library {
- name: "libbar",
- srcs: ["libbar.cc"],
- stubs: {
- symbol_file: "libbar.map.txt",
- versions: [
- "29",
- ],
- },
- }
- cc_library {
- name: "libbaz",
- srcs: ["libbaz.cc"],
- apex_available: ["myapex"],
- min_sdk_version: "29",
- stubs: {
- symbol_file: "libbaz.map.txt",
- versions: [
- "29",
- ],
- },
- }
- cc_api_library {
- name: "libbar",
- src: "libbar_stub.so",
- min_sdk_version: "29",
- variants: ["apex.29"],
- }
- cc_api_variant {
- name: "libbar",
- variant: "apex",
- version: "29",
- src: "libbar_apex_29.so",
- }
- cc_api_library {
- name: "libbaz",
- src: "libbaz_stub.so",
- min_sdk_version: "29",
- variants: ["apex.29"],
- }
- cc_api_variant {
- name: "libbaz",
- variant: "apex",
- version: "29",
- src: "libbaz_apex_29.so",
- }
- cc_api_library {
- name: "libqux",
- src: "libqux_stub.so",
- min_sdk_version: "29",
- variants: ["apex.29"],
- }
- cc_api_variant {
- name: "libqux",
- variant: "apex",
- version: "29",
- src: "libqux_apex_29.so",
- }
- api_imports {
- name: "api_imports",
- apex_shared_libs: [
- "libbar",
- "libbaz",
- "libqux",
- ],
- }
- `
- result := testApex(t, bp)
-
- hasDep := func(m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
- // Library defines stubs and cc_api_library should be used with cc_api_library
- binfooApexVariant := result.ModuleForTests("binfoo", "android_arm64_armv8-a_apex29").Module()
- libbarCoreVariant := result.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
- libbarApiImportCoreVariant := result.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(binfooApexVariant, libbarApiImportCoreVariant))
- android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbarCoreVariant))
-
- binFooCFlags := result.ModuleForTests("binfoo", "android_arm64_armv8-a_apex29").Rule("ld").Args["libFlags"]
- android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbar.apex.29.apiimport.so")
- android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbar.apiimport.so")
- android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbar.so")
-
- // Library defined in the same APEX should be linked with original definition instead of cc_api_library
- libbazApexVariant := result.ModuleForTests("libbaz", "android_arm64_armv8-a_shared_apex29").Module()
- libbazApiImportCoreVariant := result.ModuleForTests("libbaz.apiimport", "android_arm64_armv8-a_shared").Module()
- android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries even from same APEX", true, hasDep(binfooApexVariant, libbazApiImportCoreVariant))
- android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbazApexVariant))
-
- android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbaz.so")
- android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbaz.apiimport.so")
- android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbaz.apex.29.apiimport.so")
-
- // cc_api_library defined without original library should be linked with cc_api_library
- libquxApiImportApexVariant := result.ModuleForTests("libqux.apiimport", "android_arm64_armv8-a_shared").Module()
- android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries even original library definition does not exist", true, hasDep(binfooApexVariant, libquxApiImportApexVariant))
- android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libqux.apex.29.apiimport.so")
-}
-
-func TestPlatformBinaryBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
- bp := `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["libbar"],
- min_sdk_version: "29",
- }
- apex_key {
- name: "myapex.key",
- }
- cc_binary {
- name: "binfoo",
- shared_libs: ["libbar"],
- recovery_available: false,
- }
- cc_library {
- name: "libbar",
- srcs: ["libbar.cc"],
- apex_available: ["myapex"],
- min_sdk_version: "29",
- stubs: {
- symbol_file: "libbar.map.txt",
- versions: [
- "29",
- ],
- },
- }
- cc_api_library {
- name: "libbar",
- src: "libbar_stub.so",
- variants: ["apex.29"],
- }
- cc_api_variant {
- name: "libbar",
- variant: "apex",
- version: "29",
- src: "libbar_apex_29.so",
- }
- api_imports {
- name: "api_imports",
- apex_shared_libs: [
- "libbar",
- ],
- }
- `
-
- result := testApex(t, bp)
-
- hasDep := func(m android.Module, wantDep android.Module) bool {
- t.Helper()
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
- // Library defines stubs and cc_api_library should be used with cc_api_library
- binfooApexVariant := result.ModuleForTests("binfoo", "android_arm64_armv8-a").Module()
- libbarCoreVariant := result.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
- libbarApiImportCoreVariant := result.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
-
- android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(binfooApexVariant, libbarApiImportCoreVariant))
- android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbarCoreVariant))
-
- binFooCFlags := result.ModuleForTests("binfoo", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
- android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbar.apex.29.apiimport.so")
- android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbar.apiimport.so")
- android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbar.so")
+ _ = android.GroupFixturePreparers(
+ prepareForApexTest,
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("app dependency myapp must have updatable: true")).
+ RunTestWithBp(t, bp)
}
func TestTrimmedApex(t *testing.T) {
@@ -10308,21 +9938,6 @@
apex_available: ["myapex","mydcla"],
min_sdk_version: "29",
}
- cc_api_library {
- name: "libc",
- src: "libc.so",
- min_sdk_version: "29",
- recovery_available: true,
- vendor_available: true,
- product_available: true,
- }
- api_imports {
- name: "api_imports",
- shared_libs: [
- "libc",
- ],
- header_libs: [],
- }
`
ctx := testApex(t, bp)
module := ctx.ModuleForTests("myapex", "android_common_myapex")
@@ -10594,14 +10209,15 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 8 {
- t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 14 {
+ t.Fatalf("Expected 14 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
- ensureMatches(t, copyCmds[5], "^cp -f .*/package.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[6], "^cp -f .*/flag.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[7], "^cp -f .*/flag.val .*/image.apex/etc$")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info.*/image.apex/etc/flag.info")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
@@ -10611,6 +10227,7 @@
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+ VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
}
func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
@@ -10729,14 +10346,15 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 12 {
- t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 18 {
+ t.Fatalf("Expected 18 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
- ensureMatches(t, copyCmds[9], "^cp -f .*/package.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[10], "^cp -f .*/flag.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[11], "^cp -f .*/flag.val .*/image.apex/etc$")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
@@ -10747,6 +10365,7 @@
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+ VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
}
func TestAconfigFilesRustDeps(t *testing.T) {
@@ -10897,14 +10516,15 @@
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 32 {
- t.Fatalf("Expected 28 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 38 {
+ t.Fatalf("Expected 38 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[28], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
- ensureMatches(t, copyCmds[29], "^cp -f .*/package.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[30], "^cp -f .*/flag.map .*/image.apex/etc$")
- ensureMatches(t, copyCmds[31], "^cp -f .*/flag.val .*/image.apex/etc$")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
+ ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
inputs := []string{
"my_aconfig_declarations_foo/intermediate.pb",
@@ -10916,6 +10536,7 @@
VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
+ VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
}
func VerifyAconfigRule(t *testing.T, mod *android.TestingModule, desc string, inputs []string, output string, container string, file_type string) {
@@ -11244,12 +10865,12 @@
{
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.deapexer/android_common/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_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/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
},
}
@@ -11278,11 +10899,7 @@
fs["platform/Test.java"] = nil
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
)
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
checkBootDexJarPath(t, ctx, "framework-foo", tc.expectedBootJar)
@@ -11421,11 +11038,7 @@
android.FixtureMergeMockFs(map[string][]byte{
"system/sepolicy/apex/com.android.foo-file_contexts": nil,
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
)
if tc.expectedError != "" {
preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
@@ -11441,6 +11054,114 @@
}
}
+// Test that product packaging installs the selected mainline module in workspaces withtout source mainline module
+func TestInstallationRulesForMultipleApexPrebuiltsWithoutSource(t *testing.T) {
+ // for a mainline module family, check that only the flagged soong module is visible to make
+ 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"
+ }
+ return ret
+ }
+
+ for _, visibleModuleName := range visibleModuleNames {
+ visibleModule := ctx.ModuleForTests(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()
+ android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
+
+ }
+ }
+
+ bp := `
+ apex_key {
+ name: "com.android.adservices.key",
+ public_key: "com.android.adservices.avbpubkey",
+ private_key: "com.android.adservices.pem",
+ }
+
+ // AOSP source apex
+ apex {
+ name: "com.android.adservices",
+ key: "com.android.adservices.key",
+ updatable: false,
+ }
+
+ // Prebuilt Google APEX.
+
+ prebuilt_apex {
+ name: "com.google.android.adservices",
+ apex_name: "com.android.adservices",
+ src: "com.android.foo-arm.apex",
+ }
+
+ // Another Prebuilt Google APEX
+ prebuilt_apex {
+ name: "com.google.android.adservices.v2",
+ apex_name: "com.android.adservices",
+ src: "com.android.foo-arm.apex",
+ }
+
+ // APEX contribution modules
+
+
+ apex_contributions {
+ name: "adservices.prebuilt.contributions",
+ api_domain: "com.android.adservices",
+ contents: ["prebuilt_com.google.android.adservices"],
+ }
+
+ apex_contributions {
+ name: "adservices.prebuilt.v2.contributions",
+ api_domain: "com.android.adservices",
+ contents: ["prebuilt_com.google.android.adservices.v2"],
+ }
+ `
+
+ testCases := []struct {
+ desc string
+ selectedApexContributions string
+ expectedVisibleModuleNames []string
+ expectedHiddenModuleNames []string
+ }{
+ {
+ desc: "No apex contributions selected, source aosp apex should be visible, and mainline prebuilts should be hidden",
+ selectedApexContributions: "",
+ expectedVisibleModuleNames: []string{"com.android.adservices"},
+ expectedHiddenModuleNames: []string{"com.google.android.adservices", "com.google.android.adservices.v2"},
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.foo 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",
+ selectedApexContributions: "adservices.prebuilt.v2.contributions",
+ expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices.v2"},
+ expectedHiddenModuleNames: []string{"com.google.android.adservices"},
+ },
+ }
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ android.FixtureMergeMockFs(map[string][]byte{
+ "system/sepolicy/apex/com.android.adservices-file_contexts": nil,
+ }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
+ )
+ ctx := testApex(t, bp, preparer)
+
+ checkHideFromMake(t, ctx, tc.expectedVisibleModuleNames, tc.expectedHiddenModuleNames)
+ }
+}
+
func TestAconfifDeclarationsValidation(t *testing.T) {
aconfigDeclarationLibraryString := func(moduleNames []string) (ret string) {
for _, moduleName := range moduleNames {
@@ -11466,9 +11187,6 @@
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo"),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
).RunTestWithBp(t, `
java_library {
name: "baz-java-lib",
@@ -11737,7 +11455,7 @@
).RunTest(t)
ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
- android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
+ android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared_current/libfoo.so")
installRules := result.InstallMakeRulesForTesting(t)
@@ -11844,3 +11562,111 @@
)
})
}
+
+func TestSdkLibraryTransitiveClassLoaderContext(t *testing.T) {
+ // This test case tests that listing the impl lib instead of the top level java_sdk_library
+ // in libs of android_app and java_library does not lead to class loader context device/host
+ // path mismatch errors.
+ android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.PrepareForIntegrationTestWithAndroid,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureModifyEnv(func(env map[string]string) {
+ env["DISABLE_CONTAINER_CHECK"] = "true"
+ }),
+ withFiles(filesForSdkLibrary),
+ android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/com.android.foo30-file_contexts": nil,
+ }),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "com.android.foo30",
+ key: "myapex.key",
+ updatable: true,
+ bootclasspath_fragments: [
+ "foo-bootclasspath-fragment",
+ ],
+ java_libs: [
+ "bar",
+ ],
+ apps: [
+ "bar-app",
+ ],
+ min_sdk_version: "30",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ bootclasspath_fragment {
+ name: "foo-bootclasspath-fragment",
+ contents: [
+ "framework-foo",
+ ],
+ apex_available: [
+ "com.android.foo30",
+ ],
+ hidden_api: {
+ split_packages: ["*"]
+ },
+ }
+
+ java_sdk_library {
+ name: "framework-foo",
+ srcs: [
+ "A.java"
+ ],
+ unsafe_ignore_missing_latest_api: true,
+ apex_available: [
+ "com.android.foo30",
+ ],
+ compile_dex: true,
+ sdk_version: "core_current",
+ shared_library: false,
+ }
+
+ java_library {
+ name: "bar",
+ srcs: [
+ "A.java"
+ ],
+ libs: [
+ "framework-foo.impl",
+ ],
+ apex_available: [
+ "com.android.foo30",
+ ],
+ sdk_version: "core_current",
+ }
+
+ java_library {
+ name: "baz",
+ srcs: [
+ "A.java"
+ ],
+ libs: [
+ "bar",
+ ],
+ sdk_version: "core_current",
+ }
+
+ android_app {
+ name: "bar-app",
+ srcs: [
+ "A.java"
+ ],
+ libs: [
+ "baz",
+ "framework-foo.impl",
+ ],
+ apex_available: [
+ "com.android.foo30",
+ ],
+ sdk_version: "core_current",
+ min_sdk_version: "30",
+ manifest: "AndroidManifest.xml",
+ updatable: true,
+ }
+ `)
+}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 919cb01..e44d3f5 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -53,11 +53,7 @@
java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
java.FixtureConfigureApexBootJars("someapex:foo", "someapex:bar"),
prepareForTestWithArtApex,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo", "baz"),
).RunTestWithBp(t, `
@@ -108,6 +104,7 @@
test: {
enabled: true,
},
+ sdk_version: "core_current",
}
java_library {
@@ -156,7 +153,7 @@
// Check stub dex paths exported by art.
artFragment := result.Module("art-bootclasspath-fragment", "android_common")
- artInfo, _ := android.SingletonModuleProvider(result, artFragment, java.HiddenAPIInfoProvider)
+ artInfo, _ := android.OtherModuleProvider(result, artFragment, java.HiddenAPIInfoProvider)
bazPublicStubs := "out/soong/.intermediates/baz.stubs.exportable/android_common/dex/baz.stubs.exportable.jar"
bazSystemStubs := "out/soong/.intermediates/baz.stubs.exportable.system/android_common/dex/baz.stubs.exportable.system.jar"
@@ -169,7 +166,7 @@
// Check stub dex paths exported by other.
otherFragment := result.Module("other-bootclasspath-fragment", "android_common")
- otherInfo, _ := android.SingletonModuleProvider(result, otherFragment, java.HiddenAPIInfoProvider)
+ otherInfo, _ := android.OtherModuleProvider(result, otherFragment, java.HiddenAPIInfoProvider)
fooPublicStubs := "out/soong/.intermediates/foo.stubs.exportable/android_common/dex/foo.stubs.exportable.jar"
fooSystemStubs := "out/soong/.intermediates/foo.stubs.exportable.system/android_common/dex/foo.stubs.exportable.system.jar"
@@ -401,11 +398,20 @@
// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
addPrebuilt(true, "foo", "bar"),
+ android.FixtureMergeMockFs(android.MockFS{
+ "apex_contributions/Android.bp": []byte(`
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
+ `)}),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
- ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common", []string{
+ ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_com.android.art", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
@@ -498,6 +504,7 @@
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"),
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
)
bp := `
@@ -555,34 +562,33 @@
src: "com.mycompany.android.art.apex",
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
`
t.Run("disabled alternative APEX", func(t *testing.T) {
result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
- `prebuilt_com.android.art.apex.selector`,
- `prebuilt_com.android.art.deapexer`,
})
java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`prebuilt_bar`,
- `prebuilt_com.android.art.deapexer`,
`prebuilt_foo`,
})
module := result.ModuleForTests("dex_bootjars", "android_common")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
-
- t.Run("enabled alternative APEX", func(t *testing.T) {
- preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art")).
- RunTestWithBp(t, fmt.Sprintf(bp, ""))
- })
}
// checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the
@@ -690,7 +696,7 @@
// Make sure that the fragment provides the hidden API encoded dex jars to the APEX.
fragment := result.Module("mybootclasspathfragment", "android_common_apex10000")
- info, _ := android.SingletonModuleProvider(result, fragment, java.BootclasspathFragmentApexContentInfoProvider)
+ info, _ := android.OtherModuleProvider(result, fragment, java.BootclasspathFragmentApexContentInfoProvider)
checkFragmentExportedDexJar := func(name string, expectedDexJar string) {
module := result.Module(name, "android_common_apex10000")
@@ -729,11 +735,7 @@
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo", "quuz"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
apex {
name: "com.android.art",
@@ -755,6 +757,7 @@
],
srcs: ["b.java"],
compile_dex: true,
+ sdk_version: "core_current",
}
java_sdk_library {
@@ -839,6 +842,7 @@
`)
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "all_apex_contributions",
"art-bootclasspath-fragment",
"bar",
"dex2oatd",
@@ -928,6 +932,7 @@
],
srcs: ["b.java"],
compile_dex: true,
+ sdk_version: "core_current",
}
java_library {
@@ -1009,6 +1014,7 @@
`)
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "all_apex_contributions",
"android-non-updatable.stubs",
"android-non-updatable.stubs.module_lib",
"android-non-updatable.stubs.system",
@@ -1099,6 +1105,7 @@
],
srcs: ["b.java"],
compile_dex: true,
+ sdk_version: "core_current",
}
java_library {
@@ -1180,6 +1187,7 @@
`)
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "all_apex_contributions",
"android-non-updatable.stubs",
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
@@ -1251,6 +1259,7 @@
],
srcs: ["b.java"],
compile_dex: true,
+ sdk_version: "core_current",
}
java_library {
@@ -1332,6 +1341,7 @@
`)
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "all_apex_contributions",
"art-bootclasspath-fragment",
"bar",
"dex2oatd",
diff --git a/apex/builder.go b/apex/builder.go
index 6f645ab..371d7d5 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -83,6 +83,7 @@
pctx.HostBinToolVariable("assemble_vintf", "assemble_vintf")
pctx.HostBinToolVariable("apex_elf_checker", "apex_elf_checker")
pctx.HostBinToolVariable("aconfig", "aconfig")
+ pctx.HostBinToolVariable("host_apex_verifier", "host_apex_verifier")
}
type createStorageStruct struct {
@@ -95,6 +96,7 @@
{"package.map", "create_aconfig_package_map_file", "package_map"},
{"flag.map", "create_aconfig_flag_map_file", "flag_map"},
{"flag.val", "create_aconfig_flag_val_file", "flag_val"},
+ {"flag.info", "create_aconfig_flag_info_file", "flag_info"},
}
var (
@@ -249,6 +251,13 @@
Description: "run apex_linkerconfig_validation",
}, "image_dir")
+ apexHostVerifierRule = pctx.StaticRule("apexHostVerifierRule", blueprint.RuleParams{
+ Command: `${host_apex_verifier} --deapexer=${deapexer} --debugfs=${debugfs_static} ` +
+ `--fsckerofs=${fsck_erofs} --apex=${in} && touch ${out}`,
+ CommandDeps: []string{"${host_apex_verifier}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}"},
+ Description: "run host_apex_verifier",
+ })
+
assembleVintfRule = pctx.StaticRule("assembleVintfRule", blueprint.RuleParams{
Command: `rm -f $out && VINTF_IGNORE_TARGET_FCM_VERSION=true ${assemble_vintf} -i $in -o $out`,
CommandDeps: []string{"${assemble_vintf}"},
@@ -262,6 +271,58 @@
}, "tool_path", "unwanted")
)
+func (a *apexBundle) buildAconfigFiles(ctx android.ModuleContext) []apexFile {
+ var aconfigFiles android.Paths
+ for _, file := range a.filesInfo {
+ if file.module == nil {
+ continue
+ }
+ if dep, ok := android.OtherModuleProvider(ctx, file.module, android.AconfigPropagatingProviderKey); ok {
+ if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
+ aconfigFiles = append(aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
+ }
+ }
+
+ validationFlag := ctx.DeviceConfig().AconfigContainerValidation()
+ if validationFlag == "error" || validationFlag == "warning" {
+ android.VerifyAconfigBuildMode(ctx, ctx.ModuleName(), file.module, validationFlag == "error")
+ }
+ }
+ aconfigFiles = android.FirstUniquePaths(aconfigFiles)
+
+ var files []apexFile
+ if len(aconfigFiles) > 0 {
+ apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aconfig.AllDeclarationsRule,
+ Inputs: aconfigFiles,
+ Output: apexAconfigFile,
+ Description: "combine_aconfig_declarations",
+ Args: map[string]string{
+ "cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "),
+ },
+ })
+ files = append(files, newApexFile(ctx, apexAconfigFile, "aconfig_flags", "etc", etc, nil))
+
+ for _, info := range createStorageInfo {
+ outputFile := android.PathForModuleOut(ctx, info.Output_file)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aconfig.CreateStorageRule,
+ Inputs: aconfigFiles,
+ Output: outputFile,
+ Description: info.Desc,
+ Args: map[string]string{
+ "container": ctx.ModuleName(),
+ "file_type": info.File_type,
+ "cache_files": android.JoinPathsWithPrefix(aconfigFiles, "--cache "),
+ },
+ })
+ files = append(files, newApexFile(ctx, outputFile, info.File_type, "etc", etc, nil))
+ }
+ }
+ return files
+}
+
// buildManifest creates buile rules to modify the input apex_manifest.json to add information
// gathered by the build system such as provided/required native libraries. Two output files having
// different formats are generated. a.manifestJsonOut is JSON format for Q devices, and
@@ -299,14 +360,14 @@
}
manifestJsonFullOut := android.PathForModuleOut(ctx, "apex_manifest_full.json")
- defaultVersion := android.DefaultUpdatableModuleVersion
+ defaultVersion := ctx.Config().ReleaseDefaultUpdatableModuleVersion()
if a.properties.Variant_version != nil {
defaultVersionInt, err := strconv.Atoi(defaultVersion)
if err != nil {
- ctx.ModuleErrorf("expected DefaultUpdatableModuleVersion to be an int, but got %s", defaultVersion)
+ ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to be an int, but got %s", defaultVersion)
}
if defaultVersionInt%10 != 0 {
- ctx.ModuleErrorf("expected DefaultUpdatableModuleVersion to end in a zero, but got %s", defaultVersion)
+ ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to end in a zero, but got %s", defaultVersion)
}
variantVersion := []rune(*a.properties.Variant_version)
if len(variantVersion) != 1 || variantVersion[0] < '0' || variantVersion[0] > '9' {
@@ -595,7 +656,7 @@
if len(installMapSet) > 0 {
var installs []string
installs = append(installs, android.SortedKeys(installMapSet)...)
- a.SetLicenseInstallMap(installs)
+ ctx.SetLicenseInstallMap(installs)
}
////////////////////////////////////////////////////////////////////////////////////////////
@@ -644,48 +705,10 @@
outHostBinDir := ctx.Config().HostToolPath(ctx, "").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
- defaultReadOnlyFiles := []string{"apex_manifest.json", "apex_manifest.pb"}
- aconfigDest := imageDir.Join(ctx, "etc").String()
- if len(a.aconfigFiles) > 0 {
- apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb")
- ctx.Build(pctx, android.BuildParams{
- Rule: aconfig.AllDeclarationsRule,
- Inputs: a.aconfigFiles,
- Output: apexAconfigFile,
- Description: "combine_aconfig_declarations",
- Args: map[string]string{
- "cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "),
- },
- })
-
- copyCommands = append(copyCommands, "cp -f "+apexAconfigFile.String()+" "+aconfigDest)
- implicitInputs = append(implicitInputs, apexAconfigFile)
- defaultReadOnlyFiles = append(defaultReadOnlyFiles, "etc/"+apexAconfigFile.Base())
-
- for _, info := range createStorageInfo {
- outputFile := android.PathForModuleOut(ctx, info.Output_file)
- ctx.Build(pctx, android.BuildParams{
- Rule: aconfig.CreateStorageRule,
- Inputs: a.aconfigFiles,
- Output: outputFile,
- Description: info.Desc,
- Args: map[string]string{
- "container": ctx.ModuleName(),
- "file_type": info.File_type,
- "cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "),
- },
- })
-
- copyCommands = append(copyCommands, "cp -f "+outputFile.String()+" "+aconfigDest)
- implicitInputs = append(implicitInputs, outputFile)
- defaultReadOnlyFiles = append(defaultReadOnlyFiles, "etc/"+outputFile.Base())
- }
- }
-
////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
// in this APEX. The file will be used by apexer in later steps.
- cannedFsConfig := a.buildCannedFsConfig(ctx, defaultReadOnlyFiles)
+ cannedFsConfig := a.buildCannedFsConfig(ctx)
implicitInputs = append(implicitInputs, cannedFsConfig)
////////////////////////////////////////////////////////////////////////////////////
@@ -704,7 +727,7 @@
optFlags = append(optFlags, "--override_apk_package_name "+manifestPackageName)
}
- androidManifest := a.properties.AndroidManifest.GetOrDefault(a.ConfigurableEvaluator(ctx), "")
+ androidManifest := a.properties.AndroidManifest.GetOrDefault(ctx, "")
if androidManifest != "" {
androidManifestFile := android.PathForModuleSrc(ctx, androidManifest)
@@ -952,6 +975,9 @@
validations = append(validations,
runApexElfCheckerUnwanted(ctx, unsignedOutputFile.OutputPath, a.properties.Unwanted_transitive_deps))
}
+ if !a.testApex && android.InList(a.payloadFsType, []fsType{ext4, erofs}) {
+ validations = append(validations, runApexHostVerifier(ctx, unsignedOutputFile.OutputPath))
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "signapk",
@@ -1048,8 +1074,9 @@
}
return ""
}
- if a.overridableProperties.Package_name != "" {
- return a.overridableProperties.Package_name
+ packageNameFromProp := a.overridableProperties.Package_name.GetOrDefault(ctx, "")
+ if packageNameFromProp != "" {
+ return packageNameFromProp
}
manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
if overridden {
@@ -1066,7 +1093,7 @@
}
depInfos := android.DepNameToDepInfoMap{}
- a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, 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.
@@ -1133,14 +1160,27 @@
func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
depSetsBuilder := java.NewLintDepSetBuilder()
for _, fi := range a.filesInfo {
- depSetsBuilder.Transitive(fi.lintDepSets)
+ if fi.lintInfo != nil {
+ depSetsBuilder.Transitive(fi.lintInfo)
+ }
}
- a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
+ depSets := depSetsBuilder.Build()
+ var validations android.Paths
+
+ if a.checkStrictUpdatabilityLinting(ctx) {
+ baselines := depSets.Baseline.ToList()
+ if len(baselines) > 0 {
+ outputFile := java.VerifyStrictUpdatabilityChecks(ctx, baselines)
+ validations = append(validations, outputFile)
+ }
+ }
+
+ a.lintReports = java.BuildModuleLintReportZips(ctx, depSets, validations)
}
-func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext, defaultReadOnlyFiles []string) android.OutputPath {
- var readOnlyPaths = defaultReadOnlyFiles
+func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
+ var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
var executablePaths []string // this also includes dirs
var appSetDirs []string
appSetFiles := make(map[string]android.Path)
@@ -1196,7 +1236,7 @@
}
// Custom fs_config is "appended" to the last so that entries from the file are preferred
// over default ones set above.
- customFsConfig := a.properties.Canned_fs_config.GetOrDefault(a.ConfigurableEvaluator(ctx), "")
+ customFsConfig := a.properties.Canned_fs_config.GetOrDefault(ctx, "")
if customFsConfig != "" {
cmd.Text("cat").Input(android.PathForModuleSrc(ctx, customFsConfig))
}
@@ -1246,3 +1286,13 @@
})
return timestamp
}
+
+func runApexHostVerifier(ctx android.ModuleContext, apexFile android.OutputPath) android.Path {
+ timestamp := android.PathForModuleOut(ctx, "host_apex_verifier.timestamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexHostVerifierRule,
+ Input: apexFile,
+ Output: timestamp,
+ })
+ return timestamp
+}
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index b9a9198..9e1ac94 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -92,6 +92,7 @@
],
srcs: ["b.java"],
installable: true,
+ sdk_version: "core_current",
}
java_library {
diff --git a/apex/container_test.go b/apex/container_test.go
index 3931174..d28b1a6 100644
--- a/apex/container_test.go
+++ b/apex/container_test.go
@@ -30,7 +30,7 @@
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
- java.FixtureWithLastReleaseApis("mybootclasspathlib"),
+ java.FixtureWithLastReleaseApis("mybootclasspathlib", "bar"),
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -68,16 +68,17 @@
],
compile_dex: true,
static_libs: [
- "foo",
+ "food",
"baz",
],
libs: [
- "bar",
+ "bar.stubs",
],
min_sdk_version: "30",
+ sdk_version: "current",
}
java_library {
- name: "foo",
+ name: "food",
srcs:[
"A.java",
],
@@ -85,13 +86,15 @@
"myapex",
],
min_sdk_version: "30",
+ sdk_version: "core_current",
}
- java_library {
+ java_sdk_library {
name: "bar",
srcs:[
"A.java",
],
min_sdk_version: "30",
+ sdk_version: "core_current",
}
java_library {
name: "baz",
@@ -103,6 +106,7 @@
"myapex",
],
min_sdk_version: "30",
+ sdk_version: "core_current",
}
`)
testcases := []struct {
@@ -130,7 +134,7 @@
isApexContainer: false,
},
{
- moduleName: "foo",
+ moduleName: "food",
variant: "android_common_apex30",
isSystemContainer: true,
isApexContainer: true,
@@ -162,7 +166,7 @@
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
- java.FixtureWithLastReleaseApis("mybootclasspathlib"),
+ java.FixtureWithLastReleaseApis("mybootclasspathlib", "bar"),
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -199,26 +203,30 @@
],
compile_dex: true,
static_libs: [
- "foo",
+ "food",
],
libs: [
- "bar",
+ "bar.stubs",
],
+ sdk_version: "current",
}
java_library {
- name: "foo",
+ name: "food",
srcs:[
"A.java",
],
apex_available: [
"myapex",
],
+ sdk_version: "core_current",
}
- java_library {
+ java_sdk_library {
name: "bar",
srcs:[
"A.java",
],
+ sdk_version: "none",
+ system_modules: "none",
}
`)
testcases := []struct {
@@ -246,7 +254,7 @@
isApexContainer: false,
},
{
- moduleName: "foo",
+ moduleName: "food",
variant: "android_common_apex10000",
isSystemContainer: true,
isApexContainer: true,
diff --git a/apex/deapexer.go b/apex/deapexer.go
index a673108..3b8233d 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -15,37 +15,9 @@
package apex
import (
- "strings"
-
"android/soong/android"
)
-// Contains 'deapexer' a private module type used by 'prebuilt_apex' to make dex files contained
-// within a .apex file referenced by `prebuilt_apex` available for use by their associated
-// `java_import` modules.
-//
-// An 'apex' module references `java_library` modules from which .dex files are obtained that are
-// stored in the resulting `.apex` file. The resulting `.apex` file is then made available as a
-// prebuilt by referencing it from a `prebuilt_apex`. For each such `java_library` that is used by
-// modules outside the `.apex` file a `java_import` prebuilt is made available referencing a jar
-// that contains the Java classes.
-//
-// When building a Java module type, e.g. `java_module` or `android_app` against such prebuilts the
-// `java_import` provides the classes jar (jar containing `.class` files) against which the
-// module's `.java` files are compiled. That classes jar usually contains only stub classes. The
-// resulting classes jar is converted into a dex jar (jar containing `.dex` files). Then if
-// necessary the dex jar is further processed by `dexpreopt` to produce an optimized form of the
-// library specific to the current Android version. This process requires access to implementation
-// dex jars for each `java_import`. The `java_import` will obtain the implementation dex jar from
-// the `.apex` file in the associated `prebuilt_apex`.
-//
-// This is intentionally not registered by name as it is not intended to be used from within an
-// `Android.bp` file.
-
-// DeapexerProperties specifies the properties supported by the deapexer module.
-//
-// As these are never intended to be supplied in a .bp file they use a different naming convention
-// to make it clear that they are different.
type DeapexerProperties struct {
// List of common modules that may need access to files exported by this module.
//
@@ -72,46 +44,9 @@
Selected_apex *string `android:"path" blueprint:"mutated"`
}
-type Deapexer struct {
- android.ModuleBase
-
- properties DeapexerProperties
- selectedApexProperties SelectedApexProperties
-
- inputApex android.Path
-}
-
-// Returns the name of the deapexer module corresponding to an APEX module with the given name.
-func deapexerModuleName(apexModuleName string) string {
- return apexModuleName + ".deapexer"
-}
-
-// Returns the name of the APEX module corresponding to an deapexer module with
-// the given name. This reverses deapexerModuleName.
-func apexModuleName(deapexerModuleName string) string {
- return strings.TrimSuffix(deapexerModuleName, ".deapexer")
-}
-
-func privateDeapexerFactory() android.Module {
- module := &Deapexer{}
- module.AddProperties(&module.properties, &module.selectedApexProperties)
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- return module
-}
-
-func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependencies from the java modules to which this exports files from the `.apex` file onto
- // this module so that they can access the `DeapexerInfo` object that this provides.
- // TODO: b/308174306 - Once all the mainline modules have been flagged, drop this dependency edge
- for _, lib := range p.properties.CommonModules {
- dep := prebuiltApexExportedModuleName(ctx, lib)
- ctx.AddReverseDependency(ctx.Module(), android.DeapexerTag, dep)
- }
-}
-
-func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
-
+// deapex creates the build rules to deapex a prebuilt .apex file
+// it returns a pointer to a DeapexerInfo object
+func deapex(ctx android.ModuleContext, apexFile android.Path, deapexerProps DeapexerProperties) *android.DeapexerInfo {
// Create and remember the directory into which the .apex file's contents will be unpacked.
deapexerOutput := android.PathForModuleOut(ctx, "deapexer")
@@ -119,7 +54,7 @@
// Create mappings from apex relative path to the extracted file's path.
exportedPaths := make(android.Paths, 0, len(exports))
- for _, path := range p.properties.ExportedFiles {
+ for _, path := range deapexerProps.ExportedFiles {
// Populate the exports that this makes available.
extractedPath := deapexerOutput.Join(ctx, path)
exports[path] = extractedPath
@@ -131,9 +66,8 @@
// apex relative path to extracted file path available for other modules.
if len(exports) > 0 {
// Make the information available for other modules.
- di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules)
- di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...)
- android.SetProvider(ctx, android.DeapexerProvider, di)
+ di := android.NewDeapexerInfo(ctx.ModuleName(), exports, deapexerProps.CommonModules)
+ di.AddDexpreoptProfileGuidedExportedModuleNames(deapexerProps.DexpreoptProfileGuidedModules...)
// Create a sorted list of the files that this exports.
exportedPaths = android.SortedUniquePaths(exportedPaths)
@@ -147,11 +81,13 @@
BuiltTool("deapexer").
BuiltTool("debugfs").
BuiltTool("fsck.erofs").
- Input(p.inputApex).
+ Input(apexFile).
Text(deapexerOutput.String())
for _, p := range exportedPaths {
command.Output(p.(android.WritablePath))
}
- builder.Build("deapexer", "deapex "+apexModuleName(ctx.ModuleName()))
+ builder.Build("deapexer", "deapex "+ctx.ModuleName())
+ return &di
}
+ return nil
}
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index 7a17f50..4feade8 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -127,16 +127,29 @@
src: "com.android.art-arm.apex",
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
`
- result := android.GroupFixturePreparers(
+ fixture := android.GroupFixturePreparers(
java.PrepareForTestWithDexpreopt,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo"),
java.FixtureConfigureBootJars("com.android.art:core-oj", "platform:foo", "system_ext:bar", "platform:baz"),
PrepareForTestWithApexBuildComponents,
prepareForTestWithArtApex,
- ).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
+ )
+ if preferPrebuilt {
+ fixture = android.GroupFixturePreparers(
+ fixture,
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
+ )
+ }
+ result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt))
dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
rule := dexBootJars.Output(ruleFile)
@@ -200,7 +213,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.deapexer/android_common/deapexer/etc/boot-image.prof",
+ "out/soong/.intermediates/prebuilt_com.android.art/android_common_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",
}
@@ -384,12 +397,12 @@
{
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.deapexer/android_common/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_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/prebuilt_com.android.art.v2.deapexer/android_common/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_com.android.art/deapexer/etc/boot-image.prof",
},
}
for _, tc := range testCases {
@@ -399,11 +412,7 @@
java.FixtureConfigureBootJars("com.android.art:core-oj"),
PrepareForTestWithApexBuildComponents,
prepareForTestWithArtApex,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ART": tc.selectedArtApexContributions,
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", tc.selectedArtApexContributions),
).RunTestWithBp(t, bp)
dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
@@ -413,3 +422,106 @@
android.AssertStringListContains(t, tc.desc, inputs, tc.expectedProfile)
}
}
+
+// Check that dexpreopt works with Google mainline prebuilts even in workspaces where source is missing
+func TestDexpreoptWithMainlinePrebuiltNoSource(t *testing.T) {
+ bp := `
+ // Platform.
+
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+
+ // Source AOSP ART apex
+ java_library {
+ name: "core-oj",
+ srcs: ["core-oj.java"],
+ installable: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["core-oj"],
+ apex_available: [
+ "com.android.art",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+
+ // Prebuilt Google ART APEX.
+
+ java_import {
+ name: "core-oj",
+ jars: ["core-oj.jar"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["core-oj"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ prebuilt_apex {
+ name: "com.google.android.art",
+ apex_name: "com.android.art",
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
+ apex_contributions {
+ name: "art.prebuilt.contributions",
+ api_domain: "com.android.art",
+ contents: ["prebuilt_com.google.android.art"],
+ }
+ `
+ res := android.GroupFixturePreparers(
+ java.PrepareForTestWithDexpreopt,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureConfigureBootJars("com.android.art:core-oj"),
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithArtApex,
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "art.prebuilt.contributions"),
+ ).RunTestWithBp(t, bp)
+ if !java.CheckModuleHasDependency(t, res.TestContext, "dex_bootjars", "android_common", "prebuilt_com.google.android.art") {
+ t.Errorf("Expected dexpreopt to use prebuilt apex")
+ }
+}
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 4a20cf0..f4da31e 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -154,7 +154,7 @@
).RunTest(t)
pbcp := result.Module("platform-bootclasspath", "android_common")
- info, _ := android.SingletonModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
+ info, _ := android.OtherModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
for _, category := range java.HiddenAPIFlagFileCategories {
name := category.PropertyName()
@@ -236,7 +236,7 @@
)
pbcp := result.Module("myplatform-bootclasspath", "android_common")
- info, _ := android.SingletonModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
+ 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())
@@ -254,11 +254,7 @@
java.FixtureWithLastReleaseApis("foo"),
java.PrepareForTestWithDexpreopt,
dexpreopt.FixtureDisableDexpreoptBootImages(false),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
apex {
name: "com.android.art",
@@ -297,6 +293,7 @@
],
srcs: ["b.java"],
installable: true,
+ sdk_version: "core_current",
}
// Add a java_import that is not preferred and so won't have an appropriate apex variant created
@@ -412,6 +409,9 @@
// The fragments.
`com.android.art:art-bootclasspath-fragment`,
`myapex:my-bootclasspath-fragment`,
+
+ // Impl lib of sdk_library for transitive srcjar generation
+ `platform:foo.impl`,
})
}
@@ -429,10 +429,9 @@
java.PrepareForTestWithJavaSdkLibraryFiles,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
}),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
+
java.FixtureWithPrebuiltApis(map[string][]string{
"current": {},
"30": {"foo"},
@@ -569,6 +568,9 @@
// The fragments.
"myapex:mybootclasspath-fragment",
"myapex:prebuilt_mybootclasspath-fragment",
+
+ // Impl lib of sdk_library for transitive srcjar generation
+ "platform:foo.impl",
})
}
@@ -796,6 +798,128 @@
`)
}
+// Skip bcp_fragment content validation of source apexes if prebuilts are active.
+func TestNonBootJarInPrebuilts(t *testing.T) {
+ testCases := []struct {
+ description string
+ selectedApexContributions string
+ expectedError string
+ }{
+ {
+ description: "source is active",
+ selectedApexContributions: "",
+ expectedError: "in contents must also be declared in PRODUCT_APEX_BOOT_JARS",
+ },
+ {
+ description: "prebuilts are active",
+ selectedApexContributions: "myapex.prebuilt.contributions",
+ expectedError: "", // skip content validation of source bcp fragment
+ },
+ }
+ bp := `
+// Source
+apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["apex-fragment"],
+ updatable: false,
+ min_sdk_version: "29",
+}
+
+override_apex {
+ name: "myapex.override", // overrides the min_sdk_version, thereby creating different variants of its transitive deps
+ base: "myapex",
+ min_sdk_version: "34",
+}
+
+apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+}
+
+java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ min_sdk_version: "29",
+}
+
+java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["bar"],
+ min_sdk_version: "29",
+}
+
+bootclasspath_fragment {
+ name: "apex-fragment",
+ contents: ["foo", "bar"],
+ apex_available:[ "myapex" ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+}
+
+platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ fragments: [{
+ apex: "myapex",
+ module:"apex-fragment",
+ }],
+}
+
+// prebuilts
+prebuilt_apex {
+ name: "myapex",
+ apex_name: "myapex",
+ src: "myapex.apex",
+ exported_bootclasspath_fragments: ["apex-fragment"],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "apex-fragment",
+ contents: ["foo"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ }
+ java_import {
+ name: "foo",
+ jars: ["foo.jar"],
+ }
+
+apex_contributions {
+ name: "myapex.prebuilt.contributions",
+ api_domain: "myapex",
+ contents: ["prebuilt_myapex"],
+}
+`
+
+ for _, tc := range testCases {
+ fixture := android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
+ )
+ if tc.expectedError != "" {
+ fixture = fixture.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError))
+ }
+ fixture.RunTestWithBp(t, bp)
+ }
+
+}
+
// Source and prebuilt apex provide different set of boot jars
func TestNonBootJarMissingInPrebuiltFragment(t *testing.T) {
bp := `
@@ -935,11 +1059,7 @@
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
java.FixtureConfigureApexBootJars(tc.configuredBootJars...),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ART": "my_apex_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "my_apex_contributions"),
)
if tc.errorExpected {
fixture = fixture.ExtendWithErrorHandler(
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index b9cc09b..9cd5688 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -15,9 +15,6 @@
package apex
import (
- "fmt"
- "io"
- "path/filepath"
"strconv"
"strings"
@@ -42,6 +39,11 @@
CommandDeps: []string{"${extract_apks}"},
},
"abis", "allow-prereleased", "sdk-version", "skip-sdk-check")
+ decompressApex = pctx.StaticRule("decompressApex", blueprint.RuleParams{
+ Command: `rm -rf $out && ${deapexer} decompress --copy-if-uncompressed --input ${in} --output ${out}`,
+ CommandDeps: []string{"${deapexer}"},
+ Description: "decompress $out",
+ })
)
type prebuilt interface {
@@ -65,10 +67,6 @@
// fragment for this apex for apexkeys.txt
apexKeysPath android.WritablePath
- // A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used
- // to create make modules in prebuiltCommon.AndroidMkEntries.
- apexFilesForAndroidMk []apexFile
-
// Installed locations of symlinks for backward compatibility.
compatSymlinks android.InstallPaths
@@ -109,11 +107,6 @@
// from PRODUCT_PACKAGES.
Overrides []string
- // List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
- // APEX bundle will create an APEX variant and provide dex implementation jars for use by
- // dexpreopt and boot jars package check.
- Exported_java_libs []string
-
// List of bootclasspath fragments inside this prebuilt APEX bundle and for which this APEX
// bundle will create an APEX variant.
Exported_bootclasspath_fragments []string
@@ -197,14 +190,12 @@
// 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())
- install.PackageFile(ctx)
}
}
// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex
-func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) {
- // If this apex does not export anything, return
- if !p.hasExportedDeps() {
+func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext, di *android.DeapexerInfo) {
+ if di == nil {
return
}
// If this prebuilt apex has not been selected, return
@@ -213,10 +204,7 @@
}
// Use apex_name to determine the api domain of this prebuilt apex
apexName := p.ApexVariationName()
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- }
+ // TODO: do not compute twice
dc := dexpreopt.GetGlobalConfig(ctx)
systemServerJarList := dc.AllApexSystemServerJars(ctx)
@@ -231,11 +219,6 @@
}
func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) {
- for _, fi := range p.apexFilesForAndroidMk {
- entries.AddStrings("LOCAL_REQUIRED_MODULES", fi.requiredModuleNames...)
- entries.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", fi.targetRequiredModuleNames...)
- entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", fi.hostRequiredModuleNames...)
- }
entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...)
}
@@ -267,77 +250,11 @@
entriesList = append(entriesList, install.ToMakeEntries())
}
- // Iterate over the apexFilesForAndroidMk list and create an AndroidMkEntries struct for each
- // file. This provides similar behavior to that provided in apexBundle.AndroidMk() as it makes the
- // apex specific variants of the exported java modules available for use from within make.
- apexName := p.BaseModuleName()
- for _, fi := range p.apexFilesForAndroidMk {
- entries := p.createEntriesForApexFile(fi, apexName)
- entriesList = append(entriesList, entries)
- }
-
return entriesList
}
-// createEntriesForApexFile creates an AndroidMkEntries for the supplied apexFile
-func (p *prebuiltCommon) createEntriesForApexFile(fi apexFile, apexName string) android.AndroidMkEntries {
- moduleName := fi.androidMkModuleName + "." + apexName
- entries := android.AndroidMkEntries{
- Class: fi.class.nameInMake(),
- OverrideName: moduleName,
- OutputFile: android.OptionalPathForPath(fi.builtFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", p.installDir.String())
- entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", filepath.Join(p.installDir.String(), fi.stem()))
- entries.SetString("LOCAL_SOONG_INSTALL_PAIRS",
- fi.builtFile.String()+":"+filepath.Join(p.installDir.String(), fi.stem()))
-
- // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
- // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
- // we will have foo.jar.jar
- entries.SetString("LOCAL_MODULE_STEM", strings.TrimSuffix(fi.stem(), ".jar"))
- entries.SetString("LOCAL_SOONG_DEX_JAR", fi.builtFile.String())
- entries.SetString("LOCAL_DEX_PREOPT", "false")
- },
- },
- ExtraFooters: []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- // m <module_name> will build <module_name>.<apex_name> as well.
- if fi.androidMkModuleName != moduleName {
- fmt.Fprintf(w, ".PHONY: %s\n", fi.androidMkModuleName)
- fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
- }
- },
- },
- }
- return entries
-}
-
-// prebuiltApexModuleCreator defines the methods that need to be implemented by prebuilt_apex and
-// apex_set in order to create the modules needed to provide access to the prebuilt .apex file.
-type prebuiltApexModuleCreator interface {
- createPrebuiltApexModules(ctx android.TopDownMutatorContext)
-}
-
-// prebuiltApexModuleCreatorMutator is the mutator responsible for invoking the
-// prebuiltApexModuleCreator's createPrebuiltApexModules method.
-//
-// It is registered as a pre-arch mutator as it must run after the ComponentDepsMutator because it
-// will need to access dependencies added by that (exported modules) but must run before the
-// DepsMutator so that the deapexer module it creates can add dependencies onto itself from the
-// exported modules.
-func prebuiltApexModuleCreatorMutator(ctx android.TopDownMutatorContext) {
- module := ctx.Module()
- if creator, ok := module.(prebuiltApexModuleCreator); ok {
- creator.createPrebuiltApexModules(ctx)
- }
-}
-
func (p *prebuiltCommon) hasExportedDeps() bool {
- return len(p.prebuiltCommonProperties.Exported_java_libs) > 0 ||
- len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 ||
+ return len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 ||
len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0
}
@@ -345,11 +262,6 @@
func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
- for _, dep := range p.prebuiltCommonProperties.Exported_java_libs {
- prebuiltDep := android.PrebuiltNameFromSource(dep)
- ctx.AddDependency(module, exportedJavaLibTag, prebuiltDep)
- }
-
for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
prebuiltDep := android.PrebuiltNameFromSource(dep)
ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep)
@@ -467,34 +379,6 @@
}
}
-// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex
-// module. It selects the apex to use and makes it available for use by prebuilt_apex and the
-// deapexer.
-type prebuiltApexSelectorModule struct {
- android.ModuleBase
-
- apexFileProperties ApexFileProperties
-
- inputApex android.Path
-}
-
-func privateApexSelectorModuleFactory() android.Module {
- module := &prebuiltApexSelectorModule{}
- module.AddProperties(
- &module.apexFileProperties,
- )
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- return module
-}
-
-func (p *prebuiltApexSelectorModule) Srcs() android.Paths {
- return android.Paths{p.inputApex}
-}
-
-func (p *prebuiltApexSelectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src")
-}
-
type Prebuilt struct {
prebuiltCommon
@@ -511,7 +395,7 @@
// This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated
// for android_common. That is so that it will have the same arch variant as, and so be compatible
// with, the source `apex` module type that it replaces.
- Src *string `android:"path"`
+ Src proptools.Configurable[string] `android:"path,replace_instead_of_append"`
Arch struct {
Arm struct {
Src *string `android:"path"`
@@ -537,11 +421,11 @@
// to use methods on it that are specific to the current module.
//
// See the ApexFileProperties.Src property.
-func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) []string {
+func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) string {
multiTargets := prebuilt.MultiTargets()
if len(multiTargets) != 1 {
ctx.OtherModuleErrorf(prebuilt, "compile_multilib shouldn't be \"both\" for prebuilt_apex")
- return nil
+ return ""
}
var src string
switch multiTargets[0].Arch.ArchType {
@@ -561,7 +445,7 @@
src = String(p.Arch.X86_64.Src)
}
if src == "" {
- src = String(p.Src)
+ src = p.Src.GetOrDefault(ctx, "")
}
if src == "" {
@@ -574,7 +458,7 @@
// logic from reporting a more general, less useful message.
}
- return []string{src}
+ return src
}
type PrebuiltProperties struct {
@@ -591,35 +475,19 @@
func PrebuiltFactory() android.Module {
module := &Prebuilt{}
module.AddProperties(&module.properties)
- module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties)
+ module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties
+
+ // init the module as a prebuilt
+ // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing
+ // InitPrebuiltModule* are not friendly with Sources of Configurable type.
+ // The actual src will be evaluated in GenerateAndroidBuildActions.
+ android.InitPrebuiltModuleWithoutSrcs(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
-func createApexSelectorModule(ctx android.TopDownMutatorContext, name string, apexFileProperties *ApexFileProperties) {
- props := struct {
- Name *string
- }{
- Name: proptools.StringPtr(name),
- }
-
- ctx.CreateModule(privateApexSelectorModuleFactory,
- &props,
- apexFileProperties,
- )
-}
-
-// createDeapexerModuleIfNeeded will create a deapexer module if it is needed.
-//
-// A deapexer module is only needed when the prebuilt apex specifies one or more modules in either
-// the `exported_java_libs` or `exported_bootclasspath_fragments` properties as that indicates that
-// the listed modules need access to files from within the prebuilt .apex file.
-func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerName string, apexFileSource string) {
- // Only create the deapexer module if it is needed.
- if !p.hasExportedDeps() {
- return
- }
-
+func (p *prebuiltCommon) getDeapexerPropertiesIfNeeded(ctx android.ModuleContext) DeapexerProperties {
// Compute the deapexer properties from the transitive dependencies of this module.
commonModules := []string{}
dexpreoptProfileGuidedModules := []string{}
@@ -653,7 +521,7 @@
})
// Create properties for deapexer module.
- deapexerProperties := &DeapexerProperties{
+ deapexerProperties := DeapexerProperties{
// Remove any duplicates from the common modules lists as a module may be included via a direct
// dependency as well as transitive ones.
CommonModules: android.SortedUniqueStrings(commonModules),
@@ -662,22 +530,7 @@
// Populate the exported files property in a fixed order.
deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles)
-
- props := struct {
- Name *string
- Selected_apex *string
- }{
- Name: proptools.StringPtr(deapexerName),
- Selected_apex: proptools.StringPtr(apexFileSource),
- }
- ctx.CreateModule(privateDeapexerFactory,
- &props,
- deapexerProperties,
- )
-}
-
-func apexSelectorModuleName(baseModuleName string) string {
- return baseModuleName + ".apex.selector"
+ return deapexerProperties
}
func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string {
@@ -719,97 +572,50 @@
var _ android.RequiresFilesFromPrebuiltApexTag = exportedDependencyTag{}
var (
- exportedJavaLibTag = exportedDependencyTag{name: "exported_java_libs"}
exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
exportedSystemserverclasspathFragmentTag = exportedDependencyTag{name: "exported_systemserverclasspath_fragments"}
)
-var _ prebuiltApexModuleCreator = (*Prebuilt)(nil)
-
-// createPrebuiltApexModules creates modules necessary to export files from the prebuilt apex to the
-// build.
-//
-// If this needs to make files from within a `.apex` file available for use by other Soong modules,
-// e.g. make dex implementation jars available for java_import modules listed in exported_java_libs,
-// it does so as follows:
-//
-// 1. It creates a `deapexer` module that actually extracts the files from the `.apex` file and
-// makes them available for use by other modules, at both Soong and ninja levels.
-//
-// 2. It adds a dependency onto those modules and creates an apex specific variant similar to what
-// an `apex` module does. That ensures that code which looks for specific apex variant, e.g.
-// dexpreopt, will work the same way from source and prebuilt.
-//
-// 3. The `deapexer` module adds a dependency from the modules that require the exported files onto
-// itself so that they can retrieve the file paths to those files.
-//
-// It also creates a child module `selector` that is responsible for selecting the appropriate
-// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
-//
-// 1. To dedup the selection logic so it only runs in one module.
-//
-// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
-// `apex_set`.
-//
-// prebuilt_apex
-// / | \
-// / | \
-// V V V
-// selector <--- deapexer <--- exported java lib
-func (p *Prebuilt) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
- apexSelectorModuleName := apexSelectorModuleName(p.Name())
- createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties)
-
- apexFileSource := ":" + apexSelectorModuleName
- p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource)
-
- // Add a source reference to retrieve the selected apex from the selector module.
- p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
-}
-
func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
p.prebuiltApexContentsDeps(ctx)
}
-func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) {
- if p.hasExportedDeps() {
- // Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module
- // The deapexer will return a provider that will be bubbled up to the rdeps of apexes (e.g. dex_bootjars)
- ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name()))
- }
-}
-
var _ ApexInfoMutator = (*Prebuilt)(nil)
func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
p.apexInfoMutator(mctx)
}
+// creates the build rules to deapex the prebuilt, and returns a deapexerInfo
+func (p *prebuiltCommon) getDeapexerInfo(ctx android.ModuleContext, apexFile android.Path) *android.DeapexerInfo {
+ if !p.hasExportedDeps() {
+ // nothing to do
+ return nil
+ }
+ deapexerProps := p.getDeapexerPropertiesIfNeeded(ctx)
+ return deapex(ctx, apexFile, deapexerProps)
+}
+
// Set a provider containing information about the jars and .prof provided by the apex
// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module
// Used by dex_bootjars to generate the boot image
-func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) {
- if !p.hasExportedDeps() {
- // nothing to do
+func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext, di *android.DeapexerInfo) {
+ if di == nil {
return
}
- if di, err := android.FindDeapexerProviderForModule(ctx); err == nil {
- javaModuleToDexPath := map[string]android.Path{}
- for _, commonModule := range di.GetExportedModuleNames() {
- if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil {
- javaModuleToDexPath[commonModule] = dex
- }
+ javaModuleToDexPath := map[string]android.Path{}
+ for _, commonModule := range di.GetExportedModuleNames() {
+ if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil {
+ javaModuleToDexPath[commonModule] = dex
}
-
- exports := android.ApexExportsInfo{
- ApexName: p.ApexVariationName(),
- ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex),
- LibraryNameToDexJarPathOnHost: javaModuleToDexPath,
- }
- android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
- } else {
- ctx.ModuleErrorf(err.Error())
}
+
+ exports := android.ApexExportsInfo{
+ ApexName: p.ApexVariationName(),
+ ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex),
+ LibraryNameToDexJarPathOnHost: javaModuleToDexPath,
+ }
+ android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
}
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
@@ -845,7 +651,7 @@
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
- p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
+ p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module()))
p.installDir = android.PathForModuleInstall(ctx, "apex")
p.installFilename = p.InstallFilename()
if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
@@ -863,11 +669,13 @@
return
}
+ deapexerInfo := p.getDeapexerInfo(ctx, p.inputApex)
+
// dexpreopt any system server jars if present
- p.dexpreoptSystemServerJars(ctx)
+ p.dexpreoptSystemServerJars(ctx, deapexerInfo)
// provide info used for generating the boot image
- p.provideApexExportsInfo(ctx)
+ p.provideApexExportsInfo(ctx, deapexerInfo)
p.providePrebuiltInfo(ctx)
@@ -903,26 +711,11 @@
extractedApex android.WritablePath
}
-func privateApexExtractorModuleFactory() android.Module {
- module := &prebuiltApexExtractorModule{}
- module.AddProperties(
- &module.properties,
- )
- android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- return module
-}
-
-func (p *prebuiltApexExtractorModule) Srcs() android.Paths {
- return android.Paths{p.extractedApex}
-}
-
-func (p *prebuiltApexExtractorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- srcsSupplier := func(ctx android.BaseModuleContext, prebuilt android.Module) []string {
- return p.properties.prebuiltSrcs(ctx)
- }
+// 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 {
defaultAllowPrerelease := ctx.Config().IsEnvTrue("SOONG_ALLOW_PRERELEASE_APEXES")
- apexSet := android.SingleSourcePathFromSupplier(ctx, srcsSupplier, "set")
- p.extractedApex = android.PathForModuleOut(ctx, "extracted", apexSet.Base())
+ extractedApex := android.PathForModuleOut(ctx, "extracted", apexSet.Base())
// Filter out NativeBridge archs (b/260115309)
abis := java.SupportedAbis(ctx, true)
ctx.Build(pctx,
@@ -930,14 +723,16 @@
Rule: extractMatchingApex,
Description: "Extract an apex from an apex set",
Inputs: android.Paths{apexSet},
- Output: p.extractedApex,
+ Output: extractedApex,
Args: map[string]string{
"abis": strings.Join(abis, ","),
- "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(p.properties.Prerelease, defaultAllowPrerelease)),
+ "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(prerelease, defaultAllowPrerelease)),
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
"skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
},
- })
+ },
+ )
+ return extractedApex
}
type ApexSet struct {
@@ -1006,48 +801,18 @@
func apexSetFactory() android.Module {
module := &ApexSet{}
module.AddProperties(&module.properties)
- module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties)
+ module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties
+
+ // init the module as a prebuilt
+ // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing
+ // InitPrebuiltModule* are not friendly with Sources of Configurable type.
+ // The actual src will be evaluated in GenerateAndroidBuildActions.
+ android.InitPrebuiltModuleWithoutSrcs(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
-func createApexExtractorModule(ctx android.TopDownMutatorContext, name string, apexExtractorProperties *ApexExtractorProperties) {
- props := struct {
- Name *string
- }{
- Name: proptools.StringPtr(name),
- }
-
- ctx.CreateModule(privateApexExtractorModuleFactory,
- &props,
- apexExtractorProperties,
- )
-}
-
-func apexExtractorModuleName(baseModuleName string) string {
- return baseModuleName + ".apex.extractor"
-}
-
-var _ prebuiltApexModuleCreator = (*ApexSet)(nil)
-
-// createPrebuiltApexModules creates modules necessary to export files from the apex set to other
-// modules.
-//
-// This effectively does for apex_set what Prebuilt.createPrebuiltApexModules does for a
-// prebuilt_apex except that instead of creating a selector module which selects one .apex file
-// from those provided this creates an extractor module which extracts the appropriate .apex file
-// from the zip file containing them.
-func (a *ApexSet) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
- apexExtractorModuleName := apexExtractorModuleName(a.Name())
- createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties)
-
- apexFileSource := ":" + apexExtractorModuleName
- a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource)
-
- // After passing the arch specific src properties to the creating the apex selector module
- a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
-}
-
func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
a.prebuiltApexContentsDeps(ctx)
}
@@ -1070,11 +835,25 @@
ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
}
- inputApex := android.OptionalPathForModuleSrc(ctx, a.prebuiltCommonProperties.Selected_apex).Path()
+ var apexSet android.Path
+ if srcs := a.properties.prebuiltSrcs(ctx); len(srcs) == 1 {
+ apexSet = android.PathForModuleSrc(ctx, srcs[0])
+ } else {
+ ctx.ModuleErrorf("Expected exactly one source apex_set file, found %v\n", srcs)
+ }
+
+ extractedApex := extract(ctx, apexSet, a.properties.Prerelease)
+
a.outputApex = android.PathForModuleOut(ctx, a.installFilename)
+
+ // Build the output APEX. If compression is not enabled, make sure the output is not compressed even if the input is compressed
+ buildRule := android.Cp
+ if !ctx.Config().ApexCompressionEnabled() {
+ buildRule = decompressApex
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: inputApex,
+ Rule: buildRule,
+ Input: extractedApex,
Output: a.outputApex,
})
@@ -1083,11 +862,13 @@
return
}
+ deapexerInfo := a.getDeapexerInfo(ctx, extractedApex)
+
// dexpreopt any system server jars if present
- a.dexpreoptSystemServerJars(ctx)
+ a.dexpreoptSystemServerJars(ctx, deapexerInfo)
// provide info used for generating the boot image
- a.provideApexExportsInfo(ctx)
+ a.provideApexExportsInfo(ctx, deapexerInfo)
a.providePrebuiltInfo(ctx)
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index f6c53b2..acb3649 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -80,6 +80,7 @@
apex_available: [
"myapex",
],
+ sdk_version: "core_current",
}
systemserverclasspath_fragment {
@@ -274,19 +275,18 @@
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
+ `all_apex_contributions`,
`dex2oatd`,
- `prebuilt_myapex.apex.selector`,
- `prebuilt_myapex.deapexer`,
`prebuilt_mysystemserverclasspathfragment`,
})
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ `all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
- `prebuilt_myapex.deapexer`,
})
- ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -348,6 +348,7 @@
apex_available: [
"myapex",
],
+ sdk_version: "core_current",
}
systemserverclasspath_fragment {
@@ -432,12 +433,12 @@
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ `all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
- `prebuilt_myapex.deapexer`,
})
- ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
diff --git a/apex/testing.go b/apex/testing.go
index 3b200f0..63c5b69 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -16,6 +16,8 @@
import "android/soong/android"
+const testDefaultUpdatableModuleVersion = "340090000"
+
var PrepareForTestWithApexBuildComponents = android.GroupFixturePreparers(
android.FixtureRegisterWithContext(registerApexBuildComponents),
android.FixtureRegisterWithContext(registerApexKeyBuildComponents),
@@ -29,4 +31,5 @@
// Needed by prebuilt_apex.
"build/soong/scripts/unpack-prebuilt-apex.sh": nil,
}.AddToFixture(),
+ android.PrepareForTestWithBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", testDefaultUpdatableModuleVersion),
)
diff --git a/apex/vndk.go b/apex/vndk.go
index 781aa3c..5e630c0 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -20,6 +20,7 @@
"android/soong/android"
"android/soong/cc"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -54,30 +55,6 @@
Vndk_version *string
}
-func apexVndkMutator(mctx android.TopDownMutatorContext) {
- if ab, ok := mctx.Module().(*apexBundle); ok && ab.vndkApex {
- if ab.IsNativeBridgeSupported() {
- mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
- }
-
- vndkVersion := ab.vndkVersion()
- if vndkVersion != "" {
- apiLevel, err := android.ApiLevelFromUser(mctx, vndkVersion)
- if err != nil {
- mctx.PropertyErrorf("vndk_version", "%s", err.Error())
- return
- }
-
- targets := mctx.MultiTargets()
- if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) {
- // Disable VNDK APEXes for VNDK versions less than the minimum supported API
- // level for the primary architecture.
- ab.Disable()
- }
- }
- }
-}
-
func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*cc.Module); ok && cc.IsForVndkApex(mctx, m) {
vndkVersion := m.VndkVersion()
@@ -90,11 +67,37 @@
vndkApexName := "com.android.vndk." + vndkVersion
if mctx.OtherModuleExists(vndkApexName) {
- mctx.AddReverseDependency(mctx.Module(), sharedLibTag, vndkApexName)
+ // Reverse dependencies must exactly specify the variant they want, starting from the
+ // current module's variant. But unlike cc modules, the vndk apex doesn't have
+ // arch/image/link variations, so we explicitly remove them here.
+ mctx.AddReverseVariationDependency([]blueprint.Variation{
+ {Mutator: "arch", Variation: "common"},
+ {Mutator: "image", Variation: ""},
+ {Mutator: "link", Variation: ""},
+ }, sharedLibTag, vndkApexName)
}
} else if a, ok := mctx.Module().(*apexBundle); ok && a.vndkApex {
- vndkVersion := proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
- mctx.AddDependency(mctx.Module(), prebuiltTag, cc.VndkLibrariesTxtModules(vndkVersion, mctx)...)
+ if a.IsNativeBridgeSupported() {
+ mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
+ }
+
+ vndkVersion := a.vndkVersion()
+ if vndkVersion != "" {
+ apiLevel, err := android.ApiLevelFromUser(mctx, vndkVersion)
+ if err != nil {
+ mctx.PropertyErrorf("vndk_version", "%s", err.Error())
+ return
+ }
+
+ targets := mctx.MultiTargets()
+ if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) {
+ // Disable VNDK APEXes for VNDK versions less than the minimum supported API
+ // level for the primary architecture.
+ a.Disable()
+ } else {
+ mctx.AddDependency(mctx.Module(), prebuiltTag, cc.VndkLibrariesTxtModules(vndkVersion, mctx)...)
+ }
+ }
}
}
diff --git a/bazel/Android.bp b/bazel/Android.bp
deleted file mode 100644
index f8273a8..0000000
--- a/bazel/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-bootstrap_go_package {
- name: "soong-bazel",
- pkgPath: "android/soong/bazel",
- srcs: [
- "configurability.go",
- "properties.go",
- "testing.go",
- ],
- testSrcs: [
- "properties_test.go",
- ],
- pluginFor: [
- "soong_build",
- ],
- deps: [
- "blueprint",
- ],
-}
diff --git a/bazel/configurability.go b/bazel/configurability.go
deleted file mode 100644
index 2c9a536..0000000
--- a/bazel/configurability.go
+++ /dev/null
@@ -1,393 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bazel
-
-import (
- "fmt"
- "math"
- "sort"
- "strings"
-)
-
-const (
- // ArchType names in arch.go
- archArm = "arm"
- archArm64 = "arm64"
- archRiscv64 = "riscv64"
- archX86 = "x86"
- archX86_64 = "x86_64"
-
- // OsType names in arch.go
- OsAndroid = "android"
- OsDarwin = "darwin"
- OsLinux = "linux_glibc"
- osLinuxMusl = "linux_musl"
- osLinuxBionic = "linux_bionic"
- OsWindows = "windows"
-
- // Targets in arch.go
- osArchAndroidArm = "android_arm"
- OsArchAndroidArm64 = "android_arm64"
- osArchAndroidRiscv64 = "android_riscv64"
- osArchAndroidX86 = "android_x86"
- osArchAndroidX86_64 = "android_x86_64"
- osArchDarwinArm64 = "darwin_arm64"
- osArchDarwinX86_64 = "darwin_x86_64"
- osArchLinuxX86 = "linux_glibc_x86"
- osArchLinuxX86_64 = "linux_glibc_x86_64"
- osArchLinuxMuslArm = "linux_musl_arm"
- osArchLinuxMuslArm64 = "linux_musl_arm64"
- osArchLinuxMuslX86 = "linux_musl_x86"
- osArchLinuxMuslX86_64 = "linux_musl_x86_64"
- osArchLinuxBionicArm64 = "linux_bionic_arm64"
- osArchLinuxBionicX86_64 = "linux_bionic_x86_64"
- osArchWindowsX86 = "windows_x86"
- osArchWindowsX86_64 = "windows_x86_64"
-
- // This is the string representation of the default condition wherever a
- // configurable attribute is used in a select statement, i.e.
- // //conditions:default for Bazel.
- //
- // This is consistently named "conditions_default" to mirror the Soong
- // config variable default key in an Android.bp file, although there's no
- // integration with Soong config variables (yet).
- ConditionsDefaultConfigKey = "conditions_default"
-
- ConditionsDefaultSelectKey = "//conditions:default"
-
- productVariableBazelPackage = "//build/bazel/product_config/config_settings"
-
- AndroidAndInApex = "android-in_apex"
- AndroidPlatform = "system"
- Unbundled_app = "unbundled_app"
-
- InApex = "in_apex"
- NonApex = "non_apex"
-
- ErrorproneDisabled = "errorprone_disabled"
- // TODO: b/294868620 - Remove when completing the bug
- SanitizersEnabled = "sanitizers_enabled"
-)
-
-func PowerSetWithoutEmptySet[T any](items []T) [][]T {
- resultSize := int(math.Pow(2, float64(len(items))))
- powerSet := make([][]T, 0, resultSize-1)
- for i := 1; i < resultSize; i++ {
- combination := make([]T, 0)
- for j := 0; j < len(items); j++ {
- if (i>>j)%2 == 1 {
- combination = append(combination, items[j])
- }
- }
- powerSet = append(powerSet, combination)
- }
- return powerSet
-}
-
-func createPlatformArchMap() map[string]string {
- // Copy of archFeatures from android/arch_list.go because the bazel
- // package can't access the android package
- archFeatures := map[string][]string{
- "arm": {
- "neon",
- },
- "arm64": {
- "dotprod",
- },
- "riscv64": {},
- "x86": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "avx512",
- "popcnt",
- "movbe",
- },
- "x86_64": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "avx512",
- "popcnt",
- },
- }
- result := make(map[string]string)
- for arch, allFeatures := range archFeatures {
- result[arch] = "//build/bazel_common_rules/platforms/arch:" + arch
- // Sometimes we want to select on multiple features being active, so
- // add the power set of all possible features to the map. More details
- // in android.ModuleBase.GetArchVariantProperties
- for _, features := range PowerSetWithoutEmptySet(allFeatures) {
- sort.Strings(features)
- archFeaturesName := arch + "-" + strings.Join(features, "-")
- result[archFeaturesName] = "//build/bazel/platforms/arch/variants:" + archFeaturesName
- }
- }
- result[ConditionsDefaultConfigKey] = ConditionsDefaultSelectKey
- return result
-}
-
-var (
- // These are the list of OSes and architectures with a Bazel config_setting
- // and constraint value equivalent. These exist in arch.go, but the android
- // package depends on the bazel package, so a cyclic dependency prevents
- // using those variables here.
-
- // A map of architectures to the Bazel label of the constraint_value
- // for the @platforms//cpu:cpu constraint_setting
- platformArchMap = createPlatformArchMap()
-
- // A map of target operating systems to the Bazel label of the
- // constraint_value for the @platforms//os:os constraint_setting
- platformOsMap = map[string]string{
- OsAndroid: "//build/bazel_common_rules/platforms/os:android",
- OsDarwin: "//build/bazel_common_rules/platforms/os:darwin",
- OsLinux: "//build/bazel_common_rules/platforms/os:linux_glibc",
- osLinuxMusl: "//build/bazel_common_rules/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel_common_rules/platforms/os:linux_bionic",
- OsWindows: "//build/bazel_common_rules/platforms/os:windows",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
- }
-
- platformOsArchMap = map[string]string{
- osArchAndroidArm: "//build/bazel_common_rules/platforms/os_arch:android_arm",
- OsArchAndroidArm64: "//build/bazel_common_rules/platforms/os_arch:android_arm64",
- osArchAndroidRiscv64: "//build/bazel_common_rules/platforms/os_arch:android_riscv64",
- osArchAndroidX86: "//build/bazel_common_rules/platforms/os_arch:android_x86",
- osArchAndroidX86_64: "//build/bazel_common_rules/platforms/os_arch:android_x86_64",
- osArchDarwinArm64: "//build/bazel_common_rules/platforms/os_arch:darwin_arm64",
- osArchDarwinX86_64: "//build/bazel_common_rules/platforms/os_arch:darwin_x86_64",
- osArchLinuxX86: "//build/bazel_common_rules/platforms/os_arch:linux_glibc_x86",
- osArchLinuxX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_glibc_x86_64",
- osArchLinuxMuslArm: "//build/bazel_common_rules/platforms/os_arch:linux_musl_arm",
- osArchLinuxMuslArm64: "//build/bazel_common_rules/platforms/os_arch:linux_musl_arm64",
- osArchLinuxMuslX86: "//build/bazel_common_rules/platforms/os_arch:linux_musl_x86",
- osArchLinuxMuslX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_musl_x86_64",
- osArchLinuxBionicArm64: "//build/bazel_common_rules/platforms/os_arch:linux_bionic_arm64",
- osArchLinuxBionicX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_bionic_x86_64",
- osArchWindowsX86: "//build/bazel_common_rules/platforms/os_arch:windows_x86",
- osArchWindowsX86_64: "//build/bazel_common_rules/platforms/os_arch:windows_x86_64",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
- }
-
- // Map where keys are OsType names, and values are slices containing the archs
- // that that OS supports.
- // These definitions copied from arch.go.
- // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
- // in a cyclic dependency.
- osToArchMap = map[string][]string{
- OsAndroid: {archArm, archArm64, archRiscv64, archX86, archX86_64},
- OsLinux: {archX86, archX86_64},
- osLinuxMusl: {archX86, archX86_64},
- OsDarwin: {archArm64, archX86_64},
- osLinuxBionic: {archArm64, archX86_64},
- // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
- OsWindows: {archX86, archX86_64},
- }
-
- osAndInApexMap = map[string]string{
- AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
- AndroidPlatform: "//build/bazel/rules/apex:system",
- Unbundled_app: "//build/bazel/rules/apex:unbundled_app",
- OsDarwin: "//build/bazel_common_rules/platforms/os:darwin",
- OsLinux: "//build/bazel_common_rules/platforms/os:linux_glibc",
- osLinuxMusl: "//build/bazel_common_rules/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel_common_rules/platforms/os:linux_bionic",
- OsWindows: "//build/bazel_common_rules/platforms/os:windows",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
- }
-
- inApexMap = map[string]string{
- InApex: "//build/bazel/rules/apex:in_apex",
- NonApex: "//build/bazel/rules/apex:non_apex",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
- }
-
- errorProneMap = map[string]string{
- ErrorproneDisabled: "//build/bazel/rules/java/errorprone:errorprone_globally_disabled",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
- }
-
- // TODO: b/294868620 - Remove when completing the bug
- sanitizersEnabledMap = map[string]string{
- SanitizersEnabled: "//build/bazel/rules/cc:sanitizers_enabled",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
- }
-)
-
-// basic configuration types
-type configurationType int
-
-const (
- noConfig configurationType = iota
- arch
- os
- osArch
- productVariables
- osAndInApex
- inApex
- errorProneDisabled
- // TODO: b/294868620 - Remove when completing the bug
- sanitizersEnabled
-)
-
-func osArchString(os string, arch string) string {
- return fmt.Sprintf("%s_%s", os, arch)
-}
-
-func (ct configurationType) String() string {
- return map[configurationType]string{
- noConfig: "no_config",
- arch: "arch",
- os: "os",
- osArch: "arch_os",
- productVariables: "product_variables",
- osAndInApex: "os_in_apex",
- inApex: "in_apex",
- errorProneDisabled: "errorprone_disabled",
- // TODO: b/294868620 - Remove when completing the bug
- sanitizersEnabled: "sanitizers_enabled",
- }[ct]
-}
-
-func (ct configurationType) validateConfig(config string) {
- switch ct {
- case noConfig:
- if config != "" {
- panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
- }
- case arch:
- if _, ok := platformArchMap[config]; !ok {
- panic(fmt.Errorf("Unknown arch: %s", config))
- }
- case os:
- if _, ok := platformOsMap[config]; !ok {
- panic(fmt.Errorf("Unknown os: %s", config))
- }
- case osArch:
- if _, ok := platformOsArchMap[config]; !ok {
- panic(fmt.Errorf("Unknown os+arch: %s", config))
- }
- case productVariables:
- // do nothing
- case osAndInApex:
- // do nothing
- // this axis can contain additional per-apex keys
- case inApex:
- if _, ok := inApexMap[config]; !ok {
- panic(fmt.Errorf("Unknown in_apex config: %s", config))
- }
- case errorProneDisabled:
- if _, ok := errorProneMap[config]; !ok {
- panic(fmt.Errorf("Unknown errorprone config: %s", config))
- }
- // TODO: b/294868620 - Remove when completing the bug
- case sanitizersEnabled:
- if _, ok := sanitizersEnabledMap[config]; !ok {
- panic(fmt.Errorf("Unknown sanitizers_enabled config: %s", config))
- }
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
- }
-}
-
-// SelectKey returns the Bazel select key for a given configurationType and config string.
-func (ca ConfigurationAxis) SelectKey(config string) string {
- ca.validateConfig(config)
- switch ca.configurationType {
- case noConfig:
- panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
- case arch:
- return platformArchMap[config]
- case os:
- return platformOsMap[config]
- case osArch:
- return platformOsArchMap[config]
- case productVariables:
- if config == ConditionsDefaultConfigKey {
- return ConditionsDefaultSelectKey
- }
- return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
- case osAndInApex:
- if ret, exists := osAndInApexMap[config]; exists {
- return ret
- }
- return config
- case inApex:
- return inApexMap[config]
- case errorProneDisabled:
- return errorProneMap[config]
- // TODO: b/294868620 - Remove when completing the bug
- case sanitizersEnabled:
- return sanitizersEnabledMap[config]
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
- }
-}
-
-var (
- // Indicating there is no configuration axis
- NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
- // An axis for architecture-specific configurations
- ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
- // An axis for os-specific configurations
- OsConfigurationAxis = ConfigurationAxis{configurationType: os}
- // An axis for arch+os-specific configurations
- OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
- // An axis for os+in_apex-specific configurations
- OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
- // An axis for in_apex-specific configurations
- InApexAxis = ConfigurationAxis{configurationType: inApex}
-
- ErrorProneAxis = ConfigurationAxis{configurationType: errorProneDisabled}
-
- // TODO: b/294868620 - Remove when completing the bug
- SanitizersEnabledAxis = ConfigurationAxis{configurationType: sanitizersEnabled}
-)
-
-// ProductVariableConfigurationAxis returns an axis for the given product variable
-func ProductVariableConfigurationAxis(archVariant bool, variable string) ConfigurationAxis {
- return ConfigurationAxis{
- configurationType: productVariables,
- subType: variable,
- archVariant: archVariant,
- }
-}
-
-// ConfigurationAxis is an independent axis for configuration, there should be no overlap between
-// elements within an axis.
-type ConfigurationAxis struct {
- configurationType
- // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
- // distinguish between them without needing to list all 17 product variables.
- subType string
-
- archVariant bool
-}
-
-func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
- if ca.configurationType == other.configurationType {
- return ca.subType < other.subType
- }
- return ca.configurationType < other.configurationType
-}
diff --git a/bazel/properties.go b/bazel/properties.go
deleted file mode 100644
index 9c63bc0..0000000
--- a/bazel/properties.go
+++ /dev/null
@@ -1,1467 +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 bazel
-
-import (
- "fmt"
- "path/filepath"
- "reflect"
- "regexp"
- "sort"
- "strings"
-
- "github.com/google/blueprint"
-)
-
-// BazelTargetModuleProperties contain properties and metadata used for
-// Blueprint to BUILD file conversion.
-type BazelTargetModuleProperties struct {
- // The Bazel rule class for this target.
- Rule_class string `blueprint:"mutated"`
-
- // The target label for the bzl file containing the definition of the rule class.
- Bzl_load_location string `blueprint:"mutated"`
-}
-
-var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")
-
-// Label is used to represent a Bazel compatible Label. Also stores the original
-// bp text to support string replacement.
-type Label struct {
- // The string representation of a Bazel target label. This can be a relative
- // or fully qualified label. These labels are used for generating BUILD
- // files with bp2build.
- Label string
-
- // The original Soong/Blueprint module name that the label was derived from.
- // This is used for replacing references to the original name with the new
- // label, for example in genrule cmds.
- //
- // While there is a reversible 1:1 mapping from the module name to Bazel
- // label with bp2build that could make computing the original module name
- // from the label automatic, it is not the case for handcrafted targets,
- // where modules can have a custom label mapping through the { bazel_module:
- // { label: <label> } } property.
- //
- // With handcrafted labels, those modules don't go through bp2build
- // conversion, but relies on handcrafted targets in the source tree.
- OriginalModuleName string
-}
-
-// LabelList is used to represent a list of Bazel labels.
-type LabelList struct {
- Includes []Label
- Excludes []Label
-}
-
-// MakeLabelList creates a LabelList from a list Label
-func MakeLabelList(labels []Label) LabelList {
- return LabelList{
- Includes: labels,
- Excludes: nil,
- }
-}
-
-func SortedConfigurationAxes[T any](m map[ConfigurationAxis]T) []ConfigurationAxis {
- keys := make([]ConfigurationAxis, 0, len(m))
- for k := range m {
- keys = append(keys, k)
- }
-
- sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
- return keys
-}
-
-// MakeLabelListFromTargetNames creates a LabelList from unqualified target names
-// This is a utiltity function for bp2build converters of Soong modules that have 1:many generated targets
-func MakeLabelListFromTargetNames(targetNames []string) LabelList {
- labels := []Label{}
- for _, name := range targetNames {
- label := Label{Label: ":" + name}
- labels = append(labels, label)
- }
- return MakeLabelList(labels)
-}
-
-func (ll *LabelList) Equals(other LabelList) bool {
- if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) {
- return false
- }
- for i, _ := range ll.Includes {
- if ll.Includes[i] != other.Includes[i] {
- return false
- }
- }
- for i, _ := range ll.Excludes {
- if ll.Excludes[i] != other.Excludes[i] {
- return false
- }
- }
- return true
-}
-
-func (ll *LabelList) IsNil() bool {
- return ll.Includes == nil && ll.Excludes == nil
-}
-
-func (ll *LabelList) IsEmpty() bool {
- return len(ll.Includes) == 0 && len(ll.Excludes) == 0
-}
-
-func (ll *LabelList) deepCopy() LabelList {
- return LabelList{
- Includes: ll.Includes[:],
- Excludes: ll.Excludes[:],
- }
-}
-
-// uniqueParentDirectories returns a list of the unique parent directories for
-// all files in ll.Includes.
-func (ll *LabelList) uniqueParentDirectories() []string {
- dirMap := map[string]bool{}
- for _, label := range ll.Includes {
- dirMap[filepath.Dir(label.Label)] = true
- }
- dirs := []string{}
- for dir := range dirMap {
- dirs = append(dirs, dir)
- }
- return dirs
-}
-
-// Add inserts the label Label at the end of the LabelList.Includes.
-func (ll *LabelList) Add(label *Label) {
- if label == nil {
- return
- }
- ll.Includes = append(ll.Includes, *label)
-}
-
-// AddExclude inserts the label Label at the end of the LabelList.Excludes.
-func (ll *LabelList) AddExclude(label *Label) {
- if label == nil {
- return
- }
- ll.Excludes = append(ll.Excludes, *label)
-}
-
-// Append appends the fields of other labelList to the corresponding fields of ll.
-func (ll *LabelList) Append(other LabelList) {
- if len(ll.Includes) > 0 || len(other.Includes) > 0 {
- ll.Includes = append(ll.Includes, other.Includes...)
- }
- if len(ll.Excludes) > 0 || len(other.Excludes) > 0 {
- ll.Excludes = append(ll.Excludes, other.Excludes...)
- }
-}
-
-// Partition splits a LabelList into two LabelLists depending on the return value
-// of the predicate.
-// This function preserves the Includes and Excludes, but it does not provide
-// that information to the partition function.
-func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, LabelList) {
- predicated := LabelList{}
- unpredicated := LabelList{}
- for _, include := range ll.Includes {
- if predicate(include) {
- predicated.Add(&include)
- } else {
- unpredicated.Add(&include)
- }
- }
- for _, exclude := range ll.Excludes {
- if predicate(exclude) {
- predicated.AddExclude(&exclude)
- } else {
- unpredicated.AddExclude(&exclude)
- }
- }
- return predicated, unpredicated
-}
-
-// UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns
-// the slice in a sorted order.
-func UniqueSortedBazelLabels(originalLabels []Label) []Label {
- uniqueLabels := FirstUniqueBazelLabels(originalLabels)
- sort.SliceStable(uniqueLabels, func(i, j int) bool {
- return uniqueLabels[i].Label < uniqueLabels[j].Label
- })
- return uniqueLabels
-}
-
-func FirstUniqueBazelLabels(originalLabels []Label) []Label {
- var labels []Label
- found := make(map[string]bool, len(originalLabels))
- for _, l := range originalLabels {
- if _, ok := found[l.Label]; ok {
- continue
- }
- labels = append(labels, l)
- found[l.Label] = true
- }
- return labels
-}
-
-func FirstUniqueBazelLabelList(originalLabelList LabelList) LabelList {
- var uniqueLabelList LabelList
- uniqueLabelList.Includes = FirstUniqueBazelLabels(originalLabelList.Includes)
- uniqueLabelList.Excludes = FirstUniqueBazelLabels(originalLabelList.Excludes)
- return uniqueLabelList
-}
-
-func UniqueSortedBazelLabelList(originalLabelList LabelList) LabelList {
- var uniqueLabelList LabelList
- uniqueLabelList.Includes = UniqueSortedBazelLabels(originalLabelList.Includes)
- uniqueLabelList.Excludes = UniqueSortedBazelLabels(originalLabelList.Excludes)
- return uniqueLabelList
-}
-
-// Subtract needle from haystack
-func SubtractStrings(haystack []string, needle []string) []string {
- // This is really a set
- needleMap := make(map[string]bool)
- for _, s := range needle {
- needleMap[s] = true
- }
-
- var strings []string
- for _, s := range haystack {
- if exclude := needleMap[s]; !exclude {
- strings = append(strings, s)
- }
- }
-
- return strings
-}
-
-// Subtract needle from haystack
-func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
- // This is really a set
- needleMap := make(map[Label]bool)
- for _, s := range needle {
- needleMap[s] = true
- }
-
- var labels []Label
- for _, label := range haystack {
- if exclude := needleMap[label]; !exclude {
- labels = append(labels, label)
- }
- }
-
- return labels
-}
-
-// Appends two LabelLists, returning the combined list.
-func AppendBazelLabelLists(a LabelList, b LabelList) LabelList {
- var result LabelList
- result.Includes = append(a.Includes, b.Includes...)
- result.Excludes = append(a.Excludes, b.Excludes...)
- return result
-}
-
-// Subtract needle from haystack
-func SubtractBazelLabelList(haystack LabelList, needle LabelList) LabelList {
- var result LabelList
- result.Includes = SubtractBazelLabels(haystack.Includes, needle.Includes)
- // NOTE: Excludes are intentionally not subtracted
- result.Excludes = haystack.Excludes
- return result
-}
-
-// FirstUniqueBazelLabelListAttribute takes a LabelListAttribute and makes the LabelList for
-// each axis/configuration by keeping the first instance of a Label and omitting all subsequent
-// repetitions.
-func FirstUniqueBazelLabelListAttribute(attr LabelListAttribute) LabelListAttribute {
- var result LabelListAttribute
- result.Value = FirstUniqueBazelLabelList(attr.Value)
- if attr.HasConfigurableValues() {
- result.ConfigurableValues = make(configurableLabelLists)
- }
- for axis, configToLabels := range attr.ConfigurableValues {
- for c, l := range configToLabels {
- result.SetSelectValue(axis, c, FirstUniqueBazelLabelList(l))
- }
- }
-
- return result
-}
-
-// SubtractBazelLabelListAttribute subtract needle from haystack for LabelList in each
-// axis/configuration.
-func SubtractBazelLabelListAttribute(haystack LabelListAttribute, needle LabelListAttribute) LabelListAttribute {
- var result LabelListAttribute
- result.Value = SubtractBazelLabelList(haystack.Value, needle.Value)
- if haystack.HasConfigurableValues() {
- result.ConfigurableValues = make(configurableLabelLists)
- }
- for axis, configToLabels := range haystack.ConfigurableValues {
- for haystackConfig, haystackLabels := range configToLabels {
- result.SetSelectValue(axis, haystackConfig, SubtractBazelLabelList(haystackLabels, needle.SelectValue(axis, haystackConfig)))
- }
- }
-
- return result
-}
-
-type Attribute interface {
- HasConfigurableValues() bool
-}
-
-type labelSelectValues map[string]*Label
-
-type configurableLabels map[ConfigurationAxis]labelSelectValues
-
-func (cl configurableLabels) setValueForAxis(axis ConfigurationAxis, config string, value *Label) {
- if cl[axis] == nil {
- cl[axis] = make(labelSelectValues)
- }
- cl[axis][config] = value
-}
-
-// Represents an attribute whose value is a single label
-type LabelAttribute struct {
- Value *Label
-
- ConfigurableValues configurableLabels
-}
-
-func (la *LabelAttribute) axisTypes() map[configurationType]bool {
- types := map[configurationType]bool{}
- for k := range la.ConfigurableValues {
- if len(la.ConfigurableValues[k]) > 0 {
- types[k.configurationType] = true
- }
- }
- return types
-}
-
-// Collapse reduces the configurable axes of the label attribute to a single axis.
-// This is necessary for final writing to bp2build, as a configurable label
-// attribute can only be comprised by a single select.
-func (la *LabelAttribute) Collapse() error {
- axisTypes := la.axisTypes()
- _, containsOs := axisTypes[os]
- _, containsArch := axisTypes[arch]
- _, containsOsArch := axisTypes[osArch]
- _, containsProductVariables := axisTypes[productVariables]
- if containsProductVariables {
- if containsOs || containsArch || containsOsArch {
- if containsArch {
- allProductVariablesAreArchVariant := true
- for k := range la.ConfigurableValues {
- if k.configurationType == productVariables && !k.archVariant {
- allProductVariablesAreArchVariant = false
- }
- }
- if !allProductVariablesAreArchVariant {
- return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
- }
- } else {
- return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
- }
- }
- }
- if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
- // If a bool attribute has both os and arch configuration axes, the only
- // way to successfully union their values is to increase the granularity
- // of the configuration criteria to os_arch.
- for osType, supportedArchs := range osToArchMap {
- for _, supportedArch := range supportedArchs {
- osArch := osArchString(osType, supportedArch)
- if archOsVal := la.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
- // Do nothing, as the arch_os is explicitly defined already.
- } else {
- archVal := la.SelectValue(ArchConfigurationAxis, supportedArch)
- osVal := la.SelectValue(OsConfigurationAxis, osType)
- if osVal != nil && archVal != nil {
- // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
- // runs after os mutator.
- la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
- } else if osVal != nil && archVal == nil {
- la.SetSelectValue(OsArchConfigurationAxis, osArch, *osVal)
- } else if osVal == nil && archVal != nil {
- la.SetSelectValue(OsArchConfigurationAxis, osArch, *archVal)
- }
- }
- }
- }
- // All os_arch values are now set. Clear os and arch axes.
- delete(la.ConfigurableValues, ArchConfigurationAxis)
- delete(la.ConfigurableValues, OsConfigurationAxis)
- }
- return nil
-}
-
-// HasConfigurableValues returns whether there are configurable values set for this label.
-func (la LabelAttribute) HasConfigurableValues() bool {
- for _, selectValues := range la.ConfigurableValues {
- if len(selectValues) > 0 {
- return true
- }
- }
- return false
-}
-
-// SetValue sets the base, non-configured value for the Label
-func (la *LabelAttribute) SetValue(value Label) {
- la.SetSelectValue(NoConfigAxis, "", value)
-}
-
-// SetSelectValue set a value for a bazel select for the given axis, config and value.
-func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string, value Label) {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- la.Value = &value
- case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
- if la.ConfigurableValues == nil {
- la.ConfigurableValues = make(configurableLabels)
- }
- la.ConfigurableValues.setValueForAxis(axis, config, &value)
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SelectValue gets a value for a bazel select for the given axis and config.
-func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *Label {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- return la.Value
- case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
- return la.ConfigurableValues[axis][config]
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
-func (la *LabelAttribute) SortedConfigurationAxes() []ConfigurationAxis {
- return SortedConfigurationAxes(la.ConfigurableValues)
-}
-
-// MakeLabelAttribute turns a string into a LabelAttribute
-func MakeLabelAttribute(label string) *LabelAttribute {
- return &LabelAttribute{
- Value: &Label{
- Label: label,
- },
- }
-}
-
-type configToBools map[string]bool
-
-func (ctb configToBools) setValue(config string, value *bool) {
- if value == nil {
- if _, ok := ctb[config]; ok {
- delete(ctb, config)
- }
- return
- }
- ctb[config] = *value
-}
-
-type configurableBools map[ConfigurationAxis]configToBools
-
-func (cb configurableBools) setValueForAxis(axis ConfigurationAxis, config string, value *bool) {
- if cb[axis] == nil {
- cb[axis] = make(configToBools)
- }
- cb[axis].setValue(config, value)
-}
-
-// BoolAttribute represents an attribute whose value is a single bool but may be configurable..
-type BoolAttribute struct {
- Value *bool
-
- ConfigurableValues configurableBools
-}
-
-// HasConfigurableValues returns whether there are configurable values for this attribute.
-func (ba BoolAttribute) HasConfigurableValues() bool {
- for _, cfgToBools := range ba.ConfigurableValues {
- if len(cfgToBools) > 0 {
- return true
- }
- }
- return false
-}
-
-// SetValue sets value for the no config axis
-func (ba *BoolAttribute) SetValue(value *bool) {
- ba.SetSelectValue(NoConfigAxis, "", value)
-}
-
-// SetSelectValue sets value for the given axis/config.
-func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, value *bool) {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- ba.Value = value
- case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
- if ba.ConfigurableValues == nil {
- ba.ConfigurableValues = make(configurableBools)
- }
- ba.ConfigurableValues.setValueForAxis(axis, config, value)
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// ToLabelListAttribute creates and returns a LabelListAttribute from this
-// bool attribute, where each bool in this attribute corresponds to a
-// label list value in the resultant attribute.
-func (ba *BoolAttribute) ToLabelListAttribute(falseVal LabelList, trueVal LabelList) (LabelListAttribute, error) {
- getLabelList := func(boolPtr *bool) LabelList {
- if boolPtr == nil {
- return LabelList{nil, nil}
- } else if *boolPtr {
- return trueVal
- } else {
- return falseVal
- }
- }
-
- mainVal := getLabelList(ba.Value)
- if !ba.HasConfigurableValues() {
- return MakeLabelListAttribute(mainVal), nil
- }
-
- result := LabelListAttribute{}
- if err := ba.Collapse(); err != nil {
- return result, err
- }
-
- for axis, configToBools := range ba.ConfigurableValues {
- if len(configToBools) < 1 {
- continue
- }
- for config, boolPtr := range configToBools {
- val := getLabelList(&boolPtr)
- if !val.Equals(mainVal) {
- result.SetSelectValue(axis, config, val)
- }
- }
- result.SetSelectValue(axis, ConditionsDefaultConfigKey, mainVal)
- }
-
- return result, nil
-}
-
-// ToStringListAttribute creates a StringListAttribute from this BoolAttribute,
-// where each bool corresponds to a string list value generated by the provided
-// function.
-// TODO(b/271425661): Generalize this
-func (ba *BoolAttribute) ToStringListAttribute(valueFunc func(boolPtr *bool, axis ConfigurationAxis, config string) []string) (StringListAttribute, error) {
- mainVal := valueFunc(ba.Value, NoConfigAxis, "")
- if !ba.HasConfigurableValues() {
- return MakeStringListAttribute(mainVal), nil
- }
-
- result := StringListAttribute{}
- if err := ba.Collapse(); err != nil {
- return result, err
- }
-
- for axis, configToBools := range ba.ConfigurableValues {
- if len(configToBools) < 1 {
- continue
- }
- for config, boolPtr := range configToBools {
- val := valueFunc(&boolPtr, axis, config)
- if !reflect.DeepEqual(val, mainVal) {
- result.SetSelectValue(axis, config, val)
- }
- }
- result.SetSelectValue(axis, ConditionsDefaultConfigKey, mainVal)
- }
-
- return result, nil
-}
-
-// Collapse reduces the configurable axes of the boolean attribute to a single axis.
-// This is necessary for final writing to bp2build, as a configurable boolean
-// attribute can only be comprised by a single select.
-func (ba *BoolAttribute) Collapse() error {
- axisTypes := ba.axisTypes()
- _, containsOs := axisTypes[os]
- _, containsArch := axisTypes[arch]
- _, containsOsArch := axisTypes[osArch]
- _, containsProductVariables := axisTypes[productVariables]
- if containsProductVariables {
- if containsOs || containsArch || containsOsArch {
- return fmt.Errorf("boolean attribute could not be collapsed as it has two or more unrelated axes")
- }
- }
- if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
- // If a bool attribute has both os and arch configuration axes, the only
- // way to successfully union their values is to increase the granularity
- // of the configuration criteria to os_arch.
- for osType, supportedArchs := range osToArchMap {
- for _, supportedArch := range supportedArchs {
- osArch := osArchString(osType, supportedArch)
- if archOsVal := ba.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
- // Do nothing, as the arch_os is explicitly defined already.
- } else {
- archVal := ba.SelectValue(ArchConfigurationAxis, supportedArch)
- osVal := ba.SelectValue(OsConfigurationAxis, osType)
- if osVal != nil && archVal != nil {
- // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
- // runs after os mutator.
- ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
- } else if osVal != nil && archVal == nil {
- ba.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
- } else if osVal == nil && archVal != nil {
- ba.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
- }
- }
- }
- }
- // All os_arch values are now set. Clear os and arch axes.
- delete(ba.ConfigurableValues, ArchConfigurationAxis)
- delete(ba.ConfigurableValues, OsConfigurationAxis)
- // Verify post-condition; this should never fail, provided no additional
- // axes are introduced.
- if len(ba.ConfigurableValues) > 1 {
- panic(fmt.Errorf("error in collapsing attribute: %#v", ba))
- }
- }
- return nil
-}
-
-func (ba *BoolAttribute) axisTypes() map[configurationType]bool {
- types := map[configurationType]bool{}
- for k := range ba.ConfigurableValues {
- if len(ba.ConfigurableValues[k]) > 0 {
- types[k.configurationType] = true
- }
- }
- return types
-}
-
-// SelectValue gets the value for the given axis/config.
-func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- return ba.Value
- case arch, os, osArch, productVariables, osAndInApex, sanitizersEnabled:
- if v, ok := ba.ConfigurableValues[axis][config]; ok {
- return &v
- } else {
- return nil
- }
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
-func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis {
- return SortedConfigurationAxes(ba.ConfigurableValues)
-}
-
-// labelListSelectValues supports config-specific label_list typed Bazel attribute values.
-type labelListSelectValues map[string]LabelList
-
-func (ll labelListSelectValues) addSelects(label labelSelectValues) {
- for k, v := range label {
- if label == nil {
- continue
- }
- l := ll[k]
- (&l).Add(v)
- ll[k] = l
- }
-}
-
-func (ll labelListSelectValues) appendSelects(other labelListSelectValues, forceSpecifyEmptyList bool) {
- for k, v := range other {
- l := ll[k]
- if forceSpecifyEmptyList && l.IsNil() && !v.IsNil() {
- l.Includes = []Label{}
- }
- (&l).Append(v)
- ll[k] = l
- }
-}
-
-// HasConfigurableValues returns whether there are configurable values within this set of selects.
-func (ll labelListSelectValues) HasConfigurableValues() bool {
- for _, v := range ll {
- if v.Includes != nil {
- return true
- }
- }
- return false
-}
-
-// LabelListAttribute is used to represent a list of Bazel labels as an
-// attribute.
-type LabelListAttribute struct {
- // The non-configured attribute label list Value. Required.
- Value LabelList
-
- // The configured attribute label list Values. Optional
- // a map of independent configurability axes
- ConfigurableValues configurableLabelLists
-
- // If true, differentiate between "nil" and "empty" list. nil means that
- // this attribute should not be specified at all, and "empty" means that
- // the attribute should be explicitly specified as an empty list.
- // This mode facilitates use of attribute defaults: an empty list should
- // override the default.
- ForceSpecifyEmptyList bool
-
- // If true, signal the intent to the code generator to emit all select keys,
- // even if the Includes list for that key is empty. This mode facilitates
- // specific select statements where an empty list for a non-default select
- // key has a meaning.
- EmitEmptyList bool
-
- // If a property has struct tag "variant_prepend", this value should
- // be set to True, so that when bp2build generates BUILD.bazel, variant
- // properties(select ...) come before general properties.
- Prepend bool
-}
-
-type configurableLabelLists map[ConfigurationAxis]labelListSelectValues
-
-func (cll configurableLabelLists) setValueForAxis(axis ConfigurationAxis, config string, list LabelList) {
- if list.IsNil() {
- if _, ok := cll[axis][config]; ok {
- delete(cll[axis], config)
- }
- return
- }
- if cll[axis] == nil {
- cll[axis] = make(labelListSelectValues)
- }
-
- cll[axis][config] = list
-}
-
-func (cll configurableLabelLists) Append(other configurableLabelLists, forceSpecifyEmptyList bool) {
- for axis, otherSelects := range other {
- selects := cll[axis]
- if selects == nil {
- selects = make(labelListSelectValues, len(otherSelects))
- }
- selects.appendSelects(otherSelects, forceSpecifyEmptyList)
- cll[axis] = selects
- }
-}
-
-func (lla *LabelListAttribute) Clone() *LabelListAttribute {
- result := &LabelListAttribute{ForceSpecifyEmptyList: lla.ForceSpecifyEmptyList}
- return result.Append(*lla)
-}
-
-// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
-func MakeLabelListAttribute(value LabelList) LabelListAttribute {
- return LabelListAttribute{
- Value: value,
- ConfigurableValues: make(configurableLabelLists),
- }
-}
-
-// MakeSingleLabelListAttribute initializes a LabelListAttribute as a non-arch specific list with 1 element, the given Label.
-func MakeSingleLabelListAttribute(value Label) LabelListAttribute {
- return MakeLabelListAttribute(MakeLabelList([]Label{value}))
-}
-
-func (lla *LabelListAttribute) SetValue(list LabelList) {
- lla.SetSelectValue(NoConfigAxis, "", list)
-}
-
-// SetSelectValue set a value for a bazel select for the given axis, config and value.
-func (lla *LabelListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list LabelList) {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- lla.Value = list
- case arch, os, osArch, productVariables, osAndInApex, inApex, errorProneDisabled, sanitizersEnabled:
- if lla.ConfigurableValues == nil {
- lla.ConfigurableValues = make(configurableLabelLists)
- }
- lla.ConfigurableValues.setValueForAxis(axis, config, list)
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SelectValue gets a value for a bazel select for the given axis and config.
-func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string) LabelList {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- return lla.Value
- case arch, os, osArch, productVariables, osAndInApex, inApex, errorProneDisabled, sanitizersEnabled:
- return lla.ConfigurableValues[axis][config]
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
-func (lla *LabelListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
- return SortedConfigurationAxes(lla.ConfigurableValues)
-}
-
-// Append all values, including os and arch specific ones, from another
-// LabelListAttribute to this LabelListAttribute. Returns this LabelListAttribute.
-func (lla *LabelListAttribute) Append(other LabelListAttribute) *LabelListAttribute {
- forceSpecifyEmptyList := lla.ForceSpecifyEmptyList || other.ForceSpecifyEmptyList
- if forceSpecifyEmptyList && lla.Value.IsNil() && !other.Value.IsNil() {
- lla.Value.Includes = []Label{}
- }
- lla.Value.Append(other.Value)
- if lla.ConfigurableValues == nil {
- lla.ConfigurableValues = make(configurableLabelLists)
- }
- lla.ConfigurableValues.Append(other.ConfigurableValues, forceSpecifyEmptyList)
- return lla
-}
-
-// Add inserts the labels for each axis of LabelAttribute at the end of corresponding axis's
-// LabelList within the LabelListAttribute
-func (lla *LabelListAttribute) Add(label *LabelAttribute) {
- if label == nil {
- return
- }
-
- lla.Value.Add(label.Value)
- if lla.ConfigurableValues == nil && label.ConfigurableValues != nil {
- lla.ConfigurableValues = make(configurableLabelLists)
- }
- for axis, _ := range label.ConfigurableValues {
- if _, exists := lla.ConfigurableValues[axis]; !exists {
- lla.ConfigurableValues[axis] = make(labelListSelectValues)
- }
- lla.ConfigurableValues[axis].addSelects(label.ConfigurableValues[axis])
- }
-}
-
-// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
-func (lla LabelListAttribute) HasConfigurableValues() bool {
- for _, selectValues := range lla.ConfigurableValues {
- if len(selectValues) > 0 {
- return true
- }
- }
- return false
-}
-
-// HasAxisSpecificValues returns true if the attribute contains axis specific label list values from a given axis
-func (lla LabelListAttribute) HasAxisSpecificValues(axis ConfigurationAxis) bool {
- for _, values := range lla.ConfigurableValues[axis] {
- if !values.IsNil() {
- return true
- }
- }
- return false
-}
-
-// IsEmpty returns true if the attribute has no values under any configuration.
-func (lla LabelListAttribute) IsEmpty() bool {
- if len(lla.Value.Includes) > 0 {
- return false
- }
- for axis, _ := range lla.ConfigurableValues {
- if lla.ConfigurableValues[axis].HasConfigurableValues() {
- return false
- }
- }
- return true
-}
-
-// IsNil returns true if the attribute has not been set for any configuration.
-func (lla LabelListAttribute) IsNil() bool {
- if lla.Value.Includes != nil {
- return false
- }
- return !lla.HasConfigurableValues()
-}
-
-// Exclude for the given axis, config, removes Includes in labelList from Includes and appends them
-// to Excludes. This is to special case any excludes that are not specified in a bp file but need to
-// be removed, e.g. if they could cause duplicate element failures.
-func (lla *LabelListAttribute) Exclude(axis ConfigurationAxis, config string, labelList LabelList) {
- val := lla.SelectValue(axis, config)
- newList := SubtractBazelLabelList(val, labelList)
- newList.Excludes = append(newList.Excludes, labelList.Includes...)
- lla.SetSelectValue(axis, config, newList)
-}
-
-// ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
-// the base value and included in default values as appropriate.
-func (lla *LabelListAttribute) ResolveExcludes() {
- // If there are OsAndInApexAxis, we need to use
- // * includes from the OS & in APEX Axis for non-Android configs for libraries that need to be
- // included in non-Android OSes
- // * excludes from the OS Axis for non-Android configs, to exclude libraries that should _not_
- // be included in the non-Android OSes
- if _, ok := lla.ConfigurableValues[OsAndInApexAxis]; ok {
- inApexLabels := lla.ConfigurableValues[OsAndInApexAxis][ConditionsDefaultConfigKey]
- for config, labels := range lla.ConfigurableValues[OsConfigurationAxis] {
- // OsAndroid has already handled its excludes.
- // We only need to copy the excludes from other arches, so if there are none, skip it.
- if config == OsAndroid || len(labels.Excludes) == 0 {
- continue
- }
- lla.ConfigurableValues[OsAndInApexAxis][config] = LabelList{
- Includes: inApexLabels.Includes,
- Excludes: labels.Excludes,
- }
- }
- }
-
- for axis, configToLabels := range lla.ConfigurableValues {
- baseLabels := lla.Value.deepCopy()
- for config, val := range configToLabels {
- // Exclude config-specific excludes from base value
- lla.Value = SubtractBazelLabelList(lla.Value, LabelList{Includes: val.Excludes})
-
- // add base values to config specific to add labels excluded by others in this axis
- // then remove all config-specific excludes
- allLabels := baseLabels.deepCopy()
- allLabels.Append(val)
- lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(allLabels, LabelList{Includes: allLabels.Excludes})
- }
-
- // After going through all configs, delete the duplicates in the config
- // values that are already in the base Value.
- for config, val := range configToLabels {
- lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(val, lla.Value)
- }
-
- // Now that the Value list is finalized for this axis, compare it with
- // the original list, and union the difference with the default
- // condition for the axis.
- difference := SubtractBazelLabelList(baseLabels, lla.Value)
- existingDefaults := lla.ConfigurableValues[axis][ConditionsDefaultConfigKey]
- existingDefaults.Append(difference)
- lla.ConfigurableValues[axis][ConditionsDefaultConfigKey] = FirstUniqueBazelLabelList(existingDefaults)
-
- // if everything ends up without includes, just delete the axis
- if !lla.ConfigurableValues[axis].HasConfigurableValues() {
- delete(lla.ConfigurableValues, axis)
- }
- }
-}
-
-// Partition splits a LabelListAttribute into two LabelListAttributes depending
-// on the return value of the predicate.
-// This function preserves the Includes and Excludes, but it does not provide
-// that information to the partition function.
-func (lla LabelListAttribute) Partition(predicate func(label Label) bool) (LabelListAttribute, LabelListAttribute) {
- predicated := LabelListAttribute{}
- unpredicated := LabelListAttribute{}
-
- valuePartitionTrue, valuePartitionFalse := lla.Value.Partition(predicate)
- predicated.SetValue(valuePartitionTrue)
- unpredicated.SetValue(valuePartitionFalse)
-
- for axis, selectValueLabelLists := range lla.ConfigurableValues {
- for config, labelList := range selectValueLabelLists {
- configPredicated, configUnpredicated := labelList.Partition(predicate)
- predicated.SetSelectValue(axis, config, configPredicated)
- unpredicated.SetSelectValue(axis, config, configUnpredicated)
- }
- }
-
- return predicated, unpredicated
-}
-
-// OtherModuleContext is a limited context that has methods with information about other modules.
-type OtherModuleContext interface {
- ModuleFromName(name string) (blueprint.Module, bool)
- OtherModuleType(m blueprint.Module) string
- OtherModuleName(m blueprint.Module) string
- OtherModuleDir(m blueprint.Module) string
- ModuleErrorf(fmt string, args ...interface{})
-}
-
-// LabelMapper is a function that takes a OtherModuleContext and returns a (potentially changed)
-// label and whether it was changed.
-type LabelMapper func(OtherModuleContext, Label) (string, bool)
-
-// LabelPartition contains descriptions of a partition for labels
-type LabelPartition struct {
- // Extensions to include in this partition
- Extensions []string
- // LabelMapper is a function that can map a label to a new label, and indicate whether to include
- // the mapped label in the partition
- LabelMapper LabelMapper
- // Whether to store files not included in any other partition in a group of LabelPartitions
- // Only one partition in a group of LabelPartitions can enabled Keep_remainder
- Keep_remainder bool
-}
-
-// LabelPartitions is a map of partition name to a LabelPartition describing the elements of the
-// partition
-type LabelPartitions map[string]LabelPartition
-
-// filter returns a pointer to a label if the label should be included in the partition or nil if
-// not.
-func (lf LabelPartition) filter(ctx OtherModuleContext, label Label) *Label {
- if lf.LabelMapper != nil {
- if newLabel, changed := lf.LabelMapper(ctx, label); changed {
- return &Label{newLabel, label.OriginalModuleName}
- }
- }
- for _, ext := range lf.Extensions {
- if strings.HasSuffix(label.Label, ext) {
- return &label
- }
- }
-
- return nil
-}
-
-// PartitionToLabelListAttribute is map of partition name to a LabelListAttribute
-type PartitionToLabelListAttribute map[string]LabelListAttribute
-
-type partitionToLabelList map[string]*LabelList
-
-func (p partitionToLabelList) appendIncludes(partition string, label Label) {
- if _, ok := p[partition]; !ok {
- p[partition] = &LabelList{}
- }
- p[partition].Includes = append(p[partition].Includes, label)
-}
-
-func (p partitionToLabelList) excludes(partition string, excludes []Label) {
- if _, ok := p[partition]; !ok {
- p[partition] = &LabelList{}
- }
- p[partition].Excludes = excludes
-}
-
-// PartitionLabelListAttribute partitions a LabelListAttribute into the requested partitions
-func PartitionLabelListAttribute(ctx OtherModuleContext, lla *LabelListAttribute, partitions LabelPartitions) PartitionToLabelListAttribute {
- ret := PartitionToLabelListAttribute{}
- var partitionNames []string
- // Stored as a pointer to distinguish nil (no remainder partition) from empty string partition
- var remainderPartition *string
- for p, f := range partitions {
- partitionNames = append(partitionNames, p)
- if f.Keep_remainder {
- if remainderPartition != nil {
- panic("only one partition can store the remainder")
- }
- // If we take the address of p in a loop, we'll end up with the last value of p in
- // remainderPartition, we want the requested partition
- capturePartition := p
- remainderPartition = &capturePartition
- }
- }
-
- partitionLabelList := func(axis ConfigurationAxis, config string) {
- value := lla.SelectValue(axis, config)
- partitionToLabels := partitionToLabelList{}
- for _, item := range value.Includes {
- wasFiltered := false
- var inPartition *string
- for partition, f := range partitions {
- filtered := f.filter(ctx, item)
- if filtered == nil {
- // did not match this filter, keep looking
- continue
- }
- wasFiltered = true
- partitionToLabels.appendIncludes(partition, *filtered)
- // don't need to check other partitions if this filter used the item,
- // continue checking if mapped to another name
- if *filtered == item {
- if inPartition != nil {
- ctx.ModuleErrorf("%q was found in multiple partitions: %q, %q", item.Label, *inPartition, partition)
- }
- capturePartition := partition
- inPartition = &capturePartition
- }
- }
-
- // if not specified in a partition, add to remainder partition if one exists
- if !wasFiltered && remainderPartition != nil {
- partitionToLabels.appendIncludes(*remainderPartition, item)
- }
- }
-
- // ensure empty lists are maintained
- if value.Excludes != nil {
- for _, partition := range partitionNames {
- partitionToLabels.excludes(partition, value.Excludes)
- }
- }
-
- for partition, list := range partitionToLabels {
- val := ret[partition]
- (&val).SetSelectValue(axis, config, *list)
- ret[partition] = val
- }
- }
-
- partitionLabelList(NoConfigAxis, "")
- for axis, configToList := range lla.ConfigurableValues {
- for config, _ := range configToList {
- partitionLabelList(axis, config)
- }
- }
- return ret
-}
-
-// StringAttribute corresponds to the string Bazel attribute type with
-// support for additional metadata, like configurations.
-type StringAttribute struct {
- // The base value of the string attribute.
- Value *string
-
- // The configured attribute label list Values. Optional
- // a map of independent configurability axes
- ConfigurableValues configurableStrings
-}
-
-type configurableStrings map[ConfigurationAxis]stringSelectValues
-
-func (cs configurableStrings) setValueForAxis(axis ConfigurationAxis, config string, str *string) {
- if cs[axis] == nil {
- cs[axis] = make(stringSelectValues)
- }
- cs[axis][config] = str
-}
-
-type stringSelectValues map[string]*string
-
-// HasConfigurableValues returns true if the attribute contains axis-specific string values.
-func (sa StringAttribute) HasConfigurableValues() bool {
- for _, selectValues := range sa.ConfigurableValues {
- if len(selectValues) > 0 {
- return true
- }
- }
- return false
-}
-
-// SetValue sets the base, non-configured value for the Label
-func (sa *StringAttribute) SetValue(value string) {
- sa.SetSelectValue(NoConfigAxis, "", &value)
-}
-
-// SetSelectValue set a value for a bazel select for the given axis, config and value.
-func (sa *StringAttribute) SetSelectValue(axis ConfigurationAxis, config string, str *string) {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- sa.Value = str
- case arch, os, osArch, productVariables, sanitizersEnabled:
- if sa.ConfigurableValues == nil {
- sa.ConfigurableValues = make(configurableStrings)
- }
- sa.ConfigurableValues.setValueForAxis(axis, config, str)
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SelectValue gets a value for a bazel select for the given axis and config.
-func (sa *StringAttribute) SelectValue(axis ConfigurationAxis, config string) *string {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- return sa.Value
- case arch, os, osArch, productVariables, sanitizersEnabled:
- if v, ok := sa.ConfigurableValues[axis][config]; ok {
- return v
- } else {
- return nil
- }
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
-func (sa *StringAttribute) SortedConfigurationAxes() []ConfigurationAxis {
- return SortedConfigurationAxes(sa.ConfigurableValues)
-}
-
-// Collapse reduces the configurable axes of the string attribute to a single axis.
-// This is necessary for final writing to bp2build, as a configurable string
-// attribute can only be comprised by a single select.
-func (sa *StringAttribute) Collapse() error {
- axisTypes := sa.axisTypes()
- _, containsOs := axisTypes[os]
- _, containsArch := axisTypes[arch]
- _, containsOsArch := axisTypes[osArch]
- _, containsProductVariables := axisTypes[productVariables]
- if containsProductVariables {
- if containsOs || containsArch || containsOsArch {
- return fmt.Errorf("string attribute could not be collapsed as it has two or more unrelated axes")
- }
- }
- if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
- // If a bool attribute has both os and arch configuration axes, the only
- // way to successfully union their values is to increase the granularity
- // of the configuration criteria to os_arch.
- for osType, supportedArchs := range osToArchMap {
- for _, supportedArch := range supportedArchs {
- osArch := osArchString(osType, supportedArch)
- if archOsVal := sa.SelectValue(OsArchConfigurationAxis, osArch); archOsVal != nil {
- // Do nothing, as the arch_os is explicitly defined already.
- } else {
- archVal := sa.SelectValue(ArchConfigurationAxis, supportedArch)
- osVal := sa.SelectValue(OsConfigurationAxis, osType)
- if osVal != nil && archVal != nil {
- // In this case, arch takes precedence. (This fits legacy Soong behavior, as arch mutator
- // runs after os mutator.
- sa.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
- } else if osVal != nil && archVal == nil {
- sa.SetSelectValue(OsArchConfigurationAxis, osArch, osVal)
- } else if osVal == nil && archVal != nil {
- sa.SetSelectValue(OsArchConfigurationAxis, osArch, archVal)
- }
- }
- }
- }
- /// All os_arch values are now set. Clear os and arch axes.
- delete(sa.ConfigurableValues, ArchConfigurationAxis)
- delete(sa.ConfigurableValues, OsConfigurationAxis)
- // Verify post-condition; this should never fail, provided no additional
- // axes are introduced.
- if len(sa.ConfigurableValues) > 1 {
- panic(fmt.Errorf("error in collapsing attribute: %#v", sa))
- }
- } else if containsProductVariables {
- usedBaseValue := false
- for a, configToProp := range sa.ConfigurableValues {
- if a.configurationType == productVariables {
- for c, p := range configToProp {
- if p == nil {
- sa.SetSelectValue(a, c, sa.Value)
- usedBaseValue = true
- }
- }
- }
- }
- if usedBaseValue {
- sa.Value = nil
- }
- }
- return nil
-}
-
-func (sa *StringAttribute) axisTypes() map[configurationType]bool {
- types := map[configurationType]bool{}
- for k := range sa.ConfigurableValues {
- if strs := sa.ConfigurableValues[k]; len(strs) > 0 {
- types[k.configurationType] = true
- }
- }
- return types
-}
-
-// StringListAttribute corresponds to the string_list Bazel attribute type with
-// support for additional metadata, like configurations.
-type StringListAttribute struct {
- // The base value of the string list attribute.
- Value []string
-
- // The configured attribute label list Values. Optional
- // a map of independent configurability axes
- ConfigurableValues configurableStringLists
-
- // If a property has struct tag "variant_prepend", this value should
- // be set to True, so that when bp2build generates BUILD.bazel, variant
- // properties(select ...) come before general properties.
- Prepend bool
-}
-
-// IsEmpty returns true if the attribute has no values under any configuration.
-func (sla StringListAttribute) IsEmpty() bool {
- return len(sla.Value) == 0 && !sla.HasConfigurableValues()
-}
-
-type configurableStringLists map[ConfigurationAxis]stringListSelectValues
-
-func (csl configurableStringLists) Append(other configurableStringLists) {
- for axis, otherSelects := range other {
- selects := csl[axis]
- if selects == nil {
- selects = make(stringListSelectValues, len(otherSelects))
- }
- selects.appendSelects(otherSelects)
- csl[axis] = selects
- }
-}
-
-func (csl configurableStringLists) setValueForAxis(axis ConfigurationAxis, config string, list []string) {
- if csl[axis] == nil {
- csl[axis] = make(stringListSelectValues)
- }
- csl[axis][config] = list
-}
-
-type stringListSelectValues map[string][]string
-
-func (sl stringListSelectValues) appendSelects(other stringListSelectValues) {
- for k, v := range other {
- sl[k] = append(sl[k], v...)
- }
-}
-
-func (sl stringListSelectValues) hasConfigurableValues(other stringListSelectValues) bool {
- for _, val := range sl {
- if len(val) > 0 {
- return true
- }
- }
- return false
-}
-
-// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
-func MakeStringListAttribute(value []string) StringListAttribute {
- // NOTE: These strings are not necessarily unique or sorted.
- return StringListAttribute{
- Value: value,
- ConfigurableValues: make(configurableStringLists),
- }
-}
-
-// HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
-func (sla StringListAttribute) HasConfigurableValues() bool {
- for _, selectValues := range sla.ConfigurableValues {
- if len(selectValues) > 0 {
- return true
- }
- }
- return false
-}
-
-// Append appends all values, including os and arch specific ones, from another
-// StringListAttribute to this StringListAttribute
-func (sla *StringListAttribute) Append(other StringListAttribute) *StringListAttribute {
- sla.Value = append(sla.Value, other.Value...)
- if sla.ConfigurableValues == nil {
- sla.ConfigurableValues = make(configurableStringLists)
- }
- sla.ConfigurableValues.Append(other.ConfigurableValues)
- return sla
-}
-
-func (sla *StringListAttribute) Clone() *StringListAttribute {
- result := &StringListAttribute{}
- return result.Append(*sla)
-}
-
-// SetSelectValue set a value for a bazel select for the given axis, config and value.
-func (sla *StringListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list []string) {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- sla.Value = list
- case arch, os, osArch, productVariables, osAndInApex, errorProneDisabled, sanitizersEnabled:
- if sla.ConfigurableValues == nil {
- sla.ConfigurableValues = make(configurableStringLists)
- }
- sla.ConfigurableValues.setValueForAxis(axis, config, list)
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SelectValue gets a value for a bazel select for the given axis and config.
-func (sla *StringListAttribute) SelectValue(axis ConfigurationAxis, config string) []string {
- axis.validateConfig(config)
- switch axis.configurationType {
- case noConfig:
- return sla.Value
- case arch, os, osArch, productVariables, osAndInApex, errorProneDisabled, sanitizersEnabled:
- return sla.ConfigurableValues[axis][config]
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
- }
-}
-
-// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
-func (sla *StringListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
- return SortedConfigurationAxes(sla.ConfigurableValues)
-}
-
-// DeduplicateAxesFromBase ensures no duplication of items between the no-configuration value and
-// configuration-specific values. For example, if we would convert this StringListAttribute as:
-//
-// ["a", "b", "c"] + select({
-// "//condition:one": ["a", "d"],
-// "//conditions:default": [],
-// })
-//
-// after this function, we would convert this StringListAttribute as:
-//
-// ["a", "b", "c"] + select({
-// "//condition:one": ["d"],
-// "//conditions:default": [],
-// })
-func (sla *StringListAttribute) DeduplicateAxesFromBase() {
- base := sla.Value
- for axis, configToList := range sla.ConfigurableValues {
- for config, list := range configToList {
- remaining := SubtractStrings(list, base)
- if len(remaining) == 0 {
- delete(sla.ConfigurableValues[axis], config)
- } else {
- sla.ConfigurableValues[axis][config] = remaining
- }
- }
- }
-}
-
-// TryVariableSubstitution, replace string substitution formatting within each string in slice with
-// Starlark string.format compatible tag for productVariable.
-func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
- if len(slice) == 0 {
- return slice, false
- }
- ret := make([]string, 0, len(slice))
- changesMade := false
- for _, s := range slice {
- newS, changed := TryVariableSubstitution(s, productVariable)
- ret = append(ret, newS)
- changesMade = changesMade || changed
- }
- return ret, changesMade
-}
-
-// TryVariableSubstitution, replace string substitution formatting within s with Starlark
-// string.format compatible tag for productVariable.
-func TryVariableSubstitution(s string, productVariable string) (string, bool) {
- sub := productVariableSubstitutionPattern.ReplaceAllString(s, "$("+productVariable+")")
- return sub, s != sub
-}
-
-// StringMapAttribute is a map of strings.
-// The use case for this is storing the flag_values in a config_setting object.
-// Bazel rules do not support map attributes, and this should NOT be used in Bazel rules.
-type StringMapAttribute map[string]string
-
-// ConfigSettingAttributes stores the keys of a config_setting object.
-type ConfigSettingAttributes struct {
- // Each key in Flag_values is a label to a custom string_setting
- Flag_values StringMapAttribute
- // Each element in Constraint_values is a label to a constraint_value
- Constraint_values LabelListAttribute
-}
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
deleted file mode 100644
index 751cb8b..0000000
--- a/bazel/properties_test.go
+++ /dev/null
@@ -1,836 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bazel
-
-import (
- "reflect"
- "strings"
- "testing"
-
- "github.com/google/blueprint/proptools"
-)
-
-func TestUniqueBazelLabels(t *testing.T) {
- testCases := []struct {
- originalLabels []Label
- expectedUniqueLabels []Label
- }{
- {
- originalLabels: []Label{
- {Label: "a"},
- {Label: "b"},
- {Label: "a"},
- {Label: "c"},
- // namespaces
- {Label: "//foo:bar", OriginalModuleName: "bar"}, // when referenced from foo namespace
- {Label: "//foo:bar", OriginalModuleName: "//foo:bar"}, // when reference from root namespace
- },
- expectedUniqueLabels: []Label{
- {Label: "//foo:bar", OriginalModuleName: "bar"},
- {Label: "a"},
- {Label: "b"},
- {Label: "c"},
- },
- },
- }
- for _, tc := range testCases {
- actualUniqueLabels := UniqueSortedBazelLabels(tc.originalLabels)
- if !reflect.DeepEqual(tc.expectedUniqueLabels, actualUniqueLabels) {
- t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabels, actualUniqueLabels)
- }
- }
-}
-
-func TestSubtractStrings(t *testing.T) {
- testCases := []struct {
- haystack []string
- needle []string
- expectedResult []string
- }{
- {
- haystack: []string{
- "a",
- "b",
- "c",
- },
- needle: []string{
- "a",
- },
- expectedResult: []string{
- "b", "c",
- },
- },
- }
- for _, tc := range testCases {
- actualResult := SubtractStrings(tc.haystack, tc.needle)
- if !reflect.DeepEqual(tc.expectedResult, actualResult) {
- t.Fatalf("Expected %v, got %v", tc.expectedResult, actualResult)
- }
- }
-}
-
-func TestSubtractBazelLabelList(t *testing.T) {
- testCases := []struct {
- haystack LabelList
- needle LabelList
- expectedResult LabelList
- }{
- {
- haystack: LabelList{
- Includes: []Label{
- {Label: "a"},
- {Label: "b"},
- {Label: "c"},
- },
- Excludes: []Label{
- {Label: "x"},
- {Label: "y"},
- {Label: "z"},
- },
- },
- needle: LabelList{
- Includes: []Label{
- {Label: "a"},
- },
- Excludes: []Label{
- {Label: "z"},
- },
- },
- // NOTE: Excludes are intentionally not subtracted
- expectedResult: LabelList{
- Includes: []Label{
- {Label: "b"},
- {Label: "c"},
- },
- Excludes: []Label{
- {Label: "x"},
- {Label: "y"},
- {Label: "z"},
- },
- },
- },
- }
- for _, tc := range testCases {
- actualResult := SubtractBazelLabelList(tc.haystack, tc.needle)
- if !reflect.DeepEqual(tc.expectedResult, actualResult) {
- t.Fatalf("Expected %v, got %v", tc.expectedResult, actualResult)
- }
- }
-}
-
-func TestSubtractBazelLabelListAttribute(t *testing.T) {
- testCases := []struct {
- haystack LabelListAttribute
- needle LabelListAttribute
- expected LabelListAttribute
- }{
- {
- haystack: LabelListAttribute{
- Value: makeLabelList(
- []string{"a", "b", "a", "c"},
- []string{"x", "x", "y", "z"},
- ),
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{"arm_1", "arm_2"}, []string{}),
- "x86": makeLabelList([]string{"x86_3", "x86_4", "x86_5"}, []string{"x86_5"}),
- },
- },
- },
- needle: LabelListAttribute{
- Value: makeLabelList(
- []string{"d", "a"},
- []string{"x", "y2", "z2"},
- ),
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{"arm_1", "arm_3"}, []string{}),
- "x86": makeLabelList([]string{"x86_3", "x86_4"}, []string{"x86_6"}),
- },
- },
- },
- expected: LabelListAttribute{
- Value: makeLabelList(
- []string{"b", "c"},
- []string{"x", "x", "y", "z"},
- ),
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{"arm_2"}, []string{}),
- "x86": makeLabelList([]string{"x86_5"}, []string{"x86_5"}),
- },
- },
- ForceSpecifyEmptyList: false,
- EmitEmptyList: false,
- Prepend: false,
- },
- },
- }
- for _, tc := range testCases {
- got := SubtractBazelLabelListAttribute(tc.haystack, tc.needle)
- if !reflect.DeepEqual(tc.expected, got) {
- t.Fatalf("Expected\n%v, but got\n%v", tc.expected, got)
- }
- }
-}
-
-func TestFirstUniqueBazelLabelList(t *testing.T) {
- testCases := []struct {
- originalLabelList LabelList
- expectedUniqueLabelList LabelList
- }{
- {
- originalLabelList: LabelList{
- Includes: []Label{
- {Label: "a"},
- {Label: "b"},
- {Label: "a"},
- {Label: "c"},
- // namespaces
- {Label: "//foo:bar", OriginalModuleName: "bar"}, // when referenced from foo namespace
- {Label: "//foo:bar", OriginalModuleName: "//foo:bar"}, // when referenced from root namespace
- },
- Excludes: []Label{
- {Label: "x"},
- {Label: "x"},
- {Label: "y"},
- {Label: "z"},
- },
- },
- expectedUniqueLabelList: LabelList{
- Includes: []Label{
- {Label: "a"},
- {Label: "b"},
- {Label: "c"},
- {Label: "//foo:bar", OriginalModuleName: "bar"},
- },
- Excludes: []Label{
- {Label: "x"},
- {Label: "y"},
- {Label: "z"},
- },
- },
- },
- }
- for _, tc := range testCases {
- actualUniqueLabelList := FirstUniqueBazelLabelList(tc.originalLabelList)
- if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
- t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
- }
- }
-}
-
-func TestFirstUniqueBazelLabelListAttribute(t *testing.T) {
- testCases := []struct {
- originalLabelList LabelListAttribute
- expectedUniqueLabelList LabelListAttribute
- }{
- {
- originalLabelList: LabelListAttribute{
- Value: makeLabelList(
- []string{"a", "b", "a", "c"},
- []string{"x", "x", "y", "z"},
- ),
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{"1", "2", "1"}, []string{}),
- "x86": makeLabelList([]string{"3", "4", "4"}, []string{"5", "5"}),
- },
- },
- },
- expectedUniqueLabelList: LabelListAttribute{
- Value: makeLabelList(
- []string{"a", "b", "c"},
- []string{"x", "y", "z"},
- ),
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{"1", "2"}, []string{}),
- "x86": makeLabelList([]string{"3", "4"}, []string{"5"}),
- },
- },
- },
- },
- }
- for _, tc := range testCases {
- actualUniqueLabelList := FirstUniqueBazelLabelListAttribute(tc.originalLabelList)
- if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
- t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
- }
- }
-}
-
-func TestUniqueSortedBazelLabelList(t *testing.T) {
- testCases := []struct {
- originalLabelList LabelList
- expectedUniqueLabelList LabelList
- }{
- {
- originalLabelList: LabelList{
- Includes: []Label{
- {Label: "c"},
- {Label: "a"},
- {Label: "a"},
- {Label: "b"},
- },
- Excludes: []Label{
- {Label: "y"},
- {Label: "z"},
- {Label: "x"},
- {Label: "x"},
- },
- },
- expectedUniqueLabelList: LabelList{
- Includes: []Label{
- {Label: "a"},
- {Label: "b"},
- {Label: "c"},
- },
- Excludes: []Label{
- {Label: "x"},
- {Label: "y"},
- {Label: "z"},
- },
- },
- },
- }
- for _, tc := range testCases {
- actualUniqueLabelList := UniqueSortedBazelLabelList(tc.originalLabelList)
- if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
- t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
- }
- }
-}
-
-func makeLabels(labels ...string) []Label {
- var ret []Label
- for _, l := range labels {
- ret = append(ret, Label{Label: l})
- }
- return ret
-}
-
-func makeLabelList(includes, excludes []string) LabelList {
- return LabelList{
- Includes: makeLabels(includes...),
- Excludes: makeLabels(excludes...),
- }
-}
-
-func TestResolveExcludes(t *testing.T) {
- attr := LabelListAttribute{
- Value: makeLabelList(
- []string{
- "all_include",
- "arm_exclude",
- "android_exclude",
- "product_config_exclude",
- },
- []string{"all_exclude"},
- ),
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{}, []string{"arm_exclude"}),
- "x86": makeLabelList([]string{"x86_include"}, []string{}),
- ConditionsDefaultConfigKey: makeLabelList([]string{"default_include"}, []string{}),
- },
- OsConfigurationAxis: labelListSelectValues{
- "android": makeLabelList([]string{}, []string{"android_exclude"}),
- "linux": makeLabelList([]string{"linux_include"}, []string{}),
- },
- OsArchConfigurationAxis: labelListSelectValues{
- "linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}),
- },
- ProductVariableConfigurationAxis(false, "product_with_defaults"): labelListSelectValues{
- "a": makeLabelList([]string{}, []string{"not_in_value"}),
- "b": makeLabelList([]string{"b_val"}, []string{}),
- "c": makeLabelList([]string{"c_val"}, []string{}),
- ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2", "all_exclude"}, []string{}),
- },
- ProductVariableConfigurationAxis(false, "product_only_with_excludes"): labelListSelectValues{
- "a": makeLabelList([]string{}, []string{"product_config_exclude"}),
- },
- },
- }
-
- attr.ResolveExcludes()
-
- expectedBaseIncludes := []Label{{Label: "all_include"}}
- if !reflect.DeepEqual(expectedBaseIncludes, attr.Value.Includes) {
- t.Errorf("Expected Value includes %q, got %q", attr.Value.Includes, expectedBaseIncludes)
- }
- var nilLabels []Label
- expectedConfiguredIncludes := map[ConfigurationAxis]map[string][]Label{
- ArchConfigurationAxis: {
- "arm": nilLabels,
- "x86": makeLabels("arm_exclude", "x86_include"),
- ConditionsDefaultConfigKey: makeLabels("arm_exclude", "default_include"),
- },
- OsConfigurationAxis: {
- "android": nilLabels,
- "linux": makeLabels("android_exclude", "linux_include"),
- ConditionsDefaultConfigKey: makeLabels("android_exclude"),
- },
- OsArchConfigurationAxis: {
- "linux_x86": makeLabels("linux_x86_include"),
- ConditionsDefaultConfigKey: nilLabels,
- },
- ProductVariableConfigurationAxis(false, "product_with_defaults"): {
- "a": nilLabels,
- "b": makeLabels("b_val"),
- "c": makeLabels("c_val"),
- ConditionsDefaultConfigKey: makeLabels("c_val", "default", "default2"),
- },
- ProductVariableConfigurationAxis(false, "product_only_with_excludes"): {
- "a": nilLabels,
- ConditionsDefaultConfigKey: makeLabels("product_config_exclude"),
- },
- }
- for _, axis := range attr.SortedConfigurationAxes() {
- if _, ok := expectedConfiguredIncludes[axis]; !ok {
- t.Errorf("Found unexpected axis %s", axis)
- continue
- }
- expectedForAxis := expectedConfiguredIncludes[axis]
- gotForAxis := attr.ConfigurableValues[axis]
- if len(expectedForAxis) != len(gotForAxis) {
- t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis)
- }
- for config, value := range gotForAxis {
- if expected, ok := expectedForAxis[config]; ok {
- if !reflect.DeepEqual(expected, value.Includes) {
- t.Errorf("For %s,\nexpected: %#v\ngot %#v", axis, expected, value.Includes)
- }
- } else {
- t.Errorf("Got unexpected config %q for %s", config, axis)
- }
- }
- }
-}
-
-func TestLabelListAttributePartition(t *testing.T) {
- testCases := []struct {
- name string
- input LabelListAttribute
- predicated LabelListAttribute
- unpredicated LabelListAttribute
- predicate func(label Label) bool
- }{
- {
- name: "move all to predicated partition",
- input: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "throw1", "keep2", "throw2"},
- []string{"keep1", "throw1", "keep2", "throw2"},
- )),
- predicated: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "throw1", "keep2", "throw2"},
- []string{"keep1", "throw1", "keep2", "throw2"},
- )),
- unpredicated: LabelListAttribute{},
- predicate: func(label Label) bool {
- return true
- },
- },
- {
- name: "move all to unpredicated partition",
- input: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "throw1", "keep2", "throw2"},
- []string{"keep1", "throw1", "keep2", "throw2"},
- )),
- predicated: LabelListAttribute{},
- unpredicated: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "throw1", "keep2", "throw2"},
- []string{"keep1", "throw1", "keep2", "throw2"},
- )),
- predicate: func(label Label) bool {
- return false
- },
- },
- {
- name: "partition includes and excludes",
- input: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "throw1", "keep2", "throw2"},
- []string{"keep1", "throw1", "keep2", "throw2"},
- )),
- predicated: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "keep2"},
- []string{"keep1", "keep2"},
- )),
- unpredicated: MakeLabelListAttribute(makeLabelList(
- []string{"throw1", "throw2"},
- []string{"throw1", "throw2"},
- )),
- predicate: func(label Label) bool {
- return strings.HasPrefix(label.Label, "keep")
- },
- },
- {
- name: "partition excludes only",
- input: MakeLabelListAttribute(makeLabelList(
- []string{},
- []string{"keep1", "throw1", "keep2", "throw2"},
- )),
- predicated: MakeLabelListAttribute(makeLabelList(
- []string{},
- []string{"keep1", "keep2"},
- )),
- unpredicated: MakeLabelListAttribute(makeLabelList(
- []string{},
- []string{"throw1", "throw2"},
- )),
- predicate: func(label Label) bool {
- return strings.HasPrefix(label.Label, "keep")
- },
- },
- {
- name: "partition includes only",
- input: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "throw1", "keep2", "throw2"},
- []string{},
- )),
- predicated: MakeLabelListAttribute(makeLabelList(
- []string{"keep1", "keep2"},
- []string{},
- )),
- unpredicated: MakeLabelListAttribute(makeLabelList(
- []string{"throw1", "throw2"},
- []string{},
- )),
- predicate: func(label Label) bool {
- return strings.HasPrefix(label.Label, "keep")
- },
- },
- {
- name: "empty partition",
- input: MakeLabelListAttribute(makeLabelList([]string{}, []string{})),
- predicated: LabelListAttribute{},
- unpredicated: LabelListAttribute{},
- predicate: func(label Label) bool {
- return true
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- predicated, unpredicated := tc.input.Partition(tc.predicate)
- if !predicated.Value.Equals(tc.predicated.Value) {
- t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
- }
- for axis, configs := range predicated.ConfigurableValues {
- tcConfigs, ok := tc.predicated.ConfigurableValues[axis]
- if !ok || !reflect.DeepEqual(configs, tcConfigs) {
- t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated)
- }
- }
- if !unpredicated.Value.Equals(tc.unpredicated.Value) {
- t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
- }
- for axis, configs := range unpredicated.ConfigurableValues {
- tcConfigs, ok := tc.unpredicated.ConfigurableValues[axis]
- if !ok || !reflect.DeepEqual(configs, tcConfigs) {
- t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated)
- }
- }
- })
- }
-}
-
-// labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of
-// typ
-func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper {
- return func(omc OtherModuleContext, label Label) (string, bool) {
- m, ok := omc.ModuleFromName(label.Label)
- if !ok {
- return label.Label, false
- }
- mTyp := omc.OtherModuleType(m)
- if typ == mTyp {
- return label.Label + suffix, true
- }
- return label.Label, false
- }
-}
-
-func TestPartitionLabelListAttribute(t *testing.T) {
- testCases := []struct {
- name string
- ctx *OtherModuleTestContext
- labelList LabelListAttribute
- filters LabelPartitions
- expected PartitionToLabelListAttribute
- expectedErrMsg *string
- }{
- {
- name: "no configurable values",
- ctx: &OtherModuleTestContext{},
- labelList: LabelListAttribute{
- Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
- },
- filters: LabelPartitions{
- "A": LabelPartition{Extensions: []string{".a"}},
- "B": LabelPartition{Extensions: []string{".b"}},
- "C": LabelPartition{Extensions: []string{".c"}},
- },
- expected: PartitionToLabelListAttribute{
- "A": LabelListAttribute{Value: makeLabelList([]string{"a.a"}, []string{})},
- "B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})},
- "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
- },
- },
- {
- name: "no configurable values, remainder partition",
- ctx: &OtherModuleTestContext{},
- labelList: LabelListAttribute{
- Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
- },
- filters: LabelPartitions{
- "A": LabelPartition{Extensions: []string{".a"}, Keep_remainder: true},
- "B": LabelPartition{Extensions: []string{".b"}},
- "C": LabelPartition{Extensions: []string{".c"}},
- },
- expected: PartitionToLabelListAttribute{
- "A": LabelListAttribute{Value: makeLabelList([]string{"a.a", "d.d", "e.e"}, []string{})},
- "B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})},
- "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
- },
- },
- {
- name: "no configurable values, empty partition",
- ctx: &OtherModuleTestContext{},
- labelList: LabelListAttribute{
- Value: makeLabelList([]string{"a.a", "c.c"}, []string{}),
- },
- filters: LabelPartitions{
- "A": LabelPartition{Extensions: []string{".a"}},
- "B": LabelPartition{Extensions: []string{".b"}},
- "C": LabelPartition{Extensions: []string{".c"}},
- },
- expected: PartitionToLabelListAttribute{
- "A": LabelListAttribute{Value: makeLabelList([]string{"a.a"}, []string{})},
- "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
- },
- },
- {
- name: "no configurable values, has map",
- ctx: &OtherModuleTestContext{
- Modules: []TestModuleInfo{{ModuleName: "srcs", Typ: "fg", Dir: "dir"}},
- },
- labelList: LabelListAttribute{
- Value: makeLabelList([]string{"a.a", "srcs", "b.b", "c.c"}, []string{}),
- },
- filters: LabelPartitions{
- "A": LabelPartition{Extensions: []string{".a"}, LabelMapper: labelAddSuffixForTypeMapper("_a", "fg")},
- "B": LabelPartition{Extensions: []string{".b"}},
- "C": LabelPartition{Extensions: []string{".c"}},
- },
- expected: PartitionToLabelListAttribute{
- "A": LabelListAttribute{Value: makeLabelList([]string{"a.a", "srcs_a"}, []string{})},
- "B": LabelListAttribute{Value: makeLabelList([]string{"b.b"}, []string{})},
- "C": LabelListAttribute{Value: makeLabelList([]string{"c.c"}, []string{})},
- },
- },
- {
- name: "configurable values, keeps empty if excludes",
- ctx: &OtherModuleTestContext{},
- labelList: LabelListAttribute{
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "x86": makeLabelList([]string{"a.a", "c.c"}, []string{}),
- "arm": makeLabelList([]string{"b.b"}, []string{}),
- "x86_64": makeLabelList([]string{"b.b"}, []string{"d.d"}),
- },
- },
- },
- filters: LabelPartitions{
- "A": LabelPartition{Extensions: []string{".a"}},
- "B": LabelPartition{Extensions: []string{".b"}},
- "C": LabelPartition{Extensions: []string{".c"}},
- },
- expected: PartitionToLabelListAttribute{
- "A": LabelListAttribute{
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "x86": makeLabelList([]string{"a.a"}, []string{}),
- "x86_64": makeLabelList([]string{}, []string{"c.c"}),
- },
- },
- },
- "B": LabelListAttribute{
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "arm": makeLabelList([]string{"b.b"}, []string{}),
- "x86_64": makeLabelList([]string{"b.b"}, []string{"c.c"}),
- },
- },
- },
- "C": LabelListAttribute{
- ConfigurableValues: configurableLabelLists{
- ArchConfigurationAxis: labelListSelectValues{
- "x86": makeLabelList([]string{"c.c"}, []string{}),
- "x86_64": makeLabelList([]string{}, []string{"c.c"}),
- },
- },
- },
- },
- },
- {
- name: "error for multiple partitions same value",
- ctx: &OtherModuleTestContext{},
- labelList: LabelListAttribute{
- Value: makeLabelList([]string{"a.a", "b.b", "c.c", "d.d", "e.e"}, []string{}),
- },
- filters: LabelPartitions{
- "A": LabelPartition{Extensions: []string{".a"}},
- "other A": LabelPartition{Extensions: []string{".a"}},
- },
- expected: PartitionToLabelListAttribute{},
- expectedErrMsg: proptools.StringPtr(`"a.a" was found in multiple partitions:`),
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- got := PartitionLabelListAttribute(tc.ctx, &tc.labelList, tc.filters)
-
- if hasErrors, expectsErr := len(tc.ctx.errors) > 0, tc.expectedErrMsg != nil; hasErrors != expectsErr {
- t.Errorf("Unexpected error(s): %q, expected: %q", tc.ctx.errors, *tc.expectedErrMsg)
- } else if tc.expectedErrMsg != nil {
- found := false
- for _, err := range tc.ctx.errors {
- if strings.Contains(err, *tc.expectedErrMsg) {
- found = true
- break
- }
- }
-
- if !found {
- t.Errorf("Expected error message: %q, got %q", *tc.expectedErrMsg, tc.ctx.errors)
- }
- return
- }
-
- if len(tc.expected) != len(got) {
- t.Errorf("Expected %d partitions, got %d partitions", len(tc.expected), len(got))
- }
- for partition, expectedLla := range tc.expected {
- gotLla, ok := got[partition]
- if !ok {
- t.Errorf("Expected partition %q, but it was not found %v", partition, got)
- continue
- }
- expectedLabelList := expectedLla.Value
- gotLabelList := gotLla.Value
- if !reflect.DeepEqual(expectedLabelList.Includes, gotLabelList.Includes) {
- t.Errorf("Expected no config includes %v, got %v", expectedLabelList.Includes, gotLabelList.Includes)
- }
- expectedAxes := expectedLla.SortedConfigurationAxes()
- gotAxes := gotLla.SortedConfigurationAxes()
- if !reflect.DeepEqual(expectedAxes, gotAxes) {
- t.Errorf("Expected axes %v, got %v (%#v)", expectedAxes, gotAxes, gotLla)
- }
- for _, axis := range expectedLla.SortedConfigurationAxes() {
- if _, exists := gotLla.ConfigurableValues[axis]; !exists {
- t.Errorf("Expected %s to be a supported axis, but it was not found", axis)
- }
- if expected, got := expectedLla.ConfigurableValues[axis], gotLla.ConfigurableValues[axis]; len(expected) != len(got) {
- t.Errorf("For axis %q: expected configs %v, got %v", axis, expected, got)
- }
- for config, expectedLabelList := range expectedLla.ConfigurableValues[axis] {
- gotLabelList, exists := gotLla.ConfigurableValues[axis][config]
- if !exists {
- t.Errorf("Expected %s to be a supported config, but config was not found", config)
- continue
- }
- if !reflect.DeepEqual(expectedLabelList.Includes, gotLabelList.Includes) {
- t.Errorf("Expected %s %s includes %v, got %v", axis, config, expectedLabelList.Includes, gotLabelList.Includes)
- }
- }
- }
- }
- })
- }
-}
-
-func TestDeduplicateAxesFromBase(t *testing.T) {
- attr := StringListAttribute{
- Value: []string{
- "all_include",
- "arm_include",
- "android_include",
- "linux_x86_include",
- },
- ConfigurableValues: configurableStringLists{
- ArchConfigurationAxis: stringListSelectValues{
- "arm": []string{"arm_include"},
- "x86": []string{"x86_include"},
- },
- OsConfigurationAxis: stringListSelectValues{
- "android": []string{"android_include"},
- "linux": []string{"linux_include"},
- },
- OsArchConfigurationAxis: stringListSelectValues{
- "linux_x86": {"linux_x86_include"},
- },
- ProductVariableConfigurationAxis(false, "a"): stringListSelectValues{
- "a": []string{"not_in_value"},
- },
- },
- }
-
- attr.DeduplicateAxesFromBase()
-
- expectedBaseIncludes := []string{
- "all_include",
- "arm_include",
- "android_include",
- "linux_x86_include",
- }
- if !reflect.DeepEqual(expectedBaseIncludes, attr.Value) {
- t.Errorf("Expected Value includes %q, got %q", attr.Value, expectedBaseIncludes)
- }
- expectedConfiguredIncludes := configurableStringLists{
- ArchConfigurationAxis: stringListSelectValues{
- "x86": []string{"x86_include"},
- },
- OsConfigurationAxis: stringListSelectValues{
- "linux": []string{"linux_include"},
- },
- OsArchConfigurationAxis: stringListSelectValues{},
- ProductVariableConfigurationAxis(false, "a"): stringListSelectValues{
- "a": []string{"not_in_value"},
- },
- }
- for _, axis := range attr.SortedConfigurationAxes() {
- if _, ok := expectedConfiguredIncludes[axis]; !ok {
- t.Errorf("Found unexpected axis %s", axis)
- continue
- }
- expectedForAxis := expectedConfiguredIncludes[axis]
- gotForAxis := attr.ConfigurableValues[axis]
- if len(expectedForAxis) != len(gotForAxis) {
- t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis)
- }
- for config, value := range gotForAxis {
- if expected, ok := expectedForAxis[config]; ok {
- if !reflect.DeepEqual(expected, value) {
- t.Errorf("For %s, expected: %#v, got %#v", axis, expected, value)
- }
- } else {
- t.Errorf("Got unexpected config %q for %s", config, axis)
- }
- }
- }
-}
diff --git a/bazel/testing.go b/bazel/testing.go
deleted file mode 100644
index 9a43b61..0000000
--- a/bazel/testing.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bazel
-
-import (
- "fmt"
-
- "github.com/google/blueprint"
-)
-
-// TestModuleInfo implements blueprint.Module interface with sufficient information to mock a subset of
-// a blueprint ModuleContext
-type TestModuleInfo struct {
- ModuleName string
- Typ string
- Dir string
-}
-
-// Name returns name for testModuleInfo -- required to implement blueprint.Module
-func (mi TestModuleInfo) Name() string {
- return mi.ModuleName
-}
-
-// GenerateBuildActions unused, but required to implmeent blueprint.Module
-func (mi TestModuleInfo) GenerateBuildActions(blueprint.ModuleContext) {}
-
-func (mi TestModuleInfo) equals(other TestModuleInfo) bool {
- return mi.ModuleName == other.ModuleName && mi.Typ == other.Typ && mi.Dir == other.Dir
-}
-
-// ensure testModuleInfo implements blueprint.Module
-var _ blueprint.Module = TestModuleInfo{}
-
-// OtherModuleTestContext is a mock context that implements OtherModuleContext
-type OtherModuleTestContext struct {
- Modules []TestModuleInfo
- errors []string
-}
-
-// ModuleFromName retrieves the testModuleInfo corresponding to name, if it exists
-func (omc *OtherModuleTestContext) ModuleFromName(name string) (blueprint.Module, bool) {
- for _, m := range omc.Modules {
- if m.ModuleName == name {
- return m, true
- }
- }
- return TestModuleInfo{}, false
-}
-
-// testModuleInfo returns the testModuleInfo corresponding to a blueprint.Module if it exists in omc
-func (omc *OtherModuleTestContext) testModuleInfo(m blueprint.Module) (TestModuleInfo, bool) {
- mi, ok := m.(TestModuleInfo)
- if !ok {
- return TestModuleInfo{}, false
- }
- for _, other := range omc.Modules {
- if other.equals(mi) {
- return mi, true
- }
- }
- return TestModuleInfo{}, false
-}
-
-// OtherModuleType returns type of m if it exists in omc
-func (omc *OtherModuleTestContext) OtherModuleType(m blueprint.Module) string {
- if mi, ok := omc.testModuleInfo(m); ok {
- return mi.Typ
- }
- return ""
-}
-
-// OtherModuleName returns name of m if it exists in omc
-func (omc *OtherModuleTestContext) OtherModuleName(m blueprint.Module) string {
- if mi, ok := omc.testModuleInfo(m); ok {
- return mi.ModuleName
- }
- return ""
-}
-
-// OtherModuleDir returns dir of m if it exists in omc
-func (omc *OtherModuleTestContext) OtherModuleDir(m blueprint.Module) string {
- if mi, ok := omc.testModuleInfo(m); ok {
- return mi.Dir
- }
- return ""
-}
-
-func (omc *OtherModuleTestContext) ModuleErrorf(format string, args ...interface{}) {
- omc.errors = append(omc.errors, fmt.Sprintf(format, args...))
-}
-
-// Ensure otherModuleTestContext implements OtherModuleContext
-var _ OtherModuleContext = &OtherModuleTestContext{}
diff --git a/bin/aninja b/bin/aninja
index 5acb968..5cb5a55 100755
--- a/bin/aninja
+++ b/bin/aninja
@@ -34,5 +34,5 @@
esac
cd $(gettop)
-prebuilts/build-tools/${host_arch}/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja "$@"
+prebuilts/build-tools/${host_arch}/bin/ninja -f $(getoutdir)/combined-${TARGET_PRODUCT}.ninja "$@"
diff --git a/bin/dirmods b/bin/dirmods
index a6d4de3..c8976d5 100755
--- a/bin/dirmods
+++ b/bin/dirmods
@@ -32,7 +32,10 @@
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('path')
+ parser.add_argument('--no-recurse', '-n', action='store_true',
+ help='Do not include modules defined in subdirs of path')
args = parser.parse_args()
+ should_recurse = not args.no_recurse
d = os.path.normpath(args.path)
# Fix absolute path to be relative to build top
@@ -43,15 +46,15 @@
if d.startswith(base):
d = d[len(base):]
- prefix = d + '/'
+ prefix = d + os.path.sep
module_info = modinfo.ReadModuleInfo()
results = set()
for m in module_info.values():
- for path in m.get(u'path', []):
- if path == d or path.startswith(prefix):
- name = m.get(u'module_name')
+ for path in m.get('path', []):
+ if path == d or (should_recurse and path.startswith(prefix)):
+ name = m.get('module_name')
if name:
results.add(name)
diff --git a/bin/soongdbg b/bin/soongdbg
index a73bdf9..98d31eb 100755
--- a/bin/soongdbg
+++ b/bin/soongdbg
@@ -216,7 +216,7 @@
help="jq query for each module metadata")
parser.add_argument("--deptags", action="store_true",
help="show dependency tags (makes the graph much more complex)")
- parser.add_argument("--tag", action="append",
+ parser.add_argument("--tag", action="append", default=[],
help="Limit output to these dependency tags.")
group = parser.add_argument_group("output formats",
diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go
index b72b6d3..8ecea98 100644
--- a/bloaty/bloaty.go
+++ b/bloaty/bloaty.go
@@ -88,7 +88,7 @@
if !m.ExportedToMake() {
return
}
- filePaths, ok := android.SingletonModuleProvider(ctx, m, fileSizeMeasurerKey)
+ filePaths, ok := android.OtherModuleProvider(ctx, m, fileSizeMeasurerKey)
if !ok {
return
}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index ba12682..28c0268 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -9,7 +9,6 @@
"androidbp_to_build_templates.go",
"build_conversion.go",
"bzl_conversion.go",
- "configurability.go",
"constants.go",
"conversion.go",
],
@@ -21,7 +20,6 @@
"soong-android-allowlists",
"soong-android-soongconfig",
"soong-apex",
- "soong-bazel",
"soong-cc",
"soong-cc-config",
"soong-etc",
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index bd56768..18213a8 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -26,7 +26,6 @@
"strings"
"android/soong/android"
- "android/soong/bazel"
"android/soong/starlark_fmt"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -182,12 +181,11 @@
}
type CodegenContext struct {
- config android.Config
- context *android.Context
- mode CodegenMode
- additionalDeps []string
- unconvertedDepMode unconvertedDepsMode
- topDir string
+ config android.Config
+ context *android.Context
+ mode CodegenMode
+ additionalDeps []string
+ topDir string
}
func (ctx *CodegenContext) Mode() CodegenMode {
@@ -207,16 +205,6 @@
QueryView CodegenMode = iota
)
-type unconvertedDepsMode int
-
-const (
- // Include a warning in conversion metrics about converted modules with unconverted direct deps
- warnUnconvertedDeps unconvertedDepsMode = iota
- // Error and fail conversion if encountering a module with unconverted direct deps
- // Enabled by setting environment variable `BP2BUILD_ERROR_UNCONVERTED`
- errorModulesUnconvertedDeps
-)
-
func (mode CodegenMode) String() string {
switch mode {
case QueryView:
@@ -245,13 +233,11 @@
// NewCodegenContext creates a wrapper context that conforms to PathContext for
// writing BUILD files in the output directory.
func NewCodegenContext(config android.Config, context *android.Context, mode CodegenMode, topDir string) *CodegenContext {
- var unconvertedDeps unconvertedDepsMode
return &CodegenContext{
- context: context,
- config: config,
- mode: mode,
- unconvertedDepMode: unconvertedDeps,
- topDir: topDir,
+ context: context,
+ config: config,
+ mode: mode,
+ topDir: topDir,
}
}
@@ -482,14 +468,6 @@
}), nil
case reflect.Struct:
- // Special cases where the bp2build sends additional information to the codegenerator
- // by wrapping the attributes in a custom struct type.
- if attr, ok := propertyValue.Interface().(bazel.Attribute); ok {
- return prettyPrintAttribute(attr, indent)
- } else if label, ok := propertyValue.Interface().(bazel.Label); ok {
- return fmt.Sprintf("%q", label.Label), nil
- }
-
// Sort and print the struct props by the key.
structProps, err := extractStructProperties(propertyValue, indent)
@@ -506,7 +484,7 @@
// Interfaces are used for for arch, multilib and target properties.
return "", nil
case reflect.Map:
- if v, ok := propertyValue.Interface().(bazel.StringMapAttribute); ok {
+ if v, ok := propertyValue.Interface().(map[string]string); ok {
return starlark_fmt.PrintStringStringDict(v, indent), nil
}
return "", fmt.Errorf("bp2build expects map of type map[string]string for field: %s", propertyValue)
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
deleted file mode 100644
index 3d9f0a2..0000000
--- a/bp2build/configurability.go
+++ /dev/null
@@ -1,328 +0,0 @@
-package bp2build
-
-import (
- "fmt"
- "reflect"
-
- "android/soong/android"
- "android/soong/bazel"
- "android/soong/starlark_fmt"
-)
-
-// Configurability support for bp2build.
-
-type selects map[string]reflect.Value
-
-func getStringValue(str bazel.StringAttribute) (reflect.Value, []selects) {
- value := reflect.ValueOf(str.Value)
-
- if !str.HasConfigurableValues() {
- return value, []selects{}
- }
-
- ret := selects{}
- for _, axis := range str.SortedConfigurationAxes() {
- configToStrs := str.ConfigurableValues[axis]
- for config, strs := range configToStrs {
- selectKey := axis.SelectKey(config)
- ret[selectKey] = reflect.ValueOf(strs)
- }
- }
-
- // if there is a select, use the base value as the conditions default value
- if len(ret) > 0 {
- if _, ok := ret[bazel.ConditionsDefaultSelectKey]; !ok {
- ret[bazel.ConditionsDefaultSelectKey] = value
- value = reflect.Zero(value.Type())
- }
- }
-
- return value, []selects{ret}
-}
-
-func getStringListValues(list bazel.StringListAttribute) (reflect.Value, []selects, bool) {
- value := reflect.ValueOf(list.Value)
- prepend := list.Prepend
- if !list.HasConfigurableValues() {
- return value, []selects{}, prepend
- }
-
- var ret []selects
- for _, axis := range list.SortedConfigurationAxes() {
- configToLists := list.ConfigurableValues[axis]
- archSelects := map[string]reflect.Value{}
- for config, labels := range configToLists {
- selectKey := axis.SelectKey(config)
- archSelects[selectKey] = reflect.ValueOf(labels)
- }
- if len(archSelects) > 0 {
- ret = append(ret, archSelects)
- }
- }
-
- return value, ret, prepend
-}
-
-func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) {
- value := reflect.ValueOf(label.Value)
- if !label.HasConfigurableValues() {
- return value, []selects{}
- }
-
- ret := selects{}
- for _, axis := range label.SortedConfigurationAxes() {
- configToLabels := label.ConfigurableValues[axis]
- for config, labels := range configToLabels {
- selectKey := axis.SelectKey(config)
- ret[selectKey] = reflect.ValueOf(labels)
- }
- }
-
- // if there is a select, use the base value as the conditions default value
- if len(ret) > 0 {
- ret[bazel.ConditionsDefaultSelectKey] = value
- value = reflect.Zero(value.Type())
- }
-
- return value, []selects{ret}
-}
-
-func getBoolValue(boolAttr bazel.BoolAttribute) (reflect.Value, []selects) {
- value := reflect.ValueOf(boolAttr.Value)
- if !boolAttr.HasConfigurableValues() {
- return value, []selects{}
- }
-
- ret := selects{}
- for _, axis := range boolAttr.SortedConfigurationAxes() {
- configToBools := boolAttr.ConfigurableValues[axis]
- for config, bools := range configToBools {
- selectKey := axis.SelectKey(config)
- ret[selectKey] = reflect.ValueOf(bools)
- }
- }
- // if there is a select, use the base value as the conditions default value
- if len(ret) > 0 {
- ret[bazel.ConditionsDefaultSelectKey] = value
- value = reflect.Zero(value.Type())
- }
-
- return value, []selects{ret}
-}
-func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects, bool) {
- value := reflect.ValueOf(list.Value.Includes)
- prepend := list.Prepend
- var ret []selects
- for _, axis := range list.SortedConfigurationAxes() {
- configToLabels := list.ConfigurableValues[axis]
- if !configToLabels.HasConfigurableValues() {
- continue
- }
- archSelects := map[string]reflect.Value{}
- defaultVal := configToLabels[bazel.ConditionsDefaultConfigKey]
- // Skip empty list values unless ether EmitEmptyList is true, or these values differ from the default.
- emitEmptyList := list.EmitEmptyList || len(defaultVal.Includes) > 0
- for config, labels := range configToLabels {
- // Omit any entries in the map which match the default value, for brevity.
- if config != bazel.ConditionsDefaultConfigKey && labels.Equals(defaultVal) {
- continue
- }
- selectKey := axis.SelectKey(config)
- if use, value := labelListSelectValue(selectKey, labels, emitEmptyList); use {
- archSelects[selectKey] = value
- }
- }
- if len(archSelects) > 0 {
- ret = append(ret, archSelects)
- }
- }
-
- return value, ret, prepend
-}
-
-func labelListSelectValue(selectKey string, list bazel.LabelList, emitEmptyList bool) (bool, reflect.Value) {
- if selectKey == bazel.ConditionsDefaultSelectKey || emitEmptyList || len(list.Includes) > 0 {
- return true, reflect.ValueOf(list.Includes)
- } else if len(list.Excludes) > 0 {
- // if there is still an excludes -- we need to have an empty list for this select & use the
- // value in conditions default Includes
- return true, reflect.ValueOf([]string{})
- }
- return false, reflect.Zero(reflect.TypeOf([]string{}))
-}
-
-var (
- emptyBazelList = "[]"
- bazelNone = "None"
-)
-
-// prettyPrintAttribute converts an Attribute to its Bazel syntax. May contain
-// select statements.
-func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
- var value reflect.Value
- // configurableAttrs is the list of individual select statements to be
- // concatenated together. These select statements should be along different
- // axes. For example, one element may be
- // `select({"//color:red": "one", "//color:green": "two"})`, and the second
- // element may be `select({"//animal:cat": "three", "//animal:dog": "four"}).
- // These selects should be sorted by axis identifier.
- var configurableAttrs []selects
- var prepend bool
- var defaultSelectValue *string
- var emitZeroValues bool
- // If true, print the default attribute value, even if the attribute is zero.
- shouldPrintDefault := false
- switch list := v.(type) {
- case bazel.StringAttribute:
- if err := list.Collapse(); err != nil {
- return "", err
- }
- value, configurableAttrs = getStringValue(list)
- defaultSelectValue = &bazelNone
- case bazel.StringListAttribute:
- value, configurableAttrs, prepend = getStringListValues(list)
- defaultSelectValue = &emptyBazelList
- case bazel.LabelListAttribute:
- value, configurableAttrs, prepend = getLabelListValues(list)
- emitZeroValues = list.EmitEmptyList
- defaultSelectValue = &emptyBazelList
- if list.ForceSpecifyEmptyList && (!value.IsNil() || list.HasConfigurableValues()) {
- shouldPrintDefault = true
- }
- case bazel.LabelAttribute:
- if err := list.Collapse(); err != nil {
- return "", err
- }
- value, configurableAttrs = getLabelValue(list)
- defaultSelectValue = &bazelNone
- case bazel.BoolAttribute:
- if err := list.Collapse(); err != nil {
- return "", err
- }
- value, configurableAttrs = getBoolValue(list)
- defaultSelectValue = &bazelNone
- default:
- return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
- }
-
- var err error
- ret := ""
- if value.Kind() != reflect.Invalid {
- s, err := prettyPrint(value, indent, false) // never emit zero values for the base value
- if err != nil {
- return ret, err
- }
-
- ret += s
- }
- // Convenience function to prepend/append selects components to an attribute value.
- concatenateSelects := func(selectsData selects, defaultValue *string, s string, prepend bool) (string, error) {
- selectMap, err := prettyPrintSelectMap(selectsData, defaultValue, indent, emitZeroValues)
- if err != nil {
- return "", err
- }
- var left, right string
- if prepend {
- left, right = selectMap, s
- } else {
- left, right = s, selectMap
- }
- if left != "" && right != "" {
- left += " + "
- }
- left += right
-
- return left, nil
- }
-
- for _, configurableAttr := range configurableAttrs {
- ret, err = concatenateSelects(configurableAttr, defaultSelectValue, ret, prepend)
- if err != nil {
- return "", err
- }
- }
-
- if ret == "" && shouldPrintDefault {
- return *defaultSelectValue, nil
- }
- return ret, nil
-}
-
-// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
-// to construct a select map for any kind of attribute type.
-func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue *string, indent int, emitZeroValues bool) (string, error) {
- if selectMap == nil {
- return "", nil
- }
-
- var selects string
- for _, selectKey := range android.SortedKeys(selectMap) {
- if selectKey == bazel.ConditionsDefaultSelectKey {
- // Handle default condition later.
- continue
- }
- value := selectMap[selectKey]
- if isZero(value) && !emitZeroValues && isZero(selectMap[bazel.ConditionsDefaultSelectKey]) {
- // Ignore zero values to not generate empty lists. However, always note zero values if
- // the default value is non-zero.
- continue
- }
- s, err := prettyPrintSelectEntry(value, selectKey, indent, true)
- if err != nil {
- return "", err
- }
- // s could still be an empty string, e.g. unset slices of structs with
- // length of 0.
- if s != "" {
- selects += s + ",\n"
- }
- }
-
- if len(selects) == 0 {
- // If there is a default value, and there are no selects for this axis, print that without any selects.
- if val, exists := selectMap[bazel.ConditionsDefaultSelectKey]; exists {
- return prettyPrint(val, indent, emitZeroValues)
- }
- // No conditions (or all values are empty lists), so no need for a map.
- return "", nil
- }
-
- // Create the map.
- ret := "select({\n"
- ret += selects
-
- // Handle the default condition
- s, err := prettyPrintSelectEntry(selectMap[bazel.ConditionsDefaultSelectKey], bazel.ConditionsDefaultSelectKey, indent, emitZeroValues)
- if err != nil {
- return "", err
- }
- if s != "" {
- // Print the custom default value.
- ret += s
- ret += ",\n"
- } else if defaultValue != nil {
- // Print an explicit empty list (the default value) even if the value is
- // empty, to avoid errors about not finding a configuration that matches.
- ret += fmt.Sprintf("%s\"%s\": %s,\n", starlark_fmt.Indention(indent+1), bazel.ConditionsDefaultSelectKey, *defaultValue)
- }
-
- ret += starlark_fmt.Indention(indent)
- ret += "})"
-
- return ret, nil
-}
-
-// prettyPrintSelectEntry converts a reflect.Value into an entry in a select map
-// with a provided key.
-func prettyPrintSelectEntry(value reflect.Value, key string, indent int, emitZeroValues bool) (string, error) {
- s := starlark_fmt.Indention(indent + 1)
- v, err := prettyPrint(value, indent+1, emitZeroValues)
- if err != nil {
- return "", err
- }
- if v == "" {
- return "", nil
- }
- s += fmt.Sprintf("\"%s\": %s", key, v)
- return s, nil
-}
diff --git a/bp2build/constants.go b/bp2build/constants.go
index 4870dff..76ba106 100644
--- a/bp2build/constants.go
+++ b/bp2build/constants.go
@@ -20,9 +20,4 @@
// The file name used for automatically generated files.
GeneratedBuildFileName = "BUILD.bazel"
-
- // The file name used for hand-crafted build targets.
- // NOTE: It is okay that this matches GeneratedBuildFileName, since we generate BUILD files in a different directory to source files
- // FIXME: Because there are hundreds of existing BUILD.bazel files in the AOSP tree, we should pick another name here, like BUILD.android
- HandcraftedBuildFileName = "BUILD.bazel"
)
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 09262e5..8679821 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -56,6 +56,7 @@
)
func registerBpfBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("bpf_defaults", defaultsFactory)
ctx.RegisterModuleType("bpf", BpfFactory)
}
@@ -77,10 +78,16 @@
// the C/C++ module.
Cflags []string
- // directories (relative to the root of the source tree) that will
- // be added to the include paths using -I.
+ // list of directories relative to the root of the source tree that
+ // will be added to the include paths using -I.
+ // If possible, don't use this. If adding paths from the current
+ // directory, use local_include_dirs. If adding paths from other
+ // modules, use export_include_dirs in that module.
Include_dirs []string
+ // list of directories relative to the Blueprint file that will be
+ // added to the include path using -I.
+ Local_include_dirs []string
// optional subdirectory under which this module is installed into.
Sub_dir string
@@ -94,7 +101,7 @@
type bpf struct {
android.ModuleBase
-
+ android.DefaultableModuleBase
properties BpfProperties
objs android.Paths
@@ -148,24 +155,32 @@
"-no-canonical-prefixes",
"-O2",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+
"-isystem bionic/libc/include",
"-isystem bionic/libc/kernel/uapi",
// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
"-isystem bionic/libc/kernel/uapi/asm-arm64",
"-isystem bionic/libc/kernel/android/uapi",
- "-I packages/modules/Connectivity/staticlibs/native/bpf_headers/include/bpf",
+ "-I packages/modules/Connectivity/bpf/headers/include",
// TODO(b/149785767): only give access to specific file with AID_* constants
"-I system/core/libcutils/include",
"-I " + ctx.ModuleDir(),
}
+ for _, dir := range android.PathsForModuleSrc(ctx, bpf.properties.Local_include_dirs) {
+ cflags = append(cflags, "-I "+dir.String())
+ }
+
for _, dir := range android.PathsForSource(ctx, bpf.properties.Include_dirs) {
cflags = append(cflags, "-I "+dir.String())
}
cflags = append(cflags, bpf.properties.Cflags...)
- if proptools.Bool(bpf.properties.Btf) {
+ if proptools.BoolDefault(bpf.properties.Btf, true) {
cflags = append(cflags, "-g")
if runtime.GOOS != "darwin" {
cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
@@ -190,7 +205,7 @@
},
})
- if proptools.Bool(bpf.properties.Btf) {
+ if proptools.BoolDefault(bpf.properties.Btf, true) {
objStripped := android.ObjPathWithExt(ctx, "", src, "o")
ctx.Build(pctx, android.BuildParams{
Rule: stripRule,
@@ -260,6 +275,26 @@
}
}
+type Defaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+func defaultsFactory() android.Module {
+ return DefaultsFactory()
+}
+
+func DefaultsFactory(props ...interface{}) android.Module {
+ module := &Defaults{}
+
+ module.AddProperties(props...)
+ module.AddProperties(&BpfProperties{})
+
+ android.InitDefaultsModule(module)
+
+ return module
+}
+
func (bpf *bpf) SubDir() string {
return bpf.properties.Sub_dir
}
@@ -270,5 +305,7 @@
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
return module
}
diff --git a/bpf/libbpf/Android.bp b/bpf/libbpf/Android.bp
new file mode 100644
index 0000000..f0ba90f
--- /dev/null
+++ b/bpf/libbpf/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-libbpf",
+ pkgPath: "android/soong/bpf/libbpf",
+ deps: [
+ "blueprint",
+ "blueprint-proptools",
+ "soong-android",
+ "soong-cc",
+ "soong-cc-config",
+ ],
+ srcs: [
+ "libbpf_prog.go",
+ ],
+ testSrcs: [
+ "libbpf_prog_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/bpf/libbpf/libbpf_prog.go b/bpf/libbpf/libbpf_prog.go
new file mode 100644
index 0000000..ac61510
--- /dev/null
+++ b/bpf/libbpf/libbpf_prog.go
@@ -0,0 +1,310 @@
+// 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 libbpf_prog
+
+import (
+ "fmt"
+ "io"
+ "runtime"
+ "strings"
+
+ "android/soong/android"
+ "android/soong/cc"
+ "android/soong/genrule"
+
+ "github.com/google/blueprint"
+)
+
+type libbpfProgDepType struct {
+ blueprint.BaseDependencyTag
+}
+
+func init() {
+ registerLibbpfProgBuildComponents(android.InitRegistrationContext)
+ pctx.Import("android/soong/cc/config")
+ pctx.StaticVariable("relPwd", cc.PwdPrefix())
+}
+
+var (
+ pctx = android.NewPackageContext("android/soong/bpf/libbpf_prog")
+
+ libbpfProgCcRule = pctx.AndroidStaticRule("libbpfProgCcRule",
+ blueprint.RuleParams{
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
+ Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
+ CommandDeps: []string{"$ccCmd"},
+ },
+ "ccCmd", "cFlags")
+
+ libbpfProgStripRule = pctx.AndroidStaticRule("libbpfProgStripRule",
+ blueprint.RuleParams{
+ Command: `$stripCmd --strip-unneeded --remove-section=.rel.BTF ` +
+ `--remove-section=.rel.BTF.ext --remove-section=.BTF.ext $in -o $out`,
+ CommandDeps: []string{"$stripCmd"},
+ },
+ "stripCmd")
+
+ libbpfProgDepTag = libbpfProgDepType{}
+)
+
+func registerLibbpfProgBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("libbpf_defaults", defaultsFactory)
+ ctx.RegisterModuleType("libbpf_prog", LibbpfProgFactory)
+}
+
+var PrepareForTestWithLibbpfProg = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(registerLibbpfProgBuildComponents),
+ android.FixtureAddFile("libbpf_headers/Foo.h", nil),
+ android.FixtureAddFile("libbpf_headers/Android.bp", []byte(`
+ genrule {
+ name: "libbpf_headers",
+ out: ["foo.h",],
+ }
+ `)),
+ genrule.PrepareForTestWithGenRuleBuildComponents,
+)
+
+type LibbpfProgProperties struct {
+ // source paths to the files.
+ Srcs []string `android:"path"`
+
+ // additional cflags that should be used to build the libbpf variant of
+ // the C/C++ module.
+ Cflags []string `android:"arch_variant"`
+
+ // list of directories relative to the Blueprint file that will
+ // be added to the include path using -I
+ Local_include_dirs []string `android:"arch_variant"`
+
+ Header_libs []string `android:"arch_variant"`
+
+ // optional subdirectory under which this module is installed into.
+ Relative_install_path string
+}
+
+type libbpfProg struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ properties LibbpfProgProperties
+ objs android.Paths
+}
+
+var _ android.ImageInterface = (*libbpfProg)(nil)
+
+func (libbpf *libbpfProg) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+
+func (libbpf *libbpfProg) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (libbpf *libbpfProg) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (libbpf *libbpfProg) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return true
+}
+
+func (libbpf *libbpfProg) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (libbpf *libbpfProg) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (libbpf *libbpfProg) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (libbpf *libbpfProg) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (libbpf *libbpfProg) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ return nil
+}
+
+func (libbpf *libbpfProg) SetImageVariation(ctx android.BaseModuleContext, variation string) {
+}
+
+func (libbpf *libbpfProg) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), libbpfProgDepTag, "libbpf_headers")
+ ctx.AddVariationDependencies(nil, cc.HeaderDepTag(), libbpf.properties.Header_libs...)
+}
+
+func (libbpf *libbpfProg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ var cFlagsDeps android.Paths
+ cflags := []string{
+ "-nostdlibinc",
+
+ // Make paths in deps files relative
+ "-no-canonical-prefixes",
+
+ "-O2",
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+
+ "-isystem bionic/libc/include",
+ "-isystem bionic/libc/kernel/uapi",
+ // The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
+ "-isystem bionic/libc/kernel/uapi/asm-arm64",
+ "-isystem bionic/libc/kernel/android/uapi",
+ "-I " + ctx.ModuleDir(),
+ "-g", //Libbpf builds require BTF data
+ }
+
+ if runtime.GOOS != "darwin" {
+ cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
+ }
+
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ depTag := ctx.OtherModuleDependencyTag(dep)
+ if depTag == libbpfProgDepTag {
+ if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
+ cFlagsDeps = append(cFlagsDeps, genRule.GeneratedDeps()...)
+ dirs := genRule.GeneratedHeaderDirs()
+ for _, dir := range dirs {
+ cflags = append(cflags, "-I "+dir.String())
+ }
+ } else {
+ depName := ctx.OtherModuleName(dep)
+ ctx.ModuleErrorf("module %q is not a genrule", depName)
+ }
+ } else if depTag == cc.HeaderDepTag() {
+ depExporterInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
+ for _, dir := range depExporterInfo.IncludeDirs {
+ cflags = append(cflags, "-I "+dir.String())
+ }
+ }
+ })
+
+ for _, dir := range android.PathsForModuleSrc(ctx, libbpf.properties.Local_include_dirs) {
+ cflags = append(cflags, "-I "+dir.String())
+ }
+
+ cflags = append(cflags, libbpf.properties.Cflags...)
+
+ srcs := android.PathsForModuleSrc(ctx, libbpf.properties.Srcs)
+
+ for _, src := range srcs {
+ if strings.ContainsRune(src.Base(), '_') {
+ ctx.ModuleErrorf("invalid character '_' in source name")
+ }
+ obj := android.ObjPathWithExt(ctx, "unstripped", src, "o")
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: libbpfProgCcRule,
+ Input: src,
+ Implicits: cFlagsDeps,
+ Output: obj,
+ Args: map[string]string{
+ "cFlags": strings.Join(cflags, " "),
+ "ccCmd": "${config.ClangBin}/clang",
+ },
+ })
+
+ objStripped := android.ObjPathWithExt(ctx, "", src, "o")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: libbpfProgStripRule,
+ Input: obj,
+ Output: objStripped,
+ Args: map[string]string{
+ "stripCmd": "${config.ClangBin}/llvm-strip",
+ },
+ })
+ libbpf.objs = append(libbpf.objs, objStripped.WithoutRel())
+ }
+
+ installDir := android.PathForModuleInstall(ctx, "etc", "bpf/libbpf")
+ if len(libbpf.properties.Relative_install_path) > 0 {
+ installDir = installDir.Join(ctx, libbpf.properties.Relative_install_path)
+ }
+ for _, obj := range libbpf.objs {
+ ctx.PackageFile(installDir, obj.Base(), obj)
+ }
+
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
+
+ ctx.SetOutputFiles(libbpf.objs, "")
+}
+
+func (libbpf *libbpfProg) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ var names []string
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+ fmt.Fprintln(w)
+ var localModulePath string
+ localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf/libbpf"
+ if len(libbpf.properties.Relative_install_path) > 0 {
+ localModulePath += "/" + libbpf.properties.Relative_install_path
+ }
+ for _, obj := range libbpf.objs {
+ objName := name + "_" + obj.Base()
+ names = append(names, objName)
+ fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf.obj")
+ fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
+ fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
+ fmt.Fprintln(w, localModulePath)
+ // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
+ for _, extra := range data.Extra {
+ extra(w, nil)
+ }
+ fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
+ fmt.Fprintln(w)
+ }
+ fmt.Fprintln(w, "include $(CLEAR_VARS)", " # libbpf.libbpf")
+ fmt.Fprintln(w, "LOCAL_MODULE := ", name)
+ android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", names)
+ fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
+ },
+ }
+}
+
+type Defaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+func defaultsFactory() android.Module {
+ return DefaultsFactory()
+}
+
+func DefaultsFactory(props ...interface{}) android.Module {
+ module := &Defaults{}
+
+ module.AddProperties(props...)
+ module.AddProperties(&LibbpfProgProperties{})
+
+ android.InitDefaultsModule(module)
+
+ return module
+}
+
+func LibbpfProgFactory() android.Module {
+ module := &libbpfProg{}
+
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
+
+ return module
+}
diff --git a/bpf/libbpf/libbpf_prog_test.go b/bpf/libbpf/libbpf_prog_test.go
new file mode 100644
index 0000000..f4f5167
--- /dev/null
+++ b/bpf/libbpf/libbpf_prog_test.go
@@ -0,0 +1,69 @@
+// 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 libbpf_prog
+
+import (
+ "os"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func TestMain(m *testing.M) {
+ os.Exit(m.Run())
+}
+
+var prepareForLibbpfProgTest = android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "bpf.c": nil,
+ "bpf_invalid_name.c": nil,
+ "BpfTest.cpp": nil,
+ },
+ ),
+ PrepareForTestWithLibbpfProg,
+)
+
+func TestLibbpfProgDataDependency(t *testing.T) {
+ bp := `
+ libbpf_prog {
+ name: "bpf.o",
+ srcs: ["bpf.c"],
+ }
+
+ cc_test {
+ name: "vts_test_binary_bpf_module",
+ srcs: ["BpfTest.cpp"],
+ data: [":bpf.o"],
+ gtest: false,
+ }
+ `
+
+ prepareForLibbpfProgTest.RunTestWithBp(t, bp)
+}
+
+func TestLibbpfProgSourceName(t *testing.T) {
+ bp := `
+ libbpf_prog {
+ name: "bpf_invalid_name.o",
+ srcs: ["bpf_invalid_name.c"],
+ }
+ `
+ prepareForLibbpfProgTest.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `invalid character '_' in source name`)).
+ RunTestWithBp(t, bp)
+}
diff --git a/build_kzip.bash b/build_kzip.bash
index 4c42048..850aeda 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -40,6 +40,7 @@
merge_zips
xref_cxx
xref_java
+ xref_kotlin
# TODO: b/286390153 - reenable rust
# xref_rust
)
diff --git a/cc/Android.bp b/cc/Android.bp
index 3bbcaa9..88a793c 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -16,7 +16,6 @@
"soong-etc",
"soong-fuzz",
"soong-genrule",
- "soong-multitree",
"soong-testing",
"soong-tradefed",
],
@@ -65,7 +64,6 @@
"library.go",
"library_headers.go",
"library_sdk_member.go",
- "library_stub.go",
"native_bridge_sdk_trait.go",
"object.go",
"test.go",
@@ -73,7 +71,6 @@
"ndk_abi.go",
"ndk_headers.go",
"ndk_library.go",
- "ndk_prebuilt.go",
"ndk_sysroot.go",
"llndk_library.go",
@@ -105,6 +102,7 @@
"orderfile_test.go",
"prebuilt_test.go",
"proto_test.go",
+ "sabi_test.go",
"sanitize_test.go",
"sdk_test.go",
"test_data_test.go",
@@ -119,4 +117,6 @@
"cmake_module_cc.txt",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/cc/TEST_MAPPING b/cc/TEST_MAPPING
new file mode 100644
index 0000000..be2809d
--- /dev/null
+++ b/cc/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "bionic"
+ }
+ ]
+}
diff --git a/cc/afdo.go b/cc/afdo.go
index 6921edf..14d105e 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -47,6 +47,10 @@
if ctx.Config().Eng() {
afdo.Properties.Afdo = false
}
+ // Disable for native coverage builds.
+ if ctx.DeviceConfig().NativeCoverageEnabled() {
+ afdo.Properties.Afdo = false
+ }
}
// afdoEnabled returns true for binaries and shared libraries
@@ -76,6 +80,8 @@
}
if afdo.Properties.Afdo || afdo.Properties.AfdoDep {
+ // Emit additional debug info for AutoFDO
+ flags.Local.CFlags = append([]string{"-fdebug-info-for-profiling"}, flags.Local.CFlags...)
// We use `-funique-internal-linkage-names` to associate profiles to the right internal
// functions. This option should be used before generating a profile. Because a profile
// generated for a binary without unique names doesn't work well building a binary with
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 4134653..6966f76 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -21,7 +21,6 @@
"strings"
"android/soong/android"
- "android/soong/multitree"
)
var (
@@ -451,10 +450,6 @@
})
}
-func (c *ndkPrebuiltStlLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- entries.Class = "SHARED_LIBRARIES"
-}
-
func (p *prebuiltLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if p.properties.Check_elf_files != nil {
@@ -483,34 +478,6 @@
androidMkWritePrebuiltOptions(p.baseLinker, entries)
}
-func (a *apiLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- entries.Class = "SHARED_LIBRARIES"
- entries.SubName += multitree.GetApiImportSuffix()
-
- entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- a.libraryDecorator.androidMkWriteExportedFlags(entries)
- src := *a.properties.Src
- path, file := filepath.Split(src)
- stem, suffix, ext := android.SplitFileExt(file)
- entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
- entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
- entries.SetString("LOCAL_MODULE_STEM", stem)
- entries.SetString("LOCAL_MODULE_PATH", path)
- entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- entries.SetString("LOCAL_SOONG_TOC", a.toc().String())
- })
-}
-
-func (a *apiHeadersDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- entries.Class = "HEADER_LIBRARIES"
- entries.SubName += multitree.GetApiImportSuffix()
-
- entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- a.libraryDecorator.androidMkWriteExportedFlags(entries)
- entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- })
-}
-
func androidMkWritePrebuiltOptions(linker *baseLinker, entries *android.AndroidMkEntries) {
allow := linker.Properties.Allow_undefined_symbols
if allow != nil {
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 71e0cd8..4063714 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -132,7 +132,7 @@
if ccModule.linker != nil {
specifiedDeps := specifiedDeps{}
- specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
+ specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx.SdkModuleContext(), ccModule, specifiedDeps)
p.SharedLibs = specifiedDeps.sharedLibs
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
diff --git a/cc/builder.go b/cc/builder.go
index 367bda3..cd535c1 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -22,6 +22,7 @@
"fmt"
"path/filepath"
"runtime"
+ "slices"
"strconv"
"strings"
@@ -156,11 +157,17 @@
"args")
// Rule to invoke `strip` (to discard symbols and data from object files) on darwin architecture.
- darwinStrip = pctx.AndroidStaticRule("darwinStrip",
- blueprint.RuleParams{
- Command: "${config.MacStripPath} -u -r -o $out $in",
- CommandDeps: []string{"${config.MacStripPath}"},
- })
+ darwinStrip = func() blueprint.Rule {
+ if runtime.GOOS == "darwin" {
+ return pctx.AndroidStaticRule("darwinStrip",
+ blueprint.RuleParams{
+ Command: "${config.MacStripPath} -u -r -o $out $in",
+ CommandDeps: []string{"${config.MacStripPath}"},
+ })
+ } else {
+ return nil
+ }
+ }()
// b/132822437: objcopy uses a file descriptor per .o file when called on .a files, which runs the system out of
// file descriptors on darwin. Limit concurrent calls to 5 on darwin.
@@ -174,11 +181,17 @@
}
}()
- darwinLipo = pctx.AndroidStaticRule("darwinLipo",
- blueprint.RuleParams{
- Command: "${config.MacLipoPath} -create -output $out $in",
- CommandDeps: []string{"${config.MacLipoPath}"},
- })
+ darwinLipo = func() blueprint.Rule {
+ if runtime.GOOS == "darwin" {
+ return pctx.AndroidStaticRule("darwinLipo",
+ blueprint.RuleParams{
+ Command: "${config.MacLipoPath} -create -output $out $in",
+ CommandDeps: []string{"${config.MacLipoPath}"},
+ })
+ } else {
+ return nil
+ }
+ }()
_ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
@@ -898,6 +911,16 @@
"ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
"crtEnd": strings.Join(crtEnd.Strings(), " "),
}
+
+ // On Windows, we always generate a PDB file
+ // --strip-debug is needed to also keep COFF symbols which are needed when
+ // we patch binaries with symbol_inject.
+ if ctx.Windows() {
+ pdb := outputFile.ReplaceExtension(ctx, "pdb")
+ args["ldFlags"] = args["ldFlags"] + " -Wl,--strip-debug -Wl,--pdb=" + pdb.String() + " "
+ implicitOutputs = append(slices.Clone(implicitOutputs), pdb)
+ }
+
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
rule = ldRE
args["implicitOutputs"] = strings.Join(implicitOutputs.Strings(), ",")
diff --git a/cc/cc.go b/cc/cc.go
index 3c17be6..1b7624d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -34,7 +34,6 @@
"android/soong/cc/config"
"android/soong/fuzz"
"android/soong/genrule"
- "android/soong/multitree"
)
func init() {
@@ -60,10 +59,10 @@
san.registerMutators(ctx)
}
- ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator).Parallel()
+ ctx.BottomUp("sanitize_runtime_deps", sanitizerRuntimeDepsMutator).Parallel()
ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel()
- ctx.TopDown("fuzz_deps", fuzzMutatorDeps)
+ ctx.BottomUp("fuzz_deps", fuzzMutatorDeps)
ctx.Transition("coverage", &coverageTransitionMutator{})
@@ -74,12 +73,12 @@
ctx.Transition("lto", <oTransitionMutator{})
ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel()
- ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
+ ctx.BottomUp("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
- ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.PostApexMutators(func(ctx android.RegisterMutatorsContext) {
// sabi mutator needs to be run after apex mutator finishes.
- ctx.TopDown("sabi_deps", sabiDepsMutator)
+ ctx.Transition("sabi", &sabiTransitionMutator{})
})
ctx.RegisterParallelSingletonType("kythe_extract_all", kytheExtractAllFactory)
@@ -138,7 +137,7 @@
// LLNDK headers for the ABI checker to check LLNDK implementation library.
// An LLNDK implementation is the core variant. LLNDK header libs are reexported by the vendor variant.
- // The core variant cannot depend on the vendor variant because of the order of CreateVariations.
+ // The core variant cannot depend on the vendor variant because of the order of imageTransitionMutator.Split().
// Instead, the LLNDK implementation depends on the LLNDK header libs.
LlndkHeaderLibs []string
}
@@ -613,7 +612,7 @@
coverageOutputFilePath() android.OptionalPath
// Get the deps that have been explicitly specified in the properties.
- linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps
+ linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps
moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
}
@@ -906,19 +905,17 @@
logtagsPaths android.Paths
WholeRustStaticlib bool
+
+ hasAidl bool
+ hasLex bool
+ hasProto bool
+ hasRenderscript bool
+ hasSysprop bool
+ hasWinMsg bool
+ hasYacc bool
}
func (c *Module) AddJSONData(d *map[string]interface{}) {
- var hasAidl, hasLex, hasProto, hasRenderscript, hasSysprop, hasWinMsg, hasYacc bool
- if b, ok := c.compiler.(*baseCompiler); ok {
- hasAidl = b.hasSrcExt(".aidl")
- hasLex = b.hasSrcExt(".l") || b.hasSrcExt(".ll")
- hasProto = b.hasSrcExt(".proto")
- hasRenderscript = b.hasSrcExt(".rscript") || b.hasSrcExt(".fs")
- hasSysprop = b.hasSrcExt(".sysprop")
- hasWinMsg = b.hasSrcExt(".mc")
- hasYacc = b.hasSrcExt(".y") || b.hasSrcExt(".yy")
- }
c.AndroidModuleBase().AddJSONData(d)
(*d)["Cc"] = map[string]interface{}{
"SdkVersion": c.SdkVersion(),
@@ -948,14 +945,14 @@
"IsVendorPublicLibrary": c.IsVendorPublicLibrary(),
"ApexSdkVersion": c.apexSdkVersion,
"TestFor": c.TestFor(),
- "AidlSrcs": hasAidl,
- "LexSrcs": hasLex,
- "ProtoSrcs": hasProto,
- "RenderscriptSrcs": hasRenderscript,
- "SyspropSrcs": hasSysprop,
- "WinMsgSrcs": hasWinMsg,
- "YaccSrsc": hasYacc,
- "OnlyCSrcs": !(hasAidl || hasLex || hasProto || hasRenderscript || hasSysprop || hasWinMsg || hasYacc),
+ "AidlSrcs": c.hasAidl,
+ "LexSrcs": c.hasLex,
+ "ProtoSrcs": c.hasProto,
+ "RenderscriptSrcs": c.hasRenderscript,
+ "SyspropSrcs": c.hasSysprop,
+ "WinMsgSrcs": c.hasWinMsg,
+ "YaccSrsc": c.hasYacc,
+ "OnlyCSrcs": !(c.hasAidl || c.hasLex || c.hasProto || c.hasRenderscript || c.hasSysprop || c.hasWinMsg || c.hasYacc),
"OptimizeForSize": c.OptimizeForSize(),
}
}
@@ -972,7 +969,7 @@
return c.Properties.HideFromMake
}
-func (c *Module) RequiredModuleNames(ctx android.ConfigAndErrorContext) []string {
+func (c *Module) RequiredModuleNames(ctx android.ConfigurableEvaluatorContext) []string {
required := android.CopyOf(c.ModuleBase.RequiredModuleNames(ctx))
if c.ImageVariation().Variation == android.CoreVariation {
required = append(required, c.Properties.Target.Platform.Required...)
@@ -1028,13 +1025,6 @@
return ""
}
-func (c *Module) NdkPrebuiltStl() bool {
- if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok {
- return true
- }
- return false
-}
-
func (c *Module) StubDecorator() bool {
if _, ok := c.linker.(*stubDecorator); ok {
return true
@@ -1088,16 +1078,6 @@
return false
}
-func (c *Module) IsNdkPrebuiltStl() bool {
- if c.linker == nil {
- return false
- }
- if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok {
- return true
- }
- return false
-}
-
func (c *Module) RlibStd() bool {
panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName()))
}
@@ -2103,6 +2083,16 @@
buildComplianceMetadataInfo(ctx, c, deps)
+ if b, ok := c.compiler.(*baseCompiler); ok {
+ c.hasAidl = b.hasSrcExt(ctx, ".aidl")
+ c.hasLex = b.hasSrcExt(ctx, ".l") || b.hasSrcExt(ctx, ".ll")
+ c.hasProto = b.hasSrcExt(ctx, ".proto")
+ c.hasRenderscript = b.hasSrcExt(ctx, ".rscript") || b.hasSrcExt(ctx, ".fs")
+ c.hasSysprop = b.hasSrcExt(ctx, ".sysprop")
+ c.hasWinMsg = b.hasSrcExt(ctx, ".mc")
+ c.hasYacc = b.hasSrcExt(ctx, ".y") || b.hasSrcExt(ctx, ".yy")
+ }
+
c.setOutputFiles(ctx)
}
@@ -2370,24 +2360,6 @@
}
}
-func GetApiImports(c LinkableInterface, actx android.BottomUpMutatorContext) multitree.ApiImportInfo {
- apiImportInfo := multitree.ApiImportInfo{}
-
- if c.Device() {
- var apiImportModule []blueprint.Module
- if actx.OtherModuleExists("api_imports") {
- apiImportModule = actx.AddDependency(c, nil, "api_imports")
- if len(apiImportModule) > 0 && apiImportModule[0] != nil {
- apiInfo, _ := android.OtherModuleProvider(actx, apiImportModule[0], multitree.ApiImportsProvider)
- apiImportInfo = apiInfo
- android.SetProvider(actx, multitree.ApiImportsProvider, apiInfo)
- }
- }
- }
-
- return apiImportInfo
-}
-
func GetReplaceModuleName(lib string, replaceMap map[string]string) string {
if snapshot, ok := replaceMap[lib]; ok {
return snapshot
@@ -2457,11 +2429,6 @@
// NDK Variant
return true
}
-
- if c.isImportedApiLibrary() {
- // API Library should depend on API headers
- return true
- }
}
return false
@@ -2481,19 +2448,10 @@
ctx.ctx = ctx
deps := c.deps(ctx)
- apiImportInfo := GetApiImports(c, actx)
apiNdkLibs := []string{}
apiLateNdkLibs := []string{}
- if c.shouldUseApiSurface() {
- deps.SharedLibs, apiNdkLibs = rewriteLibsForApiImports(c, deps.SharedLibs, apiImportInfo.SharedLibs, ctx.Config())
- deps.LateSharedLibs, apiLateNdkLibs = rewriteLibsForApiImports(c, deps.LateSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
- deps.SystemSharedLibs, _ = rewriteLibsForApiImports(c, deps.SystemSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
- deps.ReexportHeaderLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportHeaderLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
- deps.ReexportSharedLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportSharedLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
- }
-
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
variantNdkLibs := []string{}
@@ -2510,15 +2468,16 @@
depTag.reexportFlags = true
}
- // Check header lib replacement from API surface first, and then check again with VSDK
- if c.shouldUseApiSurface() {
- lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
- }
-
if c.isNDKStubLibrary() {
- // ndk_headers do not have any variations
- actx.AddFarVariationDependencies([]blueprint.Variation{}, depTag, lib)
- } else if c.IsStubs() && !c.isImportedApiLibrary() {
+ variationExists := actx.OtherModuleDependencyVariantExists(nil, lib)
+ if variationExists {
+ actx.AddVariationDependencies(nil, depTag, lib)
+ } else {
+ // dependencies to ndk_headers fall here as ndk_headers do not have
+ // any variants.
+ actx.AddFarVariationDependencies([]blueprint.Variation{}, depTag, lib)
+ }
+ } else if c.IsStubs() {
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
depTag, lib)
} else {
@@ -2594,22 +2553,12 @@
}
name, version := StubsLibNameAndVersion(lib)
- if apiLibraryName, ok := apiImportInfo.SharedLibs[name]; ok && !ctx.OtherModuleExists(name) {
- name = apiLibraryName
- }
sharedLibNames = append(sharedLibNames, name)
variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
}
-
- if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
- AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false)
- }
-
- if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
- AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, apiLibraryName, version, false)
- }
+ AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false)
}
for _, lib := range deps.LateStaticLibs {
@@ -2704,7 +2653,6 @@
)
}
- updateImportedLibraryDependency(ctx)
}
func BeginMutator(ctx android.BottomUpMutatorContext) {
@@ -2733,10 +2681,6 @@
return
}
- // TODO(b/244244438) : Remove this once all variants are implemented
- if ccFrom, ok := from.(*Module); ok && ccFrom.isImportedApiLibrary() {
- return
- }
if from.SdkVersion() == "" {
// Platform code can link to anything
return
@@ -2754,19 +2698,11 @@
return
}
if c, ok := to.(*Module); ok {
- if c.NdkPrebuiltStl() {
- // These are allowed, but they don't set sdk_version
- return
- }
if c.StubDecorator() {
// These aren't real libraries, but are the stub shared libraries that are included in
// the NDK.
return
}
- if c.isImportedApiLibrary() {
- // Imported library from the API surface is a stub library built against interface definition.
- return
- }
}
if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" {
@@ -2847,7 +2783,7 @@
// If a library has a vendor variant and is a (transitive) dependency of an LLNDK library,
// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
// or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
-func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
+func checkDoubleLoadableLibraries(ctx android.BottomUpMutatorContext) {
check := func(child, parent android.Module) bool {
to, ok := child.(*Module)
if !ok {
@@ -2942,47 +2878,6 @@
skipModuleList := map[string]bool{}
- var apiImportInfo multitree.ApiImportInfo
- hasApiImportInfo := false
-
- ctx.VisitDirectDeps(func(dep android.Module) {
- if dep.Name() == "api_imports" {
- apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
- hasApiImportInfo = true
- }
- })
-
- if hasApiImportInfo {
- targetStubModuleList := map[string]string{}
- targetOrigModuleList := map[string]string{}
-
- // Search for dependency which both original module and API imported library with APEX stub exists
- ctx.VisitDirectDeps(func(dep android.Module) {
- depName := ctx.OtherModuleName(dep)
- if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok {
- targetStubModuleList[apiLibrary] = depName
- }
- })
- ctx.VisitDirectDeps(func(dep android.Module) {
- depName := ctx.OtherModuleName(dep)
- if origLibrary, ok := targetStubModuleList[depName]; ok {
- targetOrigModuleList[origLibrary] = depName
- }
- })
-
- // Decide which library should be used between original and API imported library
- ctx.VisitDirectDeps(func(dep android.Module) {
- depName := ctx.OtherModuleName(dep)
- if apiLibrary, ok := targetOrigModuleList[depName]; ok {
- if ShouldUseStubForApex(ctx, dep) {
- skipModuleList[depName] = true
- } else {
- skipModuleList[apiLibrary] = true
- }
- }
- })
- }
-
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
@@ -3055,7 +2950,7 @@
}
if dep.Target().Os != ctx.Os() {
- ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
+ 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 {
@@ -3411,17 +3306,7 @@
// bootstrap modules, always link to non-stub variant
isNotInPlatform := dep.(android.ApexModule).NotInPlatform()
- isApexImportedApiLibrary := false
-
- if cc, ok := dep.(*Module); ok {
- if apiLibrary, ok := cc.linker.(*apiLibraryDecorator); ok {
- if apiLibrary.hasApexStubs() {
- isApexImportedApiLibrary = true
- }
- }
- }
-
- useStubs = (isNotInPlatform || isApexImportedApiLibrary) && !bootstrap
+ useStubs = isNotInPlatform && !bootstrap
if useStubs {
// Another exception: if this module is a test for an APEX, then
@@ -3446,7 +3331,7 @@
// only partially overlapping apex_available. For that test_for
// modules would need to be split into APEX variants and resolved
// separately for each APEX they have access to.
- if !isApexImportedApiLibrary && android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
+ if android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
useStubs = false
}
}
@@ -3927,7 +3812,6 @@
headerLibrary
testBin // testBinary already declared
ndkLibrary
- ndkPrebuiltStl
)
func (c *Module) typ() moduleType {
@@ -3966,8 +3850,6 @@
return sharedLibrary
} else if c.isNDKStubLibrary() {
return ndkLibrary
- } else if c.IsNdkPrebuiltStl() {
- return ndkPrebuiltStl
}
return unknownType
}
@@ -4033,11 +3915,6 @@
return c.Properties.IsSdkVariant
}
-func (c *Module) isImportedApiLibrary() bool {
- _, ok := c.linker.(*apiLibraryDecorator)
- return ok
-}
-
func kytheExtractAllFactory() android.Singleton {
return &kytheExtractAllSingleton{}
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index ccdaae5..3f3347b 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -49,17 +49,30 @@
func registerTestMutators(ctx android.RegistrationContext) {
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex", testApexMutator).Parallel()
+ ctx.Transition("apex", &testApexTransitionMutator{})
})
}
-func testApexMutator(mctx android.BottomUpMutatorContext) {
- modules := mctx.CreateVariations(apexVariationName)
+type testApexTransitionMutator struct{}
+
+func (t *testApexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{apexVariationName}
+}
+
+func (t *testApexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (t *testApexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ return incomingVariation
+}
+
+func (t *testApexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
MinSdkVersion: android.ApiLevelForTest(apexVersion),
}
- mctx.SetVariationProvider(modules[0], android.ApexInfoProvider, apexInfo)
+ android.SetProvider(ctx, android.ApexInfoProvider, apexInfo)
}
// testCcWithConfig runs tests using the prepareForCcTest
@@ -302,7 +315,7 @@
ctx := testCcWithConfig(t, config)
testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
testBinary := testingModule.Module().(*Module).linker.(*testBinary)
- outputFiles := testingModule.OutputFiles(t, "")
+ outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
return
@@ -355,7 +368,7 @@
testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
module := testingModule.Module()
testBinary := module.(*Module).linker.(*testBinary)
- outputFiles := testingModule.OutputFiles(t, "")
+ outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
@@ -851,7 +864,7 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- staticLibInfo, _ := android.SingletonModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
+ staticLibInfo, _ := android.OtherModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
@@ -887,7 +900,7 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- staticLibInfo, _ := android.SingletonModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
+ staticLibInfo, _ := android.OtherModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b"})
@@ -927,7 +940,7 @@
cc_prebuilt_library_shared {
name: "libllndkprebuilt",
- stubs: { versions: ["1", "2"] },
+ stubs: { versions: ["1", "2"] , symbol_file: "libllndkprebuilt.map.txt" },
llndk: {
symbol_file: "libllndkprebuilt.map.txt",
},
@@ -999,7 +1012,7 @@
checkExportedIncludeDirs := func(module, variant string, expectedSystemDirs []string, expectedDirs ...string) {
t.Helper()
m := result.ModuleForTests(module, variant).Module()
- f, _ := android.SingletonModuleProvider(result, m, FlagExporterInfoProvider)
+ f, _ := android.OtherModuleProvider(result, m, FlagExporterInfoProvider)
android.AssertPathsRelativeToTopEquals(t, "exported include dirs for "+module+"["+variant+"]",
expectedDirs, f.IncludeDirs)
android.AssertPathsRelativeToTopEquals(t, "exported include dirs for "+module+"["+variant+"]",
@@ -1027,7 +1040,7 @@
}
}
vendorModule := result.ModuleForTests(module, vendorVariant).Module()
- vendorInfo, _ := android.SingletonModuleProvider(result, vendorModule, FlagExporterInfoProvider)
+ 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",
android.JoinPathsWithPrefix(vendorDirs, "-I"), abiCheckFlags)
@@ -1404,7 +1417,7 @@
testingModule := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon")
module := testingModule.Module()
testBinary := module.(*Module).linker.(*testBinary)
- outputFiles := testingModule.OutputFiles(t, "")
+ outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
}
@@ -2452,7 +2465,7 @@
checkIncludeDirs := func(t *testing.T, ctx *android.TestContext, module android.Module, checkers ...exportedChecker) {
t.Helper()
- exported, _ := android.SingletonModuleProvider(ctx, module, FlagExporterInfoProvider)
+ exported, _ := android.OtherModuleProvider(ctx, module, FlagExporterInfoProvider)
name := module.Name()
for _, checker := range checkers {
@@ -2760,7 +2773,7 @@
"external/foo/libarm",
"external/foo/lib32",
"external/foo/libandroid_arm",
- "defaults/cc/common/ndk_libc++_shared",
+ "defaults/cc/common/ndk_libc++_shared_include_dirs",
}
conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"}
@@ -3111,7 +3124,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")
- outputFile := testingModule.OutputFiles(t, "stripped_all")
+ 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])
return
@@ -3194,12 +3207,7 @@
ctx = android.GroupFixturePreparers(
prepareForCcTest,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- if variables.BuildFlags == nil {
- variables.BuildFlags = make(map[string]string)
- }
- variables.BuildFlags["RELEASE_BOARD_API_LEVEL_FROZEN"] = "true"
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_BOARD_API_LEVEL_FROZEN", "true"),
).RunTestWithBp(t, bp)
testSdkVersionFlag("libfoo", "30")
testSdkVersionFlag("libbar", "29")
diff --git a/cc/check.go b/cc/check.go
index e3af3b2..8e2844f 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -40,6 +40,10 @@
ctx.PropertyErrorf(prop, "Bad flag: `%s`, use native_coverage instead", flag)
} else if flag == "-fwhole-program-vtables" {
ctx.PropertyErrorf(prop, "Bad flag: `%s`, use whole_program_vtables instead", flag)
+ } else if flag == "-gsplit-dwarf" {
+ ctx.PropertyErrorf(prop, "Bad flag: `%s`, soong cannot track dependencies to split dwarf debuginfo", flag)
+ } else if flag == "-fno-integrated-as" {
+ ctx.PropertyErrorf("Bad flag: `%s` is disallowed as it may invoke the `as` from the build host", flag)
} else if flag == "-Weverything" {
if !ctx.Config().IsEnvTrue("ANDROID_TEMPORARILY_ALLOW_WEVERYTHING") {
ctx.PropertyErrorf(prop, "-Weverything is not allowed in Android.bp files. "+
diff --git a/cc/cmake_module_cc.txt b/cc/cmake_module_cc.txt
index 0dc45ae..0f6e62f 100644
--- a/cc/cmake_module_cc.txt
+++ b/cc/cmake_module_cc.txt
@@ -2,10 +2,10 @@
<<$includeDirs := getIncludeDirs .Ctx .M>>
<<$cflags := getCflagsProperty .Ctx .M>>
<<$deps := mapLibraries .Ctx .M (concat5
-(getLinkerProperties .M).Whole_static_libs
-(getLinkerProperties .M).Static_libs
-(getLinkerProperties .M).Shared_libs
-(getLinkerProperties .M).Header_libs
+(getWholeStaticLibsProperty .Ctx .M)
+(getStaticLibsProperty .Ctx .M)
+(getSharedLibsProperty .Ctx .M)
+(getHeaderLibsProperty .Ctx .M)
(getExtraLibs .M)
) .Pprop.LibraryMapping>>
<<$moduleType := getModuleType .M>>
diff --git a/cc/cmake_snapshot.go b/cc/cmake_snapshot.go
index 8f3ad96..61fa46d 100644
--- a/cc/cmake_snapshot.go
+++ b/cc/cmake_snapshot.go
@@ -204,12 +204,28 @@
return m.compiler.baseCompilerProps()
},
"getCflagsProperty": func(ctx android.ModuleContext, m *Module) []string {
- cflags := m.compiler.baseCompilerProps().Cflags
- return cflags.GetOrDefault(ctx, nil)
+ prop := m.compiler.baseCompilerProps().Cflags
+ return prop.GetOrDefault(ctx, nil)
},
"getLinkerProperties": func(m *Module) BaseLinkerProperties {
return m.linker.baseLinkerProps()
},
+ "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, m *Module) []string {
+ prop := m.linker.baseLinkerProps().Static_libs
+ return prop.GetOrDefault(ctx, nil)
+ },
+ "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)
+ },
"getExtraLibs": getExtraLibs,
"getIncludeDirs": getIncludeDirs,
"mapLibraries": func(ctx android.ModuleContext, m *Module, libs []string, mapping map[string]LibraryMappingProperty) []string {
@@ -476,7 +492,8 @@
var prebuiltsList android.Paths
ctx.VisitDirectDepsWithTag(cmakeSnapshotPrebuiltTag, func(dep android.Module) {
- for _, file := range dep.FilesToInstall() {
+ for _, file := range android.OtherModuleProviderOrDefault(
+ ctx, dep, android.InstallFilesProvider).InstallFiles {
prebuiltsList = append(prebuiltsList, file)
}
})
diff --git a/cc/compdb.go b/cc/compdb.go
index da28183..b33f490 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -85,23 +85,24 @@
if err != nil {
log.Fatalf("Could not create file %s: %s", compDBFile, err)
}
- defer f.Close()
+ defer func() {
+ if err := f.Close(); err != nil {
+ log.Fatalf("Could not close file %s: %s", compDBFile, err)
+ }
+ }()
v := make([]compDbEntry, 0, len(m))
-
for _, value := range m {
v = append(v, value)
}
- var dat []byte
+
+ w := json.NewEncoder(f)
if outputCompdbDebugInfo {
- dat, err = json.MarshalIndent(v, "", " ")
- } else {
- dat, err = json.Marshal(v)
+ w.SetIndent("", " ")
}
- if err != nil {
- log.Fatalf("Failed to marshal: %s", err)
+ if err := w.Encode(v); err != nil {
+ log.Fatalf("Failed to encode: %s", err)
}
- f.Write(dat)
if finalLinkDir := ctx.Config().Getenv(envVariableCompdbLink); finalLinkDir != "" {
finalLinkPath := filepath.Join(finalLinkDir, compdbFilename)
diff --git a/cc/compiler.go b/cc/compiler.go
index 03f9899..022b712 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -37,7 +37,7 @@
// list of source files used to compile the C/C++ module. May be .c, .cpp, or .S files.
// srcs may reference the outputs of other modules that produce source files like genrule
// or filegroup using the syntax ":module".
- Srcs []string `android:"path,arch_variant"`
+ Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
// list of source files that should not be compiled with clang-tidy.
Tidy_disabled_srcs []string `android:"path,arch_variant"`
@@ -47,13 +47,13 @@
// list of source files that should not be used to build the C/C++ module.
// This is most useful in the arch/multilib variants to remove non-common files
- Exclude_srcs []string `android:"path,arch_variant"`
+ Exclude_srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
// list of module-specific flags that will be used for C and C++ compiles.
Cflags proptools.Configurable[[]string] `android:"arch_variant"`
// list of module-specific flags that will be used for C++ compiles
- Cppflags []string `android:"arch_variant"`
+ Cppflags proptools.Configurable[[]string] `android:"arch_variant"`
// list of module-specific flags that will be used for C compiles
Conlyflags []string `android:"arch_variant"`
@@ -228,9 +228,6 @@
Static *bool `android:"arch_variant"`
} `android:"arch_variant"`
- // Stores the original list of source files before being cleared by library reuse
- OriginalSrcs []string `blueprint:"mutated"`
-
// Build and link with OpenMP
Openmp *bool `android:"arch_variant"`
}
@@ -300,7 +297,7 @@
deps.AidlLibs = append(deps.AidlLibs, compiler.Properties.Aidl.Libs...)
android.ProtoDeps(ctx, &compiler.Proto)
- if compiler.hasSrcExt(".proto") {
+ if compiler.hasSrcExt(ctx, ".proto") {
deps = protoDeps(ctx, deps, &compiler.Proto, Bool(compiler.Properties.Proto.Static))
}
@@ -363,12 +360,25 @@
tc := ctx.toolchain()
modulePath := ctx.ModuleDir()
- compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
- compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...)
+ reuseObjs := false
+ if len(ctx.GetDirectDepsWithTag(reuseObjTag)) > 0 {
+ reuseObjs = true
+ }
+
+ // If a reuseObjTag dependency exists then this module is reusing the objects (generally the shared variant
+ // reusing objects from the static variant), and doesn't need to compile any sources of its own.
+ var srcs []string
+ if !reuseObjs {
+ srcs = compiler.Properties.Srcs.GetOrDefault(ctx, nil)
+ exclude_srcs := compiler.Properties.Exclude_srcs.GetOrDefault(ctx, nil)
+ compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs)
+ compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...)
+ }
cflags := compiler.Properties.Cflags.GetOrDefault(ctx, nil)
+ cppflags := compiler.Properties.Cppflags.GetOrDefault(ctx, nil)
CheckBadCompilerFlags(ctx, "cflags", cflags)
- CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags)
+ CheckBadCompilerFlags(ctx, "cppflags", cppflags)
CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags)
@@ -381,7 +391,7 @@
esc := proptools.NinjaAndShellEscapeList
flags.Local.CFlags = append(flags.Local.CFlags, esc(cflags)...)
- flags.Local.CppFlags = append(flags.Local.CppFlags, esc(compiler.Properties.Cppflags)...)
+ flags.Local.CppFlags = append(flags.Local.CppFlags, esc(cppflags)...)
flags.Local.ConlyFlags = append(flags.Local.ConlyFlags, esc(compiler.Properties.Conlyflags)...)
flags.Local.AsFlags = append(flags.Local.AsFlags, esc(compiler.Properties.Asflags)...)
flags.Local.YasmFlags = append(flags.Local.YasmFlags, esc(compiler.Properties.Asflags)...)
@@ -434,18 +444,20 @@
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VNDK__")
if ctx.inVendor() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VENDOR__")
-
- vendorApiLevel := ctx.Config().VendorApiLevel()
- if vendorApiLevel == "" {
- // TODO(b/314036847): This is a fallback for UDC targets.
- // This must be a build failure when UDC is no longer built
- // from this source tree.
- vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
- }
- flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VENDOR_API__="+vendorApiLevel)
} else if ctx.inProduct() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_PRODUCT__")
}
+
+ // Define __ANDROID_VENDOR_API__ for both product and vendor variants
+ // because they both use the same LLNDK libraries.
+ vendorApiLevel := ctx.Config().VendorApiLevel()
+ if vendorApiLevel == "" {
+ // TODO(b/314036847): This is a fallback for UDC targets.
+ // This must be a build failure when UDC is no longer built
+ // from this source tree.
+ vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
+ }
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VENDOR_API__="+vendorApiLevel)
}
if ctx.inRecovery() {
@@ -602,11 +614,11 @@
flags.Global.CFlags = append(flags.Global.CFlags, "-DANDROID_STRICT")
}
- if compiler.hasSrcExt(".proto") {
+ if compiler.hasSrcExt(ctx, ".proto") {
flags = protoFlags(ctx, flags, &compiler.Proto)
}
- if compiler.hasSrcExt(".y") || compiler.hasSrcExt(".yy") {
+ if compiler.hasSrcExt(ctx, ".y") || compiler.hasSrcExt(ctx, ".yy") {
flags.Local.CommonFlags = append(flags.Local.CommonFlags,
"-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String())
}
@@ -616,7 +628,7 @@
ctx.ModuleErrorf("aidl.libs and (aidl.include_dirs or aidl.local_include_dirs) can't be set at the same time. For aidl headers, please only use aidl.libs prop")
}
- if compiler.hasAidl(deps) {
+ if compiler.hasAidl(ctx, deps) {
flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
@@ -645,7 +657,7 @@
}
flags.aidlFlags = append(flags.aidlFlags, "--min_sdk_version="+aidlMinSdkVersion)
- if compiler.hasSrcExt(".aidl") {
+ if compiler.hasSrcExt(ctx, ".aidl") {
flags.Local.CommonFlags = append(flags.Local.CommonFlags,
"-I"+android.PathForModuleGen(ctx, "aidl").String())
}
@@ -655,16 +667,16 @@
}
}
- if compiler.hasSrcExt(".rscript") || compiler.hasSrcExt(".fs") {
+ if compiler.hasSrcExt(ctx, ".rscript") || compiler.hasSrcExt(ctx, ".fs") {
flags = rsFlags(ctx, flags, &compiler.Properties)
}
- if compiler.hasSrcExt(".sysprop") {
+ if compiler.hasSrcExt(ctx, ".sysprop") {
flags.Local.CommonFlags = append(flags.Local.CommonFlags,
"-I"+android.PathForModuleGen(ctx, "sysprop", "include").String())
}
- if len(compiler.Properties.Srcs) > 0 {
+ if len(srcs) > 0 {
module := ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
if inList("-Wno-error", flags.Local.CFlags) || inList("-Wno-error", flags.Local.CppFlags) {
addToModuleList(ctx, modulesUsingWnoErrorKey, module)
@@ -705,18 +717,13 @@
return flags
}
-func (compiler *baseCompiler) hasSrcExt(ext string) bool {
+func (compiler *baseCompiler) hasSrcExt(ctx BaseModuleContext, ext string) bool {
for _, src := range compiler.srcsBeforeGen {
if src.Ext() == ext {
return true
}
}
- for _, src := range compiler.Properties.Srcs {
- if filepath.Ext(src) == ext {
- return true
- }
- }
- for _, src := range compiler.Properties.OriginalSrcs {
+ for _, src := range compiler.Properties.Srcs.GetOrDefault(ctx, nil) {
if filepath.Ext(src) == ext {
return true
}
@@ -744,8 +751,8 @@
return nil
}
-func (compiler *baseCompiler) hasAidl(deps PathDeps) bool {
- return len(deps.AidlLibraryInfos) > 0 || compiler.hasSrcExt(".aidl")
+func (compiler *baseCompiler) hasAidl(ctx BaseModuleContext, deps PathDeps) bool {
+ return len(deps.AidlLibraryInfos) > 0 || compiler.hasSrcExt(ctx, ".aidl")
}
func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
@@ -795,20 +802,20 @@
Local_include_dirs []string `android:"arch_variant,variant_prepend"`
// list of static libraries that provide headers for this binding.
- Static_libs []string `android:"arch_variant,variant_prepend"`
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of shared libraries that provide headers for this binding.
- Shared_libs []string `android:"arch_variant"`
+ Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
// List of libraries which export include paths required for this module
- Header_libs []string `android:"arch_variant,variant_prepend"`
+ Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of clang flags required to correctly interpret the headers.
Cflags proptools.Configurable[[]string] `android:"arch_variant"`
// list of c++ specific clang flags required to correctly interpret the headers.
// This is provided primarily to make sure cppflags defined in cc_defaults are pulled in.
- Cppflags []string `android:"arch_variant"`
+ Cppflags proptools.Configurable[[]string] `android:"arch_variant"`
// C standard version to use. Can be a specific version (such as "gnu11"),
// "experimental" (which will use draft versions like C1x when available),
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 289409f..f514db6 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -35,4 +35,8 @@
testSrcs: [
"tidy_test.go",
],
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//prebuilts/clang/host/linux-x86/soong",
+ ],
}
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index beb68e1..0dcf2cf 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -41,11 +41,18 @@
"armv8-2a-dotprod": []string{
"-march=armv8.2-a+dotprod",
},
+ // On ARMv9 and later, Pointer Authentication Codes (PAC) are mandatory,
+ // so -fstack-protector is unnecessary.
"armv9-a": []string{
"-march=armv8.2-a+dotprod",
"-mbranch-protection=standard",
"-fno-stack-protector",
},
+ "armv9-2a": []string{
+ "-march=armv9.2-a",
+ "-mbranch-protection=standard",
+ "-fno-stack-protector",
+ },
}
arm64Ldflags = []string{
@@ -111,11 +118,9 @@
pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
- pctx.StaticVariable("Arm64Armv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
- pctx.StaticVariable("Arm64Armv8ABranchProtCflags", strings.Join(arm64ArchVariantCflags["armv8-a-branchprot"], " "))
- pctx.StaticVariable("Arm64Armv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
- pctx.StaticVariable("Arm64Armv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " "))
- pctx.StaticVariable("Arm64Armv9ACflags", strings.Join(arm64ArchVariantCflags["armv9-a"], " "))
+ for variant, cflags := range arm64ArchVariantCflags {
+ pctx.StaticVariable("Arm64"+variant+"VariantCflags", strings.Join(cflags, " "))
+ }
pctx.StaticVariable("Arm64CortexA53Cflags", strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
pctx.StaticVariable("Arm64CortexA55Cflags", strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
@@ -127,14 +132,6 @@
}
var (
- arm64ArchVariantCflagsVar = map[string]string{
- "armv8-a": "${config.Arm64Armv8ACflags}",
- "armv8-a-branchprot": "${config.Arm64Armv8ABranchProtCflags}",
- "armv8-2a": "${config.Arm64Armv82ACflags}",
- "armv8-2a-dotprod": "${config.Arm64Armv82ADotprodCflags}",
- "armv9-a": "${config.Arm64Armv9ACflags}",
- }
-
arm64CpuVariantCflagsVar = map[string]string{
"cortex-a53": "${config.Arm64CortexA53Cflags}",
"cortex-a55": "${config.Arm64CortexA55Cflags}",
@@ -204,18 +201,12 @@
}
func arm64ToolchainFactory(arch android.Arch) Toolchain {
- switch arch.ArchVariant {
- case "armv8-a":
- case "armv8-a-branchprot":
- case "armv8-2a":
- case "armv8-2a-dotprod":
- case "armv9-a":
- // Nothing extra for armv8-a/armv8-2a
- default:
- panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant))
+ // Error now rather than having a confusing Ninja error
+ if _, ok := arm64ArchVariantCflags[arch.ArchVariant]; !ok {
+ panic(fmt.Sprintf("Unknown ARM64 architecture version: %q", arch.ArchVariant))
}
- toolchainCflags := []string{arm64ArchVariantCflagsVar[arch.ArchVariant]}
+ toolchainCflags := []string{"${config.Arm64" + arch.ArchVariant + "VariantCflags}"}
toolchainCflags = append(toolchainCflags,
variantOrDefault(arm64CpuVariantCflagsVar, arch.CpuVariant))
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 438e0e6..a19b0ed 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -87,8 +87,8 @@
}
func linuxBionicArm64ToolchainFactory(arch android.Arch) Toolchain {
- archVariant := "armv8-a" // for host, default to armv8-a
- toolchainCflags := []string{arm64ArchVariantCflagsVar[archVariant]}
+ // for host, default to armv8-a
+ toolchainCflags := []string{"-march=armv8-a"}
// We don't specify CPU architecture for host. Conservatively assume
// the host CPU needs the fix
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 4856669..1783f49 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -18,6 +18,7 @@
"fmt"
"os/exec"
"path/filepath"
+ "runtime"
"strings"
"sync"
@@ -28,6 +29,7 @@
darwinCflags = []string{
"-fPIC",
"-funwind-tables",
+ "-fno-omit-frame-pointer",
"-isysroot ${macSdkRoot}",
"-mmacosx-version-min=${macMinVersion}",
@@ -73,31 +75,33 @@
)
func init() {
- pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
- return getMacTools(ctx).sdkRoot
- })
- pctx.StaticVariable("macMinVersion", "10.14")
- pctx.VariableFunc("MacArPath", func(ctx android.PackageVarContext) string {
- return getMacTools(ctx).arPath
- })
+ if runtime.GOOS == "darwin" {
+ pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
+ return getMacTools(ctx).sdkRoot
+ })
+ pctx.StaticVariable("macMinVersion", "10.14")
+ pctx.VariableFunc("MacArPath", func(ctx android.PackageVarContext) string {
+ return getMacTools(ctx).arPath
+ })
- pctx.VariableFunc("MacLipoPath", func(ctx android.PackageVarContext) string {
- return getMacTools(ctx).lipoPath
- })
+ pctx.VariableFunc("MacLipoPath", func(ctx android.PackageVarContext) string {
+ return getMacTools(ctx).lipoPath
+ })
- pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string {
- return getMacTools(ctx).stripPath
- })
+ pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string {
+ return getMacTools(ctx).stripPath
+ })
- pctx.VariableFunc("MacToolPath", func(ctx android.PackageVarContext) string {
- return getMacTools(ctx).toolPath
- })
+ pctx.VariableFunc("MacToolPath", func(ctx android.PackageVarContext) string {
+ return getMacTools(ctx).toolPath
+ })
- pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
- pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
- pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " "))
+ pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
+ pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
+ pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " "))
- pctx.StaticVariable("DarwinYasmFlags", "-f macho -m amd64")
+ pctx.StaticVariable("DarwinYasmFlags", "-f macho -m amd64")
+ }
}
func MacStripPath(ctx android.PathContext) string {
diff --git a/cc/config/global.go b/cc/config/global.go
index bf2502f..9d3de6d 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -136,11 +136,6 @@
// displaying logs in web browsers.
"-fmessage-length=0",
- // Disable C++17 "relaxed template template argument matching" as a workaround for
- // our out-dated libcxx.
- // http://b/341084395
- "-fno-relaxed-template-template-args",
-
// Using simple template names reduces the size of debug builds.
"-gsimple-template-names",
@@ -149,9 +144,6 @@
// Make paths in deps files relative.
"-no-canonical-prefixes",
-
- // http://b/315250603 temporarily disabled
- "-Wno-error=format",
}
commonGlobalConlyflags = []string{}
@@ -181,9 +173,6 @@
"-Werror=sequence-point",
"-Werror=format-security",
"-nostdlibinc",
-
- // Emit additional debug info for AutoFDO
- "-fdebug-info-for-profiling",
}
commonGlobalLldflags = []string{
@@ -286,7 +275,7 @@
"-Wno-zero-as-null-pointer-constant", // http://b/68236239
"-Wno-deprecated-anon-enum-enum-conversion", // http://b/153746485
"-Wno-deprecated-enum-enum-conversion",
- "-Wno-pessimizing-move", // http://b/154270751
+ "-Wno-error=pessimizing-move", // http://b/154270751
// New warnings to be fixed after clang-r399163
"-Wno-non-c-typedef-for-linkage", // http://b/161304145
// New warnings to be fixed after clang-r428724
@@ -297,20 +286,14 @@
// 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-r475365
- "-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
- "-Wno-error=enum-constexpr-conversion", // http://b/243964282
+ "-Wno-error=enum-constexpr-conversion", // http://b/243964282
// New warnings to be fixed after clang-r522817
"-Wno-error=invalid-offsetof",
"-Wno-error=thread-safety-reference-return",
- // Irrelevant on Android because _we_ don't use exceptions, but causes
- // lots of build noise because libcxx/libcxxabi do. This can probably
- // go away when we're on a new enough libc++, but has to be global
- // until then because it causes warnings in the _callers_, not the
- // project itself.
- "-Wno-deprecated-dynamic-exception-spec",
-
// Allow using VLA CXX extension.
"-Wno-vla-cxx-extension",
}
@@ -350,6 +333,9 @@
"-Wno-unused",
"-Wno-deprecated",
+
+ // http://b/315250603 temporarily disabled
+ "-Wno-error=format",
}
// Similar to noOverrideGlobalCflags, but applies only to third-party code
@@ -376,6 +362,7 @@
"-Wno-unqualified-std-cast-call",
"-Wno-array-parameter",
"-Wno-gnu-offsetof-extensions",
+ "-Wno-pessimizing-move",
// TODO: Enable this warning http://b/315245071
"-Wno-fortify-source",
}
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 5aa2a7e..e7ac038 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -40,6 +40,9 @@
"-march=x86-64",
},
+ "alderlake": []string{
+ "-march=alderlake",
+ },
"broadwell": []string{
"-march=broadwell",
},
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 4b0041c..a92881d 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -42,6 +42,9 @@
"x86_64": []string{
"-march=prescott",
},
+ "alderlake": []string{
+ "-march=alderlake",
+ },
"atom": []string{
"-march=atom",
},
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 515cb21..ddc86c2 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -25,6 +25,8 @@
"-fPIC",
+ "-fno-omit-frame-pointer",
+
"-U_FORTIFY_SOURCE",
"-D_FORTIFY_SOURCE=2",
"-fstack-protector-strong",
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 7f22377..287967c 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -26,6 +26,8 @@
"-fPIC",
+ "-fno-omit-frame-pointer",
+
"-U_FORTIFY_SOURCE",
"-D_FORTIFY_SOURCE=2",
"-fstack-protector",
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 1e61b01..a4d43b9 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -43,6 +43,12 @@
"-mno-ms-bitfields",
"--sysroot ${WindowsGccRoot}/${WindowsGccTriple}",
+
+ // Windows flags to generate PDB
+ "-g",
+ "-gcodeview",
+
+ "-fno-omit-frame-pointer",
}
windowsIncludeFlags = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 92f2c5e..3f21bc6 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -57,7 +57,7 @@
return []interface{}{&fuzzer.Properties}
}
-func fuzzMutatorDeps(mctx android.TopDownMutatorContext) {
+func fuzzMutatorDeps(mctx android.BottomUpMutatorContext) {
currentModule, ok := mctx.Module().(*Module)
if !ok {
return
@@ -373,7 +373,7 @@
}
if targetFramework == fuzz.AFL {
- fuzzBin.baseCompiler.Properties.Srcs = append(fuzzBin.baseCompiler.Properties.Srcs, ":aflpp_driver", ":afl-compiler-rt")
+ fuzzBin.baseCompiler.Properties.Srcs.AppendSimpleValue([]string{":aflpp_driver", ":afl-compiler-rt"})
module.fuzzer.Properties.FuzzFramework = fuzz.AFL
}
})
diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go
index b1084e4..709586b 100644
--- a/cc/generated_cc_library.go
+++ b/cc/generated_cc_library.go
@@ -18,7 +18,7 @@
"android/soong/android"
)
-func GeneratedCcLibraryModuleFactory(moduleName string, callbacks Generator) android.Module {
+func GeneratedCcLibraryModuleFactory(callbacks Generator) android.Module {
module, _ := NewLibrary(android.HostAndDeviceSupported)
// Can be used as both a static and a shared library.
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index b3d5116..9a8049b 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -236,7 +236,7 @@
}
`
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
- gen_32bit := result.ModuleForTests("gen", "android_arm_armv7-a-neon").OutputFiles(t, "")
+ gen_32bit := result.ModuleForTests("gen", "android_arm_armv7-a-neon").OutputFiles(result.TestContext, t, "")
android.AssertPathsEndWith(t,
"genrule_out",
[]string{
@@ -245,7 +245,7 @@
gen_32bit,
)
- gen_64bit := result.ModuleForTests("gen", "android_arm64_armv8-a").OutputFiles(t, "")
+ gen_64bit := result.ModuleForTests("gen", "android_arm64_armv8-a").OutputFiles(result.TestContext, t, "")
android.AssertPathsEndWith(t,
"genrule_out",
[]string{
diff --git a/cc/image.go b/cc/image.go
index 2e52ccc..7594a08 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -465,11 +465,8 @@
func squashVendorSrcs(m *Module) {
if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
- lib.baseCompiler.Properties.Target.Vendor.Srcs...)
-
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
- lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
+ lib.baseCompiler.Properties.Srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Vendor.Srcs)
+ lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs)
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
@@ -482,11 +479,8 @@
func squashProductSrcs(m *Module) {
if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
- lib.baseCompiler.Properties.Target.Product.Srcs...)
-
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
- lib.baseCompiler.Properties.Target.Product.Exclude_srcs...)
+ lib.baseCompiler.Properties.Srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Product.Srcs)
+ lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Product.Exclude_srcs)
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
@@ -499,11 +493,8 @@
func squashRecoverySrcs(m *Module) {
if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
- lib.baseCompiler.Properties.Target.Recovery.Srcs...)
-
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
- lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
+ lib.baseCompiler.Properties.Srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Recovery.Srcs)
+ lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs)
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
@@ -512,13 +503,13 @@
func squashVendorRamdiskSrcs(m *Module) {
if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...)
+ lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs)
}
}
func squashRamdiskSrcs(m *Module) {
if lib, ok := m.compiler.(*libraryDecorator); ok {
- lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs...)
+ lib.baseCompiler.Properties.Exclude_srcs.AppendSimpleValue(lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs)
}
}
diff --git a/cc/libbuildversion/Android.bp b/cc/libbuildversion/Android.bp
index b105a30..c1f2c10 100644
--- a/cc/libbuildversion/Android.bp
+++ b/cc/libbuildversion/Android.bp
@@ -20,4 +20,5 @@
"//apex_available:anyapex",
],
vendor_available: true,
+ visibility: ["//visibility:public"],
}
diff --git a/cc/library.go b/cc/library.go
index 092b177..988a7fa 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -142,7 +142,7 @@
// Use `StaticProperties` or `SharedProperties`, depending on which variant is needed.
// `StaticOrSharedProperties` exists only to avoid duplication.
type StaticOrSharedProperties struct {
- Srcs []string `android:"path,arch_variant"`
+ Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
Tidy_disabled_srcs []string `android:"path,arch_variant"`
@@ -152,11 +152,11 @@
Cflags proptools.Configurable[[]string] `android:"arch_variant"`
- Enabled *bool `android:"arch_variant"`
- Whole_static_libs []string `android:"arch_variant"`
- Static_libs []string `android:"arch_variant"`
- Shared_libs []string `android:"arch_variant"`
- System_shared_libs []string `android:"arch_variant"`
+ Enabled *bool `android:"arch_variant"`
+ Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant"`
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
+ Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
+ System_shared_libs []string `android:"arch_variant"`
Export_shared_lib_headers []string `android:"arch_variant"`
Export_static_lib_headers []string `android:"arch_variant"`
@@ -548,8 +548,7 @@
return flags
}
-func (library *libraryDecorator) getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties {
- m := ctx.Module().(*Module)
+func (library *libraryDecorator) getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties {
variantProps := &library.Properties.Target.Platform.Header_abi_checker
if m.InVendor() {
variantProps = &library.Properties.Target.Vendor.Header_abi_checker
@@ -559,7 +558,7 @@
props := library.Properties.Header_abi_checker
err := proptools.AppendProperties(&props, variantProps, nil)
if err != nil {
- ctx.ModuleErrorf("Cannot merge headerAbiCheckerProperties: %s", err.Error())
+ panic(fmt.Errorf("Cannot merge headerAbiCheckerProperties: %s", err.Error()))
}
return props
}
@@ -594,53 +593,20 @@
return objs
}
if library.buildStubs() {
- symbolFile := String(library.Properties.Stubs.Symbol_file)
- if symbolFile != "" && !strings.HasSuffix(symbolFile, ".map.txt") {
- ctx.PropertyErrorf("symbol_file", "%q doesn't have .map.txt suffix", symbolFile)
- return Objects{}
- }
- 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.Module().(android.ApexModule).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 !ctx.Module().(*Module).IsNdk(ctx.Config()) {
- flag = flag + " --no-ndk"
- }
- nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
- android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
- objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
- library.versionScriptPath = android.OptionalPathForPath(
- 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)
- }
-
- return objs
+ return library.compileModuleLibApiStubs(ctx, flags, deps)
}
+ srcs := library.baseCompiler.Properties.Srcs.GetOrDefault(ctx, nil)
+ staticSrcs := library.StaticProperties.Static.Srcs.GetOrDefault(ctx, nil)
+ sharedSrcs := library.SharedProperties.Shared.Srcs.GetOrDefault(ctx, nil)
if !library.buildShared() && !library.buildStatic() {
- if len(library.baseCompiler.Properties.Srcs) > 0 {
+ if len(srcs) > 0 {
ctx.PropertyErrorf("srcs", "cc_library_headers must not have any srcs")
}
- if len(library.StaticProperties.Static.Srcs) > 0 {
+ if len(staticSrcs) > 0 {
ctx.PropertyErrorf("static.srcs", "cc_library_headers must not have any srcs")
}
- if len(library.SharedProperties.Shared.Srcs) > 0 {
+ if len(sharedSrcs) > 0 {
ctx.PropertyErrorf("shared.srcs", "cc_library_headers must not have any srcs")
}
return Objects{}
@@ -651,8 +617,8 @@
for _, dir := range dirs {
flags.SAbiFlags = append(flags.SAbiFlags, "-I"+dir)
}
- totalLength := len(library.baseCompiler.Properties.Srcs) + len(deps.GeneratedSources) +
- len(library.SharedProperties.Shared.Srcs) + len(library.StaticProperties.Static.Srcs)
+ totalLength := len(srcs) + len(deps.GeneratedSources) +
+ len(sharedSrcs) + len(staticSrcs)
if totalLength > 0 {
flags.SAbiDump = true
}
@@ -662,13 +628,13 @@
buildFlags := flagsToBuilderFlags(flags)
if library.static() {
- srcs := android.PathsForModuleSrc(ctx, library.StaticProperties.Static.Srcs)
+ srcs := android.PathsForModuleSrc(ctx, staticSrcs)
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))
} else if library.shared() {
- srcs := android.PathsForModuleSrc(ctx, library.SharedProperties.Shared.Srcs)
+ 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),
@@ -678,6 +644,61 @@
return objs
}
+// 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 {
+ // TODO (b/275273834): Make this a hard error when the symbol files have been added to module sdk.
+ 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.Module().(android.ApexModule).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 !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,
+ android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
+ objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
+
+ library.versionScriptPath = android.OptionalPathForPath(
+ 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)
+ }
+
+ return objs
+}
+
type libraryInterface interface {
versionedInterface
@@ -696,7 +717,7 @@
setShared()
// Gets the ABI properties for vendor, product, or platform variant
- getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties
+ getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties
// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
@@ -834,9 +855,9 @@
if library.static() {
deps.WholeStaticLibs = append(deps.WholeStaticLibs,
- library.StaticProperties.Static.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs...)
+ library.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)...)
+ deps.StaticLibs = append(deps.StaticLibs, library.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)...)
+ deps.SharedLibs = append(deps.SharedLibs, library.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)...)
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.StaticProperties.Static.Export_shared_lib_headers...)
deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...)
@@ -849,9 +870,9 @@
if library.baseLinker.Properties.crtPadSegment() {
deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtPadSegmentSharedLibrary()...)
}
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...)
- deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs...)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)...)
+ deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)...)
+ deps.SharedLibs = append(deps.SharedLibs, library.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)...)
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.SharedProperties.Shared.Export_shared_lib_headers...)
deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.SharedProperties.Shared.Export_static_lib_headers...)
@@ -897,8 +918,8 @@
return deps
}
-func (library *libraryDecorator) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
- specifiedDeps = library.baseLinker.linkerSpecifiedDeps(specifiedDeps)
+func (library *libraryDecorator) linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
+ specifiedDeps = library.baseLinker.linkerSpecifiedDeps(ctx, module, specifiedDeps)
var properties StaticOrSharedProperties
if library.static() {
properties = library.StaticProperties.Static
@@ -906,7 +927,8 @@
properties = library.SharedProperties.Shared
}
- specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs...)
+ eval := module.ConfigurableEvaluator(ctx)
+ specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs.GetOrDefault(eval, nil)...)
// Must distinguish nil and [] in system_shared_libs - ensure that [] in
// either input list doesn't come out as nil.
@@ -1178,12 +1200,17 @@
return unstrippedOutputFile
}
-func addStubDependencyProviders(ctx ModuleContext) {
+// Visits the stub variants of the library and returns a struct containing the stub .so paths
+func addStubDependencyProviders(ctx ModuleContext) []SharedStubLibrary {
+ stubsInfo := []SharedStubLibrary{}
stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
if len(stubs) > 0 {
- var stubsInfo []SharedStubLibrary
for _, stub := range stubs {
- stubInfo, _ := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
+ stubInfo, ok := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
+ // TODO (b/275273834): Make this a hard error when the symbol files have been added to module sdk.
+ if !ok {
+ continue
+ }
flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
stubsInfo = append(stubsInfo, SharedStubLibrary{
Version: moduleLibraryInterface(stub).stubsVersion(),
@@ -1191,11 +1218,14 @@
FlagExporterInfo: flagInfo,
})
}
- android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
- SharedStubLibraries: stubsInfo,
- IsLLNDK: ctx.IsLlndk(),
- })
+ if len(stubsInfo) > 0 {
+ android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
+ SharedStubLibraries: stubsInfo,
+ IsLLNDK: ctx.IsLlndk(),
+ })
+ }
}
+ return stubsInfo
}
func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
@@ -1233,14 +1263,6 @@
func (library *libraryDecorator) llndkIncludeDirsForAbiCheck(ctx ModuleContext, deps PathDeps) []string {
var includeDirs, systemIncludeDirs []string
- // The ABI checker does not need the preprocess which adds macro guards to function declarations.
- preprocessedDirs := android.PathsForModuleSrc(ctx, library.Properties.Llndk.Export_preprocessed_headers).Strings()
- if Bool(library.Properties.Llndk.Export_headers_as_system) {
- systemIncludeDirs = append(systemIncludeDirs, preprocessedDirs...)
- } else {
- includeDirs = append(includeDirs, preprocessedDirs...)
- }
-
if library.Properties.Llndk.Override_export_include_dirs != nil {
includeDirs = append(includeDirs, android.PathsForModuleSrc(
ctx, library.Properties.Llndk.Override_export_include_dirs).Strings()...)
@@ -1342,7 +1364,7 @@
sourceVersion, errorMessage string) {
extraFlags := []string{"-target-version", sourceVersion}
- headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module))
if Bool(headerAbiChecker.Check_all_apis) {
extraFlags = append(extraFlags, "-check-all-apis")
} else {
@@ -1414,7 +1436,7 @@
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathDeps, objs Objects, fileName string, soFile android.Path) {
if library.sabi.shouldCreateSourceAbiDump() {
exportedIncludeDirs := library.exportedIncludeDirsForAbiCheck(ctx)
- headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module))
currSdkVersion := currRefAbiDumpSdkVersion(ctx)
currVendorVersion := ctx.Config().VendorApiLevel()
@@ -1428,7 +1450,7 @@
[]string{} /* includeSymbolTags */, currSdkVersion, false /* isLlndk */)
var llndkDump, apexVariantDump android.Path
- tags := classifySourceAbiDump(ctx)
+ tags := classifySourceAbiDump(ctx.Module().(*Module))
optInTags := []lsdumpTag{}
for _, tag := range tags {
if tag == llndkLsdumpTag && currVendorVersion != "" {
@@ -1548,25 +1570,6 @@
}
}
-func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) (timestamp android.Path, installPaths android.WritablePaths) {
- srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
- srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
-
- for _, header := range srcFiles {
- headerDir := filepath.Dir(header.String())
- relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir)
- if err != nil {
- ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s",
- srcDir.String(), headerDir, err)
- continue
- }
-
- installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
- }
-
- return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths), installPaths
-}
-
// link registers actions to link this library, and sets various fields
// on this library to reflect information that should be exported up the build
// tree (for example, exported flags and include paths).
@@ -1574,26 +1577,6 @@
flags Flags, deps PathDeps, objs Objects) android.Path {
if ctx.IsLlndk() {
- if len(library.Properties.Llndk.Export_preprocessed_headers) > 0 {
- // This is the vendor variant of an LLNDK library with preprocessed headers.
- genHeaderOutDir := android.PathForModuleGen(ctx, "include")
-
- var timestampFiles android.Paths
- for _, dir := range library.Properties.Llndk.Export_preprocessed_headers {
- timestampFile, installPaths := processLLNDKHeaders(ctx, dir, genHeaderOutDir)
- timestampFiles = append(timestampFiles, timestampFile)
- library.addExportedGeneratedHeaders(installPaths.Paths()...)
- }
-
- if Bool(library.Properties.Llndk.Export_headers_as_system) {
- library.reexportSystemDirs(genHeaderOutDir)
- } else {
- library.reexportDirs(genHeaderOutDir)
- }
-
- library.reexportDeps(timestampFiles...)
- }
-
// override the module's export_include_dirs with llndk.override_export_include_dirs
// if it is set.
if override := library.Properties.Llndk.Override_export_include_dirs; override != nil {
@@ -1651,8 +1634,8 @@
// Optionally export aidl headers.
if Bool(library.Properties.Aidl.Export_aidl_headers) {
- if library.baseCompiler.hasAidl(deps) {
- if library.baseCompiler.hasSrcExt(".aidl") {
+ if library.baseCompiler.hasAidl(ctx, deps) {
+ if library.baseCompiler.hasSrcExt(ctx, ".aidl") {
dir := android.PathForModuleGen(ctx, "aidl")
library.reexportDirs(dir)
}
@@ -1668,7 +1651,7 @@
// Optionally export proto headers.
if Bool(library.Properties.Proto.Export_proto_headers) {
- if library.baseCompiler.hasSrcExt(".proto") {
+ if library.baseCompiler.hasSrcExt(ctx, ".proto") {
var includes android.Paths
if flags.proto.CanonicalPathFromRoot {
includes = append(includes, flags.proto.SubDir)
@@ -1682,7 +1665,7 @@
}
// If the library is sysprop_library, expose either public or internal header selectively.
- if library.baseCompiler.hasSrcExt(".sysprop") {
+ if library.baseCompiler.hasSrcExt(ctx, ".sysprop") {
dir := android.PathForModuleGen(ctx, "sysprop", "include")
if library.Properties.Sysprop.Platform != nil {
isOwnerPlatform := Bool(library.Properties.Sysprop.Platform)
@@ -1884,7 +1867,7 @@
}
func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *string {
- if props := library.getHeaderAbiCheckerProperties(ctx); props.Symbol_file != nil {
+ if props := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)); props.Symbol_file != nil {
return props.Symbol_file
}
if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
@@ -2076,23 +2059,18 @@
// include directories.
if len(sharedCompiler.StaticProperties.Static.Cflags.GetOrDefault(ctx, nil)) == 0 &&
len(sharedCompiler.SharedProperties.Shared.Cflags.GetOrDefault(ctx, nil)) == 0 &&
- len(sharedCompiler.StaticProperties.Static.Whole_static_libs) == 0 &&
- len(sharedCompiler.SharedProperties.Shared.Whole_static_libs) == 0 &&
- len(sharedCompiler.StaticProperties.Static.Static_libs) == 0 &&
- len(sharedCompiler.SharedProperties.Shared.Static_libs) == 0 &&
- len(sharedCompiler.StaticProperties.Static.Shared_libs) == 0 &&
- len(sharedCompiler.SharedProperties.Shared.Shared_libs) == 0 &&
+ len(sharedCompiler.StaticProperties.Static.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Whole_static_libs.GetOrDefault(ctx, nil)) == 0 &&
+ len(sharedCompiler.StaticProperties.Static.Static_libs.GetOrDefault(ctx, nil)) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Static_libs.GetOrDefault(ctx, nil)) == 0 &&
+ len(sharedCompiler.StaticProperties.Static.Shared_libs.GetOrDefault(ctx, nil)) == 0 &&
+ len(sharedCompiler.SharedProperties.Shared.Shared_libs.GetOrDefault(ctx, nil)) == 0 &&
// Compare System_shared_libs properties with nil because empty lists are
// semantically significant for them.
sharedCompiler.StaticProperties.Static.System_shared_libs == nil &&
sharedCompiler.SharedProperties.Shared.System_shared_libs == nil {
- // TODO: namespaces?
ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, reuseObjTag, ctx.ModuleName())
- sharedCompiler.baseCompiler.Properties.OriginalSrcs =
- sharedCompiler.baseCompiler.Properties.Srcs
- sharedCompiler.baseCompiler.Properties.Srcs = nil
- sharedCompiler.baseCompiler.Properties.Generated_sources = nil
}
// This dep is just to reference static variant from shared variant
@@ -2366,9 +2344,8 @@
if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
isLLNDK := m.IsLlndk()
isVendorPublicLibrary := m.IsVendorPublicLibrary()
- isImportedApiLibrary := m.isImportedApiLibrary()
- if variation != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
+ if variation != "" || isLLNDK || isVendorPublicLibrary {
// A stubs or LLNDK stubs variant.
if m.sanitize != nil {
m.sanitize.Properties.ForceDisable = true
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index e8a9827..af3658d 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -543,7 +543,7 @@
p.ExportedFlags = exportedInfo.Flags
if ccModule.linker != nil {
specifiedDeps := specifiedDeps{}
- specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
+ specifiedDeps = ccModule.linker.linkerSpecifiedDeps(ctx.SdkModuleContext(), ccModule, specifiedDeps)
if lib := ccModule.library; lib != nil {
if !lib.hasStubsVariants() {
diff --git a/cc/library_stub.go b/cc/library_stub.go
deleted file mode 100644
index 6367825..0000000
--- a/cc/library_stub.go
+++ /dev/null
@@ -1,512 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cc
-
-import (
- "regexp"
- "strings"
-
- "android/soong/android"
- "android/soong/multitree"
-
- "github.com/google/blueprint/proptools"
-)
-
-var (
- ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
- stubVariantRegex = regexp.MustCompile("apex\\.([a-zA-Z0-9]+)")
-)
-
-func init() {
- RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
-}
-
-func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
- ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
- ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
-}
-
-func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
- m, ok := ctx.Module().(*Module)
- if !ok {
- return
- }
-
- apiLibrary, ok := m.linker.(*apiLibraryDecorator)
- if !ok {
- return
- }
-
- if m.InVendorOrProduct() && apiLibrary.hasLLNDKStubs() {
- // Add LLNDK variant dependency
- if inList("llndk", apiLibrary.properties.Variants) {
- variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
- ctx.AddDependency(m, nil, variantName)
- }
- } else if m.IsSdkVariant() {
- // Add NDK variant dependencies
- targetVariant := "ndk." + m.StubsVersion()
- if inList(targetVariant, apiLibrary.properties.Variants) {
- variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
- ctx.AddDependency(m, nil, variantName)
- }
- } else if m.IsStubs() {
- targetVariant := "apex." + m.StubsVersion()
- if inList(targetVariant, apiLibrary.properties.Variants) {
- variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
- ctx.AddDependency(m, nil, variantName)
- }
- }
-}
-
-// 'cc_api_library' is a module type which is from the exported API surface
-// with C shared library type. The module will replace original module, and
-// offer a link to the module that generates shared library object from the
-// map file.
-type apiLibraryProperties struct {
- Src *string `android:"arch_variant"`
- Variants []string
-}
-
-type apiLibraryDecorator struct {
- *libraryDecorator
- properties apiLibraryProperties
-}
-
-func CcApiLibraryFactory() android.Module {
- module, decorator := NewLibrary(android.DeviceSupported)
- apiLibraryDecorator := &apiLibraryDecorator{
- libraryDecorator: decorator,
- }
- apiLibraryDecorator.BuildOnlyShared()
-
- module.stl = nil
- module.sanitize = nil
- decorator.disableStripping()
-
- module.compiler = nil
- module.linker = apiLibraryDecorator
- module.installer = nil
- module.library = apiLibraryDecorator
- module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
-
- // Prevent default system libs (libc, libm, and libdl) from being linked
- if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
- apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
- }
-
- apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
- apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
-
- module.Init()
-
- return module
-}
-
-func (d *apiLibraryDecorator) Name(basename string) string {
- return basename + multitree.GetApiImportSuffix()
-}
-
-// Export include dirs without checking for existence.
-// The directories are not guaranteed to exist during Soong analysis.
-func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
- exporterProps := d.flagExporter.Properties
- for _, dir := range exporterProps.Export_include_dirs.GetOrDefault(ctx, nil) {
- d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
- }
- // system headers
- for _, dir := range exporterProps.Export_system_include_dirs {
- d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
- }
-}
-
-func (d *apiLibraryDecorator) linkerInit(ctx BaseModuleContext) {
- d.baseLinker.linkerInit(ctx)
-
- if d.hasNDKStubs() {
- // Set SDK version of module as current
- ctx.Module().(*Module).Properties.Sdk_version = StringPtr("current")
-
- // Add NDK stub as NDK known libs
- name := ctx.ModuleName()
-
- ndkKnownLibsLock.Lock()
- ndkKnownLibs := getNDKKnownLibs(ctx.Config())
- if !inList(name, *ndkKnownLibs) {
- *ndkKnownLibs = append(*ndkKnownLibs, name)
- }
- ndkKnownLibsLock.Unlock()
- }
-}
-
-func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
- m, _ := ctx.Module().(*Module)
-
- var in android.Path
-
- // src might not exist during the beginning of soong analysis in Multi-tree
- if src := String(d.properties.Src); src != "" {
- in = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), src)
- }
-
- libName := m.BaseModuleName() + multitree.GetApiImportSuffix()
-
- load_cc_variant := func(apiVariantModule string) {
- var mod android.Module
-
- ctx.VisitDirectDeps(func(depMod android.Module) {
- if depMod.Name() == apiVariantModule {
- mod = depMod
- libName = apiVariantModule
- }
- })
-
- if mod != nil {
- variantMod, ok := mod.(*CcApiVariant)
- if ok {
- in = variantMod.Src()
-
- // Copy LLDNK properties to cc_api_library module
- exportIncludeDirs := append(d.libraryDecorator.flagExporter.Properties.Export_include_dirs.GetOrDefault(ctx, nil),
- variantMod.exportProperties.Export_include_dirs...)
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](
- nil,
- []proptools.ConfigurableCase[[]string]{
- proptools.NewConfigurableCase[[]string](nil, &exportIncludeDirs),
- },
- )
-
- // Export headers as system include dirs if specified. Mostly for libc
- if Bool(variantMod.exportProperties.Export_headers_as_system) {
- d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
- d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs.GetOrDefault(ctx, nil)...)
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](nil, nil)
- }
- }
- }
- }
-
- if m.InVendorOrProduct() && d.hasLLNDKStubs() {
- // LLNDK variant
- load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "llndk", ""))
- } else if m.IsSdkVariant() {
- // NDK Variant
- load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion()))
- } else if m.IsStubs() {
- // APEX Variant
- load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "apex", m.StubsVersion()))
- }
-
- // Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
- d.exportIncludes(ctx)
- d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
- d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
- d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
- d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
- d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
-
- if in == nil {
- ctx.PropertyErrorf("src", "Unable to locate source property")
- return nil
- }
-
- // Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
- // The .so file itself has an order-only dependency on the headers contributed by this library.
- // Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
- d.libraryDecorator.reexportDeps(in)
- d.libraryDecorator.flagExporter.setProvider(ctx)
-
- d.unstrippedOutputFile = in
- libName += flags.Toolchain.ShlibSuffix()
-
- tocFile := android.PathForModuleOut(ctx, libName+".toc")
- d.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, in, tocFile)
-
- outputFile := android.PathForModuleOut(ctx, libName)
-
- // TODO(b/270485584) This copies with a new name, just to avoid conflict with prebuilts.
- // We can just use original input if there is any way to avoid name conflict without copy.
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Description: "API surface imported library",
- Input: in,
- Output: outputFile,
- Args: map[string]string{
- "cpFlags": "-L",
- },
- })
-
- android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
- SharedLibrary: outputFile,
- Target: ctx.Target(),
-
- TableOfContents: d.tocFile,
- })
-
- d.shareStubs(ctx)
-
- return outputFile
-}
-
-// Share additional information about stub libraries with provider
-func (d *apiLibraryDecorator) shareStubs(ctx ModuleContext) {
- stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
- if len(stubs) > 0 {
- var stubsInfo []SharedStubLibrary
- for _, stub := range stubs {
- stubInfo, _ := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
- flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
- stubsInfo = append(stubsInfo, SharedStubLibrary{
- Version: moduleLibraryInterface(stub).stubsVersion(),
- SharedLibraryInfo: stubInfo,
- FlagExporterInfo: flagInfo,
- })
- }
- android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
- SharedStubLibraries: stubsInfo,
-
- IsLLNDK: ctx.IsLlndk(),
- })
- }
-}
-
-func (d *apiLibraryDecorator) availableFor(what string) bool {
- // Stub from API surface should be available for any APEX.
- return true
-}
-
-func (d *apiLibraryDecorator) hasApexStubs() bool {
- for _, variant := range d.properties.Variants {
- if strings.HasPrefix(variant, "apex") {
- return true
- }
- }
- return false
-}
-
-func (d *apiLibraryDecorator) hasStubsVariants() bool {
- return d.hasApexStubs()
-}
-
-func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseModuleContext) []string {
- m, ok := ctx.Module().(*Module)
-
- if !ok {
- return nil
- }
-
- // TODO(b/244244438) Create more version information for NDK and APEX variations
- // NDK variants
- if m.IsSdkVariant() {
- // TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
- if d.hasNDKStubs() {
- return d.getNdkVersions()
- }
- }
-
- if d.hasLLNDKStubs() && m.InVendorOrProduct() {
- // LLNDK libraries only need a single stubs variant.
- return []string{android.FutureApiLevel.String()}
- }
-
- stubsVersions := d.getStubVersions()
-
- if len(stubsVersions) != 0 {
- return stubsVersions
- }
-
- if m.MinSdkVersion() == "" {
- return nil
- }
-
- firstVersion, err := nativeApiLevelFromUser(ctx,
- m.MinSdkVersion())
-
- if err != nil {
- return nil
- }
-
- return ndkLibraryVersions(ctx, firstVersion)
-}
-
-func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
- return inList("llndk", d.properties.Variants)
-}
-
-func (d *apiLibraryDecorator) hasNDKStubs() bool {
- for _, variant := range d.properties.Variants {
- if ndkVariantRegex.MatchString(variant) {
- return true
- }
- }
- return false
-}
-
-func (d *apiLibraryDecorator) getNdkVersions() []string {
- ndkVersions := []string{}
-
- for _, variant := range d.properties.Variants {
- if match := ndkVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
- ndkVersions = append(ndkVersions, match[1])
- }
- }
-
- return ndkVersions
-}
-
-func (d *apiLibraryDecorator) getStubVersions() []string {
- stubVersions := []string{}
-
- for _, variant := range d.properties.Variants {
- if match := stubVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
- stubVersions = append(stubVersions, match[1])
- }
- }
-
- return stubVersions
-}
-
-// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
-// header libraries. The module will replace any dependencies to existing
-// original header libraries.
-type apiHeadersDecorator struct {
- *libraryDecorator
-}
-
-func CcApiHeadersFactory() android.Module {
- module, decorator := NewLibrary(android.DeviceSupported)
- apiHeadersDecorator := &apiHeadersDecorator{
- libraryDecorator: decorator,
- }
- apiHeadersDecorator.HeaderOnly()
-
- module.stl = nil
- module.sanitize = nil
- decorator.disableStripping()
-
- module.compiler = nil
- module.linker = apiHeadersDecorator
- module.installer = nil
-
- // Prevent default system libs (libc, libm, and libdl) from being linked
- if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
- apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
- }
-
- apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
- apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
-
- module.Init()
-
- return module
-}
-
-func (d *apiHeadersDecorator) Name(basename string) string {
- return basename + multitree.GetApiImportSuffix()
-}
-
-func (d *apiHeadersDecorator) availableFor(what string) bool {
- // Stub from API surface should be available for any APEX.
- return true
-}
-
-type ccApiexportProperties struct {
- Src *string `android:"arch_variant"`
- Variant *string
- Version *string
-}
-
-type variantExporterProperties struct {
- // Header directory to export
- Export_include_dirs []string `android:"arch_variant"`
-
- // Export all headers as system include
- Export_headers_as_system *bool
-}
-
-type CcApiVariant struct {
- android.ModuleBase
-
- properties ccApiexportProperties
- exportProperties variantExporterProperties
-
- src android.Path
-}
-
-var _ android.Module = (*CcApiVariant)(nil)
-var _ android.ImageInterface = (*CcApiVariant)(nil)
-
-func CcApiVariantFactory() android.Module {
- module := &CcApiVariant{}
-
- module.AddProperties(&module.properties)
- module.AddProperties(&module.exportProperties)
-
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
- return module
-}
-
-func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // No need to build
-
- if String(v.properties.Src) == "" {
- ctx.PropertyErrorf("src", "src is a required property")
- }
-
- // Skip the existence check of the stub prebuilt file.
- // The file is not guaranteed to exist during Soong analysis.
- // Build orchestrator will be responsible for creating a connected ninja graph.
- v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), String(v.properties.Src))
-}
-
-func (v *CcApiVariant) Name() string {
- version := String(v.properties.Version)
- return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
-}
-
-func (v *CcApiVariant) Src() android.Path {
- return v.src
-}
-
-func BuildApiVariantName(baseName string, variant string, version string) string {
- names := []string{baseName, variant}
- if version != "" {
- names = append(names, version)
- }
-
- return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
-}
-
-// Implement ImageInterface to generate image variants
-func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
-func (v *CcApiVariant) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
- return String(v.properties.Variant) == "llndk"
-}
-func (v *CcApiVariant) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
- return String(v.properties.Variant) == "llndk"
-}
-func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
- return inList(String(v.properties.Variant), []string{"ndk", "apex"})
-}
-func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
-func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
-func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
-func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
-func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string { return nil }
-func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string) {
-}
diff --git a/cc/linker.go b/cc/linker.go
index d2974c2..1efacad 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -37,16 +37,16 @@
// in their entirety. For static library modules, all of the .o files from the intermediate
// directory of the dependency will be linked into this modules .a file. For a shared library,
// the dependency's .a file will be linked into this module using -Wl,--whole-archive.
- Whole_static_libs []string `android:"arch_variant,variant_prepend"`
+ Whole_static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of modules that should be statically linked into this module.
- Static_libs []string `android:"arch_variant,variant_prepend"`
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of modules that should be dynamically linked into this module.
- Shared_libs []string `android:"arch_variant"`
+ Shared_libs proptools.Configurable[[]string] `android:"arch_variant"`
// list of modules that should only provide headers for this module.
- Header_libs []string `android:"arch_variant,variant_prepend"`
+ Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of module-specific flags that will be used for all link steps
Ldflags []string `android:"arch_variant"`
@@ -296,10 +296,10 @@
}
func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
- deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
- deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
- deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...)
- deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs.GetOrDefault(ctx, nil)...)
+ deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs.GetOrDefault(ctx, nil)...)
+ deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs.GetOrDefault(ctx, nil)...)
+ deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...)
deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...)
@@ -645,8 +645,9 @@
panic(fmt.Errorf("baseLinker doesn't know how to link"))
}
-func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
- specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
+func (linker *baseLinker) linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
+ eval := module.ConfigurableEvaluator(ctx)
+ specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs.GetOrDefault(eval, nil)...)
// Must distinguish nil and [] in system_shared_libs - ensure that [] in
// either input list doesn't come out as nil.
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 5ece78a..c7950f9 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -36,10 +36,6 @@
// bionic/libc.
Export_headers_as_system *bool
- // Which headers to process with versioner. This really only handles
- // bionic/libc/include right now.
- Export_preprocessed_headers []string
-
// Whether the system library uses symbol versions.
Unversioned *bool
diff --git a/cc/makevars.go b/cc/makevars.go
index cd13965..c9352a4 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -140,7 +140,6 @@
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " "))
ctx.Strict("HWADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(hwasanCflags, " "))
- ctx.Strict("HWADDRESS_SANITIZER_GLOBAL_OPTIONS", strings.Join(hwasanGlobalOptions, ","))
ctx.Strict("CFI_EXTRA_CFLAGS", strings.Join(cfiCflags, " "))
ctx.Strict("CFI_EXTRA_ASFLAGS", strings.Join(cfiAsflags, " "))
diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go
index 5beeab1..2706261 100644
--- a/cc/ndk_abi.go
+++ b/cc/ndk_abi.go
@@ -46,7 +46,7 @@
if m, ok := module.(*Module); ok {
if installer, ok := m.installer.(*stubDecorator); ok {
- if canDumpAbi(ctx.Config()) {
+ if installer.hasAbiDump {
depPaths = append(depPaths, installer.abiDumpPath)
}
}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 57a3b3a..7481954 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -18,19 +18,11 @@
"path/filepath"
"android/soong/android"
+
"github.com/google/blueprint"
)
var (
- versionBionicHeaders = pctx.AndroidStaticRule("versionBionicHeaders",
- blueprint.RuleParams{
- // The `&& touch $out` isn't really necessary, but Blueprint won't
- // let us have only implicit outputs.
- Command: "$versionerCmd -o $outDir $srcDir $depsPath && touch $out",
- CommandDeps: []string{"$versionerCmd"},
- },
- "depsPath", "srcDir", "outDir")
-
preprocessNdkHeader = pctx.AndroidStaticRule("preprocessNdkHeader",
blueprint.RuleParams{
Command: "$preprocessor -o $out $in",
@@ -39,12 +31,8 @@
"preprocessor")
)
-func init() {
- pctx.SourcePathVariable("versionerCmd", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/versioner")
-}
-
// Returns the NDK base include path for use with sdk_version current. Usable with -I.
-func getCurrentIncludePath(ctx android.ModuleContext) android.OutputPath {
+func getCurrentIncludePath(ctx android.PathContext) android.OutputPath {
return getNdkSysrootBase(ctx).Join(ctx, "usr/include")
}
@@ -73,6 +61,13 @@
// Path to the NOTICE file associated with the headers.
License *string `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.
+ Skip_verification *bool
}
type headerModule struct {
@@ -159,126 +154,6 @@
return module
}
-type versionedHeaderProperties struct {
- // Base directory of the headers being installed. As an example:
- //
- // versioned_ndk_headers {
- // name: "foo",
- // from: "include",
- // to: "",
- // }
- //
- // Will install $SYSROOT/usr/include/foo/bar/baz.h. If `from` were instead
- // "include/foo", it would have installed $SYSROOT/usr/include/bar/baz.h.
- From *string
-
- // Install path within the sysroot. This is relative to usr/include.
- To *string
-
- // Path to the NOTICE file associated with the headers.
- License *string
-}
-
-// Like ndk_headers, but preprocesses the headers with the bionic versioner:
-// https://android.googlesource.com/platform/bionic/+/main/tools/versioner/README.md.
-//
-// Unlike ndk_headers, we don't operate on a list of sources but rather a whole directory, the
-// module does not have the srcs property, and operates on a full directory (the `from` property).
-//
-// Note that this is really only built to handle bionic/libc/include.
-type versionedHeaderModule struct {
- android.ModuleBase
-
- properties versionedHeaderProperties
-
- srcPaths android.Paths
- installPaths android.Paths
- licensePath android.Path
-}
-
-// Return the glob pattern to find all .h files beneath `dir`
-func headerGlobPattern(dir string) string {
- return filepath.Join(dir, "**", "*.h")
-}
-
-func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if String(m.properties.License) == "" {
- ctx.PropertyErrorf("license", "field is required")
- }
-
- m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
-
- fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From))
- toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
- m.srcPaths = ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
- var installPaths []android.WritablePath
- for _, header := range m.srcPaths {
- installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To))
- installPath := installDir.Join(ctx, header.Base())
- installPaths = append(installPaths, installPath)
- m.installPaths = append(m.installPaths, installPath)
- }
-
- if len(m.installPaths) == 0 {
- ctx.ModuleErrorf("glob %q matched zero files", String(m.properties.From))
- }
-
- processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, m.srcPaths, installPaths)
-}
-
-func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path,
- srcPaths android.Paths, installPaths []android.WritablePath) android.Path {
- // The versioner depends on a dependencies directory to simplify determining include paths
- // when parsing headers. This directory contains architecture specific directories as well
- // as a common directory, each of which contains symlinks to the actually directories to
- // be included.
- //
- // ctx.Glob doesn't follow symlinks, so we need to do this ourselves so we correctly
- // depend on these headers.
- // TODO(http://b/35673191): Update the versioner to use a --sysroot.
- depsPath := android.PathForSource(ctx, "bionic/libc/versioner-dependencies")
- depsGlob := ctx.Glob(filepath.Join(depsPath.String(), "**/*"), nil)
- for i, path := range depsGlob {
- if ctx.IsSymlink(path) {
- dest := ctx.Readlink(path)
- // Additional .. to account for the symlink itself.
- depsGlob[i] = android.PathForSource(
- ctx, filepath.Clean(filepath.Join(path.String(), "..", dest)))
- }
- }
-
- timestampFile := android.PathForModuleOut(ctx, "versioner.timestamp")
- ctx.Build(pctx, android.BuildParams{
- Rule: versionBionicHeaders,
- Description: "versioner preprocess " + srcDir.Rel(),
- Output: timestampFile,
- Implicits: append(srcPaths, depsGlob...),
- ImplicitOutputs: installPaths,
- Args: map[string]string{
- "depsPath": depsPath.String(),
- "srcDir": srcDir.String(),
- "outDir": outDir.String(),
- },
- })
-
- return timestampFile
-}
-
-// versioned_ndk_headers preprocesses the headers with the bionic versioner:
-// https://android.googlesource.com/platform/bionic/+/main/tools/versioner/README.md.
-// Unlike the ndk_headers soong module, versioned_ndk_headers operates on a
-// directory level specified in `from` property. This is only used to process
-// the bionic/libc/include directory.
-func VersionedNdkHeadersFactory() android.Module {
- module := &versionedHeaderModule{}
-
- module.AddProperties(&module.properties)
-
- android.InitAndroidModule(module)
-
- return module
-}
-
// preprocessed_ndk_header {
//
// name: "foo",
@@ -309,6 +184,13 @@
// Path to the NOTICE file associated with the headers.
License *string
+
+ // 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.
+ Skip_verification *bool
}
type preprocessedHeadersModule struct {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index b822e5c..01551ab 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -103,8 +103,17 @@
// https://github.com/android-ndk/ndk/issues/265.
Unversioned_until *string
- // Headers presented by this library to the Public API Surface
+ // DO NOT USE THIS
+ // NDK libraries should not export their headers. Headers belonging to NDK
+ // libraries should be added to the NDK with an ndk_headers module.
Export_header_libs []string
+
+ // Do not add other export_* properties without consulting with danalbert@.
+ // Consumers of ndk_library modules should emulate the typical NDK build
+ // behavior as closely as possible (that is, all NDK APIs are exposed to
+ // builds via --sysroot). Export behaviors used in Soong will not be present
+ // for app developers as they don't use Soong, and reliance on these export
+ // behaviors can mask issues with the NDK sysroot.
}
type stubDecorator struct {
@@ -116,6 +125,7 @@
parsedCoverageXmlPath android.ModuleOutPath
installPath android.Path
abiDumpPath android.OutputPath
+ hasAbiDump bool
abiDiffPaths android.Paths
apiLevel android.ApiLevel
@@ -321,12 +331,27 @@
}
// Feature flag.
-func canDumpAbi(config android.Config) bool {
+func (this *stubDecorator) canDumpAbi(ctx ModuleContext) bool {
if runtime.GOOS == "darwin" {
return false
}
+ if strings.HasPrefix(ctx.ModuleDir(), "bionic/") {
+ // Bionic has enough uncommon implementation details like ifuncs and asm
+ // code that the ABI tracking here has a ton of false positives. That's
+ // causing pretty extreme friction for development there, so disabling
+ // it until the workflow can be improved.
+ //
+ // http://b/358653811
+ return false
+ }
+
+ if this.apiLevel.IsCurrent() {
+ // "current" (AKA 10000) is not tracked.
+ return false
+ }
+
// http://b/156513478
- return config.ReleaseNdkAbiMonitored()
+ return ctx.Config().ReleaseNdkAbiMonitored()
}
// Feature flag to disable diffing against prebuilts.
@@ -339,6 +364,7 @@
this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
this.apiLevel.String(), ctx.Arch().ArchType.String(),
this.libraryName(ctx), "abi.stg")
+ this.hasAbiDump = true
headersList := getNdkABIHeadersFile(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: stg,
@@ -403,41 +429,45 @@
// Also ensure that the ABI of the next API level (if there is one) matches
// this API level. *New* ABI is allowed, but any changes to APIs that exist
// in this API level are disallowed.
- if !this.apiLevel.IsCurrent() && prebuiltAbiDump.Valid() {
+ if prebuiltAbiDump.Valid() {
nextApiLevel := findNextApiLevel(ctx, this.apiLevel)
if nextApiLevel == nil {
panic(fmt.Errorf("could not determine which API level follows "+
"non-current API level %s", this.apiLevel))
}
- nextAbiDiffPath := android.PathForModuleOut(ctx,
- "abidiff_next.timestamp")
- nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
- missingNextPrebuiltError := fmt.Sprintf(
- missingPrebuiltErrorTemplate, this.libraryName(ctx),
- nextAbiDump.InvalidReason())
- if !nextAbiDump.Valid() {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.ErrorRule,
- Output: nextAbiDiffPath,
- Args: map[string]string{
- "error": missingNextPrebuiltError,
- },
- })
- } else {
- ctx.Build(pctx, android.BuildParams{
- Rule: stgdiff,
- Description: fmt.Sprintf(
- "Comparing ABI to the next API level %s %s",
- prebuiltAbiDump, nextAbiDump),
- Output: nextAbiDiffPath,
- Inputs: android.Paths{
- prebuiltAbiDump.Path(), nextAbiDump.Path()},
- Args: map[string]string{
- "args": "--format=small --ignore=interface_addition",
- },
- })
+
+ // "current" ABI is not tracked.
+ if !nextApiLevel.IsCurrent() {
+ nextAbiDiffPath := android.PathForModuleOut(ctx,
+ "abidiff_next.timestamp")
+ nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
+ missingNextPrebuiltError := fmt.Sprintf(
+ missingPrebuiltErrorTemplate, this.libraryName(ctx),
+ nextAbiDump.InvalidReason())
+ if !nextAbiDump.Valid() {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: nextAbiDiffPath,
+ Args: map[string]string{
+ "error": missingNextPrebuiltError,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: stgdiff,
+ Description: fmt.Sprintf(
+ "Comparing ABI to the next API level %s %s",
+ prebuiltAbiDump, nextAbiDump),
+ Output: nextAbiDiffPath,
+ Inputs: android.Paths{
+ prebuiltAbiDump.Path(), nextAbiDump.Path()},
+ Args: map[string]string{
+ "args": "--format=small --ignore=interface_addition",
+ },
+ })
+ }
+ this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
}
- this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
}
}
@@ -460,7 +490,7 @@
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, c.apiLevel, "")
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
c.versionScriptPath = nativeAbiResult.versionScript
- if canDumpAbi(ctx.Config()) {
+ if c.canDumpAbi(ctx) {
c.dumpAbi(ctx, nativeAbiResult.symbolList)
if canDiffAbi(ctx.Config()) {
c.diffAbi(ctx)
@@ -475,7 +505,8 @@
// Add a dependency on the header modules of this ndk_library
func (linker *stubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
return Deps{
- HeaderLibs: linker.properties.Export_header_libs,
+ ReexportHeaderLibHeaders: linker.properties.Export_header_libs,
+ HeaderLibs: linker.properties.Export_header_libs,
}
}
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
deleted file mode 100644
index f503982..0000000
--- a/cc/ndk_prebuilt.go
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2016 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// 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 (
- "strings"
-
- "android/soong/android"
-)
-
-func init() {
- android.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
- android.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
-}
-
-// NDK prebuilt libraries.
-//
-// These differ from regular prebuilts in that they aren't stripped and usually aren't installed
-// either (with the exception of the shared STLs, which are installed to the app's directory rather
-// than to the system image).
-
-type ndkPrebuiltStlLinker struct {
- *libraryDecorator
-}
-
-func (ndk *ndkPrebuiltStlLinker) linkerProps() []interface{} {
- return append(ndk.libraryDecorator.linkerProps(), &ndk.Properties, &ndk.flagExporter.Properties)
-}
-
-func (*ndkPrebuiltStlLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
- // NDK libraries can't have any dependencies
- return deps
-}
-
-func (*ndkPrebuiltStlLinker) availableFor(what string) bool {
- // ndk prebuilt objects are available to everywhere
- return true
-}
-
-// ndk_prebuilt_shared_stl exports a precompiled ndk shared standard template
-// library (stl) library for linking operation. The soong's module name format
-// is ndk_<NAME>.so where the library is located under
-// ./prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/$(HOST_ARCH)/<NAME>.so.
-func NdkPrebuiltSharedStlFactory() android.Module {
- module, library := NewLibrary(android.DeviceSupported)
- library.BuildOnlyShared()
- module.compiler = nil
- module.linker = &ndkPrebuiltStlLinker{
- libraryDecorator: library,
- }
- module.installer = nil
- module.Properties.Sdk_version = StringPtr("minimum")
- module.Properties.AlwaysSdk = true
- module.stl.Properties.Stl = StringPtr("none")
- return module.Init()
-}
-
-// ndk_prebuilt_static_stl exports a precompiled ndk static standard template
-// library (stl) library for linking operation. The soong's module name format
-// is ndk_<NAME>.a where the library is located under
-// ./prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/$(HOST_ARCH)/<NAME>.a.
-func NdkPrebuiltStaticStlFactory() android.Module {
- module, library := NewLibrary(android.DeviceSupported)
- library.BuildOnlyStatic()
- module.compiler = nil
- module.linker = &ndkPrebuiltStlLinker{
- libraryDecorator: library,
- }
- module.installer = nil
- module.Properties.Sdk_version = StringPtr("minimum")
- module.Properties.HideFromMake = true
- module.Properties.AlwaysSdk = true
- module.Properties.Sdk_version = StringPtr("current")
- module.stl.Properties.Stl = StringPtr("none")
- return module.Init()
-}
-
-const (
- libDir = "current/sources/cxx-stl/llvm-libc++/libs"
-)
-
-func getNdkStlLibDir(ctx android.ModuleContext) android.SourcePath {
- return android.PathForSource(ctx, ctx.ModuleDir(), libDir).Join(ctx, ctx.Arch().Abi[0])
-}
-
-func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
- deps PathDeps, objs Objects) android.Path {
- // A null build step, but it sets up the output path.
- if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
- ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name")
- }
-
- ndk.libraryDecorator.flagExporter.exportIncludesAsSystem(ctx)
-
- libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
- libExt := flags.Toolchain.ShlibSuffix()
- if ndk.static() {
- libExt = staticLibraryExtension
- }
-
- libDir := getNdkStlLibDir(ctx)
- lib := libDir.Join(ctx, libName+libExt)
-
- ndk.libraryDecorator.flagExporter.setProvider(ctx)
-
- if ndk.static() {
- depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(lib).Build()
- android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{
- StaticLibrary: lib,
-
- TransitiveStaticLibrariesForOrdering: depSet,
- })
- } else {
- android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
- SharedLibrary: lib,
- Target: ctx.Target(),
- })
- }
-
- return lib
-}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 3c48f68..92da172 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -54,7 +54,22 @@
import (
"android/soong/android"
+ "fmt"
+ "path/filepath"
"strings"
+
+ "github.com/google/blueprint"
+)
+
+var (
+ verifyCCompat = pctx.AndroidStaticRule("verifyCCompat",
+ blueprint.RuleParams{
+ Command: "$ccCmd -x c -fsyntax-only $flags $in && touch $out",
+ CommandDeps: []string{"$ccCmd"},
+ },
+ "ccCmd",
+ "flags",
+ )
)
func init() {
@@ -64,7 +79,6 @@
func RegisterNdkModuleTypes(ctx android.RegistrationContext) {
ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
- ctx.RegisterModuleType("versioned_ndk_headers", VersionedNdkHeadersFactory)
ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory)
ctx.RegisterParallelSingletonType("ndk", NdkSingleton)
}
@@ -103,6 +117,45 @@
return android.PathForOutput(ctx, "ndk_abi_headers.txt")
}
+func verifyNdkHeaderIsCCompatible(ctx android.SingletonContext,
+ src android.Path, dest android.Path) android.Path {
+ sysrootInclude := getCurrentIncludePath(ctx)
+ baseOutputDir := android.PathForOutput(ctx, "c-compat-verification")
+ installRelPath, err := filepath.Rel(sysrootInclude.String(), dest.String())
+ if err != nil {
+ ctx.Errorf("filepath.Rel(%q, %q) failed: %s", dest, sysrootInclude, err)
+ }
+ output := baseOutputDir.Join(ctx, installRelPath)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: verifyCCompat,
+ Description: fmt.Sprintf("Verifying C compatibility of %s", src),
+ Output: output,
+ Input: dest,
+ // Ensures that all the headers in the sysroot are already installed
+ // before testing any of the headers for C compatibility, and also that
+ // the check will be re-run whenever the sysroot changes. This is
+ // necessary because many of the NDK headers depend on other NDK
+ // headers, but we don't have explicit dependency tracking for that.
+ Implicits: []android.Path{getNdkHeadersTimestampFile(ctx)},
+ Args: map[string]string{
+ "ccCmd": "${config.ClangBin}/clang",
+ "flags": fmt.Sprintf(
+ // Ideally we'd check each ABI, multiple API levels,
+ // fortify/non-fortify, and a handful of other variations. It's
+ // a lot more difficult to do that though, and would eat up more
+ // build time. All the problems we've seen so far that this
+ // check would catch have been in arch-generic and
+ // minSdkVersion-generic code in frameworks though, so this is a
+ // good place to start.
+ "-target aarch64-linux-android%d --sysroot %s",
+ android.FutureApiLevel.FinalOrFutureInt(),
+ getNdkSysrootBase(ctx).String(),
+ ),
+ },
+ })
+ return output
+}
+
func NdkSingleton() android.Singleton {
return &ndkSingleton{}
}
@@ -143,10 +196,17 @@
type ndkSingleton struct{}
+type srcDestPair struct {
+ src android.Path
+ dest android.Path
+}
+
func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var staticLibInstallPaths android.Paths
var headerSrcPaths android.Paths
var headerInstallPaths android.Paths
+ var headersToVerify []srcDestPair
+ var headerCCompatVerificationTimestampPaths android.Paths
var installPaths android.Paths
var licensePaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
@@ -157,13 +217,14 @@
if m, ok := module.(*headerModule); ok {
headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
headerInstallPaths = append(headerInstallPaths, m.installPaths...)
- installPaths = append(installPaths, m.installPaths...)
- licensePaths = append(licensePaths, m.licensePath)
- }
-
- if m, ok := module.(*versionedHeaderModule); ok {
- headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
- headerInstallPaths = append(headerInstallPaths, m.installPaths...)
+ if !Bool(m.properties.Skip_verification) {
+ for i, installPath := range m.installPaths {
+ headersToVerify = append(headersToVerify, srcDestPair{
+ src: m.srcPaths[i],
+ dest: installPath,
+ })
+ }
+ }
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
@@ -171,6 +232,14 @@
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 {
+ headersToVerify = append(headersToVerify, srcDestPair{
+ src: m.srcPaths[i],
+ dest: installPath,
+ })
+ }
+ }
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
@@ -223,6 +292,12 @@
Implicits: headerInstallPaths,
})
+ for _, srcDestPair := range headersToVerify {
+ headerCCompatVerificationTimestampPaths = append(
+ headerCCompatVerificationTimestampPaths,
+ verifyNdkHeaderIsCCompatible(ctx, srcDestPair.src, srcDestPair.dest))
+ }
+
writeNdkAbiSrcFilter(ctx, headerSrcPaths, getNdkABIHeadersFile(ctx))
fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
@@ -235,6 +310,6 @@
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
Output: getNdkFullTimestampFile(ctx),
- Implicits: fullDepPaths,
+ Implicits: append(fullDepPaths, headerCCompatVerificationTimestampPaths...),
})
}
diff --git a/cc/object.go b/cc/object.go
index 8b23295..c89520a 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -19,6 +19,8 @@
"strings"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
//
@@ -50,13 +52,13 @@
type ObjectLinkerProperties struct {
// list of static library modules that should only provide headers for this module.
- Static_libs []string `android:"arch_variant,variant_prepend"`
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of shared library modules should only provide headers for this module.
- Shared_libs []string `android:"arch_variant,variant_prepend"`
+ Shared_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of modules that should only provide headers for this module.
- Header_libs []string `android:"arch_variant,variant_prepend"`
+ Header_libs proptools.Configurable[[]string] `android:"arch_variant,variant_prepend"`
// list of default libraries that will provide headers for this module. If unset, generally
// defaults to libc, libm, and libdl. Set to [] to prevent using headers from the defaults.
@@ -116,9 +118,9 @@
func (*objectLinker) linkerInit(ctx BaseModuleContext) {}
func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
- deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs...)
- deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs...)
- deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs...)
+ deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs.GetOrDefault(ctx, nil)...)
+ deps.SharedLibs = append(deps.SharedLibs, object.Properties.Shared_libs.GetOrDefault(ctx, nil)...)
+ deps.StaticLibs = append(deps.StaticLibs, object.Properties.Static_libs.GetOrDefault(ctx, nil)...)
deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...)
deps.SystemSharedLibs = object.Properties.System_shared_libs
@@ -201,8 +203,9 @@
return outputFile
}
-func (object *objectLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
- specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs...)
+func (object *objectLinker) linkerSpecifiedDeps(ctx android.ConfigurableEvaluatorContext, module *Module, specifiedDeps specifiedDeps) specifiedDeps {
+ eval := module.ConfigurableEvaluator(ctx)
+ specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, object.Properties.Shared_libs.GetOrDefault(eval, nil)...)
// Must distinguish nil and [] in system_shared_libs - ensure that [] in
// either input list doesn't come out as nil.
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index e023a32..299fb51 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,6 +16,7 @@
import (
"path/filepath"
+ "strings"
"github.com/google/blueprint/proptools"
@@ -48,7 +49,7 @@
Source_module_name *string
// a prebuilt library or binary. Can reference a genrule module that generates an executable file.
- Srcs []string `android:"path,arch_variant"`
+ Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
Sanitized Sanitized `android:"arch_variant"`
@@ -75,10 +76,6 @@
return &p.Prebuilt
}
-func (p *prebuiltLinker) PrebuiltSrcs() []string {
- return p.properties.Srcs
-}
-
type prebuiltLibraryInterface interface {
libraryInterface
prebuiltLinkerInterface
@@ -99,10 +96,6 @@
return p.libraryDecorator.linkerDeps(ctx, deps)
}
-func (p *prebuiltLibraryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- return flags
-}
-
func (p *prebuiltLibraryLinker) linkerProps() []interface{} {
return p.libraryDecorator.linkerProps()
}
@@ -121,6 +114,30 @@
// TODO(ccross): verify shared library dependencies
srcs := p.prebuiltSrcs(ctx)
+ stubInfo := addStubDependencyProviders(ctx)
+
+ // Stub variants will create a stub .so file from stub .c files
+ 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.
+
+ // The map.txt files of libclang_rt.* contain version information, but the checked in .so files do not.
+ // e.g. libclang_rt.* libs impl
+ // $ nm -D prebuilts/../libclang_rt.hwasan-aarch64-android.so
+ // __hwasan_init
+
+ // stubs generated from .map.txt
+ // $ nm -D out/soong/.intermediates/../<stubs>/libclang_rt.hwasan-aarch64-android.so
+ // __hwasan_init@@LIBCLANG_RT_ASAN
+
+ // Special-case libclang_rt.* libs to account for this discrepancy.
+ // TODO (spandandas): Remove this special case https://r.android.com/3236596 has been submitted, and a new set of map.txt
+ // files of libclang_rt.* libs have been generated.
+ if strings.Contains(ctx.ModuleName(), "libclang_rt.") {
+ p.versionScriptPath = android.OptionalPathForPath(nil)
+ }
+ return p.linkShared(ctx, flags, deps, objs)
+ }
+
if len(srcs) > 0 {
if len(srcs) > 1 {
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
@@ -207,6 +224,16 @@
return outputFile
}
+ } else if p.shared() && len(stubInfo) > 0 {
+ // This is a prebuilt which does not have any implementation (nil `srcs`), but provides APIs.
+ // Provide the latest (i.e. `current`) stubs to reverse dependencies.
+ latestStub := stubInfo[len(stubInfo)-1].SharedLibraryInfo.SharedLibrary
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
+ SharedLibrary: latestStub,
+ Target: ctx.Target(),
+ })
+
+ return latestStub
}
if p.header() {
@@ -226,14 +253,14 @@
func (p *prebuiltLibraryLinker) prebuiltSrcs(ctx android.BaseModuleContext) []string {
sanitize := ctx.Module().(*Module).sanitize
- srcs := p.properties.Srcs
+ srcs := p.properties.Srcs.GetOrDefault(ctx, nil)
srcs = append(srcs, srcsForSanitizer(sanitize, p.properties.Sanitized)...)
if p.static() {
- srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...)
+ srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs.GetOrDefault(ctx, nil)...)
srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.StaticProperties.Static.Sanitized)...)
}
if p.shared() {
- srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...)
+ srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs.GetOrDefault(ctx, nil)...)
srcs = append(srcs, srcsForSanitizer(sanitize, p.libraryDecorator.SharedProperties.Shared.Sanitized)...)
}
return srcs
@@ -248,7 +275,7 @@
}
func (p *prebuiltLibraryLinker) disablePrebuilt() {
- p.properties.Srcs = nil
+ p.properties.Srcs = proptools.NewConfigurable[[]string](nil, nil)
p.properties.Sanitized.None.Srcs = nil
p.properties.Sanitized.Address.Srcs = nil
p.properties.Sanitized.Hwaddress.Srcs = nil
@@ -261,11 +288,11 @@
func NewPrebuiltLibrary(hod android.HostOrDeviceSupported, srcsProperty string) (*Module, *libraryDecorator) {
module, library := NewLibrary(hod)
- module.compiler = nil
prebuilt := &prebuiltLibraryLinker{
libraryDecorator: library,
}
+ module.compiler = prebuilt
module.linker = prebuilt
module.library = prebuilt
@@ -284,6 +311,13 @@
return module, library
}
+func (p *prebuiltLibraryLinker) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
+ if p.buildStubs() && p.stubsVersion() != "" {
+ return p.compileModuleLibApiStubs(ctx, flags, deps)
+ }
+ return Objects{}
+}
+
// cc_prebuilt_library installs a precompiled shared library that are
// listed in the srcs property in the device's directory.
func PrebuiltLibraryFactory() android.Module {
@@ -416,7 +450,7 @@
func (p *prebuiltBinaryLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
// TODO(ccross): verify shared library dependencies
- if len(p.properties.Srcs) > 0 {
+ if len(p.properties.Srcs.GetOrDefault(ctx, nil)) > 0 {
fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
in := p.Prebuilt.SingleSourcePath(ctx)
outputFile := android.PathForModuleOut(ctx, fileName)
@@ -500,7 +534,7 @@
module.AddProperties(&prebuilt.properties)
- android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
+ android.InitConfigurablePrebuiltModule(module, &prebuilt.properties.Srcs)
return module, binary
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 86e6af9..acbbabc 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -476,11 +476,7 @@
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
android.RegisterApexContributionsBuildComponents(ctx)
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
)
ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
"libbar.so": nil,
@@ -574,11 +570,7 @@
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
android.RegisterApexContributionsBuildComponents(ctx)
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
)
if tc.expectedErr != "" {
preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedErr))
@@ -638,11 +630,7 @@
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
android.RegisterApexContributionsBuildComponents(ctx)
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
)
ctx := testPrebuilt(t, bp, map[string][]byte{
"libbar.so": nil,
diff --git a/cc/sabi.go b/cc/sabi.go
index 64eab41..2caf0d4 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -84,8 +84,8 @@
type SAbiProperties struct {
// Whether ABI dump should be created for this module.
- // Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static
- // library that is depended on by an ABI checked library.
+ // Set by `sabiTransitionMutator` if this module is a shared library that needs ABI check,
+ // or a static library that is depended on by an ABI checked library.
ShouldCreateSourceAbiDump bool `blueprint:"mutated"`
// Include directories that may contain ABI information exported by a library.
@@ -121,10 +121,9 @@
}
// Returns a slice of strings that represent the ABI dumps generated for this module.
-func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag {
+func classifySourceAbiDump(m *Module) []lsdumpTag {
result := []lsdumpTag{}
- m := ctx.Module().(*Module)
- headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := m.library.getHeaderAbiCheckerProperties(m)
if headerAbiChecker.explicitlyDisabled() {
return result
}
@@ -149,24 +148,37 @@
return result
}
-// Called from sabiDepsMutator to check whether ABI dumps should be created for this module.
+type shouldCreateAbiDumpContext interface {
+ android.ModuleProviderContext
+ Module() android.Module
+ Config() android.Config
+}
+
+var _ shouldCreateAbiDumpContext = android.ModuleContext(nil)
+var _ shouldCreateAbiDumpContext = android.OutgoingTransitionContext(nil)
+
+// Called from sabiTransitionMutator to check whether ABI dumps should be created for this module.
// ctx should be wrapping a native library type module.
-func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool {
- // Only generate ABI dump for device modules.
- if !ctx.Device() {
+func shouldCreateSourceAbiDumpForLibrary(ctx shouldCreateAbiDumpContext) bool {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
return false
}
- m := ctx.Module().(*Module)
+ // Only generate ABI dump for device modules.
+ if !m.Device() {
+ return false
+ }
// Only create ABI dump for native library module types.
if m.library == nil {
return false
}
- // Create ABI dump for static libraries only if they are dependencies of ABI checked libraries.
+ // Don't create ABI dump for static libraries
+ // The sabi variant will be propagated to dependencies of ABI checked libraries.
if m.library.static() {
- return m.sabi.shouldCreateSourceAbiDump()
+ return false
}
// Module is shared library type.
@@ -215,31 +227,64 @@
return false
}
}
- return len(classifySourceAbiDump(ctx)) > 0
+ return len(classifySourceAbiDump(m)) > 0
}
// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
// of their dependencies would be generated.
-func sabiDepsMutator(mctx android.TopDownMutatorContext) {
+type sabiTransitionMutator struct{}
+
+func (s *sabiTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{""}
+}
+
+func (s *sabiTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
// Escape hatch to not check any ABI dump.
- if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
- return
+ if ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+ return ""
}
+
// Only create ABI dump for native shared libraries and their static library dependencies.
- if m, ok := mctx.Module().(*Module); ok && m.sabi != nil {
- if shouldCreateSourceAbiDumpForLibrary(mctx) {
- // Mark this module so that .sdump / .lsdump for this library can be generated.
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ if shouldCreateSourceAbiDumpForLibrary(ctx) {
+ if IsStaticDepTag(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
+ return "sabi"
+ }
+ } else if sourceVariation == "sabi" {
+ if IsWholeStaticLib(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
+ return "sabi"
+ }
+ }
+ }
+
+ return ""
+}
+
+func (s *sabiTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if incomingVariation == "" {
+ return ""
+ }
+
+ if incomingVariation == "sabi" {
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ return "sabi"
+ }
+ }
+
+ return ""
+}
+
+func (s *sabiTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ if variation == "sabi" {
m.sabi.Properties.ShouldCreateSourceAbiDump = true
- // Mark all of its static library dependencies.
- mctx.VisitDirectDeps(func(child android.Module) {
- depTag := mctx.OtherModuleDependencyTag(child)
- if IsStaticDepTag(depTag) || depTag == reuseObjTag {
- if c, ok := child.(*Module); ok && c.sabi != nil {
- // Mark this module so that .sdump for this static library can be generated.
- c.sabi.Properties.ShouldCreateSourceAbiDump = true
- }
- }
- })
+ m.HideFromMake()
+ m.Properties.PreventInstall = true
+ } else if shouldCreateSourceAbiDumpForLibrary(ctx) {
+ // Escape hatch to not check any ABI dump.
+ if !ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+ m.sabi.Properties.ShouldCreateSourceAbiDump = true
+ }
}
}
}
diff --git a/cc/sabi_test.go b/cc/sabi_test.go
new file mode 100644
index 0000000..6b8cc17
--- /dev/null
+++ b/cc/sabi_test.go
@@ -0,0 +1,66 @@
+// 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 cc
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestSabi(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libsabi",
+ srcs: ["sabi.cpp"],
+ static_libs: ["libdirect"],
+ header_abi_checker: {
+ enabled: true,
+ symbol_file: "libsabi.map.txt",
+ ref_dump_dirs: ["abi-dumps"],
+ },
+ }
+
+ cc_library {
+ name: "libdirect",
+ srcs: ["direct.cpp"],
+ whole_static_libs: ["libtransitive"],
+ }
+
+ cc_library {
+ name: "libtransitive",
+ srcs: ["transitive.cpp"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithCcDefaultModules,
+ ).RunTestWithBp(t, bp)
+
+ libsabiStatic := result.ModuleForTests("libsabi", "android_arm64_armv8-a_static_sabi")
+ sabiObjSDump := libsabiStatic.Output("obj/sabi.sdump")
+
+ libDirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static_sabi")
+ directObjSDump := libDirect.Output("obj/direct.sdump")
+
+ libTransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static_sabi")
+ transitiveObjSDump := libTransitive.Output("obj/transitive.sdump")
+
+ libsabiShared := result.ModuleForTests("libsabi", "android_arm64_armv8-a_shared")
+ sabiLink := libsabiShared.Rule("sAbiLink")
+
+ android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), sabiObjSDump.Output.String())
+ android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), directObjSDump.Output.String())
+ android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), transitiveObjSDump.Output.String())
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 64a313b..7f52ce1 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -79,8 +79,6 @@
minimalRuntimeFlags = []string{"-fsanitize-minimal-runtime", "-fno-sanitize-trap=integer,undefined",
"-fno-sanitize-recover=integer,undefined"}
- hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
- "export_memory_stats=0", "max_malloc_fill_size=131072", "malloc_fill_byte=0"}
memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"}
@@ -178,7 +176,7 @@
switch t {
case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack:
sanitizer := &sanitizerSplitMutator{t}
- ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
+ ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
ctx.Transition(t.variationName(), sanitizer)
case Memtag_heap, Memtag_globals, intOverflow:
// do nothing
@@ -1155,7 +1153,7 @@
// If an APEX is sanitized or not depends on whether it contains at least one
// sanitized module. Transition mutators cannot propagate information up the
// dependency graph this way, so we need an auxiliary mutator to do so.
-func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.TopDownMutatorContext) {
+func (s *sanitizerSplitMutator) markSanitizableApexesMutator(ctx android.BottomUpMutatorContext) {
if sanitizeable, ok := ctx.Module().(Sanitizeable); ok {
enabled := sanitizeable.IsSanitizerEnabled(ctx.Config(), s.sanitizer.name())
ctx.VisitDirectDeps(func(dep android.Module) {
@@ -1357,7 +1355,7 @@
}
// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
-func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
+func sanitizerRuntimeDepsMutator(mctx android.BottomUpMutatorContext) {
// Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers.
if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
if c.sanitize.Properties.ForceDisable {
@@ -1439,11 +1437,11 @@
//"null",
//"shift-base",
//"signed-integer-overflow",
- // TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
- // https://llvm.org/PR19302
- // http://reviews.llvm.org/D6974
- // "object-size",
)
+
+ if mctx.Config().ReleaseBuildObjectSizeSanitizer() {
+ sanitizers = append(sanitizers, "object-size")
+ }
}
sanitizers = append(sanitizers, sanProps.Misc_undefined...)
}
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 44f38e1..a1cfb5c 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -47,7 +47,7 @@
`))
type providerInterface interface {
- android.SingletonModuleProviderContext
+ android.OtherModuleProviderContext
}
// expectSharedLinkDep verifies that the from module links against the to module as a
@@ -55,7 +55,7 @@
func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)
+ toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)
if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); !android.InList(w, g) {
t.Errorf("%s should link against %s, expected %q, got %q",
@@ -68,7 +68,7 @@
func expectNoSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)
+ toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)
if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); android.InList(w, g) {
t.Errorf("%s should not link against %s, expected %q, got %q",
@@ -81,7 +81,7 @@
func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)
+ toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)
if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); !android.InList(w, g) {
t.Errorf("%s should link against %s, expected %q, got %q",
@@ -95,7 +95,7 @@
func expectNoStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)
+ toInfo, _ := android.OtherModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)
if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); android.InList(w, g) {
t.Errorf("%s should not link against %s, expected %q, got %q",
@@ -794,47 +794,47 @@
android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_with_ubsan static libs",
strings.Split(binWithUbsan.Rule("ld").Args["libFlags"], " "),
- minimalRuntime.OutputFiles(t, "")[0].String())
+ minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())
android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in bin_depends_ubsan_static static libs",
strings.Split(binDependsUbsan.Rule("ld").Args["libFlags"], " "),
- minimalRuntime.OutputFiles(t, "")[0].String())
+ minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())
android.AssertStringListContains(t, "missing libclang_rt.ubsan_minimal in libsharedubsan static libs",
strings.Split(libSharedUbsan.Rule("ld").Args["libFlags"], " "),
- minimalRuntime.OutputFiles(t, "")[0].String())
+ minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())
android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_depends_ubsan_shared static libs",
strings.Split(binDependsUbsanShared.Rule("ld").Args["libFlags"], " "),
- minimalRuntime.OutputFiles(t, "")[0].String())
+ minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())
android.AssertStringListDoesNotContain(t, "unexpected libclang_rt.ubsan_minimal in bin_no_ubsan static libs",
strings.Split(binNoUbsan.Rule("ld").Args["libFlags"], " "),
- minimalRuntime.OutputFiles(t, "")[0].String())
+ minimalRuntime.OutputFiles(result.TestContext, t, "")[0].String())
android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_with_ubsan",
strings.Split(binWithUbsan.Rule("ld").Args["ldFlags"], " "),
- "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+ "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())
android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan_static static libs",
strings.Split(binDependsUbsan.Rule("ld").Args["ldFlags"], " "),
- "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+ "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())
android.AssertStringListContains(t, "missing -Wl,--exclude-libs for minimal runtime in libsharedubsan static libs",
strings.Split(libSharedUbsan.Rule("ld").Args["ldFlags"], " "),
- "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+ "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())
android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_depends_ubsan_shared static libs",
strings.Split(binDependsUbsanShared.Rule("ld").Args["ldFlags"], " "),
- "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+ "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())
android.AssertStringListDoesNotContain(t, "unexpected -Wl,--exclude-libs for minimal runtime in bin_no_ubsan static libs",
strings.Split(binNoUbsan.Rule("ld").Args["ldFlags"], " "),
- "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
+ "-Wl,--exclude-libs="+minimalRuntime.OutputFiles(result.TestContext, t, "")[0].Base())
android.AssertStringListContains(t, "missing libclang_rt.ubsan_standalone.static in static_bin_with_ubsan_dep static libs",
strings.Split(staticBin.Rule("ld").Args["libFlags"], " "),
- standaloneRuntime.OutputFiles(t, "")[0].String())
+ standaloneRuntime.OutputFiles(result.TestContext, t, "")[0].String())
}
diff --git a/cc/sdk.go b/cc/sdk.go
index dc1261d..5dd44d8 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -51,13 +51,6 @@
return []string{""}
}
}
- case *CcApiVariant:
- ccApiVariant, _ := ctx.Module().(*CcApiVariant)
- if String(ccApiVariant.properties.Variant) == "ndk" {
- return []string{"sdk"}
- } else {
- return []string{""}
- }
}
return []string{""}
@@ -84,11 +77,6 @@
return incomingVariation
}
}
- case *CcApiVariant:
- ccApiVariant, _ := ctx.Module().(*CcApiVariant)
- if String(ccApiVariant.properties.Variant) == "ndk" {
- return "sdk"
- }
}
if ctx.IsAddingDependency() {
diff --git a/cc/stl.go b/cc/stl.go
index de2066f..8c4ef0b 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -177,7 +177,7 @@
} else {
deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
}
- deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
+ deps.StaticLibs = append(deps.StaticLibs, "libunwind")
default:
panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
}
diff --git a/cc/stub_library.go b/cc/stub_library.go
index 47c6cb9..e746a33 100644
--- a/cc/stub_library.go
+++ b/cc/stub_library.go
@@ -39,8 +39,9 @@
}
// Get target file name to be installed from this module
-func getInstalledFileName(m *Module) string {
- for _, ps := range m.PackagingSpecs() {
+func getInstalledFileName(ctx android.SingletonContext, m *Module) string {
+ for _, ps := range android.OtherModuleProviderOrDefault(
+ ctx, m.Module(), android.InstallFilesProvider).PackagingSpecs {
if name := ps.FileName(); name != "" {
return name
}
@@ -53,14 +54,14 @@
ctx.VisitAllModules(func(module android.Module) {
if m, ok := module.(*Module); ok {
if IsStubTarget(m) {
- if name := getInstalledFileName(m); name != "" {
+ if name := getInstalledFileName(ctx, m); name != "" {
s.stubLibraryMap[name] = true
if m.InVendor() {
s.stubVendorLibraryMap[name] = true
}
}
}
- if m.library != nil {
+ if m.library != nil && android.IsModulePreferred(m) {
if p := m.library.getAPIListCoverageXMLPath().String(); p != "" {
s.apiListCoverageXmlPaths = append(s.apiListCoverageXmlPaths, p)
}
diff --git a/cc/testing.go b/cc/testing.go
index 02f9924..14a6b7a 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -20,7 +20,6 @@
"android/soong/android"
"android/soong/genrule"
- "android/soong/multitree"
)
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
@@ -29,17 +28,12 @@
RegisterBinaryBuildComponents(ctx)
RegisterLibraryBuildComponents(ctx)
RegisterLibraryHeadersBuildComponents(ctx)
- RegisterLibraryStubBuildComponents(ctx)
-
- multitree.RegisterApiImportsModule(ctx)
ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
ctx.RegisterModuleType("cc_object", ObjectFactory)
ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
- ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
- ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
}
@@ -312,6 +306,25 @@
],
}
cc_library {
+ name: "ndk_libc++_shared",
+ export_include_dirs: ["ndk_libc++_shared_include_dirs"],
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ stl: "none",
+ vendor_available: true,
+ vendor_ramdisk_available: true,
+ product_available: true,
+ recovery_available: true,
+ host_supported: false,
+ sdk_version: "minimum",
+ double_loadable: true,
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ }
+ cc_library {
name: "libc++demangle",
no_libcrt: true,
nocrt: true,
@@ -397,13 +410,6 @@
name: "libprotobuf-cpp-lite",
}
- cc_library {
- name: "ndk_libunwind",
- sdk_version: "minimum",
- stl: "none",
- system_shared_libs: [],
- }
-
ndk_library {
name: "libc",
first_version: "minimum",
@@ -422,11 +428,6 @@
symbol_file: "libdl.map.txt",
}
- ndk_prebuilt_shared_stl {
- name: "ndk_libc++_shared",
- export_include_dirs: ["ndk_libc++_shared"],
- }
-
cc_library_static {
name: "libgoogle-benchmark",
sdk_version: "current",
@@ -557,13 +558,6 @@
RegisterLlndkLibraryTxtType(ctx)
}),
-
- // 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 a cc module type.
- android.MockFS{
- // Needed for ndk_prebuilt_(shared|static)_stl.
- "defaults/cc/common/current/sources/cxx-stl/llvm-libc++/libs": nil,
- }.AddToFixture(),
)
// Preparer that will define default cc modules, e.g. standard prebuilt modules.
@@ -572,17 +566,17 @@
// Additional files needed in tests that disallow non-existent source.
android.MockFS{
- "defaults/cc/common/libc.map.txt": nil,
- "defaults/cc/common/libdl.map.txt": nil,
- "defaults/cc/common/libft2.map.txt": nil,
- "defaults/cc/common/libm.map.txt": nil,
- "defaults/cc/common/ndk_libc++_shared": nil,
- "defaults/cc/common/crtbegin_so.c": nil,
- "defaults/cc/common/crtbegin.c": nil,
- "defaults/cc/common/crtend_so.c": nil,
- "defaults/cc/common/crtend.c": nil,
- "defaults/cc/common/crtbrand.c": nil,
- "external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
+ "defaults/cc/common/libc.map.txt": nil,
+ "defaults/cc/common/libdl.map.txt": nil,
+ "defaults/cc/common/libft2.map.txt": nil,
+ "defaults/cc/common/libm.map.txt": nil,
+ "defaults/cc/common/ndk_libc++_shared_include_dirs": nil,
+ "defaults/cc/common/crtbegin_so.c": nil,
+ "defaults/cc/common/crtbegin.c": nil,
+ "defaults/cc/common/crtend_so.c": nil,
+ "defaults/cc/common/crtend.c": nil,
+ "defaults/cc/common/crtbrand.c": nil,
+ "external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a": nil,
@@ -715,7 +709,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)
- outputFiles := mod.OutputFiles(t, "")
+ outputFiles := mod.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Errorf("%q must have single output\n", moduleName)
return
diff --git a/cmd/extract_apks/bundle_proto/Android.bp b/cmd/extract_apks/bundle_proto/Android.bp
index e56c0fb..0abf1e2 100644
--- a/cmd/extract_apks/bundle_proto/Android.bp
+++ b/cmd/extract_apks/bundle_proto/Android.bp
@@ -10,4 +10,8 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//tools/mainline:__subpackages__",
+ ],
}
diff --git a/cmd/release_config/release_config_contributions/Android.bp b/cmd/release_config/release_config_contributions/Android.bp
new file mode 100644
index 0000000..6882ea2
--- /dev/null
+++ b/cmd/release_config/release_config_contributions/Android.bp
@@ -0,0 +1,32 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "release-config-contributions",
+ deps: [
+ "golang-protobuf-encoding-prototext",
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ "soong-cmd-release_config-proto",
+ "soong-cmd-release_config-lib",
+ ],
+ srcs: [
+ "main.go",
+ ],
+}
+
+bootstrap_go_package {
+ name: "soong-cmd-release_config-release_config_contributions",
+ pkgPath: "android/soong/cmd/release_config/release_config_contributions",
+ deps: [
+ "golang-protobuf-encoding-prototext",
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ "soong-cmd-release_config-proto",
+ "soong-cmd-release_config-lib",
+ ],
+ srcs: [
+ "main.go",
+ ],
+}
diff --git a/cmd/release_config/release_config_contributions/main.go b/cmd/release_config/release_config_contributions/main.go
new file mode 100644
index 0000000..a954cf1
--- /dev/null
+++ b/cmd/release_config/release_config_contributions/main.go
@@ -0,0 +1,130 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "slices"
+ "strings"
+
+ rc_lib "android/soong/cmd/release_config/release_config_lib"
+ rc_proto "android/soong/cmd/release_config/release_config_proto"
+)
+
+type Flags struct {
+ // The path to the top of the workspace. Default: ".".
+ top string
+
+ // Output file.
+ output string
+
+ // Format for output file
+ format string
+
+ // List of release config directories to process.
+ dirs rc_lib.StringList
+
+ // Disable warning messages
+ quiet bool
+
+ // Panic on errors.
+ debug bool
+}
+
+func sortDirectories(dirList []string) {
+ order := func(dir string) int {
+ switch {
+ // These three are always in this order.
+ case dir == "build/release":
+ return 1
+ case dir == "vendor/google_shared/build/release":
+ return 2
+ case dir == "vendor/google/release":
+ return 3
+ // Keep their subdirs in the same order.
+ case strings.HasPrefix(dir, "build/release/"):
+ return 21
+ case strings.HasPrefix(dir, "vendor/google_shared/build/release/"):
+ return 22
+ case strings.HasPrefix(dir, "vendor/google/release/"):
+ return 23
+ // Everything else sorts by directory path.
+ default:
+ return 99
+ }
+ }
+
+ slices.SortFunc(dirList, func(a, b string) int {
+ aOrder, bOrder := order(a), order(b)
+ if aOrder != bOrder {
+ return aOrder - bOrder
+ }
+ return strings.Compare(a, b)
+ })
+}
+
+func main() {
+ var flags Flags
+ topDir, err := rc_lib.GetTopDir()
+
+ // Handle the common arguments
+ flag.StringVar(&flags.top, "top", topDir, "path to top of workspace")
+ flag.Var(&flags.dirs, "dir", "path to a release config contribution directory. May be repeated")
+ flag.StringVar(&flags.format, "format", "pb", "output file format")
+ flag.StringVar(&flags.output, "output", "release_config_contributions.pb", "output file")
+ flag.BoolVar(&flags.debug, "debug", false, "turn on debugging output for errors")
+ flag.BoolVar(&flags.quiet, "quiet", false, "disable warning messages")
+ flag.Parse()
+
+ errorExit := func(err error) {
+ if flags.debug {
+ panic(err)
+ }
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+
+ if flags.quiet {
+ rc_lib.DisableWarnings()
+ }
+
+ if err = os.Chdir(flags.top); err != nil {
+ errorExit(err)
+ }
+
+ contributingDirsMap := make(map[string][]string)
+ for _, dir := range flags.dirs {
+ contributions, err := rc_lib.EnumerateReleaseConfigs(dir)
+ if err != nil {
+ errorExit(err)
+ }
+ for _, name := range contributions {
+ contributingDirsMap[name] = append(contributingDirsMap[name], dir)
+ }
+ }
+
+ releaseConfigNames := []string{}
+ for name := range contributingDirsMap {
+ releaseConfigNames = append(releaseConfigNames, name)
+ }
+ slices.Sort(releaseConfigNames)
+
+ message := &rc_proto.ReleaseConfigContributionsArtifacts{
+ ReleaseConfigContributionsArtifactList: []*rc_proto.ReleaseConfigContributionsArtifact{},
+ }
+ for _, name := range releaseConfigNames {
+ dirs := contributingDirsMap[name]
+ sortDirectories(dirs)
+ message.ReleaseConfigContributionsArtifactList = append(
+ message.ReleaseConfigContributionsArtifactList,
+ &rc_proto.ReleaseConfigContributionsArtifact{
+ Name: &name,
+ ContributingDirectories: dirs,
+ })
+ }
+
+ err = rc_lib.WriteFormattedMessage(flags.output, flags.format, message)
+ if err != nil {
+ errorExit(err)
+ }
+}
diff --git a/cmd/release_config/release_config_lib/flag_artifact.go b/cmd/release_config/release_config_lib/flag_artifact.go
index 93c50cd..51c02d2 100644
--- a/cmd/release_config/release_config_lib/flag_artifact.go
+++ b/cmd/release_config/release_config_lib/flag_artifact.go
@@ -102,7 +102,7 @@
if description := fa.FlagDeclaration.GetDescription(); description != "" {
ret.Description = proto.String(description)
}
- if workflow := fa.FlagDeclaration.GetWorkflow(); workflow != rc_proto.Workflow_Workflow_Unspecified {
+ if workflow := fa.FlagDeclaration.GetWorkflow(); workflow != rc_proto.Workflow_WORKFLOW_UNSPECIFIED {
ret.Workflow = &workflow
}
if containers := fa.FlagDeclaration.GetContainers(); containers != nil {
diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go
index 97eb8f1..831ec02 100644
--- a/cmd/release_config/release_config_lib/release_configs.go
+++ b/cmd/release_config/release_config_lib/release_configs.go
@@ -248,6 +248,18 @@
return configs.configDirs[index], nil
}
+// Return the (unsorted) release configs contributed to by `dir`.
+func EnumerateReleaseConfigs(dir string) ([]string, error) {
+ var ret []string
+ err := WalkTextprotoFiles(dir, "release_configs", func(path string, d fs.DirEntry, err error) error {
+ // Strip off the trailing `.textproto` from the name.
+ name := filepath.Base(path)
+ ret = append(ret, name[:len(name)-10])
+ return err
+ })
+ return ret, err
+}
+
func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error {
if _, err := os.Stat(path); err != nil {
return fmt.Errorf("%s does not exist\n", path)
diff --git a/cmd/release_config/release_config_proto/Android.bp b/cmd/release_config/release_config_proto/Android.bp
index c34d203..c6869b1 100644
--- a/cmd/release_config/release_config_proto/Android.bp
+++ b/cmd/release_config/release_config_proto/Android.bp
@@ -28,5 +28,6 @@
"build_flags_declarations.pb.go",
"build_flags_src.pb.go",
"build_flags_out.pb.go",
+ "release_configs_contributions.pb.go",
],
}
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 82fbcfa..f8ad38f 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
@@ -38,6 +38,8 @@
type Workflow int32
const (
+ Workflow_WORKFLOW_UNSPECIFIED Workflow = 0
+ // Deprecated. Use WORKFLOW_UNSPECIFIED instead.
Workflow_Workflow_Unspecified Workflow = 0
// Boolean value flags that progress from false to true.
Workflow_LAUNCH Workflow = 1
@@ -52,12 +54,14 @@
// Enum value maps for Workflow.
var (
Workflow_name = map[int32]string{
- 0: "Workflow_Unspecified",
+ 0: "WORKFLOW_UNSPECIFIED",
+ // Duplicate value: 0: "Workflow_Unspecified",
1: "LAUNCH",
2: "PREBUILT",
3: "MANUAL",
}
Workflow_value = map[string]int32{
+ "WORKFLOW_UNSPECIFIED": 0,
"Workflow_Unspecified": 0,
"LAUNCH": 1,
"PREBUILT": 2,
@@ -108,15 +112,17 @@
0x0a, 0x18, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x6f,
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 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, 0x2a, 0x4a, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b,
- 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
- 0x5f, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0a,
- 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52,
- 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55,
- 0x41, 0x4c, 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,
+ 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x68, 0x0a, 0x08, 0x57, 0x6f, 0x72, 0x6b,
+ 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57,
+ 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18,
+ 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x55, 0x6e, 0x73, 0x70, 0x65,
+ 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e,
+ 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54,
+ 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x1a, 0x02,
+ 0x10, 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 (
@@ -133,7 +139,7 @@
var file_build_flags_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_build_flags_common_proto_goTypes = []interface{}{
- (Workflow)(0), // 0: android.release_config_proto.workflow
+ (Workflow)(0), // 0: android.release_config_proto.Workflow
}
var file_build_flags_common_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
diff --git a/cmd/release_config/release_config_proto/build_flags_common.proto b/cmd/release_config/release_config_proto/build_flags_common.proto
index d5d6101..cd9f1e0 100644
--- a/cmd/release_config/release_config_proto/build_flags_common.proto
+++ b/cmd/release_config/release_config_proto/build_flags_common.proto
@@ -20,7 +20,11 @@
// This protobuf file defines common messages used in the rest of the build flag
// protos.
-enum workflow {
+enum Workflow {
+ option allow_alias = true;
+ WORKFLOW_UNSPECIFIED = 0;
+
+ // Deprecated. Use WORKFLOW_UNSPECIFIED instead.
Workflow_Unspecified = 0;
// Boolean value flags that progress from false to true.
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 d2de89a..7db945a 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
@@ -121,7 +121,7 @@
if x != nil && x.Workflow != nil {
return *x.Workflow
}
- return Workflow_Workflow_Unspecified
+ return Workflow_WORKFLOW_UNSPECIFIED
}
func (x *FlagDeclarationArtifact) GetContainers() []string {
@@ -187,37 +187,37 @@
0x12, 0x1c, 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, 0x1a, 0x18,
0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
- 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8e, 0x02, 0x0a, 0x19, 0x66, 0x6c, 0x61,
- 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 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, 0x1c, 0x0a, 0x09, 0x6e, 0x61,
- 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e,
- 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65,
- 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x50, 0x61, 0x74, 0x68, 0x12, 0x43, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
- 0x77, 0x18, 0xcd, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 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, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
- 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x6f,
- 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0xce, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
- 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10,
- 0x05, 0x4a, 0x06, 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22, 0x9a, 0x01, 0x0a, 0x1a, 0x66, 0x6c,
- 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61,
- 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x7c, 0x0a, 0x1e, 0x66, 0x6c, 0x61, 0x67,
- 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x74,
- 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x37, 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,
- 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x1b, 0x66, 0x6c, 0x61, 0x67, 0x44,
- 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61,
- 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 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, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8c, 0x02, 0x0a, 0x17, 0x46, 0x6c, 0x61,
+ 0x67, 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 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, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d,
+ 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, 0x63, 0x6c,
+ 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50,
+ 0x61, 0x74, 0x68, 0x12, 0x43, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18,
+ 0xcd, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 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, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x08,
+ 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0xce, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63,
+ 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a,
+ 0x06, 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22, 0x96, 0x01, 0x0a, 0x18, 0x46, 0x6c, 0x61, 0x67,
+ 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x74, 0x69, 0x66,
+ 0x61, 0x63, 0x74, 0x73, 0x12, 0x7a, 0x0a, 0x1e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63,
+ 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63,
+ 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 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, 0x46, 0x6c, 0x61, 0x67,
+ 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x74, 0x69, 0x66,
+ 0x61, 0x63, 0x74, 0x52, 0x1b, 0x66, 0x6c, 0x61, 0x67, 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74,
+ 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 (
@@ -234,13 +234,13 @@
var file_build_flags_declarations_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_build_flags_declarations_proto_goTypes = []interface{}{
- (*FlagDeclarationArtifact)(nil), // 0: android.release_config_proto.flag_declaration_artifact
- (*FlagDeclarationArtifacts)(nil), // 1: android.release_config_proto.flag_declaration_artifacts
- (Workflow)(0), // 2: android.release_config_proto.workflow
+ (*FlagDeclarationArtifact)(nil), // 0: android.release_config_proto.FlagDeclarationArtifact
+ (*FlagDeclarationArtifacts)(nil), // 1: android.release_config_proto.FlagDeclarationArtifacts
+ (Workflow)(0), // 2: android.release_config_proto.Workflow
}
var file_build_flags_declarations_proto_depIdxs = []int32{
- 2, // 0: android.release_config_proto.flag_declaration_artifact.workflow:type_name -> android.release_config_proto.workflow
- 0, // 1: android.release_config_proto.flag_declaration_artifacts.flag_declaration_artifact_list:type_name -> android.release_config_proto.flag_declaration_artifact
+ 2, // 0: android.release_config_proto.FlagDeclarationArtifact.workflow:type_name -> android.release_config_proto.Workflow
+ 0, // 1: android.release_config_proto.FlagDeclarationArtifacts.flag_declaration_artifact_list:type_name -> android.release_config_proto.FlagDeclarationArtifact
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
diff --git a/cmd/release_config/release_config_proto/build_flags_declarations.proto b/cmd/release_config/release_config_proto/build_flags_declarations.proto
index 233158e..d755e02 100644
--- a/cmd/release_config/release_config_proto/build_flags_declarations.proto
+++ b/cmd/release_config/release_config_proto/build_flags_declarations.proto
@@ -39,7 +39,7 @@
// com.android.mypackage is a valid name while com.android.myPackage,
// com.android.1mypackage are invalid
-message flag_declaration_artifact {
+message FlagDeclarationArtifact {
// The name of the flag.
// See # name for format detail
optional string name = 1;
@@ -58,7 +58,7 @@
optional string declaration_path = 5;
// Workflow for this flag.
- optional workflow workflow = 205;
+ optional Workflow workflow = 205;
// The container for this flag. This overrides any default container given
// in the release_config_map message.
@@ -69,7 +69,7 @@
reserved 207;
}
-message flag_declaration_artifacts {
+message FlagDeclarationArtifacts {
// The artifacts
- repeated flag_declaration_artifact flag_declaration_artifact_list = 1;
+ repeated FlagDeclarationArtifact flag_declaration_artifact_list = 1;
}
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 c63ea26..60ba2e1 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
@@ -399,89 +399,88 @@
0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61,
0x67, 0x73, 0x5f, 0x73, 0x72, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x60, 0x0a, 0x0a,
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f,
+ 0x54, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x23, 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, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xe8,
- 0x01, 0x0a, 0x0d, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74,
- 0x12, 0x59, 0x0a, 0x10, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 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, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64,
- 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x66, 0x6c, 0x61, 0x67,
- 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65,
- 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xe6,
+ 0x01, 0x0a, 0x0c, 0x46, 0x6c, 0x61, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12,
+ 0x58, 0x0a, 0x10, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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, 0x46, 0x6c, 0x61, 0x67, 0x44, 0x65, 0x63,
+ 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x66, 0x6c, 0x61, 0x67, 0x44, 0x65,
+ 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18,
+ 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 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, 0x54, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52,
+ 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x61, 0x0a, 0x0d, 0x46, 0x6c, 0x61, 0x67, 0x41,
+ 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67,
+ 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, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e,
- 0x74, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x0e, 0x66, 0x6c, 0x61,
- 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x66,
- 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 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, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61,
- 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, 0xdd,
- 0x02, 0x0a, 0x17, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x5f, 0x61, 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, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20,
- 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12,
- 0x41, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b,
- 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, 0x66, 0x6c,
- 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x05, 0x66, 0x6c, 0x61,
- 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10,
- 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73,
- 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b,
- 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
- 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x21,
- 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x18, 0x07,
- 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x67, 0x65,
- 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63,
- 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x52, 0x0e,
- 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xe8,
- 0x03, 0x0a, 0x18, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x5c, 0x0a, 0x0e, 0x72,
- 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x65,
- 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 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, 0x35, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 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, 0xda, 0x02, 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,
+ 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x05, 0x66, 0x6c, 0x61,
+ 0x67, 0x73, 0x18, 0x03, 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, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f,
- 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 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, 0x87, 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, 0x50, 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, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x73, 0x5f, 0x61, 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, 0x79,
- 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, 0x46, 0x0a,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x72, 0x65, 0x6c, 0x65,
- 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 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,
+ 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, 0x12, 0x2c, 0x0a, 0x12, 0x61,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74,
+ 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x68,
+ 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x68,
+ 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x6f, 0x72,
+ 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70,
+ 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x67, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18,
+ 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 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 (
@@ -498,27 +497,27 @@
var file_build_flags_out_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_build_flags_out_proto_goTypes = []interface{}{
- (*Tracepoint)(nil), // 0: android.release_config_proto.tracepoint
- (*FlagArtifact)(nil), // 1: android.release_config_proto.flag_artifact
- (*FlagArtifacts)(nil), // 2: android.release_config_proto.flag_artifacts
- (*ReleaseConfigArtifact)(nil), // 3: android.release_config_proto.release_config_artifact
- (*ReleaseConfigsArtifact)(nil), // 4: android.release_config_proto.release_configs_artifact
- nil, // 5: android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry
- (*Value)(nil), // 6: android.release_config_proto.value
- (*FlagDeclaration)(nil), // 7: android.release_config_proto.flag_declaration
- (*ReleaseConfigMap)(nil), // 8: android.release_config_proto.release_config_map
+ (*Tracepoint)(nil), // 0: android.release_config_proto.Tracepoint
+ (*FlagArtifact)(nil), // 1: android.release_config_proto.FlagArtifact
+ (*FlagArtifacts)(nil), // 2: android.release_config_proto.FlagArtifacts
+ (*ReleaseConfigArtifact)(nil), // 3: android.release_config_proto.ReleaseConfigArtifact
+ (*ReleaseConfigsArtifact)(nil), // 4: android.release_config_proto.ReleaseConfigsArtifact
+ nil, // 5: android.release_config_proto.ReleaseConfigsArtifact.ReleaseConfigMapsMapEntry
+ (*Value)(nil), // 6: android.release_config_proto.Value
+ (*FlagDeclaration)(nil), // 7: android.release_config_proto.FlagDeclaration
+ (*ReleaseConfigMap)(nil), // 8: android.release_config_proto.ReleaseConfigMap
}
var file_build_flags_out_proto_depIdxs = []int32{
- 6, // 0: android.release_config_proto.tracepoint.value:type_name -> android.release_config_proto.value
- 7, // 1: android.release_config_proto.flag_artifact.flag_declaration:type_name -> android.release_config_proto.flag_declaration
- 6, // 2: android.release_config_proto.flag_artifact.value:type_name -> android.release_config_proto.value
- 0, // 3: android.release_config_proto.flag_artifact.traces:type_name -> android.release_config_proto.tracepoint
- 1, // 4: android.release_config_proto.flag_artifacts.flags:type_name -> android.release_config_proto.flag_artifact
- 1, // 5: android.release_config_proto.release_config_artifact.flags:type_name -> android.release_config_proto.flag_artifact
- 3, // 6: android.release_config_proto.release_configs_artifact.release_config:type_name -> android.release_config_proto.release_config_artifact
- 3, // 7: android.release_config_proto.release_configs_artifact.other_release_configs:type_name -> android.release_config_proto.release_config_artifact
- 5, // 8: android.release_config_proto.release_configs_artifact.release_config_maps_map:type_name -> android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry
- 8, // 9: android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry.value:type_name -> android.release_config_proto.release_config_map
+ 6, // 0: android.release_config_proto.Tracepoint.value:type_name -> android.release_config_proto.Value
+ 7, // 1: android.release_config_proto.FlagArtifact.flag_declaration:type_name -> android.release_config_proto.FlagDeclaration
+ 6, // 2: android.release_config_proto.FlagArtifact.value:type_name -> android.release_config_proto.Value
+ 0, // 3: android.release_config_proto.FlagArtifact.traces:type_name -> android.release_config_proto.Tracepoint
+ 1, // 4: android.release_config_proto.FlagArtifacts.flags:type_name -> android.release_config_proto.FlagArtifact
+ 1, // 5: android.release_config_proto.ReleaseConfigArtifact.flags:type_name -> android.release_config_proto.FlagArtifact
+ 3, // 6: android.release_config_proto.ReleaseConfigsArtifact.release_config:type_name -> android.release_config_proto.ReleaseConfigArtifact
+ 3, // 7: android.release_config_proto.ReleaseConfigsArtifact.other_release_configs:type_name -> android.release_config_proto.ReleaseConfigArtifact
+ 5, // 8: android.release_config_proto.ReleaseConfigsArtifact.release_config_maps_map:type_name -> android.release_config_proto.ReleaseConfigsArtifact.ReleaseConfigMapsMapEntry
+ 8, // 9: android.release_config_proto.ReleaseConfigsArtifact.ReleaseConfigMapsMapEntry.value:type_name -> android.release_config_proto.ReleaseConfigMap
10, // [10:10] is the sub-list for method output_type
10, // [10:10] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension type_name
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 4dc84e9..2ab62d1 100644
--- a/cmd/release_config/release_config_proto/build_flags_out.proto
+++ b/cmd/release_config/release_config_proto/build_flags_out.proto
@@ -39,30 +39,30 @@
// com.android.mypackage is a valid name while com.android.myPackage,
// com.android.1mypackage are invalid
-message tracepoint {
+message Tracepoint {
// Path to declaration or value file relative to $TOP
optional string source = 1;
- optional value value = 201;
+ optional Value value = 201;
}
-message flag_artifact {
+message FlagArtifact {
// The original declaration
- optional flag_declaration flag_declaration = 1;
+ optional FlagDeclaration flag_declaration = 1;
// Value for the flag
- optional value value = 201;
+ optional Value value = 201;
// Trace of where the flag value was assigned.
- repeated tracepoint traces = 8;
+ repeated Tracepoint traces = 8;
}
-message flag_artifacts {
+message FlagArtifacts {
// The artifacts
- repeated flag_artifact flags = 1;
+ repeated FlagArtifact flags = 1;
reserved "flag_artifacts";
}
-message release_config_artifact {
+message ReleaseConfigArtifact {
// The name of the release config.
// See # name for format detail
optional string name = 1;
@@ -72,7 +72,7 @@
// The complete set of build flags in this release config, after all
// inheritance and other processing is complete.
- repeated flag_artifact flags = 3;
+ repeated FlagArtifact flags = 3;
reserved "flag_artifacts";
// The (complete) list of aconfig_value_sets Soong modules to use.
@@ -98,14 +98,14 @@
repeated string value_directories = 8;
}
-message release_configs_artifact {
+message ReleaseConfigsArtifact {
// The active release config for this build.
- optional release_config_artifact release_config = 1;
+ optional ReleaseConfigArtifact release_config = 1;
// All other release configs defined for this TARGET_PRODUCT.
- repeated release_config_artifact other_release_configs = 2;
+ repeated ReleaseConfigArtifact other_release_configs = 2;
// Map of release_config_artifact.directories to release_config_map message.
- map<string, release_config_map> release_config_maps_map = 3;
+ map<string, ReleaseConfigMap> release_config_maps_map = 3;
}
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 bc5f5c0..d784dee 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
@@ -232,7 +232,7 @@
if x != nil && x.Workflow != nil {
return *x.Workflow
}
- return Workflow_Workflow_Unspecified
+ return Workflow_WORKFLOW_UNSPECIFIED
}
func (x *FlagDeclaration) GetContainers() []string {
@@ -531,7 +531,7 @@
0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x61,
0x67, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
- 0xa5, 0x01, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x11, 0x75, 0x6e, 0x73,
+ 0xa5, 0x01, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x11, 0x75, 0x6e, 0x73,
0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc8,
0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x10, 0x75, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69,
0x66, 0x69, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x24, 0x0a, 0x0c, 0x73, 0x74, 0x72,
@@ -541,62 +541,62 @@
0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x12, 0x1d, 0x0a, 0x08, 0x6f, 0x62, 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x18, 0xcb, 0x01,
0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x62, 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65,
- 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x96, 0x02, 0x0a, 0x10, 0x66, 0x6c, 0x61, 0x67,
- 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20,
- 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x95, 0x02, 0x0a, 0x0f, 0x46, 0x6c, 0x61, 0x67,
+ 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
+ 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a,
+ 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+ 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x23, 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, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x08, 0x77,
+ 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0xcd, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26,
+ 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, 0x57, 0x6f,
+ 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
+ 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0xce,
+ 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
+ 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x06, 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22,
+ 0x78, 0x0a, 0x09, 0x46, 0x6c, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x23, 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,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x08,
- 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0xcd, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
- 0x26, 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, 0x77,
- 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
- 0x77, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18,
- 0xce, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
- 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x06, 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01,
- 0x22, 0x79, 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x23, 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, 0x76, 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, 0xbf, 0x01, 0x0a, 0x0e,
- 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 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, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x2c,
- 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f,
- 0x73, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12,
- 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6f, 0x6e,
- 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72,
- 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
- 0x52, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x67, 0x65, 0x73, 0x22, 0x3b, 0x0a,
- 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 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, 0xac, 0x01, 0x0a, 0x12, 0x72,
- 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61,
- 0x70, 0x12, 0x45, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x2b, 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, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 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, 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,
+ 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, 0xbe, 0x01, 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, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74,
+ 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6c,
+ 0x61, 0x67, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x6f, 0x72,
+ 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70,
+ 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x67, 0x65, 0x73, 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, 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 (
@@ -613,19 +613,19 @@
var file_build_flags_src_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_build_flags_src_proto_goTypes = []interface{}{
- (*Value)(nil), // 0: android.release_config_proto.value
- (*FlagDeclaration)(nil), // 1: android.release_config_proto.flag_declaration
- (*FlagValue)(nil), // 2: android.release_config_proto.flag_value
- (*ReleaseConfig)(nil), // 3: android.release_config_proto.release_config
- (*ReleaseAlias)(nil), // 4: android.release_config_proto.release_alias
- (*ReleaseConfigMap)(nil), // 5: android.release_config_proto.release_config_map
- (Workflow)(0), // 6: android.release_config_proto.workflow
+ (*Value)(nil), // 0: android.release_config_proto.Value
+ (*FlagDeclaration)(nil), // 1: android.release_config_proto.FlagDeclaration
+ (*FlagValue)(nil), // 2: android.release_config_proto.FlagValue
+ (*ReleaseConfig)(nil), // 3: android.release_config_proto.ReleaseConfig
+ (*ReleaseAlias)(nil), // 4: android.release_config_proto.ReleaseAlias
+ (*ReleaseConfigMap)(nil), // 5: android.release_config_proto.ReleaseConfigMap
+ (Workflow)(0), // 6: android.release_config_proto.Workflow
}
var file_build_flags_src_proto_depIdxs = []int32{
- 0, // 0: android.release_config_proto.flag_declaration.value:type_name -> android.release_config_proto.value
- 6, // 1: android.release_config_proto.flag_declaration.workflow:type_name -> android.release_config_proto.workflow
- 0, // 2: android.release_config_proto.flag_value.value:type_name -> android.release_config_proto.value
- 4, // 3: android.release_config_proto.release_config_map.aliases:type_name -> android.release_config_proto.release_alias
+ 0, // 0: android.release_config_proto.FlagDeclaration.value:type_name -> android.release_config_proto.Value
+ 6, // 1: android.release_config_proto.FlagDeclaration.workflow:type_name -> android.release_config_proto.Workflow
+ 0, // 2: android.release_config_proto.FlagValue.value:type_name -> android.release_config_proto.Value
+ 4, // 3: android.release_config_proto.ReleaseConfigMap.aliases:type_name -> android.release_config_proto.ReleaseAlias
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
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 4fad478..e1925bc 100644
--- a/cmd/release_config/release_config_proto/build_flags_src.proto
+++ b/cmd/release_config/release_config_proto/build_flags_src.proto
@@ -44,7 +44,7 @@
// com.android.mypackage is a valid name while com.android.myPackage,
// com.android.1mypackage are invalid
-message value {
+message Value {
oneof val {
bool unspecified_value = 200;
string string_value = 201;
@@ -55,7 +55,7 @@
}
// The proto used in the source tree.
-message flag_declaration {
+message FlagDeclaration {
// The name of the flag.
// See # name for format detail
optional string name = 1;
@@ -71,10 +71,10 @@
reserved 4;
// Value for the flag
- optional value value = 201;
+ optional Value value = 201;
// Workflow for this flag.
- optional workflow workflow = 205;
+ optional Workflow workflow = 205;
// The container for this flag. This overrides any default container given
// in the release_config_map message.
@@ -85,13 +85,13 @@
reserved 207;
}
-message flag_value {
+message FlagValue {
// Name of the flag.
// See # name for format detail
optional string name = 2;
// Value for the flag
- optional value value = 201;
+ optional Value value = 201;
// If true, the flag is completely removed from the release config as if
// never declared.
@@ -99,7 +99,7 @@
}
// This replaces $(call declare-release-config).
-message release_config {
+message ReleaseConfig {
// The name of the release config.
// See # name for format detail
optional string name = 1;
@@ -120,7 +120,7 @@
}
// Any aliases. These are used for continuous integration builder config.
-message release_alias {
+message ReleaseAlias {
// The name of the alias.
optional string name = 1;
@@ -129,9 +129,9 @@
}
// This provides the data from release_config_map.mk
-message release_config_map {
+message ReleaseConfigMap {
// Any aliases.
- repeated release_alias aliases = 1;
+ repeated ReleaseAlias aliases = 1;
// Description of this map and its intended use.
optional string description = 2;
diff --git a/cmd/release_config/release_config_proto/regen.sh b/cmd/release_config/release_config_proto/regen.sh
index 23e3115..a92bfc0 100644
--- a/cmd/release_config/release_config_proto/regen.sh
+++ b/cmd/release_config/release_config_proto/regen.sh
@@ -1,3 +1,3 @@
#!/bin/bash
-aprotoc --go_out=paths=source_relative:. build_flags_src.proto build_flags_out.proto build_flags_common.proto build_flags_declarations.proto
+aprotoc --go_out=paths=source_relative:. build_flags_src.proto build_flags_out.proto build_flags_common.proto build_flags_declarations.proto release_configs_contributions.proto
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
new file mode 100644
index 0000000..54854f1
--- /dev/null
+++ b/cmd/release_config/release_config_proto/release_configs_contributions.pb.go
@@ -0,0 +1,252 @@
+//
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.33.0
+// protoc v3.21.12
+// source: release_configs_contributions.proto
+
+package release_config_proto
+
+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 ReleaseConfigContributionsArtifact struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The name of the release config.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // The release config contribution directories that may contribute to this
+ // release config.
+ ContributingDirectories []string `protobuf:"bytes,2,rep,name=contributing_directories,json=contributingDirectories" json:"contributing_directories,omitempty"`
+}
+
+func (x *ReleaseConfigContributionsArtifact) Reset() {
+ *x = ReleaseConfigContributionsArtifact{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_release_configs_contributions_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ReleaseConfigContributionsArtifact) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReleaseConfigContributionsArtifact) ProtoMessage() {}
+
+func (x *ReleaseConfigContributionsArtifact) ProtoReflect() protoreflect.Message {
+ mi := &file_release_configs_contributions_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 ReleaseConfigContributionsArtifact.ProtoReflect.Descriptor instead.
+func (*ReleaseConfigContributionsArtifact) Descriptor() ([]byte, []int) {
+ return file_release_configs_contributions_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ReleaseConfigContributionsArtifact) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *ReleaseConfigContributionsArtifact) GetContributingDirectories() []string {
+ if x != nil {
+ return x.ContributingDirectories
+ }
+ return nil
+}
+
+type ReleaseConfigContributionsArtifacts struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The artifacts
+ ReleaseConfigContributionsArtifactList []*ReleaseConfigContributionsArtifact `protobuf:"bytes,1,rep,name=release_config_contributions_artifact_list,json=releaseConfigContributionsArtifactList" json:"release_config_contributions_artifact_list,omitempty"`
+}
+
+func (x *ReleaseConfigContributionsArtifacts) Reset() {
+ *x = ReleaseConfigContributionsArtifacts{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_release_configs_contributions_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ReleaseConfigContributionsArtifacts) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReleaseConfigContributionsArtifacts) ProtoMessage() {}
+
+func (x *ReleaseConfigContributionsArtifacts) ProtoReflect() protoreflect.Message {
+ mi := &file_release_configs_contributions_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 ReleaseConfigContributionsArtifacts.ProtoReflect.Descriptor instead.
+func (*ReleaseConfigContributionsArtifacts) Descriptor() ([]byte, []int) {
+ return file_release_configs_contributions_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ReleaseConfigContributionsArtifacts) GetReleaseConfigContributionsArtifactList() []*ReleaseConfigContributionsArtifact {
+ if x != nil {
+ return x.ReleaseConfigContributionsArtifactList
+ }
+ return nil
+}
+
+var File_release_configs_contributions_proto protoreflect.FileDescriptor
+
+var file_release_configs_contributions_proto_rawDesc = []byte{
+ 0x0a, 0x23, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 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, 0x22, 0x73, 0x0a, 0x22, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 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, 0x39, 0x0a,
+ 0x18, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
+ 0x17, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x69, 0x72,
+ 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x22, 0xc4, 0x01, 0x0a, 0x23, 0x52, 0x65, 0x6c,
+ 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69,
+ 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73,
+ 0x12, 0x9c, 0x01, 0x0a, 0x2a, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 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, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x41,
+ 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x26, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 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 (
+ file_release_configs_contributions_proto_rawDescOnce sync.Once
+ file_release_configs_contributions_proto_rawDescData = file_release_configs_contributions_proto_rawDesc
+)
+
+func file_release_configs_contributions_proto_rawDescGZIP() []byte {
+ file_release_configs_contributions_proto_rawDescOnce.Do(func() {
+ file_release_configs_contributions_proto_rawDescData = protoimpl.X.CompressGZIP(file_release_configs_contributions_proto_rawDescData)
+ })
+ return file_release_configs_contributions_proto_rawDescData
+}
+
+var file_release_configs_contributions_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_release_configs_contributions_proto_goTypes = []interface{}{
+ (*ReleaseConfigContributionsArtifact)(nil), // 0: android.release_config_proto.ReleaseConfigContributionsArtifact
+ (*ReleaseConfigContributionsArtifacts)(nil), // 1: android.release_config_proto.ReleaseConfigContributionsArtifacts
+}
+var file_release_configs_contributions_proto_depIdxs = []int32{
+ 0, // 0: android.release_config_proto.ReleaseConfigContributionsArtifacts.release_config_contributions_artifact_list:type_name -> android.release_config_proto.ReleaseConfigContributionsArtifact
+ 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_release_configs_contributions_proto_init() }
+func file_release_configs_contributions_proto_init() {
+ if File_release_configs_contributions_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_release_configs_contributions_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ReleaseConfigContributionsArtifact); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_release_configs_contributions_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ReleaseConfigContributionsArtifacts); 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_release_configs_contributions_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_release_configs_contributions_proto_goTypes,
+ DependencyIndexes: file_release_configs_contributions_proto_depIdxs,
+ MessageInfos: file_release_configs_contributions_proto_msgTypes,
+ }.Build()
+ File_release_configs_contributions_proto = out.File
+ file_release_configs_contributions_proto_rawDesc = nil
+ file_release_configs_contributions_proto_goTypes = nil
+ file_release_configs_contributions_proto_depIdxs = nil
+}
diff --git a/cmd/release_config/release_config_proto/release_configs_contributions.proto b/cmd/release_config/release_config_proto/release_configs_contributions.proto
new file mode 100644
index 0000000..bc7aeda
--- /dev/null
+++ b/cmd/release_config/release_config_proto/release_configs_contributions.proto
@@ -0,0 +1,32 @@
+//
+// 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.
+
+syntax = "proto2";
+package android.release_config_proto;
+option go_package = "android/soong/release_config/release_config_proto";
+
+message ReleaseConfigContributionsArtifact {
+ // The name of the release config.
+ optional string name = 1;
+
+ // The release config contribution directories that may contribute to this
+ // release config.
+ repeated string contributing_directories = 2;
+}
+
+message ReleaseConfigContributionsArtifacts {
+ // The artifacts
+ repeated ReleaseConfigContributionsArtifact release_config_contributions_artifact_list = 1;
+}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index e69a930..f3931a4 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -27,6 +27,7 @@
"os"
"os/exec"
"path/filepath"
+ "regexp"
"strconv"
"strings"
"time"
@@ -51,6 +52,8 @@
sandboxDirPlaceholder = "__SBOX_SANDBOX_DIR__"
)
+var envVarNameRegex = regexp.MustCompile("^[a-zA-Z0-9_-]+$")
+
func init() {
flag.StringVar(&sandboxesRoot, "sandbox-path", "",
"root of temp directory to put the sandbox into")
@@ -238,6 +241,51 @@
return &manifest, nil
}
+func createEnv(command *sbox_proto.Command) ([]string, error) {
+ env := []string{}
+ if command.DontInheritEnv == nil || !*command.DontInheritEnv {
+ env = os.Environ()
+ }
+ for _, envVar := range command.Env {
+ if envVar.Name == nil || !envVarNameRegex.MatchString(*envVar.Name) {
+ name := "nil"
+ if envVar.Name != nil {
+ name = *envVar.Name
+ }
+ return nil, fmt.Errorf("Invalid environment variable name: %q", name)
+ }
+ if envVar.State == nil {
+ return nil, fmt.Errorf("Must set state")
+ }
+ switch state := envVar.State.(type) {
+ case *sbox_proto.EnvironmentVariable_Value:
+ env = append(env, *envVar.Name+"="+state.Value)
+ case *sbox_proto.EnvironmentVariable_Unset:
+ if !state.Unset {
+ return nil, fmt.Errorf("Can't have unset set to false")
+ }
+ prefix := *envVar.Name + "="
+ for i := 0; i < len(env); i++ {
+ if strings.HasPrefix(env[i], prefix) {
+ env = append(env[:i], env[i+1:]...)
+ i--
+ }
+ }
+ case *sbox_proto.EnvironmentVariable_Inherit:
+ if !state.Inherit {
+ return nil, fmt.Errorf("Can't have inherit set to false")
+ }
+ val, ok := os.LookupEnv(*envVar.Name)
+ if ok {
+ env = append(env, *envVar.Name+"="+val)
+ }
+ default:
+ return nil, fmt.Errorf("Unhandled state type")
+ }
+ }
+ return env, nil
+}
+
// runCommand runs a single command from a manifest. If the command references the
// __SBOX_DEPFILE__ placeholder it returns the name of the depfile that was used.
func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (depFile string, err error) {
@@ -313,6 +361,12 @@
return "", fmt.Errorf("Failed to update PATH: %w", err)
}
}
+
+ cmd.Env, err = createEnv(command)
+ if err != nil {
+ return "", err
+ }
+
err = cmd.Run()
if err != nil {
diff --git a/cmd/sbox/sbox_proto/sbox.pb.go b/cmd/sbox/sbox_proto/sbox.pb.go
index 7c84f2c..271039c 100644
--- a/cmd/sbox/sbox_proto/sbox.pb.go
+++ b/cmd/sbox/sbox_proto/sbox.pb.go
@@ -14,8 +14,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.26.0
-// protoc v3.9.1
+// protoc-gen-go v1.33.0
+// protoc v3.21.12
// source: sbox.proto
package sbox_proto
@@ -116,6 +116,13 @@
// A list of files that will be copied before the sandboxed command, and whose contents should be
// copied as if they were listed in copy_before.
RspFiles []*RspFile `protobuf:"bytes,6,rep,name=rsp_files,json=rspFiles" json:"rsp_files,omitempty"`
+ // The environment variables that will be set or unset while running the command.
+ // Also see dont_inherit_env.
+ Env []*EnvironmentVariable `protobuf:"bytes,7,rep,name=env" json:"env,omitempty"`
+ // By default, all environment variables are inherited from the calling process, but may be
+ // replaced or unset by env. If dont_inherit_env is set, no environment variables will be
+ // inherited, and instead only the variables in env will be defined.
+ DontInheritEnv *bool `protobuf:"varint,8,opt,name=dont_inherit_env,json=dontInheritEnv" json:"dont_inherit_env,omitempty"`
}
func (x *Command) Reset() {
@@ -192,6 +199,129 @@
return nil
}
+func (x *Command) GetEnv() []*EnvironmentVariable {
+ if x != nil {
+ return x.Env
+ }
+ return nil
+}
+
+func (x *Command) GetDontInheritEnv() bool {
+ if x != nil && x.DontInheritEnv != nil {
+ return *x.DontInheritEnv
+ }
+ return false
+}
+
+type EnvironmentVariable struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The name of the environment variable
+ Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
+ // Types that are assignable to State:
+ //
+ // *EnvironmentVariable_Value
+ // *EnvironmentVariable_Unset
+ // *EnvironmentVariable_Inherit
+ State isEnvironmentVariable_State `protobuf_oneof:"state"`
+}
+
+func (x *EnvironmentVariable) Reset() {
+ *x = EnvironmentVariable{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_sbox_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EnvironmentVariable) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EnvironmentVariable) ProtoMessage() {}
+
+func (x *EnvironmentVariable) ProtoReflect() protoreflect.Message {
+ mi := &file_sbox_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 EnvironmentVariable.ProtoReflect.Descriptor instead.
+func (*EnvironmentVariable) Descriptor() ([]byte, []int) {
+ return file_sbox_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *EnvironmentVariable) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (m *EnvironmentVariable) GetState() isEnvironmentVariable_State {
+ if m != nil {
+ return m.State
+ }
+ return nil
+}
+
+func (x *EnvironmentVariable) GetValue() string {
+ if x, ok := x.GetState().(*EnvironmentVariable_Value); ok {
+ return x.Value
+ }
+ return ""
+}
+
+func (x *EnvironmentVariable) GetUnset() bool {
+ if x, ok := x.GetState().(*EnvironmentVariable_Unset); ok {
+ return x.Unset
+ }
+ return false
+}
+
+func (x *EnvironmentVariable) GetInherit() bool {
+ if x, ok := x.GetState().(*EnvironmentVariable_Inherit); ok {
+ return x.Inherit
+ }
+ return false
+}
+
+type isEnvironmentVariable_State interface {
+ isEnvironmentVariable_State()
+}
+
+type EnvironmentVariable_Value struct {
+ // The value to set the environment variable to.
+ Value string `protobuf:"bytes,2,opt,name=value,oneof"`
+}
+
+type EnvironmentVariable_Unset struct {
+ // This environment variable should be unset in the command.
+ Unset bool `protobuf:"varint,3,opt,name=unset,oneof"`
+}
+
+type EnvironmentVariable_Inherit struct {
+ // This environment variable should be inherited from the parent process.
+ // Can be combined with dont_inherit_env to only inherit certain environment
+ // variables.
+ Inherit bool `protobuf:"varint,4,opt,name=inherit,oneof"`
+}
+
+func (*EnvironmentVariable_Value) isEnvironmentVariable_State() {}
+
+func (*EnvironmentVariable_Unset) isEnvironmentVariable_State() {}
+
+func (*EnvironmentVariable_Inherit) isEnvironmentVariable_State() {}
+
// Copy describes a from-to pair of files to copy. The paths may be relative, the root that they
// are relative to is specific to the context the Copy is used in and will be different for
// from and to.
@@ -209,7 +339,7 @@
func (x *Copy) Reset() {
*x = Copy{}
if protoimpl.UnsafeEnabled {
- mi := &file_sbox_proto_msgTypes[2]
+ mi := &file_sbox_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -222,7 +352,7 @@
func (*Copy) ProtoMessage() {}
func (x *Copy) ProtoReflect() protoreflect.Message {
- mi := &file_sbox_proto_msgTypes[2]
+ mi := &file_sbox_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -235,7 +365,7 @@
// Deprecated: Use Copy.ProtoReflect.Descriptor instead.
func (*Copy) Descriptor() ([]byte, []int) {
- return file_sbox_proto_rawDescGZIP(), []int{2}
+ return file_sbox_proto_rawDescGZIP(), []int{3}
}
func (x *Copy) GetFrom() string {
@@ -274,7 +404,7 @@
func (x *RspFile) Reset() {
*x = RspFile{}
if protoimpl.UnsafeEnabled {
- mi := &file_sbox_proto_msgTypes[3]
+ mi := &file_sbox_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -287,7 +417,7 @@
func (*RspFile) ProtoMessage() {}
func (x *RspFile) ProtoReflect() protoreflect.Message {
- mi := &file_sbox_proto_msgTypes[3]
+ mi := &file_sbox_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -300,7 +430,7 @@
// Deprecated: Use RspFile.ProtoReflect.Descriptor instead.
func (*RspFile) Descriptor() ([]byte, []int) {
- return file_sbox_proto_rawDescGZIP(), []int{3}
+ return file_sbox_proto_rawDescGZIP(), []int{4}
}
func (x *RspFile) GetFile() string {
@@ -330,7 +460,7 @@
func (x *PathMapping) Reset() {
*x = PathMapping{}
if protoimpl.UnsafeEnabled {
- mi := &file_sbox_proto_msgTypes[4]
+ mi := &file_sbox_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -343,7 +473,7 @@
func (*PathMapping) ProtoMessage() {}
func (x *PathMapping) ProtoReflect() protoreflect.Message {
- mi := &file_sbox_proto_msgTypes[4]
+ mi := &file_sbox_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -356,7 +486,7 @@
// Deprecated: Use PathMapping.ProtoReflect.Descriptor instead.
func (*PathMapping) Descriptor() ([]byte, []int) {
- return file_sbox_proto_rawDescGZIP(), []int{4}
+ return file_sbox_proto_rawDescGZIP(), []int{5}
}
func (x *PathMapping) GetFrom() string {
@@ -383,7 +513,7 @@
0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x75, 0x74,
0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x70, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x44, 0x65, 0x70, 0x66, 0x69, 0x6c, 0x65,
- 0x22, 0xdc, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2b, 0x0a, 0x0b,
+ 0x22, 0xb3, 0x02, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2b, 0x0a, 0x0b,
0x63, 0x6f, 0x70, 0x79, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x0a, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x0a, 0x63,
0x6f, 0x70, 0x79, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x64,
@@ -396,23 +526,37 @@
0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x48,
0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x09, 0x72, 0x73, 0x70, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x52, 0x73,
- 0x70, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x72, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22,
- 0x4a, 0x0a, 0x04, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18,
- 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74,
- 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x65,
- 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x55, 0x0a, 0x07, 0x52,
- 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01,
- 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x61,
- 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70,
- 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x70, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e,
- 0x67, 0x73, 0x22, 0x31, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e,
- 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52,
- 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28,
- 0x09, 0x52, 0x02, 0x74, 0x6f, 0x42, 0x23, 0x5a, 0x21, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x73, 0x62, 0x6f, 0x78, 0x2f,
- 0x73, 0x62, 0x6f, 0x78, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x70, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x72, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12,
+ 0x2b, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73,
+ 0x62, 0x6f, 0x78, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56,
+ 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x28, 0x0a, 0x10,
+ 0x64, 0x6f, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x5f, 0x65, 0x6e, 0x76,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x64, 0x6f, 0x6e, 0x74, 0x49, 0x6e, 0x68, 0x65,
+ 0x72, 0x69, 0x74, 0x45, 0x6e, 0x76, 0x22, 0x7e, 0x0a, 0x13, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f,
+ 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x16, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x75, 0x6e, 0x73,
+ 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x05, 0x75, 0x6e, 0x73, 0x65,
+ 0x74, 0x12, 0x1a, 0x0a, 0x07, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x42, 0x07, 0x0a,
+ 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x4a, 0x0a, 0x04, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x12,
+ 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72,
+ 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x02,
+ 0x74, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x22, 0x55, 0x0a, 0x07, 0x52, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a,
+ 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c,
+ 0x65, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e,
+ 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x62, 0x6f, 0x78, 0x2e,
+ 0x50, 0x61, 0x74, 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x70, 0x61, 0x74,
+ 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x31, 0x0a, 0x0b, 0x50, 0x61, 0x74,
+ 0x68, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d,
+ 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02,
+ 0x74, 0x6f, 0x18, 0x02, 0x20, 0x02, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x42, 0x23, 0x5a, 0x21,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6d,
+ 0x64, 0x2f, 0x73, 0x62, 0x6f, 0x78, 0x2f, 0x73, 0x62, 0x6f, 0x78, 0x5f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f,
}
var (
@@ -427,25 +571,27 @@
return file_sbox_proto_rawDescData
}
-var file_sbox_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_sbox_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_sbox_proto_goTypes = []interface{}{
- (*Manifest)(nil), // 0: sbox.Manifest
- (*Command)(nil), // 1: sbox.Command
- (*Copy)(nil), // 2: sbox.Copy
- (*RspFile)(nil), // 3: sbox.RspFile
- (*PathMapping)(nil), // 4: sbox.PathMapping
+ (*Manifest)(nil), // 0: sbox.Manifest
+ (*Command)(nil), // 1: sbox.Command
+ (*EnvironmentVariable)(nil), // 2: sbox.EnvironmentVariable
+ (*Copy)(nil), // 3: sbox.Copy
+ (*RspFile)(nil), // 4: sbox.RspFile
+ (*PathMapping)(nil), // 5: sbox.PathMapping
}
var file_sbox_proto_depIdxs = []int32{
1, // 0: sbox.Manifest.commands:type_name -> sbox.Command
- 2, // 1: sbox.Command.copy_before:type_name -> sbox.Copy
- 2, // 2: sbox.Command.copy_after:type_name -> sbox.Copy
- 3, // 3: sbox.Command.rsp_files:type_name -> sbox.RspFile
- 4, // 4: sbox.RspFile.path_mappings:type_name -> sbox.PathMapping
- 5, // [5:5] is the sub-list for method output_type
- 5, // [5:5] is the sub-list for method input_type
- 5, // [5:5] is the sub-list for extension type_name
- 5, // [5:5] is the sub-list for extension extendee
- 0, // [0:5] is the sub-list for field type_name
+ 3, // 1: sbox.Command.copy_before:type_name -> sbox.Copy
+ 3, // 2: sbox.Command.copy_after:type_name -> sbox.Copy
+ 4, // 3: sbox.Command.rsp_files:type_name -> sbox.RspFile
+ 2, // 4: sbox.Command.env:type_name -> sbox.EnvironmentVariable
+ 5, // 5: sbox.RspFile.path_mappings:type_name -> sbox.PathMapping
+ 6, // [6:6] is the sub-list for method output_type
+ 6, // [6:6] is the sub-list for method input_type
+ 6, // [6:6] is the sub-list for extension type_name
+ 6, // [6:6] is the sub-list for extension extendee
+ 0, // [0:6] is the sub-list for field type_name
}
func init() { file_sbox_proto_init() }
@@ -479,7 +625,7 @@
}
}
file_sbox_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Copy); i {
+ switch v := v.(*EnvironmentVariable); i {
case 0:
return &v.state
case 1:
@@ -491,7 +637,7 @@
}
}
file_sbox_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RspFile); i {
+ switch v := v.(*Copy); i {
case 0:
return &v.state
case 1:
@@ -503,6 +649,18 @@
}
}
file_sbox_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RspFile); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_sbox_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PathMapping); i {
case 0:
return &v.state
@@ -515,13 +673,18 @@
}
}
}
+ file_sbox_proto_msgTypes[2].OneofWrappers = []interface{}{
+ (*EnvironmentVariable_Value)(nil),
+ (*EnvironmentVariable_Unset)(nil),
+ (*EnvironmentVariable_Inherit)(nil),
+ }
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_sbox_proto_rawDesc,
NumEnums: 0,
- NumMessages: 5,
+ NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/cmd/sbox/sbox_proto/sbox.proto b/cmd/sbox/sbox_proto/sbox.proto
index 2f0dcf0..1158554 100644
--- a/cmd/sbox/sbox_proto/sbox.proto
+++ b/cmd/sbox/sbox_proto/sbox.proto
@@ -51,6 +51,30 @@
// A list of files that will be copied before the sandboxed command, and whose contents should be
// copied as if they were listed in copy_before.
repeated RspFile rsp_files = 6;
+
+ // The environment variables that will be set or unset while running the command.
+ // Also see dont_inherit_env.
+ repeated EnvironmentVariable env = 7;
+
+ // By default, all environment variables are inherited from the calling process, but may be
+ // replaced or unset by env. If dont_inherit_env is set, no environment variables will be
+ // inherited, and instead only the variables in env will be defined.
+ optional bool dont_inherit_env = 8;
+}
+
+message EnvironmentVariable {
+ // The name of the environment variable
+ required string name = 1;
+ oneof state {
+ // The value to set the environment variable to.
+ string value = 2;
+ // This environment variable should be unset in the command.
+ bool unset = 3;
+ // This environment variable should be inherited from the parent process.
+ // Can be combined with dont_inherit_env to only inherit certain environment
+ // variables.
+ bool inherit = 4;
+ }
}
// Copy describes a from-to pair of files to copy. The paths may be relative, the root that they
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index a8be7ec..5b1ae54 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -15,7 +15,6 @@
package main
import (
- "bytes"
"encoding/json"
"errors"
"flag"
@@ -29,10 +28,12 @@
"android/soong/android/allowlists"
"android/soong/bp2build"
"android/soong/shared"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/deptools"
"github.com/google/blueprint/metrics"
+ "github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
androidProtobuf "google.golang.org/protobuf/android"
)
@@ -42,8 +43,6 @@
availableEnvFile string
usedEnvFile string
- globFile string
- globListDir string
delveListen string
delvePath string
@@ -64,8 +63,6 @@
flag.StringVar(&cmdlineArgs.SoongOutDir, "soong_out", "", "Soong output directory (usually $TOP/out/soong)")
flag.StringVar(&availableEnvFile, "available_env", "", "File containing available environment variables")
flag.StringVar(&usedEnvFile, "used_env", "", "File containing used environment variables")
- flag.StringVar(&globFile, "globFile", "build-globs.ninja", "the Ninja file of globs to output")
- flag.StringVar(&globListDir, "globListDir", "", "the directory containing the glob list files")
flag.StringVar(&cmdlineArgs.OutDir, "out", "", "the ninja builddir directory")
flag.StringVar(&cmdlineArgs.ModuleListFile, "l", "", "file that lists filepaths to parse")
@@ -206,20 +203,6 @@
ctx.Context.PrintJSONGraphAndActions(graphFile, actionsFile)
}
-func writeBuildGlobsNinjaFile(ctx *android.Context) {
- ctx.EventHandler.Begin("globs_ninja_file")
- defer ctx.EventHandler.End("globs_ninja_file")
-
- globDir := bootstrap.GlobDirectory(ctx.Config().SoongOutDir(), globListDir)
- err := bootstrap.WriteBuildGlobsNinjaFile(&bootstrap.GlobSingleton{
- GlobLister: ctx.Globs,
- GlobFile: globFile,
- GlobDir: globDir,
- SrcDir: ctx.SrcDir(),
- }, ctx.Config())
- maybeQuit(err, "")
-}
-
func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDeps []string) {
eventHandler.Begin("ninja_deps")
defer eventHandler.End("ninja_deps")
@@ -229,7 +212,14 @@
}
// Check if there are changes to the environment file, product variable file and
-// soong_build binary, in which case no incremental will be performed.
+// soong_build binary, in which case no incremental will be performed. For env
+// variables we check the used env file, which will be removed in soong ui if
+// there is any changes to the env variables used last time, in which case the
+// check below will fail and a full build will be attempted. If any new env
+// variables are added in the new run, soong ui won't be able to detect it, the
+// used env file check below will pass. But unless there is a soong build code
+// change, in which case the soong build binary check will fail, otherwise the
+// new env variables shouldn't have any affect.
func incrementalValid(config android.Config, configCacheFile string) (*ConfigCache, bool) {
var newConfigCache ConfigCache
data, err := os.ReadFile(shared.JoinPath(topDir, usedEnvFile))
@@ -283,7 +273,9 @@
}
// runSoongOnlyBuild runs the standard Soong build in a number of different modes.
-func runSoongOnlyBuild(ctx *android.Context, extraNinjaDeps []string) string {
+// It returns the path to the output file (usually the ninja file) and the deps that need
+// to trigger a soong rerun.
+func runSoongOnlyBuild(ctx *android.Context) (string, []string) {
ctx.EventHandler.Begin("soong_build")
defer ctx.EventHandler.End("soong_build")
@@ -299,37 +291,30 @@
ninjaDeps, err := bootstrap.RunBlueprint(cmdlineArgs.Args, stopBefore, ctx.Context, ctx.Config())
maybeQuit(err, "")
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
-
- writeBuildGlobsNinjaFile(ctx)
// Convert the Soong module graph into Bazel BUILD files.
switch ctx.Config().BuildMode {
case android.GenerateQueryView:
queryviewMarkerFile := cmdlineArgs.BazelQueryViewDir + ".marker"
runQueryView(cmdlineArgs.BazelQueryViewDir, queryviewMarkerFile, ctx)
- writeDepFile(queryviewMarkerFile, ctx.EventHandler, ninjaDeps)
- return queryviewMarkerFile
+ return queryviewMarkerFile, ninjaDeps
case android.GenerateModuleGraph:
writeJsonModuleGraphAndActions(ctx, cmdlineArgs)
- writeDepFile(cmdlineArgs.ModuleGraphFile, ctx.EventHandler, ninjaDeps)
- return cmdlineArgs.ModuleGraphFile
+ return cmdlineArgs.ModuleGraphFile, ninjaDeps
case android.GenerateDocFile:
// TODO: we could make writeDocs() return the list of documentation files
// written and add them to the .d file. Then soong_docs would be re-run
// whenever one is deleted.
err := writeDocs(ctx, shared.JoinPath(topDir, cmdlineArgs.DocFile))
maybeQuit(err, "error building Soong documentation")
- writeDepFile(cmdlineArgs.DocFile, ctx.EventHandler, ninjaDeps)
- return cmdlineArgs.DocFile
+ return cmdlineArgs.DocFile, ninjaDeps
default:
// The actual output (build.ninja) was written in the RunBlueprint() call
// above
- writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
if needToWriteNinjaHint(ctx) {
writeNinjaHint(ctx)
}
- return cmdlineArgs.OutFile
+ return cmdlineArgs.OutFile, ninjaDeps
}
}
@@ -359,6 +344,8 @@
func main() {
flag.Parse()
+ soongStartTime := time.Now()
+
shared.ReexecWithDelveMaybe(delveListen, delvePath)
android.InitSandbox(topDir)
@@ -369,13 +356,6 @@
configuration.SetAllowMissingDependencies()
}
- extraNinjaDeps := []string{configuration.ProductVariablesFileName, usedEnvFile}
- if shared.IsDebugging() {
- // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
- // enabled even if it completed successfully.
- extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.SoongOutDir(), "always_rerun_for_delve"))
- }
-
// Bypass configuration.Getenv, as LOG_DIR does not need to be dependency tracked. By definition, it will
// change between every CI build, so tracking it would require re-running Soong for every build.
metricsDir := availableEnv["LOG_DIR"]
@@ -393,7 +373,17 @@
ctx.SetIncrementalAnalysis(incremental)
ctx.Register()
- finalOutputFile := runSoongOnlyBuild(ctx, extraNinjaDeps)
+ finalOutputFile, ninjaDeps := runSoongOnlyBuild(ctx)
+
+ ninjaDeps = append(ninjaDeps, configuration.ProductVariablesFileName)
+ ninjaDeps = append(ninjaDeps, usedEnvFile)
+ if shared.IsDebugging() {
+ // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
+ // enabled even if it completed successfully.
+ ninjaDeps = append(ninjaDeps, filepath.Join(configuration.SoongOutDir(), "always_rerun_for_delve"))
+ }
+
+ writeDepFile(finalOutputFile, ctx.EventHandler, ninjaDeps)
if ctx.GetIncrementalEnabled() {
data, err := shared.EnvFileContents(configuration.EnvDeps())
@@ -407,6 +397,9 @@
writeUsedEnvironmentFile(configuration)
+ err = writeGlobFile(ctx.EventHandler, finalOutputFile, ctx.Globs(), soongStartTime)
+ maybeQuit(err, "")
+
// Touch the output file so that it's the newest file created by soong_build.
// This is necessary because, if soong_build generated any files which
// are ninja inputs to the main output file, then ninja would superfluously
@@ -423,18 +416,33 @@
data, err := shared.EnvFileContents(configuration.EnvDeps())
maybeQuit(err, "error writing used environment file '%s'\n", usedEnvFile)
- if preexistingData, err := os.ReadFile(path); err != nil {
- if !os.IsNotExist(err) {
- maybeQuit(err, "error reading used environment file '%s'", usedEnvFile)
- }
- } else if bytes.Equal(preexistingData, data) {
- // used environment file is unchanged
- return
- }
- err = os.WriteFile(path, data, 0666)
+ err = pathtools.WriteFileIfChanged(path, data, 0666)
maybeQuit(err, "error writing used environment file '%s'", usedEnvFile)
}
+func writeGlobFile(eventHandler *metrics.EventHandler, finalOutFile string, globs pathtools.MultipleGlobResults, soongStartTime time.Time) error {
+ eventHandler.Begin("writeGlobFile")
+ defer eventHandler.End("writeGlobFile")
+
+ globsFile, err := os.Create(shared.JoinPath(topDir, finalOutFile+".globs"))
+ if err != nil {
+ return err
+ }
+ defer globsFile.Close()
+ globsFileEncoder := json.NewEncoder(globsFile)
+ for _, glob := range globs {
+ if err := globsFileEncoder.Encode(glob); err != nil {
+ return err
+ }
+ }
+
+ return os.WriteFile(
+ shared.JoinPath(topDir, finalOutFile+".globs_time"),
+ []byte(fmt.Sprintf("%d\n", soongStartTime.UnixMicro())),
+ 0666,
+ )
+}
+
func touch(path string) {
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
maybeQuit(err, "Error touching '%s'", path)
diff --git a/cmd/symbols_map/Android.bp b/cmd/symbols_map/Android.bp
index e3ae6ed..272e806 100644
--- a/cmd/symbols_map/Android.bp
+++ b/cmd/symbols_map/Android.bp
@@ -30,4 +30,5 @@
srcs: [
"symbols_map_proto/symbols_map.pb.go",
],
+ visibility: ["//visibility:public"],
}
diff --git a/cmd/zip2zip/Android.bp b/cmd/zip2zip/Android.bp
index 3ef7668..7f9b165 100644
--- a/cmd/zip2zip/Android.bp
+++ b/cmd/zip2zip/Android.bp
@@ -27,4 +27,6 @@
"zip2zip.go",
],
testSrcs: ["zip2zip_test.go"],
+ // Used by genrules
+ visibility: ["//visibility:public"],
}
diff --git a/compliance/Android.bp b/compliance/Android.bp
new file mode 100644
index 0000000..72c2f27
--- /dev/null
+++ b/compliance/Android.bp
@@ -0,0 +1,39 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-compliance",
+ pkgPath: "android/soong/compliance",
+ deps: [
+ "soong-android",
+ ],
+ srcs: [
+ "notice.go",
+ ],
+ testSrcs: [
+ ],
+ pluginFor: ["soong_build"],
+}
+
+notice_xml {
+ name: "notice_xml_system",
+ partition_name: "system",
+ visibility: [
+ "//build/make/target/product/generic",
+ ],
+}
diff --git a/compliance/license_metadata_proto/Android.bp b/compliance/license_metadata_proto/Android.bp
index 3c041e4..4761285 100644
--- a/compliance/license_metadata_proto/Android.bp
+++ b/compliance/license_metadata_proto/Android.bp
@@ -24,4 +24,8 @@
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
],
+ visibility: [
+ "//build/make/tools/compliance:__subpackages__",
+ "//build/soong:__subpackages__",
+ ],
}
diff --git a/compliance/notice.go b/compliance/notice.go
new file mode 100644
index 0000000..4fc83ab
--- /dev/null
+++ b/compliance/notice.go
@@ -0,0 +1,100 @@
+// 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 compliance
+
+import (
+ "path/filepath"
+
+ "android/soong/android"
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterNoticeXmlBuildComponents(android.InitRegistrationContext)
+}
+
+var PrepareForTestWithNoticeXmlBuildComponents = android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(RegisterNoticeXmlBuildComponents),
+)
+
+var PrepareForTestWithNoticeXml = android.GroupFixturePreparers(
+ PrepareForTestWithNoticeXmlBuildComponents,
+)
+
+func RegisterNoticeXmlBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("notice_xml", NoticeXmlFactory)
+}
+
+var (
+ pctx = android.NewPackageContext("android/soong/compliance")
+
+ genNoticeXml = pctx.HostBinToolVariable("genNoticeXml", "gen_notice_xml")
+
+ // Command to generate NOTICE.xml.gz for a partition
+ genNoticeXmlRule = pctx.AndroidStaticRule("genNoticeXmlRule", blueprint.RuleParams{
+ Command: "rm -rf $out && " +
+ "${genNoticeXml} --output_file ${out} --metadata ${in} --partition ${partition} --product_out ${productOut} --soong_out ${soongOut}",
+ CommandDeps: []string{"${genNoticeXml}"},
+ }, "partition", "productOut", "soongOut")
+)
+
+func NoticeXmlFactory() android.Module {
+ m := &NoticeXmlModule{}
+ m.AddProperties(&m.props)
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibFirst)
+ return m
+}
+
+type NoticeXmlModule struct {
+ android.ModuleBase
+
+ props noticeXmlProperties
+
+ outputFile android.OutputPath
+ installPath android.InstallPath
+}
+
+type noticeXmlProperties struct {
+ Partition_name string
+}
+
+func (nx *NoticeXmlModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ 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,
+ Args: map[string]string{
+ "productOut": filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()),
+ "soongOut": ctx.Config().SoongOutDir(),
+ "partition": nx.props.Partition_name,
+ },
+ })
+
+ nx.outputFile = output.OutputPath
+
+ if android.Bool(ctx.Config().ProductVariables().UseSoongSystemImage) {
+ nx.installPath = android.PathForModuleInPartitionInstall(ctx, nx.props.Partition_name, "etc")
+ ctx.InstallFile(nx.installPath, "NOTICE.xml.gz", nx.outputFile)
+ }
+}
+
+func (nx *NoticeXmlModule) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(nx.outputFile),
+ }}
+}
diff --git a/compliance/notice_test.go b/compliance/notice_test.go
new file mode 100644
index 0000000..6187e53
--- /dev/null
+++ b/compliance/notice_test.go
@@ -0,0 +1,38 @@
+// 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 compliance
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+var prepareForNoticeXmlTest = android.GroupFixturePreparers(
+ android.PrepareForTestWithArchMutator,
+ PrepareForTestWithNoticeXml,
+)
+
+func TestPrebuiltEtcOutputFile(t *testing.T) {
+ result := prepareForNoticeXmlTest.RunTestWithBp(t, `
+ notice_xml {
+ name: "notice_xml_system",
+ partition_name: "system",
+ }
+ `)
+
+ m := result.Module("notice_xml_system", "android_arm64_armv8-a").(*NoticeXmlModule)
+ android.AssertStringEquals(t, "output file", "NOTICE.xml.gz", m.outputFile.Base())
+}
\ No newline at end of file
diff --git a/compliance/project_metadata_proto/Android.bp b/compliance/project_metadata_proto/Android.bp
index 56e76e7..0c807b2 100644
--- a/compliance/project_metadata_proto/Android.bp
+++ b/compliance/project_metadata_proto/Android.bp
@@ -24,4 +24,5 @@
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
],
+ visibility: ["//build/make/tools/compliance:__subpackages__"],
}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index fe6317c..84d4f10 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -191,6 +191,10 @@
ForceCreateAppImage bool
PresignedPrebuilt bool
+
+ // ApexPartition is the partition in which the dexpreopt files of apex system server jars (if any) are installed.
+ // This is a noop unless the module is apex system server jar.
+ ApexPartition string
}
type globalSoongConfigSingleton struct{}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 5616483..7a39fa1 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -219,9 +219,9 @@
}
// Returns the location to the odex file for the dex file at `path`.
-func ToOdexPath(path string, arch android.ArchType) string {
+func ToOdexPath(path string, arch android.ArchType, partition string) string {
if strings.HasPrefix(path, "/apex/") {
- return filepath.Join("/system/framework/oat", arch.String(),
+ return filepath.Join(partition, "framework/oat", arch.String(),
strings.ReplaceAll(path[1:], "/", "@")+"@classes.odex")
}
@@ -245,7 +245,7 @@
odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex"))
odexSymbolsPath := odexPath.ReplaceExtension(ctx, "symbols.odex")
- odexInstallPath := ToOdexPath(module.DexLocation, arch)
+ odexInstallPath := ToOdexPath(module.DexLocation, arch, module.ApexPartition)
if odexOnSystemOther(module, global) {
odexInstallPath = filepath.Join(SystemOtherPartition, odexInstallPath)
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 6f7d3bb..7b0f51f 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -42,12 +42,14 @@
}
func testApexModuleConfig(ctx android.PathContext, name, apexName string) *ModuleConfig {
- return createTestModuleConfig(
+ ret := createTestModuleConfig(
name,
fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, name),
android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)),
android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)),
android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
+ ret.ApexPartition = "/system"
+ return ret
}
func testPlatformSystemServerModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
@@ -221,6 +223,49 @@
DexpreoptRunningInSoong = oldDexpreoptRunningInSoong
}
+// Same as `TestDexPreoptApexSystemServerJars`, but the apex jar is in /system_ext
+func TestDexPreoptApexSystemServerJarsSystemExt(t *testing.T) {
+ // modify the global variable for test
+ var oldDexpreoptRunningInSoong = DexpreoptRunningInSoong
+ DexpreoptRunningInSoong = true
+
+ // test begin
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.BuilderContextForTesting(config)
+ globalSoong := globalSoongConfigForTests(ctx)
+ global := GlobalConfigForTests(ctx)
+ module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
+ module.ApexPartition = "/system_ext"
+ productPackages := android.PathForTesting("product_packages.txt")
+
+ global.ApexSystemServerJars = android.CreateTestConfiguredJarList(
+ []string{"com.android.apex1:service-A"})
+
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wantInstalls := android.RuleBuilderInstalls{
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system_ext/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.odex"},
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system_ext/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.vdex"},
+ }
+
+ 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
+}
+
func TestDexPreoptStandaloneSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
diff --git a/docs/OWNERS b/docs/OWNERS
new file mode 100644
index 0000000..776beca
--- /dev/null
+++ b/docs/OWNERS
@@ -0,0 +1 @@
+per-file map_files.md = danalbert@google.com
diff --git a/docs/map_files.md b/docs/map_files.md
index e1ddefc..8d6af87 100644
--- a/docs/map_files.md
+++ b/docs/map_files.md
@@ -88,12 +88,17 @@
### introduced
-Indicates the version in which an API was first introduced. For example,
-`introduced=21` specifies that the API was first added (or first made public) in
-API level 21. This tag can be applied to either a version definition or an
-individual symbol. If applied to a version, all symbols contained in the version
-will have the tag applied. An `introduced` tag on a symbol overrides the value
-set for the version, if both are defined.
+Indicates the version in which an API was first introduced in the NDK. For
+example, `introduced=21` specifies that the API was first added (or first made
+public) in API level 21. This tag can be applied to either a version definition
+or an individual symbol. If applied to a version, all symbols contained in the
+version will have the tag applied. An `introduced` tag on a symbol overrides the
+value set for the version, if both are defined.
+
+The `introduced` tag should only be used with NDK APIs. Other API surface tags
+(such as `apex`) will override `introduced`. APIs that are in the NDK should
+never use tags like `apex`, and APIs that are not in the NDK should never use
+`introduced`.
Note: The map file alone does not contain all the information needed to
determine which API level an API was added in. The `first_version` property of
diff --git a/docs/tidy.md b/docs/tidy.md
index ae0ca93..2e4c957 100644
--- a/docs/tidy.md
+++ b/docs/tidy.md
@@ -38,7 +38,7 @@
clang-tidy is enabled explicitly and with a different check list:
```
cc_defaults {
- name: "bpf_defaults",
+ name: "bpf_cc_defaults",
// snipped
tidy: true,
tidy_checks: [
@@ -52,7 +52,7 @@
}
```
That means in normal builds, even without `WITH_TIDY=1`,
-the modules that use `bpf_defaults` _should_ run clang-tidy
+the modules that use `bpf_cc_defaults` _should_ run clang-tidy
over C/C++ source files with the given `tidy_checks`.
However since clang-tidy warnings and its runtime cost might
diff --git a/etc/Android.bp b/etc/Android.bp
index f02c12a..580c54f 100644
--- a/etc/Android.bp
+++ b/etc/Android.bp
@@ -20,4 +20,6 @@
"install_symlink_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 5c047bc..8af2ffa 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -79,6 +79,7 @@
generatePartitionAconfigStorageFile("package_map", "package.map")
generatePartitionAconfigStorageFile("flag_map", "flag.map")
generatePartitionAconfigStorageFile("flag_val", "flag.val")
+ generatePartitionAconfigStorageFile("flag_info", "flag.info")
android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 5c7ef43..09d8fba 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -35,9 +35,9 @@
}
func registerBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("android_filesystem", filesystemFactory)
+ ctx.RegisterModuleType("android_filesystem", FilesystemFactory)
ctx.RegisterModuleType("android_filesystem_defaults", filesystemDefaultsFactory)
- ctx.RegisterModuleType("android_system_image", systemImageFactory)
+ ctx.RegisterModuleType("android_system_image", SystemImageFactory)
ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
ctx.RegisterModuleType("avb_add_hash_footer_defaults", avbAddHashFooterDefaultsFactory)
ctx.RegisterModuleType("avb_gen_vbmeta_image", avbGenVbmetaImageFactory)
@@ -49,7 +49,7 @@
android.PackagingBase
android.DefaultableModuleBase
- properties filesystemProperties
+ properties FilesystemProperties
// Function that builds extra files under the root directory and returns the files
buildExtraFiles func(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths
@@ -71,7 +71,7 @@
Name *string
}
-type filesystemProperties struct {
+type FilesystemProperties struct {
// When set to true, sign the image with avbtool. Default is false.
Use_avb *bool
@@ -137,6 +137,12 @@
Gen_aconfig_flags_pb *bool
Fsverity fsverityProperties
+
+ // If this property is set to true, the filesystem will call ctx.UncheckedModule(), causing
+ // it to not be built on checkbuilds. Used for the automatic migration from make to soong
+ // build modules, where we want to emit some not-yet-working filesystems and we don't want them
+ // to be built.
+ Unchecked_module *bool `blueprint:"mutated"`
}
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -144,17 +150,17 @@
// modules in the filesystem image are built for the target device (i.e. Android, not Linux host).
// The modules are placed in the filesystem image just like they are installed to the ordinary
// partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory.
-func filesystemFactory() android.Module {
+func FilesystemFactory() android.Module {
module := &filesystem{}
module.filterPackagingSpec = module.filterInstallablePackagingSpec
- initFilesystemModule(module)
+ initFilesystemModule(module, module)
return module
}
-func initFilesystemModule(module *filesystem) {
- module.AddProperties(&module.properties)
- android.InitPackageModule(module)
- module.PackagingBase.DepsCollectFirstTargetOnly = true
+func initFilesystemModule(module android.DefaultableModule, filesystemModule *filesystem) {
+ module.AddProperties(&filesystemModule.properties)
+ android.InitPackageModule(filesystemModule)
+ filesystemModule.PackagingBase.DepsCollectFirstTargetOnly = true
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
}
@@ -177,6 +183,13 @@
unknown
)
+type FilesystemInfo struct {
+ // A text file containing the list of paths installed on the partition.
+ FileListFile android.Path
+}
+
+var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]()
+
func (f *filesystem) fsType(ctx android.ModuleContext) fsType {
typeStr := proptools.StringDefault(f.properties.Type, "ext4")
switch typeStr {
@@ -227,6 +240,14 @@
f.fileListFile = android.PathForModuleOut(ctx, "fileList").OutputPath
android.WriteFileRule(ctx, f.fileListFile, f.installedFilesList())
+
+ android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{
+ FileListFile: f.fileListFile,
+ })
+
+ if proptools.Bool(f.properties.Unchecked_module) {
+ ctx.UncheckedModule()
+ }
}
func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.OutputPath) {
@@ -331,6 +352,14 @@
return f.CopySpecsToDirs(ctx, builder, dirsToSpecs)
}
+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) buildImageUsingBuildImage(ctx android.ModuleContext) android.OutputPath {
rootDir := android.PathForModuleOut(ctx, "root").OutputPath
rebasedDir := rootDir
@@ -348,6 +377,7 @@
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
f.buildEventLogtagsFile(ctx, builder, rebasedDir)
f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
+ f.copyFilesToProductOut(ctx, builder, rebasedDir)
// run host_init_verifier
// Ideally we should have a concept of pluggable linters that verify the generated image.
@@ -490,6 +520,7 @@
f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir)
f.buildEventLogtagsFile(ctx, builder, rebasedDir)
f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir)
+ f.copyFilesToProductOut(ctx, builder, rebasedDir)
output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath
cmd := builder.Command().
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 2dc8c21..8c0d111 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -16,7 +16,6 @@
import (
"os"
- "path/filepath"
"testing"
"android/soong/android"
@@ -147,8 +146,8 @@
output := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img")
- stampFile := filepath.Join(result.Config.OutDir(), "target/product/test_device/obj/PACKAGING/system_intermediates/staging_dir.stamp")
- fileListFile := filepath.Join(result.Config.OutDir(), "target/product/test_device/obj/PACKAGING/system_intermediates/file_list.txt")
+ 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)
}
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
index e483fe4..988a57b 100644
--- a/filesystem/logical_partition.go
+++ b/filesystem/logical_partition.go
@@ -146,9 +146,16 @@
partitionNames[pName] = true
}
// Get size of the partition by reading the -size.txt file
- pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName])
+ var pSize string
+ if size, hasSize := sparseImageSizes[pName]; hasSize {
+ pSize = fmt.Sprintf("$(cat %s)", size)
+ } else {
+ pSize = "0"
+ }
cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName))
- cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName])
+ if image, hasImage := sparseImages[pName]; hasImage {
+ cmd.FlagWithInput("--image="+pName+"=", image)
+ }
}
}
@@ -192,6 +199,9 @@
// Add a rule that converts the filesystem for the given partition to the given rule builder. The
// path to the sparse file and the text file having the size of the partition are returned.
func sparseFilesystem(ctx android.ModuleContext, p partitionProperties, builder *android.RuleBuilder) (sparseImg android.OutputPath, sizeTxt android.OutputPath) {
+ if p.Filesystem == nil {
+ return
+ }
img := android.PathForModuleSrc(ctx, proptools.String(p.Filesystem))
name := proptools.String(p.Name)
sparseImg = android.PathForModuleOut(ctx, name+".img").OutputPath
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index 69d922d..57239ae 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -27,21 +27,25 @@
type systemImageProperties struct {
// Path to the input linker config json file.
- Linker_config_src *string
+ Linker_config_src *string `android:"path"`
}
// android_system_image is a specialization of android_filesystem for the 'system' partition.
// Currently, the only difference is the inclusion of linker.config.pb file which specifies
// the provided and the required libraries to and from APEXes.
-func systemImageFactory() android.Module {
+func SystemImageFactory() android.Module {
module := &systemImage{}
module.AddProperties(&module.properties)
module.filesystem.buildExtraFiles = module.buildExtraFiles
module.filesystem.filterPackagingSpec = module.filterPackagingSpec
- initFilesystemModule(&module.filesystem)
+ initFilesystemModule(module, &module.filesystem)
return module
}
+func (s systemImage) FsProps() FilesystemProperties {
+ return s.filesystem.properties
+}
+
func (s *systemImage) buildExtraFiles(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths {
if s.filesystem.properties.Partition_type != nil {
ctx.PropertyErrorf("partition_type", "partition_type must be unset on an android_system_image module. It is assumed to be 'system'.")
@@ -61,7 +65,8 @@
deps := s.gatherFilteredPackagingSpecs(ctx)
ctx.WalkDeps(func(child, parent android.Module) bool {
- for _, ps := range child.PackagingSpecs() {
+ for _, ps := range android.OtherModuleProviderOrDefault(
+ ctx, child, android.InstallFilesProvider).PackagingSpecs {
if _, ok := deps[ps.RelPathInPackage()]; ok {
modulesInPackageByModule[child] = true
modulesInPackageByName[child.Name()] = true
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index f049ec4..1d64796 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -110,7 +110,7 @@
var vbmetaPartitionDep = vbmetaDep{kind: "partition"}
func (v *vbmeta) DepsMutator(ctx android.BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), vbmetaPartitionDep, v.properties.Partitions.GetOrDefault(v.ConfigurableEvaluator(ctx), nil)...)
+ ctx.AddDependency(ctx.Module(), vbmetaPartitionDep, v.properties.Partitions.GetOrDefault(ctx, nil)...)
}
func (v *vbmeta) installFileName() string {
@@ -213,6 +213,7 @@
ctx.InstallFile(v.installDir, v.installFileName(), v.output)
ctx.SetOutputFiles([]android.Path{v.output}, "")
+ android.SetProvider(ctx, android.AndroidMkInfoProvider, v.prepareAndroidMKProviderInfo())
}
// Returns the embedded shell command that prints the rollback index
@@ -265,20 +266,17 @@
return result
}
-var _ android.AndroidMkEntriesProvider = (*vbmeta)(nil)
-
-// Implements android.AndroidMkEntriesProvider
-func (v *vbmeta) AndroidMkEntries() []android.AndroidMkEntries {
- return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "ETC",
- OutputFile: android.OptionalPathForPath(v.output),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", v.installDir.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", v.installFileName())
- },
+func (v *vbmeta) prepareAndroidMKProviderInfo() *android.AndroidMkProviderInfo {
+ providerData := android.AndroidMkProviderInfo{
+ PrimaryInfo: android.AndroidMkInfo{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(v.output),
+ EntryMap: make(map[string][]string),
},
- }}
+ }
+ providerData.PrimaryInfo.SetString("LOCAL_MODULE_PATH", v.installDir.String())
+ providerData.PrimaryInfo.SetString("LOCAL_INSTALLED_MODULE_STEM", v.installFileName())
+ return &providerData
}
var _ Filesystem = (*vbmeta)(nil)
diff --git a/fsgen/Android.bp b/fsgen/Android.bp
new file mode 100644
index 0000000..9fa9557
--- /dev/null
+++ b/fsgen/Android.bp
@@ -0,0 +1,25 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-fsgen",
+ pkgPath: "android/soong/fsgen",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-filesystem",
+ ],
+ srcs: [
+ "filesystem_creator.go",
+ ],
+ testSrcs: [
+ "filesystem_creator_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
+
+soong_filesystem_creator {
+ name: "soong_filesystem_creator",
+}
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
new file mode 100644
index 0000000..eb4f318
--- /dev/null
+++ b/fsgen/filesystem_creator.go
@@ -0,0 +1,217 @@
+// 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/android"
+ "android/soong/filesystem"
+ "crypto/sha256"
+ "fmt"
+ "strconv"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var pctx = android.NewPackageContext("android/soong/fsgen")
+
+func init() {
+ registerBuildComponents(android.InitRegistrationContext)
+}
+
+func registerBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("soong_filesystem_creator", filesystemCreatorFactory)
+}
+
+type filesystemCreatorProps struct {
+ Generated_partition_types []string `blueprint:"mutated"`
+ Unsupported_partition_types []string `blueprint:"mutated"`
+}
+
+type filesystemCreator struct {
+ android.ModuleBase
+
+ properties filesystemCreatorProps
+}
+
+func filesystemCreatorFactory() android.Module {
+ module := &filesystemCreator{}
+
+ android.InitAndroidModule(module)
+ module.AddProperties(&module.properties)
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.createInternalModules(ctx)
+ })
+
+ return module
+}
+
+func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) {
+ for _, partitionType := range []string{"system"} {
+ if f.createPartition(ctx, partitionType) {
+ f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType)
+ } else {
+ f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
+ }
+ }
+}
+
+func (f *filesystemCreator) generatedModuleNameForPartition(cfg android.Config, partitionType string) string {
+ prefix := "soong"
+ if cfg.HasDeviceProduct() {
+ prefix = cfg.DeviceProduct()
+ }
+ return fmt.Sprintf("%s_generated_%s_image", prefix, partitionType)
+}
+
+// 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 := &struct {
+ Name *string
+ }{
+ Name: proptools.StringPtr(f.generatedModuleNameForPartition(ctx.Config(), partitionType)),
+ }
+
+ fsProps := &filesystem.FilesystemProperties{}
+
+ // Don't build this module on checkbuilds, the soong-built partitions are still in-progress
+ // and sometimes don't build.
+ fsProps.Unchecked_module = proptools.BoolPtr(true)
+
+ partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
+ specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType]
+
+ // BOARD_AVB_ENABLE
+ fsProps.Use_avb = proptools.BoolPtr(partitionVars.BoardAvbEnable)
+ // BOARD_AVB_KEY_PATH
+ fsProps.Avb_private_key = proptools.StringPtr(specificPartitionVars.BoardAvbKeyPath)
+ // BOARD_AVB_ALGORITHM
+ fsProps.Avb_algorithm = proptools.StringPtr(specificPartitionVars.BoardAvbAlgorithm)
+ // BOARD_AVB_SYSTEM_ROLLBACK_INDEX
+ if rollbackIndex, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64); err == nil {
+ fsProps.Rollback_index = proptools.Int64Ptr(rollbackIndex)
+ }
+
+ fsProps.Partition_name = proptools.StringPtr(partitionType)
+ // BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE
+ fsProps.Type = proptools.StringPtr(specificPartitionVars.BoardFileSystemType)
+ if *fsProps.Type != "ext4" {
+ // Currently the android_filesystem module type only supports ext4:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/filesystem/filesystem.go;l=416;drc=98047cfd07944b297a12d173453bc984806760d2
+ return false
+ }
+
+ fsProps.Base_dir = proptools.StringPtr(partitionType)
+
+ fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true)
+
+ // Identical to that of the generic_system_image
+ fsProps.Fsverity.Inputs = []string{
+ "etc/boot-image.prof",
+ "etc/dirty-image-objects",
+ "etc/preloaded-classes",
+ "etc/classpaths/*.pb",
+ "framework/*",
+ "framework/*/*", // framework/{arch}
+ "framework/oat/*/*", // framework/oat/{arch}
+ }
+
+ // system_image properties that are not set:
+ // - filesystemProperties.Avb_hash_algorithm
+ // - filesystemProperties.File_contexts
+ // - filesystemProperties.Dirs
+ // - filesystemProperties.Symlinks
+ // - filesystemProperties.Fake_timestamp
+ // - filesystemProperties.Uuid
+ // - filesystemProperties.Mount_point
+ // - filesystemProperties.Include_make_built_files
+ // - filesystemProperties.Build_logtags
+ // - filesystemProperties.Fsverity.Libs
+ // - systemImageProperties.Linker_config_src
+ var module android.Module
+ if partitionType == "system" {
+ module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps)
+ } else {
+ module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps)
+ }
+ module.HideFromMake()
+ return true
+}
+
+func (f *filesystemCreator) createDiffTest(ctx android.ModuleContext, partitionType string) android.Path {
+ partitionModuleName := f.generatedModuleNameForPartition(ctx.Config(), partitionType)
+ systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag)
+ filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider)
+ if !ok {
+ ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName)
+ }
+ makeFileList := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partitionType))
+ // For now, don't allowlist anything. The test will fail, but that's fine in the current
+ // early stages where we're just figuring out what we need
+ emptyAllowlistFile := android.PathForModuleOut(ctx, "allowlist_%s.txt", partitionModuleName)
+ android.WriteFileRule(ctx, emptyAllowlistFile, "")
+ diffTestResultFile := android.PathForModuleOut(ctx, "diff_test_%s.txt", partitionModuleName)
+
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().BuiltTool("file_list_diff").
+ Input(makeFileList).
+ Input(filesystemInfo.FileListFile).
+ Input(emptyAllowlistFile).
+ Text(partitionModuleName)
+ builder.Command().Text("touch").Output(diffTestResultFile)
+ builder.Build(partitionModuleName+" diff test", partitionModuleName+" diff test")
+ return diffTestResultFile
+}
+
+func createFailingCommand(ctx android.ModuleContext, message string) android.Path {
+ hasher := sha256.New()
+ hasher.Write([]byte(message))
+ filename := fmt.Sprintf("failing_command_%x.txt", hasher.Sum(nil))
+ file := android.PathForModuleOut(ctx, filename)
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Textf("echo %s", proptools.NinjaAndShellEscape(message))
+ builder.Command().Text("exit 1 #").Output(file)
+ builder.Build("failing command "+filename, "failing command "+filename)
+ return file
+}
+
+type systemImageDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var generatedFilesystemDepTag systemImageDepTagType
+
+func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
+ for _, partitionType := range f.properties.Generated_partition_types {
+ ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, f.generatedModuleNameForPartition(ctx.Config(), partitionType))
+ }
+}
+
+func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if ctx.ModuleDir() != "build/soong/fsgen" {
+ ctx.ModuleErrorf("There can only be one soong_filesystem_creator in build/soong/fsgen")
+ }
+ f.HideFromMake()
+
+ var diffTestFiles []android.Path
+ for _, partitionType := range f.properties.Generated_partition_types {
+ diffTestFiles = append(diffTestFiles, f.createDiffTest(ctx, partitionType))
+ }
+ for _, partitionType := range f.properties.Unsupported_partition_types {
+ diffTestFiles = append(diffTestFiles, createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType)))
+ }
+ ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...)
+}
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
new file mode 100644
index 0000000..554b66b
--- /dev/null
+++ b/fsgen/filesystem_creator_test.go
@@ -0,0 +1,88 @@
+// 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 fsgen
+
+import (
+ "android/soong/android"
+ "android/soong/filesystem"
+ "testing"
+
+ "github.com/google/blueprint/proptools"
+)
+
+var prepareForTestWithFsgenBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
+
+func TestFileSystemCreatorSystemImageProps(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ android.PrepareForIntegrationTestWithAndroid,
+ android.PrepareForTestWithAndroidBuildComponents,
+ filesystem.PrepareForTestWithFilesystemBuildComponents,
+ prepareForTestWithFsgenBuildComponents,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.BoardAvbEnable = true
+ config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.PartitionQualifiedVariables =
+ map[string]android.PartitionQualifiedVariablesType{
+ "system": {
+ BoardAvbKeyPath: "external/avb/test/data/testkey_rsa4096.pem",
+ BoardAvbAlgorithm: "SHA256_RSA4096",
+ BoardAvbRollbackIndex: "0",
+ BoardFileSystemType: "ext4",
+ },
+ }
+ }),
+ android.FixtureMergeMockFs(android.MockFS{
+ "external/avb/test/data/testkey_rsa4096.pem": nil,
+ "build/soong/fsgen/Android.bp": []byte(`
+ soong_filesystem_creator {
+ name: "foo",
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ fooSystem := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().(interface {
+ FsProps() filesystem.FilesystemProperties
+ })
+ android.AssertBoolEquals(
+ t,
+ "Property expected to match the product variable 'BOARD_AVB_ENABLE'",
+ true,
+ proptools.Bool(fooSystem.FsProps().Use_avb),
+ )
+ android.AssertStringEquals(
+ t,
+ "Property expected to match the product variable 'BOARD_AVB_KEY_PATH'",
+ "external/avb/test/data/testkey_rsa4096.pem",
+ proptools.String(fooSystem.FsProps().Avb_private_key),
+ )
+ android.AssertStringEquals(
+ t,
+ "Property expected to match the product variable 'BOARD_AVB_ALGORITHM'",
+ "SHA256_RSA4096",
+ proptools.String(fooSystem.FsProps().Avb_algorithm),
+ )
+ android.AssertIntEquals(
+ t,
+ "Property expected to match the product variable 'BOARD_AVB_SYSTEM_ROLLBACK_INDEX'",
+ 0,
+ proptools.Int(fooSystem.FsProps().Rollback_index),
+ )
+ android.AssertStringEquals(
+ t,
+ "Property expected to match the product variable 'BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE'",
+ "ext4",
+ proptools.String(fooSystem.FsProps().Type),
+ )
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 306d65e..a059837 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -449,7 +449,7 @@
}
}
-func IsValid(ctx android.ConfigAndErrorContext, fuzzModule FuzzModule) bool {
+func IsValid(ctx android.ConfigurableEvaluatorContext, fuzzModule FuzzModule) bool {
// Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
// fuzz targets we're going to package anyway.
if !fuzzModule.Enabled(ctx) || fuzzModule.InRamdisk() || fuzzModule.InVendorRamdisk() || fuzzModule.InRecovery() {
diff --git a/genrule/Android.bp b/genrule/Android.bp
index 7331741..49df480 100644
--- a/genrule/Android.bp
+++ b/genrule/Android.bp
@@ -22,4 +22,56 @@
"genrule_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
+}
+
+genrule {
+ name: "nsjail_genrule_test_input",
+ cmd: "echo nsjail_genrule_test_input > $(out)",
+ out: ["nsjail_genrule_test_input.txt"],
+}
+
+// Pseudo-test that's run on checkbuilds to verify consistent directory
+// structure for genrules using sbox or nsjail.
+genrule_defaults {
+ name: "nsjail_genrule_test_gen_defaults",
+ // verify both relative paths and its contents
+ cmd: "(echo $(out) $(genDir) && sha256sum " +
+ "$(location get_clang_version) " +
+ "$(location py3-cmd) " +
+ "$(location genrule.go) " +
+ "$(location :nsjail_genrule_test_input) " +
+ "$(locations *.go)) | sed 's@\\./@@g' > $(out)",
+ tools: [
+ "get_clang_version", // random tool
+ "py3-cmd", // random prebuilt tool
+ ],
+ tool_files: ["genrule.go"], // random local file
+ srcs: [
+ ":nsjail_genrule_test_input", // random OutputFileProducer
+ "*.go", // random glob
+ ],
+ out: ["nsjail_genrule_test.txt"],
+}
+
+genrule {
+ name: "nsjail_genrule_test_gen_without_nsjail",
+ defaults: ["nsjail_genrule_test_gen_defaults"],
+}
+
+genrule {
+ name: "nsjail_genrule_test_gen_with_nsjail",
+ defaults: ["nsjail_genrule_test_gen_defaults"],
+ use_nsjail: true,
+}
+
+genrule {
+ name: "nsjail_genrule_test",
+ srcs: [
+ ":nsjail_genrule_test_gen_without_nsjail",
+ ":nsjail_genrule_test_gen_with_nsjail",
+ ],
+ cmd: "diff $(in) > $(out)",
+ out: ["nsjail_genrule_test"],
}
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index 7c71b77..45a7f72 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -17,8 +17,6 @@
var (
SandboxingDenyModuleList = []string{
// go/keep-sorted start
- "aidl_camera_build_version",
- "com.google.pixel.camera.hal.manifest",
// go/keep-sorted end
}
)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 08d857d..e5222a4 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -21,11 +21,11 @@
import (
"fmt"
"io"
+ "path/filepath"
"strconv"
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -147,6 +147,21 @@
// Enable restat to update the output only if the output is changed
Write_if_changed *bool
+
+ // When set to true, an additional $(build_number_file) label will be available
+ // to use in the cmd. This will be the location of a text file containing the
+ // build number. The dependency on this file will be "order-only", meaning that
+ // the genrule will not rerun when only this file changes, to avoid rerunning
+ // the genrule every build, because the build number changes every build.
+ // This also means that you should not attempt to consume the build number from
+ // the result of this genrule in another build rule. If you do, the build number
+ // in the second build rule will be stale when the second build rule rebuilds
+ // but this genrule does not. Only certain allowlisted modules are allowed to
+ // use this property, usages of the build number should be kept to the absolute
+ // minimum. Particularly no modules on the system image may include the build
+ // number. Prefer using libbuildversion via the use_version_lib property on
+ // cc modules.
+ Uses_order_only_build_number_file *bool
}
type Module struct {
@@ -196,6 +211,9 @@
// For gensrsc sharding.
shard int
shards int
+
+ // For nsjail tasks
+ useNsjail bool
}
func (g *Module) GeneratedSourceFiles() android.Paths {
@@ -228,6 +246,37 @@
}
}
+var buildNumberAllowlistKey = android.NewOnceKey("genruleBuildNumberAllowlistKey")
+
+// This allowlist should be kept to the bare minimum, it's
+// intended for things that existed before the build number
+// was tightly controlled. Prefer using libbuildversion
+// via the use_version_lib property of cc modules.
+// This is a function instead of a global map so that
+// soong plugins cannot add entries to the allowlist
+func isModuleInBuildNumberAllowlist(ctx android.ModuleContext) bool {
+ allowlist := ctx.Config().Once(buildNumberAllowlistKey, func() interface{} {
+ // Define the allowlist as a list and then copy it into a map so that
+ // gofmt doesn't change unnecessary lines trying to align the values of the map.
+ allowlist := []string{
+ // go/keep-sorted start
+ "build/soong/tests:gen",
+ "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",
+ // go/keep-sorted end
+ }
+ allowlistMap := make(map[string]bool, len(allowlist))
+ for _, a := range allowlist {
+ allowlistMap[a] = true
+ }
+ return allowlistMap
+ }).(map[string]bool)
+
+ _, ok := allowlist[ctx.ModuleDir()+":"+ctx.ModuleName()]
+ return ok
+}
+
// generateCommonBuildActions contains build action generation logic
// common to both the mixed build case and the legacy case of genrule processing.
// To fully support genrule in mixed builds, the contents of this function should
@@ -268,16 +317,14 @@
if len(g.properties.Tools) > 0 {
seenTools := make(map[string]bool)
- ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ ctx.VisitDirectDepsAllowDisabled(func(module android.Module) {
switch tag := ctx.OtherModuleDependencyTag(module).(type) {
case hostToolDependencyTag:
tool := ctx.OtherModuleName(module)
- if m, ok := module.(android.Module); ok {
- // Necessary to retrieve any prebuilt replacement for the tool, since
- // toolDepsMutator runs too late for the prebuilt mutators to have
- // replaced the dependency.
- module = android.PrebuiltGetPreferred(ctx, m)
- }
+ // Necessary to retrieve any prebuilt replacement for the tool, since
+ // toolDepsMutator runs too late for the prebuilt mutators to have
+ // replaced the dependency.
+ module = android.PrebuiltGetPreferred(ctx, module)
switch t := module.(type) {
case android.HostToolProvider:
@@ -296,7 +343,8 @@
ctx.ModuleErrorf("host tool %q missing output file", tool)
return
}
- if specs := t.TransitivePackagingSpecs(); specs != nil {
+ if specs := android.OtherModuleProviderOrDefault(
+ ctx, t, android.InstallFilesProvider).TransitivePackagingSpecs.ToList(); specs != nil {
// If the HostToolProvider has PackgingSpecs, which are definitions of the
// required relative locations of the tool and its dependencies, use those
// instead. They will be copied to those relative locations in the sbox
@@ -318,11 +366,6 @@
tools = append(tools, path.Path())
addLocationLabel(tag.label, toolLocation{android.Paths{path.Path()}})
}
- case bootstrap.GoBinaryTool:
- // A GoBinaryTool provides the install path to a tool, which will be copied.
- p := android.PathForGoBinary(ctx, t)
- tools = append(tools, p)
- addLocationLabel(tag.label, toolLocation{android.Paths{p}})
default:
ctx.ModuleErrorf("%q is not a host tool provider", tool)
return
@@ -383,7 +426,7 @@
}
return srcFiles
}
- g.properties.ResolvedSrcs = g.properties.Srcs.GetOrDefault(g.ConfigurableEvaluator(ctx), nil)
+ g.properties.ResolvedSrcs = g.properties.Srcs.GetOrDefault(ctx, nil)
srcFiles := addLabelsForInputs("srcs", g.properties.ResolvedSrcs, g.properties.Exclude_srcs)
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
@@ -413,21 +456,26 @@
// Pick a unique path outside the task.genDir for the sbox manifest textproto,
// a unique rule name, and the user-visible description.
- manifestName := "genrule.sbox.textproto"
+ var rule *android.RuleBuilder
desc := "generate"
name := "generator"
- if task.shards > 0 {
- manifestName = "genrule_" + strconv.Itoa(task.shard) + ".sbox.textproto"
- desc += " " + strconv.Itoa(task.shard)
- name += strconv.Itoa(task.shard)
- } else if len(task.out) == 1 {
- desc += " " + task.out[0].Base()
+ if task.useNsjail {
+ rule = android.NewRuleBuilder(pctx, ctx).Nsjail(task.genDir, android.PathForModuleOut(ctx, "nsjail_build_sandbox"))
+ } else {
+ manifestName := "genrule.sbox.textproto"
+ if task.shards > 0 {
+ manifestName = "genrule_" + strconv.Itoa(task.shard) + ".sbox.textproto"
+ desc += " " + strconv.Itoa(task.shard)
+ name += strconv.Itoa(task.shard)
+ } else if len(task.out) == 1 {
+ desc += " " + task.out[0].Base()
+ }
+
+ manifestPath := android.PathForModuleOut(ctx, manifestName)
+
+ // Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
+ rule = getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
}
-
- manifestPath := android.PathForModuleOut(ctx, manifestName)
-
- // Use a RuleBuilder to create a rule that runs the command inside an sbox sandbox.
- rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(task.genDir, manifestPath))
if Bool(g.properties.Write_if_changed) {
rule.Restat()
}
@@ -470,6 +518,11 @@
return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil
case "genDir":
return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil
+ case "build_number_file":
+ if !proptools.Bool(g.properties.Uses_order_only_build_number_file) {
+ return reportError("to use the $(build_number_file) label, you must set uses_order_only_build_number_file: true")
+ }
+ return proptools.ShellEscape(cmd.PathForInput(ctx.Config().BuildNumberFile(ctx))), nil
default:
if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -516,6 +569,21 @@
cmd.Implicits(task.in)
cmd.ImplicitTools(tools)
cmd.ImplicitPackagedTools(packagedTools)
+ if proptools.Bool(g.properties.Uses_order_only_build_number_file) {
+ if !isModuleInBuildNumberAllowlist(ctx) {
+ ctx.ModuleErrorf("Only allowlisted modules may use uses_order_only_build_number_file: true")
+ }
+ cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx))
+ }
+
+ if task.useNsjail {
+ for _, input := range task.in {
+ // can fail if input is a file.
+ if paths, err := ctx.GlobWithDeps(filepath.Join(input.String(), "**/*"), nil); err == nil {
+ rule.NsjailImplicits(android.PathsForSource(ctx, paths))
+ }
+ }
+ }
// Create the rule to run the genrule command inside sbox.
rule.Build(name, desc)
@@ -589,7 +657,7 @@
}
// Collect information for opening IDE project files in java/jdeps.go.
-func (g *Module) IDEInfo(dpInfo *android.IdeInfo) {
+func (g *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
dpInfo.Srcs = append(dpInfo.Srcs, g.Srcs().Strings()...)
for _, src := range g.properties.ResolvedSrcs {
if strings.HasPrefix(src, ":") {
@@ -780,15 +848,18 @@
properties := &genRuleProperties{}
taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
+ useNsjail := Bool(properties.Use_nsjail)
+
outs := make(android.WritablePaths, len(properties.Out))
for i, out := range properties.Out {
outs[i] = android.PathForModuleGen(ctx, out)
}
return []generateTask{{
- in: srcFiles,
- out: outs,
- genDir: android.PathForModuleGen(ctx),
- cmd: rawCommand,
+ in: srcFiles,
+ out: outs,
+ genDir: android.PathForModuleGen(ctx),
+ cmd: rawCommand,
+ useNsjail: useNsjail,
}}
}
@@ -803,6 +874,8 @@
}
type genRuleProperties struct {
+ Use_nsjail *bool
+
// names of the output files that will be generated
Out []string `android:"arch_variant"`
}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 444aedb..9278f15 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -19,6 +19,7 @@
"os"
"regexp"
"strconv"
+ "strings"
"testing"
"android/soong/android"
@@ -1192,6 +1193,68 @@
}
}
+func TestGenruleUsesOrderOnlyBuildNumberFile(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ fs android.MockFS
+ expectedError string
+ expectedCommand string
+ }{
+ {
+ name: "not allowed when not in allowlist",
+ fs: android.MockFS{
+ "foo/Android.bp": []byte(`
+genrule {
+ name: "gen",
+ uses_order_only_build_number_file: true,
+ cmd: "cp $(build_number_file) $(out)",
+ out: ["out.txt"],
+}
+`),
+ },
+ expectedError: `Only allowlisted modules may use uses_order_only_build_number_file: true`,
+ },
+ {
+ name: "normal",
+ fs: android.MockFS{
+ "build/soong/tests/Android.bp": []byte(`
+genrule {
+ name: "gen",
+ uses_order_only_build_number_file: true,
+ cmd: "cp $(build_number_file) $(out)",
+ out: ["out.txt"],
+}
+`),
+ },
+ expectedCommand: `cp BUILD_NUMBER_FILE __SBOX_SANDBOX_DIR__/out/out.txt`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ fixtures := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.PrepareForTestWithVisibility,
+ android.FixtureMergeMockFs(tc.fs),
+ android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) {
+ config.TestProductVariables.BuildNumberFile = proptools.StringPtr("build_number.txt")
+ }),
+ )
+ if tc.expectedError != "" {
+ fixtures = fixtures.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
+ }
+ result := fixtures.RunTest(t)
+
+ if tc.expectedError == "" {
+ tc.expectedCommand = strings.ReplaceAll(tc.expectedCommand, "BUILD_NUMBER_FILE", result.Config.SoongOutDir()+"/build_number.txt")
+ gen := result.Module("gen", "").(*Module)
+ android.AssertStringEquals(t, "raw commands", tc.expectedCommand, gen.rawCommands[0])
+ }
+ })
+ }
+}
+
type testTool struct {
android.ModuleBase
outputFile android.Path
diff --git a/golang/Android.bp b/golang/Android.bp
new file mode 100644
index 0000000..3eae94f
--- /dev/null
+++ b/golang/Android.bp
@@ -0,0 +1,22 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-golang",
+ pkgPath: "android/soong/golang",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "blueprint-bootstrap",
+ "soong",
+ "soong-android",
+ ],
+ srcs: [
+ "golang.go",
+ ],
+ testSrcs: [
+ "golang_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/golang/golang.go b/golang/golang.go
new file mode 100644
index 0000000..618a085
--- /dev/null
+++ b/golang/golang.go
@@ -0,0 +1,136 @@
+// 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 golang wraps the blueprint blueprint_go_binary and bootstrap_go_binary module types in versions
+// that implement android.Module that are used when building in Soong. This simplifies the code in Soong
+// so it can always assume modules are an android.Module.
+// The original blueprint blueprint_go_binary and bootstrap_go_binary module types are still used during
+// bootstrapping, so the Android.bp entries for these module types must be compatible with both the
+// original blueprint module types and these wrapped module types.
+package golang
+
+import (
+ "android/soong/android"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/bootstrap"
+)
+
+func init() {
+ // Wrap the blueprint Go module types with Soong ones that interoperate with the rest of the Soong modules.
+ bootstrap.GoModuleTypesAreWrapped()
+ RegisterGoModuleTypes(android.InitRegistrationContext)
+}
+
+func RegisterGoModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("bootstrap_go_package", goPackageModuleFactory)
+ ctx.RegisterModuleType("blueprint_go_binary", goBinaryModuleFactory)
+}
+
+// A GoPackage is a module for building Go packages.
+type GoPackage struct {
+ android.ModuleBase
+ bootstrap.GoPackage
+}
+
+func goPackageModuleFactory() android.Module {
+ module := &GoPackage{}
+ module.AddProperties(module.Properties()...)
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
+func (g *GoPackage) GenerateBuildActions(ctx blueprint.ModuleContext) {
+ // The embedded ModuleBase and bootstrap.GoPackage each implement GenerateBuildActions,
+ // the delegation has to be implemented manually to disambiguate. Call ModuleBase's
+ // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call
+ // bootstrap.GoPackage.GenerateBuildActions.
+ g.ModuleBase.GenerateBuildActions(ctx)
+}
+
+func (g *GoPackage) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ g.GoPackage.GenerateBuildActions(ctx.BlueprintModuleContext())
+}
+
+// A GoBinary is a module for building executable binaries from Go sources.
+type GoBinary struct {
+ android.ModuleBase
+ bootstrap.GoBinary
+
+ outputFile android.Path
+}
+
+func goBinaryModuleFactory() android.Module {
+ module := &GoBinary{}
+ module.AddProperties(module.Properties()...)
+ android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
+ return module
+}
+
+func (g *GoBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
+ // The embedded ModuleBase and bootstrap.GoBinary each implement GenerateBuildActions,
+ // the delegation has to be implemented manually to disambiguate. Call ModuleBase's
+ // GenerateBuildActions, which will call GenerateAndroidBuildActions, which will call
+ // bootstrap.GoBinary.GenerateBuildActions.
+ g.ModuleBase.GenerateBuildActions(ctx)
+}
+
+func (g *GoBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Install the file in Soong instead of blueprint so that Soong knows about the install rules.
+ g.GoBinary.SetSkipInstall()
+
+ // Run the build actions from the wrapped blueprint bootstrap module.
+ g.GoBinary.GenerateBuildActions(ctx.BlueprintModuleContext())
+
+ // Translate the bootstrap module's string path into a Path
+ 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)
+
+ // 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)
+ }
+ }
+
+ ctx.SetOutputFiles(android.Paths{outputFile}, "")
+}
+
+func usedByBootstrap(name string) bool {
+ switch name {
+ case "loadplugins", "soong_build":
+ return true
+ default:
+ return false
+ }
+}
+
+func (g *GoBinary) HostToolPath() android.OptionalPath {
+ return android.OptionalPathForPath(g.outputFile)
+}
+
+func (g *GoBinary) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{
+ {
+ Class: "EXECUTABLES",
+ OutputFile: android.OptionalPathForPath(g.outputFile),
+ Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
+ },
+ }
+}
diff --git a/golang/golang_test.go b/golang/golang_test.go
new file mode 100644
index 0000000..b512144
--- /dev/null
+++ b/golang/golang_test.go
@@ -0,0 +1,51 @@
+// 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 golang
+
+import (
+ "android/soong/android"
+ "github.com/google/blueprint/bootstrap"
+ "path/filepath"
+ "testing"
+)
+
+func TestGolang(t *testing.T) {
+ bp := `
+ bootstrap_go_package {
+ name: "gopkg",
+ pkgPath: "test/pkg",
+ }
+
+ blueprint_go_binary {
+ name: "gobin",
+ deps: ["gopkg"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ android.PrepareForTestWithArchMutator,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ RegisterGoModuleTypes(ctx)
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps)
+ })
+ }),
+ ).RunTestWithBp(t, bp)
+
+ bin := result.ModuleForTests("gobin", result.Config.BuildOSTarget.String())
+
+ expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "bin/go/gobin/obj/gobin")
+ android.AssertPathsRelativeToTopEquals(t, "output files", []string{expected}, bin.OutputFiles(result.TestContext, t, ""))
+}
diff --git a/java/Android.bp b/java/Android.bp
index 9603815..1101d7a 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -72,7 +72,7 @@
"rro.go",
"sdk.go",
"sdk_library.go",
- "sdk_library_external.go",
+ "sdk_library_internal.go",
"support_libraries.go",
"system_modules.go",
"systemserver_classpath_fragment.go",
@@ -120,4 +120,5 @@
"test_spec_test.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/java/aar.go b/java/aar.go
index b69b7c2..7d73b03 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -15,10 +15,10 @@
package java
import (
+ "crypto/sha256"
"fmt"
"path/filepath"
"slices"
- "strconv"
"strings"
"android/soong/android"
@@ -45,7 +45,7 @@
ctx.RegisterModuleType("android_library_import", AARImportFactory)
ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator)
+ ctx.Transition("propagate_rro_enforcement", &propagateRROEnforcementTransitionMutator{})
})
}
@@ -76,7 +76,7 @@
// list of directories relative to the Blueprints file containing
// Android resources. Defaults to ["res"] if a directory called res exists.
// Set to [] to disable the default.
- Resource_dirs []string
+ Resource_dirs []string `android:"path"`
// list of zip files containing Android resources.
Resource_zips []string `android:"path"`
@@ -151,22 +151,78 @@
path android.Path
}
-// Propagate RRO enforcement flag to static lib dependencies transitively.
-func propagateRROEnforcementMutator(ctx android.TopDownMutatorContext) {
+// Propagate RRO enforcement flag to static lib dependencies transitively. If EnforceRROGlobally is set then
+// all modules will use the "" variant. If specific modules have RRO enforced, then modules (usually apps) with
+// RRO enabled will use the "" variation for themselves, but use the "rro" variant of direct and transitive static
+// android_library dependencies.
+type propagateRROEnforcementTransitionMutator struct{}
+
+func (p propagateRROEnforcementTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ // Never split modules, apps with or without RRO enabled use the "" variant, static android_library dependencies
+ // will use create the "rro" variant from incoming tranisitons.
+ return []string{""}
+}
+
+func (p propagateRROEnforcementTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ // Non-static dependencies are not involved in RRO and always use the empty variant.
+ if ctx.DepTag() != staticLibTag {
+ return ""
+ }
+
m := ctx.Module()
- if d, ok := m.(AndroidLibraryDependency); ok && d.IsRROEnforced(ctx) {
- ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(AndroidLibraryDependency); ok {
- a.SetRROEnforcedForDependent(true)
- }
- })
+ if _, ok := m.(AndroidLibraryDependency); ok {
+ // If RRO is enforced globally don't bother using "rro" variants, the empty variant will have RRO enabled.
+ if ctx.Config().EnforceRROGlobally() {
+ return ""
+ }
+
+ // If RRO is enabled for this module use the "rro" variants of static dependencies. IncomingTransition will
+ // rewrite this back to "" if the dependency is not an android_library.
+ if ctx.Config().EnforceRROForModule(ctx.Module().Name()) {
+ return "rro"
+ }
+ }
+
+ return sourceVariation
+}
+
+func (p propagateRROEnforcementTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ // Propagate the "rro" variant to android_library modules, but use the empty variant for everything else.
+ if incomingVariation == "rro" {
+ m := ctx.Module()
+ if _, ok := m.(AndroidLibraryDependency); ok {
+ return "rro"
+ }
+ return ""
+ }
+
+ return ""
+}
+
+func (p propagateRROEnforcementTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ m := ctx.Module()
+ if d, ok := m.(AndroidLibraryDependency); ok {
+ if variation == "rro" {
+ // This is the "rro" variant of a module that has both variants, mark this one as RRO enabled and
+ // hide it from make to avoid collisions with the non-RRO empty variant.
+ d.SetRROEnforcedForDependent(true)
+ m.HideFromMake()
+ } else if ctx.Config().EnforceRROGlobally() {
+ // RRO is enabled globally, mark it enabled for this module, but there is only one variant so no
+ // need to hide it from make.
+ d.SetRROEnforcedForDependent(true)
+ }
}
}
func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool {
return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault()) &&
// TODO(b/331641946): remove this when ResourceProcessorBusyBox supports generating shared libraries.
- !slices.Contains(a.aaptProperties.Aaptflags, "--shared-lib")
+ !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()
}
func (a *aapt) filterProduct() string {
@@ -232,18 +288,20 @@
rroDirs = append(rroDirs, resRRODirs...)
}
+ assetDirsHasher := sha256.New()
var assetDeps android.Paths
- for i, dir := range assetDirs {
+ for _, dir := range assetDirs {
// Add a dependency on every file in the asset directory. This ensures the aapt2
// rule will be rerun if one of the files in the asset directory is modified.
- assetDeps = append(assetDeps, androidResourceGlob(ctx, dir)...)
+ dirContents := androidResourceGlob(ctx, dir)
+ assetDeps = append(assetDeps, dirContents...)
- // Add a dependency on a file that contains a list of all the files in the asset directory.
+ // Add a hash of all the files in the asset directory to the command line.
// This ensures the aapt2 rule will be run if a file is removed from the asset directory,
// or a file is added whose timestamp is older than the output of aapt2.
- assetFileListFile := android.PathForModuleOut(ctx, "asset_dir_globs", strconv.Itoa(i)+".glob")
- androidResourceGlobList(ctx, dir, assetFileListFile)
- assetDeps = append(assetDeps, assetFileListFile)
+ for _, path := range dirContents.Strings() {
+ assetDirsHasher.Write([]byte(path))
+ }
}
assetDirStrings := assetDirs.Strings()
@@ -278,6 +336,7 @@
linkDeps = append(linkDeps, manifestPath)
linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirStrings, "-A "))
+ linkFlags = append(linkFlags, fmt.Sprintf("$$(: %x)", assetDirsHasher.Sum(nil)))
linkDeps = append(linkDeps, assetDeps...)
// Returns the effective version for {min|target}_sdk_version
@@ -399,6 +458,7 @@
packageName: a.manifestValues.applicationId,
}
a.mergedManifestFile = manifestMerger(ctx, transitiveManifestPaths[0], manifestMergerParams)
+ ctx.CheckbuildFile(a.mergedManifestFile)
if !a.isLibrary {
// Only use the merged manifest for applications. For libraries, the transitive closure of manifests
// will be propagated to the final application and merged there. The merged manifest for libraries is
@@ -533,6 +593,8 @@
aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages,
opts.aconfigTextFiles)
+ ctx.CheckbuildFile(packageRes)
+
// Extract assets from the resource package output so that they can be used later in aapt2link
// for modules that depend on this one.
if android.PrefixInList(linkFlags, "-A ") {
@@ -877,13 +939,12 @@
extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
}
- a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
+ a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars, nil)
a.aarFile = android.PathForModuleOut(ctx, ctx.ModuleName()+".aar")
var res android.Paths
if a.androidLibraryProperties.BuildAAR {
BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
- ctx.CheckbuildFile(a.aarFile)
}
prebuiltJniPackages := android.Paths{}
@@ -910,12 +971,12 @@
setOutputFiles(ctx, a.Library.Module)
}
-func (a *AndroidLibrary) IDEInfo(dpInfo *android.IdeInfo) {
- a.Library.IDEInfo(dpInfo)
- a.aapt.IDEInfo(dpInfo)
+func (a *AndroidLibrary) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
+ a.Library.IDEInfo(ctx, dpInfo)
+ a.aapt.IDEInfo(ctx, dpInfo)
}
-func (a *aapt) IDEInfo(dpInfo *android.IdeInfo) {
+func (a *aapt) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
if a.rJar != nil {
dpInfo.Jars = append(dpInfo.Jars, a.rJar.String())
}
@@ -964,7 +1025,7 @@
// Defaults to sdk_version if not set. See sdk_version for possible values.
Min_sdk_version *string
// List of java static libraries that the included ARR (android library prebuilts) has dependencies to.
- Static_libs []string
+ Static_libs proptools.Configurable[[]string]
// List of java libraries that the included ARR (android library prebuilts) has dependencies to.
Libs []string
// If set to true, run Jetifier against .aar file. Defaults to false.
@@ -987,21 +1048,21 @@
// Functionality common to Module and Import.
embeddableInModuleAndImport
- providesTransitiveHeaderJars
+ providesTransitiveHeaderJarsForR8
properties AARImportProperties
- headerJarFile android.WritablePath
- implementationJarFile android.WritablePath
- implementationAndResourcesJarFile android.WritablePath
- proguardFlags android.WritablePath
- exportPackage android.WritablePath
+ headerJarFile android.Path
+ implementationJarFile android.Path
+ implementationAndResourcesJarFile android.Path
+ proguardFlags android.Path
+ exportPackage android.Path
transitiveAaptResourcePackagesFile android.Path
- extraAaptPackagesFile android.WritablePath
+ extraAaptPackagesFile android.Path
manifest android.Path
- assetsPackage android.WritablePath
- rTxt android.WritablePath
- rJar android.WritablePath
+ assetsPackage android.Path
+ rTxt android.Path
+ rJar android.Path
resourcesNodesDepSet *android.DepSet[*resourcesNode]
manifestsDepSet *android.DepSet[android.Path]
@@ -1094,7 +1155,7 @@
}
ctx.AddVariationDependencies(nil, libTag, a.properties.Libs...)
- ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, a.properties.Static_libs.GetOrDefault(ctx, nil)...)
a.usesLibrary.deps(ctx, false)
}
@@ -1150,8 +1211,9 @@
if Bool(a.properties.Jetifier) {
inputFile := a.aarPath
- a.aarPath = android.PathForModuleOut(ctx, "jetifier", aarName)
- TransformJetifier(ctx, a.aarPath.(android.WritablePath), inputFile)
+ jetifierPath := android.PathForModuleOut(ctx, "jetifier", aarName)
+ TransformJetifier(ctx, jetifierPath, inputFile)
+ a.aarPath = jetifierPath
}
jarName := ctx.ModuleName() + ".jar"
@@ -1166,14 +1228,14 @@
a.manifest = extractedManifest
}
- a.rTxt = extractedAARDir.Join(ctx, "R.txt")
- a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
- a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
+ rTxt := extractedAARDir.Join(ctx, "R.txt")
+ assetsPackage := android.PathForModuleOut(ctx, "assets.zip")
+ proguardFlags := extractedAARDir.Join(ctx, "proguard.txt")
transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{
ProguardFlagsFiles: android.NewDepSet[android.Path](
android.POSTORDER,
- android.Paths{a.proguardFlags},
+ android.Paths{proguardFlags},
transitiveProguardFlags,
),
UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path](
@@ -1186,15 +1248,19 @@
ctx.Build(pctx, android.BuildParams{
Rule: unzipAAR,
Input: a.aarPath,
- Outputs: android.WritablePaths{classpathFile, a.proguardFlags, extractedManifest, a.assetsPackage, a.rTxt},
+ Outputs: android.WritablePaths{classpathFile, proguardFlags, extractedManifest, assetsPackage, rTxt},
Description: "unzip AAR",
Args: map[string]string{
"outDir": extractedAARDir.String(),
"combinedClassesJar": classpathFile.String(),
- "assetsPackage": a.assetsPackage.String(),
+ "assetsPackage": assetsPackage.String(),
},
})
+ a.proguardFlags = proguardFlags
+ a.assetsPackage = assetsPackage
+ a.rTxt = rTxt
+
// Always set --pseudo-localize, it will be stripped out later for release
// builds that don't want it.
compileFlags := []string{"--pseudo-localize"}
@@ -1202,10 +1268,10 @@
flata := compiledResDir.Join(ctx, "gen_res.flata")
aapt2CompileZip(ctx, flata, a.aarPath, "res", compileFlags)
- a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
+ exportPackage := android.PathForModuleOut(ctx, "package-res.apk")
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
aaptRTxt := android.PathForModuleOut(ctx, "R.txt")
- a.extraAaptPackagesFile = android.PathForModuleOut(ctx, "extra_packages")
+ extraAaptPackagesFile := android.PathForModuleOut(ctx, "extra_packages")
var linkDeps android.Paths
@@ -1241,13 +1307,18 @@
}
transitiveAssets := android.ReverseSliceInPlace(staticDeps.assets())
- aapt2Link(ctx, a.exportPackage, nil, proguardOptionsFile, aaptRTxt,
+ aapt2Link(ctx, exportPackage, nil, proguardOptionsFile, aaptRTxt,
linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil)
+ ctx.CheckbuildFile(exportPackage)
+ a.exportPackage = exportPackage
- a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
- resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil, false)
+ rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, rJar, nil, true, nil, false)
+ ctx.CheckbuildFile(rJar)
+ a.rJar = rJar
- aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)
+ aapt2ExtractExtraPackages(ctx, extraAaptPackagesFile, a.rJar)
+ a.extraAaptPackagesFile = extraAaptPackagesFile
resourcesNodesDepSetBuilder := android.NewDepSetBuilder[*resourcesNode](android.TOPOLOGICAL)
resourcesNodesDepSetBuilder.Direct(&resourcesNode{
@@ -1274,13 +1345,17 @@
android.WriteFileRule(ctx, transitiveAaptResourcePackagesFile, strings.Join(transitiveAaptResourcePackages, "\n"))
a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
- a.collectTransitiveHeaderJars(ctx)
+ a.collectTransitiveHeaderJarsForR8(ctx)
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
var staticJars android.Paths
var staticHeaderJars android.Paths
var staticResourceJars android.Paths
+ var transitiveStaticLibsHeaderJars []*android.DepSet[android.Path]
+ var transitiveStaticLibsImplementationJars []*android.DepSet[android.Path]
+ var transitiveStaticLibsResourceJars []*android.DepSet[android.Path]
+
ctx.VisitDirectDeps(func(module android.Module) {
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
tag := ctx.OtherModuleDependencyTag(module)
@@ -1289,61 +1364,111 @@
staticJars = append(staticJars, dep.ImplementationJars...)
staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
staticResourceJars = append(staticResourceJars, dep.ResourceJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveStaticLibsHeaderJars = append(transitiveStaticLibsHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsImplementationJars != nil {
+ transitiveStaticLibsImplementationJars = append(transitiveStaticLibsImplementationJars, dep.TransitiveStaticLibsImplementationJars)
+ }
+ if dep.TransitiveStaticLibsResourceJars != nil {
+ transitiveStaticLibsResourceJars = append(transitiveStaticLibsResourceJars, dep.TransitiveStaticLibsResourceJars)
+ }
}
}
addCLCFromDep(ctx, module, a.classLoaderContexts)
addMissingOptionalUsesLibsFromDep(ctx, module, &a.usesLibrary)
})
- var implementationJarFile android.OutputPath
- if len(staticJars) > 0 {
- combineJars := append(android.Paths{classpathFile}, staticJars...)
- implementationJarFile = android.PathForModuleOut(ctx, "combined", jarName).OutputPath
- TransformJarsToJar(ctx, implementationJarFile, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+ completeStaticLibsHeaderJars := android.NewDepSet(android.PREORDER, android.Paths{classpathFile}, transitiveStaticLibsHeaderJars)
+ completeStaticLibsImplementationJars := android.NewDepSet(android.PREORDER, android.Paths{classpathFile}, transitiveStaticLibsImplementationJars)
+ completeStaticLibsResourceJars := android.NewDepSet(android.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...)
+ }
+
+ if len(combineJars) > 1 {
+ implementationJarOutputPath := android.PathForModuleOut(ctx, "combined", jarName)
+ TransformJarsToJar(ctx, implementationJarOutputPath, "combine", combineJars, android.OptionalPath{}, false, nil, nil)
+ implementationJarFile = implementationJarOutputPath
} else {
implementationJarFile = classpathFile
}
var resourceJarFile android.Path
- if len(staticResourceJars) > 1 {
+ var resourceJars android.Paths
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ resourceJars = completeStaticLibsResourceJars.ToList()
+ } else {
+ resourceJars = staticResourceJars
+ }
+ if len(resourceJars) > 1 {
combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for resources", staticResourceJars, android.OptionalPath{},
+ TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
false, nil, nil)
resourceJarFile = combinedJar
- } else if len(staticResourceJars) == 1 {
- resourceJarFile = staticResourceJars[0]
+ } else if len(resourceJars) == 1 {
+ resourceJarFile = resourceJars[0]
}
// merge implementation jar with resources if necessary
- implementationAndResourcesJar := implementationJarFile
- if resourceJarFile != nil {
- jars := android.Paths{resourceJarFile, implementationAndResourcesJar}
- combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+ var implementationAndResourcesJars android.Paths
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ implementationAndResourcesJars = append(slices.Clone(resourceJars), combineJars...)
+ } else {
+ implementationAndResourcesJars = android.PathsIfNonNil(resourceJarFile, implementationJarFile)
+ }
+ var implementationAndResourcesJar android.Path
+ if len(implementationAndResourcesJars) > 1 {
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", implementationAndResourcesJars, android.OptionalPath{},
false, nil, nil)
implementationAndResourcesJar = combinedJar
+ } else {
+ implementationAndResourcesJar = implementationAndResourcesJars[0]
}
a.implementationJarFile = implementationJarFile
// 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()
- if len(staticHeaderJars) > 0 {
- combineJars := append(android.Paths{classpathFile}, staticHeaderJars...)
- a.headerJarFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
- TransformJarsToJar(ctx, a.headerJarFile, "combine header jars", combineJars, android.OptionalPath{}, false, nil, nil)
+ var headerJars android.Paths
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ headerJars = completeStaticLibsHeaderJars.ToList()
} else {
- a.headerJarFile = classpathFile
+ headerJars = append(android.Paths{classpathFile}, staticHeaderJars...)
+ }
+ if len(headerJars) > 1 {
+ headerJarFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, headerJarFile, "combine header jars", headerJars, android.OptionalPath{}, false, nil, nil)
+ a.headerJarFile = headerJarFile
+ } else {
+ a.headerJarFile = headerJars[0]
}
- android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(a.headerJarFile),
- ResourceJars: android.PathsIfNonNil(resourceJarFile),
- TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(a.implementationAndResourcesJarFile),
- ImplementationJars: android.PathsIfNonNil(a.implementationJarFile),
- StubsLinkType: Implementation,
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ ctx.CheckbuildFile(classpathFile)
+ } else {
+ ctx.CheckbuildFile(a.headerJarFile)
+ ctx.CheckbuildFile(a.implementationJarFile)
+ }
+
+ android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ HeaderJars: android.PathsIfNonNil(a.headerJarFile),
+ LocalHeaderJars: android.PathsIfNonNil(classpathFile),
+ TransitiveStaticLibsHeaderJars: completeStaticLibsHeaderJars,
+ TransitiveStaticLibsImplementationJars: completeStaticLibsImplementationJars,
+ TransitiveStaticLibsResourceJars: completeStaticLibsResourceJars,
+ ResourceJars: android.PathsIfNonNil(resourceJarFile),
+ TransitiveLibsHeaderJarsForR8: a.transitiveLibsHeaderJarsForR8,
+ TransitiveStaticLibsHeaderJarsForR8: a.transitiveStaticLibsHeaderJarsForR8,
+ ImplementationAndResourcesJars: android.PathsIfNonNil(a.implementationAndResourcesJarFile),
+ ImplementationJars: android.PathsIfNonNil(a.implementationJarFile),
+ StubsLinkType: Implementation,
// TransitiveAconfigFiles: // TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
@@ -1436,3 +1561,7 @@
InitJavaModuleMultiTargets(module, android.DeviceSupported)
return module
}
+
+func (a *AARImport) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
+ dpInfo.Jars = append(dpInfo.Jars, a.headerJarFile.String(), a.rJar.String())
+}
diff --git a/java/aar_test.go b/java/aar_test.go
index ebad310..aa4f0af 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -53,7 +53,7 @@
appMod := ctx.Module(tc.name, "android_common")
appTestMod := ctx.ModuleForTests(tc.name, "android_common")
- info, ok := android.SingletonModuleProvider(ctx, appMod, JniPackageProvider)
+ info, ok := android.OtherModuleProvider(ctx, appMod, JniPackageProvider)
if !ok {
t.Errorf("expected android_library_import to have JniPackageProvider")
}
@@ -159,9 +159,9 @@
bar := result.ModuleForTests("bar", "android_common")
baz := result.ModuleForTests("baz", "android_common")
- fooOutputPaths := foo.OutputFiles(t, "")
- barOutputPaths := bar.OutputFiles(t, "")
- bazOutputPaths := baz.OutputFiles(t, "")
+ fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
+ barOutputPaths := bar.OutputFiles(result.TestContext, t, "")
+ bazOutputPaths := baz.OutputFiles(result.TestContext, t, "")
android.AssertPathsRelativeToTopEquals(t, "foo output path",
[]string{"out/soong/.intermediates/foo/android_common/withres/foo.jar"}, fooOutputPaths)
diff --git a/java/android_resources.go b/java/android_resources.go
index 038a260..3bb3eb5 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -39,15 +39,6 @@
return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames)
}
-// androidResourceGlobList creates a rule to write the list of files in the given directory, using
-// the standard exclusion patterns for Android resources, to the given output file.
-func androidResourceGlobList(ctx android.ModuleContext, dir android.Path,
- fileListFile android.WritablePath) {
-
- android.GlobToListFileRule(ctx, filepath.Join(dir.String(), "**/*"),
- androidResourceIgnoreFilenames, fileListFile)
-}
-
type overlayType int
const (
diff --git a/java/androidmk.go b/java/androidmk.go
index a1bc904..0539d25 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -415,7 +415,7 @@
} else {
var names []string
for _, jniLib := range app.jniLibs {
- names = append(names, jniLib.name)
+ names = append(names, jniLib.name+":"+jniLib.target.Arch.ArchType.Bitness())
}
entries.AddStrings("LOCAL_REQUIRED_MODULES", names...)
}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 243a279..1d98b18 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -286,7 +286,7 @@
}{
{
name: "app",
- expected: []string{"libjni"},
+ expected: []string{"libjni:64"},
},
{
name: "app_embedded",
diff --git a/java/app.go b/java/app.go
index 19dc8d5..dd99675 100644
--- a/java/app.go
+++ b/java/app.go
@@ -63,6 +63,16 @@
ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
}
+type AppInfo struct {
+ // Updatable is set to the value of the updatable property
+ Updatable bool
+
+ // TestHelperApp is true if the module is a android_test_helper_app
+ TestHelperApp bool
+}
+
+var AppInfoProvider = blueprint.NewProvider[*AppInfo]()
+
// AndroidManifest.xml merging
// package splits
@@ -83,7 +93,7 @@
Package_splits []string
// list of native libraries that will be provided in or alongside the resulting jar
- Jni_libs []string `android:"arch_variant"`
+ Jni_libs proptools.Configurable[[]string] `android:"arch_variant"`
// if true, use JNI libraries that link against platform APIs even if this module sets
// sdk_version.
@@ -162,7 +172,7 @@
RotationMinSdkVersion *string
// the package name of this app. The package name in the manifest file is used if one was not given.
- Package_name *string
+ Package_name proptools.Configurable[string]
// the logging parent of this app.
Logging_parent *string
@@ -311,7 +321,7 @@
} else {
tag = jniInstallTag
}
- ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
+ ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs.GetOrDefault(ctx, nil)...)
}
for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
@@ -376,7 +386,8 @@
checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx))
applicationId := a.appTestHelperAppProperties.Manifest_values.ApplicationId
if applicationId != nil {
- if a.overridableAppProperties.Package_name != nil {
+ packageName := a.overridableAppProperties.Package_name.Get(ctx)
+ if packageName.IsPresent() {
ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
}
a.aapt.manifestValues.applicationId = *applicationId
@@ -385,7 +396,10 @@
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
TestOnly: true,
})
-
+ android.SetProvider(ctx, AppInfoProvider, &AppInfo{
+ Updatable: Bool(a.appProperties.Updatable),
+ TestHelperApp: true,
+ })
}
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -393,6 +407,10 @@
a.checkEmbedJnis(ctx)
a.generateAndroidBuildActions(ctx)
a.generateJavaUsedByApex(ctx)
+ android.SetProvider(ctx, AppInfoProvider, &AppInfo{
+ Updatable: Bool(a.appProperties.Updatable),
+ TestHelperApp: false,
+ })
}
func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
@@ -428,7 +446,7 @@
func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) {
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
apkInApex := !apexInfo.IsForPlatform()
- hasJnis := len(a.appProperties.Jni_libs) > 0
+ hasJnis := len(a.appProperties.Jni_libs.GetOrDefault(ctx, nil)) > 0
if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) {
ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true")
@@ -569,10 +587,11 @@
}
manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName())
- if overridden || a.overridableAppProperties.Package_name != nil {
+ packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
+ if overridden || packageNameProp.IsPresent() {
// The product override variable has a priority over the package_name property.
if !overridden {
- manifestPackageName = *a.overridableAppProperties.Package_name
+ manifestPackageName = packageNameProp.Get()
}
aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, a.renameResourcesPackage())...)
a.overriddenManifestPackageName = manifestPackageName
@@ -586,7 +605,7 @@
if override := ctx.Config().Getenv("OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION"); override != "" {
a.aapt.defaultManifestVersion = override
} else {
- a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
+ a.aapt.defaultManifestVersion = ctx.Config().ReleaseDefaultUpdatableModuleVersion()
}
}
@@ -690,7 +709,7 @@
extraSrcJars = android.Paths{a.aapt.aaptSrcJar}
}
- a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
+ 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")
@@ -812,11 +831,12 @@
return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist)
}
- if a.overridableAppProperties.Package_name == nil {
+ packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
+ if packageNameProp.IsEmpty() {
ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist")
}
- packageName := *a.overridableAppProperties.Package_name
+ packageName := packageNameProp.Get()
fileName := "privapp_allowlist_" + packageName + ".xml"
outPath := android.PathForModuleOut(ctx, fileName).OutputPath
ctx.Build(pctx, android.BuildParams{
@@ -1009,6 +1029,8 @@
ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
}
+ ctx.CheckbuildFile(a.outputFile)
+
a.buildAppDependencyInfo(ctx)
providePrebuiltInfo(ctx,
@@ -1109,7 +1131,7 @@
coverageFile: dep.CoverageOutputFile(),
unstrippedFile: dep.UnstrippedOutputFile(),
partition: dep.Partition(),
- installPaths: dep.FilesToInstall(),
+ installPaths: android.OtherModuleProviderOrDefault(ctx, dep, android.InstallFilesProvider).InstallFiles,
})
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{otherName})
@@ -1133,7 +1155,7 @@
return jniLibs, prebuiltJniPackages
}
-func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
+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 {
@@ -1151,7 +1173,7 @@
}
depsInfo := android.DepNameToDepInfoMap{}
- a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
depName := to.Name()
// Skip dependencies that are only available to APEXes; they are developed with updatability
@@ -1204,10 +1226,6 @@
return Bool(a.appProperties.Updatable)
}
-func (a *AndroidApp) SetUpdatable(val bool) {
- a.appProperties.Updatable = &val
-}
-
func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string {
certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
if overridden {
@@ -1243,9 +1261,9 @@
var _ cc.Coverage = (*AndroidApp)(nil)
-func (a *AndroidApp) IDEInfo(dpInfo *android.IdeInfo) {
- a.Library.IDEInfo(dpInfo)
- a.aapt.IDEInfo(dpInfo)
+func (a *AndroidApp) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
+ a.Library.IDEInfo(ctx, dpInfo)
+ a.aapt.IDEInfo(ctx, dpInfo)
}
func (a *AndroidApp) productCharacteristicsRROPackageName() string {
@@ -1403,7 +1421,8 @@
}
applicationId := a.appTestProperties.Manifest_values.ApplicationId
if applicationId != nil {
- if a.overridableAppProperties.Package_name != nil {
+ packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
+ if packageNameProp.IsPresent() {
ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
}
a.aapt.manifestValues.applicationId = *applicationId
@@ -1415,7 +1434,8 @@
}
testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config,
- a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config, configs)
+ a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites,
+ a.testProperties.Auto_gen_config, configs, a.testProperties.Test_options.Test_runner_options)
a.testConfig = a.FixTestConfig(ctx, testConfig)
a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
@@ -1453,10 +1473,11 @@
command.FlagWithArg("--test-file-name ", a.installApkName+".apk")
}
- if a.overridableAppProperties.Package_name != nil {
+ packageNameProp := a.overridableAppProperties.Package_name.Get(ctx)
+ if packageNameProp.IsPresent() {
fixNeeded = true
command.FlagWithInput("--manifest ", a.manifestPath).
- FlagWithArg("--package-name ", *a.overridableAppProperties.Package_name)
+ FlagWithArg("--package-name ", packageNameProp.Get())
}
if a.appTestProperties.Mainline_package_name != nil {
@@ -1471,7 +1492,23 @@
return testConfig
}
+func (a *AndroidTestHelperApp) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") {
+ // Instrument the android_test_helper target to log potential API calls at the run time.
+ // Contact android-xts-infra team before using the environment var EMMA_API_MAPPER.
+ ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib")
+ a.setApiMapper(true)
+ }
+ a.AndroidApp.DepsMutator(ctx)
+}
+
func (a *AndroidTest) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if len(a.ApexProperties.Apex_available) == 0 && ctx.Config().IsEnvTrue("EMMA_API_MAPPER") {
+ // Instrument the android_test_helper target to log potential API calls at the run time.
+ // Contact android-xts-infra team before using the environment var EMMA_API_MAPPER.
+ ctx.AddVariationDependencies(nil, staticLibTag, "apimapper-helper-device-lib")
+ a.setApiMapper(true)
+ }
a.AndroidApp.DepsMutator(ctx)
}
@@ -1763,16 +1800,15 @@
}
}
- // Skip java_sdk_library dependencies that provide stubs, but not an implementation.
- // This will be restricted to optional_uses_libs
- if sdklib, ok := m.(SdkLibraryDependency); ok {
- if tag == usesLibOptTag && sdklib.DexJarBuildPath(ctx).PathOrNil() == nil {
- u.shouldDisableDexpreopt = true
- return
- }
- }
-
if lib, ok := m.(UsesLibraryDependency); ok {
+ 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 {
+ u.shouldDisableDexpreopt = true
+ return
+ }
+ }
libName := dep
if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
libName = *ulib.ProvidesUsesLib()
diff --git a/java/app_import.go b/java/app_import.go
index 045a89a..a54cf2f 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -533,10 +533,6 @@
return android.SdkSpecPrivate.ApiLevel
}
-func (a *AndroidAppImport) LintDepSets() LintDepSets {
- return LintDepSets{}
-}
-
var _ android.ApexModule = (*AndroidAppImport)(nil)
// Implements android.ApexModule
diff --git a/java/app_set.go b/java/app_set.go
index 33d3ade..7997570 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -35,7 +35,7 @@
type AndroidAppSetProperties struct {
// APK Set path
- Set *string
+ Set *string `android:"path"`
// Specifies that this app should be installed to the priv-app directory,
// where the system will grant it additional privileges not available to
diff --git a/java/app_set_test.go b/java/app_set_test.go
index 10bc5de..c02b359 100644
--- a/java/app_set_test.go
+++ b/java/app_set_test.go
@@ -56,7 +56,7 @@
mkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, module.Module())[0]
actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"]
expectedInstallFile := []string{
- strings.Replace(params.ImplicitOutputs[0].String(), android.OutSoongDir, result.Config.SoongOutDir(), 1),
+ strings.Replace(params.ImplicitOutputs[0].String(), android.TestOutSoongDir, result.Config.SoongOutDir(), 1),
}
if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) {
t.Errorf("Unexpected LOCAL_APK_SET_INSTALL_FILE value: '%s', expected: '%s',",
diff --git a/java/app_test.go b/java/app_test.go
index 6b7d522..dd672a0 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -119,7 +119,7 @@
foo.Output(expectedOutput)
}
- outputFiles := foo.OutputFiles(t, "")
+ outputFiles := foo.OutputFiles(ctx, t, "")
android.AssertPathsRelativeToTopEquals(t, `OutputFiles("")`, expectedOutputs, outputFiles)
}
@@ -530,9 +530,9 @@
`)
foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
android.AssertStringDoesContain(t,
- "com.android.foo: expected manifest fixer to set override-placeholder-version to android.DefaultUpdatableModuleVersion",
+ "com.android.foo: expected manifest fixer to set override-placeholder-version to RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION",
foo.BuildParams.Args["args"],
- fmt.Sprintf("--override-placeholder-version %s", android.DefaultUpdatableModuleVersion),
+ fmt.Sprintf("--override-placeholder-version %s", testDefaultUpdatableModuleVersion),
)
}
@@ -1419,26 +1419,31 @@
}
func TestAndroidResourceOverlays(t *testing.T) {
+ type moduleAndVariant struct {
+ module string
+ variant string
+ }
+
testCases := []struct {
name string
enforceRROTargets []string
enforceRROExcludedOverlays []string
- resourceFiles map[string][]string
- overlayFiles map[string][]string
- rroDirs map[string][]string
+ resourceFiles map[moduleAndVariant][]string
+ overlayFiles map[moduleAndVariant][]string
+ rroDirs map[moduleAndVariant][]string
}{
{
name: "no RRO",
enforceRROTargets: nil,
enforceRROExcludedOverlays: nil,
- resourceFiles: map[string][]string{
- "foo": nil,
- "bar": {"bar/res/res/values/strings.xml"},
- "lib": nil,
- "lib2": {"lib2/res/res/values/strings.xml"},
+ resourceFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: {"bar/res/res/values/strings.xml"},
+ {"lib", "android_common"}: nil,
+ {"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
},
- overlayFiles: map[string][]string{
- "foo": {
+ overlayFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"out/soong/.intermediates/lib/android_common/package-res.apk",
"out/soong/.intermediates/lib3/android_common/package-res.apk",
@@ -1447,57 +1452,65 @@
"device/vendor/blah/overlay/foo/res/values/strings.xml",
"product/vendor/blah/overlay/foo/res/values/strings.xml",
},
- "bar": {
+ {"bar", "android_common"}: {
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
"device/vendor/blah/overlay/bar/res/values/strings.xml",
},
- "lib": {
+ {"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",
},
},
- rroDirs: map[string][]string{
- "foo": nil,
- "bar": nil,
+ rroDirs: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: nil,
},
},
{
name: "enforce RRO on foo",
enforceRROTargets: []string{"foo"},
enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
- resourceFiles: map[string][]string{
- "foo": nil,
- "bar": {"bar/res/res/values/strings.xml"},
- "lib": nil,
- "lib2": {"lib2/res/res/values/strings.xml"},
+ resourceFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: {"bar/res/res/values/strings.xml"},
+ {"lib", "android_common"}: nil,
+ {"lib", "android_common_rro"}: nil,
+ {"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
+ {"lib2", "android_common_rro"}: {"lib2/res/res/values/strings.xml"},
},
- overlayFiles: map[string][]string{
- "foo": {
- "out/soong/.intermediates/lib2/android_common/package-res.apk",
- "out/soong/.intermediates/lib/android_common/package-res.apk",
- "out/soong/.intermediates/lib3/android_common/package-res.apk",
+ overlayFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
+ "out/soong/.intermediates/lib2/android_common_rro/package-res.apk",
+ "out/soong/.intermediates/lib/android_common_rro/package-res.apk",
+ "out/soong/.intermediates/lib3/android_common_rro/package-res.apk",
"foo/res/res/values/strings.xml",
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
- "bar": {
+ {"bar", "android_common"}: {
"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
"device/vendor/blah/overlay/bar/res/values/strings.xml",
},
- "lib": {
+ {"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",
},
},
- rroDirs: map[string][]string{
- "foo": {
+ rroDirs: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"device:device/vendor/blah/overlay/foo/res",
"product:product/vendor/blah/overlay/foo/res",
"device:device/vendor/blah/overlay/lib/res",
},
- "bar": nil,
- "lib": {"device:device/vendor/blah/overlay/lib/res"},
+ {"bar", "android_common"}: nil,
+ {"lib", "android_common"}: nil,
+ {"lib", "android_common_rro"}: {"device:device/vendor/blah/overlay/lib/res"},
},
},
{
@@ -1508,35 +1521,35 @@
"device/vendor/blah/static_overlay/foo",
"device/vendor/blah/static_overlay/bar/res",
},
- resourceFiles: map[string][]string{
- "foo": nil,
- "bar": {"bar/res/res/values/strings.xml"},
- "lib": nil,
- "lib2": {"lib2/res/res/values/strings.xml"},
+ resourceFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: nil,
+ {"bar", "android_common"}: {"bar/res/res/values/strings.xml"},
+ {"lib", "android_common"}: nil,
+ {"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
},
- overlayFiles: map[string][]string{
- "foo": {
+ overlayFiles: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"out/soong/.intermediates/lib2/android_common/package-res.apk",
"out/soong/.intermediates/lib/android_common/package-res.apk",
"out/soong/.intermediates/lib3/android_common/package-res.apk",
"foo/res/res/values/strings.xml",
"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
},
- "bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
- "lib": {
+ {"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",
},
},
- rroDirs: map[string][]string{
- "foo": {
+ rroDirs: map[moduleAndVariant][]string{
+ {"foo", "android_common"}: {
"device:device/vendor/blah/overlay/foo/res",
"product:product/vendor/blah/overlay/foo/res",
// Lib dep comes after the direct deps
"device:device/vendor/blah/overlay/lib/res",
},
- "bar": {"device:device/vendor/blah/overlay/bar/res"},
- "lib": {"device:device/vendor/blah/overlay/lib/res"},
+ {"bar", "android_common"}: {"device:device/vendor/blah/overlay/bar/res"},
+ {"lib", "android_common"}: {"device:device/vendor/blah/overlay/lib/res"},
},
},
}
@@ -1621,19 +1634,19 @@
for _, o := range list {
res := module.MaybeOutput(o)
if res.Rule != nil {
- // If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
+ // If the overlay is compiled as part of this moduleAndVariant (i.e. a .arsc.flat file),
// verify the inputs to the .arsc.flat rule.
files = append(files, res.Inputs.Strings()...)
} else {
- // Otherwise, verify the full path to the output of the other module
+ // Otherwise, verify the full path to the output of the other moduleAndVariant
files = append(files, o)
}
}
return files
}
- getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
- module := result.ModuleForTests(moduleName, "android_common")
+ getResources := func(moduleName, variantName string) (resourceFiles, overlayFiles, rroDirs []string) {
+ module := result.ModuleForTests(moduleName, variantName)
resourceList := module.MaybeOutput("aapt2/res.list")
if resourceList.Rule != nil {
resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs))
@@ -1658,21 +1671,33 @@
return resourceFiles, overlayFiles, rroDirs
}
- modules := []string{"foo", "bar", "lib", "lib2"}
- for _, module := range modules {
- resourceFiles, overlayFiles, rroDirs := getResources(module)
+ modules := []moduleAndVariant{
+ {"foo", "android_common"},
+ {"foo", "android_common_rro"},
+ {"bar", "android_common"},
+ {"bar", "android_common_rro"},
+ {"lib", "android_common"},
+ {"lib", "android_common_rro"},
+ {"lib2", "android_common"},
+ {"lib2", "android_common_rro"},
+ }
+ for _, moduleAndVariant := range modules {
+ if _, exists := testCase.resourceFiles[moduleAndVariant]; !exists {
+ continue
+ }
+ resourceFiles, overlayFiles, rroDirs := getResources(moduleAndVariant.module, moduleAndVariant.variant)
- if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
+ if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[moduleAndVariant]) {
t.Errorf("expected %s resource files:\n %#v\n got:\n %#v",
- module, testCase.resourceFiles[module], resourceFiles)
+ moduleAndVariant, testCase.resourceFiles[moduleAndVariant], resourceFiles)
}
- if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
+ if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[moduleAndVariant]) {
t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v",
- module, testCase.overlayFiles[module], overlayFiles)
+ moduleAndVariant, testCase.overlayFiles[moduleAndVariant], overlayFiles)
}
- if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
+ if !reflect.DeepEqual(rroDirs, testCase.rroDirs[moduleAndVariant]) {
t.Errorf("expected %s rroDirs: %#v\n got:\n %#v",
- module, testCase.rroDirs[module], rroDirs)
+ moduleAndVariant, testCase.rroDirs[moduleAndVariant], rroDirs)
}
}
})
@@ -3241,7 +3266,7 @@
java_library {
name: "static-runtime-helper",
srcs: ["a.java"],
- libs: ["runtime-library"],
+ libs: ["runtime-library.impl"],
sdk_version: "current",
}
@@ -3305,7 +3330,7 @@
name: "app",
srcs: ["a.java"],
libs: [
- "qux",
+ "qux.impl",
"quuz.stubs"
],
static_libs: [
diff --git a/java/base.go b/java/base.go
index 02df147..fc21c44 100644
--- a/java/base.go
+++ b/java/base.go
@@ -15,6 +15,7 @@
package java
import (
+ "encoding/gob"
"fmt"
"path/filepath"
"reflect"
@@ -80,10 +81,7 @@
Libs []string `android:"arch_variant"`
// list of java libraries that will be compiled into the resulting jar
- Static_libs []string `android:"arch_variant"`
-
- // list of java libraries that should not be used to build this module
- Exclude_static_libs []string `android:"arch_variant"`
+ Static_libs proptools.Configurable[[]string] `android:"arch_variant"`
// manifest file to be included in resulting jar
Manifest *string `android:"path"`
@@ -98,9 +96,6 @@
// if not blank, used as prefix to generate repackage rule
Jarjar_prefix *string
- // if set to true, skip the jarjar repackaging
- Skip_jarjar_repackage *bool
-
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -222,6 +217,25 @@
// the stubs via libs, but should be set to true when the module depends on
// the stubs via static libs.
Is_stubs_module *bool
+
+ Ravenizer struct {
+ // If true, enable the "Ravenizer" tool on the output jar.
+ // "Ravenizer" is a tool for Ravenwood tests, but it can also be enabled on other kinds
+ // of java targets.
+ Enabled *bool
+
+ // If true, the "Ravenizer" tool will remove all Mockito and DexMaker
+ // classes from the output jar.
+ Strip_mockito *bool
+ }
+
+ // Contributing api surface of the stub module. Is not visible to bp modules, and should
+ // only be set for stub submodules generated by the java_sdk_library
+ Stub_contributing_api *string `blueprint:"mutated"`
+
+ // If true, enable the "ApiMapper" tool on the output jar. "ApiMapper" is a tool to inject
+ // bytecode to log API calls.
+ ApiMapper bool `blueprint:"mutated"`
}
// Properties that are specific to device modules. Host module factories should not add these when
@@ -448,15 +462,10 @@
// inserting into the bootclasspath/classpath of another compile
headerJarFile android.Path
- repackagedHeaderJarFile android.Path
-
// jar file containing implementation classes including static library dependencies but no
// resources
implementationJarFile android.Path
- // jar file containing only resources including from static library dependencies
- resourceJar android.Path
-
// args and dependencies to package source files into a srcjar
srcJarArgs []string
srcJarDeps android.Paths
@@ -527,7 +536,8 @@
linter
// list of the xref extraction files
- kytheFiles android.Paths
+ kytheFiles android.Paths
+ kytheKotlinFiles android.Paths
hideApexVariantFromMake bool
@@ -558,13 +568,23 @@
// List of soong module dependencies required to compile the current module.
// This information is printed out to `Dependencies` field in module_bp_java_deps.json
compileDepNames []string
+
+ ravenizer struct {
+ enabled bool
+ }
}
var _ android.InstallableModule = (*Module)(nil)
// To satisfy the InstallableModule interface
-func (j *Module) EnforceApiContainerChecks() bool {
- return true
+func (j *Module) StaticDependencyTags() []blueprint.DependencyTag {
+ return []blueprint.DependencyTag{staticLibTag}
+}
+
+// To satisfy the InstallableModule interface
+func (j *Module) DynamicDependencyTags() []blueprint.DependencyTag {
+ return []blueprint.DependencyTag{libTag, sdkLibTag, bootClasspathTag, systemModulesTag,
+ instrumentationForTag, java9LibTag}
}
// Overrides android.ModuleBase.InstallInProduct()
@@ -572,6 +592,13 @@
return j.ProductSpecific()
}
+var _ android.StubsAvailableModule = (*Module)(nil)
+
+// To safisfy the StubsAvailableModule interface
+func (j *Module) IsStubsModule() bool {
+ return proptools.Bool(j.properties.Is_stubs_module)
+}
+
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
sdkVersion := j.SdkVersion(ctx)
if sdkVersion.Stable() {
@@ -682,9 +709,6 @@
ctx.SetOutputFiles(android.Paths{m.dexer.proguardDictionary.Path()}, ".proguard_map")
}
ctx.SetOutputFiles(m.properties.Generated_srcjars, ".generated_srcjars")
- if m.linter.outputs.xml != nil {
- ctx.SetOutputFiles(android.Paths{m.linter.outputs.xml}, ".lint")
- }
}
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
@@ -711,6 +735,10 @@
ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
}
+func (j *Module) shouldApiMapper() bool {
+ return j.properties.ApiMapper
+}
+
func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
return j.properties.Supports_static_instrumentation &&
j.shouldInstrument(ctx) &&
@@ -739,6 +767,10 @@
j.properties.Instrument = value
}
+func (j *Module) setApiMapper(value bool) {
+ j.properties.ApiMapper = value
+}
+
func (j *Module) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version))
}
@@ -795,6 +827,10 @@
return j.ApexModuleBase.AvailableFor(what)
}
+func (j *Module) staticLibs(ctx android.BaseModuleContext) []string {
+ return j.properties.Static_libs.GetOrDefault(ctx, nil)
+}
+
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if ctx.Device() {
j.linter.deps(ctx)
@@ -811,39 +847,11 @@
libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
- j.properties.Static_libs = android.RemoveListFromList(j.properties.Static_libs, j.properties.Exclude_static_libs)
- ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.staticLibs(ctx)...)
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
- if ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
- // Require java_sdk_library at inter-partition java dependency to ensure stable
- // interface between partitions. If inter-partition java_library dependency is detected,
- // raise build error because java_library doesn't have a stable interface.
- //
- // Inputs:
- // PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
- // if true, enable enforcement
- // PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
- // exception list of java_library names to allow inter-partition dependency
- for idx := range j.properties.Libs {
- if libDeps[idx] == nil {
- continue
- }
-
- if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok {
- // java_sdk_library is always allowed at inter-partition dependency.
- // So, skip check.
- if _, ok := javaDep.(*SdkLibrary); ok {
- continue
- }
-
- j.checkPartitionsForJavaDependency(ctx, "libs", javaDep)
- }
- }
- }
-
// 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 {
@@ -875,9 +883,12 @@
if j.hasSrcExt(".kt") {
// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
// Kotlin files
- ctx.AddVariationDependencies(nil, kotlinStdlibTag,
- "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8")
- ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
+ tag := staticLibTag
+ if !BoolDefault(j.properties.Static_kotlin_stdlib, true) {
+ tag = libTag
+ }
+ ctx.AddVariationDependencies(nil, tag,
+ "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-annotations")
}
// Framework libraries need special handling in static coverage builds: they should not have
@@ -891,7 +902,7 @@
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
- if j.useCompose() {
+ if j.useCompose(ctx) {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
"androidx.compose.compiler_compiler-hosted")
}
@@ -1112,24 +1123,26 @@
j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
}
-func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
-
+func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars, extraDepCombinedJars android.Paths) {
// Auto-propagating jarjar rules
jarjarProviderData := j.collectJarJarRules(ctx)
if jarjarProviderData != nil {
android.SetProvider(ctx, JarJarProvider, *jarjarProviderData)
- if !proptools.Bool(j.properties.Skip_jarjar_repackage) {
- text := getJarJarRuleText(jarjarProviderData)
- if text != "" {
- ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
- android.WriteFileRule(ctx, ruleTextFile, text)
- j.repackageJarjarRules = ruleTextFile
- }
+ text := getJarJarRuleText(jarjarProviderData)
+ if text != "" {
+ ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
+ android.WriteFileRule(ctx, ruleTextFile, text)
+ j.repackageJarjarRules = ruleTextFile
}
}
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
+ // Only override the original value if explicitly set
+ if j.properties.Ravenizer.Enabled != nil {
+ j.ravenizer.enabled = *j.properties.Ravenizer.Enabled
+ }
+
deps := j.collectDeps(ctx)
flags := j.collectBuilderFlags(ctx, deps)
@@ -1209,7 +1222,6 @@
// Collect .java and .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
- var kotlinJars android.Paths
var kotlinHeaderJars android.Paths
// Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
@@ -1219,6 +1231,8 @@
j.aconfigCacheFiles = append(deps.aconfigProtoFiles, j.properties.Aconfig_Cache_files...)
+ var localImplementationJars android.Paths
+
// If compiling headers then compile them and skip the rest
if proptools.Bool(j.properties.Headers_only) {
if srcFiles.HasExt(".kt") {
@@ -1228,17 +1242,43 @@
ctx.ModuleErrorf("headers_only is enabled but Turbine is disabled.")
}
- _, j.headerJarFile, _ =
- j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
- extraCombinedJars)
+ transitiveStaticLibsHeaderJars := deps.transitiveStaticLibsHeaderJars
+
+ localHeaderJars, combinedHeaderJarFile := j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
+ extraCombinedJars)
+
+ combinedHeaderJarFile, jarjared := j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine")
+ if jarjared {
+ localHeaderJars = android.Paths{combinedHeaderJarFile}
+ transitiveStaticLibsHeaderJars = nil
+ }
+ combinedHeaderJarFile, repackaged := j.repackageFlagsIfNecessary(ctx, combinedHeaderJarFile, jarName, "repackage-turbine")
+ if repackaged {
+ localHeaderJars = android.Paths{combinedHeaderJarFile}
+ transitiveStaticLibsHeaderJars = nil
+ }
if ctx.Failed() {
return
}
+ j.headerJarFile = combinedHeaderJarFile
- android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ 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()
+ }
+ } else {
+ ctx.CheckbuildFile(j.headerJarFile)
+ }
+
+ android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ LocalHeaderJars: localHeaderJars,
+ TransitiveStaticLibsHeaderJars: android.NewDepSet(android.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
+ TransitiveLibsHeaderJarsForR8: j.transitiveLibsHeaderJarsForR8,
+ TransitiveStaticLibsHeaderJarsForR8: j.transitiveStaticLibsHeaderJarsForR8,
AidlIncludeDirs: j.exportAidlIncludeDirs,
ExportedPlugins: j.exportedPluginJars,
ExportedPluginClasses: j.exportedPluginClasses,
@@ -1286,9 +1326,6 @@
// Collect common .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
- flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
- flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
-
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...)
flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...)
@@ -1298,7 +1335,7 @@
kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
kotlinKapt(ctx, kaptSrcJar, kaptResJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
srcJars = append(srcJars, kaptSrcJar)
- kotlinJars = append(kotlinJars, kaptResJar)
+ localImplementationJars = append(localImplementationJars, kaptResJar)
// Disable annotation processing in javac, it's already been handled by kapt
flags.processorPath = nil
flags.processors = nil
@@ -1306,37 +1343,29 @@
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
- kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ j.kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
- kotlinJarPath := j.repackageFlagsIfNecessary(ctx, kotlinJar.OutputPath, jarName, "kotlinc")
+ kotlinJarPath, _ := j.repackageFlagsIfNecessary(ctx, kotlinJar, jarName, "kotlinc")
// Make javac rule depend on the kotlinc rule
flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
- kotlinJars = append(kotlinJars, kotlinJarPath)
+ localImplementationJars = append(localImplementationJars, kotlinJarPath)
+
kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
-
- // Jar kotlin classes into the final jar after javac
- if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
- kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
- kotlinJars = append(kotlinJars, deps.kotlinAnnotations...)
- kotlinHeaderJars = append(kotlinHeaderJars, deps.kotlinStdlib...)
- kotlinHeaderJars = append(kotlinHeaderJars, deps.kotlinAnnotations...)
- } else {
- flags.dexClasspath = append(flags.dexClasspath, deps.kotlinStdlib...)
- flags.dexClasspath = append(flags.dexClasspath, deps.kotlinAnnotations...)
- }
}
- jars := slices.Clone(kotlinJars)
-
j.compiledSrcJars = srcJars
+ transitiveStaticLibsHeaderJars := deps.transitiveStaticLibsHeaderJars
+
enableSharding := false
- var headerJarFileWithoutDepsOrJarjar android.Path
+ var localHeaderJars android.Paths
+ var shardingHeaderJars android.Paths
+ var repackagedHeaderJarFile android.Path
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enableSharding = true
@@ -1346,11 +1375,28 @@
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
- extraJars := append(slices.Clone(kotlinHeaderJars), extraCombinedJars...)
- headerJarFileWithoutDepsOrJarjar, j.headerJarFile, j.repackagedHeaderJarFile =
- j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
- if ctx.Failed() {
- return
+ extraJars := slices.Clone(kotlinHeaderJars)
+ extraJars = append(extraJars, extraCombinedJars...)
+ var combinedHeaderJarFile android.Path
+ localHeaderJars, combinedHeaderJarFile = j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
+ shardingHeaderJars = localHeaderJars
+
+ var jarjared bool
+ j.headerJarFile, jarjared = j.jarjarIfNecessary(ctx, combinedHeaderJarFile, jarName, "turbine")
+ if jarjared {
+ // jarjar modifies transitive static dependencies, use the combined header jar and drop the transitive
+ // static libs header jars.
+ localHeaderJars = android.Paths{j.headerJarFile}
+ transitiveStaticLibsHeaderJars = nil
+ }
+ var repackaged bool
+ repackagedHeaderJarFile, repackaged = j.repackageFlagsIfNecessary(ctx, j.headerJarFile, jarName, "turbine")
+ if repackaged {
+ // repackage modifies transitive static dependencies, use the combined header jar and drop the transitive
+ // static libs header jars.
+ // TODO(b/356688296): this shouldn't export both the unmodified and repackaged header jars
+ localHeaderJars = android.Paths{j.headerJarFile, repackagedHeaderJarFile}
+ transitiveStaticLibsHeaderJars = nil
}
}
if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 {
@@ -1386,8 +1432,8 @@
}
if enableSharding {
- if headerJarFileWithoutDepsOrJarjar != nil {
- flags.classpath = append(classpath{headerJarFileWithoutDepsOrJarjar}, flags.classpath...)
+ if len(shardingHeaderJars) > 0 {
+ flags.classpath = append(classpath(slices.Clone(shardingHeaderJars)), flags.classpath...)
}
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
@@ -1396,8 +1442,8 @@
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
- classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
- jars = append(jars, classes)
+ classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
+ localImplementationJars = append(localImplementationJars, classes)
}
}
// Assume approximately 5 sources per srcjar.
@@ -1409,21 +1455,21 @@
for idx, shardSrcJars := range shardSrcJarsList {
classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
nil, shardSrcJars, flags, extraJarDeps)
- classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
- jars = append(jars, classes)
+ classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
+ localImplementationJars = append(localImplementationJars, classes)
}
}
} else {
classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
- classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
- jars = append(jars, classes)
+ classes, _ = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
+ localImplementationJars = append(localImplementationJars, classes)
}
if ctx.Failed() {
return
}
}
- jars = append(jars, extraCombinedJars...)
+ localImplementationJars = append(localImplementationJars, extraCombinedJars...)
j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
@@ -1450,40 +1496,18 @@
resArgs = append(resArgs, extraArgs...)
resDeps = append(resDeps, extraDeps...)
+ var localResourceJars android.Paths
if len(resArgs) > 0 {
resourceJar := android.PathForModuleOut(ctx, "res", jarName)
TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
- j.resourceJar = resourceJar
if ctx.Failed() {
return
}
+ localResourceJars = append(localResourceJars, resourceJar)
}
- var resourceJars android.Paths
- if j.resourceJar != nil {
- resourceJars = append(resourceJars, j.resourceJar)
- }
if Bool(j.properties.Include_srcs) {
- resourceJars = append(resourceJars, includeSrcJar)
- }
- resourceJars = append(resourceJars, deps.staticResourceJars...)
-
- if len(resourceJars) > 1 {
- combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
- false, nil, nil)
- j.resourceJar = combinedJar
- } else if len(resourceJars) == 1 {
- j.resourceJar = resourceJars[0]
- }
-
- if len(deps.staticJars) > 0 {
- jars = append(jars, deps.staticJars...)
- }
-
- manifest := j.overrideManifest
- if !manifest.Valid() && j.properties.Manifest != nil {
- manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest))
+ localResourceJars = append(localResourceJars, includeSrcJar)
}
services := android.PathsForModuleSrc(ctx, j.properties.Services)
@@ -1508,70 +1532,125 @@
Implicits: services,
Args: args,
})
- jars = append(jars, servicesJar)
+ localResourceJars = append(localResourceJars, servicesJar)
+ }
+
+ completeStaticLibsResourceJars := android.NewDepSet(android.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...)
+ }
+ if len(resourceJars) == 1 {
+ combinedResourceJar = resourceJars[0]
+ } else if len(resourceJars) > 0 {
+ combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{},
+ false, nil, nil)
+ combinedResourceJar = combinedJar
+ }
+
+ manifest := j.overrideManifest
+ if !manifest.Valid() && j.properties.Manifest != nil {
+ manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest))
}
// Combine the classes built from sources, any manifests, and any static libraries into
// classes.jar. If there is only one input jar this step will be skipped.
- var outputFile android.OutputPath
+ var outputFile android.Path
+
+ completeStaticLibsImplementationJars := android.NewDepSet(android.PREORDER, localImplementationJars, deps.transitiveStaticLibsImplementationJars)
+
+ var jars android.Paths
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ jars = completeStaticLibsImplementationJars.ToList()
+ } else {
+ jars = append(slices.Clone(localImplementationJars), deps.staticJars...)
+ }
+
+ jars = append(jars, extraDepCombinedJars...)
if len(jars) == 1 && !manifest.Valid() {
// Optimization: skip the combine step as there is nothing to do
// TODO(ccross): this leaves any module-info.class files, but those should only come from
// prebuilt dependencies until we support modules in the platform build, so there shouldn't be
- // any if len(jars) == 1.
+ // any if len(extraJars) == 0.
// moduleStubLinkType determines if the module is the TopLevelStubLibrary generated
// from sdk_library. The TopLevelStubLibrary contains only one static lib,
// either with .from-source or .from-text suffix.
// outputFile should be agnostic to the build configuration,
- // thus "combine" the single static lib in order to prevent the static lib from being exposed
+ // thus copy the single input static lib in order to prevent the static lib from being exposed
// to the copy rules.
- stub, _ := moduleStubLinkType(ctx.ModuleName())
-
- // Transform the single path to the jar into an OutputPath as that is required by the following
- // code.
- if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok && !stub {
- // The path contains an embedded OutputPath so reuse that.
- outputFile = moduleOutPath.OutputPath
- } else if outputPath, ok := jars[0].(android.OutputPath); ok && !stub {
- // The path is an OutputPath so reuse it directly.
- outputFile = outputPath
- } else {
- // The file is not in the out directory so create an OutputPath into which it can be copied
- // and which the following code can use to refer to it.
- combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
+ if stub, _ := moduleStubLinkType(j); stub {
+ copiedJar := android.PathForModuleOut(ctx, "combined", jarName)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: jars[0],
- Output: combinedJar,
+ Output: copiedJar,
})
- outputFile = combinedJar.OutputPath
+ completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, android.Paths{copiedJar}, nil)
+ outputFile = copiedJar
+ } else {
+ outputFile = jars[0]
}
} else {
combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
false, nil, nil)
- outputFile = combinedJar.OutputPath
+ outputFile = combinedJar
}
// jarjar implementation jar if necessary
- if j.expandJarjarRules != nil {
- // Transform classes.jar into classes-jarjar.jar
- jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName).OutputPath
- TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules)
- outputFile = jarjarFile
+ jarjarFile, jarjarred := j.jarjarIfNecessary(ctx, outputFile, jarName, "")
+ if jarjarred {
+ localImplementationJars = android.Paths{jarjarFile}
+ completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, localImplementationJars, nil)
+ }
+ outputFile = jarjarFile
- // jarjar resource jar if necessary
- if j.resourceJar != nil {
- resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName)
- TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, j.expandJarjarRules)
- j.resourceJar = resourceJarJarFile
+ // jarjar resource jar if necessary
+ if combinedResourceJar != nil {
+ resourceJarJarFile, jarjarred := j.jarjarIfNecessary(ctx, combinedResourceJar, jarName, "resource")
+ combinedResourceJar = resourceJarJarFile
+ if jarjarred {
+ localResourceJars = android.Paths{resourceJarJarFile}
+ completeStaticLibsResourceJars = android.NewDepSet(android.PREORDER, localResourceJars, nil)
}
+ }
- if ctx.Failed() {
- return
+ if ctx.Failed() {
+ return
+ }
+
+ if j.ravenizer.enabled {
+ ravenizerInput := outputFile
+ ravenizerOutput := android.PathForModuleOut(ctx, "ravenizer", jarName)
+ ravenizerArgs := ""
+ if proptools.Bool(j.properties.Ravenizer.Strip_mockito) {
+ ravenizerArgs = "--strip-mockito"
}
+ TransformRavenizer(ctx, ravenizerOutput, ravenizerInput, ravenizerArgs)
+ outputFile = ravenizerOutput
+ localImplementationJars = android.Paths{ravenizerOutput}
+ completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, localImplementationJars, nil)
+ }
+
+ if j.shouldApiMapper() {
+ inputFile := outputFile
+ apiMapperFile := android.PathForModuleOut(ctx, "apimapper", jarName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apimapper,
+ Description: "apimapper",
+ Input: inputFile,
+ Output: apiMapperFile,
+ })
+ outputFile = apiMapperFile
+ localImplementationJars = android.Paths{apiMapperFile}
+ completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, localImplementationJars, nil)
}
// Check package restrictions if necessary.
@@ -1583,15 +1662,18 @@
// will check that the jar only contains the permitted packages. The new location will become
// the output file of this module.
inputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "package-check", jarName).OutputPath
+ packageCheckOutputFile := android.PathForModuleOut(ctx, "package-check", jarName)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: inputFile,
- Output: outputFile,
+ Output: packageCheckOutputFile,
// Make sure that any dependency on the output file will cause ninja to run the package check
// rule.
Validation: pkgckFile,
})
+ outputFile = packageCheckOutputFile
+ localImplementationJars = android.Paths{packageCheckOutputFile}
+ completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, localImplementationJars, nil)
// Check packages and create a timestamp file when complete.
CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
@@ -1610,6 +1692,13 @@
headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName)
convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile)
j.headerJarFile = headerJarFile
+ if len(localImplementationJars) == 1 && ctx.Config().UseTransitiveJarsInClasspath() {
+ localHeaderJarFile := android.PathForModuleOut(ctx, "local-javac-header", jarName)
+ convertImplementationJarToHeaderJar(ctx, localImplementationJars[0], localHeaderJarFile)
+ localHeaderJars = append(localHeaderJars, localHeaderJarFile)
+ } else {
+ localHeaderJars = append(localHeaderJars, headerJarFile)
+ }
}
// enforce syntax check to jacoco filters for any build (http://b/183622051)
@@ -1618,21 +1707,36 @@
return
}
+ completeStaticLibsImplementationJarsToCombine := completeStaticLibsImplementationJars
+
if j.shouldInstrument(ctx) {
- outputFile = j.instrument(ctx, flags, outputFile, jarName, specs)
+ instrumentedOutputFile := j.instrument(ctx, flags, outputFile, jarName, specs)
+ completeStaticLibsImplementationJarsToCombine = android.NewDepSet(android.PREORDER, android.Paths{instrumentedOutputFile}, nil)
+ outputFile = instrumentedOutputFile
}
// merge implementation jar with resources if necessary
- implementationAndResourcesJar := outputFile
- if j.resourceJar != nil {
- jars := android.Paths{j.resourceJar, implementationAndResourcesJar}
- combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest,
- false, nil, nil)
- implementationAndResourcesJar = combinedJar
+ 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}
+ }
}
- j.implementationAndResourcesJar = implementationAndResourcesJar
+ if len(implementationAndResourcesJarsToCombine) > 0 {
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", implementationAndResourcesJarsToCombine, manifest,
+ false, nil, nil)
+ outputFile = combinedJar
+ }
+
+ j.implementationAndResourcesJar = outputFile
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
compileDex := j.dexProperties.Compile_dex
@@ -1653,22 +1757,22 @@
android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
// Dex compilation
- var dexOutputFile android.OutputPath
+ var dexOutputFile android.Path
params := &compileDexParams{
flags: flags,
sdkVersion: j.SdkVersion(ctx),
minSdkVersion: j.MinSdkVersion(ctx),
- classesJar: implementationAndResourcesJar,
+ classesJar: outputFile,
jarName: jarName,
}
- if j.GetProfileGuided() && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting() {
+ if j.GetProfileGuided(ctx) && j.optimizeOrObfuscateEnabled() && !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.",
)
}
- if j.EnableProfileRewriting() {
- profile := j.GetProfile()
- if profile == "" || !j.GetProfileGuided() {
+ if j.EnableProfileRewriting(ctx) {
+ profile := j.GetProfile(ctx)
+ if profile == "" || !j.GetProfileGuided(ctx) {
ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
}
params.artProfileInput = &profile
@@ -1680,17 +1784,27 @@
// If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
if dexArtProfileOutput != nil {
- j.dexpreopter.SetRewrittenProfile(*dexArtProfileOutput)
+ j.dexpreopter.SetRewrittenProfile(dexArtProfileOutput)
}
// merge dex jar with resources if necessary
- if j.resourceJar != nil {
- jars := android.Paths{dexOutputFile, j.resourceJar}
- combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
+ 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 {
+ combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for dex resources", dexAndResourceJarsToCombine, android.OptionalPath{},
false, nil, nil)
if *j.dexProperties.Uncompress_dex {
- combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
+ combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil)
dexOutputFile = combinedAlignedJar
} else {
@@ -1715,18 +1829,17 @@
j.dexpreopt(ctx, libName, dexOutputFile)
outputFile = dexOutputFile
+
+ ctx.CheckbuildFile(dexOutputFile)
} else {
// There is no code to compile into a dex jar, make sure the resources are propagated
// to the APK if this is an app.
- outputFile = implementationAndResourcesJar
- j.dexJarFile = makeDexJarPathFromPath(j.resourceJar)
+ j.dexJarFile = makeDexJarPathFromPath(combinedResourceJar)
}
if ctx.Failed() {
return
}
- } else {
- outputFile = implementationAndResourcesJar
}
if ctx.Device() {
@@ -1758,16 +1871,34 @@
j.collectTransitiveSrcFiles(ctx, srcFiles)
- ctx.CheckbuildFile(outputFile)
+ 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()
+ }
+ } else {
+ ctx.CheckbuildFile(j.implementationJarFile)
+ ctx.CheckbuildFile(j.headerJarFile)
+ }
- android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ RepackagedHeaderJars: android.PathsIfNonNil(repackagedHeaderJarFile),
+
+ LocalHeaderJars: localHeaderJars,
+ TransitiveStaticLibsHeaderJars: android.NewDepSet(android.PREORDER, localHeaderJars, transitiveStaticLibsHeaderJars),
+ TransitiveStaticLibsImplementationJars: completeStaticLibsImplementationJars,
+ TransitiveStaticLibsResourceJars: completeStaticLibsResourceJars,
+
+ TransitiveLibsHeaderJarsForR8: j.transitiveLibsHeaderJarsForR8,
+ TransitiveStaticLibsHeaderJarsForR8: j.transitiveStaticLibsHeaderJarsForR8,
ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
- ResourceJars: android.PathsIfNonNil(j.resourceJar),
+ ResourceJars: android.PathsIfNonNil(combinedResourceJar),
AidlIncludeDirs: j.exportAidlIncludeDirs,
SrcJarArgs: j.srcJarArgs,
SrcJarDeps: j.srcJarDeps,
@@ -1784,8 +1915,8 @@
j.outputFile = outputFile.WithoutRel()
}
-func (j *Module) useCompose() bool {
- return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs)
+func (j *Module) useCompose(ctx android.BaseModuleContext) bool {
+ return android.InList("androidx.compose.runtime_runtime", j.staticLibs(ctx))
}
func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) {
@@ -1850,7 +1981,7 @@
}
func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
- srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.Path {
kzipName := pathtools.ReplaceExtension(jarName, "kzip")
annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
@@ -1860,7 +1991,7 @@
jarName += strconv.Itoa(idx)
}
- classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
+ classes := android.PathForModuleOut(ctx, "javac", jarName)
TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
if ctx.Config().EmitXrefRules() && ctx.Module() == ctx.PrimaryModule() {
@@ -1903,62 +2034,41 @@
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar android.Path) {
+ extraJars android.Paths) (localHeaderJars android.Paths, combinedHeaderJar android.Path) {
- var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
// Compile java sources into turbine.jar.
turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
- if ctx.Failed() {
- return nil, nil, nil
- }
- jars = append(jars, turbineJar)
- headerJar = turbineJar
+ localHeaderJars = append(localHeaderJars, turbineJar)
}
- jars = append(jars, extraJars...)
+ localHeaderJars = append(localHeaderJars, extraJars...)
// Combine any static header libraries into classes-header.jar. If there is only
// one input jar this step will be skipped.
- jars = append(jars, deps.staticHeaderJars...)
+ var jars android.Paths
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ depSet := android.NewDepSet(android.PREORDER, localHeaderJars, deps.transitiveStaticLibsHeaderJars)
+ jars = depSet.ToList()
+ } else {
+ jars = append(slices.Clone(localHeaderJars), deps.staticHeaderJars...)
+ }
// 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
- combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
+ combinedHeaderJarOutputPath := android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ TransformJarsToJar(ctx, combinedHeaderJarOutputPath, "for turbine", jars, android.OptionalPath{},
false, nil, []string{"META-INF/TRANSITIVE"})
- jarjarAndDepsHeaderJar = combinedJar
- if j.expandJarjarRules != nil {
- // Transform classes.jar into classes-jarjar.jar
- jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
- TransformJarJar(ctx, jarjarFile, jarjarAndDepsHeaderJar, j.expandJarjarRules)
- jarjarAndDepsHeaderJar = jarjarFile
- if ctx.Failed() {
- return nil, nil, nil
- }
- }
-
- if j.repackageJarjarRules != nil {
- repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-turbine-jarjar", jarName)
- TransformJarJar(ctx, repackagedJarjarFile, jarjarAndDepsHeaderJar, j.repackageJarjarRules)
- jarjarAndDepsRepackagedHeaderJar = repackagedJarjarFile
- if ctx.Failed() {
- return nil, nil, nil
- }
- } else {
- jarjarAndDepsRepackagedHeaderJar = jarjarAndDepsHeaderJar
- }
-
- return headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar
+ return localHeaderJars, combinedHeaderJarOutputPath
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string, specs string) android.OutputPath {
+ classesJar android.Path, jarName string, specs string) android.Path {
jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName)
- instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath
+ instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName)
jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs)
@@ -1967,22 +2077,18 @@
return instrumentedJar
}
-type providesTransitiveHeaderJars struct {
+type providesTransitiveHeaderJarsForR8 struct {
// set of header jars for all transitive libs deps
- transitiveLibsHeaderJars *android.DepSet[android.Path]
+ transitiveLibsHeaderJarsForR8 *android.DepSet[android.Path]
// set of header jars for all transitive static libs deps
- transitiveStaticLibsHeaderJars *android.DepSet[android.Path]
+ transitiveStaticLibsHeaderJarsForR8 *android.DepSet[android.Path]
}
-func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet[android.Path] {
- return j.transitiveLibsHeaderJars
-}
-
-func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet[android.Path] {
- return j.transitiveStaticLibsHeaderJars
-}
-
-func (j *providesTransitiveHeaderJars) collectTransitiveHeaderJars(ctx android.ModuleContext) {
+// collectTransitiveHeaderJarsForR8 visits direct dependencies and collects all transitive libs and static_libs
+// header jars. The semantics of the collected jars are odd (it collects combined jars that contain the static
+// libs, but also the static libs, and it collects transitive libs dependencies of static_libs), so these
+// are only used to expand the --lib arguments to R8.
+func (j *providesTransitiveHeaderJarsForR8) collectTransitiveHeaderJarsForR8(ctx android.ModuleContext) {
directLibs := android.Paths{}
directStaticLibs := android.Paths{}
transitiveLibs := []*android.DepSet[android.Path]{}
@@ -1993,27 +2099,29 @@
return
}
- dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
- tag := ctx.OtherModuleDependencyTag(module)
- _, isUsesLibDep := tag.(usesLibraryDependencyTag)
- if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
- directLibs = append(directLibs, dep.HeaderJars...)
- } else if tag == staticLibTag {
- directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
- } else {
- // Don't propagate transitive libs for other kinds of dependencies.
- return
- }
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ tag := ctx.OtherModuleDependencyTag(module)
+ _, isUsesLibDep := tag.(usesLibraryDependencyTag)
+ if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
+ directLibs = append(directLibs, dep.HeaderJars...)
+ } else if tag == staticLibTag {
+ directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
+ } else {
+ // Don't propagate transitive libs for other kinds of dependencies.
+ return
+ }
- if dep.TransitiveLibsHeaderJars != nil {
- transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
- }
- if dep.TransitiveStaticLibsHeaderJars != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
+ if dep.TransitiveLibsHeaderJarsForR8 != nil {
+ transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJarsForR8)
+ }
+ if dep.TransitiveStaticLibsHeaderJarsForR8 != nil {
+ transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJarsForR8)
+ }
+
}
})
- j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
- j.transitiveStaticLibsHeaderJars = android.NewDepSet(android.POSTORDER, directStaticLibs, transitiveStaticLibs)
+ j.transitiveLibsHeaderJarsForR8 = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
+ j.transitiveStaticLibsHeaderJarsForR8 = android.NewDepSet(android.POSTORDER, directStaticLibs, transitiveStaticLibs)
}
func (j *Module) HeaderJars() android.Paths {
@@ -2055,17 +2163,21 @@
}
// Collect information for opening IDE project files in java/jdeps.go.
-func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
- dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
- dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
- dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
+func (j *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
+ // jarjar rules will repackage the sources. To prevent misleading results, IdeInfo should contain the
+ // repackaged jar instead of the input sources.
if j.expandJarjarRules != nil {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
+ dpInfo.Jars = append(dpInfo.Jars, j.headerJarFile.String())
+ } else {
+ dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
}
- dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...)
+ dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
+ dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
+ dpInfo.Static_libs = append(dpInfo.Static_libs, j.staticLibs(ctx)...)
dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
}
func (j *Module) CompilerDeps() []string {
@@ -2115,9 +2227,10 @@
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
if tag == staticLibTag {
- depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
- if depInfo.TransitiveSrcFiles != nil {
- fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles)
+ if depInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if depInfo.TransitiveSrcFiles != nil {
+ fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles)
+ }
}
}
})
@@ -2174,6 +2287,25 @@
getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool)
}
+func sdkLinkTypeFromSdkKind(k android.SdkKind) sdkLinkType {
+ switch k {
+ case android.SdkCore:
+ return javaCore
+ case android.SdkSystem:
+ return javaSystem
+ case android.SdkPublic:
+ return javaSdk
+ case android.SdkModule:
+ return javaModule
+ case android.SdkSystemServer:
+ return javaSystemServer
+ case android.SdkPrivate, android.SdkNone, android.SdkCorePlatform, android.SdkTest:
+ return javaPlatform
+ default:
+ return javaSdk
+ }
+}
+
func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
switch name {
case android.SdkCore.DefaultJavaLibraryName(),
@@ -2195,30 +2327,16 @@
return javaSystem, true
}
- if stub, linkType := moduleStubLinkType(name); stub {
+ if stub, linkType := moduleStubLinkType(m); stub {
return linkType, true
}
ver := m.SdkVersion(ctx)
- switch ver.Kind {
- case android.SdkCore:
- return javaCore, false
- case android.SdkSystem:
- return javaSystem, false
- case android.SdkPublic:
- return javaSdk, false
- case android.SdkModule:
- return javaModule, false
- case android.SdkSystemServer:
- return javaSystemServer, false
- case android.SdkPrivate, android.SdkNone, android.SdkCorePlatform, android.SdkTest:
- return javaPlatform, false
- }
-
if !ver.Valid() {
panic(fmt.Errorf("sdk_version is invalid. got %q", ver.Raw))
}
- return javaSdk, false
+
+ return sdkLinkTypeFromSdkKind(ver.Kind), false
}
// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
@@ -2247,24 +2365,17 @@
func (j *Module) collectDeps(ctx android.ModuleContext) deps {
var deps deps
- if ctx.Device() {
- sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
- if sdkDep.invalidVersion {
- ctx.AddMissingDependencies(sdkDep.bootclasspath)
- ctx.AddMissingDependencies(sdkDep.java9Classpath)
- } else if sdkDep.useFiles {
- // sdkDep.jar is actually equivalent to turbine header.jar.
- deps.classpath = append(deps.classpath, sdkDep.jars...)
- deps.dexClasspath = append(deps.dexClasspath, sdkDep.jars...)
- deps.aidlPreprocess = sdkDep.aidl
- } else {
- deps.aidlPreprocess = sdkDep.aidl
- }
- }
-
sdkLinkType, _ := j.getSdkLinkType(ctx, ctx.ModuleName())
- j.collectTransitiveHeaderJars(ctx)
+ j.collectTransitiveHeaderJarsForR8(ctx)
+
+ var transitiveBootClasspathHeaderJars []*android.DepSet[android.Path]
+ var transitiveClasspathHeaderJars []*android.DepSet[android.Path]
+ var transitiveJava9ClasspathHeaderJars []*android.DepSet[android.Path]
+ var transitiveStaticJarsHeaderLibs []*android.DepSet[android.Path]
+ var transitiveStaticJarsImplementationLibs []*android.DepSet[android.Path]
+ var transitiveStaticJarsResourceLibs []*android.DepSet[android.Path]
+
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -2278,14 +2389,12 @@
return
}
- if dep, ok := module.(SdkLibraryDependency); ok {
+ if sdkInfo, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
switch tag {
- case sdkLibTag, libTag:
- depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))
- deps.classpath = append(deps.classpath, depHeaderJars...)
- deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...)
- case staticLibTag:
- ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+ case sdkLibTag, libTag, staticLibTag:
+ generatingLibsString := android.PrettyConcat(
+ getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
+ ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
}
} else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
if sdkLinkType != javaPlatform {
@@ -2299,6 +2408,9 @@
switch tag {
case bootClasspathTag:
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
case sdkLibTag, libTag, instrumentationForTag:
if _, ok := module.(*Plugin); ok {
ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName)
@@ -2312,8 +2424,15 @@
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
case java9LibTag:
deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveJava9ClasspathHeaderJars = append(transitiveJava9ClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
case staticLibTag:
if _, ok := module.(*Plugin); ok {
ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName)
@@ -2329,6 +2448,17 @@
// optimization.
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
+
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, dep.TransitiveStaticLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsImplementationJars != nil {
+ transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, dep.TransitiveStaticLibsImplementationJars)
+ }
+ if dep.TransitiveStaticLibsResourceJars != nil {
+ transitiveStaticJarsResourceLibs = append(transitiveStaticJarsResourceLibs, dep.TransitiveStaticLibsResourceJars)
+ }
case pluginTag:
if plugin, ok := module.(*Plugin); ok {
if plugin.pluginProperties.Processor_class != nil {
@@ -2362,10 +2492,6 @@
} else {
ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName)
}
- case kotlinStdlibTag:
- deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
- case kotlinAnnotationsTag:
- deps.kotlinAnnotations = dep.HeaderJars
case kotlinPluginTag:
deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
case syspropPublicStubDepTag:
@@ -2381,11 +2507,18 @@
checkProducesJars(ctx, dep)
deps.classpath = append(deps.classpath, dep.Srcs()...)
deps.dexClasspath = append(deps.classpath, dep.Srcs()...)
+ transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars,
+ android.NewDepSet(android.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()...)
+
+ depHeaderJars := android.NewDepSet(android.PREORDER, dep.Srcs(), nil)
+ transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, depHeaderJars)
+ transitiveStaticJarsHeaderLibs = append(transitiveStaticJarsHeaderLibs, depHeaderJars)
+ transitiveStaticJarsImplementationLibs = append(transitiveStaticJarsImplementationLibs, depHeaderJars)
}
} else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
switch tag {
@@ -2397,16 +2530,27 @@
case bootClasspathTag:
// If a system modules dependency has been added to the bootclasspath
// then add its libs to the bootclasspath.
- sm := module.(SystemModulesProvider)
- deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
+ if sm, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
+ deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars...)
+ if sm.TransitiveStaticLibsHeaderJars != nil {
+ transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars,
+ sm.TransitiveStaticLibsHeaderJars)
+ }
+ } else {
+ ctx.PropertyErrorf("boot classpath dependency %q does not provide SystemModulesProvider",
+ ctx.OtherModuleName(module))
+ }
case systemModulesTag:
if deps.systemModules != nil {
panic("Found two system module dependencies")
}
- sm := module.(SystemModulesProvider)
- outputDir, outputDeps := sm.OutputDirAndDeps()
- deps.systemModules = &systemModules{outputDir, outputDeps}
+ if sm, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
+ deps.systemModules = &systemModules{sm.OutputDir, sm.OutputDirDeps}
+ } else {
+ ctx.PropertyErrorf("system modules dependency %q does not provide SystemModulesProvider",
+ ctx.OtherModuleName(module))
+ }
case instrumentationForTag:
ctx.PropertyErrorf("instrumentation_for", "dependency %q of type %q does not provide JavaInfo so is unsuitable for use with this property", ctx.OtherModuleName(module), ctx.OtherModuleType(module))
@@ -2422,6 +2566,39 @@
addMissingOptionalUsesLibsFromDep(ctx, module, &j.usesLibrary)
})
+ deps.transitiveStaticLibsHeaderJars = transitiveStaticJarsHeaderLibs
+ deps.transitiveStaticLibsImplementationJars = transitiveStaticJarsImplementationLibs
+ deps.transitiveStaticLibsResourceJars = transitiveStaticJarsResourceLibs
+
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ depSet := android.NewDepSet(android.PREORDER, nil, transitiveClasspathHeaderJars)
+ deps.classpath = depSet.ToList()
+ depSet = android.NewDepSet(android.PREORDER, nil, transitiveBootClasspathHeaderJars)
+ deps.bootClasspath = depSet.ToList()
+ depSet = android.NewDepSet(android.PREORDER, nil, transitiveJava9ClasspathHeaderJars)
+ deps.java9Classpath = depSet.ToList()
+ }
+
+ if ctx.Device() {
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
+ if sdkDep.invalidVersion {
+ ctx.AddMissingDependencies(sdkDep.bootclasspath)
+ ctx.AddMissingDependencies(sdkDep.java9Classpath)
+ } else if sdkDep.useFiles {
+ // sdkDep.jar is actually equivalent to turbine header.jar.
+ deps.classpath = append(slices.Clone(classpath(sdkDep.jars)), deps.classpath...)
+ deps.dexClasspath = append(slices.Clone(classpath(sdkDep.jars)), deps.dexClasspath...)
+ deps.aidlPreprocess = sdkDep.aidl
+ // Add the sdk module dependency to `compileDepNames`.
+ // This ensures that the dependency is reported in `module_bp_java_deps.json`
+ // TODO (b/358608607): Move this to decodeSdkDep
+ sdkSpec := android.SdkContext(j).SdkVersion(ctx)
+ j.compileDepNames = append(j.compileDepNames, fmt.Sprintf("sdk_%s_%s_android", sdkSpec.Kind.String(), sdkSpec.ApiLevel.String()))
+ } else {
+ deps.aidlPreprocess = sdkDep.aidl
+ }
+ }
+
return deps
}
@@ -2472,6 +2649,8 @@
func init() {
android.SetJarJarPrefixHandler(mergeJarJarPrefixes)
+
+ gob.Register(BaseJarJarProviderData{})
}
// BaseJarJarProviderData contains information that will propagate across dependencies regardless of
@@ -2521,7 +2700,7 @@
module := ctx.Module()
moduleName := module.Name()
- ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) {
+ ctx.VisitDirectDeps(func(m android.Module) {
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
@@ -2544,7 +2723,7 @@
if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
return RenameUseExclude, "tags"
}
- if _, ok := m.(SdkLibraryDependency); ok {
+ if _, ok := android.OtherModuleProvider(ctx, m, SdkLibraryInfoProvider); ok {
switch tag {
case sdkLibTag, libTag:
return RenameUseExclude, "sdklibdep" // matches collectDeps()
@@ -2581,8 +2760,6 @@
return RenameUseInclude, "tagswitch"
case exportedPluginTag:
return RenameUseInclude, "tagswitch"
- case kotlinStdlibTag, kotlinAnnotationsTag:
- return RenameUseExclude, "tagswitch"
case kotlinPluginTag:
return RenameUseInclude, "tagswitch"
default:
@@ -2733,13 +2910,23 @@
}
// Repackage the flags if the jarjar rule txt for the flags is generated
-func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.WritablePath, jarName, info string) android.WritablePath {
+func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string) (android.Path, bool) {
if j.repackageJarjarRules == nil {
- return infile
+ return infile, false
}
- repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info+jarName)
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info, jarName)
TransformJarJar(ctx, repackagedJarjarFile, infile, j.repackageJarjarRules)
- return repackagedJarjarFile
+ return repackagedJarjarFile, true
+}
+
+func (j *Module) jarjarIfNecessary(ctx android.ModuleContext, infile android.Path, jarName, info string) (android.Path, bool) {
+ if j.expandJarjarRules == nil {
+ return infile, false
+ }
+ jarjarFile := android.PathForModuleOut(ctx, "jarjar", info, jarName)
+ TransformJarJar(ctx, jarjarFile, infile, j.expandJarjarRules)
+ return jarjarFile, true
+
}
func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
diff --git a/java/boot_jars.go b/java/boot_jars.go
index 6223ded..3c3bd55 100644
--- a/java/boot_jars.go
+++ b/java/boot_jars.go
@@ -21,7 +21,7 @@
// isActiveModule returns true if the given module should be considered for boot
// jars, i.e. if it's enabled and the preferred one in case of source and
// prebuilt alternatives.
-func isActiveModule(ctx android.ConfigAndErrorContext, module android.Module) bool {
+func isActiveModule(ctx android.ConfigurableEvaluatorContext, module android.Module) bool {
if !module.Enabled(ctx) {
return false
}
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 77ddf5c..029f6f6 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -196,7 +196,7 @@
type BootclasspathNestedAPIProperties struct {
// java_library or preferably, java_sdk_library modules providing stub classes that define the
// APIs provided by this bootclasspath_fragment.
- Stub_libs []string
+ Stub_libs proptools.Configurable[[]string]
}
// BootclasspathAPIProperties defines properties for defining the API provided by parts of the
@@ -229,11 +229,11 @@
// apiScopeToStubLibs calculates the stub library modules for each relevant *HiddenAPIScope from the
// Stub_libs properties.
-func (p BootclasspathAPIProperties) apiScopeToStubLibs() map[*HiddenAPIScope][]string {
+func (p BootclasspathAPIProperties) apiScopeToStubLibs(ctx android.BaseModuleContext) map[*HiddenAPIScope][]string {
m := map[*HiddenAPIScope][]string{}
for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
- m[apiScope] = p.Api.Stub_libs
+ m[apiScope] = p.Api.Stub_libs.GetOrDefault(ctx, nil)
}
- m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs
+ m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs.GetOrDefault(ctx, nil)
return m
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 16209b7..4fcd40b 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -414,6 +414,12 @@
// Cross-cutting metadata dependencies are metadata.
return false
}
+ // Dependency to the bootclasspath fragment of another apex
+ // e.g. concsrypt-bootclasspath-fragment --> art-bootclasspath-fragment
+ if tag == bootclasspathFragmentDepTag {
+ return false
+
+ }
panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
}
@@ -445,7 +451,7 @@
func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies onto all the modules that provide the API stubs for classes on this
// bootclasspath fragment.
- hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs())
+ hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs(ctx))
for _, additionalStubModule := range b.properties.Additional_stubs {
for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
@@ -463,6 +469,12 @@
// 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) {
@@ -836,7 +848,7 @@
}
// Collect information for opening IDE project files in java/jdeps.go.
-func (b *BootclasspathFragmentModule) IDEInfo(dpInfo *android.IdeInfo) {
+func (b *BootclasspathFragmentModule) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, b.properties.Contents...)
}
@@ -933,8 +945,8 @@
b.Filtered_flags_path = android.OptionalPathForPath(hiddenAPIInfo.FilteredFlagsPath)
// Copy stub_libs properties.
- b.Stub_libs = module.properties.Api.Stub_libs
- b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs
+ b.Stub_libs = module.properties.Api.Stub_libs.GetOrDefault(mctx, nil)
+ b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs.GetOrDefault(mctx, nil)
// Copy fragment properties.
b.Fragments = module.properties.Fragments
@@ -1093,22 +1105,10 @@
return &output
}
+// DEPRECATED: this information is now generated in the context of the top level prebuilt apex.
// produceBootImageProfile extracts the boot image profile from the APEX if available.
func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx android.ModuleContext) android.WritablePath {
- // This module does not provide a boot image profile.
- if module.getProfileProviderApex(ctx) == "" {
- return nil
- }
-
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- // An error was found, possibly due to multiple apexes in the tree that export this library
- // Defer the error till a client tries to call getProfilePath
- module.profilePathErr = err
- return nil // An error has been reported by FindDeapexerProviderForModule.
- }
-
- return di.PrebuiltExportPath(ProfileInstallPathInApex)
+ return android.PathForModuleInstall(ctx, "intentionally_no_longer_supported")
}
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 8bc0a7e..60f1a50 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -222,11 +222,7 @@
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
FixtureConfigureApexBootJars("someapex:mysdklibrary"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
bootclasspath_fragment {
name: "myfragment",
@@ -277,7 +273,7 @@
`)
fragment := result.Module("myfragment", "android_common")
- info, _ := android.SingletonModuleProvider(result, fragment, HiddenAPIInfoProvider)
+ info, _ := android.OtherModuleProvider(result, fragment, HiddenAPIInfoProvider)
stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
@@ -461,7 +457,7 @@
// Make sure that the library exports hidden API properties for use by the bootclasspath_fragment.
library := result.Module("mynewlibrary", "android_common")
- info, _ := android.SingletonModuleProvider(result, library, hiddenAPIPropertyInfoProvider)
+ info, _ := android.OtherModuleProvider(result, library, hiddenAPIPropertyInfoProvider)
android.AssertArrayString(t, "split packages", []string{"sdklibrary", "newlibrary"}, info.SplitPackages)
android.AssertArrayString(t, "package prefixes", []string{"newlibrary.all.mine"}, info.PackagePrefixes)
android.AssertArrayString(t, "single packages", []string{"newlibrary.mine"}, info.SinglePackages)
diff --git a/java/builder.go b/java/builder.go
index 5d84d0b..e5d5109 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -156,7 +156,7 @@
turbine, turbineRE = pctx.RemoteStaticRules("turbine",
blueprint.RuleParams{
Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} $outputFlags ` +
- `--sources @$out.rsp --source_jars $srcJars ` +
+ `--sources @$out.rsp ` +
`--javacopts ${config.CommonJdkFlags} ` +
`$javacFlags -source $javaVersion -target $javaVersion -- $turbineFlags && ` +
`(for o in $outputs; do if cmp -s $${o}.tmp $${o} ; then rm $${o}.tmp ; else mv $${o}.tmp $${o} ; fi; done )`,
@@ -170,13 +170,13 @@
},
&remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"},
ExecStrategy: "${config.RETurbineExecStrategy}",
- Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
- RSPFiles: []string{"${out}.rsp"},
+ Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$rbeInputs"},
+ RSPFiles: []string{"$out.rsp", "$rspFiles"},
OutputFiles: []string{"$rbeOutputs"},
ToolchainInputs: []string{"${config.JavaCmd}"},
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- []string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs", "srcJars"}, []string{"implicits"})
+ []string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs"}, []string{"rbeInputs", "rspFiles"})
jar, jarRE = pctx.RemoteStaticRules("jar",
blueprint.RuleParams{
@@ -258,6 +258,20 @@
},
)
+ ravenizer = pctx.AndroidStaticRule("ravenizer",
+ blueprint.RuleParams{
+ Command: "rm -f $out && ${ravenizer} --in-jar $in --out-jar $out $ravenizerArgs",
+ CommandDeps: []string{"${ravenizer}"},
+ },
+ "ravenizerArgs")
+
+ apimapper = pctx.AndroidStaticRule("apimapper",
+ blueprint.RuleParams{
+ Command: "${apimapper} --in-jar $in --out-jar $out",
+ CommandDeps: []string{"${apimapper}"},
+ },
+ )
+
zipalign = pctx.AndroidStaticRule("zipalign",
blueprint.RuleParams{
Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " +
@@ -307,6 +321,8 @@
pctx.Import("android/soong/java/config")
pctx.HostBinToolVariable("aconfig", "aconfig")
+ pctx.HostBinToolVariable("ravenizer", "ravenizer")
+ pctx.HostBinToolVariable("apimapper", "apimapper")
pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
}
@@ -428,53 +444,72 @@
})
}
-func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string) (string, android.Paths) {
- var deps android.Paths
+func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags, dir string, srcJars android.Paths) (string, android.Paths, android.Paths, android.Paths) {
+ var implicits android.Paths
+ var rbeInputs android.Paths
+ var rspFiles android.Paths
classpath := flags.classpath
- var bootClasspath string
+ srcJarArgs := strings.Join(srcJars.Strings(), " ")
+ implicits = append(implicits, srcJars...)
+ const srcJarArgsLimit = 32 * 1024
+ if len(srcJarArgs) > srcJarArgsLimit {
+ srcJarRspFile := android.PathForModuleOut(ctx, "turbine", "srcjars.rsp")
+ android.WriteFileRule(ctx, srcJarRspFile, srcJarArgs)
+ srcJarArgs = "@" + srcJarRspFile.String()
+ implicits = append(implicits, srcJarRspFile)
+ rbeInputs = append(rbeInputs, srcJarRspFile)
+ } else {
+ rbeInputs = append(rbeInputs, srcJars...)
+ }
+
+ var bootClasspathFlags string
if flags.javaVersion.usesJavaModules() {
var systemModuleDeps android.Paths
- bootClasspath, systemModuleDeps = flags.systemModules.FormTurbineSystemModulesPath(ctx.Device())
- deps = append(deps, systemModuleDeps...)
+ bootClasspathFlags, systemModuleDeps = flags.systemModules.FormTurbineSystemModulesPath(ctx.Device())
+ implicits = append(implicits, systemModuleDeps...)
+ rbeInputs = append(rbeInputs, systemModuleDeps...)
classpath = append(flags.java9Classpath, classpath...)
} else {
- deps = append(deps, flags.bootClasspath...)
+ implicits = append(implicits, flags.bootClasspath...)
+ rbeInputs = append(rbeInputs, flags.bootClasspath...)
if len(flags.bootClasspath) == 0 && ctx.Device() {
// explicitly specify -bootclasspath "" if the bootclasspath is empty to
// ensure turbine does not fall back to the default bootclasspath.
- bootClasspath = `--bootclasspath ""`
+ bootClasspathFlags = `--bootclasspath ""`
} else {
- bootClasspath = flags.bootClasspath.FormTurbineClassPath("--bootclasspath ")
+ bootClasspathFlags = flags.bootClasspath.FormTurbineClassPath("--bootclasspath ")
}
}
- deps = append(deps, classpath...)
- turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ")
-
- const flagsLimit = 32 * 1024
- if len(turbineFlags) > flagsLimit {
- flagsRspFile := android.PathForModuleOut(ctx, dir, "turbine-flags.rsp")
- android.WriteFileRule(ctx, flagsRspFile, turbineFlags)
- turbineFlags = "@" + flagsRspFile.String()
- deps = append(deps, flagsRspFile)
+ classpathFlags := classpath.FormTurbineClassPath("")
+ implicits = append(implicits, classpath...)
+ const classpathLimit = 32 * 1024
+ if len(classpathFlags) > classpathLimit {
+ classpathRspFile := android.PathForModuleOut(ctx, dir, "classpath.rsp")
+ android.WriteFileRule(ctx, classpathRspFile, classpathFlags)
+ classpathFlags = "@" + classpathRspFile.String()
+ implicits = append(implicits, classpathRspFile)
+ rspFiles = append(rspFiles, classpathRspFile)
+ rbeInputs = append(rbeInputs, classpathRspFile)
+ } else {
+ rbeInputs = append(rbeInputs, classpath...)
}
- return turbineFlags, deps
+ turbineFlags := "--source_jars " + srcJarArgs + " " + bootClasspathFlags + " --classpath " + classpathFlags
+
+ return turbineFlags, implicits, rbeInputs, rspFiles
}
func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
- turbineFlags, deps := turbineFlags(ctx, flags, "turbine")
-
- deps = append(deps, srcJars...)
+ turbineFlags, implicits, rbeInputs, rspFiles := turbineFlags(ctx, flags, "turbine", srcJars)
rule := turbine
args := map[string]string{
"javacFlags": flags.javacFlags,
- "srcJars": strings.Join(srcJars.Strings(), " "),
"javaVersion": flags.javaVersion.String(),
"turbineFlags": turbineFlags,
"outputFlags": "--output " + outputFile.String() + ".tmp",
@@ -482,15 +517,16 @@
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
rule = turbineRE
- args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["rbeInputs"] = strings.Join(rbeInputs.Strings(), ",")
args["rbeOutputs"] = outputFile.String() + ".tmp"
+ args["rspFiles"] = strings.Join(rspFiles.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "turbine",
Output: outputFile,
Inputs: srcFiles,
- Implicits: deps,
+ Implicits: implicits,
Args: args,
})
}
@@ -499,11 +535,10 @@
func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath,
srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
- turbineFlags, deps := turbineFlags(ctx, flags, "kapt")
+ turbineFlags, implicits, rbeInputs, rspFiles := turbineFlags(ctx, flags, "turbine-apt", srcJars)
- deps = append(deps, srcJars...)
-
- deps = append(deps, flags.processorPath...)
+ implicits = append(implicits, flags.processorPath...)
+ rbeInputs = append(rbeInputs, flags.processorPath...)
turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ")
turbineFlags += " --processors " + strings.Join(flags.processors, " ")
@@ -514,7 +549,6 @@
rule := turbine
args := map[string]string{
"javacFlags": flags.javacFlags,
- "srcJars": strings.Join(srcJars.Strings(), " "),
"javaVersion": flags.javaVersion.String(),
"turbineFlags": turbineFlags,
"outputFlags": outputFlags,
@@ -522,8 +556,9 @@
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") {
rule = turbineRE
- args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["rbeInputs"] = strings.Join(rbeInputs.Strings(), ",")
args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp"
+ args["rspFiles"] = strings.Join(rspFiles.Strings(), ",")
}
ctx.Build(pctx, android.BuildParams{
Rule: rule,
@@ -531,7 +566,7 @@
Output: outputs[0],
ImplicitOutputs: outputs[1:],
Inputs: srcFiles,
- Implicits: deps,
+ Implicits: implicits,
Args: args,
})
}
@@ -668,6 +703,7 @@
// Remove any module-info.class files that may have come from prebuilt jars, they cause problems
// for downstream tools like desugar.
jarArgs = append(jarArgs, "-stripFile module-info.class")
+ jarArgs = append(jarArgs, "-stripFile META-INF/versions/*/module-info.class")
if stripDirEntries {
jarArgs = append(jarArgs, "-D")
@@ -746,6 +782,19 @@
})
}
+func TransformRavenizer(ctx android.ModuleContext, outputFile android.WritablePath,
+ inputFile android.Path, ravenizerArgs string) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: ravenizer,
+ Description: "ravenizer",
+ Output: outputFile,
+ Input: inputFile,
+ Args: map[string]string{
+ "ravenizerArgs": ravenizerArgs,
+ },
+ })
+}
+
func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) {
android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n")
}
diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go
index 99b1f52..9dc9a22 100644
--- a/java/code_metadata_test.go
+++ b/java/code_metadata_test.go
@@ -29,7 +29,7 @@
module := result.ModuleForTests("module-name", "")
// Check that the provider has the right contents
- data, _ := android.SingletonModuleProvider(result, module.Module(), soongTesting.CodeMetadataProviderKey)
+ data, _ := android.OtherModuleProvider(result, module.Module(), soongTesting.CodeMetadataProviderKey)
if !strings.HasSuffix(
data.IntermediatePath.String(), "/intermediateCodeMetadata.pb",
) {
diff --git a/java/config/Android.bp b/java/config/Android.bp
index bfe83ab..6217390 100644
--- a/java/config/Android.bp
+++ b/java/config/Android.bp
@@ -17,4 +17,8 @@
"kotlin.go",
"makevars.go",
],
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//external/error_prone/soong",
+ ],
}
diff --git a/java/config/config.go b/java/config/config.go
index 66e857c..87703d8 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -47,11 +47,12 @@
"services",
"android.car",
"android.car7",
- "android.car.builtin",
+ "android.car.builtin.impl",
"conscrypt",
"core-icu4j",
"core-oj",
"core-libart",
+ "wear-sdk.impl",
}
)
@@ -96,11 +97,19 @@
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
}, dexerJavaVmFlagsList...), " "))
- pctx.StaticVariable("R8Flags", strings.Join(append([]string{
- "-JXmx4096M",
- "-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
- "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
- }, dexerJavaVmFlagsList...), " "))
+
+ pctx.VariableFunc("R8Flags", func(ctx android.PackageVarContext) string {
+ r8flags := append([]string{
+ "-JXmx4096M",
+ "-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
+ }, dexerJavaVmFlagsList...)
+ if r8DumpDir := ctx.Config().Getenv("R8_DUMP_DIRECTORY"); r8DumpDir != "" {
+ r8flags = append(r8flags, "-JDcom.android.tools.r8.dumpinputtodirectory="+r8DumpDir)
+ }
+ return strings.Join(r8flags, " ")
+
+ })
pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
`-Xmaxerrs 9999999`,
@@ -144,6 +153,7 @@
pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar")
+ pctx.SourcePathVariable("KotlinKytheExtractor", "prebuilts/build-tools/${hostPrebuiltTag}/bin/kotlinc_extractor")
pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar")
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index e5e187c..302d021 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -50,4 +50,11 @@
}, " "))
pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
+ // Use KotlincKytheGlobalFlags to prevent kotlinc version skew issues between android and
+ // g3 kythe indexers.
+ // This is necessary because there might be instances of kotlin code in android
+ // 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"}, " "))
}
diff --git a/java/container_test.go b/java/container_test.go
index 3441855..25cfa4c 100644
--- a/java/container_test.go
+++ b/java/container_test.go
@@ -65,6 +65,18 @@
"general-tests",
],
}
+ java_library {
+ name: "bar",
+ static_libs: [
+ "framework-minus-apex",
+ ],
+ }
+ java_library {
+ name: "baz",
+ static_libs: [
+ "bar",
+ ],
+ }
`)
testcases := []struct {
@@ -73,6 +85,7 @@
isVendorContainer bool
isProductContainer bool
isCts bool
+ isUnstable bool
}{
{
moduleName: "foo",
@@ -80,6 +93,7 @@
isVendorContainer: false,
isProductContainer: false,
isCts: false,
+ isUnstable: false,
},
{
moduleName: "foo_vendor",
@@ -87,6 +101,7 @@
isVendorContainer: true,
isProductContainer: false,
isCts: false,
+ isUnstable: false,
},
{
moduleName: "foo_soc_specific",
@@ -94,6 +109,7 @@
isVendorContainer: true,
isProductContainer: false,
isCts: false,
+ isUnstable: false,
},
{
moduleName: "foo_product_specific",
@@ -101,6 +117,7 @@
isVendorContainer: false,
isProductContainer: true,
isCts: false,
+ isUnstable: false,
},
{
moduleName: "foo_cts_test",
@@ -108,6 +125,7 @@
isVendorContainer: false,
isProductContainer: false,
isCts: true,
+ isUnstable: false,
},
{
moduleName: "foo_non_cts_test",
@@ -115,6 +133,23 @@
isVendorContainer: false,
isProductContainer: false,
isCts: false,
+ isUnstable: false,
+ },
+ {
+ moduleName: "bar",
+ isSystemContainer: true,
+ isVendorContainer: false,
+ isProductContainer: false,
+ isCts: false,
+ isUnstable: true,
+ },
+ {
+ moduleName: "baz",
+ isSystemContainer: true,
+ isVendorContainer: false,
+ isProductContainer: false,
+ isCts: false,
+ isUnstable: true,
},
}
@@ -125,5 +160,7 @@
checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers))
checkContainerMatch(t, c.moduleName, "vendor", c.isVendorContainer, android.InList(android.VendorContainer, belongingContainers))
checkContainerMatch(t, c.moduleName, "product", c.isProductContainer, android.InList(android.ProductContainer, belongingContainers))
+ checkContainerMatch(t, c.moduleName, "cts", c.isCts, android.InList(android.CtsContainer, belongingContainers))
+ checkContainerMatch(t, c.moduleName, "unstable", c.isUnstable, android.InList(android.UnstableContainer, belongingContainers))
}
}
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index ab72e8b..1cca7ad 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -38,10 +38,11 @@
visibility: ["//visibility:public"],
sdk_version: "none",
system_modules: "none",
+ is_stubs_module: true,
}
java_library {
- name: "core.current.stubs.from-source",
+ name: "core.current.stubs",
defaults: [
"core.current.stubs.defaults",
],
@@ -52,8 +53,12 @@
],
}
+// Used for bootstrapping ART system modules
java_api_library {
name: "core.current.stubs.from-text",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
api_surface: "core",
api_contributions: [
"art.module.public.api.stubs.source.api.contribution",
@@ -68,27 +73,7 @@
}
java_library {
- name: "core.current.stubs",
- defaults: [
- "core.current.stubs.defaults",
- ],
- static_libs: [
- "core.current.stubs.from-source",
- ],
- product_variables: {
- build_from_text_stub: {
- static_libs: [
- "core.current.stubs.from-text",
- ],
- exclude_static_libs: [
- "core.current.stubs.from-source",
- ],
- },
- },
-}
-
-java_library {
- name: "core.current.stubs.exportable.from-source",
+ name: "core.current.stubs.exportable",
defaults: [
"core.current.stubs.defaults",
],
@@ -103,16 +88,6 @@
},
}
-java_library {
- name: "core.current.stubs.exportable",
- defaults: [
- "core.current.stubs.defaults",
- ],
- static_libs: [
- "core.current.stubs.exportable.from-source",
- ],
-}
-
// Distributed with the SDK for turning into system modules to compile apps
// against.
//
@@ -201,26 +176,6 @@
"core.module_lib.stubs.defaults",
],
static_libs: [
- "core.module_lib.stubs.from-source",
- ],
- product_variables: {
- build_from_text_stub: {
- static_libs: [
- "core.module_lib.stubs.from-text",
- ],
- exclude_static_libs: [
- "core.module_lib.stubs.from-source",
- ],
- },
- },
-}
-
-java_library {
- name: "core.module_lib.stubs.from-source",
- defaults: [
- "core.module_lib.stubs.defaults",
- ],
- static_libs: [
"art.module.public.api.stubs.module_lib",
// Replace the following with the module-lib correspondence when Conscrypt or i18N module
@@ -231,27 +186,6 @@
],
}
-java_api_library {
- name: "core.module_lib.stubs.from-text",
- api_surface: "module-lib",
- api_contributions: [
- "art.module.public.api.stubs.source.api.contribution",
- "art.module.public.api.stubs.source.system.api.contribution",
- "art.module.public.api.stubs.source.module_lib.api.contribution",
-
- // Add the module-lib correspondence when Conscrypt or i18N module
- // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
- // @SystemApi(MODULE_LIBRARIES).
- "conscrypt.module.public.api.stubs.source.api.contribution",
- "i18n.module.public.api.stubs.source.api.contribution",
- ],
- libs: [
- "stub-annotations",
- ],
- visibility: ["//visibility:private"],
- stubs_type: "everything",
-}
-
// Produces a dist file that is used by the
// prebuilts/sdk/update_prebuilts.py script to update the prebuilts/sdk
// directory.
@@ -311,7 +245,7 @@
// API annotations are available to the dex tools that enable enforcement of runtime
// accessibility. b/119068555
java_library {
- name: "legacy.core.platform.api.stubs.from-source",
+ name: "legacy.core.platform.api.stubs",
visibility: core_platform_visibility,
defaults: [
"core.platform.api.stubs.defaults",
@@ -324,7 +258,7 @@
}
java_library {
- name: "legacy.core.platform.api.stubs.exportable.from-source",
+ name: "legacy.core.platform.api.stubs.exportable",
visibility: core_platform_visibility,
defaults: [
"core.platform.api.stubs.defaults",
@@ -348,53 +282,6 @@
],
}
-java_api_library {
- name: "legacy.core.platform.api.stubs.from-text",
- api_surface: "core_platform",
- defaults: [
- "android_core_platform_stubs_current_contributions",
- ],
- api_contributions: [
- "legacy.i18n.module.platform.api.stubs.source.api.contribution",
- ],
- libs: [
- "stub-annotations",
- ],
- stubs_type: "everything",
-}
-
-java_library {
- name: "legacy.core.platform.api.stubs",
- visibility: core_platform_visibility,
- defaults: [
- "core.platform.api.stubs.defaults",
- ],
- static_libs: [
- "legacy.core.platform.api.stubs.from-source",
- ],
- product_variables: {
- build_from_text_stub: {
- static_libs: [
- "legacy.core.platform.api.stubs.from-text",
- ],
- exclude_static_libs: [
- "legacy.core.platform.api.stubs.from-source",
- ],
- },
- },
-}
-
-java_library {
- name: "legacy.core.platform.api.stubs.exportable",
- visibility: core_platform_visibility,
- defaults: [
- "core.platform.api.stubs.defaults",
- ],
- static_libs: [
- "legacy.core.platform.api.stubs.exportable.from-source",
- ],
-}
-
java_defaults {
name: "core.platform.api.stubs.defaults",
hostdex: true,
@@ -403,6 +290,7 @@
sdk_version: "none",
system_modules: "none",
patch_module: "java.base",
+ is_stubs_module: true,
}
// Same as legacy.core.platform.api.stubs, but android annotations are
@@ -421,10 +309,11 @@
"legacy.core.platform.api.stubs",
],
patch_module: "java.base",
+ is_stubs_module: true,
}
java_library {
- name: "stable.core.platform.api.stubs.from-source",
+ name: "stable.core.platform.api.stubs",
visibility: core_platform_visibility,
defaults: [
"core.platform.api.stubs.defaults",
@@ -437,42 +326,6 @@
],
}
-java_api_library {
- name: "stable.core.platform.api.stubs.from-text",
- api_surface: "core_platform",
- defaults: [
- "android_core_platform_stubs_current_contributions",
- ],
- api_contributions: [
- "stable.i18n.module.platform.api.stubs.source.api.contribution",
- ],
- libs: [
- "stub-annotations",
- ],
- stubs_type: "everything",
-}
-
-java_library {
- name: "stable.core.platform.api.stubs",
- visibility: core_platform_visibility,
- defaults: [
- "core.platform.api.stubs.defaults",
- ],
- static_libs: [
- "stable.core.platform.api.stubs.from-source",
- ],
- product_variables: {
- build_from_text_stub: {
- static_libs: [
- "stable.core.platform.api.stubs.from-text",
- ],
- exclude_static_libs: [
- "stable.core.platform.api.stubs.from-source",
- ],
- },
- },
-}
-
// Same as stable.core.platform.api.stubs, but android annotations are
// stripped. This is used by the Java toolchain, while the annotated stub is to
// be used by Kotlin one.
@@ -489,6 +342,7 @@
"stable.core.platform.api.stubs",
],
patch_module: "java.base",
+ is_stubs_module: true,
}
// Used when compiling higher-level code against *.core.platform.api.stubs.
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 3f8735c..3f4e3cd 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -96,6 +96,10 @@
ctx.PropertyErrorf("libs", "at least one dependency is required")
}
+ var transitiveHeaderJars []*android.DepSet[android.Path]
+ var transitiveImplementationJars []*android.DepSet[android.Path]
+ var transitiveResourceJars []*android.DepSet[android.Path]
+
ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) {
if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
d.headerJars = append(d.headerJars, dep.HeaderJars...)
@@ -105,6 +109,16 @@
d.srcJarArgs = append(d.srcJarArgs, dep.SrcJarArgs...)
d.srcJarDeps = append(d.srcJarDeps, dep.SrcJarDeps...)
+
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveHeaderJars = append(transitiveHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsImplementationJars != nil {
+ transitiveImplementationJars = append(transitiveImplementationJars, dep.TransitiveStaticLibsImplementationJars)
+ }
+ if dep.TransitiveStaticLibsResourceJars != nil {
+ transitiveResourceJars = append(transitiveResourceJars, dep.TransitiveStaticLibsResourceJars)
+ }
} else {
ctx.PropertyErrorf("libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
}
@@ -130,14 +144,18 @@
d.combinedHeaderJar = d.headerJars[0]
}
- android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: d.headerJars,
- ImplementationAndResourcesJars: d.implementationAndResourceJars,
- ImplementationJars: d.implementationJars,
- ResourceJars: d.resourceJars,
- SrcJarArgs: d.srcJarArgs,
- SrcJarDeps: d.srcJarDeps,
- StubsLinkType: Implementation,
+ android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ HeaderJars: d.headerJars,
+ LocalHeaderJars: d.headerJars,
+ TransitiveStaticLibsHeaderJars: android.NewDepSet(android.PREORDER, nil, transitiveHeaderJars),
+ TransitiveStaticLibsImplementationJars: android.NewDepSet(android.PREORDER, nil, transitiveImplementationJars),
+ TransitiveStaticLibsResourceJars: android.NewDepSet(android.PREORDER, nil, transitiveResourceJars),
+ ImplementationAndResourcesJars: d.implementationAndResourceJars,
+ ImplementationJars: d.implementationJars,
+ ResourceJars: d.resourceJars,
+ SrcJarArgs: d.srcJarArgs,
+ SrcJarDeps: d.srcJarDeps,
+ StubsLinkType: Implementation,
// TODO: Not sure if aconfig flags that have been moved between device and host variants
// make sense.
})
@@ -188,3 +206,11 @@
},
}
}
+
+// implement the following interface for IDE completion.
+var _ android.IDEInfo = (*DeviceHostConverter)(nil)
+
+func (d *DeviceHostConverter) IDEInfo(ctx android.BaseModuleContext, ideInfo *android.IdeInfo) {
+ ideInfo.Deps = append(ideInfo.Deps, d.properties.Libs...)
+ ideInfo.Libs = append(ideInfo.Libs, d.properties.Libs...)
+}
diff --git a/java/dex.go b/java/dex.go
index 7bb6925..a3f699b 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -108,7 +108,7 @@
resourcesInput android.OptionalPath
resourcesOutput android.OptionalPath
- providesTransitiveHeaderJars
+ providesTransitiveHeaderJarsForR8
}
func (d *dexer) effectiveOptimizeEnabled() bool {
@@ -120,7 +120,7 @@
}
func (d *DexProperties) optimizedResourceShrinkingEnabled(ctx android.ModuleContext) bool {
- return d.resourceShrinkingEnabled(ctx) && Bool(d.Optimize.Optimized_shrink_resources)
+ return d.resourceShrinkingEnabled(ctx) && BoolDefault(d.Optimize.Optimized_shrink_resources, ctx.Config().UseOptimizedResourceShrinkingByDefault())
}
func (d *dexer) optimizeOrObfuscateEnabled() bool {
@@ -133,7 +133,7 @@
`$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in && ` +
`$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"`,
+ `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
CommandDeps: []string{
"${config.D8Cmd}",
"${config.SoongZipCmd}",
@@ -172,7 +172,7 @@
`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"`,
+ `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
CommandDeps: []string{
@@ -220,14 +220,21 @@
deps = append(deps, f)
}
- if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" {
+ var requestReleaseMode bool
+ requestReleaseMode, flags = android.RemoveFromList("--release", flags)
+
+ if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" || ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
flags = append(flags, "--debug")
+ requestReleaseMode = false
}
- if ctx.Config().Getenv("GENERATE_DEX_DEBUG") != "" {
- flags = append(flags,
- "--debug",
- "--verbose")
+ // 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 {
+ flags = append(flags, "--release")
+ } else if ctx.Config().Eng() {
+ flags = append(flags, "--debug")
}
// Supplying the platform build flag disables various features like API modeling and desugaring.
@@ -245,6 +252,16 @@
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
}
+ if !Bool(d.dexProperties.No_dex_container) && effectiveVersion.FinalOrFutureInt() >= 36 {
+ // W is 36, but we have not bumped the SDK version yet, so check for both.
+ if ctx.Config().PlatformSdkVersion().FinalInt() >= 36 ||
+ ctx.Config().PlatformSdkCodename() == "Wear" {
+ // TODO(b/329465418): Skip this module since it causes issue with app DRM
+ if ctx.ModuleName() != "framework-minus-apex" {
+ flags = append([]string{"-JDcom.android.tools.r8.dexContainerExperiment"}, flags...)
+ }
+ }
+ }
// If the specified SDK level is 10000, then configure the compiler to use the
// current platform SDK level and to compile the build as a platform build.
@@ -289,28 +306,32 @@
// - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
// - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
// See b/20667396
- var proguardRaiseDeps classpath
- ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
- dep, _ := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
- proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
- })
+ // 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) {
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+ proguardRaiseDeps = append(proguardRaiseDeps, dep.RepackagedHeaderJars...)
+ }
+ })
+ r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
+ r8Deps = append(r8Deps, proguardRaiseDeps...)
+ }
- r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
- r8Deps = append(r8Deps, proguardRaiseDeps...)
r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
r8Deps = append(r8Deps, flags.bootClasspath...)
r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
r8Deps = append(r8Deps, flags.dexClasspath...)
transitiveStaticLibsLookupMap := map[android.Path]bool{}
- if d.transitiveStaticLibsHeaderJars != nil {
- for _, jar := range d.transitiveStaticLibsHeaderJars.ToList() {
+ if d.transitiveStaticLibsHeaderJarsForR8 != nil {
+ for _, jar := range d.transitiveStaticLibsHeaderJarsForR8.ToList() {
transitiveStaticLibsLookupMap[jar] = true
}
}
transitiveHeaderJars := android.Paths{}
- if d.transitiveLibsHeaderJars != nil {
- for _, jar := range d.transitiveLibsHeaderJars.ToList() {
+ if d.transitiveLibsHeaderJarsForR8 != nil {
+ for _, jar := range d.transitiveLibsHeaderJarsForR8.ToList() {
if _, ok := transitiveStaticLibsLookupMap[jar]; ok {
// don't include a lib if it is already packaged in the current JAR as a static lib
continue
@@ -370,11 +391,6 @@
// TODO(ccross): if this is an instrumentation test of an obfuscated app, use the
// dictionary of the app and move the app from libraryjars to injars.
- // Don't strip out debug information for eng builds.
- if ctx.Config().Eng() {
- r8Flags = append(r8Flags, "--debug")
- }
-
// TODO(b/180878971): missing classes should be added to the relevant builds.
// TODO(b/229727645): do not use true as default for Android platform builds.
if proptools.BoolDefault(opt.Ignore_warnings, true) {
@@ -386,7 +402,7 @@
r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
r8Deps = append(r8Deps, d.resourcesInput.Path())
r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
- if Bool(opt.Optimized_shrink_resources) {
+ if d.dexProperties.optimizedResourceShrinkingEnabled(ctx) {
r8Flags = append(r8Flags, "--optimized-resource-shrinking")
}
}
@@ -428,7 +444,7 @@
}
// Return the compiled dex jar and (optional) profile _after_ r8 optimization
-func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) (android.OutputPath, *android.OutputPath) {
+func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParams) (android.Path, android.Path) {
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
diff --git a/java/dex_test.go b/java/dex_test.go
index 4862d06..8bc28e6 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -713,3 +713,97 @@
}
}`)
}
+
+func TestDebugReleaseFlags(t *testing.T) {
+ bp := `
+ android_app {
+ name: "app",
+ srcs: ["foo.java"],
+ platform_apis: true,
+ dxflags: ["%s"]
+ }
+ `
+
+ testcases := []struct {
+ name string
+ envVar string
+ isEng bool
+ dxFlags string
+ expectedFlags string
+ }{
+ {
+ name: "app_no_optimize_dx",
+ envVar: "NO_OPTIMIZE_DX",
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_release_no_optimize_dx",
+ envVar: "NO_OPTIMIZE_DX",
+ dxFlags: "--release",
+ // Global env vars override explicit dxflags.
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_generate_dex_debug",
+ envVar: "GENERATE_DEX_DEBUG",
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_release_generate_dex_debug",
+ envVar: "GENERATE_DEX_DEBUG",
+ dxFlags: "--release",
+ // Global env vars override explicit dxflags.
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_eng",
+ isEng: true,
+ expectedFlags: "--debug",
+ },
+ {
+ name: "app_release_eng",
+ isEng: true,
+ dxFlags: "--release",
+ // Eng mode does *not* override explicit dxflags.
+ expectedFlags: "--release",
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ fixturePreparer := PrepareForTestWithJavaDefaultModules
+ fixturePreparer = android.GroupFixturePreparers(
+ fixturePreparer,
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Eng = proptools.BoolPtr(tc.isEng)
+ },
+ ),
+ )
+ if tc.envVar != "" {
+ fixturePreparer = android.GroupFixturePreparers(
+ fixturePreparer,
+ android.FixtureMergeEnv(map[string]string{
+ tc.envVar: "true",
+ }),
+ )
+ }
+ result := fixturePreparer.RunTestWithBp(t, fmt.Sprintf(bp, tc.dxFlags))
+
+ appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ android.AssertStringDoesContain(t, "expected flag in R8 flags",
+ appR8.Args["r8Flags"], tc.expectedFlags)
+
+ var unexpectedFlags string
+ if tc.expectedFlags == "--debug" {
+ unexpectedFlags = "--release"
+ } else if tc.expectedFlags == "--release" {
+ unexpectedFlags = "--debug"
+ }
+ if unexpectedFlags != "" {
+ android.AssertStringDoesNotContain(t, "unexpected flag in R8 flags",
+ appR8.Args["r8Flags"], unexpectedFlags)
+ }
+ })
+ }
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 7949244..637da36 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -88,18 +88,11 @@
entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
- // Unset LOCAL_SOONG_INSTALLED_MODULE so that this does not default to the primary .apex file
- // Without this, installation of the dexpreopt artifacts get skipped
- entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", "")
},
},
}
}
-func (install dexpreopterInstall) PackageFile(ctx android.ModuleContext) android.PackagingSpec {
- return ctx.PackageFile(install.installDirOnDevice, install.installFileOnDevice, install.outputPathOnHost)
-}
-
type Dexpreopter struct {
dexpreopter
}
@@ -154,25 +147,25 @@
type DexpreoptProperties struct {
Dex_preopt struct {
// If false, prevent dexpreopting. Defaults to true.
- Enabled *bool
+ Enabled proptools.Configurable[bool] `android:"replace_instead_of_append"`
// If true, generate an app image (.art file) for this module.
- App_image *bool
+ App_image proptools.Configurable[bool] `android:"replace_instead_of_append"`
// If true, use a checked-in profile to guide optimization. Defaults to false unless
// a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR
// that matches the name of this module, in which case it is defaulted to true.
- Profile_guided *bool
+ Profile_guided proptools.Configurable[bool] `android:"replace_instead_of_append"`
// If set, provides the path to profile relative to the Android.bp file. If not set,
// defaults to searching for a file that matches the name of this module in the default
// profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
- Profile *string `android:"path"`
+ Profile proptools.Configurable[string] `android:"path,replace_instead_of_append"`
// If set to true, r8/d8 will use `profile` as input to generate a new profile that matches
// the optimized dex.
// The new profile will be subsequently used as the profile to dexpreopt the dex file.
- Enable_profile_rewriting *bool
+ Enable_profile_rewriting proptools.Configurable[bool] `android:"replace_instead_of_append"`
}
Dex_preopt_result struct {
@@ -216,16 +209,25 @@
psi = prebuiltSelectionInfo
}
})
+
// Find the apex variant for this module
- _, apexVariantsWithoutTestApexes, _ := android.ListSetDifference(apexInfo.InApexVariants, apexInfo.TestApexes)
+ apexVariantsWithoutTestApexes := []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...)
+ }
+ if apexInfo.ApexAvailableName != "" {
+ apexVariantsWithoutTestApexes = append(apexVariantsWithoutTestApexes, apexInfo.ApexAvailableName)
+ }
disableSource := false
// find the selected apexes
for _, apexVariant := range apexVariantsWithoutTestApexes {
- for _, selected := range psi.GetSelectedModulesForApiDomain(apexVariant) {
- // If the apex_contribution for this api domain contains a prebuilt apex, disable the source variant
- if strings.HasPrefix(selected, "prebuilt_com.google.android") {
- disableSource = true
- }
+ if len(psi.GetSelectedModulesForApiDomain(apexVariant)) > 0 {
+ // If the apex_contribution for this api domain is non-empty, disable the source variant
+ disableSource = true
}
}
return disableSource
@@ -242,7 +244,7 @@
return true
}
- if !BoolDefault(d.dexpreoptProperties.Dex_preopt.Enabled, true) {
+ if !d.dexpreoptProperties.Dex_preopt.Enabled.GetOrDefault(ctx, true) {
return true
}
@@ -359,7 +361,7 @@
d.dexpreopt(ctx, libraryName, dexJarFile)
}
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJarFile android.WritablePath) {
+func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJarFile android.Path) {
global := dexpreopt.GetGlobalConfig(ctx)
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
@@ -431,12 +433,12 @@
if d.inputProfilePathOnHost != nil {
profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
- } else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
+ } else if d.dexpreoptProperties.Dex_preopt.Profile_guided.GetOrDefault(ctx, true) && !forPrebuiltApex(ctx) {
// If enable_profile_rewriting is set, use the rewritten profile instead of the checked-in profile
- if d.EnableProfileRewriting() {
+ if d.EnableProfileRewriting(ctx) {
profileClassListing = android.OptionalPathForPath(d.GetRewrittenProfile())
profileIsTextListing = true
- } else if profile := d.GetProfile(); profile != "" {
+ } else if profile := d.GetProfile(ctx); profile != "" {
// If dex_preopt.profile_guided is not set, default it based on the existence of the
// dexprepot.profile option or the profile class listing.
profileClassListing = android.OptionalPathForPath(
@@ -456,6 +458,8 @@
// Use the dexJar to create a unique scope for each
dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext())
+ appImage := d.dexpreoptProperties.Dex_preopt.App_image.Get(ctx)
+
// Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: libName,
@@ -484,14 +488,21 @@
PreoptBootClassPathDexFiles: dexFiles.Paths(),
PreoptBootClassPathDexLocations: dexLocations,
- NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
- ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
+ NoCreateAppImage: !appImage.GetOrDefault(true),
+ ForceCreateAppImage: appImage.GetOrDefault(false),
PresignedPrebuilt: d.isPresignedPrebuilt,
}
+ if ctx.Config().InstallApexSystemServerDexpreoptSamePartition() {
+ dexpreoptConfig.ApexPartition = android.PathForModuleInstall(ctx).Partition()
+ } else {
+ dexpreoptConfig.ApexPartition = "system"
+ }
+
d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config")
dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
+ ctx.CheckbuildFile(d.configPath)
if d.dexpreoptDisabled(ctx, libName) {
return
@@ -583,16 +594,20 @@
// 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.
- d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
+ di := dexpreopterInstall{
name: arch + "-" + installBase,
moduleName: libName,
outputPathOnHost: install.From,
installDirOnDevice: installPath,
installFileOnDevice: installBase,
- })
+ }
+ ctx.InstallFile(di.installDirOnDevice, di.installFileOnDevice, di.outputPathOnHost)
+ d.builtInstalledForApex = append(d.builtInstalledForApex, di)
+
}
} else if !d.preventInstall {
- ctx.InstallFile(installPath, installBase, install.From)
+ // Install without adding to checkbuild to match behavior of previous Make-based checkbuild rules
+ ctx.InstallFileWithoutCheckbuild(installPath, installBase, install.From)
}
}
@@ -616,10 +631,8 @@
return installPath, relDir, installBase
}
-// RuleBuilder.Install() adds output-to-install copy pairs to a list for Make. To share this
-// information with PackagingSpec in soong, call PackageFile for them.
-// The install path and the target install partition of the module must be the same.
-func packageFile(ctx android.ModuleContext, install android.RuleBuilderInstall) {
+// installFile will install the file if `install` path and the target install partition are the same.
+func installFile(ctx android.ModuleContext, install android.RuleBuilderInstall) {
installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To)
// Empty name means the install partition is not for the target image.
// For the system image, files for "apex" and "system_other" are skipped here.
@@ -628,7 +641,7 @@
// TODO(b/320196894): Files for "system_other" are skipped because soong creates the system
// image only for now.
if name != "" {
- ctx.PackageFile(installPath.Join(ctx, relDir), name, install.From)
+ ctx.InstallFile(installPath.Join(ctx, relDir), name, install.From)
}
}
@@ -652,16 +665,16 @@
d.shouldDisableDexpreopt = true
}
-func (d *dexpreopter) EnableProfileRewriting() bool {
- return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting)
+func (d *dexpreopter) EnableProfileRewriting(ctx android.BaseModuleContext) bool {
+ return d.dexpreoptProperties.Dex_preopt.Enable_profile_rewriting.GetOrDefault(ctx, false)
}
-func (d *dexpreopter) GetProfile() string {
- return proptools.String(d.dexpreoptProperties.Dex_preopt.Profile)
+func (d *dexpreopter) GetProfile(ctx android.BaseModuleContext) string {
+ return d.dexpreoptProperties.Dex_preopt.Profile.GetOrDefault(ctx, "")
}
-func (d *dexpreopter) GetProfileGuided() bool {
- return proptools.Bool(d.dexpreoptProperties.Dex_preopt.Profile_guided)
+func (d *dexpreopter) GetProfileGuided(ctx android.BaseModuleContext) bool {
+ return d.dexpreoptProperties.Dex_preopt.Profile_guided.GetOrDefault(ctx, false)
}
func (d *dexpreopter) GetRewrittenProfile() android.Path {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index defa82c..5c69ff1 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -463,6 +463,7 @@
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).Parallel()
})
@@ -491,6 +492,11 @@
// Build path to a config file that Soong writes for Make (to be used in makefiles that install
// the default boot image).
dexpreoptConfigForMake android.WritablePath
+
+ // Build path to the boot framework profile.
+ // This is used as the `OutputFile` in `AndroidMkEntries`.
+ // A non-nil value ensures that this singleton module does not get skipped in AndroidMkEntries processing.
+ bootFrameworkProfile android.WritablePath
}
func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -553,6 +559,10 @@
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))
}
}
}
@@ -592,6 +602,7 @@
d.defaultBootImage = defaultBootImageConfig(ctx)
d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
var profileInstalls android.RuleBuilderInstalls
+ var artBootImageHostInstalls android.RuleBuilderInstalls
for _, name := range getImageNames() {
config := imageConfigs[name]
if config != d.defaultBootImage {
@@ -603,9 +614,22 @@
installs := generateBootImage(ctx, config)
profileInstalls = append(profileInstalls, installs...)
if config == d.defaultBootImage {
- _, installs := bootFrameworkProfileRule(ctx, config)
+ bootProfile, installs := bootFrameworkProfileRule(ctx, config)
+ d.bootFrameworkProfile = bootProfile
profileInstalls = append(profileInstalls, installs...)
}
+ // Gather the install files of the host variant of the ART boot image.
+ // These installed files will be used in ART tests.
+ if config.name == "art" {
+ for _, variant := range config.variants {
+ if variant.target.Os != ctx.Config().BuildOS {
+ // not a host variant
+ continue
+ }
+ artBootImageHostInstalls = append(artBootImageHostInstalls, variant.installs...)
+ artBootImageHostInstalls = append(artBootImageHostInstalls, variant.vdexInstalls...)
+ }
+ }
}
if len(profileInstalls) > 0 {
android.SetProvider(ctx, profileInstallInfoProvider, profileInstallInfo{
@@ -613,9 +637,18 @@
profileLicenseMetadataFile: android.OptionalPathForPath(ctx.LicenseMetadataFile()),
})
for _, install := range profileInstalls {
- packageFile(ctx, install)
+ installFile(ctx, install)
}
}
+ // Set a provider containing the install files of the host variant of the ART boot image.
+ // The actual install rules will be created by `art_boot_images`
+ android.SetProvider(
+ ctx,
+ artBootImageHostInfoProvider,
+ artBootImageHostInfo{
+ installs: artBootImageHostInstalls,
+ },
+ )
}
// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
@@ -939,28 +972,33 @@
}
for _, install := range image.installs {
- packageFile(ctx, install)
+ installFile(ctx, install)
}
for _, install := range image.vdexInstalls {
- if image.target.Arch.ArchType.Name != ctx.DeviceConfig().DeviceArch() {
- // Note that the vdex files are identical between architectures. If the target image is
- // not for the primary architecture create symlinks to share the vdex of the primary
- // architecture with the other architectures.
- //
- // Assuming that the install path has the architecture name with it, replace the
- // architecture name with the primary architecture name to find the source vdex file.
- installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To)
- if name != "" {
- srcRelDir := strings.Replace(relDir, image.target.Arch.ArchType.Name, ctx.DeviceConfig().DeviceArch(), 1)
- ctx.InstallSymlink(installPath.Join(ctx, relDir), name, installPath.Join(ctx, srcRelDir, name))
- }
- } else {
- packageFile(ctx, install)
+ installPath, relDir, name := getModuleInstallPathInfo(ctx, install.To)
+ if name == "" {
+ continue
+ }
+ // Note that the vdex files are identical between architectures. Copy the vdex to a no arch directory
+ // and create symlinks for both the primary and secondary arches.
+ ctx.InstallSymlink(installPath.Join(ctx, relDir), name, installPath.Join(ctx, "framework", name))
+ if image.target.Arch.ArchType.Name == ctx.DeviceConfig().DeviceArch() {
+ // Copy the vdex from the primary arch to the no-arch directory
+ // e.g. /system/framework/$bootjar.vdex
+ ctx.InstallFile(installPath.Join(ctx, "framework"), name, install.From)
}
}
}
+var artBootImageHostInfoProvider = blueprint.NewProvider[artBootImageHostInfo]()
+
+// artBootImageHostInfo contains the install locations of the host variant of ART boot image
+// this contains both the primary and secondary arch locations
+type artBootImageHostInfo struct {
+ installs android.RuleBuilderInstalls
+}
+
// Generate boot image build rules for a specific target.
func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
@@ -1179,8 +1217,13 @@
return nil
}
- defaultProfile := "frameworks/base/config/boot-image-profile.txt"
- extraProfile := "frameworks/base/config/boot-image-profile-extra.txt"
+ defaultProfile := "frameworks/base/boot/boot-image-profile.txt"
+ // If ART is prebuilt, primarily in next release configs, this will still use
+ // the profile from source which represent the latest code, so it may not
+ // correspond to the BCP jars in the prebuilt APEX, but this is the profile we
+ // have access to.
+ artProfile := "art/build/boot/boot-image-profile.txt"
+ extraProfile := "frameworks/base/boot/boot-image-profile-extra.txt"
rule := android.NewRuleBuilder(pctx, ctx)
@@ -1195,6 +1238,9 @@
// Return nil and continue without profile.
return nil
}
+ if path := android.ExistentPathForSource(ctx, artProfile); path.Valid() {
+ profiles = append(profiles, path.Path())
+ }
if path := android.ExistentPathForSource(ctx, extraProfile); path.Valid() {
profiles = append(profiles, path.Path())
}
@@ -1234,7 +1280,7 @@
profile := bootImageProfileRuleCommon(ctx, image.name, image.dexPathsDeps.Paths(), image.getAnyAndroidVariant().dexLocationsDeps)
- if image == defaultBootImageConfig(ctx) {
+ if image == defaultBootImageConfig(ctx) && profile != nil {
rule := android.NewRuleBuilder(pctx, ctx)
rule.Install(profile, "/system/etc/boot-image.prof")
return profile, rule.Installs()
@@ -1252,7 +1298,7 @@
return nil, nil
}
- defaultProfile := "frameworks/base/config/boot-profile.txt"
+ defaultProfile := "frameworks/base/boot/boot-profile.txt"
bootFrameworkProfile := android.PathForSource(ctx, defaultProfile)
profile := image.dir.Join(ctx, "boot.bprof")
@@ -1337,18 +1383,7 @@
}
image := d.defaultBootImage
- if image != nil {
- if profileInstallInfo, ok := android.SingletonModuleProvider(ctx, d, profileInstallInfoProvider); ok {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", profileInstallInfo.profileInstalls.String())
- if profileInstallInfo.profileLicenseMetadataFile.Valid() {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", profileInstallInfo.profileLicenseMetadataFile.String())
- }
- }
-
- if SkipDexpreoptBootJars(ctx) {
- return
- }
-
+ if image != nil && !SkipDexpreoptBootJars(ctx) {
global := dexpreopt.GetGlobalConfig(ctx)
dexPaths, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
@@ -1380,3 +1415,79 @@
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(getImageNames(), " "))
}
}
+
+// Add one of the outputs in `OutputFile`
+// This ensures that this singleton module does not get skipped when writing out/soong/Android-*.mk
+func (d *dexpreoptBootJars) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(d.bootFrameworkProfile),
+ }}
+}
+
+// artBootImages is a thin wrapper around `dex_bootjars`.
+// it creates the installation rules for the host variant of the ART boot image.
+type artBootImages struct {
+ android.ModuleBase
+
+ // A non-empty file that will be written as `LOCAL_SOONG_INSTALLED_MODULE` in out/soong/Android-*.mk
+ outputFile android.OptionalPath
+}
+
+func artBootImagesFactory() android.Module {
+ m := &artBootImages{}
+ android.InitAndroidMultiTargetsArchModule(m, android.HostSupported, android.MultilibCommon)
+ return m
+}
+
+func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Create a dependency on `dex_bootjars` to access the intermediate locations of host art boot image.
+ ctx.AddDependency(ctx.Module(), dexpreoptBootJarDepTag, "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"))
+ }
+ })
+}
+
+// Creates an installation rule for host variant of ART boot image files.
+// Returns the list of install locations (out/host/linux-x86/...)
+func (d *artBootImages) installFile(ctx android.ModuleContext, ruleBuilderInstalls android.RuleBuilderInstalls) android.Paths {
+ var ret android.Paths
+ for _, ruleBuilderInstall := range ruleBuilderInstalls {
+ installDir := android.PathForModuleInstall(
+ ctx,
+ strings.TrimPrefix(filepath.Dir(ruleBuilderInstall.To), "/"),
+ )
+ filename := filepath.Base(ruleBuilderInstall.To)
+ ctx.InstallFile(
+ installDir,
+ filename,
+ ruleBuilderInstall.From,
+ )
+ ret = append(ret, installDir.Join(ctx, filename))
+ }
+ return ret
+}
+
+// Set `OutputFile` expclitly so that this module does not get elided when generating out/soong/Android-*.mk
+func (d *artBootImages) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: d.outputFile,
+ }}
+}
diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go
index 33be603..c971565 100644
--- a/java/dexpreopt_check.go
+++ b/java/dexpreopt_check.go
@@ -17,6 +17,8 @@
import (
"strings"
+ "github.com/google/blueprint"
+
"android/soong/android"
"android/soong/dexpreopt"
@@ -43,16 +45,12 @@
type dexpreoptSystemserverCheck struct {
android.SingletonModuleBase
- // Mapping from the module name to the install paths to the compilation artifacts.
- artifactsByModuleName map[string][]string
-
// The install paths to the compilation artifacts.
artifacts []string
}
func dexpreoptSystemserverCheckFactory() android.SingletonModule {
m := &dexpreoptSystemserverCheck{}
- m.artifactsByModuleName = make(map[string][]string)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
}
@@ -62,7 +60,25 @@
ctx, "", strings.TrimPrefix(location, "/"))
}
-func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+type systemServerDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+// systemServerJarDepTag willl be used for validation. Skip visiblility.
+func (b systemServerDependencyTag) ExcludeFromVisibilityEnforcement() {
+}
+
+var (
+ // dep tag for platform and apex system server jars
+ systemServerJarDepTag = systemServerDependencyTag{}
+)
+
+var _ android.ExcludeFromVisibilityEnforcementTag = systemServerJarDepTag
+
+// Add a depenendency on the system server jars. The dexpreopt files of those will be emitted to make.
+// The kati packaging system will verify that those files appear in installed files.
+// Adding the dependency allows the singleton module to determine whether an apex system server jar is system_ext specific.
+func (m *dexpreoptSystemserverCheck) DepsMutator(ctx android.BottomUpMutatorContext) {
global := dexpreopt.GetGlobalConfig(ctx)
targets := ctx.Config().Targets[android.Android]
@@ -72,23 +88,27 @@
return
}
- systemServerJars := global.AllSystemServerJars(ctx)
- for _, jar := range systemServerJars.CopyOfJars() {
- dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, jar)
- odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType)
+ ctx.AddDependency(ctx.Module(), systemServerJarDepTag, global.AllSystemServerJars(ctx).CopyOfJars()...)
+}
+
+func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ global := dexpreopt.GetGlobalConfig(ctx)
+ targets := ctx.Config().Targets[android.Android]
+
+ ctx.VisitDirectDepsWithTag(systemServerJarDepTag, func(systemServerJar android.Module) {
+ partition := "system"
+ if systemServerJar.InstallInSystemExt() && ctx.Config().InstallApexSystemServerDexpreoptSamePartition() {
+ partition = ctx.DeviceConfig().SystemExtPath() // system_ext
+ }
+ dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, systemServerJar.Name())
+ odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType, partition)
odexPath := getInstallPath(ctx, odexLocation)
vdexPath := getInstallPath(ctx, pathtools.ReplaceExtension(odexLocation, "vdex"))
- m.artifactsByModuleName[jar] = []string{odexPath.String(), vdexPath.String()}
- }
+ m.artifacts = append(m.artifacts, odexPath.String(), vdexPath.String())
+ })
}
func (m *dexpreoptSystemserverCheck) GenerateSingletonBuildActions(ctx android.SingletonContext) {
- // Only keep modules defined in Soong.
- ctx.VisitAllModules(func(module android.Module) {
- if artifacts, ok := m.artifactsByModuleName[module.Name()]; ok {
- m.artifacts = append(m.artifacts, artifacts...)
- }
- })
}
func (m *dexpreoptSystemserverCheck) MakeVars(ctx android.MakeVarsContext) {
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 104829f..33c682b 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -1237,7 +1237,7 @@
if !mutated {
dexBootJarModule := result.ModuleForTests("dex_bootjars", "android_common")
- profileInstallInfo, _ := android.SingletonModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider)
+ profileInstallInfo, _ := android.OtherModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider)
assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, profileInstallInfo.profileInstalls)
android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, profileInstallInfo.profileLicenseMetadataFile.RelativeToTop().String())
}
@@ -1335,8 +1335,6 @@
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/boot.art:out/soong/dexpreopt_arm64/dex_mainlinejars/android/system/framework/boot-framework-foo.art
DEXPREOPT_IMAGE_NAMES=art boot mainline
-DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof:/system/etc/boot-image.prof out/soong/dexpreopt_arm64/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof
-DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/default/java/dex_bootjars/android_common/meta_lic
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-extra1.oat:/apex/art_boot_images/javalib/arm/boot-extra1.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-extra1.oat:/apex/art_boot_images/javalib/arm64/boot-extra1.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/dexpreopt_arm64/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-extra1.oat:/apex/art_boot_images/javalib/x86/boot-extra1.oat
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 73e33f4..07d0595 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -54,6 +54,7 @@
name: "foo",
installable: true,
srcs: ["a.java"],
+ sdk_version: "current",
}`,
enabled: true,
},
@@ -98,6 +99,7 @@
java_library {
name: "foo",
installable: true,
+ sdk_version: "current",
}`,
enabled: false,
},
@@ -107,6 +109,7 @@
java_library {
name: "foo",
srcs: ["a.java"],
+ sdk_version: "current",
}`,
enabled: false,
},
@@ -144,6 +147,7 @@
name: "foo",
srcs: ["a.java"],
compile_dex: true,
+ sdk_version: "current",
}`,
enabled: false,
},
@@ -164,6 +168,7 @@
installable: true,
srcs: ["a.java"],
apex_available: ["com.android.apex1"],
+ sdk_version: "current",
}`,
apexVariant: true,
enabled: false,
@@ -176,6 +181,7 @@
installable: true,
srcs: ["a.java"],
apex_available: ["com.android.apex1"],
+ sdk_version: "current",
}`,
moduleName: "service-foo",
apexVariant: true,
@@ -189,6 +195,7 @@
installable: true,
srcs: ["a.java"],
apex_available: ["com.android.apex1"],
+ sdk_version: "current",
}`,
moduleName: "prebuilt_service-foo",
apexVariant: true,
@@ -202,6 +209,7 @@
installable: true,
srcs: ["a.java"],
apex_available: ["com.android.apex1"],
+ sdk_version: "current",
}`,
moduleName: "service-foo",
apexVariant: false,
@@ -311,6 +319,7 @@
installable: true,
srcs: ["a.java"],
apex_available: ["com.android.apex1"],
+ sdk_version: "current",
}`)
ctx := result.TestContext
module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
@@ -342,6 +351,7 @@
name: "foo",
installable: true,
srcs: ["a.java"],
+ sdk_version: "current",
}`)
ctx = result.TestContext
module = ctx.ModuleForTests("foo", "android_common")
@@ -398,6 +408,7 @@
installable: true,
srcs: ["a.java"],
apex_available: ["com.android.apex1"],
+ sdk_version: "current",
}`)
ctx := result.TestContext
module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
@@ -429,6 +440,7 @@
name: "foo",
installable: true,
srcs: ["a.java"],
+ sdk_version: "current",
}`)
ctx = result.TestContext
module = ctx.ModuleForTests("foo", "android_common")
@@ -454,6 +466,7 @@
profile: "art-profile",
},
srcs: ["a.java"],
+ sdk_version: "current",
}`)
ctx := result.TestContext
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 730f236..2980d91 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -54,7 +54,7 @@
Filter_packages []string
// list of java libraries that will be in the classpath.
- Libs []string `android:"arch_variant"`
+ Libs proptools.Configurable[[]string] `android:"arch_variant"`
// If set to false, don't allow this module(-docs.zip) to be exported. Defaults to true.
Installable *bool
@@ -274,7 +274,7 @@
}
}
- ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, libTag, j.properties.Libs.GetOrDefault(ctx, nil)...)
}
func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags {
@@ -365,16 +365,18 @@
case bootClasspathTag:
if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars...)
- } else if sm, ok := module.(SystemModulesProvider); ok {
+ } else if sm, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
// A system modules dependency has been added to the bootclasspath
// so add its libs to the bootclasspath.
- deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...)
+ deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars...)
} else {
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
}
case libTag, sdkLibTag:
- if dep, ok := module.(SdkLibraryDependency); ok {
- deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
+ if sdkInfo, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
+ generatingLibsString := android.PrettyConcat(
+ getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
+ ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
} else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
@@ -396,9 +398,12 @@
if deps.systemModules != nil {
panic("Found two system module dependencies")
}
- sm := module.(SystemModulesProvider)
- outputDir, outputDeps := sm.OutputDirAndDeps()
- deps.systemModules = &systemModules{outputDir, outputDeps}
+ if sm, ok := android.OtherModuleProvider(ctx, module, SystemModulesProvider); ok {
+ deps.systemModules = &systemModules{sm.OutputDir, sm.OutputDirDeps}
+ } else {
+ ctx.PropertyErrorf("boot classpath dependency %q does not provide SystemModulesProvider",
+ ctx.OtherModuleName(module))
+ }
case aconfigDeclarationTag:
if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
diff --git a/java/droiddoc_test.go b/java/droiddoc_test.go
index e584640..9e1ebbe 100644
--- a/java/droiddoc_test.go
+++ b/java/droiddoc_test.go
@@ -69,7 +69,7 @@
"bar-doc/a.java": nil,
"bar-doc/b.java": nil,
})
- barStubsOutputs := ctx.ModuleForTests("bar-stubs", "android_common").OutputFiles(t, "")
+ barStubsOutputs := ctx.ModuleForTests("bar-stubs", "android_common").OutputFiles(ctx, t, "")
if len(barStubsOutputs) != 1 {
t.Errorf("Expected one output from \"bar-stubs\" got %s", barStubsOutputs)
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index d622903..6bcdf85 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -970,6 +970,15 @@
d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
+ // If UnflaggedApi issues have not already been configured then make sure that existing
+ // UnflaggedApi issues are reported as warnings but issues in new/changed code are treated as
+ // errors by the Build Warnings Aye Aye Analyzer in Gerrit.
+ // Once existing issues have been fixed this will be changed to error.
+ // TODO(b/362771529): Switch to --error
+ if !strings.Contains(cmd.String(), " UnflaggedApi ") {
+ cmd.Flag("--error-when-new UnflaggedApi")
+ }
+
// TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
if d.Name() != "android.car-system-stubs-docs" &&
d.Name() != "android.car-stubs-docs" {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 6a14f36..1e8362c 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -421,11 +421,9 @@
result := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
variables.ExportRuntimeApis = proptools.BoolPtr(true)
}),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
android.FixtureMergeMockFs(map[string][]byte{
"a/A.java": nil,
"a/current.txt": nil,
diff --git a/java/fuzz.go b/java/fuzz.go
index d37c558..e5f1f04 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -85,10 +85,11 @@
func (j *JavaFuzzTest) DepsMutator(ctx android.BottomUpMutatorContext) {
if j.Os().Class.String() == deviceString {
- j.testProperties.Jni_libs = append(j.testProperties.Jni_libs, artDeps...)
+ j.testProperties.Jni_libs.AppendSimpleValue(artDeps)
}
- if len(j.testProperties.Jni_libs) > 0 {
+ jniLibs := j.testProperties.Jni_libs.GetOrDefault(ctx, nil)
+ if len(jniLibs) > 0 {
if j.fuzzPackagedModule.FuzzProperties.Fuzz_config == nil {
config := &fuzz.FuzzConfig{}
j.fuzzPackagedModule.FuzzProperties.Fuzz_config = config
@@ -98,7 +99,7 @@
j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
for _, target := range ctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
- ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
+ ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, jniLibs...)
}
}
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
index d5e6d8f..79f1b6f 100644
--- a/java/generated_java_library.go
+++ b/java/generated_java_library.go
@@ -70,14 +70,6 @@
module.Library.properties.Libs = append(module.Library.properties.Libs, name)
}
-// Add a java shared library as a dependency, as if they had said `libs: [ "name" ]`
-func (module *GeneratedJavaLibraryModule) AddStaticLibrary(name string) {
- if module.depsMutatorDone {
- panic("GeneratedJavaLibraryModule.AddStaticLibrary called after DepsMutator")
- }
- module.Library.properties.Static_libs = append(module.Library.properties.Static_libs, name)
-}
-
func (module *GeneratedJavaLibraryModule) DepsMutator(ctx android.BottomUpMutatorContext) {
module.callbacks.DepsMutator(module, ctx)
module.depsMutatorDone = true
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 5441a3b..b1a9deb 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -98,8 +98,9 @@
// processing.
classesJars := android.Paths{classesJar}
ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
- javaInfo, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
- classesJars = append(classesJars, javaInfo.ImplementationJars...)
+ if javaInfo, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ classesJars = append(classesJars, javaInfo.ImplementationJars...)
+ }
})
h.classesJarPaths = classesJars
@@ -151,7 +152,7 @@
//
// Otherwise, it creates a copy of the supplied dex file into which it has encoded the hiddenapi
// flags and returns this instead of the supplied dex jar.
-func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.OutputPath) android.OutputPath {
+func (h *hiddenAPI) hiddenAPIEncodeDex(ctx android.ModuleContext, dexJar android.Path) android.Path {
if !h.active {
return dexJar
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 4144de8..3650058 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -298,13 +298,12 @@
// available, or reports an error.
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
var dexJar OptionalDexJarPath
- if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
+ if sdkLibrary, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
if ctx.Config().ReleaseHiddenApiExportableStubs() {
- dexJar = sdkLibrary.SdkApiExportableStubDexJar(ctx, kind)
+ dexJar = sdkLibrary.ExportableStubDexJarPaths[kind]
} else {
- dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
+ dexJar = sdkLibrary.EverythingStubDexJarPaths[kind]
}
-
} else if j, ok := module.(UsesLibraryDependency); ok {
dexJar = j.DexJarBuildPath(ctx)
} else {
@@ -853,15 +852,15 @@
i.StubDexJarsByScope.addStubDexJar(ctx, module, apiScope, dexJar)
}
- if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
- removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
+ if sdkLibrary, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
+ removedTxtFile := sdkLibrary.RemovedTxtFiles[sdkKind]
i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
}
}
// If the contents includes any java_sdk_library modules then add them to the stubs.
for _, module := range contents {
- if _, ok := module.(SdkLibraryDependency); ok {
+ if _, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
// Add information for every possible API scope needed by hidden API.
for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
addFromModule(ctx, module, apiScope)
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 6229797..afe8b4c 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -203,10 +203,8 @@
FixtureConfigureBootJars("platform:foo"),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
}),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
java_library {
name: "foo",
diff --git a/java/java.go b/java/java.go
index b320732..661422b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -254,16 +254,26 @@
type JavaInfo struct {
// HeaderJars is a list of jars that can be passed as the javac classpath in order to link
// against this module. If empty, ImplementationJars should be used instead.
+ // Unlike LocalHeaderJars, HeaderJars includes classes from static dependencies.
HeaderJars android.Paths
RepackagedHeaderJars android.Paths
// set of header jars for all transitive libs deps
- TransitiveLibsHeaderJars *android.DepSet[android.Path]
+ TransitiveLibsHeaderJarsForR8 *android.DepSet[android.Path]
// set of header jars for all transitive static libs deps
+ TransitiveStaticLibsHeaderJarsForR8 *android.DepSet[android.Path]
+
+ // depset of header jars for this module and all transitive static dependencies
TransitiveStaticLibsHeaderJars *android.DepSet[android.Path]
+ // depset of implementation jars for this module and all transitive static dependencies
+ TransitiveStaticLibsImplementationJars *android.DepSet[android.Path]
+
+ // depset of resource jars for this module and all transitive static dependencies
+ TransitiveStaticLibsResourceJars *android.DepSet[android.Path]
+
// ImplementationAndResourceJars is a list of jars that contain the implementations of classes
// in the module as well as any resources included in the module.
ImplementationAndResourcesJars android.Paths
@@ -275,6 +285,9 @@
// ResourceJars is a list of jars that contain the resources included in the module.
ResourceJars android.Paths
+ // LocalHeaderJars is a list of jars that contain classes from this module, but not from any static dependencies.
+ LocalHeaderJars android.Paths
+
// AidlIncludeDirs is a list of directories that should be passed to the aidl tool when
// depending on this module.
AidlIncludeDirs android.Paths
@@ -315,14 +328,14 @@
AconfigIntermediateCacheOutputPaths android.Paths
}
-var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
+var JavaInfoProvider = blueprint.NewProvider[*JavaInfo]()
// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
// the sysprop implementation library.
type SyspropPublicStubInfo struct {
// JavaInfo is the JavaInfoProvider of the sysprop public stub library that corresponds to
// the sysprop implementation library.
- JavaInfo JavaInfo
+ JavaInfo *JavaInfo
}
var SyspropPublicStubInfoProvider = blueprint.NewProvider[SyspropPublicStubInfo]()
@@ -343,12 +356,17 @@
// TODO(jungjw): Move this to kythe.go once it's created.
type xref interface {
XrefJavaFiles() android.Paths
+ XrefKotlinFiles() android.Paths
}
func (j *Module) XrefJavaFiles() android.Paths {
return j.kytheFiles
}
+func (j *Module) XrefKotlinFiles() android.Paths {
+ return j.kytheKotlinFiles
+}
+
func (d dependencyTag) PropagateAconfigValidation() bool {
return d.static
}
@@ -421,8 +439,6 @@
bootClasspathTag = dependencyTag{name: "bootclasspath", runtimeLinked: true}
systemModulesTag = dependencyTag{name: "system modules", runtimeLinked: true}
frameworkResTag = dependencyTag{name: "framework-res"}
- kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib", runtimeLinked: true}
- kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations", runtimeLinked: true}
kotlinPluginTag = dependencyTag{name: "kotlin-plugin", toolchain: true}
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
certificateTag = dependencyTag{name: "certificate"}
@@ -432,7 +448,6 @@
r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
- depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
@@ -459,8 +474,6 @@
bootClasspathTag,
systemModulesTag,
java9LibTag,
- kotlinStdlibTag,
- kotlinAnnotationsTag,
kotlinPluginTag,
syspropPublicStubDepTag,
instrumentationForTag,
@@ -558,7 +571,7 @@
// are provided by systemModules.
java9Classpath classpath
- processorPath classpath
+ processorPath classpath ``
errorProneProcessorPath classpath
processorClasses []string
staticJars android.Paths
@@ -569,12 +582,14 @@
srcJars android.Paths
systemModules *systemModules
aidlPreprocess android.OptionalPath
- kotlinStdlib android.Paths
- kotlinAnnotations android.Paths
kotlinPlugins android.Paths
aconfigProtoFiles android.Paths
disableTurbine bool
+
+ transitiveStaticLibsHeaderJars []*android.DepSet[android.Path]
+ transitiveStaticLibsImplementationJars []*android.DepSet[android.Path]
+ transitiveStaticLibsResourceJars []*android.DepSet[android.Path]
}
func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
@@ -987,7 +1002,7 @@
j.dexpreopter.disableDexpreopt()
}
}
- j.compile(ctx, nil, nil, nil)
+ j.compile(ctx, nil, nil, nil, nil)
// If this module is an impl library created from java_sdk_library,
// install the files under the java_sdk_library module outdir instead of this module outdir.
@@ -1015,7 +1030,7 @@
}
hostDexNeeded := Bool(j.deviceProperties.Hostdex) && !ctx.Host()
if hostDexNeeded {
- j.hostdexInstallFile = ctx.InstallFile(
+ j.hostdexInstallFile = ctx.InstallFileWithoutCheckbuild(
android.PathForHostDexInstall(ctx, "framework"),
j.Stem()+"-hostdex.jar", j.outputFile)
}
@@ -1029,7 +1044,7 @@
} else {
installDir = android.PathForModuleInstall(ctx, "framework")
}
- j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
+ j.installFile = ctx.InstallFileWithoutCheckbuild(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
}
@@ -1286,7 +1301,7 @@
Test_options TestOptions
// Names of modules containing JNI libraries that should be installed alongside the test.
- Jni_libs []string
+ Jni_libs proptools.Configurable[[]string]
// Install the test into a folder named for the module in all test suites.
Per_testcase_directory *bool
@@ -1470,10 +1485,11 @@
}
}
- if len(j.testProperties.Jni_libs) > 0 {
+ jniLibs := j.testProperties.Jni_libs.GetOrDefault(ctx, nil)
+ if len(jniLibs) > 0 {
for _, target := range ctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
- ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, j.testProperties.Jni_libs...)
+ ctx.AddFarVariationDependencies(sharedLibVariations, jniLibTag, jniLibs...)
}
}
@@ -1871,10 +1887,12 @@
if ctx.Arch().ArchType == android.Common {
j.deps(ctx)
}
- if ctx.Arch().ArchType != android.Common {
- // These dependencies ensure the host installation rules will install the jar file and
- // the jni libraries when the wrapper is installed.
+ // These dependencies ensure the installation rules will install the jar file when the
+ // wrapper is installed, and the jni libraries on host when the wrapper is installed.
+ if ctx.Arch().ArchType != android.Common && ctx.Os().Class == android.Host {
ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
+ }
+ if ctx.Arch().ArchType != android.Common {
ctx.AddVariationDependencies(
[]blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
binaryInstallTag, ctx.ModuleName())
@@ -1999,17 +2017,11 @@
// List of shared java libs that this module has dependencies to and
// should be passed as classpath in javac invocation
- Libs []string
+ Libs proptools.Configurable[[]string]
// List of java libs that this module has static dependencies to and will be
// merge zipped after metalava invocation
- Static_libs []string
-
- // Java Api library to provide the full API surface stub jar file.
- // If this property is set, the stub jar of this module is created by
- // extracting the compiled class files provided by the
- // full_api_surface_stub module.
- Full_api_surface_stub *string
+ Static_libs proptools.Configurable[[]string]
// Version of previously released API file for compatibility check.
Previous_api *string `android:"path"`
@@ -2043,6 +2055,15 @@
// List of hard coded filegroups containing Metalava config files that are passed to every
// Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd.
ConfigFiles []string `android:"path" blueprint:"mutated"`
+
+ // If not blank, set to the version of the sdk to compile against.
+ // Defaults to an empty string, which compiles the module against the private platform APIs.
+ // Values are of one of the following forms:
+ // 1) numerical API level, "current", "none", or "core_platform"
+ // 2) An SDK kind with an API level: "<sdk kind>_<API level>"
+ // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds.
+ // If the SDK kind is empty, it will be set to public.
+ Sdk_version *string
}
func ApiLibraryFactory() android.Module {
@@ -2141,40 +2162,6 @@
}
}
-// This method extracts the stub class files from the stub jar file provided
-// from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava.
-// This method is used because metalava can generate compilable from-text stubs only when
-// the codebase encompasses all classes listed in the input API text file, and a class can extend
-// a class that is not within the same API domain.
-func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, fullApiSurfaceStubJar android.Path) {
- classFilesList := android.PathForModuleOut(ctx, "metalava", "classes.txt")
- unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
-
- rule.Command().
- BuiltTool("list_files").
- Text(stubsDir.String()).
- FlagWithOutput("--out ", classFilesList).
- FlagWithArg("--extensions ", ".java").
- FlagWithArg("--root ", unzippedSrcJarDir.String()).
- Flag("--classes")
-
- rule.Command().
- Text("unzip").
- Flag("-q").
- Input(fullApiSurfaceStubJar).
- FlagWithArg("-d ", unzippedSrcJarDir.String())
-
- rule.Command().
- BuiltTool("soong_zip").
- Flag("-jar").
- Flag("-write_if_changed").
- Flag("-ignore_missing_files").
- Flag("-quiet").
- FlagWithArg("-C ", unzippedSrcJarDir.String()).
- FlagWithInput("-l ", classFilesList).
- FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
-}
-
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
@@ -2201,14 +2188,18 @@
}
}
}
- ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
- ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
- if al.properties.Full_api_surface_stub != nil {
- ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
+ if ctx.Device() {
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(al))
+ if sdkDep.useModule {
+ ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+ ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
+ ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
+
+ }
}
- if al.properties.System_modules != nil {
- ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules))
- }
+ ctx.AddVariationDependencies(nil, libTag, al.properties.Libs.GetOrDefault(ctx, nil)...)
+ ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs.GetOrDefault(ctx, nil)...)
+
for _, aconfigDeclarationsName := range al.properties.Aconfig_declarations {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationsName)
}
@@ -2264,8 +2255,8 @@
var srcFilesInfo []JavaApiImportInfo
var classPaths android.Paths
+ var bootclassPaths android.Paths
var staticLibs android.Paths
- var depApiSrcsStubsJar android.Path
var systemModulesPaths android.Paths
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
@@ -2277,17 +2268,21 @@
}
srcFilesInfo = append(srcFilesInfo, provider)
case libTag:
- provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
- classPaths = append(classPaths, provider.HeaderJars...)
+ if provider, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ classPaths = append(classPaths, provider.HeaderJars...)
+ }
+ case bootClasspathTag:
+ if provider, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ bootclassPaths = append(bootclassPaths, provider.HeaderJars...)
+ }
case staticLibTag:
- provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
- staticLibs = append(staticLibs, provider.HeaderJars...)
- case depApiSrcsTag:
- provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
- depApiSrcsStubsJar = provider.HeaderJars[0]
+ if provider, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ staticLibs = append(staticLibs, provider.HeaderJars...)
+ }
case systemModulesTag:
- module := dep.(SystemModulesProvider)
- systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...)
+ if sm, ok := android.OtherModuleProvider(ctx, dep, SystemModulesProvider); ok {
+ systemModulesPaths = append(systemModulesPaths, sm.HeaderJars...)
+ }
case metalavaCurrentApiTimestampTag:
if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok {
al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp())
@@ -2319,7 +2314,10 @@
configFiles := android.PathsForModuleSrc(ctx, al.properties.ConfigFiles)
- cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths, configFiles)
+ combinedPaths := append(([]android.Path)(nil), systemModulesPaths...)
+ combinedPaths = append(combinedPaths, classPaths...)
+ combinedPaths = append(combinedPaths, bootclassPaths...)
+ cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, combinedPaths, configFiles)
al.stubsFlags(ctx, cmd, stubsDir)
@@ -2337,9 +2335,6 @@
al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
- if depApiSrcsStubsJar != nil {
- al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsJar)
- }
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
@@ -2350,19 +2345,18 @@
rule.Build("metalava", "metalava merged text")
- if depApiSrcsStubsJar == nil {
- var flags javaBuilderFlags
- flags.javaVersion = getStubsJavaVersion()
- flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
- flags.classpath = classpath(classPaths)
- flags.bootClasspath = classpath(systemModulesPaths)
-
- annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
-
- TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
- android.Paths{al.stubsSrcJar}, annoSrcJar, flags, android.Paths{})
+ javacFlags := javaBuilderFlags{
+ javaVersion: getStubsJavaVersion(),
+ javacFlags: strings.Join(al.properties.Javacflags, " "),
+ classpath: classpath(classPaths),
+ bootClasspath: classpath(append(systemModulesPaths, bootclassPaths...)),
}
+ annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
+
+ TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
+ android.Paths{al.stubsSrcJar}, annoSrcJar, javacFlags, android.Paths{})
+
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().
BuiltTool("merge_zips").
@@ -2373,7 +2367,7 @@
// compile stubs to .dex for hiddenapi processing
dexParams := &compileDexParams{
- flags: javaBuilderFlags{},
+ flags: javacFlags,
sdkVersion: al.SdkVersion(ctx),
minSdkVersion: al.MinSdkVersion(ctx),
classesJar: al.stubsJar,
@@ -2387,12 +2381,15 @@
ctx.Phony(ctx.ModuleName(), al.stubsJar)
- android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(al.stubsJar),
- ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
- ImplementationJars: android.PathsIfNonNil(al.stubsJar),
- AidlIncludeDirs: android.Paths{},
- StubsLinkType: Stubs,
+ android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ HeaderJars: android.PathsIfNonNil(al.stubsJar),
+ LocalHeaderJars: android.PathsIfNonNil(al.stubsJar),
+ TransitiveStaticLibsHeaderJars: android.NewDepSet(android.PREORDER, android.PathsIfNonNil(al.stubsJar), nil),
+ TransitiveStaticLibsImplementationJars: android.NewDepSet(android.PREORDER, android.PathsIfNonNil(al.stubsJar), nil),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
+ ImplementationJars: android.PathsIfNonNil(al.stubsJar),
+ AidlIncludeDirs: android.Paths{},
+ StubsLinkType: Stubs,
// No aconfig libraries on api libraries
})
}
@@ -2409,34 +2406,45 @@
return nil
}
-// java_api_library constitutes the sdk, and does not build against one
+// Most java_api_library constitues the sdk, but there are some java_api_library that
+// does not contribute to the api surface. Such modules are allowed to set sdk_version
+// other than "none"
func (al *ApiLibrary) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecNone
+ return android.SdkSpecFrom(ctx, proptools.String(al.properties.Sdk_version))
}
// java_api_library is always at "current". Return FutureApiLevel
func (al *ApiLibrary) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- return android.FutureApiLevel
+ return al.SdkVersion(ctx).ApiLevel
}
-func (al *ApiLibrary) IDEInfo(i *android.IdeInfo) {
- i.Deps = append(i.Deps, al.ideDeps()...)
- i.Libs = append(i.Libs, al.properties.Libs...)
- i.Static_libs = append(i.Static_libs, al.properties.Static_libs...)
+func (al *ApiLibrary) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return al.SdkVersion(ctx).ApiLevel
+}
+
+func (al *ApiLibrary) SystemModules() string {
+ return proptools.String(al.properties.System_modules)
+}
+
+func (al *ApiLibrary) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return al.SdkVersion(ctx).ApiLevel
+}
+
+func (al *ApiLibrary) IDEInfo(ctx android.BaseModuleContext, i *android.IdeInfo) {
+ i.Deps = append(i.Deps, al.ideDeps(ctx)...)
+ i.Libs = append(i.Libs, al.properties.Libs.GetOrDefault(ctx, nil)...)
+ i.Static_libs = append(i.Static_libs, al.properties.Static_libs.GetOrDefault(ctx, nil)...)
i.SrcJars = append(i.SrcJars, al.stubsSrcJar.String())
}
// deps of java_api_library for module_bp_java_deps.json
-func (al *ApiLibrary) ideDeps() []string {
+func (al *ApiLibrary) ideDeps(ctx android.BaseModuleContext) []string {
ret := []string{}
- ret = append(ret, al.properties.Libs...)
- ret = append(ret, al.properties.Static_libs...)
+ ret = append(ret, al.properties.Libs.GetOrDefault(ctx, nil)...)
+ ret = append(ret, al.properties.Static_libs.GetOrDefault(ctx, nil)...)
if al.properties.System_modules != nil {
ret = append(ret, proptools.String(al.properties.System_modules))
}
- if al.properties.Full_api_surface_stub != nil {
- ret = append(ret, proptools.String(al.properties.Full_api_surface_stub))
- }
// Other non java_library dependencies like java_api_contribution are ignored for now.
return ret
}
@@ -2444,6 +2452,7 @@
// implement the following interfaces for hiddenapi processing
var _ hiddenAPIModule = (*ApiLibrary)(nil)
var _ UsesLibraryDependency = (*ApiLibrary)(nil)
+var _ android.SdkContext = (*ApiLibrary)(nil)
// implement the following interface for IDE completion.
var _ android.IDEInfo = (*ApiLibrary)(nil)
@@ -2476,7 +2485,7 @@
Libs []string
// List of static java libs that this module has dependencies to
- Static_libs []string
+ Static_libs proptools.Configurable[[]string]
// List of files to remove from the jar file(s)
Exclude_files []string
@@ -2604,20 +2613,9 @@
return nil
}
-func (j *Import) LintDepSets() LintDepSets {
- return LintDepSets{}
-}
-
-func (j *Import) getStrictUpdatabilityLinting() bool {
- return false
-}
-
-func (j *Import) setStrictUpdatabilityLinting(bool) {
-}
-
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
- ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs.GetOrDefault(ctx, nil)...)
if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
sdkDeps(ctx, android.SdkContext(j), j.dexer)
@@ -2651,8 +2649,15 @@
var flags javaBuilderFlags
- j.collectTransitiveHeaderJars(ctx)
+ var transitiveClasspathHeaderJars []*android.DepSet[android.Path]
+ var transitiveBootClasspathHeaderJars []*android.DepSet[android.Path]
+ var transitiveStaticLibsHeaderJars []*android.DepSet[android.Path]
+ var transitiveStaticLibsImplementationJars []*android.DepSet[android.Path]
+ var transitiveStaticLibsResourceJars []*android.DepSet[android.Path]
+
+ j.collectTransitiveHeaderJarsForR8(ctx)
var staticJars android.Paths
+ var staticResourceJars android.Paths
var staticHeaderJars android.Paths
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
@@ -2661,107 +2666,156 @@
case libTag, sdkLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
case staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
- staticJars = append(staticJars, dep.ImplementationAndResourcesJars...)
+ staticJars = append(staticJars, dep.ImplementationJars...)
+ staticResourceJars = append(staticResourceJars, dep.ResourceJars...)
staticHeaderJars = append(staticHeaderJars, dep.HeaderJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveClasspathHeaderJars = append(transitiveClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ transitiveStaticLibsHeaderJars = append(transitiveStaticLibsHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsImplementationJars != nil {
+ transitiveStaticLibsImplementationJars = append(transitiveStaticLibsImplementationJars, dep.TransitiveStaticLibsImplementationJars)
+ }
+ if dep.TransitiveStaticLibsResourceJars != nil {
+ transitiveStaticLibsResourceJars = append(transitiveStaticLibsResourceJars, dep.TransitiveStaticLibsResourceJars)
+ }
case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveBootClasspathHeaderJars = append(transitiveBootClasspathHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
}
- } else if dep, ok := module.(SdkLibraryDependency); ok {
+ } else if _, ok := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider); ok {
switch tag {
case libTag, sdkLibTag:
- flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
+ sdkInfo, _ := android.OtherModuleProvider(ctx, module, SdkLibraryInfoProvider)
+ generatingLibsString := android.PrettyConcat(
+ getGeneratingLibs(ctx, j.SdkVersion(ctx), module.Name(), sdkInfo), true, "or")
+ ctx.ModuleErrorf("cannot depend directly on java_sdk_library %q; try depending on %s instead", module.Name(), generatingLibsString)
}
}
addCLCFromDep(ctx, module, j.classLoaderContexts)
})
- jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
+ localJars := android.PathsForModuleSrc(ctx, j.properties.Jars)
jarName := j.Stem() + ".jar"
+ // Combine only the local jars together for use in transitive classpaths.
+ // Always pass input jar through TransformJarsToJar to strip module-info.class from prebuilts.
+ localCombinedHeaderJar := android.PathForModuleOut(ctx, "local-combined", jarName)
+ TransformJarsToJar(ctx, localCombinedHeaderJar, "combine local prebuilt implementation jars", localJars, android.OptionalPath{},
+ false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+ localStrippedJars := android.Paths{localCombinedHeaderJar}
+
+ completeStaticLibsHeaderJars := android.NewDepSet(android.PREORDER, localStrippedJars, transitiveStaticLibsHeaderJars)
+ completeStaticLibsImplementationJars := android.NewDepSet(android.PREORDER, localStrippedJars, transitiveStaticLibsImplementationJars)
+ completeStaticLibsResourceJars := android.NewDepSet(android.PREORDER, nil, transitiveStaticLibsResourceJars)
+
// Always pass the input jars to TransformJarsToJar, even if there is only a single jar, we need the output
// file of the module to be named jarName.
- outputFile := android.PathForModuleOut(ctx, "combined", jarName)
- implementationJars := append(slices.Clone(jars), staticJars...)
- TransformJarsToJar(ctx, outputFile, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
+ 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...)
+ }
+ TransformJarsToJar(ctx, combinedImplementationJar, "combine prebuilt implementation jars", implementationJars, android.OptionalPath{},
false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+ outputFile = combinedImplementationJar
// If no dependencies have separate header jars then there is no need to create a separate
// header jar for this module.
reuseImplementationJarAsHeaderJar := slices.Equal(staticJars, staticHeaderJars)
- var headerOutputFile android.ModuleOutPath
+ var resourceJarFile android.Path
+ if len(staticResourceJars) > 1 {
+ combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", staticResourceJars, android.OptionalPath{},
+ false, nil, nil)
+ resourceJarFile = combinedJar
+ } else if len(staticResourceJars) == 1 {
+ resourceJarFile = staticResourceJars[0]
+ }
+
+ var headerJar android.Path
if reuseImplementationJarAsHeaderJar {
- headerOutputFile = outputFile
+ headerJar = outputFile
} else {
- headerJars := append(slices.Clone(jars), staticHeaderJars...)
- headerOutputFile = android.PathForModuleOut(ctx, "turbine-combined", jarName)
+ var headerJars android.Paths
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ headerJars = completeStaticLibsHeaderJars.ToList()
+ } else {
+ headerJars = append(slices.Clone(localJars), staticHeaderJars...)
+ }
+ headerOutputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
TransformJarsToJar(ctx, headerOutputFile, "combine prebuilt header jars", headerJars, android.OptionalPath{},
false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+ headerJar = headerOutputFile
}
if Bool(j.properties.Jetifier) {
- inputFile := outputFile
- outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
- TransformJetifier(ctx, outputFile, inputFile)
+ jetifierOutputFile := android.PathForModuleOut(ctx, "jetifier", jarName)
+ TransformJetifier(ctx, jetifierOutputFile, outputFile)
+ outputFile = jetifierOutputFile
if !reuseImplementationJarAsHeaderJar {
- headerInputFile := headerOutputFile
- headerOutputFile = android.PathForModuleOut(ctx, "jetifier-headers", jarName)
- TransformJetifier(ctx, headerOutputFile, headerInputFile)
+ jetifierHeaderJar := android.PathForModuleOut(ctx, "jetifier-headers", jarName)
+ TransformJetifier(ctx, jetifierHeaderJar, headerJar)
+ headerJar = jetifierHeaderJar
} else {
- headerOutputFile = outputFile
+ headerJar = outputFile
}
+
+ // Enabling jetifier requires modifying classes from transitive dependencies, disable transitive
+ // classpath and use the combined header jar instead.
+ completeStaticLibsHeaderJars = android.NewDepSet(android.PREORDER, android.Paths{headerJar}, nil)
+ completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, android.Paths{outputFile}, nil)
+ }
+
+ implementationJarFile := outputFile
+
+ // merge implementation jar with resources if necessary
+ if resourceJarFile != nil {
+ jars := android.Paths{resourceJarFile, outputFile}
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ outputFile = combinedJar
}
// 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.
- j.combinedHeaderFile = headerOutputFile.WithoutRel()
+ j.combinedHeaderFile = headerJar.WithoutRel()
j.combinedImplementationFile = outputFile.WithoutRel()
j.maybeInstall(ctx, jarName, outputFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
+ if ctx.Config().UseTransitiveJarsInClasspath() {
+ ctx.CheckbuildFile(localJars...)
+ } else {
+ ctx.CheckbuildFile(outputFile)
+ }
+
if ctx.Device() {
- // If this is a variant created for a prebuilt_apex then use the dex implementation jar
- // obtained from the associated deapexer module.
+ // Shared libraries deapexed from prebuilt apexes are no longer supported.
+ // Set the dexJarBuildPath to a fake path.
+ // This allows soong analysis pass, but will be an error during ninja execution if there are
+ // any rdeps.
ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
- // Get the path of the dex implementation jar from the `deapexer` module.
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- // An error was found, possibly due to multiple apexes in the tree that export this library
- // Defer the error till a client tries to call DexJarBuildPath
- j.dexJarFileErr = err
- j.initHiddenAPIError(err)
- return
- }
- dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
- if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
- dexJarFile := makeDexJarPathFromPath(dexOutputPath)
- j.dexJarFile = dexJarFile
- installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, ApexRootRelativePathToJavaLib(j.BaseModuleName()))
- j.dexJarInstallFile = installPath
-
- j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
- setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
- j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
-
- if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
- j.dexpreopter.inputProfilePathOnHost = profilePath
- }
-
- // Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
- } else {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // prebuilt_apex has been configured to export the java library dex file.
- ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
- }
+ j.dexJarFile = makeDexJarPathFromPath(android.PathForModuleInstall(ctx, "intentionally_no_longer_supported"))
+ j.initHiddenAPI(ctx, j.dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
} else if Bool(j.dexProperties.Compile_dex) {
sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
if sdkDep.invalidVersion {
@@ -2779,7 +2833,7 @@
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
- var dexOutputFile android.OutputPath
+ var dexOutputFile android.Path
dexParams := &compileDexParams{
flags: flags,
sdkVersion: j.SdkVersion(ctx),
@@ -2792,6 +2846,7 @@
if ctx.Failed() {
return
}
+ ctx.CheckbuildFile(dexOutputFile)
// Initialize the hiddenapi structure.
j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), outputFile, j.dexProperties.Uncompress_dex)
@@ -2804,14 +2859,19 @@
}
}
- android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
- ImplementationJars: android.PathsIfNonNil(j.combinedImplementationFile),
- AidlIncludeDirs: j.exportAidlIncludeDirs,
- StubsLinkType: j.stubsLinkType,
+ android.SetProvider(ctx, JavaInfoProvider, &JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
+ LocalHeaderJars: android.PathsIfNonNil(j.combinedHeaderFile),
+ TransitiveLibsHeaderJarsForR8: j.transitiveLibsHeaderJarsForR8,
+ TransitiveStaticLibsHeaderJarsForR8: j.transitiveStaticLibsHeaderJarsForR8,
+ TransitiveStaticLibsHeaderJars: completeStaticLibsHeaderJars,
+ TransitiveStaticLibsImplementationJars: completeStaticLibsImplementationJars,
+ TransitiveStaticLibsResourceJars: completeStaticLibsResourceJars,
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedImplementationFile),
+ ImplementationJars: android.PathsIfNonNil(implementationJarFile.WithoutRel()),
+ ResourceJars: android.PathsIfNonNil(resourceJarFile),
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ StubsLinkType: j.stubsLinkType,
// TODO(b/289117800): LOCAL_ACONFIG_FILES for prebuilts
})
@@ -2923,8 +2983,8 @@
// Collect information for opening IDE project files in java/jdeps.go.
-func (j *Import) IDEInfo(dpInfo *android.IdeInfo) {
- dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...)
+func (j *Import) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
+ dpInfo.Jars = append(dpInfo.Jars, j.combinedHeaderFile.String())
}
func (j *Import) IDECustomizedModuleName() string {
@@ -3028,21 +3088,10 @@
return nil
}
-func (a *DexImport) LintDepSets() LintDepSets {
- return LintDepSets{}
-}
-
func (j *DexImport) IsInstallable() bool {
return true
}
-func (j *DexImport) getStrictUpdatabilityLinting() bool {
- return false
-}
-
-func (j *DexImport) setStrictUpdatabilityLinting(bool) {
-}
-
func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(j.properties.Jars) != 1 {
ctx.PropertyErrorf("jars", "exactly one jar must be provided")
@@ -3212,15 +3261,20 @@
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()...)
}
})
// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
if len(xrefTargets) > 0 {
ctx.Phony("xref_java", xrefTargets...)
}
+ if len(xrefKotlinTargets) > 0 {
+ ctx.Phony("xref_kotlin", xrefKotlinTargets...)
+ }
}
var Bool = proptools.Bool
@@ -3240,9 +3294,13 @@
depName := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(depModule))
var sdkLib *string
- if lib, ok := depModule.(SdkLibraryDependency); ok && lib.sharedLibrary() {
+ 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 ulib, ok := depModule.(ProvidesUsesLib); ok {
// 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.
diff --git a/java/java_test.go b/java/java_test.go
index 33079f3..db154ce 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -20,6 +20,7 @@
"path/filepath"
"reflect"
"runtime"
+ "slices"
"strconv"
"strings"
"testing"
@@ -211,7 +212,7 @@
}
func TestSimple(t *testing.T) {
- ctx, _ := testJava(t, `
+ bp := `
java_library {
name: "foo",
srcs: ["a.java"],
@@ -222,31 +223,157 @@
java_library {
name: "bar",
srcs: ["b.java"],
+ static_libs: ["quz"],
}
java_library {
name: "baz",
srcs: ["c.java"],
+ static_libs: ["quz"],
}
- `)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
+ java_library {
+ name: "quz",
+ srcs: ["d.java"],
+ }`
- if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
- t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
+ 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",
}
- baz := ctx.ModuleForTests("baz", "android_common").Rule("javac").Output.String()
- barTurbine := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
- bazTurbine := filepath.Join("out", "soong", ".intermediates", "baz", "android_common", "turbine-combined", "baz.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",
+ }
- android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], barTurbine)
+ testCases := []struct {
+ name string
- android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], bazTurbine)
+ preparer android.FixturePreparer
- if len(combineJar.Inputs) != 2 || combineJar.Inputs[1].String() != baz {
- t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, baz)
+ fooJavacInputs []string
+ fooJavacClasspath []string
+ fooCombinedInputs []string
+ fooHeaderCombinedInputs []string
+
+ barJavacInputs []string
+ barJavacClasspath []string
+ barCombinedInputs []string
+ barHeaderCombinedInputs []string
+ }{
+ {
+ name: "normal",
+ 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",
+ "out/soong/.intermediates/quz/android_common/turbine/quz.jar",
+ "out/soong/.intermediates/baz/android_common/turbine/baz.jar",
+ },
+ ),
+ fooCombinedInputs: []string{
+ "out/soong/.intermediates/foo/android_common/javac/foo.jar",
+ "out/soong/.intermediates/baz/android_common/javac/baz.jar",
+ "out/soong/.intermediates/quz/android_common/javac/quz.jar",
+ },
+
+ fooHeaderCombinedInputs: []string{
+ "out/soong/.intermediates/foo/android_common/turbine/foo.jar",
+ "out/soong/.intermediates/baz/android_common/turbine/baz.jar",
+ "out/soong/.intermediates/quz/android_common/turbine/quz.jar",
+ },
+
+ barJavacInputs: []string{"b.java"},
+ barJavacClasspath: slices.Concat(
+ frameworkTurbineJars,
+ []string{"out/soong/.intermediates/quz/android_common/turbine/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/quz.jar",
+ },
+ },
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ tt.preparer,
+ ).RunTestWithBp(t, bp)
+ foo := result.ModuleForTests("foo", "android_common")
+
+ fooJavac := foo.Rule("javac")
+ android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs)
+
+ fooJavacClasspath := fooJavac.Args["classpath"]
+ android.AssertStringPathsRelativeToTopEquals(t, "foo javac classpath", result.Config, tt.fooJavacClasspath,
+ strings.Split(strings.TrimPrefix(fooJavacClasspath, "-classpath "), ":"))
+
+ fooCombinedJar := foo.Output("combined/foo.jar")
+ android.AssertPathsRelativeToTopEquals(t, "foo combined inputs", tt.fooCombinedInputs, fooCombinedJar.Inputs)
+
+ fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar")
+ android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs)
+
+ bar := result.ModuleForTests("bar", "android_common")
+ barJavac := bar.Rule("javac")
+ android.AssertPathsRelativeToTopEquals(t, "bar javac inputs", tt.barJavacInputs, barJavac.Inputs)
+
+ barJavacClasspath := barJavac.Args["classpath"]
+ android.AssertStringPathsRelativeToTopEquals(t, "bar javac classpath", result.Config, tt.barJavacClasspath,
+ strings.Split(strings.TrimPrefix(barJavacClasspath, "-classpath "), ":"))
+
+ barCombinedJar := bar.Output("combined/bar.jar")
+ android.AssertPathsRelativeToTopEquals(t, "bar combined inputs", tt.barCombinedInputs, barCombinedJar.Inputs)
+
+ barCombinedHeaderJar := bar.Output("turbine-combined/bar.jar")
+ android.AssertPathsRelativeToTopEquals(t, "bar header combined inputs", tt.barHeaderCombinedInputs, barCombinedHeaderJar.Inputs)
+ })
}
}
@@ -543,7 +670,7 @@
java_library {
name: "foo",
srcs: ["a.java", ":stubs-source"],
- libs: ["bar", "sdklib"],
+ libs: ["bar", "sdklib.stubs"],
static_libs: ["baz"],
}
@@ -590,7 +717,7 @@
barModule := ctx.ModuleForTests("bar", "android_common")
barJar := barModule.Output("combined/bar.jar").Output
bazModule := ctx.ModuleForTests("baz", "android_common")
- bazJar := bazModule.Rule("combineJar").Output
+ bazJar := bazModule.Output("combined/baz.jar").Output
sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").
Output("combined/sdklib.stubs.jar").Output
@@ -1100,7 +1227,7 @@
source := ctx.ModuleForTests("source_library", "android_common")
sourceJar := source.Output("javac/source_library.jar")
sourceHeaderJar := source.Output("turbine-combined/source_library.jar")
- sourceJavaInfo, _ := android.SingletonModuleProvider(ctx, source.Module(), JavaInfoProvider)
+ sourceJavaInfo, _ := android.OtherModuleProvider(ctx, source.Module(), JavaInfoProvider)
// The source library produces separate implementation and header jars
android.AssertPathsRelativeToTopEquals(t, "source library implementation jar",
@@ -1110,7 +1237,7 @@
importWithNoDeps := ctx.ModuleForTests("import_with_no_deps", "android_common")
importWithNoDepsJar := importWithNoDeps.Output("combined/import_with_no_deps.jar")
- importWithNoDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
+ importWithNoDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithNoDeps.Module(), JavaInfoProvider)
// An import with no deps produces a single jar used as both the header and implementation jar.
android.AssertPathsRelativeToTopEquals(t, "import with no deps implementation jar",
@@ -1123,7 +1250,7 @@
importWithSourceDeps := ctx.ModuleForTests("import_with_source_deps", "android_common")
importWithSourceDepsJar := importWithSourceDeps.Output("combined/import_with_source_deps.jar")
importWithSourceDepsHeaderJar := importWithSourceDeps.Output("turbine-combined/import_with_source_deps.jar")
- importWithSourceDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
+ importWithSourceDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithSourceDeps.Module(), JavaInfoProvider)
// An import with source deps produces separate header and implementation jars.
android.AssertPathsRelativeToTopEquals(t, "import with source deps implementation jar",
@@ -1137,7 +1264,7 @@
importWithImportDeps := ctx.ModuleForTests("import_with_import_deps", "android_common")
importWithImportDepsJar := importWithImportDeps.Output("combined/import_with_import_deps.jar")
- importWithImportDepsJavaInfo, _ := android.SingletonModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
+ importWithImportDepsJavaInfo, _ := android.OtherModuleProvider(ctx, importWithImportDeps.Module(), JavaInfoProvider)
// An import with only import deps produces a single jar used as both the header and implementation jar.
android.AssertPathsRelativeToTopEquals(t, "import with import deps implementation jar",
@@ -1342,12 +1469,12 @@
}
`)
- checkBootClasspathForSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar")
+ checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-source-system-modules", "/source-jar.jar")
- checkBootClasspathForSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar")
+ checkBootClasspathForLibWithSystemModule(t, ctx, "lib-with-prebuilt-system-modules", "/prebuilt-jar.jar")
}
-func checkBootClasspathForSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
+func checkBootClasspathForLibWithSystemModule(t *testing.T, ctx *android.TestContext, moduleName string, expectedSuffix string) {
javacRule := ctx.ModuleForTests(moduleName, "android_common").Rule("javac")
bootClasspath := javacRule.Args["bootClasspath"]
if strings.HasPrefix(bootClasspath, "--system ") && strings.HasSuffix(bootClasspath, expectedSuffix) {
@@ -2256,61 +2383,6 @@
}
}
-func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
- provider_bp_a := `
- java_api_contribution {
- name: "foo1",
- api_file: "current.txt",
- api_surface: "public",
- }
- `
- provider_bp_b := `
- java_api_contribution {
- name: "foo2",
- api_file: "current.txt",
- api_surface: "public",
- }
- `
- lib_bp_a := `
- java_api_library {
- name: "lib1",
- api_surface: "public",
- api_contributions: ["foo1", "foo2"],
- stubs_type: "everything",
- }
- `
-
- ctx := android.GroupFixturePreparers(
- prepareForJavaTest,
- android.FixtureMergeMockFs(
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- },
- ),
- android.FixtureMergeEnv(
- map[string]string{
- "DISABLE_STUB_VALIDATION": "true",
- },
- ),
- ).RunTestWithBp(t, `
- java_api_library {
- name: "bar1",
- api_surface: "public",
- api_contributions: ["foo1"],
- full_api_surface_stub: "lib1",
- stubs_type: "everything",
- }
- `)
-
- m := ctx.ModuleForTests("bar1", "android_common")
- manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
- manifestCommand := sboxProto.Commands[0].GetCommand()
- android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
-}
-
func TestTransitiveSrcFiles(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -2329,7 +2401,7 @@
}
`)
c := ctx.ModuleForTests("c", "android_common").Module()
- javaInfo, _ := android.SingletonModuleProvider(ctx, c, JavaInfoProvider)
+ 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())
}
@@ -2382,37 +2454,6 @@
}
}
-func TestJavaExcludeStaticLib(t *testing.T) {
- ctx, _ := testJava(t, `
- java_library {
- name: "bar",
- }
- java_library {
- name: "foo",
- }
- java_library {
- name: "baz",
- static_libs: [
- "foo",
- "bar",
- ],
- exclude_static_libs: [
- "bar",
- ],
- }
- `)
-
- // "bar" not included as dependency of "baz"
- CheckModuleDependencies(t, ctx, "baz", "android_common", []string{
- `core-lambda-stubs`,
- `ext`,
- `foo`,
- `framework`,
- `stable-core-platform-api-stubs-system-modules`,
- `stable.core.platform.api.stubs`,
- })
-}
-
func TestJavaLibraryWithResourcesStem(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
java_library {
@@ -2511,9 +2552,6 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
android.FixtureMergeMockFs(
map[string][]byte{
"A.java": nil,
@@ -2534,12 +2572,8 @@
system_modules: "baz",
}
`)
- m := result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common")
- manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest)
- manifestCommand := sboxProto.Commands[0].GetCommand()
- classPathFlag := "--classpath __SBOX_SANDBOX_DIR__/out/soong/.intermediates/bar/android_common/turbine-combined/bar.jar"
- android.AssertStringDoesContain(t, "command expected to contain classpath flag", manifestCommand, classPathFlag)
+
+ checkBootClasspathForLibWithSystemModule(t, result.TestContext, apiScopePublic.apiLibraryModuleName("foo"), "/bar.jar")
}
func TestApiLibraryDroidstubsDependency(t *testing.T) {
@@ -2547,9 +2581,6 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
android.FixtureMergeMockFs(
map[string][]byte{
"A.java": nil,
@@ -2598,7 +2629,6 @@
PrepareForTestWithJacocoInstrumentation,
FixtureWithLastReleaseApis("foo"),
android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
config.SetBuildFromTextStub(true)
}),
android.FixtureModifyEnv(func(env map[string]string) {
@@ -2613,7 +2643,7 @@
android.AssertBoolEquals(t, "stub module expected to depend on from-source stub",
true, CheckModuleHasDependency(t, result.TestContext,
apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
- apiScopePublic.sourceStubLibraryModuleName("foo")))
+ apiScopePublic.sourceStubsLibraryModuleName("foo")))
android.AssertBoolEquals(t, "stub module expected to not depend on from-text stub",
false, CheckModuleHasDependency(t, result.TestContext,
@@ -2700,11 +2730,7 @@
for _, tc := range testCases {
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
// check that rdep gets the correct variation of dep
@@ -2774,11 +2800,7 @@
ctx := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithPlatformCompatConfig,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
- }
- }),
+ 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")
@@ -2993,9 +3015,9 @@
bar := result.ModuleForTests("bar", "android_common")
baz := result.ModuleForTests("baz", "android_common")
- fooOutputPaths := foo.OutputFiles(t, "")
- barOutputPaths := bar.OutputFiles(t, "")
- bazOutputPaths := baz.OutputFiles(t, "")
+ fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
+ barOutputPaths := bar.OutputFiles(result.TestContext, t, "")
+ bazOutputPaths := baz.OutputFiles(result.TestContext, t, "")
android.AssertPathsRelativeToTopEquals(t, "foo output path",
[]string{"out/soong/.intermediates/foo/android_common/javac/foo.jar"}, fooOutputPaths)
@@ -3012,6 +3034,43 @@
"baz.jar", bazOutputPaths[0].Rel())
}
+func TestCoverage(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ prepareForTestWithFrameworkJacocoInstrumentation,
+ PrepareForTestWithTransitiveClasspathEnabled,
+ ).RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["foo.java"],
+ static_libs: ["android.car"],
+ platform_apis: true,
+ }
+
+ // A library in InstrumentFrameworkModules
+ java_library {
+ name: "android.car",
+ srcs: ["android.car.java"],
+ }
+ `)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ androidCar := result.ModuleForTests("android.car", "android_common")
+
+ fooJacoco := foo.Rule("jacoco")
+ fooCombine := foo.Description("for javac")
+
+ androidCarJacoco := androidCar.Rule("jacoco")
+ androidCarJavac := androidCar.Rule("javac")
+
+ android.AssertStringEquals(t, "foo instrumentation rule inputs", fooJacoco.Input.String(), fooCombine.Output.String())
+ android.AssertStringEquals(t, "android.car instrumentation rule inputs", androidCarJacoco.Input.String(), androidCarJavac.Output.String())
+
+ // The input to instrumentation for the `foo` app contains the non-instrumented android.car classes.
+ android.AssertStringListContains(t, "foo combined inputs", fooCombine.Inputs.Strings(), androidCarJavac.Output.String())
+ android.AssertStringListDoesNotContain(t, "foo combined inputs", fooCombine.Inputs.Strings(), androidCarJacoco.Output.String())
+}
+
func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTestOnly []string, expectedTopLevel []string) {
t.Helper()
actualTrueModules := []string{}
@@ -3042,3 +3101,37 @@
t.Errorf("top-level: Expected but not found: %v, Found but not expected: %v", left, right)
}
}
+
+// Test that a dependency edge is created to the "first" variant of a native library listed in `required` of java_binary
+func TestNativeRequiredDepOfJavaBinary(t *testing.T) {
+ findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module {
+ var ret []blueprint.Module
+ ctx.VisitDirectDeps(module, func(dep blueprint.Module) {
+ if dep.Name() == depName {
+ ret = append(ret, dep)
+ }
+ })
+ return ret
+ }
+
+ bp := cc.GatherRequiredDepsForTest(android.Android) + `
+java_binary {
+ name: "myjavabin",
+ main_class: "com.android.MyJava",
+ required: ["mynativelib"],
+}
+cc_library_shared {
+ name: "mynativelib",
+}
+`
+ res, _ := testJava(t, bp)
+ // The first variant installs the native library via the common variant, so check the deps of both variants.
+ nativeVariantDepsWithDups := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_arm64_armv8-a").Module(), "mynativelib")
+ nativeVariantDepsWithDups = append(nativeVariantDepsWithDups, findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib")...)
+
+ nativeVariantDepsUnique := map[blueprint.Module]bool{}
+ for _, dep := range nativeVariantDepsWithDups {
+ nativeVariantDepsUnique[dep] = true
+ }
+ android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(nativeVariantDepsUnique))
+}
diff --git a/java/jdeps.go b/java/jdeps.go
index 3400263..c2ce503 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -57,27 +57,19 @@
return
}
- ideInfoProvider, ok := module.(android.IDEInfo)
+ ideInfoProvider, ok := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
if !ok {
return
}
- name := ideInfoProvider.BaseModuleName()
+ name := ideInfoProvider.BaseModuleName
ideModuleNameProvider, ok := module.(android.IDECustomizedModuleName)
if ok {
name = ideModuleNameProvider.IDECustomizedModuleName()
}
dpInfo := moduleInfos[name]
- ideInfoProvider.IDEInfo(&dpInfo)
- dpInfo.Deps = android.FirstUniqueStrings(dpInfo.Deps)
- dpInfo.Srcs = android.FirstUniqueStrings(dpInfo.Srcs)
- dpInfo.Aidl_include_dirs = android.FirstUniqueStrings(dpInfo.Aidl_include_dirs)
- dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules)
- dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars)
- dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars)
+ dpInfo = dpInfo.Merge(ideInfoProvider)
dpInfo.Paths = []string{ctx.ModuleDir(module)}
- dpInfo.Static_libs = android.FirstUniqueStrings(dpInfo.Static_libs)
- dpInfo.Libs = android.FirstUniqueStrings(dpInfo.Libs)
moduleInfos[name] = dpInfo
mkProvider, ok := module.(android.AndroidMkDataProvider)
@@ -89,7 +81,7 @@
dpInfo.Classes = append(dpInfo.Classes, data.Class)
}
- if dep, ok := android.SingletonModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
dpInfo.Installed_paths = append(dpInfo.Installed_paths, dep.ImplementationJars.Strings()...)
}
dpInfo.Classes = android.FirstUniqueStrings(dpInfo.Classes)
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index e180224..d282f19 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -32,9 +32,7 @@
}
`)
module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
- dpInfo := &android.IdeInfo{}
-
- module.IDEInfo(dpInfo)
+ dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
for _, expected := range []string{"Foo", "Bar"} {
if !android.InList(expected, dpInfo.Deps) {
@@ -54,9 +52,7 @@
}
`)
module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
- dpInfo := &android.IdeInfo{}
-
- module.IDEInfo(dpInfo)
+ dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
for _, expected := range []string{"Foo", "Bar"} {
if !android.InList(expected, dpInfo.Deps) {
@@ -66,40 +62,75 @@
}
func TestCollectJavaLibraryPropertiesAddScrs(t *testing.T) {
- expected := []string{"Foo", "Bar"}
- module := LibraryFactory().(*Library)
- module.expandIDEInfoCompiledSrcs = append(module.expandIDEInfoCompiledSrcs, expected...)
- dpInfo := &android.IdeInfo{}
+ ctx, _ := testJava(t,
+ `
+ java_library {
+ name: "javalib",
+ srcs: ["Foo.java", "Bar.java"],
+ }
+ `)
+ module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
- module.IDEInfo(dpInfo)
-
+ expected := []string{"Foo.java", "Bar.java"}
if !reflect.DeepEqual(dpInfo.Srcs, expected) {
t.Errorf("Library.IDEInfo() Srcs = %v, want %v", dpInfo.Srcs, expected)
}
}
func TestCollectJavaLibraryPropertiesAddAidlIncludeDirs(t *testing.T) {
+ ctx, _ := testJava(t,
+ `
+ java_library {
+ name: "javalib",
+ aidl: {
+ include_dirs: ["Foo", "Bar"],
+ },
+ }
+ `)
+ module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
+
expected := []string{"Foo", "Bar"}
- module := LibraryFactory().(*Library)
- module.deviceProperties.Aidl.Include_dirs = append(module.deviceProperties.Aidl.Include_dirs, expected...)
- dpInfo := &android.IdeInfo{}
-
- module.IDEInfo(dpInfo)
-
if !reflect.DeepEqual(dpInfo.Aidl_include_dirs, expected) {
t.Errorf("Library.IDEInfo() Aidl_include_dirs = %v, want %v", dpInfo.Aidl_include_dirs, expected)
}
}
-func TestCollectJavaLibraryPropertiesAddJarjarRules(t *testing.T) {
- expected := "Jarjar_rules.txt"
- module := LibraryFactory().(*Library)
- module.expandJarjarRules = android.PathForTesting(expected)
- dpInfo := &android.IdeInfo{}
+func TestCollectJavaLibraryWithJarJarRules(t *testing.T) {
+ ctx, _ := testJava(t,
+ `
+ java_library {
+ name: "javalib",
+ srcs: ["foo.java"],
+ jarjar_rules: "jarjar_rules.txt",
+ }
+ `)
+ module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
+ dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
- module.IDEInfo(dpInfo)
-
- if dpInfo.Jarjar_rules[0] != expected {
- t.Errorf("Library.IDEInfo() Jarjar_rules = %v, want %v", dpInfo.Jarjar_rules[0], expected)
+ android.AssertBoolEquals(t, "IdeInfo.Srcs of repackaged library should be empty", true, len(dpInfo.Srcs) == 0)
+ android.AssertStringEquals(t, "IdeInfo.Jar_rules of repackaged library should not be empty", "jarjar_rules.txt", dpInfo.Jarjar_rules[0])
+ if !android.SubstringInList(dpInfo.Jars, "soong/.intermediates/javalib/android_common/jarjar/turbine/javalib.jar") {
+ t.Errorf("IdeInfo.Jars of repackaged library should contain the output of jarjar-ing. All outputs: %v\n", dpInfo.Jars)
}
}
+
+func TestCollectJavaLibraryLinkingAgainstVersionedSdk(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "29": {},
+ })).RunTestWithBp(t,
+ `
+ java_library {
+ name: "javalib",
+ srcs: ["foo.java"],
+ sdk_version: "29",
+ }
+ `)
+ module := ctx.ModuleForTests("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")
+}
diff --git a/java/kotlin.go b/java/kotlin.go
index aa2db0e..f42d163 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -64,6 +64,28 @@
"kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir",
"headerClassesDir", "headerJar", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
+var kotlinKytheExtract = pctx.AndroidStaticRule("kotlinKythe",
+ blueprint.RuleParams{
+ Command: `rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` +
+ `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" -f "*.kt" $srcJars && ` +
+ `${config.KotlinKytheExtractor} -corpus ${kytheCorpus} --srcs @$out.rsp --srcs @"$srcJarDir/list" $commonSrcFilesList --cp @$classpath -o $out --kotlin_out $outJar ` +
+ // wrap the additional kotlin args.
+ // Skip Xbuild file, pass the cp explicitly.
+ // Skip header jars, those should not have an effect on kythe results.
+ ` --args '${config.KotlincGlobalFlags} ` +
+ ` ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` +
+ ` $kotlincFlags -jvm-target $kotlinJvmTarget ` +
+ `${config.KotlincKytheGlobalFlags}'`,
+ CommandDeps: []string{
+ "${config.KotlinKytheExtractor}",
+ "${config.ZipSyncCmd}",
+ },
+ Rspfile: "$out.rsp",
+ RspfileContent: "$in",
+ },
+ "classpath", "kotlincFlags", "commonSrcFilesList", "kotlinJvmTarget", "outJar", "srcJars", "srcJarDir",
+)
+
func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Paths) android.OptionalPath {
if len(commonSrcFiles) > 0 {
// The list of common_srcs may be too long to put on the command line, but
@@ -81,7 +103,7 @@
}
// kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
-func kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath,
+func (j *Module) kotlinCompile(ctx android.ModuleContext, outputFile, headerOutputFile android.WritablePath,
srcFiles, commonSrcFiles, srcJars android.Paths,
flags javaBuilderFlags) {
@@ -101,6 +123,10 @@
commonSrcFilesArg = "--common_srcs " + commonSrcsList.String()
}
+ classpathRspFile := android.PathForModuleOut(ctx, "kotlinc", "classpath.rsp")
+ android.WriteFileRule(ctx, classpathRspFile, strings.Join(flags.kotlincClasspath.Strings(), " "))
+ deps = append(deps, classpathRspFile)
+
ctx.Build(pctx, android.BuildParams{
Rule: kotlinc,
Description: "kotlinc",
@@ -109,7 +135,7 @@
Inputs: srcFiles,
Implicits: deps,
Args: map[string]string{
- "classpath": flags.kotlincClasspath.FormJavaClassPath(""),
+ "classpath": classpathRspFile.String(),
"kotlincFlags": flags.kotlincFlags,
"commonSrcFilesArg": commonSrcFilesArg,
"srcJars": strings.Join(srcJars.Strings(), " "),
@@ -123,6 +149,31 @@
"name": kotlinName,
},
})
+
+ // Emit kythe xref rule
+ if (ctx.Config().EmitXrefRules()) && ctx.Module() == ctx.PrimaryModule() {
+ extractionFile := outputFile.ReplaceExtension(ctx, "kzip")
+ args := map[string]string{
+ "classpath": classpathRspFile.String(),
+ "kotlincFlags": flags.kotlincFlags,
+ "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
+ "outJar": outputFile.String(),
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars.xref").String(),
+ }
+ if commonSrcsList.Valid() {
+ args["commonSrcFilesList"] = "--common_srcs @" + commonSrcsList.String()
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: kotlinKytheExtract,
+ Description: "kotlinKythe",
+ Output: extractionFile,
+ Inputs: srcFiles,
+ Implicits: deps,
+ Args: args,
+ })
+ j.kytheKotlinFiles = append(j.kytheKotlinFiles, extractionFile)
+ }
}
var kaptStubs = pctx.AndroidRemoteStaticRule("kaptStubs", android.RemoteRuleSupports{Goma: true},
@@ -205,6 +256,10 @@
kotlinName := filepath.Join(ctx.ModuleDir(), ctx.ModuleSubDir(), ctx.ModuleName())
kotlinName = strings.ReplaceAll(kotlinName, "/", "__")
+ classpathRspFile := android.PathForModuleOut(ctx, "kapt", "classpath.rsp")
+ android.WriteFileRule(ctx, classpathRspFile, strings.Join(flags.kotlincClasspath.Strings(), "\n"))
+ deps = append(deps, classpathRspFile)
+
// First run kapt to generate .java stubs from .kt files
kaptStubsJar := android.PathForModuleOut(ctx, "kapt", "stubs.jar")
ctx.Build(pctx, android.BuildParams{
@@ -214,7 +269,7 @@
Inputs: srcFiles,
Implicits: deps,
Args: map[string]string{
- "classpath": flags.kotlincClasspath.FormJavaClassPath(""),
+ "classpath": classpathRspFile.String(),
"kotlincFlags": flags.kotlincFlags,
"commonSrcFilesArg": commonSrcFilesArg,
"srcJars": strings.Join(srcJars.Strings(), " "),
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 933fc51..f6e7fca 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "slices"
"strconv"
"strings"
"testing"
@@ -23,10 +24,11 @@
)
func TestKotlin(t *testing.T) {
- ctx, _ := testJava(t, `
+ bp := `
java_library {
name: "foo",
srcs: ["a.java", "b.kt"],
+ static_libs: ["quz"],
}
java_library {
@@ -39,85 +41,236 @@
java_library {
name: "baz",
srcs: ["c.java"],
+ static_libs: ["quz"],
}
- `)
- kotlinStdlib := ctx.ModuleForTests("kotlin-stdlib", "android_common").
- Output("turbine-combined/kotlin-stdlib.jar").Output
- kotlinStdlibJdk7 := ctx.ModuleForTests("kotlin-stdlib-jdk7", "android_common").
- Output("turbine-combined/kotlin-stdlib-jdk7.jar").Output
- kotlinStdlibJdk8 := ctx.ModuleForTests("kotlin-stdlib-jdk8", "android_common").
- Output("turbine-combined/kotlin-stdlib-jdk8.jar").Output
- kotlinAnnotations := ctx.ModuleForTests("kotlin-annotations", "android_common").
- Output("turbine-combined/kotlin-annotations.jar").Output
+ java_library {
+ name: "quz",
+ srcs: ["d.kt"],
+ }`
- fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
- fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
- fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
-
- fooKotlincClasses := fooKotlinc.Output
- fooKotlincHeaderClasses := fooKotlinc.ImplicitOutput
-
- if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
- fooKotlinc.Inputs[1].String() != "b.kt" {
- t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
+ 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",
}
- if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
- t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
+ 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",
+ "out/soong/.intermediates/default/java/kotlin-stdlib-jdk8/android_common/turbine/kotlin-stdlib-jdk8.jar",
+ "out/soong/.intermediates/default/java/kotlin-annotations/android_common/turbine/kotlin-annotations.jar",
}
- if !strings.Contains(fooJavac.Args["classpath"], fooKotlincHeaderClasses.String()) {
- t.Errorf("foo classpath %v does not contain %q",
- fooJavac.Args["classpath"], fooKotlincHeaderClasses.String())
+ kotlinStdlibJavacJars := []string{
+ "out/soong/.intermediates/default/java/kotlin-stdlib/android_common/javac/kotlin-stdlib.jar",
+ "out/soong/.intermediates/default/java/kotlin-stdlib-jdk7/android_common/javac/kotlin-stdlib-jdk7.jar",
+ "out/soong/.intermediates/default/java/kotlin-stdlib-jdk8/android_common/javac/kotlin-stdlib-jdk8.jar",
+ "out/soong/.intermediates/default/java/kotlin-annotations/android_common/javac/kotlin-annotations.jar",
}
- if !inList(fooKotlincClasses.String(), fooJar.Inputs.Strings()) {
- t.Errorf("foo jar inputs %v does not contain %q",
- fooJar.Inputs.Strings(), fooKotlincClasses.String())
+ 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",
}
- if !inList(kotlinStdlib.String(), fooJar.Inputs.Strings()) {
- t.Errorf("foo jar inputs %v does not contain %v",
- fooJar.Inputs.Strings(), kotlinStdlib.String())
+ 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",
}
- if !inList(kotlinStdlibJdk7.String(), fooJar.Inputs.Strings()) {
- t.Errorf("foo jar inputs %v does not contain %v",
- fooJar.Inputs.Strings(), kotlinStdlibJdk7.String())
+ 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",
}
- if !inList(kotlinStdlibJdk8.String(), fooJar.Inputs.Strings()) {
- t.Errorf("foo jar inputs %v does not contain %v",
- fooJar.Inputs.Strings(), kotlinStdlibJdk8.String())
+ frameworkTurbineJars := []string{
+ "out/soong/.intermediates/default/java/ext/android_common/turbine/ext.jar",
+ "out/soong/.intermediates/default/java/framework/android_common/turbine/framework.jar",
}
- if !inList(kotlinAnnotations.String(), fooJar.Inputs.Strings()) {
- t.Errorf("foo jar inputs %v does not contain %v",
- fooJar.Inputs.Strings(), kotlinAnnotations.String())
+ testCases := []struct {
+ name string
+
+ preparer android.FixturePreparer
+
+ fooKotlincInputs []string
+ fooJavacInputs []string
+ fooKotlincClasspath []string
+ fooJavacClasspath []string
+ fooCombinedInputs []string
+ fooHeaderCombinedInputs []string
+
+ barKotlincInputs []string
+ barKotlincClasspath []string
+ barCombinedInputs []string
+ 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,
+ fooKotlincInputs: []string{"a.java", "b.kt"},
+ fooJavacInputs: []string{"a.java"},
+ fooKotlincClasspath: slices.Concat(
+ bootclasspathTurbineJars,
+ frameworkTurbineJars,
+ []string{"out/soong/.intermediates/quz/android_common/kotlin_headers/quz.jar"},
+ kotlinStdlibTurbineJars,
+ ),
+ fooJavacClasspath: slices.Concat(
+ []string{"out/soong/.intermediates/foo/android_common/kotlin_headers/foo.jar"},
+ frameworkTurbineJars,
+ []string{"out/soong/.intermediates/quz/android_common/kotlin_headers/quz.jar"},
+ kotlinStdlibTurbineJars,
+ ),
+ 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/kotlin/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/kotlin_headers/quz.jar",
+ },
+ kotlinStdlibTurbineJars,
+ ),
+
+ barKotlincInputs: []string{"b.kt"},
+ barKotlincClasspath: slices.Concat(
+ bootclasspathTurbineJars,
+ frameworkTurbineJars,
+ []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/kotlin_headers/quz.jar",
+ },
+ kotlinStdlibTurbineJars,
+ []string{"out/soong/.intermediates/baz/android_common/turbine/baz.jar"},
+ ),
+ barCombinedInputs: slices.Concat(
+ []string{
+ "out/soong/.intermediates/bar/android_common/kotlin/bar.jar",
+ "out/soong/.intermediates/baz/android_common/javac/baz.jar",
+ "out/soong/.intermediates/quz/android_common/kotlin/quz.jar",
+ },
+ kotlinStdlibJavacJars,
+ ),
+ barHeaderCombinedInputs: slices.Concat(
+ []string{
+ "out/soong/.intermediates/bar/android_common/kotlin_headers/bar.jar",
+ "out/soong/.intermediates/baz/android_common/turbine/baz.jar",
+ "out/soong/.intermediates/quz/android_common/kotlin_headers/quz.jar",
+ },
+ kotlinStdlibTurbineJars,
+ ),
+ },
}
- if !inList(fooKotlincHeaderClasses.String(), fooHeaderJar.Inputs.Strings()) {
- t.Errorf("foo header jar inputs %v does not contain %q",
- fooHeaderJar.Inputs.Strings(), fooKotlincHeaderClasses.String())
- }
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ tt.preparer,
+ ).RunTestWithBp(t, bp)
+ foo := result.ModuleForTests("foo", "android_common")
+ fooKotlinc := foo.Rule("kotlinc")
+ android.AssertPathsRelativeToTopEquals(t, "foo kotlinc inputs", tt.fooKotlincInputs, fooKotlinc.Inputs)
- bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
- barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
+ fooKotlincClasspath := android.ContentFromFileRuleForTests(t, result.TestContext, foo.Output("kotlinc/classpath.rsp"))
+ android.AssertStringPathsRelativeToTopEquals(t, "foo kotlinc classpath", result.Config, tt.fooKotlincClasspath, strings.Fields(fooKotlincClasspath))
- if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
- t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
- }
+ fooJavac := foo.Rule("javac")
+ android.AssertPathsRelativeToTopEquals(t, "foo javac inputs", tt.fooJavacInputs, fooJavac.Inputs)
- if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
- t.Errorf(`expected %q in bar implicits %v`,
- fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
- }
+ fooJavacClasspath := fooJavac.Args["classpath"]
+ android.AssertStringPathsRelativeToTopEquals(t, "foo javac classpath", result.Config, tt.fooJavacClasspath,
+ strings.Split(strings.TrimPrefix(fooJavacClasspath, "-classpath "), ":"))
- if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
- t.Errorf(`expected %q in bar implicits %v`,
- bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
+ fooCombinedJar := foo.Output("combined/foo.jar")
+ android.AssertPathsRelativeToTopEquals(t, "foo combined inputs", tt.fooCombinedInputs, fooCombinedJar.Inputs)
+
+ fooCombinedHeaderJar := foo.Output("turbine-combined/foo.jar")
+ android.AssertPathsRelativeToTopEquals(t, "foo header combined inputs", tt.fooHeaderCombinedInputs, fooCombinedHeaderJar.Inputs)
+
+ bar := result.ModuleForTests("bar", "android_common")
+ barKotlinc := bar.Rule("kotlinc")
+ android.AssertPathsRelativeToTopEquals(t, "bar kotlinc inputs", tt.barKotlincInputs, barKotlinc.Inputs)
+
+ barKotlincClasspath := android.ContentFromFileRuleForTests(t, result.TestContext, bar.Output("kotlinc/classpath.rsp"))
+ android.AssertStringPathsRelativeToTopEquals(t, "bar kotlinc classpath", result.Config, tt.barKotlincClasspath, strings.Fields(barKotlincClasspath))
+
+ barCombinedJar := bar.Output("combined/bar.jar")
+ android.AssertPathsRelativeToTopEquals(t, "bar combined inputs", tt.barCombinedInputs, barCombinedJar.Inputs)
+
+ barCombinedHeaderJar := bar.Output("turbine-combined/bar.jar")
+ android.AssertPathsRelativeToTopEquals(t, "bar header combined inputs", tt.barHeaderCombinedInputs, barCombinedHeaderJar.Inputs)
+ })
}
}
diff --git a/java/lint.go b/java/lint.go
index 2eea07d..2cbefc3 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -19,6 +19,7 @@
"sort"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -90,7 +91,6 @@
compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
- outputs lintOutputs
properties LintProperties
extraMainlineLintErrors []string
compile_data android.Paths
@@ -100,68 +100,55 @@
buildModuleReportZip bool
}
-type lintOutputs struct {
- html android.Path
- text android.Path
- xml android.Path
- referenceBaseline android.Path
-
- depSets LintDepSets
-}
-
-type lintOutputsIntf interface {
- lintOutputs() *lintOutputs
-}
-
-type LintDepSetsIntf interface {
- LintDepSets() LintDepSets
-
- // Methods used to propagate strict_updatability_linting values.
- GetStrictUpdatabilityLinting() bool
- SetStrictUpdatabilityLinting(bool)
-}
-
type LintDepSets struct {
- HTML, Text, XML *android.DepSet[android.Path]
+ HTML, Text, XML, Baseline *android.DepSet[android.Path]
}
type LintDepSetsBuilder struct {
- HTML, Text, XML *android.DepSetBuilder[android.Path]
+ HTML, Text, XML, Baseline *android.DepSetBuilder[android.Path]
}
func NewLintDepSetBuilder() LintDepSetsBuilder {
return LintDepSetsBuilder{
- HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
- Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
- XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ HTML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Text: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ XML: android.NewDepSetBuilder[android.Path](android.POSTORDER),
+ Baseline: android.NewDepSetBuilder[android.Path](android.POSTORDER),
}
}
-func (l LintDepSetsBuilder) Direct(html, text, xml android.Path) LintDepSetsBuilder {
+func (l LintDepSetsBuilder) Direct(html, text, xml android.Path, baseline android.OptionalPath) LintDepSetsBuilder {
l.HTML.Direct(html)
l.Text.Direct(text)
l.XML.Direct(xml)
+ if baseline.Valid() {
+ l.Baseline.Direct(baseline.Path())
+ }
return l
}
-func (l LintDepSetsBuilder) Transitive(depSets LintDepSets) LintDepSetsBuilder {
- if depSets.HTML != nil {
- l.HTML.Transitive(depSets.HTML)
+func (l LintDepSetsBuilder) Transitive(info *LintInfo) LintDepSetsBuilder {
+ if info.TransitiveHTML != nil {
+ l.HTML.Transitive(info.TransitiveHTML)
}
- if depSets.Text != nil {
- l.Text.Transitive(depSets.Text)
+ if info.TransitiveText != nil {
+ l.Text.Transitive(info.TransitiveText)
}
- if depSets.XML != nil {
- l.XML.Transitive(depSets.XML)
+ if info.TransitiveXML != nil {
+ l.XML.Transitive(info.TransitiveXML)
+ }
+ if info.TransitiveBaseline != nil {
+ l.Baseline.Transitive(info.TransitiveBaseline)
}
return l
}
func (l LintDepSetsBuilder) Build() LintDepSets {
return LintDepSets{
- HTML: l.HTML.Build(),
- Text: l.Text.Build(),
- XML: l.XML.Build(),
+ HTML: l.HTML.Build(),
+ Text: l.Text.Build(),
+ XML: l.XML.Build(),
+ Baseline: l.Baseline.Build(),
}
}
@@ -209,24 +196,18 @@
},
}
-func (l *linter) LintDepSets() LintDepSets {
- return l.outputs.depSets
-}
+var LintProvider = blueprint.NewProvider[*LintInfo]()
-func (l *linter) GetStrictUpdatabilityLinting() bool {
- return BoolDefault(l.properties.Lint.Strict_updatability_linting, false)
-}
+type LintInfo struct {
+ HTML android.Path
+ Text android.Path
+ XML android.Path
+ ReferenceBaseline android.Path
-func (l *linter) SetStrictUpdatabilityLinting(strictLinting bool) {
- l.properties.Lint.Strict_updatability_linting = &strictLinting
-}
-
-var _ LintDepSetsIntf = (*linter)(nil)
-
-var _ lintOutputsIntf = (*linter)(nil)
-
-func (l *linter) lintOutputs() *lintOutputs {
- return &l.outputs
+ TransitiveHTML *android.DepSet[android.Path]
+ TransitiveText *android.DepSet[android.Path]
+ TransitiveXML *android.DepSet[android.Path]
+ TransitiveBaseline *android.DepSet[android.Path]
}
func (l *linter) enabled() bool {
@@ -262,7 +243,9 @@
return ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
}
-func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path) lintPaths {
+func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder, srcsList android.Path,
+ baselines android.Paths) lintPaths {
+
projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
// Lint looks for a lint.xml file next to the project.xml file, give it one.
configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
@@ -325,12 +308,10 @@
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- if l.GetStrictUpdatabilityLinting() {
+ if Bool(l.properties.Lint.Strict_updatability_linting) && len(baselines) > 0 {
// Verify the module does not baseline issues that endanger safe updatability.
- if l.properties.Lint.Baseline_filename != nil {
- cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
- cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
- }
+ strictUpdatabilityChecksOutputFile := VerifyStrictUpdatabilityChecks(ctx, baselines)
+ cmd.Validation(strictUpdatabilityChecksOutputFile)
}
return lintPaths{
@@ -342,6 +323,22 @@
}
+func VerifyStrictUpdatabilityChecks(ctx android.ModuleContext, baselines android.Paths) android.Path {
+ rule := android.NewRuleBuilder(pctx, ctx)
+ baselineRspFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check_baselines.rsp")
+ outputFile := android.PathForModuleOut(ctx, "lint_strict_updatability_check.stamp")
+ rule.Command().Text("rm -f").Output(outputFile)
+ rule.Command().
+ BuiltTool("lint_strict_updatability_checks").
+ FlagWithArg("--name ", ctx.ModuleName()).
+ FlagWithRspFileInputList("--baselines ", baselineRspFile, baselines).
+ FlagForEachArg("--disallowed_issues ", updatabilityChecks)
+ rule.Command().Text("touch").Output(outputFile)
+ rule.Build("lint_strict_updatability_checks", "lint strict updatability checks")
+
+ return outputFile
+}
+
// generateManifest adds a command to the rule to write a simple manifest that contains the
// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest.
func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.WritablePath {
@@ -411,6 +408,26 @@
l.extraLintCheckJars = append(l.extraLintCheckJars, android.PathForSource(ctx,
"prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar"))
+ var baseline android.OptionalPath
+ if l.properties.Lint.Baseline_filename != nil {
+ baseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ }
+
+ html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
+ text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
+ xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
+ referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml")
+
+ depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml, baseline)
+
+ ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
+ if info, ok := android.OtherModuleProvider(ctx, dep, LintProvider); ok {
+ depSetsBuilder.Transitive(info)
+ }
+ })
+
+ depSets := depSetsBuilder.Build()
+
rule := android.NewRuleBuilder(pctx, ctx).
Sbox(android.PathForModuleOut(ctx, "lint"),
android.PathForModuleOut(ctx, "lint.sbox.textproto")).
@@ -437,20 +454,9 @@
srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data)
- lintPaths := l.writeLintProjectXML(ctx, rule, srcsList)
+ baselines := depSets.Baseline.ToList()
- html := android.PathForModuleOut(ctx, "lint", "lint-report.html")
- text := android.PathForModuleOut(ctx, "lint", "lint-report.txt")
- xml := android.PathForModuleOut(ctx, "lint", "lint-report.xml")
- referenceBaseline := android.PathForModuleOut(ctx, "lint", "lint-baseline.xml")
-
- depSetsBuilder := NewLintDepSetBuilder().Direct(html, text, xml)
-
- ctx.VisitDirectDepsWithTag(staticLibTag, func(dep android.Module) {
- if depLint, ok := dep.(LintDepSetsIntf); ok {
- depSetsBuilder.Transitive(depLint.LintDepSets())
- }
- })
+ lintPaths := l.writeLintProjectXML(ctx, rule, srcsList, baselines)
rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
@@ -505,8 +511,8 @@
cmd.FlagWithArg("--check ", checkOnly)
}
- if l.properties.Lint.Baseline_filename != nil {
- cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
+ if baseline.Valid() {
+ cmd.FlagWithInput("--baseline ", baseline.Path())
}
cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
@@ -530,25 +536,30 @@
rule.Build("lint", "lint")
- l.outputs = lintOutputs{
- html: html,
- text: text,
- xml: xml,
- referenceBaseline: referenceBaseline,
+ android.SetProvider(ctx, LintProvider, &LintInfo{
+ HTML: html,
+ Text: text,
+ XML: xml,
+ ReferenceBaseline: referenceBaseline,
- depSets: depSetsBuilder.Build(),
- }
+ TransitiveHTML: depSets.HTML,
+ TransitiveText: depSets.Text,
+ TransitiveXML: depSets.XML,
+ TransitiveBaseline: depSets.Baseline,
+ })
if l.buildModuleReportZip {
- l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
+ l.reports = BuildModuleLintReportZips(ctx, depSets, nil)
}
// Create a per-module phony target to run the lint check.
phonyName := ctx.ModuleName() + "-lint"
ctx.Phony(phonyName, xml)
+
+ ctx.SetOutputFiles(android.Paths{xml}, ".lint")
}
-func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
+func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets, validations android.Paths) android.Paths {
htmlList := android.SortedUniquePaths(depSets.HTML.ToList())
textList := android.SortedUniquePaths(depSets.Text.ToList())
xmlList := android.SortedUniquePaths(depSets.XML.ToList())
@@ -558,13 +569,13 @@
}
htmlZip := android.PathForModuleOut(ctx, "lint-report-html.zip")
- lintZip(ctx, htmlList, htmlZip)
+ lintZip(ctx, htmlList, htmlZip, validations)
textZip := android.PathForModuleOut(ctx, "lint-report-text.zip")
- lintZip(ctx, textList, textZip)
+ lintZip(ctx, textList, textZip, validations)
xmlZip := android.PathForModuleOut(ctx, "lint-report-xml.zip")
- lintZip(ctx, xmlList, xmlZip)
+ lintZip(ctx, xmlList, xmlZip, validations)
return android.Paths{htmlZip, textZip, xmlZip}
}
@@ -642,7 +653,7 @@
return
}
- var outputs []*lintOutputs
+ var outputs []*LintInfo
var dirs []string
ctx.VisitAllModules(func(m android.Module) {
if ctx.Config().KatiEnabled() && !m.ExportedToMake() {
@@ -650,7 +661,7 @@
}
if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
- apexInfo, _ := android.SingletonModuleProvider(ctx, m, android.ApexInfoProvider)
+ apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
// There are stray platform variants of modules in apexes that are not available for
// the platform, and they sometimes can't be built. Don't depend on them.
@@ -658,14 +669,14 @@
}
}
- if l, ok := m.(lintOutputsIntf); ok {
- outputs = append(outputs, l.lintOutputs())
+ if lintInfo, ok := android.OtherModuleProvider(ctx, m, LintProvider); ok {
+ outputs = append(outputs, lintInfo)
}
})
dirs = android.SortedUniqueStrings(dirs)
- zip := func(outputPath android.WritablePath, get func(*lintOutputs) android.Path) {
+ zip := func(outputPath android.WritablePath, get func(*LintInfo) android.Path) {
var paths android.Paths
for _, output := range outputs {
@@ -674,20 +685,20 @@
}
}
- lintZip(ctx, paths, outputPath)
+ lintZip(ctx, paths, outputPath, nil)
}
l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip")
- zip(l.htmlZip, func(l *lintOutputs) android.Path { return l.html })
+ zip(l.htmlZip, func(l *LintInfo) android.Path { return l.HTML })
l.textZip = android.PathForOutput(ctx, "lint-report-text.zip")
- zip(l.textZip, func(l *lintOutputs) android.Path { return l.text })
+ zip(l.textZip, func(l *LintInfo) android.Path { return l.Text })
l.xmlZip = android.PathForOutput(ctx, "lint-report-xml.zip")
- zip(l.xmlZip, func(l *lintOutputs) android.Path { return l.xml })
+ zip(l.xmlZip, func(l *LintInfo) android.Path { return l.XML })
l.referenceBaselineZip = android.PathForOutput(ctx, "lint-report-reference-baselines.zip")
- zip(l.referenceBaselineZip, func(l *lintOutputs) android.Path { return l.referenceBaseline })
+ zip(l.referenceBaselineZip, func(l *LintInfo) android.Path { return l.ReferenceBaseline })
ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip, l.referenceBaselineZip)
}
@@ -703,17 +714,9 @@
func init() {
android.RegisterParallelSingletonType("lint",
func() android.Singleton { return &lintSingleton{} })
-
- registerLintBuildComponents(android.InitRegistrationContext)
}
-func registerLintBuildComponents(ctx android.RegistrationContext) {
- ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("enforce_strict_updatability_linting", enforceStrictUpdatabilityLintingMutator).Parallel()
- })
-}
-
-func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath) {
+func lintZip(ctx android.BuilderContext, paths android.Paths, outputPath android.WritablePath, validations android.Paths) {
paths = android.SortedUniquePaths(android.CopyOfPaths(paths))
sort.Slice(paths, func(i, j int) bool {
@@ -725,19 +728,8 @@
rule.Command().BuiltTool("soong_zip").
FlagWithOutput("-o ", outputPath).
FlagWithArg("-C ", android.PathForIntermediates(ctx).String()).
- FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths)
+ FlagWithRspFileInputList("-r ", outputPath.ReplaceExtension(ctx, "rsp"), paths).
+ Validations(validations)
rule.Build(outputPath.Base(), outputPath.Base())
}
-
-// Enforce the strict updatability linting to all applicable transitive dependencies.
-func enforceStrictUpdatabilityLintingMutator(ctx android.TopDownMutatorContext) {
- m := ctx.Module()
- if d, ok := m.(LintDepSetsIntf); ok && d.GetStrictUpdatabilityLinting() {
- ctx.VisitDirectDepsWithTag(staticLibTag, func(d android.Module) {
- if a, ok := d.(LintDepSetsIntf); ok {
- a.SetStrictUpdatabilityLinting(true)
- }
- })
- }
-}
diff --git a/java/lint_test.go b/java/lint_test.go
index b51753f..afe3914 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -164,7 +164,7 @@
sdk_version: "current",
lint: {
strict_updatability_linting: true,
- baseline_filename: "lint-baseline.xml",
+ baseline_filename: "foo_lint_baseline.xml",
},
}
@@ -176,7 +176,7 @@
min_sdk_version: "29",
sdk_version: "current",
lint: {
- baseline_filename: "lint-baseline.xml",
+ baseline_filename: "bar_lint_baseline.xml",
}
}
`
@@ -188,18 +188,13 @@
RunTestWithBp(t, bp)
foo := result.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command,
- "--baseline lint-baseline.xml --disallowed_issues NewApi") {
+ strictUpdatabilityCheck := foo.Output("lint_strict_updatability_check.stamp")
+ if !strings.Contains(strictUpdatabilityCheck.RuleParams.Command,
+ "--disallowed_issues NewApi") {
t.Error("did not restrict baselining NewApi")
}
-
- bar := result.ModuleForTests("bar", "android_common")
- sboxProto = android.RuleBuilderSboxProtoForTests(t, result.TestContext, bar.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command,
- "--baseline lint-baseline.xml --disallowed_issues NewApi") {
- t.Error("did not restrict baselining NewApi")
- }
+ android.AssertStringListContains(t, "strict updatability check baseline inputs", strictUpdatabilityCheck.Inputs.Strings(), "foo_lint_baseline.xml")
+ android.AssertStringListContains(t, "strict updatability check baseline inputs", strictUpdatabilityCheck.Inputs.Strings(), "bar_lint_baseline.xml")
}
func TestJavaLintDatabaseSelectionFull(t *testing.T) {
diff --git a/java/metalava/Android.bp b/java/metalava/Android.bp
index ccbd191..6bf1832 100644
--- a/java/metalava/Android.bp
+++ b/java/metalava/Android.bp
@@ -15,4 +15,5 @@
filegroup {
name: "metalava-config-files",
srcs: ["*-config.xml"],
+ visibility: ["//visibility:public"],
}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 38553a6..5bb7754 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -33,6 +33,7 @@
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 platformBootclasspathModule struct {
@@ -111,12 +112,18 @@
// Add dependencies on all the ART jars.
global := dexpreopt.GetGlobalConfig(ctx)
addDependenciesOntoSelectedBootImageApexes(ctx, "com.android.art")
+
+ var bootImageModuleNames []string
+
// TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
+ bootImageModuleNames = append(bootImageModuleNames, global.ArtApexJars.CopyOfJars()...)
// Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
// APEXes.
- addDependenciesOntoBootImageModules(ctx, b.platformJars(ctx), platformBootclasspathBootJarDepTag)
+ platformJars := b.platformJars(ctx)
+ addDependenciesOntoBootImageModules(ctx, platformJars, platformBootclasspathBootJarDepTag)
+ bootImageModuleNames = append(bootImageModuleNames, platformJars.CopyOfJars()...)
// Add dependencies on all the updatable jars, except the ART jars.
apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
@@ -127,9 +134,17 @@
addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
// TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
+ bootImageModuleNames = append(bootImageModuleNames, apexJars.CopyOfJars()...)
// Add dependencies on all the fragments.
b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx)
+
+ for _, bootImageModuleName := range bootImageModuleNames {
+ implLibName := implLibraryModuleName(bootImageModuleName)
+ if ctx.OtherModuleExists(implLibName) {
+ ctx.AddFarVariationDependencies(nil, platformBootclasspathImplLibDepTag, implLibName)
+ }
+ }
}
func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tag bootclasspathDependencyTag) {
@@ -166,11 +181,19 @@
allModules = append(allModules, apexModules...)
b.configuredModules = allModules
+ // 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) {
+ implLibModule = append(implLibModule, m)
+ })
+
var transitiveSrcFiles android.Paths
- for _, module := range allModules {
- depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
- if depInfo.TransitiveSrcFiles != nil {
- transitiveSrcFiles = append(transitiveSrcFiles, depInfo.TransitiveSrcFiles.ToList()...)
+ for _, module := range append(allModules, implLibModule...) {
+ if depInfo, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if depInfo.TransitiveSrcFiles != nil {
+ transitiveSrcFiles = append(transitiveSrcFiles, depInfo.TransitiveSrcFiles.ToList()...)
+ }
}
}
jarArgs := resourcePathsToJarArgs(transitiveSrcFiles)
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 67ed84e..5b145c6 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -110,6 +110,7 @@
p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base())
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}, "")
}
func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 00613ee..527e479 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -124,8 +124,8 @@
return
}
-func prebuiltApiModuleName(mctx android.LoadHookContext, module, scope, version string) string {
- return fmt.Sprintf("%s_%s_%s_%s", mctx.ModuleName(), scope, version, module)
+func prebuiltApiModuleName(moduleName, module, scope, version string) string {
+ return fmt.Sprintf("%s_%s_%s_%s", moduleName, scope, version, module)
}
func createImport(mctx android.LoadHookContext, module, scope, version, path, sdkVersion string, compileDex bool) {
props := struct {
@@ -135,7 +135,7 @@
Installable *bool
Compile_dex *bool
}{
- Name: proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, version)),
+ Name: proptools.StringPtr(prebuiltApiModuleName(mctx.ModuleName(), module, scope, version)),
Jars: []string{path},
Sdk_version: proptools.StringPtr(sdkVersion),
Installable: proptools.BoolPtr(false),
@@ -257,8 +257,8 @@
Name *string
Libs []string
}{}
- props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", scope, version))
- props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", scope, version))
+ props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx.ModuleName(), "system_modules", scope, version))
+ props.Libs = append(props.Libs, prebuiltApiModuleName(mctx.ModuleName(), "core-for-system-modules", scope, version))
mctx.CreateModule(systemModulesImportFactory, &props)
}
diff --git a/java/ravenwood.go b/java/ravenwood.go
index 84c285c..4c9fdc2 100644
--- a/java/ravenwood.go
+++ b/java/ravenwood.go
@@ -33,8 +33,8 @@
var ravenwoodLibContentTag = dependencyTag{name: "ravenwoodlibcontent"}
var ravenwoodUtilsTag = dependencyTag{name: "ravenwoodutils"}
var ravenwoodRuntimeTag = dependencyTag{name: "ravenwoodruntime"}
-var ravenwoodDataTag = dependencyTag{name: "ravenwooddata"}
var ravenwoodTestResourceApkTag = dependencyTag{name: "ravenwoodtestresapk"}
+var ravenwoodTestInstResourceApkTag = dependencyTag{name: "ravenwoodtest-inst-res-apk"}
const ravenwoodUtilsName = "ravenwood-utils"
const ravenwoodRuntimeName = "ravenwood-runtime"
@@ -54,14 +54,20 @@
}
type ravenwoodTestProperties struct {
- Jni_libs []string
+ Jni_libs proptools.Configurable[[]string]
// Specify another android_app module here to copy it to the test directory, so that
- // the ravenwood test can access it.
+ // the ravenwood test can access it. This APK will be loaded as resources of the test
+ // target app.
// TODO: For now, we simply refer to another android_app module and copy it to the
// test directory. Eventually, android_ravenwood_test should support all the resource
// related properties and build resources from the `res/` directory.
Resource_apk *string
+
+ // Specify another android_app module here to copy it to the test directory, so that
+ // the ravenwood test can access it. This APK will be loaded as resources of the test
+ // instrumentation app itself.
+ Inst_resource_apk *string
}
type ravenwoodTest struct {
@@ -120,7 +126,7 @@
}
// Add jni libs
- for _, lib := range r.ravenwoodTestProperties.Jni_libs {
+ for _, lib := range r.ravenwoodTestProperties.Jni_libs.GetOrDefault(ctx, nil) {
ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
}
@@ -128,6 +134,10 @@
if resourceApk := proptools.String(r.ravenwoodTestProperties.Resource_apk); resourceApk != "" {
ctx.AddVariationDependencies(nil, ravenwoodTestResourceApkTag, resourceApk)
}
+
+ if resourceApk := proptools.String(r.ravenwoodTestProperties.Inst_resource_apk); resourceApk != "" {
+ ctx.AddVariationDependencies(nil, ravenwoodTestInstResourceApkTag, resourceApk)
+ }
}
func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -143,6 +153,9 @@
HostTemplate: "${RavenwoodTestConfigTemplate}",
})
+ // Always enable Ravenizer for ravenwood tests.
+ r.Library.ravenizer.enabled = true
+
r.Library.GenerateAndroidBuildActions(ctx)
// Start by depending on all files installed by dependencies
@@ -152,7 +165,8 @@
var runtimeJniModuleNames map[string]bool
if utils := ctx.GetDirectDepsWithTag(ravenwoodUtilsTag)[0]; utils != nil {
- for _, installFile := range utils.FilesToInstall() {
+ for _, installFile := range android.OtherModuleProviderOrDefault(
+ ctx, utils, android.InstallFilesProvider).InstallFiles {
installDeps = append(installDeps, installFile)
}
jniDeps, ok := android.OtherModuleProvider(ctx, utils, ravenwoodLibgroupJniDepProvider)
@@ -162,7 +176,8 @@
}
if runtime := ctx.GetDirectDepsWithTag(ravenwoodRuntimeTag)[0]; runtime != nil {
- for _, installFile := range runtime.FilesToInstall() {
+ for _, installFile := range android.OtherModuleProviderOrDefault(
+ ctx, runtime, android.InstallFilesProvider).InstallFiles {
installDeps = append(installDeps, installFile)
}
jniDeps, ok := android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider)
@@ -190,12 +205,16 @@
}
resApkInstallPath := installPath.Join(ctx, "ravenwood-res-apks")
- if resApk := ctx.GetDirectDepsWithTag(ravenwoodTestResourceApkTag); len(resApk) > 0 {
- for _, installFile := range resApk[0].FilesToInstall() {
- installResApk := ctx.InstallFile(resApkInstallPath, "ravenwood-res.apk", installFile)
+
+ copyResApk := func(tag blueprint.DependencyTag, toFileName string) {
+ if resApk := ctx.GetDirectDepsWithTag(tag); len(resApk) > 0 {
+ installFile := android.OutputFileForModule(ctx, resApk[0], "")
+ installResApk := ctx.InstallFile(resApkInstallPath, toFileName, installFile)
installDeps = append(installDeps, installResApk)
}
}
+ copyResApk(ravenwoodTestResourceApkTag, "ravenwood-res.apk")
+ copyResApk(ravenwoodTestInstResourceApkTag, "ravenwood-inst-res.apk")
// Install our JAR with all dependencies
ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
@@ -219,10 +238,13 @@
type ravenwoodLibgroupProperties struct {
Libs []string
- Jni_libs []string
+ Jni_libs proptools.Configurable[[]string]
// We use this to copy framework-res.apk to the ravenwood runtime directory.
- Data []string
+ Data []string `android:"path,arch_variant"`
+
+ // We use this to copy font files to the ravenwood runtime directory.
+ Fonts []string `android:"path,arch_variant"`
}
type ravenwoodLibgroup struct {
@@ -258,12 +280,9 @@
for _, lib := range r.ravenwoodLibgroupProperties.Libs {
ctx.AddVariationDependencies(nil, ravenwoodLibContentTag, lib)
}
- for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs {
+ for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs.GetOrDefault(ctx, nil) {
ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
}
- for _, data := range r.ravenwoodLibgroupProperties.Data {
- ctx.AddVariationDependencies(nil, ravenwoodDataTag, data)
- }
}
func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -285,6 +304,14 @@
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
for _, lib := range r.ravenwoodLibgroupProperties.Libs {
libModule := ctx.GetDirectDepWithTag(lib, ravenwoodLibContentTag)
+ if libModule == nil {
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{lib})
+ } else {
+ ctx.PropertyErrorf("lib", "missing dependency %q", lib)
+ }
+ continue
+ }
libJar := android.OutputFileForModule(ctx, libModule, "")
ctx.InstallFile(installPath, lib+".jar", libJar)
}
@@ -295,12 +322,17 @@
}
dataInstallPath := installPath.Join(ctx, "ravenwood-data")
- for _, data := range r.ravenwoodLibgroupProperties.Data {
- libModule := ctx.GetDirectDepWithTag(data, ravenwoodDataTag)
- file := android.OutputFileForModule(ctx, libModule, "")
+ data := android.PathsForModuleSrc(ctx, r.ravenwoodLibgroupProperties.Data)
+ for _, file := range data {
ctx.InstallFile(dataInstallPath, file.Base(), file)
}
+ fontsInstallPath := installPath.Join(ctx, "fonts")
+ fonts := android.PathsForModuleSrc(ctx, r.ravenwoodLibgroupProperties.Fonts)
+ for _, file := range fonts {
+ ctx.InstallFile(fontsInstallPath, file.Base(), file)
+ }
+
// Normal build should perform install steps
ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))
}
diff --git a/java/ravenwood_test.go b/java/ravenwood_test.go
index d26db93..753a118 100644
--- a/java/ravenwood_test.go
+++ b/java/ravenwood_test.go
@@ -19,6 +19,7 @@
"testing"
"android/soong/android"
+ "android/soong/etc"
)
var prepareRavenwoodRuntime = android.GroupFixturePreparers(
@@ -59,11 +60,19 @@
}
android_app {
name: "app1",
- sdk_version: "current",
+ sdk_version: "current",
}
android_app {
name: "app2",
- sdk_version: "current",
+ sdk_version: "current",
+ }
+ android_app {
+ name: "app3",
+ sdk_version: "current",
+ }
+ prebuilt_font {
+ name: "Font.ttf",
+ src: "Font.ttf",
}
android_ravenwood_libgroup {
name: "ravenwood-runtime",
@@ -76,7 +85,10 @@
"ravenwood-runtime-jni2",
],
data: [
- "app1",
+ ":app1",
+ ],
+ fonts: [
+ ":Font.ttf"
],
}
android_ravenwood_libgroup {
@@ -97,6 +109,7 @@
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
+ etc.PrepareForTestWithPrebuiltEtc,
prepareRavenwoodRuntime,
).RunTest(t)
@@ -114,6 +127,7 @@
runtime.Output(installPathPrefix + "/ravenwood-runtime/lib64/libred.so")
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.Output(installPathPrefix + "/ravenwood-utils/framework-rules.ravenwood.jar")
}
@@ -125,29 +139,30 @@
ctx := android.GroupFixturePreparers(
PrepareForIntegrationTestWithJava,
+ etc.PrepareForTestWithPrebuiltEtc,
prepareRavenwoodRuntime,
).RunTestWithBp(t, `
- cc_library_shared {
- name: "jni-lib1",
- host_supported: true,
- srcs: ["jni.cpp"],
- }
- cc_library_shared {
- name: "jni-lib2",
- host_supported: true,
- srcs: ["jni.cpp"],
- stem: "libblue",
- shared_libs: [
- "jni-lib3",
- ],
- }
- cc_library_shared {
- name: "jni-lib3",
- host_supported: true,
- srcs: ["jni.cpp"],
- stem: "libpink",
- }
- android_ravenwood_test {
+ cc_library_shared {
+ name: "jni-lib1",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ }
+ cc_library_shared {
+ name: "jni-lib2",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libblue",
+ shared_libs: [
+ "jni-lib3",
+ ],
+ }
+ cc_library_shared {
+ name: "jni-lib3",
+ host_supported: true,
+ srcs: ["jni.cpp"],
+ stem: "libpink",
+ }
+ android_ravenwood_test {
name: "ravenwood-test",
srcs: ["Test.java"],
jni_libs: [
@@ -156,6 +171,7 @@
"ravenwood-runtime-jni2",
],
resource_apk: "app2",
+ inst_resource_apk: "app3",
sdk_version: "test_current",
}
`)
@@ -183,6 +199,7 @@
module.Output(installPathPrefix + "/ravenwood-test/lib64/libblue.so")
module.Output(installPathPrefix + "/ravenwood-test/lib64/libpink.so")
module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-res.apk")
+ module.Output(installPathPrefix + "/ravenwood-test/ravenwood-res-apks/ravenwood-inst-res.apk")
// ravenwood-runtime*.so are included in the runtime, so it shouldn't be emitted.
for _, o := range module.AllOutputs() {
diff --git a/java/robolectric.go b/java/robolectric.go
index 4cad5b1..30c7203 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -16,9 +16,6 @@
import (
"fmt"
- "io"
- "strconv"
- "strings"
"android/soong/android"
"android/soong/java/config"
@@ -79,7 +76,7 @@
// Use strict mode to limit access of Robolectric API directly. See go/roboStrictMode
Strict_mode *bool
- Jni_libs []string
+ Jni_libs proptools.Configurable[[]string]
}
type robolectricTest struct {
@@ -88,16 +85,6 @@
robolectricProperties robolectricProperties
testProperties testProperties
- libs []string
- tests []string
-
- manifest android.Path
- resourceApk android.Path
-
- combinedJar android.WritablePath
-
- roboSrcJar android.Path
-
testConfig android.Path
data android.Paths
@@ -121,12 +108,12 @@
}
if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
- ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, 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, libTag, robolectricCurrentLib+"_upstream")
+ ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib+"_upstream")
} else {
- ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ ctx.AddVariationDependencies(nil, staticLibTag, robolectricCurrentLib)
}
}
@@ -134,17 +121,17 @@
ctx.AddVariationDependencies(nil, roboRuntimeOnlyTag, robolectricCurrentLib+"_upstream")
} else {
// opting out from strict mode, robolectric_non_strict_mode_permission lib should be added
- ctx.AddVariationDependencies(nil, libTag, "robolectric_non_strict_mode_permission")
+ ctx.AddVariationDependencies(nil, staticLibTag, "robolectric_non_strict_mode_permission")
}
- ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, robolectricDefaultLibs...)
ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
roboRuntimesTag, "robolectric-android-all-prebuilts")
- for _, lib := range r.robolectricProperties.Jni_libs {
+ for _, lib := range r.robolectricProperties.Jni_libs.GetOrDefault(ctx, nil) {
ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
}
}
@@ -163,9 +150,6 @@
})
r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data)
- roboTestConfig := android.PathForModuleGen(ctx, "robolectric").
- Join(ctx, "com/android/tools/test_config.properties")
-
var ok bool
var instrumentedApp *AndroidApp
@@ -181,89 +165,58 @@
panic(fmt.Errorf("expected exactly 1 instrumented dependency, got %d", len(instrumented)))
}
+ var resourceApk android.Path
+ var manifest android.Path
if instrumentedApp != nil {
- r.manifest = instrumentedApp.mergedManifestFile
- r.resourceApk = instrumentedApp.outputFile
-
- generateRoboTestConfig(ctx, roboTestConfig, instrumentedApp)
- r.extraResources = android.Paths{roboTestConfig}
- }
-
- r.Library.GenerateAndroidBuildActions(ctx)
-
- roboSrcJar := android.PathForModuleGen(ctx, "robolectric", ctx.ModuleName()+".srcjar")
-
- if instrumentedApp != nil {
- r.generateRoboSrcJar(ctx, roboSrcJar, instrumentedApp)
- r.roboSrcJar = roboSrcJar
+ manifest = instrumentedApp.mergedManifestFile
+ resourceApk = instrumentedApp.outputFile
}
roboTestConfigJar := android.PathForModuleOut(ctx, "robolectric_samedir", "samedir_config.jar")
generateSameDirRoboTestConfigJar(ctx, roboTestConfigJar)
- combinedJarJars := android.Paths{
- // roboTestConfigJar comes first so that its com/android/tools/test_config.properties
- // overrides the one from r.extraResources. The r.extraResources one can be removed
- // once the Make test runner is removed.
- roboTestConfigJar,
- r.outputFile,
- }
+ extraCombinedJars := android.Paths{roboTestConfigJar}
- if instrumentedApp != nil {
- combinedJarJars = append(combinedJarJars, instrumentedApp.implementationAndResourcesJar)
- }
-
- handleLibDeps := func(dep android.Module, runtimeOnly bool) {
- m, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
- if !runtimeOnly {
- r.libs = append(r.libs, ctx.OtherModuleName(dep))
- }
+ handleLibDeps := func(dep android.Module) {
if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
- combinedJarJars = append(combinedJarJars, m.ImplementationAndResourcesJars...)
+ if m, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ extraCombinedJars = append(extraCombinedJars, m.ImplementationAndResourcesJars...)
+ }
}
}
for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
- handleLibDeps(dep, false)
+ handleLibDeps(dep)
}
for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
- handleLibDeps(dep, false)
+ handleLibDeps(dep)
}
// handle the runtimeOnly tag for strict_mode
for _, dep := range ctx.GetDirectDepsWithTag(roboRuntimeOnlyTag) {
- handleLibDeps(dep, true)
+ handleLibDeps(dep)
}
- r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
- TransformJarsToJar(ctx, r.combinedJar, "combine jars", combinedJarJars, android.OptionalPath{},
- false, nil, nil)
-
- // TODO: this could all be removed if tradefed was used as the test runner, it will find everything
- // annotated as a test and run it.
- for _, src := range r.uniqueSrcFiles {
- s := src.Rel()
- if !strings.HasSuffix(s, "Test.java") && !strings.HasSuffix(s, "Test.kt") {
- continue
- } else if strings.HasSuffix(s, "/BaseRobolectricTest.java") {
- continue
- } else {
- s = strings.TrimPrefix(s, "src/")
- }
- r.tests = append(r.tests, s)
+ if instrumentedApp != nil {
+ extraCombinedJars = append(extraCombinedJars, instrumentedApp.implementationAndResourcesJar)
}
+ 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)
+
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
var installDeps android.InstallPaths
- if r.manifest != nil {
- r.data = append(r.data, r.manifest)
- installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", r.manifest)
+ if manifest != nil {
+ r.data = append(r.data, manifest)
+ installedManifest := ctx.InstallFile(installPath, ctx.ModuleName()+"-AndroidManifest.xml", manifest)
installDeps = append(installDeps, installedManifest)
}
- if r.resourceApk != nil {
- r.data = append(r.data, r.resourceApk)
- installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", r.resourceApk)
+ if resourceApk != nil {
+ r.data = append(r.data, resourceApk)
+ installedResourceApk := ctx.InstallFile(installPath, ctx.ModuleName()+".apk", resourceApk)
installDeps = append(installDeps, installedResourceApk)
}
@@ -286,29 +239,10 @@
installDeps = append(installDeps, installJni)
}
- r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
+ r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)
android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
-func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath,
- instrumentedApp *AndroidApp) {
- rule := android.NewRuleBuilder(pctx, ctx)
-
- manifest := instrumentedApp.mergedManifestFile
- resourceApk := instrumentedApp.outputFile
-
- rule.Command().Text("rm -f").Output(outputFile)
- rule.Command().
- Textf(`echo "android_merged_manifest=%s" >>`, manifest.String()).Output(outputFile).Text("&&").
- Textf(`echo "android_resource_apk=%s" >>`, resourceApk.String()).Output(outputFile).
- // Make it depend on the files to which it points so the test file's timestamp is updated whenever the
- // contents change
- Implicit(manifest).
- Implicit(resourceApk)
-
- rule.Build("generate_test_config", "generate test_config.properties")
-}
-
func generateSameDirRoboTestConfigJar(ctx android.ModuleContext, outputFile android.ModuleOutPath) {
rule := android.NewRuleBuilder(pctx, ctx)
@@ -331,22 +265,6 @@
rule.Build("generate_test_config_samedir", "generate test_config.properties")
}
-func (r *robolectricTest) generateRoboSrcJar(ctx android.ModuleContext, outputFile android.WritablePath,
- instrumentedApp *AndroidApp) {
-
- srcJarArgs := android.CopyOf(instrumentedApp.srcJarArgs)
- srcJarDeps := append(android.Paths(nil), instrumentedApp.srcJarDeps...)
-
- for _, m := range ctx.GetDirectDepsWithTag(roboCoverageLibsTag) {
- if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
- srcJarArgs = append(srcJarArgs, dep.SrcJarArgs...)
- srcJarDeps = append(srcJarDeps, dep.SrcJarDeps...)
- }
- }
-
- TransformResourcesToJar(ctx, outputFile, srcJarArgs, srcJarDeps)
-}
-
func (r *robolectricTest) AndroidMkEntries() []android.AndroidMkEntries {
entriesList := r.Library.AndroidMkEntries()
entries := &entriesList[0]
@@ -358,61 +276,11 @@
entries.SetPath("LOCAL_FULL_TEST_CONFIG", r.testConfig)
}
})
-
- entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- if s := r.robolectricProperties.Test_options.Shards; s != nil && *s > 1 {
- numShards := int(*s)
- shardSize := (len(r.tests) + numShards - 1) / numShards
- shards := android.ShardStrings(r.tests, shardSize)
- for i, shard := range shards {
- r.writeTestRunner(w, name, "Run"+name+strconv.Itoa(i), shard)
- }
-
- // TODO: add rules to dist the outputs of the individual tests, or combine them together?
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, ".PHONY:", "Run"+name)
- fmt.Fprintln(w, "Run"+name, ": \\")
- for i := range shards {
- fmt.Fprintln(w, " ", "Run"+name+strconv.Itoa(i), "\\")
- }
- fmt.Fprintln(w, "")
- } else {
- r.writeTestRunner(w, name, "Run"+name, r.tests)
- }
- },
- }
-
return entriesList
}
-func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, tests []string) {
- fmt.Fprintln(w, "")
- fmt.Fprintln(w, "include $(CLEAR_VARS)", " # java.robolectricTest")
- fmt.Fprintln(w, "LOCAL_MODULE :=", name)
- android.AndroidMkEmitAssignList(w, "LOCAL_JAVA_LIBRARIES", []string{module}, r.libs)
- fmt.Fprintln(w, "LOCAL_TEST_PACKAGE :=", String(r.robolectricProperties.Instrumentation_for))
- if r.roboSrcJar != nil {
- fmt.Fprintln(w, "LOCAL_INSTRUMENT_SRCJARS :=", r.roboSrcJar.String())
- }
- android.AndroidMkEmitAssignList(w, "LOCAL_ROBOTEST_FILES", tests)
- if t := r.robolectricProperties.Test_options.Timeout; t != nil {
- fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
- }
- if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
- fmt.Fprintf(w, "-include prebuilts/misc/common/robolectric/%s/run_robotests.mk\n", v)
- } else {
- fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
- }
-}
-
// An android_robolectric_test module compiles tests against the Robolectric framework that can run on the local host
-// instead of on a device. It also generates a rule with the name of the module prefixed with "Run" that can be
-// used to run the tests. Running the tests with build rule will eventually be deprecated and replaced with atest.
-//
-// The test runner considers any file listed in srcs whose name ends with Test.java to be a test class, unless
-// it is named BaseRobolectricTest.java. The path to the each source file must exactly match the package
-// name, or match the package name when the prefix "src/" is removed.
+// instead of on a device.
func RobolectricTestFactory() android.Module {
module := &robolectricTest{}
diff --git a/java/rro.go b/java/rro.go
index 0fc6e1c..8bb9be2 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -17,7 +17,11 @@
// This file contains the module implementations for runtime_resource_overlay and
// override_runtime_resource_overlay.
-import "android/soong/android"
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint/proptools"
+)
func init() {
RegisterRuntimeResourceOverlayBuildComponents(android.InitRegistrationContext)
@@ -71,7 +75,7 @@
Min_sdk_version *string
// list of android_library modules whose resources are extracted and linked against statically
- Static_libs []string
+ Static_libs proptools.Configurable[[]string]
// list of android_app modules whose resources are extracted and linked against
Resource_libs []string
@@ -120,7 +124,7 @@
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
- ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, r.properties.Static_libs.GetOrDefault(ctx, nil)...)
ctx.AddVariationDependencies(nil, libTag, r.properties.Resource_libs...)
for _, aconfig_declaration := range r.aaptProperties.Flags_packages {
diff --git a/java/rro_test.go b/java/rro_test.go
index 742c839..4d79130 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -282,7 +282,7 @@
enforceRROTargets: []string{"foo"},
rroDirs: map[string][]string{
"foo": {"product/vendor/blah/overlay/lib2/res"},
- "bar": {"product/vendor/blah/overlay/lib2/res"},
+ "bar": nil,
},
},
}
diff --git a/java/sdk.go b/java/sdk.go
index 4ef4ee2..4537f19 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -278,7 +278,7 @@
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
- if j, ok := android.SingletonModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if j, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
name := ctx.ModuleName(module)
if i := android.IndexList(name, stubsModules); i != -1 {
stubsJars[i] = j.HeaderJars
@@ -308,10 +308,12 @@
rule.Command().
Text("rm -f").Output(aidl)
+
rule.Command().
BuiltTool("sdkparcelables").
Input(jar).
- Output(aidl)
+ Output(aidl).
+ Flag("--guarantee_stable")
aidls = append(aidls, aidl)
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 3931456..f308772 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -20,7 +20,6 @@
"path"
"path/filepath"
"reflect"
- "regexp"
"sort"
"strings"
"sync"
@@ -30,11 +29,6 @@
"android/soong/android"
"android/soong/dexpreopt"
- "android/soong/etc"
-)
-
-const (
- sdkXmlFileSuffix = ".xml"
)
// A tag to associated a dependency with a specific api scope.
@@ -249,7 +243,7 @@
return scope.stubsLibraryModuleName(baseName) + ".from-text"
}
-func (scope *apiScope) sourceStubLibraryModuleName(baseName string) string {
+func (scope *apiScope) sourceStubsLibraryModuleName(baseName string) string {
return scope.stubsLibraryModuleName(baseName) + ".from-source"
}
@@ -269,10 +263,6 @@
return baseName + ".stubs.source" + scope.moduleSuffix
}
-func (scope *apiScope) apiModuleName(baseName string) string {
- return baseName + ".api" + scope.moduleSuffix
-}
-
func (scope *apiScope) String() string {
return scope.name
}
@@ -427,22 +417,10 @@
apiScopeModuleLib,
apiScopeSystemServer,
}
- apiLibraryAdditionalProperties = map[string]struct {
- FullApiSurfaceStubLib string
- AdditionalApiContribution string
- }{
- "legacy.i18n.module.platform.api": {
- FullApiSurfaceStubLib: "legacy.core.platform.api.stubs",
- AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
- },
- "stable.i18n.module.platform.api": {
- FullApiSurfaceStubLib: "stable.core.platform.api.stubs",
- AdditionalApiContribution: "i18n.module.public.api.stubs.source.api.contribution",
- },
- "conscrypt.module.platform.api": {
- FullApiSurfaceStubLib: "stable.core.platform.api.stubs",
- AdditionalApiContribution: "conscrypt.module.public.api.stubs.source.api.contribution",
- },
+ apiLibraryAdditionalProperties = map[string]string{
+ "legacy.i18n.module.platform.api": "i18n.module.public.api.stubs.source.api.contribution",
+ "stable.i18n.module.platform.api": "i18n.module.public.api.stubs.source.api.contribution",
+ "conscrypt.module.platform.api": "conscrypt.module.public.api.stubs.source.api.contribution",
}
)
@@ -650,17 +628,14 @@
Legacy_errors_allowed *bool
}
- // Determines if the module contributes to any api surfaces.
- // This property should be set to true only if the module is listed under
- // frameworks-base-api.bootclasspath in frameworks/base/api/Android.bp.
- // Otherwise, this property should be set to false.
- // Defaults to false.
- Contribute_to_android_api *bool
-
// a list of aconfig_declarations module names that the stubs generated in this module
// depend on.
Aconfig_declarations []string
+ // Determines if the module generates the stubs from the api signature files
+ // instead of the source Java files. Defaults to true.
+ Build_from_text_stub *bool
+
// TODO: determines whether to create HTML doc or not
// Html_doc *bool
}
@@ -846,16 +821,6 @@
}
type commonToSdkLibraryAndImportProperties struct {
- // The naming scheme to use for the components that this module creates.
- //
- // If not specified then it defaults to "default".
- //
- // This is a temporary mechanism to simplify conversion from separate modules for each
- // component that follow a different naming pattern to the default one.
- //
- // TODO(b/155480189) - Remove once naming inconsistencies have been resolved.
- Naming_scheme *string
-
// Specifies whether this module can be used as an Android shared library; defaults
// to true.
//
@@ -931,8 +896,6 @@
scopePaths map[*apiScope]*scopePaths
- namingScheme sdkLibraryComponentNamingScheme
-
commonSdkLibraryProperties commonToSdkLibraryAndImportProperties
// Paths to commonSdkLibraryProperties.Doctag_files
@@ -959,16 +922,7 @@
c.initSdkLibraryComponent(module)
}
-func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool {
- schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default")
- switch schemeProperty {
- case "default":
- c.namingScheme = &defaultNamingScheme{}
- default:
- ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty)
- return false
- }
-
+func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied() bool {
namePtr := proptools.StringPtr(c.module.RootLibraryName())
c.sdkLibraryComponentProperties.SdkLibraryName = namePtr
@@ -990,62 +944,32 @@
return c.sharedLibrary()
}
-func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
+func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) SdkLibraryInfo {
c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
-}
-func (c *commonToSdkLibraryAndImport) getImplLibraryModule() *Library {
- return c.implLibraryModule
-}
+ everythingStubPaths := make(map[android.SdkKind]OptionalDexJarPath)
+ exportableStubPaths := make(map[android.SdkKind]OptionalDexJarPath)
+ removedApiFilePaths := make(map[android.SdkKind]android.OptionalPath)
+ for kind := android.SdkNone; kind <= android.SdkPrivate; kind += 1 {
+ everythingStubPath := makeUnsetDexJarPath()
+ exportableStubPath := makeUnsetDexJarPath()
+ removedApiFilePath := android.OptionalPath{}
+ if scopePath := c.findClosestScopePath(sdkKindToApiScope(kind)); scopePath != nil {
+ everythingStubPath = scopePath.stubsDexJarPath
+ exportableStubPath = scopePath.exportableStubsDexJarPath
+ removedApiFilePath = scopePath.removedApiFilePath
+ }
+ everythingStubPaths[kind] = everythingStubPath
+ exportableStubPaths[kind] = exportableStubPath
+ removedApiFilePaths[kind] = removedApiFilePath
+ }
-// Module name of the runtime implementation library
-func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
- return c.module.RootLibraryName() + ".impl"
-}
-
-// Module name of the XML file for the lib
-func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
- return c.module.RootLibraryName() + sdkXmlFileSuffix
-}
-
-// Name of the java_library module that compiles the stubs source.
-func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return c.namingScheme.stubsLibraryModuleName(apiScope, baseName)
-}
-
-// Name of the java_library module that compiles the exportable stubs source.
-func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName)
-}
-
-// Name of the droidstubs module that generates the stubs source and may also
-// generate/check the API.
-func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return c.namingScheme.stubsSourceModuleName(apiScope, baseName)
-}
-
-// Name of the java_api_library module that generates the from-text stubs source
-// and compiles to a jar file.
-func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return c.namingScheme.apiLibraryModuleName(apiScope, baseName)
-}
-
-// Name of the java_library module that compiles the stubs
-// generated from source Java files.
-func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName)
-}
-
-// Name of the java_library module that compiles the exportable stubs
-// generated from source Java files.
-func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string {
- baseName := c.module.RootLibraryName()
- return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName)
+ return SdkLibraryInfo{
+ EverythingStubDexJarPaths: everythingStubPaths,
+ ExportableStubDexJarPaths: exportableStubPaths,
+ RemovedTxtFiles: removedApiFilePaths,
+ SharedLibrary: c.sharedLibrary(),
+ }
}
// The component names for different outputs of the java_sdk_library.
@@ -1061,28 +985,6 @@
annotationsComponentName = "annotations.zip"
)
-// A regular expression to match tags that reference a specific stubs component.
-//
-// It will only match if given a valid scope and a valid component. It is verfy strict
-// to ensure it does not accidentally match a similar looking tag that should be processed
-// by the embedded Library.
-var tagSplitter = func() *regexp.Regexp {
- // Given a list of literal string items returns a regular expression that will
- // match any one of the items.
- choice := func(items ...string) string {
- return `\Q` + strings.Join(items, `\E|\Q`) + `\E`
- }
-
- // Regular expression to match one of the scopes.
- scopesRegexp := choice(allScopeNames...)
-
- // Regular expression to match one of the components.
- componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName, annotationsComponentName)
-
- // Regular expression to match any combination of one scope and one component.
- return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp))
-}()
-
func (module *commonToSdkLibraryAndImport) setOutputFiles(ctx android.ModuleContext) {
if module.doctagPaths != nil {
ctx.SetOutputFiles(module.doctagPaths, ".doctags")
@@ -1141,44 +1043,6 @@
return nil
}
-func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
-
- // If a specific numeric version has been requested then use prebuilt versions of the sdk.
- if !sdkVersion.ApiLevel.IsPreview() {
- return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion)
- }
-
- paths := c.selectScopePaths(ctx, sdkVersion.Kind)
- if paths == nil {
- return nil
- }
-
- return paths.stubsHeaderPath
-}
-
-// selectScopePaths returns the *scopePaths appropriate for the specific kind.
-//
-// If the module does not support the specific kind then it will return the *scopePaths for the
-// closest kind which is a subset of the requested kind. e.g. if requesting android.SdkModule then
-// it will return *scopePaths for android.SdkSystem if available or android.SdkPublic of not.
-func (c *commonToSdkLibraryAndImport) selectScopePaths(ctx android.BaseModuleContext, kind android.SdkKind) *scopePaths {
- apiScope := sdkKindToApiScope(kind)
-
- paths := c.findClosestScopePath(apiScope)
- if paths == nil {
- var scopes []string
- for _, s := range AllApiScopes {
- if c.findScopePaths(s) != nil {
- scopes = append(scopes, s.name)
- }
- }
- ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.module.RootLibraryName(), scopes)
- return nil
- }
-
- return paths
-}
-
// sdkKindToApiScope maps from android.SdkKind to apiScope.
func sdkKindToApiScope(kind android.SdkKind) *apiScope {
var apiScope *apiScope
@@ -1197,37 +1061,6 @@
return apiScope
}
-// to satisfy SdkLibraryDependency interface
-func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
- paths := c.selectScopePaths(ctx, kind)
- if paths == nil {
- return makeUnsetDexJarPath()
- }
-
- return paths.stubsDexJarPath
-}
-
-// to satisfy SdkLibraryDependency interface
-func (c *commonToSdkLibraryAndImport) SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
- paths := c.selectScopePaths(ctx, kind)
- if paths == nil {
- return makeUnsetDexJarPath()
- }
-
- return paths.exportableStubsDexJarPath
-}
-
-// to satisfy SdkLibraryDependency interface
-func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath {
- apiScope := sdkKindToApiScope(kind)
- paths := c.findScopePaths(apiScope)
- if paths == nil {
- return android.OptionalPath{}
- }
-
- return paths.removedApiFilePath
-}
-
func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
componentProps := &struct {
SdkLibraryName *string
@@ -1318,33 +1151,43 @@
var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
-// Provides access to sdk_version related files, e.g. header and implementation jars.
-type SdkLibraryDependency interface {
- SdkLibraryComponentDependency
+type SdkLibraryInfo struct {
+ // GeneratingLibs is the names of the library modules that this sdk library
+ // generates. Note that this only includes the name of the modules that other modules can
+ // depend on, and is not a holistic list of generated modules.
+ GeneratingLibs []string
- // Get the header jars appropriate for the supplied sdk_version.
- //
- // These are turbine generated jars so they only change if the externals of the
- // class changes but it does not contain and implementation or JavaDoc.
- SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
+ // Map of sdk kind to the dex jar for the "everything" stubs.
+ // It is needed by the hiddenapi processing tool which processes dex files.
+ EverythingStubDexJarPaths map[android.SdkKind]OptionalDexJarPath
- // SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt
- // java_sdk_library_import module. It is needed by the hiddenapi processing tool which
- // processes dex files.
- SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
+ // Map of sdk kind to the dex jar for the "exportable" stubs.
+ // It is needed by the hiddenapi processing tool which processes dex files.
+ ExportableStubDexJarPaths map[android.SdkKind]OptionalDexJarPath
- // SdkApiExportableStubDexJar returns the exportable dex jar for the stubs for
- // java_sdk_library module. It is needed by the hiddenapi processing tool which processes
- // dex files.
- SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
+ // Map of sdk kind to the optional path to the removed.txt file.
+ RemovedTxtFiles map[android.SdkKind]android.OptionalPath
- // SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind.
- SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath
+ // Whether if this can be used as a shared library.
+ SharedLibrary bool
+}
- // sharedLibrary returns true if this can be used as a shared library.
- sharedLibrary() bool
+var SdkLibraryInfoProvider = blueprint.NewProvider[SdkLibraryInfo]()
- getImplLibraryModule() *Library
+func getGeneratingLibs(ctx android.ModuleContext, sdkVersion android.SdkSpec, sdkLibraryModuleName string, sdkInfo SdkLibraryInfo) []string {
+ apiLevel := sdkVersion.ApiLevel
+ if apiLevel.IsPreview() {
+ return sdkInfo.GeneratingLibs
+ }
+
+ generatingPrebuilts := []string{}
+ for _, apiScope := range AllApiScopes {
+ scopePrebuiltModuleName := prebuiltApiModuleName("sdk", sdkLibraryModuleName, apiScope.name, apiLevel.String())
+ if ctx.OtherModuleExists(scopePrebuiltModuleName) {
+ generatingPrebuilts = append(generatingPrebuilts, scopePrebuiltModuleName)
+ }
+ }
+ return generatingPrebuilts
}
type SdkLibrary struct {
@@ -1360,12 +1203,13 @@
builtInstalledForApex []dexpreopterInstall
}
-var _ SdkLibraryDependency = (*SdkLibrary)(nil)
-
func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool {
return module.sdkLibraryProperties.Generate_system_and_test_apis
}
+var _ UsesLibraryDependency = (*SdkLibrary)(nil)
+
+// To satisfy the UsesLibraryDependency interface
func (module *SdkLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
if module.implLibraryModule != nil {
return module.implLibraryModule.DexJarBuildPath(ctx)
@@ -1373,6 +1217,7 @@
return makeUnsetDexJarPath()
}
+// To satisfy the UsesLibraryDependency interface
func (module *SdkLibrary) DexJarInstallPath() android.Path {
if module.implLibraryModule != nil {
return module.implLibraryModule.DexJarInstallPath()
@@ -1435,7 +1280,7 @@
}
func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) {
- android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.ModuleContext, do android.PayloadDepsCallback) {
+ 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 {
@@ -1490,7 +1335,7 @@
ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName)
// Add a dependency on the stubs source in order to access both stubs source and api information.
- ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
+ ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.droidstubsModuleName(apiScope))
if module.compareAgainstLatestApi(apiScope) {
// Add dependencies on the latest finalized version of the API .txt file.
@@ -1560,8 +1405,6 @@
module.HideFromMake()
}
- module.generateCommonBuildActions(ctx)
-
module.stem = proptools.StringDefault(module.overridableProperties.Stem, ctx.ModuleName())
module.provideHiddenAPIPropertyInfo(ctx)
@@ -1586,17 +1429,19 @@
scopeTag.extractDepInfo(ctx, to, scopePaths)
exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
+
+ ctx.Phony(ctx.ModuleName(), scopePaths.stubsHeaderPath...)
}
if tag == implLibraryTag {
if dep, ok := android.OtherModuleProvider(ctx, to, JavaInfoProvider); ok {
module.implLibraryHeaderJars = append(module.implLibraryHeaderJars, dep.HeaderJars...)
module.implLibraryModule = to.(*Library)
- android.SetProvider(ctx, JavaInfoProvider, dep)
}
}
})
+ sdkLibInfo := module.generateCommonBuildActions(ctx)
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
module.hideApexVariantFromMake = true
@@ -1625,12 +1470,20 @@
module.dexer.proguardDictionary = module.implLibraryModule.dexer.proguardDictionary
module.dexer.proguardUsageZip = module.implLibraryModule.dexer.proguardUsageZip
module.linter.reports = module.implLibraryModule.linter.reports
- module.linter.outputs.depSets = module.implLibraryModule.LintDepSets()
+
+ if lintInfo, ok := android.OtherModuleProvider(ctx, module.implLibraryModule, LintProvider); ok {
+ android.SetProvider(ctx, LintProvider, lintInfo)
+ }
if !module.Host() {
module.hostdexInstallFile = module.implLibraryModule.hostdexInstallFile
}
+ if installFilesInfo, ok := android.OtherModuleProvider(ctx, module.implLibraryModule, android.InstallFilesProvider); ok {
+ if installFilesInfo.CheckbuildTarget != nil {
+ ctx.CheckbuildFile(installFilesInfo.CheckbuildTarget)
+ }
+ }
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: module.implLibraryModule.uniqueSrcFiles.Strings()})
}
@@ -1662,9 +1515,21 @@
}
android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
module.setOutputFiles(ctx)
+
+ var generatingLibs []string
+ for _, apiScope := range AllApiScopes {
+ if _, ok := module.scopePaths[apiScope]; ok {
+ generatingLibs = append(generatingLibs, module.stubsLibraryModuleName(apiScope))
+ }
+ }
+
if module.requiresRuntimeImplementationLibrary() && module.implLibraryModule != nil {
+ generatingLibs = append(generatingLibs, module.implLibraryModuleName())
setOutputFiles(ctx, module.implLibraryModule.Module)
}
+
+ sdkLibInfo.GeneratingLibs = generatingLibs
+ android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo)
}
func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall {
@@ -1747,30 +1612,13 @@
return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope)
}
-func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool {
- _, exists := c.GetApiLibraries()[module.Name()]
- return exists
-}
-
-// The listed modules are the special java_sdk_libraries where apiScope.kind do not match the
-// api surface that the module contribute to. For example, the public droidstubs and java_library
-// do not contribute to the public api surface, but contributes to the core platform api surface.
-// This method returns the full api surface stub lib that
-// the generated java_api_library should depend on.
-func (module *SdkLibrary) alternativeFullApiSurfaceStubLib() string {
- if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
- return val.FullApiSurfaceStubLib
- }
- return ""
-}
-
// The listed modules' stubs contents do not match the corresponding txt files,
// but require additional api contributions to generate the full stubs.
// This method returns the name of the additional api contribution module
// for corresponding sdk_library modules.
func (module *SdkLibrary) apiLibraryAdditionalApiContribution() string {
if val, ok := apiLibraryAdditionalProperties[module.Name()]; ok {
- return val.AdditionalApiContribution
+ return val
}
return ""
}
@@ -1788,406 +1636,6 @@
return visibility
}
-// Creates the implementation java library
-func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
- visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
-
- props := struct {
- Name *string
- Visibility []string
- Libs []string
- Static_libs []string
- Apex_available []string
- Stem *string
- }{
- Name: proptools.StringPtr(module.implLibraryModuleName()),
- Visibility: visibility,
-
- Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
-
- Static_libs: append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...),
- // Pass the apex_available settings down so that the impl library can be statically
- // embedded within a library that is added to an APEX. Needed for updatable-media.
- Apex_available: module.ApexAvailable(),
-
- Stem: proptools.StringPtr(module.Name()),
- }
-
- properties := []interface{}{
- &module.properties,
- &module.protoProperties,
- &module.deviceProperties,
- &module.dexProperties,
- &module.dexpreoptProperties,
- &module.linter.properties,
- &module.overridableProperties,
- &props,
- module.sdkComponentPropertiesForChildLibrary(),
- }
- mctx.CreateModule(LibraryFactory, properties...)
-}
-
-type libraryProperties struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- System_modules *string
- Patch_module *string
- Libs []string
- Static_libs []string
- Compile_dex *bool
- Java_version *string
- Openjdk9 struct {
- Srcs []string
- Javacflags []string
- }
- Dist struct {
- Targets []string
- Dest *string
- Dir *string
- Tag *string
- }
- Is_stubs_module *bool
-}
-
-func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
- props := libraryProperties{}
- props.Visibility = []string{"//visibility:override", "//visibility:private"}
- // sources are generated from the droiddoc
- sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
- props.Sdk_version = proptools.StringPtr(sdkVersion)
- props.System_modules = module.deviceProperties.System_modules
- props.Patch_module = module.properties.Patch_module
- props.Installable = proptools.BoolPtr(false)
- props.Libs = module.sdkLibraryProperties.Stub_only_libs
- props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
- props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
- // The stub-annotations library contains special versions of the annotations
- // with CLASS retention policy, so that they're kept.
- if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
- props.Libs = append(props.Libs, "stub-annotations")
- }
- props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
- props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
- // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
- // interop with older developer tools that don't support 1.9.
- props.Java_version = proptools.StringPtr("1.8")
- props.Is_stubs_module = proptools.BoolPtr(true)
-
- return props
-}
-
-// Creates a static java library that has API stubs
-func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
-
- props := module.stubsLibraryProps(mctx, apiScope)
- props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope))
- props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-// Create a static java library that compiles the "exportable" stubs
-func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
- props := module.stubsLibraryProps(mctx, apiScope)
- props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope))
- props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"}
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-// Creates a droidstubs module that creates stubs source files from the given full source
-// files and also updates and checks the API specification files.
-func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
- props := struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- Api_surface *string
- System_modules *string
- Libs []string
- Output_javadoc_comments *bool
- Arg_files []string
- Args *string
- Java_version *string
- Annotations_enabled *bool
- Merge_annotations_dirs []string
- Merge_inclusion_annotations_dirs []string
- Generate_stubs *bool
- Previous_api *string
- Aconfig_declarations []string
- Check_api struct {
- Current ApiToCheck
- Last_released ApiToCheck
-
- Api_lint struct {
- Enabled *bool
- New_since *string
- Baseline_file *string
- }
- }
- Aidl struct {
- Include_dirs []string
- Local_include_dirs []string
- }
- Dists []android.Dist
- }{}
-
- // The stubs source processing uses the same compile time classpath when extracting the
- // API from the implementation library as it does when compiling it. i.e. the same
- // * sdk version
- // * system_modules
- // * libs (static_libs/libs)
-
- props.Name = proptools.StringPtr(name)
- props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
- 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.System_modules = module.deviceProperties.System_modules
- props.Installable = proptools.BoolPtr(false)
- // A droiddoc module has only one Libs property and doesn't distinguish between
- // shared libs and static libs. So we need to add both of these libs to Libs property.
- props.Libs = module.properties.Libs
- props.Libs = append(props.Libs, module.properties.Static_libs...)
- props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
- props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
- props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
- props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
- props.Java_version = module.properties.Java_version
-
- props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
- props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
- props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
- props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
-
- droidstubsArgs := []string{}
- if len(module.sdkLibraryProperties.Api_packages) != 0 {
- droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
- }
- droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
- disabledWarnings := []string{"HiddenSuperclass"}
- if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
- disabledWarnings = append(disabledWarnings,
- "BroadcastBehavior",
- "DeprecationMismatch",
- "MissingPermission",
- "SdkConstant",
- "Todo",
- )
- }
- droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
-
- // Output Javadoc comments for public scope.
- if apiScope == apiScopePublic {
- props.Output_javadoc_comments = proptools.BoolPtr(true)
- }
-
- // Add in scope specific arguments.
- droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
- props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
- props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
-
- // List of APIs identified from the provided source files are created. They are later
- // compared against to the not-yet-released (a.k.a current) list of APIs and to the
- // last-released (a.k.a numbered) list of API.
- currentApiFileName := apiScope.apiFilePrefix + "current.txt"
- removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
- apiDir := module.getApiDir()
- currentApiFileName = path.Join(apiDir, currentApiFileName)
- removedApiFileName = path.Join(apiDir, removedApiFileName)
-
- // check against the not-yet-release API
- props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
- props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
-
- if module.compareAgainstLatestApi(apiScope) {
- // check against the latest released API
- latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
- props.Previous_api = latestApiFilegroupName
- props.Check_api.Last_released.Api_file = latestApiFilegroupName
- props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
- module.latestRemovedApiFilegroupName(apiScope))
- props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
- module.latestIncompatibilitiesFilegroupName(apiScope))
-
- if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
- // Enable api lint.
- props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
- props.Check_api.Api_lint.New_since = latestApiFilegroupName
-
- // If it exists then pass a lint-baseline.txt through to droidstubs.
- baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
- baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
- paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
- if err != nil {
- mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
- }
- if len(paths) == 1 {
- props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
- } else if len(paths) != 0 {
- mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
- }
- }
- }
-
- if !Bool(module.sdkLibraryProperties.No_dist) {
- // Dist the api txt and removed api txt artifacts for sdk builds.
- distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
- stubsTypeTagPrefix := ""
- if mctx.Config().ReleaseHiddenApiExportableStubs() {
- stubsTypeTagPrefix = ".exportable"
- }
- for _, p := range []struct {
- tag string
- pattern string
- }{
- // "exportable" api files are copied to the dist directory instead of the
- // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
- // is set. Otherwise, the "everything" api files are copied to the dist directory.
- {tag: "%s.api.txt", pattern: "%s.txt"},
- {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
- } {
- props.Dists = append(props.Dists, android.Dist{
- Targets: []string{"sdk", "win_sdk"},
- Dir: distDir,
- Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
- Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
- })
- }
- }
-
- mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
-}
-
-func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) {
- props := struct {
- Name *string
- Visibility []string
- Api_contributions []string
- Libs []string
- Static_libs []string
- Full_api_surface_stub *string
- System_modules *string
- Enable_validation *bool
- Stubs_type *string
- }{}
-
- props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
- props.Visibility = []string{"//visibility:override", "//visibility:private"}
-
- apiContributions := []string{}
-
- // Api surfaces are not independent of each other, but have subset relationships,
- // and so does the api files. To generate from-text stubs for api surfaces other than public,
- // all subset api domains' api_contriubtions must be added as well.
- scope := apiScope
- for scope != nil {
- apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution")
- scope = scope.extends
- }
- if apiScope == apiScopePublic {
- additionalApiContribution := module.apiLibraryAdditionalApiContribution()
- if additionalApiContribution != "" {
- apiContributions = append(apiContributions, additionalApiContribution)
- }
- }
-
- props.Api_contributions = apiContributions
- props.Libs = module.properties.Libs
- props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
- props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
- props.Libs = append(props.Libs, "stub-annotations")
- props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
- props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName())
- if alternativeFullApiSurfaceStub != "" {
- props.Full_api_surface_stub = proptools.StringPtr(alternativeFullApiSurfaceStub)
- }
-
- // android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n.
- // Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
- if apiScope.kind == android.SdkModule {
- props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
- }
-
- // java_sdk_library modules that set sdk_version as none does not depend on other api
- // domains. Therefore, java_api_library created from such modules should not depend on
- // full_api_surface_stubs but create and compile stubs by the java_api_library module
- // itself.
- if module.SdkVersion(mctx).Kind == android.SdkNone {
- props.Full_api_surface_stub = nil
- }
-
- props.System_modules = module.deviceProperties.System_modules
- props.Enable_validation = proptools.BoolPtr(true)
- props.Stubs_type = proptools.StringPtr("everything")
-
- mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
- props := libraryProperties{}
-
- props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
- sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
- props.Sdk_version = proptools.StringPtr(sdkVersion)
-
- props.System_modules = module.deviceProperties.System_modules
-
- // The imports need to be compiled to dex if the java_sdk_library requests it.
- compileDex := module.dexProperties.Compile_dex
- if module.stubLibrariesCompiledForDex() {
- compileDex = proptools.BoolPtr(true)
- }
- props.Compile_dex = compileDex
-
- if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
- props.Dist.Targets = []string{"sdk", "win_sdk"}
- props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
- props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
- props.Dist.Tag = proptools.StringPtr(".jar")
- }
-
- return props
-}
-
-func (module *SdkLibrary) createTopLevelStubsLibrary(
- mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
-
- // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
- doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
- props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
- props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
-
- // Add the stub compiling java_library/java_api_library as static lib based on build config
- staticLib := module.sourceStubsLibraryModuleName(apiScope)
- if mctx.Config().BuildFromTextStub() && contributesToApiSurface {
- staticLib = module.apiLibraryModuleName(apiScope)
- }
- props.Static_libs = append(props.Static_libs, staticLib)
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
- mctx android.DefaultableHookContext, apiScope *apiScope) {
-
- // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
- doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
- props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
- props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
-
- staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
- props.Static_libs = append(props.Static_libs, staticLib)
-
- mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool {
return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api)
}
@@ -2209,106 +1657,8 @@
return module.uniqueApexVariations()
}
-func (module *SdkLibrary) ContributeToApi() bool {
- return proptools.BoolDefault(module.sdkLibraryProperties.Contribute_to_android_api, false)
-}
-
-// Creates the xml file that publicizes the runtime library
-func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
- moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
- var moduleMinApiLevelStr = moduleMinApiLevel.String()
- if moduleMinApiLevel == android.NoneApiLevel {
- moduleMinApiLevelStr = "current"
- }
- props := struct {
- Name *string
- Lib_name *string
- Apex_available []string
- On_bootclasspath_since *string
- On_bootclasspath_before *string
- Min_device_sdk *string
- Max_device_sdk *string
- Sdk_library_min_api_level *string
- Uses_libs_dependencies []string
- }{
- Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
- Lib_name: proptools.StringPtr(module.BaseModuleName()),
- Apex_available: module.ApexProperties.Apex_available,
- On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since,
- On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before,
- Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
- Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
- Sdk_library_min_api_level: &moduleMinApiLevelStr,
- Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
- }
-
- mctx.CreateModule(sdkLibraryXmlFactory, &props)
-}
-
-func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths {
- var ver android.ApiLevel
- var kind android.SdkKind
- if s.UsePrebuilt(ctx) {
- ver = s.ApiLevel
- kind = s.Kind
- } else {
- // We don't have prebuilt SDK for the specific sdkVersion.
- // Instead of breaking the build, fallback to use "system_current"
- ver = android.FutureApiLevel
- kind = android.SdkSystem
- }
-
- dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
- jar := filepath.Join(dir, baseName+".jar")
- jarPath := android.ExistentPathForSource(ctx, jar)
- if !jarPath.Valid() {
- if ctx.Config().AllowMissingDependencies() {
- return android.Paths{android.PathForSource(ctx, jar)}
- } else {
- ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar)
- }
- return nil
- }
- return android.Paths{jarPath.Path()}
-}
-
-// Check to see if the other module is within the same set of named APEXes as this module.
-//
-// If either this or the other module are on the platform then this will return
-// false.
-func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
- apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
- otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider)
- return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
-}
-
-func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- // If the client doesn't set sdk_version, but if this library prefers stubs over
- // the impl library, let's provide the widest API surface possible. To do so,
- // force override sdk_version to module_current so that the closest possible API
- // surface could be found in selectHeaderJarsForSdkVersion
- if module.defaultsToStubs() && !sdkVersion.Specified() {
- sdkVersion = android.SdkSpecFrom(ctx, "module_current")
- }
-
- // Only provide access to the implementation library if it is actually built.
- if module.requiresRuntimeImplementationLibrary() {
- // Check any special cases for java_sdk_library.
- //
- // Only allow access to the implementation library in the following condition:
- // * No sdk_version specified on the referencing module.
- // * The referencing module is in the same apex as this.
- if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
- return module.implLibraryHeaderJars
- }
- }
-
- return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
-}
-
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- return module.sdkJars(ctx, sdkVersion)
+func (module *SdkLibrary) ModuleBuildFromTextStubs() bool {
+ return proptools.BoolDefault(module.sdkLibraryProperties.Build_from_text_stub, true)
}
var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
@@ -2327,11 +1677,6 @@
// runtime libs and xml file. If requested, the stubs and docs are created twice
// once for public API level and once for system API level
func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookContext) {
- // If the module has been disabled then don't create any child modules.
- if !module.Enabled(mctx) {
- return
- }
-
if len(module.properties.Srcs) == 0 {
mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
return
@@ -2381,21 +1726,15 @@
for _, scope := range generatedScopes {
// Use the stubs source name for legacy reasons.
- module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
+ module.createDroidstubs(mctx, scope, module.droidstubsModuleName(scope), scope.droidstubsArgs)
- module.createStubsLibrary(mctx, scope)
- module.createExportableStubsLibrary(mctx, scope)
+ module.createFromSourceStubsLibrary(mctx, scope)
+ module.createExportableFromSourceStubsLibrary(mctx, scope)
- alternativeFullApiSurfaceStubLib := ""
- if scope == apiScopePublic {
- alternativeFullApiSurfaceStubLib = module.alternativeFullApiSurfaceStubLib()
+ if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() {
+ module.createApiLibrary(mctx, scope)
}
- contributesToApiSurface := module.contributesToApiSurface(mctx.Config()) || alternativeFullApiSurfaceStubLib != ""
- if contributesToApiSurface {
- module.createApiLibrary(mctx, scope, alternativeFullApiSurfaceStubLib)
- }
-
- module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface)
+ module.createTopLevelStubsLibrary(mctx, scope)
module.createTopLevelExportableStubsLibrary(mctx, scope)
}
@@ -2423,7 +1762,7 @@
// Add the impl_only_libs and impl_only_static_libs *after* we're done using them in submodules.
module.properties.Libs = append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...)
- module.properties.Static_libs = append(module.properties.Static_libs, module.sdkLibraryProperties.Impl_only_static_libs...)
+ module.properties.Static_libs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs)
}
func (module *SdkLibrary) InitSdkLibraryProperties() {
@@ -2440,84 +1779,25 @@
return !proptools.Bool(module.sdkLibraryProperties.Api_only)
}
-func (module *SdkLibrary) defaultsToStubs() bool {
- return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
-}
-
-// Defines how to name the individual component modules the sdk library creates.
-type sdkLibraryComponentNamingScheme interface {
- stubsLibraryModuleName(scope *apiScope, baseName string) string
-
- stubsSourceModuleName(scope *apiScope, baseName string) string
-
- apiLibraryModuleName(scope *apiScope, baseName string) string
-
- sourceStubsLibraryModuleName(scope *apiScope, baseName string) string
-
- exportableStubsLibraryModuleName(scope *apiScope, baseName string) string
-
- exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string
-}
-
-type defaultNamingScheme struct {
-}
-
-func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string {
- return scope.stubsLibraryModuleName(baseName)
-}
-
-func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string {
- return scope.stubsSourceModuleName(baseName)
-}
-
-func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName string) string {
- return scope.apiLibraryModuleName(baseName)
-}
-
-func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
- return scope.sourceStubLibraryModuleName(baseName)
-}
-
-func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string {
- return scope.exportableStubsLibraryModuleName(baseName)
-}
-
-func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
- return scope.exportableSourceStubsLibraryModuleName(baseName)
-}
-
-var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
-
-func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool {
- return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) ||
- strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix())
-}
-
-func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
- name = strings.TrimSuffix(name, ".from-source")
-
- // This suffix-based approach is fragile and could potentially mis-trigger.
- // TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
- if hasStubsLibrarySuffix(name, apiScopePublic) {
- if name == "hwbinder.stubs" || name == "libcore_private.stubs" {
- // Due to a previous bug, these modules were not considered stubs, so we retain that.
- return false, javaPlatform
- }
+func moduleStubLinkType(j *Module) (stub bool, ret sdkLinkType) {
+ kind := android.ToSdkKind(proptools.String(j.properties.Stub_contributing_api))
+ switch kind {
+ case android.SdkPublic:
return true, javaSdk
- }
- if hasStubsLibrarySuffix(name, apiScopeSystem) {
+ case android.SdkSystem:
return true, javaSystem
- }
- if hasStubsLibrarySuffix(name, apiScopeModuleLib) {
+ case android.SdkModule:
return true, javaModule
- }
- if hasStubsLibrarySuffix(name, apiScopeTest) {
+ case android.SdkTest:
return true, javaSystem
- }
- if hasStubsLibrarySuffix(name, apiScopeSystemServer) {
+ case android.SdkSystemServer:
return true, javaSystemServer
+ // Default value for all modules other than java_sdk_library-generated stub submodules
+ case android.SdkInvalid:
+ return false, javaPlatform
+ default:
+ panic(fmt.Sprintf("stub_contributing_api set as an unsupported sdk kind %s", kind.String()))
}
- return false, javaPlatform
}
// java_sdk_library is a special Java library that provides optional platform APIs to apps.
@@ -2560,7 +1840,7 @@
module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false)
}
- if module.initCommonAfterDefaultsApplied(ctx) {
+ if module.initCommonAfterDefaultsApplied() {
module.CreateInternalModules(ctx)
}
})
@@ -2639,8 +1919,6 @@
installFile android.Path
}
-var _ SdkLibraryDependency = (*SdkLibraryImport)(nil)
-
// The type of a structure that contains a field of type sdkLibraryScopeProperties
// for each apiscope in allApiScopes, e.g. something like:
//
@@ -2696,7 +1974,7 @@
InitJavaModule(module, android.HostAndDeviceSupported)
module.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
- if module.initCommonAfterDefaultsApplied(mctx) {
+ if module.initCommonAfterDefaultsApplied() {
module.createInternalModules(mctx)
}
})
@@ -2750,86 +2028,6 @@
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
-func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
- // Creates a java import for the jar with ".stubs" suffix
- props := struct {
- Name *string
- Source_module_name *string
- Created_by_java_sdk_library_name *string
- Sdk_version *string
- Libs []string
- Jars []string
- Compile_dex *bool
- Is_stubs_module *bool
-
- android.UserSuppliedPrebuiltProperties
- }{}
- props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
- props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
- props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
- props.Sdk_version = scopeProperties.Sdk_version
- // Prepend any of the libs from the legacy public properties to the libs for each of the
- // scopes to avoid having to duplicate them in each scope.
- props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
- props.Jars = scopeProperties.Jars
-
- // The imports are preferred if the java_sdk_library_import is preferred.
- props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
-
- // The imports need to be compiled to dex if the java_sdk_library_import requests it.
- compileDex := module.properties.Compile_dex
- if module.stubLibrariesCompiledForDex() {
- compileDex = proptools.BoolPtr(true)
- }
- props.Compile_dex = compileDex
- props.Is_stubs_module = proptools.BoolPtr(true)
-
- mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
- props := struct {
- Name *string
- Source_module_name *string
- Created_by_java_sdk_library_name *string
- Srcs []string
-
- android.UserSuppliedPrebuiltProperties
- }{}
- props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
- props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
- props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
- props.Srcs = scopeProperties.Stub_srcs
-
- // The stubs source is preferred if the java_sdk_library_import is preferred.
- props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
-
- mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
-func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
- api_file := scopeProperties.Current_api
- api_surface := &apiScope.name
-
- props := struct {
- Name *string
- Source_module_name *string
- Created_by_java_sdk_library_name *string
- Api_surface *string
- Api_file *string
- Visibility []string
- }{}
-
- props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
- props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
- props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
- props.Api_surface = api_surface
- props.Api_file = api_file
- props.Visibility = []string{"//visibility:override", "//visibility:public"}
-
- mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
-}
-
// Add the dependencies on the child module in the component deps mutator so that it
// creates references to the prebuilt and not the source modules.
func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -2843,7 +2041,7 @@
if len(scopeProperties.Stub_srcs) > 0 {
// Add dependencies to the prebuilt stubs source library
- ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.stubsSourceModuleName(apiScope)))
+ ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, android.PrebuiltNameFromSource(module.droidstubsModuleName(apiScope)))
}
}
}
@@ -2897,8 +2095,6 @@
var _ hiddenAPIModule = (*SdkLibraryImport)(nil)
func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- module.generateCommonBuildActions(ctx)
-
// Assume that source module(sdk_library) is installed in /<sdk_library partition>/framework
module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar")
@@ -2928,6 +2124,7 @@
}
}
})
+ sdkLibInfo := module.generateCommonBuildActions(ctx)
// Populate the scope paths with information from the properties.
for apiScope, scopeProperties := range module.scopeProperties {
@@ -2942,70 +2139,38 @@
}
if ctx.Device() {
- // If this is a variant created for a prebuilt_apex then use the dex implementation jar
- // obtained from the associated deapexer module.
+ // Shared libraries deapexed from prebuilt apexes are no longer supported.
+ // Set the dexJarBuildPath to a fake path.
+ // This allows soong analysis pass, but will be an error during ninja execution if there are
+ // any rdeps.
ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
- // Get the path of the dex implementation jar from the `deapexer` module.
- di, err := android.FindDeapexerProviderForModule(ctx)
- if err != nil {
- // An error was found, possibly due to multiple apexes in the tree that export this library
- // Defer the error till a client tries to call DexJarBuildPath
- module.dexJarFileErr = err
- module.initHiddenAPIError(err)
- return
- }
- dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())
- if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
- dexJarFile := makeDexJarPathFromPath(dexOutputPath)
- module.dexJarFile = dexJarFile
- installPath := android.PathForModuleInPartitionInstall(
- ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative)
- module.installFile = installPath
- module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
+ module.dexJarFile = makeDexJarPathFromPath(android.PathForModuleInstall(ctx, "intentionally_no_longer_supported"))
+ module.initHiddenAPI(ctx, module.dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
+ }
+ }
- module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
- module.dexpreopter.isSDKLibrary = true
- module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &module.dexpreopter)
-
- if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
- module.dexpreopter.inputProfilePathOnHost = profilePath
- }
- } else {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // prebuilt_apex has been configured to export the java library dex file.
- ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
+ var generatingLibs []string
+ for _, apiScope := range AllApiScopes {
+ if scopeProperties, ok := module.scopeProperties[apiScope]; ok {
+ if len(scopeProperties.Jars) == 0 {
+ continue
}
+ generatingLibs = append(generatingLibs, module.stubsLibraryModuleName(apiScope))
}
}
module.setOutputFiles(ctx)
if module.implLibraryModule != nil {
+ generatingLibs = append(generatingLibs, module.implLibraryModuleName())
setOutputFiles(ctx, module.implLibraryModule.Module)
}
+
+ sdkLibInfo.GeneratingLibs = generatingLibs
+ android.SetProvider(ctx, SdkLibraryInfoProvider, sdkLibInfo)
}
-func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
-
- // For consistency with SdkLibrary make the implementation jar available to libraries that
- // are within the same APEX.
- implLibraryModule := module.implLibraryModule
- if implLibraryModule != nil && withinSameApexesAs(ctx, module) {
- if headerJars {
- return implLibraryModule.HeaderJars()
- } else {
- return implLibraryModule.ImplementationJars()
- }
- }
-
- return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
-}
-
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
- // This module is just a wrapper for the prebuilt stubs.
- return module.sdkJars(ctx, sdkVersion, true)
-}
+var _ UsesLibraryDependency = (*SdkLibraryImport)(nil)
// to satisfy UsesLibraryDependency interface
func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
@@ -3044,29 +2209,6 @@
}
// to satisfy apex.javaDependency interface
-func (module *SdkLibraryImport) LintDepSets() LintDepSets {
- if module.implLibraryModule == nil {
- return LintDepSets{}
- } else {
- return module.implLibraryModule.LintDepSets()
- }
-}
-
-func (module *SdkLibraryImport) GetStrictUpdatabilityLinting() bool {
- if module.implLibraryModule == nil {
- return false
- } else {
- return module.implLibraryModule.GetStrictUpdatabilityLinting()
- }
-}
-
-func (module *SdkLibraryImport) SetStrictUpdatabilityLinting(strictLinting bool) {
- if module.implLibraryModule != nil {
- module.implLibraryModule.SetStrictUpdatabilityLinting(strictLinting)
- }
-}
-
-// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) Stem() string {
return module.BaseModuleName()
}
@@ -3107,333 +2249,6 @@
return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
}
-// java_sdk_library_xml
-type sdkLibraryXml struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.ApexModuleBase
-
- properties sdkLibraryXmlProperties
-
- outputFilePath android.OutputPath
- installDirPath android.InstallPath
-
- hideApexVariantFromMake bool
-}
-
-type sdkLibraryXmlProperties struct {
- // canonical name of the lib
- Lib_name *string
-
- // Signals that this shared library is part of the bootclasspath starting
- // on the version indicated in this attribute.
- //
- // This will make platforms at this level and above to ignore
- // <uses-library> tags with this library name because the library is already
- // available
- On_bootclasspath_since *string
-
- // Signals that this shared library was part of the bootclasspath before
- // (but not including) the version indicated in this attribute.
- //
- // The system will automatically add a <uses-library> tag with this library to
- // apps that target any SDK less than the version indicated in this attribute.
- On_bootclasspath_before *string
-
- // Indicates that PackageManager should ignore this shared library if the
- // platform is below the version indicated in this attribute.
- //
- // This means that the device won't recognise this library as installed.
- Min_device_sdk *string
-
- // Indicates that PackageManager should ignore this shared library if the
- // platform is above the version indicated in this attribute.
- //
- // This means that the device won't recognise this library as installed.
- Max_device_sdk *string
-
- // The SdkLibrary's min api level as a string
- //
- // This value comes from the ApiLevel of the MinSdkVersion property.
- Sdk_library_min_api_level *string
-
- // Uses-libs dependencies that the shared library requires to work correctly.
- //
- // This will add dependency="foo:bar" to the <library> section.
- Uses_libs_dependencies []string
-}
-
-// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
-// Not to be used directly by users. java_sdk_library internally uses this.
-func sdkLibraryXmlFactory() android.Module {
- module := &sdkLibraryXml{}
-
- module.AddProperties(&module.properties)
-
- android.InitApexModule(module)
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
-
- return module
-}
-
-func (module *sdkLibraryXml) UniqueApexVariations() bool {
- // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
- // mounted APEX, which contains the name of the APEX.
- return true
-}
-
-// from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) BaseDir() string {
- return "etc"
-}
-
-// from android.PrebuiltEtcModule
-func (module *sdkLibraryXml) SubDir() string {
- return "permissions"
-}
-
-var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
-
-// from android.ApexModule
-func (module *sdkLibraryXml) AvailableFor(what string) bool {
- return true
-}
-
-func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
- // do nothing
-}
-
-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
-}
-
-// File path to the runtime implementation library
-func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
- implName := proptools.String(module.properties.Lib_name)
- if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
- // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
- // In most cases, this works fine. But when apex_name is set or override_apex is used
- // this can be wrong.
- return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName)
- }
- partition := "system"
- if module.SocSpecific() {
- partition = "vendor"
- } else if module.DeviceSpecific() {
- partition = "odm"
- } else if module.ProductSpecific() {
- partition = "product"
- } else if module.SystemExtSpecific() {
- partition = "system_ext"
- }
- return "/" + partition + "/framework/" + implName + ".jar"
-}
-
-func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
- if value == nil {
- return ""
- }
- apiLevel, err := android.ApiLevelFromUser(ctx, *value)
- if err != nil {
- // attributes in bp files have underscores but in the xml have dashes.
- ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
- return ""
- }
- if apiLevel.IsCurrent() {
- // passing "current" would always mean a future release, never the current (or the current in
- // progress) which means some conditions would never be triggered.
- ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
- `"current" is not an allowed value for this attribute`)
- return ""
- }
- // "safeValue" is safe because it translates finalized codenames to a string
- // with their SDK int.
- safeValue := apiLevel.String()
- return formattedOptionalAttribute(attrName, &safeValue)
-}
-
-// formats an attribute for the xml permissions file if the value is not null
-// returns empty string otherwise
-func formattedOptionalAttribute(attrName string, value *string) string {
- if value == nil {
- return ""
- }
- return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value)
-}
-
-func formattedDependenciesAttribute(dependencies []string) string {
- if dependencies == nil {
- return ""
- }
- return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":"))
-}
-
-func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
- libName := proptools.String(module.properties.Lib_name)
- libNameAttr := formattedOptionalAttribute("name", &libName)
- filePath := module.implPath(ctx)
- filePathAttr := formattedOptionalAttribute("file", &filePath)
- implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
- implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
- minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
- maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
- dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
- // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
- // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
- var libraryTag string
- if module.properties.Min_device_sdk != nil {
- libraryTag = " <apex-library\n"
- } else {
- libraryTag = " <library\n"
- }
-
- return strings.Join([]string{
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
- "<!-- Copyright (C) 2018 The Android Open Source Project\n",
- "\n",
- " Licensed under the Apache License, Version 2.0 (the \"License\");\n",
- " you may not use this file except in compliance with the License.\n",
- " You may obtain a copy of the License at\n",
- "\n",
- " http://www.apache.org/licenses/LICENSE-2.0\n",
- "\n",
- " Unless required by applicable law or agreed to in writing, software\n",
- " distributed under the License is distributed on an \"AS IS\" BASIS,\n",
- " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
- " See the License for the specific language governing permissions and\n",
- " limitations under the License.\n",
- "-->\n",
- "<permissions>\n",
- libraryTag,
- libNameAttr,
- filePathAttr,
- implicitFromAttr,
- implicitUntilAttr,
- minSdkAttr,
- maxSdkAttr,
- dependenciesAttr,
- " />\n",
- "</permissions>\n",
- }, "")
-}
-
-func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
- module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
-
- libName := proptools.String(module.properties.Lib_name)
- module.selfValidate(ctx)
- xmlContent := module.permissionsContents(ctx)
-
- module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
- android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
-
- module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
- ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
-
- ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
-}
-
-func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
- if module.hideApexVariantFromMake {
- return []android.AndroidMkEntries{{
- Disabled: true,
- }}
- }
-
- return []android.AndroidMkEntries{{
- Class: "ETC",
- OutputFile: android.OptionalPathForPath(module.outputFilePath),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_TAGS", "optional")
- entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
- },
- },
- }}
-}
-
-func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
- module.validateAtLeastTAttributes(ctx)
- module.validateMinAndMaxDeviceSdk(ctx)
- module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
- module.validateOnBootclasspathBeforeRequirements(ctx)
-}
-
-func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
- t := android.ApiLevelOrPanic(ctx, "Tiramisu")
- module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
- module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
- module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
- module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
-}
-
-func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
- if attr != nil {
- if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
- // we will inform the user of invalid inputs when we try to write the
- // permissions xml file so we don't need to do it here
- if t.GreaterThan(level) {
- ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
- }
- }
- }
-}
-
-func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
- if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
- min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
- max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
- if minErr == nil && maxErr == nil {
- // we will inform the user of invalid inputs when we try to write the
- // permissions xml file so we don't need to do it here
- if min.GreaterThan(max) {
- ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
- }
- }
- }
-}
-
-func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
- moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
- if module.properties.Min_device_sdk != nil {
- api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
- if err == nil {
- if moduleMinApi.GreaterThan(api) {
- ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
- }
- }
- }
- if module.properties.Max_device_sdk != nil {
- api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
- if err == nil {
- if moduleMinApi.GreaterThan(api) {
- ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
- }
- }
- }
-}
-
-func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
- moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
- if module.properties.On_bootclasspath_before != nil {
- t := android.ApiLevelOrPanic(ctx, "Tiramisu")
- // if we use the attribute, then we need to do this validation
- if moduleMinApi.LessThan(t) {
- // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
- if module.properties.Min_device_sdk == nil {
- ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
- }
- }
- }
-}
-
type sdkLibrarySdkMemberType struct {
android.SdkMemberTypeBase
}
@@ -3570,7 +2385,6 @@
}
}
- s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
s.Compile_dex = sdk.dexProperties.Compile_dex
s.Doctag_paths = sdk.doctagPaths
@@ -3580,7 +2394,7 @@
s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
- implLibrary := sdk.getImplLibraryModule()
+ implLibrary := sdk.implLibraryModule
if implLibrary != nil && implLibrary.dexpreopter.dexpreoptProperties.Dex_preopt_result.Profile_guided {
s.DexPreoptProfileGuided = proptools.BoolPtr(true)
}
@@ -3667,3 +2481,19 @@
propertySet.AddProperty("doctag_files", dests)
}
}
+
+// TODO(b/358613520): This can be removed when modules are no longer allowed to depend on the top-level library.
+func (s *SdkLibrary) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
+ s.Library.IDEInfo(ctx, dpInfo)
+ if s.implLibraryModule != nil {
+ dpInfo.Deps = append(dpInfo.Deps, s.implLibraryModule.Name())
+ } else {
+ // This java_sdk_library does not have an implementation (it sets `api_only` to true).
+ // Examples of this are `art.module.intra.core.api` (IntraCore api surface).
+ // Return the "public" stubs for these.
+ stubPaths := s.findClosestScopePath(apiScopePublic)
+ if len(stubPaths.stubsHeaderPath) > 0 {
+ dpInfo.Jars = append(dpInfo.Jars, stubPaths.stubsHeaderPath[0].String())
+ }
+ }
+}
diff --git a/java/sdk_library_external.go b/java/sdk_library_external.go
deleted file mode 100644
index 4f83981..0000000
--- a/java/sdk_library_external.go
+++ /dev/null
@@ -1,119 +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 java
-
-import (
- "android/soong/android"
-)
-
-type partitionGroup int
-
-// Representation of partition group for checking inter-partition library dependencies.
-// Between system and system_ext, there are no restrictions of dependencies,
-// so we can treat these partitions as the same in terms of inter-partition dependency.
-// Same policy is applied between vendor and odm partiton.
-const (
- partitionGroupNone partitionGroup = iota
- // group for system, and system_ext partition
- partitionGroupSystem
- // group for vendor and odm partition
- partitionGroupVendor
- // product partition
- partitionGroupProduct
-)
-
-func (g partitionGroup) String() string {
- switch g {
- case partitionGroupSystem:
- return "system"
- case partitionGroupVendor:
- return "vendor"
- case partitionGroupProduct:
- return "product"
- }
-
- return ""
-}
-
-// Get partition group of java module that can be used at inter-partition dependency check.
-// We currently have three groups
-//
-// (system, system_ext) => system partition group
-// (vendor, odm) => vendor partition group
-// (product) => product partition group
-func (j *Module) partitionGroup(ctx android.EarlyModuleContext) partitionGroup {
- // system and system_ext partition can be treated as the same in terms of inter-partition dependency.
- if j.Platform() || j.SystemExtSpecific() {
- return partitionGroupSystem
- }
-
- // vendor and odm partition can be treated as the same in terms of inter-partition dependency.
- if j.SocSpecific() || j.DeviceSpecific() {
- return partitionGroupVendor
- }
-
- // product partition is independent.
- if j.ProductSpecific() {
- return partitionGroupProduct
- }
-
- panic("Cannot determine partition type")
-}
-
-func (j *Module) allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool {
- return inList(j.Name(), ctx.Config().InterPartitionJavaLibraryAllowList())
-}
-
-func (j *Module) syspropWithPublicStubs() bool {
- return j.deviceProperties.SyspropPublicStub != ""
-}
-
-type javaSdkLibraryEnforceContext interface {
- Name() string
- allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool
- partitionGroup(ctx android.EarlyModuleContext) partitionGroup
- syspropWithPublicStubs() bool
-}
-
-var _ javaSdkLibraryEnforceContext = (*Module)(nil)
-
-func (j *Module) checkPartitionsForJavaDependency(ctx android.EarlyModuleContext, propName string, dep javaSdkLibraryEnforceContext) {
- if dep.allowListedInterPartitionJavaLibrary(ctx) {
- return
- }
-
- if dep.syspropWithPublicStubs() {
- return
- }
-
- // If product interface is not enforced, skip check between system and product partition.
- // But still need to check between product and vendor partition because product interface flag
- // just represents enforcement between product and system, and vendor interface enforcement
- // that is enforced here by precondition is representing enforcement between vendor and other partitions.
- if !ctx.Config().EnforceProductPartitionInterface() {
- productToSystem := j.partitionGroup(ctx) == partitionGroupProduct && dep.partitionGroup(ctx) == partitionGroupSystem
- systemToProduct := j.partitionGroup(ctx) == partitionGroupSystem && dep.partitionGroup(ctx) == partitionGroupProduct
-
- if productToSystem || systemToProduct {
- return
- }
- }
-
- // If module and dependency library is inter-partition
- if j.partitionGroup(ctx) != dep.partitionGroup(ctx) {
- errorFormat := "dependency on java_library (%q) is not allowed across the partitions (%s -> %s), use java_sdk_library instead"
- ctx.PropertyErrorf(propName, errorFormat, dep.Name(), j.partitionGroup(ctx), dep.partitionGroup(ctx))
- }
-}
diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go
new file mode 100644
index 0000000..ca088cf
--- /dev/null
+++ b/java/sdk_library_internal.go
@@ -0,0 +1,1017 @@
+// 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 java
+
+import (
+ "android/soong/android"
+ "android/soong/etc"
+ "fmt"
+ "path"
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+)
+
+// ---------------------------------------------------------------------------------------------
+// Naming scheme of the submodules generated by java_sdk_library and java_sdk_library_import
+// ---------------------------------------------------------------------------------------------
+
+const (
+ sdkXmlFileSuffix = ".xml"
+ implLibSuffix = ".impl"
+)
+
+func implLibraryModuleName(sdkLibName string) string {
+ return sdkLibName + implLibSuffix
+}
+
+// Module name of the runtime implementation library
+func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
+ return implLibraryModuleName(c.module.RootLibraryName())
+}
+
+// Module name of the XML file for the lib
+func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
+ return c.module.RootLibraryName() + sdkXmlFileSuffix
+}
+
+// Name of the java_library module that compiles the stubs source.
+func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.stubsLibraryModuleName(baseName)
+}
+
+// Name of the java_library module that compiles the exportable stubs source.
+func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.exportableStubsLibraryModuleName(baseName)
+}
+
+// Name of the droidstubs module that generates the stubs source and may also
+// generate/check the API.
+func (c *commonToSdkLibraryAndImport) droidstubsModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.stubsSourceModuleName(baseName)
+}
+
+// Name of the java_api_library module that generates the from-text stubs source
+// and compiles to a jar file.
+func (c *commonToSdkLibraryAndImport) fromTextStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.apiLibraryModuleName(baseName)
+}
+
+// Name of the java_library module that compiles the stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) fromSourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.sourceStubsLibraryModuleName(baseName)
+}
+
+// Name of the java_library module that compiles the exportable stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) exportableFromSourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.RootLibraryName()
+ return apiScope.exportableSourceStubsLibraryModuleName(baseName)
+}
+
+// ---------------------------------------------------------------------------------------------
+// Build rules of the submodules generated by java_sdk_library.
+// java_sdk_library "framework-foo" generates the following submodules:
+//
+// - "framework-foo.impl" (type: [Library]): the implementation library, which generates the
+// compilation outputs that include the implementation details and the private apis
+// (i.e. class/methods that are annotated @hide).
+//
+// - "framework-foo.stubs.source.<[apiScope.name]>" (type: [Droidstubs]): droidstubs module that
+// generates the stubs and the api files for the given api scope.
+//
+// - "framework-foo.stubs.<[apiScope.name]>" (type: [Library]): stub library module that
+// provides the compilation output of the stubs to the reverse dependencies. The module
+// itself does not perform any compilation actions; the module statically depends on one of
+// the from-source stub module or the from-text stub configuration based on the build
+// configuration.
+//
+// - "framework-foo.stubs.<[apiScope.name]>.from-source" (type: [Library]): stub library module
+// that compiles the stubs generated by the droidstubs submodule. This module is a static
+// dependency of the stub library module when
+// [android/soong/android/config.BuildFromTextStub()] is false.
+//
+// - "framework-foo.stubs.<[apiScope.name]>.from-text" (type: [ApiLibrary]): api library module
+// that generates and compiles the stubs from the api files checked in the tree instead of
+// the source Java files (e.g. *-current.txt files). This module is a static dependency of
+// the stub library module when [android/soong/android/config.BuildFromTextStub()] is true.
+//
+// - "framework-foo.stubs.exportable.<[apiScope.name]>" (type: [Library]): stub library module
+// that provides the "exportable" stubs. "exportable" stubs are the stubs that do not
+// include in-development flagged apis. This module is only used for SDK builds to generate
+// the SDK artifacts, and not purposed for consumption for other modules.
+//
+// - "framework-foo.stubs.exportable.<[apiScope.name]>.from-source" (type: [Library]): stub
+// library module that compiles the "exportable" stubs generated by the droidstubs
+// submodule. This module is always a static dependency of the "exportable" stub library
+// module given that from-text stubs cannot be used for SDK builds as it does not contain
+// documentations.
+//
+// - "framework-foo.xml" (type: [sdkLibraryXml]): xml library that generates the permission xml
+// file, which allows [SdkLibrary] to be used with <uses-permission> tag in the
+// AndroidManifest.xml files.
+// ---------------------------------------------------------------------------------------------
+
+// Creates the implementation [Library] with ".impl" suffix.
+func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
+ visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility)
+
+ staticLibs := module.properties.Static_libs.Clone()
+ staticLibs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs)
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Libs []string
+ Static_libs proptools.Configurable[[]string]
+ Apex_available []string
+ Stem *string
+ }{
+ Name: proptools.StringPtr(module.implLibraryModuleName()),
+ Enabled: module.EnabledProperty(),
+ Visibility: visibility,
+
+ Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...),
+
+ Static_libs: staticLibs,
+ // Pass the apex_available settings down so that the impl library can be statically
+ // embedded within a library that is added to an APEX. Needed for updatable-media.
+ Apex_available: module.ApexAvailable(),
+
+ Stem: proptools.StringPtr(module.Name()),
+ }
+
+ properties := []interface{}{
+ &module.properties,
+ &module.protoProperties,
+ &module.deviceProperties,
+ &module.dexProperties,
+ &module.dexpreoptProperties,
+ &module.linter.properties,
+ &module.overridableProperties,
+ &props,
+ module.sdkComponentPropertiesForChildLibrary(),
+ }
+ mctx.CreateModule(LibraryFactory, properties...)
+}
+
+// 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).
+func (module *SdkLibrary) createDroidstubs(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) {
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ Api_surface *string
+ System_modules *string
+ Libs proptools.Configurable[[]string]
+ Output_javadoc_comments *bool
+ Arg_files []string
+ Args *string
+ Java_version *string
+ Annotations_enabled *bool
+ Merge_annotations_dirs []string
+ Merge_inclusion_annotations_dirs []string
+ Generate_stubs *bool
+ Previous_api *string
+ Aconfig_declarations []string
+ Check_api struct {
+ Current ApiToCheck
+ Last_released ApiToCheck
+
+ Api_lint struct {
+ Enabled *bool
+ New_since *string
+ Baseline_file *string
+ }
+ }
+ Aidl struct {
+ Include_dirs []string
+ Local_include_dirs []string
+ }
+ Dists []android.Dist
+ }{}
+
+ // The stubs source processing uses the same compile time classpath when extracting the
+ // API from the implementation library as it does when compiling it. i.e. the same
+ // * sdk version
+ // * system_modules
+ // * libs (static_libs/libs)
+
+ props.Name = proptools.StringPtr(name)
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
+ 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.System_modules = module.deviceProperties.System_modules
+ props.Installable = proptools.BoolPtr(false)
+ // A droiddoc module has only one Libs property and doesn't distinguish between
+ // shared libs and static libs. So we need to add both of these libs to Libs property.
+ props.Libs = proptools.NewConfigurable[[]string](nil, nil)
+ props.Libs.AppendSimpleValue(module.properties.Libs)
+ props.Libs.Append(module.properties.Static_libs)
+ props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
+ props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
+ props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
+ props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
+ props.Java_version = module.properties.Java_version
+
+ props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
+ props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
+ props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
+ props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
+
+ droidstubsArgs := []string{}
+ if len(module.sdkLibraryProperties.Api_packages) != 0 {
+ droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
+ }
+ droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
+ disabledWarnings := []string{"HiddenSuperclass"}
+ if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
+ disabledWarnings = append(disabledWarnings,
+ "BroadcastBehavior",
+ "DeprecationMismatch",
+ "MissingPermission",
+ "SdkConstant",
+ "Todo",
+ )
+ }
+ droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
+
+ // Output Javadoc comments for public scope.
+ if apiScope == apiScopePublic {
+ props.Output_javadoc_comments = proptools.BoolPtr(true)
+ }
+
+ // Add in scope specific arguments.
+ droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...)
+ props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
+ props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
+
+ // List of APIs identified from the provided source files are created. They are later
+ // compared against to the not-yet-released (a.k.a current) list of APIs and to the
+ // last-released (a.k.a numbered) list of API.
+ currentApiFileName := apiScope.apiFilePrefix + "current.txt"
+ removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
+ apiDir := module.getApiDir()
+ currentApiFileName = path.Join(apiDir, currentApiFileName)
+ removedApiFileName = path.Join(apiDir, removedApiFileName)
+
+ // check against the not-yet-release API
+ props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
+ props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
+
+ if module.compareAgainstLatestApi(apiScope) {
+ // check against the latest released API
+ latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
+ props.Previous_api = latestApiFilegroupName
+ props.Check_api.Last_released.Api_file = latestApiFilegroupName
+ props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
+ module.latestRemovedApiFilegroupName(apiScope))
+ props.Check_api.Last_released.Baseline_file = proptools.StringPtr(
+ module.latestIncompatibilitiesFilegroupName(apiScope))
+
+ if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) {
+ // Enable api lint.
+ props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true)
+ props.Check_api.Api_lint.New_since = latestApiFilegroupName
+
+ // If it exists then pass a lint-baseline.txt through to droidstubs.
+ baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt")
+ baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath)
+ paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil)
+ if err != nil {
+ mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err)
+ }
+ if len(paths) == 1 {
+ props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath)
+ } else if len(paths) != 0 {
+ mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths)
+ }
+ }
+ }
+
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ // Dist the api txt and removed api txt artifacts for sdk builds.
+ distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api"))
+ stubsTypeTagPrefix := ""
+ if mctx.Config().ReleaseHiddenApiExportableStubs() {
+ stubsTypeTagPrefix = ".exportable"
+ }
+ for _, p := range []struct {
+ tag string
+ pattern string
+ }{
+ // "exportable" api files are copied to the dist directory instead of the
+ // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag
+ // is set. Otherwise, the "everything" api files are copied to the dist directory.
+ {tag: "%s.api.txt", pattern: "%s.txt"},
+ {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"},
+ } {
+ props.Dists = append(props.Dists, android.Dist{
+ Targets: []string{"sdk", "win_sdk"},
+ Dir: distDir,
+ Dest: proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())),
+ Tag: proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)),
+ })
+ }
+ }
+
+ mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
+}
+
+type libraryProperties struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ System_modules *string
+ Patch_module *string
+ Libs []string
+ Static_libs []string
+ Compile_dex *bool
+ Java_version *string
+ Openjdk9 struct {
+ Srcs []string
+ Javacflags []string
+ }
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ Tag *string
+ }
+ Is_stubs_module *bool
+ Stub_contributing_api *string
+}
+
+func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+ props := libraryProperties{}
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = []string{"//visibility:override", "//visibility:private"}
+ // sources are generated from the droiddoc
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
+ props.Sdk_version = proptools.StringPtr(sdkVersion)
+ props.System_modules = module.deviceProperties.System_modules
+ props.Patch_module = module.properties.Patch_module
+ props.Installable = proptools.BoolPtr(false)
+ props.Libs = module.sdkLibraryProperties.Stub_only_libs
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
+ props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
+ // The stub-annotations library contains special versions of the annotations
+ // with CLASS retention policy, so that they're kept.
+ if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) {
+ props.Libs = append(props.Libs, "stub-annotations")
+ }
+ props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
+ props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
+ // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
+ // interop with older developer tools that don't support 1.9.
+ props.Java_version = proptools.StringPtr("1.8")
+ props.Is_stubs_module = proptools.BoolPtr(true)
+ props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())
+
+ return props
+}
+
+// Creates the from-source stub [Library] with ".stubs.<[apiScope.name]>.from-source" suffix.
+func (module *SdkLibrary) createFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.fromSourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.droidstubsModuleName(apiScope)}
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the "exportable" from-source stub [Library] with
+// ".stubs.exportable.<[apiScope.name]>" suffix.
+func (module *SdkLibrary) createExportableFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.exportableFromSourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.droidstubsModuleName(apiScope) + "{.exportable}"}
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the from-text stub [ApiLibrary] with ".stubs.<[apiScope.name]>.from-text" suffix.
+func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Visibility []string
+ Api_contributions []string
+ Libs proptools.Configurable[[]string]
+ Static_libs []string
+ System_modules *string
+ Enable_validation *bool
+ Stubs_type *string
+ Sdk_version *string
+ Previous_api *string
+ }{}
+
+ props.Name = proptools.StringPtr(module.fromTextStubsLibraryModuleName(apiScope))
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = []string{"//visibility:override", "//visibility:private"}
+
+ apiContributions := []string{}
+
+ // Api surfaces are not independent of each other, but have subset relationships,
+ // and so does the api files. To generate from-text stubs for api surfaces other than public,
+ // all subset api domains' api_contriubtions must be added as well.
+ scope := apiScope
+ for scope != nil {
+ apiContributions = append(apiContributions, module.droidstubsModuleName(scope)+".api.contribution")
+ scope = scope.extends
+ }
+ if apiScope == apiScopePublic {
+ additionalApiContribution := module.apiLibraryAdditionalApiContribution()
+ if additionalApiContribution != "" {
+ apiContributions = append(apiContributions, additionalApiContribution)
+ }
+ }
+
+ props.Api_contributions = apiContributions
+
+ // Ensure that stub-annotations is added to the classpath before any other libs
+ props.Libs = proptools.NewConfigurable[[]string](nil, nil)
+ props.Libs.AppendSimpleValue([]string{"stub-annotations"})
+ props.Libs.AppendSimpleValue(module.properties.Libs)
+ props.Libs.Append(module.properties.Static_libs)
+ props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs)
+ props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs)
+ props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
+
+ props.System_modules = module.deviceProperties.System_modules
+ props.Enable_validation = proptools.BoolPtr(true)
+ props.Stubs_type = proptools.StringPtr("everything")
+
+ if module.deviceProperties.Sdk_version != nil {
+ props.Sdk_version = module.deviceProperties.Sdk_version
+ }
+
+ if module.compareAgainstLatestApi(apiScope) {
+ // check against the latest released API
+ latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope))
+ props.Previous_api = latestApiFilegroupName
+ }
+
+ mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties {
+ props := libraryProperties{}
+
+ props.Enabled = module.EnabledProperty()
+ props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
+ sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
+ props.Sdk_version = proptools.StringPtr(sdkVersion)
+
+ props.System_modules = module.deviceProperties.System_modules
+
+ // The imports need to be compiled to dex if the java_sdk_library requests it.
+ compileDex := module.dexProperties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
+ }
+ props.Compile_dex = compileDex
+
+ props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String())
+
+ if !Bool(module.sdkLibraryProperties.No_dist) && doDist {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
+ props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+ props.Dist.Tag = proptools.StringPtr(".jar")
+ }
+ props.Is_stubs_module = proptools.BoolPtr(true)
+
+ return props
+}
+
+// Creates the stub [Library] with ".stubs.<[apiScope.name]>" suffix.
+func (module *SdkLibrary) createTopLevelStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false
+ doDist := !mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
+ props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+
+ // Add the stub compiling java_library/java_api_library as static lib based on build config
+ staticLib := module.fromSourceStubsLibraryModuleName(apiScope)
+ if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() {
+ staticLib = module.fromTextStubsLibraryModuleName(apiScope)
+ }
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the "exportable" stub [Library] with ".stubs.exportable.<[apiScope.name]>" suffix.
+func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true
+ doDist := mctx.Config().ReleaseHiddenApiExportableStubs()
+ props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist)
+ props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
+
+ staticLib := module.exportableFromSourceStubsLibraryModuleName(apiScope)
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the [sdkLibraryXml] with ".xml" suffix.
+func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
+ moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
+ var moduleMinApiLevelStr = moduleMinApiLevel.String()
+ if moduleMinApiLevel == android.NoneApiLevel {
+ moduleMinApiLevelStr = "current"
+ }
+ props := struct {
+ Name *string
+ Enabled proptools.Configurable[bool]
+ Lib_name *string
+ Apex_available []string
+ On_bootclasspath_since *string
+ On_bootclasspath_before *string
+ Min_device_sdk *string
+ Max_device_sdk *string
+ Sdk_library_min_api_level *string
+ Uses_libs_dependencies []string
+ }{
+ Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
+ Enabled: module.EnabledProperty(),
+ Lib_name: proptools.StringPtr(module.BaseModuleName()),
+ Apex_available: module.ApexProperties.Apex_available,
+ On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since,
+ On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before,
+ Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
+ Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
+ Sdk_library_min_api_level: &moduleMinApiLevelStr,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
+ }
+
+ mctx.CreateModule(sdkLibraryXmlFactory, &props)
+}
+
+// ---------------------------------------------------------------------------------------------
+// Build rules of the submodules generated by java_sdk_library_import.
+// Note that the java_sdk_library_import module does not generate the implementation library.
+// Instead, it will create a dependency to the source implemenetation library if one exists.
+// java_sdk_library_import "framework-foo" generates the following submodules:
+//
+// - "framework-foo.stubs.<[apiScope.name]>" (type: [Import]): prebuilt stub library module that
+// provides the stub jar file checked in the tree.
+//
+// - "framework-foo.stubs.source.<[apiScope.name]>" (type: [PrebuiltStubsSources]): prebuilt
+// droidstubs module that provides the stub source jar file checked in the tree.
+//
+// - "framework-foo.stubs.source.<[apiScope.name]>.api.contribution"
+// (type [JavaApiContributionImport]): prebuilt java_api_contribution module that provides
+// the prebuilt api file for previously released from-text stub generation.
+// ---------------------------------------------------------------------------------------------
+
+// Creates the prebuilt stub [Import] with ".stubs.<[apiScope.name]>" suffix.
+func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ // Creates a java import for the jar with ".stubs" suffix
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Sdk_version *string
+ Libs []string
+ Jars []string
+ Compile_dex *bool
+ Is_stubs_module *bool
+
+ android.UserSuppliedPrebuiltProperties
+ }{}
+ props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Sdk_version = scopeProperties.Sdk_version
+ // Prepend any of the libs from the legacy public properties to the libs for each of the
+ // scopes to avoid having to duplicate them in each scope.
+ props.Libs = append(module.properties.Libs, scopeProperties.Libs...)
+ props.Jars = scopeProperties.Jars
+
+ // The imports are preferred if the java_sdk_library_import is preferred.
+ props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
+
+ // The imports need to be compiled to dex if the java_sdk_library_import requests it.
+ compileDex := module.properties.Compile_dex
+ if module.stubLibrariesCompiledForDex() {
+ compileDex = proptools.BoolPtr(true)
+ }
+ props.Compile_dex = compileDex
+ props.Is_stubs_module = proptools.BoolPtr(true)
+
+ mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Srcs []string
+
+ android.UserSuppliedPrebuiltProperties
+ }{}
+ props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope))
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Srcs = scopeProperties.Stub_srcs
+
+ // The stubs source is preferred if the java_sdk_library_import is preferred.
+ props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
+
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Creates the prebuilt api contribution [JavaApiContributionImport] with
+// ".stubs.source.<[apiScope.name]>.api.contribution" suffix.
+func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ api_file := scopeProperties.Current_api
+ api_surface := &apiScope.name
+
+ props := struct {
+ Name *string
+ Source_module_name *string
+ Created_by_java_sdk_library_name *string
+ Api_surface *string
+ Api_file *string
+ Visibility []string
+ }{}
+
+ props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope) + ".api.contribution")
+ props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution")
+ props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName())
+ props.Api_surface = api_surface
+ props.Api_file = api_file
+ props.Visibility = []string{"//visibility:override", "//visibility:public"}
+
+ mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// ---------------------------------------------------------------------------------------------
+// End of the build rules of the submodules generated by java_sdk_library_import.
+// ---------------------------------------------------------------------------------------------
+
+// Definition of the [sdkLibraryXml] module. The module generates the permissions xml file,
+// so that the apps can specify the java_sdk_library using <uses-permission> tag in the
+// AndroidManifest.xml file.
+type sdkLibraryXml struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.ApexModuleBase
+
+ properties sdkLibraryXmlProperties
+
+ outputFilePath android.OutputPath
+ installDirPath android.InstallPath
+
+ hideApexVariantFromMake bool
+}
+
+type sdkLibraryXmlProperties struct {
+ // canonical name of the lib
+ Lib_name *string
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
+
+ // The SdkLibrary's min api level as a string
+ //
+ // This value comes from the ApiLevel of the MinSdkVersion property.
+ Sdk_library_min_api_level *string
+
+ // Uses-libs dependencies that the shared library requires to work correctly.
+ //
+ // This will add dependency="foo:bar" to the <library> section.
+ Uses_libs_dependencies []string
+}
+
+// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
+// Not to be used directly by users. java_sdk_library internally uses this.
+func sdkLibraryXmlFactory() android.Module {
+ module := &sdkLibraryXml{}
+
+ module.AddProperties(&module.properties)
+
+ android.InitApexModule(module)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+
+ return module
+}
+
+func (module *sdkLibraryXml) UniqueApexVariations() bool {
+ // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
+ // mounted APEX, which contains the name of the APEX.
+ return true
+}
+
+// from android.PrebuiltEtcModule
+func (module *sdkLibraryXml) BaseDir() string {
+ return "etc"
+}
+
+// from android.PrebuiltEtcModule
+func (module *sdkLibraryXml) SubDir() string {
+ return "permissions"
+}
+
+var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)
+
+// from android.ApexModule
+func (module *sdkLibraryXml) AvailableFor(what string) bool {
+ return true
+}
+
+func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // do nothing
+}
+
+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
+}
+
+// File path to the runtime implementation library
+func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
+ implName := proptools.String(module.properties.Lib_name)
+ if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
+ // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
+ // In most cases, this works fine. But when apex_name is set or override_apex is used
+ // this can be wrong.
+ return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName)
+ }
+ partition := "system"
+ if module.SocSpecific() {
+ partition = "vendor"
+ } else if module.DeviceSpecific() {
+ partition = "odm"
+ } else if module.ProductSpecific() {
+ partition = "product"
+ } else if module.SystemExtSpecific() {
+ partition = "system_ext"
+ }
+ return "/" + partition + "/framework/" + implName + ".jar"
+}
+
+func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ apiLevel, err := android.ApiLevelFromUser(ctx, *value)
+ if err != nil {
+ // attributes in bp files have underscores but in the xml have dashes.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
+ return ""
+ }
+ if apiLevel.IsCurrent() {
+ // passing "current" would always mean a future release, never the current (or the current in
+ // progress) which means some conditions would never be triggered.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
+ `"current" is not an allowed value for this attribute`)
+ return ""
+ }
+ // "safeValue" is safe because it translates finalized codenames to a string
+ // with their SDK int.
+ safeValue := apiLevel.String()
+ return formattedOptionalAttribute(attrName, &safeValue)
+}
+
+// formats an attribute for the xml permissions file if the value is not null
+// returns empty string otherwise
+func formattedOptionalAttribute(attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ return fmt.Sprintf(" %s=\"%s\"\n", attrName, *value)
+}
+
+func formattedDependenciesAttribute(dependencies []string) string {
+ if dependencies == nil {
+ return ""
+ }
+ return fmt.Sprintf(" dependency=\"%s\"\n", strings.Join(dependencies, ":"))
+}
+
+func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
+ libName := proptools.String(module.properties.Lib_name)
+ libNameAttr := formattedOptionalAttribute("name", &libName)
+ filePath := module.implPath(ctx)
+ filePathAttr := formattedOptionalAttribute("file", &filePath)
+ implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
+ implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
+ minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
+ maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
+ dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
+ // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
+ // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
+ var libraryTag string
+ if module.properties.Min_device_sdk != nil {
+ libraryTag = " <apex-library\n"
+ } else {
+ libraryTag = " <library\n"
+ }
+
+ return strings.Join([]string{
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
+ "<!-- Copyright (C) 2018 The Android Open Source Project\n",
+ "\n",
+ " Licensed under the Apache License, Version 2.0 (the \"License\");\n",
+ " you may not use this file except in compliance with the License.\n",
+ " You may obtain a copy of the License at\n",
+ "\n",
+ " http://www.apache.org/licenses/LICENSE-2.0\n",
+ "\n",
+ " Unless required by applicable law or agreed to in writing, software\n",
+ " distributed under the License is distributed on an \"AS IS\" BASIS,\n",
+ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
+ " See the License for the specific language governing permissions and\n",
+ " limitations under the License.\n",
+ "-->\n",
+ "<permissions>\n",
+ libraryTag,
+ libNameAttr,
+ filePathAttr,
+ implicitFromAttr,
+ implicitUntilAttr,
+ minSdkAttr,
+ maxSdkAttr,
+ dependenciesAttr,
+ " />\n",
+ "</permissions>\n",
+ }, "")
+}
+
+func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
+
+ libName := proptools.String(module.properties.Lib_name)
+ module.selfValidate(ctx)
+ xmlContent := module.permissionsContents(ctx)
+
+ module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
+ android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
+
+ module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
+ ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
+
+ ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "")
+}
+
+func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
+ if module.hideApexVariantFromMake {
+ return []android.AndroidMkEntries{{
+ Disabled: true,
+ }}
+ }
+
+ return []android.AndroidMkEntries{{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(module.outputFilePath),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_TAGS", "optional")
+ entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base())
+ },
+ },
+ }}
+}
+
+func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
+ module.validateAtLeastTAttributes(ctx)
+ module.validateMinAndMaxDeviceSdk(ctx)
+ module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
+ module.validateOnBootclasspathBeforeRequirements(ctx)
+}
+
+func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
+}
+
+func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
+ if attr != nil {
+ if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if t.GreaterThan(level) {
+ ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
+ if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
+ min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if minErr == nil && maxErr == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if min.GreaterThan(max) {
+ ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.Min_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+ if module.properties.Max_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.On_bootclasspath_before != nil {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ // if we use the attribute, then we need to do this validation
+ if moduleMinApi.LessThan(t) {
+ // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
+ if module.properties.Min_device_sdk == nil {
+ ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
+ }
+ }
+ }
+}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index a8a1494..6031d72 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -22,8 +22,6 @@
"testing"
"android/soong/android"
-
- "github.com/google/blueprint/proptools"
)
func TestJavaSdkLibrary(t *testing.T) {
@@ -35,14 +33,7 @@
"29": {"foo"},
"30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"},
}),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
@@ -62,7 +53,7 @@
java_library {
name: "baz",
srcs: ["c.java"],
- libs: ["foo", "bar.stubs"],
+ libs: ["foo.stubs.system", "bar.stubs"],
sdk_version: "system_current",
}
java_sdk_library {
@@ -99,25 +90,25 @@
java_library {
name: "qux",
srcs: ["c.java"],
- libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"],
+ libs: ["baz", "fred.stubs", "quuz.stubs", "wilma.stubs", "barney.stubs.system", "betty.stubs.system"],
sdk_version: "system_current",
}
java_library {
name: "baz-test",
srcs: ["c.java"],
- libs: ["foo"],
+ libs: ["foo.stubs.test"],
sdk_version: "test_current",
}
java_library {
name: "baz-29",
srcs: ["c.java"],
- libs: ["foo"],
+ libs: ["sdk_system_29_foo"],
sdk_version: "system_29",
}
java_library {
name: "baz-module-30",
srcs: ["c.java"],
- libs: ["foo"],
+ libs: ["sdk_module-lib_30_foo"],
sdk_version: "module_30",
}
`)
@@ -137,7 +128,7 @@
result.ModuleForTests("foo.api.system.28", "")
result.ModuleForTests("foo.api.test.28", "")
- exportedComponentsInfo, _ := android.SingletonModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
+ exportedComponentsInfo, _ := android.OtherModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
expectedFooExportedComponents := []string{
"foo-removed.api.combined.public.latest",
"foo-removed.api.combined.system.latest",
@@ -169,11 +160,11 @@
baz29Javac := result.ModuleForTests("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/29/system/foo.jar")
+ android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/sdk_system_29_foo/android_common/combined/sdk_system_29_foo.jar")
bazModule30Javac := result.ModuleForTests("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/30/module-lib/foo.jar")
+ 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")
// test if baz has exported SDK lib names foo and bar to qux
qux := result.ModuleForTests("qux", "android_common")
@@ -429,7 +420,7 @@
for _, expectation := range expectations {
verify("sdklib.impl", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
- stubName := apiScopePublic.sourceStubLibraryModuleName("sdklib")
+ stubName := apiScopePublic.sourceStubsLibraryModuleName("sdklib")
verify(stubName, expectation.lib, expectation.on_stub_classpath, expectation.in_stub_combined)
}
}
@@ -452,7 +443,7 @@
java_library {
name: "bar",
srcs: ["b.java"],
- libs: ["foo"],
+ libs: ["foo.stubs"],
}
`)
@@ -540,11 +531,7 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -774,7 +761,7 @@
java_library {
name: "bar",
srcs: ["a.java"],
- libs: ["foo-public", "foo-system", "foo-module-lib", "foo-system-server"],
+ libs: ["foo-public.stubs", "foo-system.stubs.system", "foo-module-lib.stubs.module_lib", "foo-system-server.stubs.system_server"],
sdk_version: "system_server_current",
}
`)
@@ -800,102 +787,26 @@
}
}
-func TestJavaSdkLibrary_MissingScope(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).
- RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- public: {
- enabled: false,
- },
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- sdk_version: "module_current",
- }
- `)
-}
-
-func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- system: {
- enabled: true,
- },
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- // foo does not have module-lib scope so it should fallback to system
- sdk_version: "module_current",
- }
- `)
-}
-
-func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- system: {
- enabled: true,
- },
- default_to_stubs: true,
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- // does not have sdk_version set, should fallback to module,
- // which will then fallback to system because the module scope
- // is not enabled.
- }
- `)
- // The baz library should depend on the system stubs jar.
- bazLibrary := result.ModuleForTests("baz", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
- t.Errorf("expected %q, found %#q", expected, actual)
- }
-}
-
func TestJavaSdkLibraryImport(t *testing.T) {
result := prepareForJavaTest.RunTestWithBp(t, `
java_library {
name: "foo",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs"],
sdk_version: "current",
}
java_library {
name: "foo.system",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs.system"],
sdk_version: "system_current",
}
java_library {
name: "foo.test",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs.test"],
sdk_version: "test_current",
}
@@ -918,11 +829,12 @@
fooModule := result.ModuleForTests("foo"+scope, "android_common")
javac := fooModule.Rule("javac")
- sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Rule("combineJar").Output
+ sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Output("combined/sdklib.stubs" + scope + ".jar").Output
android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], sdklibStubsJar.String())
}
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`prebuilt_sdklib.stubs`,
`prebuilt_sdklib.stubs.source.test`,
@@ -936,11 +848,7 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -989,11 +897,7 @@
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
preparer,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -1035,7 +939,7 @@
java_library {
name: "public",
srcs: ["a.java"],
- libs: ["sdklib"],
+ libs: ["sdklib.stubs"],
sdk_version: "current",
}
`)
@@ -1185,11 +1089,7 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib.source_preferred_using_legacy_flags", "sdklib.prebuilt_preferred_using_legacy_flags"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "my_mainline_module_contributions"),
).RunTestWithBp(t, bp)
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
@@ -1212,155 +1112,6 @@
}
}
-func TestJavaSdkLibraryEnforce(t *testing.T) {
- partitionToBpOption := func(partition string) string {
- switch partition {
- case "system":
- return ""
- case "vendor":
- return "soc_specific: true,"
- case "product":
- return "product_specific: true,"
- default:
- panic("Invalid partition group name: " + partition)
- }
- }
-
- type testConfigInfo struct {
- libraryType string
- fromPartition string
- toPartition string
- enforceProductInterface bool
- enforceJavaSdkLibraryCheck bool
- allowList []string
- }
-
- createPreparer := func(info testConfigInfo) android.FixturePreparer {
- bpFileTemplate := `
- java_library {
- name: "foo",
- srcs: ["foo.java"],
- libs: ["bar"],
- sdk_version: "current",
- %s
- }
-
- %s {
- name: "bar",
- srcs: ["bar.java"],
- sdk_version: "current",
- %s
- }
- `
-
- bpFile := fmt.Sprintf(bpFileTemplate,
- partitionToBpOption(info.fromPartition),
- info.libraryType,
- partitionToBpOption(info.toPartition))
-
- return android.GroupFixturePreparers(
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("bar"),
- android.FixtureWithRootAndroidBp(bpFile),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
- variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
- variables.InterPartitionJavaLibraryAllowList = info.allowList
- }),
- )
- }
-
- runTest := func(t *testing.T, info testConfigInfo, expectedErrorPattern string) {
- t.Run(fmt.Sprintf("%v", info), func(t *testing.T) {
- errorHandler := android.FixtureExpectsNoErrors
- if expectedErrorPattern != "" {
- errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
- }
- android.GroupFixturePreparers(
- prepareForJavaTest,
- createPreparer(info),
- ).
- ExtendWithErrorHandler(errorHandler).
- RunTest(t)
- })
- }
-
- errorMessage := "is not allowed across the partitions"
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: false,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: false,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- allowList: []string{"bar"},
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "product",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "product",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "vendor",
- toPartition: "product",
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-}
-
func TestJavaSdkLibraryDist(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaBuildComponents,
@@ -1371,11 +1122,7 @@
"sdklib_group_foo",
"sdklib_owner_foo",
"foo"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib_no_group",
@@ -1554,7 +1301,8 @@
// The foo.stubs.source should depend on bar-lib
fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
- android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
+ 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) {
@@ -1580,7 +1328,8 @@
// The foo.stubs.source should depend on bar-lib
fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
- android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
+ 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) {
@@ -1588,9 +1337,6 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
).RunTestWithBp(t, `
java_sdk_library {
name: "foo",
@@ -1609,36 +1355,30 @@
`)
testCases := []struct {
- scope *apiScope
- apiContributions []string
- fullApiSurfaceStub string
+ scope *apiScope
+ apiContributions []string
}{
{
- scope: apiScopePublic,
- apiContributions: []string{"foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_stubs_current",
+ scope: apiScopePublic,
+ apiContributions: []string{"foo.stubs.source.api.contribution"},
},
{
- scope: apiScopeSystem,
- apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_system_stubs_current",
+ scope: apiScopeSystem,
+ apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
},
{
- scope: apiScopeTest,
- apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_test_stubs_current",
+ scope: apiScopeTest,
+ apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
},
{
- scope: apiScopeModuleLib,
- apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
- fullApiSurfaceStub: "android_module_lib_stubs_current_full.from-text",
+ scope: apiScopeModuleLib,
+ apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
},
}
for _, c := range testCases {
m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary)
android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions)
- android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.fullApiSurfaceStub, *m.properties.Full_api_surface_stub)
}
}
@@ -1690,7 +1430,7 @@
name: "bar",
srcs: ["c.java", "b.java"],
libs: [
- "foo",
+ "foo.stubs",
],
uses_libs: [
"foo",
@@ -1708,9 +1448,6 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("foo"),
- android.FixtureModifyConfig(func(config android.Config) {
- config.SetApiLibraries([]string{"foo"})
- }),
).RunTestWithBp(t, `
aconfig_declarations {
name: "bar",
@@ -1743,18 +1480,15 @@
exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo")
// Check modules generation
- topLevelModule := result.ModuleForTests(exportableStubsLibraryModuleName, "android_common")
+ result.ModuleForTests(exportableStubsLibraryModuleName, "android_common")
result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common")
// Check static lib dependency
android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+
"exportable source stubs library module", true,
- CheckModuleHasDependency(t, result.TestContext, exportableStubsLibraryModuleName,
- "android_common", exportableSourceStubsLibraryModuleName),
+ CheckModuleHasDependencyWithTag(t, result.TestContext, exportableStubsLibraryModuleName,
+ "android_common", staticLibTag, exportableSourceStubsLibraryModuleName),
)
- android.AssertArrayString(t, "exportable source stub library is a static lib of the"+
- "top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName},
- topLevelModule.Module().(*Library).properties.Static_libs)
}
// For java libraries depending on java_sdk_library(_import) via libs, assert that
@@ -1791,7 +1525,7 @@
name: "mymodule",
srcs: ["a.java"],
sdk_version: "current",
- libs: ["sdklib",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
+ libs: ["sdklib.stubs",], // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
}
`
@@ -1799,12 +1533,8 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- // We can use any of the apex contribution build flags from build/soong/android/config.go#mainlineApexContributionBuildFlags here
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
- }
- }),
+ // We can use any of the apex contribution build flags from build/soong/android/config.go#mainlineApexContributionBuildFlags here
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "my_mainline_module_contributions"),
)
result := fixture.RunTestWithBp(t, bp)
@@ -1887,11 +1617,7 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib", "sdklib.v1", "sdklib.v2"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "my_mainline_module_contributions"),
)
for _, tc := range testCases {
@@ -1904,3 +1630,147 @@
android.AssertStringListContains(t, "Could not find the expected stub on classpath", inputs, tc.expectedStubPath)
}
}
+
+func TestStubLinkType(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `module "baz" variant "android_common": compiles against system API, but dependency `+
+ `"bar.stubs.system" is compiling against module API. In order to fix this, `+
+ `consider adjusting sdk_version: OR platform_apis: property of the source or `+
+ `target module so that target module is built with the same or smaller API set `+
+ `when compared to the source.`),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ java_library {
+ name: "bar.stubs.system",
+ srcs: ["a.java"],
+ sdk_version: "module_current",
+ is_stubs_module: false,
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["b.java"],
+ libs: [
+ "foo.stubs.system",
+ "bar.stubs.system",
+ ],
+ sdk_version: "system_current",
+ }
+ `)
+}
+
+func TestSdkLibDirectDependency(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo", "bar"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern([]string{
+ `module "baz" variant "android_common": cannot depend directly on java_sdk_library ` +
+ `"foo"; try depending on "foo.stubs", or "foo.impl" instead`,
+ `module "baz" variant "android_common": cannot depend directly on java_sdk_library ` +
+ `"prebuilt_bar"; try depending on "bar.stubs", or "bar.impl" instead`,
+ }),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library_import {
+ name: "foo",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library_import {
+ name: "bar",
+ prefer: true,
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["b.java"],
+ libs: [
+ "foo",
+ "bar",
+ ],
+ }
+ `)
+}
+
+func TestSdkLibDirectDependencyWithPrebuiltSdk(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = intPtr(34)
+ variables.Platform_sdk_codename = stringPtr("VanillaIceCream")
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ variables.Platform_systemsdk_versions = []string{"33", "34", "VanillaIceCream"}
+ variables.DeviceSystemSdkVersions = []string{"VanillaIceCream"}
+ }),
+ FixtureWithPrebuiltApis(map[string][]string{
+ "33": {"foo"},
+ "34": {"foo"},
+ "35": {"foo"},
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(
+ `module "baz" variant "android_common": cannot depend directly on java_sdk_library "foo"; `+
+ `try depending on "sdk_public_33_foo", "sdk_system_33_foo", "sdk_test_33_foo", `+
+ `"sdk_module-lib_33_foo", or "sdk_system-server_33_foo" instead`),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["b.java"],
+ libs: [
+ "foo",
+ ],
+ sdk_version: "system_33",
+ }
+ `)
+}
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 9e8ba6e..9bfe6a2 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -388,22 +388,29 @@
},
}
+ t.Parallel()
t.Run("basic", func(t *testing.T) {
- testClasspathTestCases(t, classpathTestcases, false)
+ t.Parallel()
+ testClasspathTestCases(t, classpathTestcases, false, false)
})
t.Run("Always_use_prebuilt_sdks=true", func(t *testing.T) {
- testClasspathTestCases(t, classpathTestcases, true)
+ testClasspathTestCases(t, classpathTestcases, true, false)
+ })
+
+ t.Run("UseTransitiveJarsInClasspath", func(t *testing.T) {
+ testClasspathTestCases(t, classpathTestcases, false, true)
})
}
-func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase, alwaysUsePrebuiltSdks bool) {
+func testClasspathTestCases(t *testing.T, classpathTestcases []classpathTestCase, alwaysUsePrebuiltSdks, useTransitiveJarsInClasspath bool) {
for _, testcase := range classpathTestcases {
if testcase.forAlwaysUsePrebuiltSdks != nil && *testcase.forAlwaysUsePrebuiltSdks != alwaysUsePrebuiltSdks {
continue
}
t.Run(testcase.name, func(t *testing.T) {
+ t.Parallel()
moduleType := "java_library"
if testcase.moduleType != "" {
moduleType = testcase.moduleType
@@ -434,7 +441,14 @@
convertModulesToPaths := func(cp []string) []string {
ret := make([]string, len(cp))
for i, e := range cp {
- ret[i] = defaultModuleToPath(e)
+ 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")
+ }
}
return ret
}
@@ -528,6 +542,9 @@
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
})
}
+ if useTransitiveJarsInClasspath {
+ preparer = PrepareForTestWithTransitiveClasspathEnabled
+ }
fixtureFactory := android.GroupFixturePreparers(
prepareForJavaTest,
diff --git a/java/system_modules.go b/java/system_modules.go
index 8e2d5d8..d9430b2 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -120,14 +120,19 @@
return module
}
-type SystemModulesProvider interface {
- HeaderJars() android.Paths
- OutputDirAndDeps() (android.Path, android.Paths)
+type SystemModulesProviderInfo struct {
+ // The aggregated header jars from all jars specified in the libs property.
+ // Used when system module is added as a dependency to bootclasspath.
+ HeaderJars android.Paths
+
+ OutputDir android.Path
+ OutputDirDeps android.Paths
+
+ // depset of header jars for this module and all transitive static dependencies
+ TransitiveStaticLibsHeaderJars *android.DepSet[android.Path]
}
-var _ SystemModulesProvider = (*SystemModules)(nil)
-
-var _ SystemModulesProvider = (*systemModulesImport)(nil)
+var SystemModulesProvider = blueprint.NewProvider[*SystemModulesProviderInfo]()
type SystemModules struct {
android.ModuleBase
@@ -135,9 +140,6 @@
properties SystemModulesProperties
- // The aggregated header jars from all jars specified in the libs property.
- // Used when system module is added as a dependency to bootclasspath.
- headerJars android.Paths
outputDir android.Path
outputDeps android.Paths
}
@@ -147,28 +149,27 @@
Libs []string
}
-func (system *SystemModules) HeaderJars() android.Paths {
- return system.headerJars
-}
-
-func (system *SystemModules) OutputDirAndDeps() (android.Path, android.Paths) {
- if system.outputDir == nil || len(system.outputDeps) == 0 {
- panic("Missing directory for system module dependency")
- }
- return system.outputDir, system.outputDeps
-}
-
func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var jars android.Paths
+ var transitiveStaticLibsHeaderJars []*android.DepSet[android.Path]
ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
- dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
- jars = append(jars, dep.HeaderJars...)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ jars = append(jars, dep.HeaderJars...)
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveStaticLibsHeaderJars = append(transitiveStaticLibsHeaderJars, dep.TransitiveStaticLibsHeaderJars)
+ }
+ }
})
- system.headerJars = jars
-
system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
+
+ android.SetProvider(ctx, SystemModulesProvider, &SystemModulesProviderInfo{
+ HeaderJars: jars,
+ OutputDir: system.outputDir,
+ OutputDirDeps: system.outputDeps,
+ TransitiveStaticLibsHeaderJars: android.NewDepSet(android.PREORDER, nil, transitiveStaticLibsHeaderJars),
+ })
}
// ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
@@ -310,3 +311,11 @@
propertySet.AddPropertyWithTag("libs", p.Libs, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
}
}
+
+// implement the following interface for IDE completion.
+var _ android.IDEInfo = (*SystemModules)(nil)
+
+func (s *SystemModules) IDEInfo(ctx android.BaseModuleContext, ideInfo *android.IdeInfo) {
+ ideInfo.Deps = append(ideInfo.Deps, s.properties.Libs...)
+ ideInfo.Libs = append(ideInfo.Libs, s.properties.Libs...)
+}
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 336dd21..b05b0e4 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -25,7 +25,7 @@
paths := []string{}
for _, moduleName := range moduleNames {
module := result.Module(moduleName, "android_common")
- info, _ := android.SingletonModuleProvider(result, module, JavaInfoProvider)
+ info, _ := android.OtherModuleProvider(result, module, JavaInfoProvider)
paths = append(paths, info.HeaderJars.RelativeToTop().Strings()...)
}
return paths
@@ -182,11 +182,7 @@
for _, tc := range testCases {
res := android.GroupFixturePreparers(
prepareForJavaTest,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", "myapex_contributions"),
).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
// check that rdep gets the correct variation of system_modules
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index bad2cf1..924abd4 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -216,6 +216,11 @@
return tag == systemServerClasspathFragmentContentDepTag
}
+// The dexpreopt artifacts of apex system server jars are installed onto system image.
+func (s systemServerClasspathFragmentContentDependencyTag) InstallDepNeeded() bool {
+ return true
+}
+
func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
_, isSourceModule := module.(*SystemServerClasspathModule)
@@ -234,7 +239,7 @@
}
// Collect information for opening IDE project files in java/jdeps.go.
-func (s *SystemServerClasspathModule) IDEInfo(dpInfo *android.IdeInfo) {
+func (s *SystemServerClasspathModule) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, s.properties.Contents...)
dpInfo.Deps = append(dpInfo.Deps, s.properties.Standalone_contents...)
}
diff --git a/java/test_spec_test.go b/java/test_spec_test.go
index 4144dad..f0a5fdb 100644
--- a/java/test_spec_test.go
+++ b/java/test_spec_test.go
@@ -32,7 +32,7 @@
module := result.ModuleForTests("module-name", "")
// Check that the provider has the right contents
- data, _ := android.SingletonModuleProvider(result, module.Module(), soongTesting.TestSpecProviderKey)
+ data, _ := android.OtherModuleProvider(result, module.Module(), soongTesting.TestSpecProviderKey)
if !strings.HasSuffix(
data.IntermediatePath.String(), "/intermediateTestSpecMetadata.pb",
) {
diff --git a/java/testing.go b/java/testing.go
index 7a42e4c..988514d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -30,6 +30,7 @@
)
const defaultJavaDir = "default/java"
+const testDefaultUpdatableModuleVersion = "340090000"
// Test fixture preparer that will register most java build components.
//
@@ -61,6 +62,7 @@
// Needed for the global lint checks provided from frameworks/base
"prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar": nil,
}.AddToFixture(),
+ android.PrepareForTestWithBuildFlag("RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION", testDefaultUpdatableModuleVersion),
)
var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers(
@@ -184,6 +186,10 @@
host_supported: true,
srcs: ["Test.java"],
sdk_version: "current",
+ apex_available: [
+ "//apex_available:anyapex",
+ "//apex_available:platform",
+ ],
}
`)),
)
@@ -384,7 +390,6 @@
RegisterStubsBuildComponents(ctx)
RegisterSystemModulesBuildComponents(ctx)
registerSystemserverClasspathBuildComponents(ctx)
- registerLintBuildComponents(ctx)
android.RegisterApexContributionsBuildComponents(ctx)
}
@@ -408,7 +413,6 @@
"core.current.stubs",
"legacy.core.platform.api.stubs",
"stable.core.platform.api.stubs",
-
"android_stubs_current_exportable",
"android_system_stubs_current_exportable",
"android_test_stubs_current_exportable",
@@ -416,7 +420,6 @@
"android_system_server_stubs_current_exportable",
"core.current.stubs.exportable",
"legacy.core.platform.api.stubs.exportable",
-
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
@@ -424,6 +427,7 @@
"stub-annotations",
"aconfig-annotations-lib",
+ "aconfig_storage_reader_java",
"unsupportedappusage",
}
@@ -435,6 +439,7 @@
sdk_version: "none",
system_modules: "stable-core-platform-api-stubs-system-modules",
compile_dex: true,
+ is_stubs_module: true,
}
`, extra)
}
@@ -486,21 +491,17 @@
}
extraApiLibraryModules := map[string]droidstubsStruct{
- "android_stubs_current.from-text": publicDroidstubs,
- "android_system_stubs_current.from-text": systemDroidstubs,
- "android_test_stubs_current.from-text": testDroidstubs,
- "android_module_lib_stubs_current.from-text": moduleLibDroidstubs,
- "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs,
- "android_system_server_stubs_current.from-text": systemServerDroidstubs,
- "core.current.stubs.from-text": publicDroidstubs,
- "legacy.core.platform.api.stubs.from-text": publicDroidstubs,
- "stable.core.platform.api.stubs.from-text": publicDroidstubs,
- "core-lambda-stubs.from-text": publicDroidstubs,
- "android-non-updatable.stubs.from-text": publicDroidstubs,
- "android-non-updatable.stubs.system.from-text": systemDroidstubs,
- "android-non-updatable.stubs.test.from-text": testDroidstubs,
- "android-non-updatable.stubs.module_lib.from-text": moduleLibDroidstubs,
- "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs,
+ "android_stubs_current.from-text": publicDroidstubs,
+ "android_system_stubs_current.from-text": systemDroidstubs,
+ "android_test_stubs_current.from-text": testDroidstubs,
+ "android_module_lib_stubs_current.from-text": moduleLibDroidstubs,
+ "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs,
+ "android_system_server_stubs_current.from-text": systemServerDroidstubs,
+ "core.current.stubs.from-text": publicDroidstubs,
+ "legacy.core.platform.api.stubs.from-text": publicDroidstubs,
+ "stable.core.platform.api.stubs.from-text": publicDroidstubs,
+ "core-lambda-stubs.from-text": publicDroidstubs,
+ "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs,
}
for _, droidstubs := range droidstubsStructs {
@@ -529,6 +530,8 @@
name: "%s",
api_contributions: ["%s"],
stubs_type: "everything",
+ sdk_version: "none",
+ system_modules: "none",
}
`, libName, droidstubs.name+".api.contribution")
}
@@ -544,6 +547,16 @@
},
compile_dex: true,
}
+ java_library {
+ name: "framework-minus-apex",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "stable-core-platform-api-stubs-system-modules",
+ aidl: {
+ export_include_dirs: ["framework/aidl"],
+ },
+ compile_dex: true,
+ }
android_app {
name: "framework-res",
@@ -571,6 +584,7 @@
name: "%[1]s-lib",
sdk_version: "none",
system_modules: "none",
+ srcs: ["a.java"],
}
`, extra)
}
@@ -622,6 +636,18 @@
return false
}
+// 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()
+ found := false
+ ctx.VisitDirectDepsWithTags(module, func(m blueprint.Module, tag blueprint.DependencyTag) {
+ if tag == desiredTag && m.Name() == expected {
+ found = true
+ }
+ })
+ return found
+}
+
// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by
// the platform-bootclasspath module.
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
@@ -634,7 +660,7 @@
func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) {
t.Helper()
p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
- info, _ := android.SingletonModuleProvider(result, p, ClasspathFragmentProtoContentInfoProvider)
+ info, _ := android.OtherModuleProvider(result, p, ClasspathFragmentProtoContentInfoProvider)
android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated)
android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String())
@@ -654,7 +680,7 @@
func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
name := module.Name()
var apex string
- apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
+ apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
apex = "platform"
} else {
@@ -770,3 +796,5 @@
config.installDir = installDir
})
}
+
+var PrepareForTestWithTransitiveClasspathEnabled = android.PrepareForTestWithBuildFlag("RELEASE_USE_TRANSITIVE_JARS_IN_CLASSPATH", "true")
diff --git a/kernel/prebuilt_kernel_modules_test.go b/kernel/prebuilt_kernel_modules_test.go
index 90b9886..7b81869 100644
--- a/kernel/prebuilt_kernel_modules_test.go
+++ b/kernel/prebuilt_kernel_modules_test.go
@@ -49,7 +49,8 @@
}
var actual []string
- for _, ps := range ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().PackagingSpecs() {
+ for _, ps := range android.OtherModuleProviderOrDefault(
+ ctx, ctx.ModuleForTests("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 87c0814..05b99fd 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -98,6 +98,7 @@
builder.Command().
BuiltTool("conv_linker_config").
Flag("proto").
+ Flag("--force").
FlagWithInput("-s ", input).
FlagWithOutput("-o ", interimOutput)
@@ -105,7 +106,8 @@
var provideLibs []string
for _, m := range provideModules {
if c, ok := m.(*cc.Module); ok && (cc.IsStubTarget(c) || c.HasLlndkStubs()) {
- for _, ps := range c.PackagingSpecs() {
+ for _, ps := range android.OtherModuleProviderOrDefault(
+ ctx, c, android.InstallFilesProvider).PackagingSpecs {
provideLibs = append(provideLibs, ps.FileName())
}
}
diff --git a/linkerconfig/proto/Android.bp b/linkerconfig/proto/Android.bp
index 754e7bf..a930502 100644
--- a/linkerconfig/proto/Android.bp
+++ b/linkerconfig/proto/Android.bp
@@ -15,6 +15,7 @@
"//apex_available:platform",
"//apex_available:anyapex",
],
+ visibility: ["//system/linkerconfig"],
}
python_library_host {
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 78ab771..2e408b7 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -72,6 +72,7 @@
"add_soong_config_namespace": &simpleCallParser{name: baseName + ".soong_config_namespace", returnType: starlarkTypeVoid, addGlobals: true},
"add_soong_config_var_value": &simpleCallParser{name: baseName + ".soong_config_set", returnType: starlarkTypeVoid, addGlobals: true},
soongConfigAssign: &simpleCallParser{name: baseName + ".soong_config_set", returnType: starlarkTypeVoid, addGlobals: true},
+ "soong_config_set_bool": &simpleCallParser{name: baseName + ".soong_config_set_bool", returnType: starlarkTypeVoid, addGlobals: true},
soongConfigAppend: &simpleCallParser{name: baseName + ".soong_config_append", returnType: starlarkTypeVoid, addGlobals: true},
"soong_config_get": &simpleCallParser{name: baseName + ".soong_config_get", returnType: starlarkTypeString, addGlobals: true},
"add-to-product-copy-files-if-exists": &simpleCallParser{name: baseName + ".copy_if_exists", returnType: starlarkTypeList},
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 0c4d213..c295c40 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -853,6 +853,7 @@
$(call add_soong_config_namespace,snsconfig)
$(call add_soong_config_var_value,snsconfig,imagetype,odm_image)
$(call soong_config_set, snsconfig, foo, foo_value)
+$(call soong_config_set_bool, snsconfig, bar, true)
$(call soong_config_append, snsconfig, bar, bar_value)
PRODUCT_COPY_FILES := $(call copy-files,$(wildcard foo*.mk),etc)
PRODUCT_COPY_FILES := $(call product-copy-files-by-pattern,from/%,to/%,a b c)
@@ -880,6 +881,7 @@
rblf.soong_config_namespace(g, "snsconfig")
rblf.soong_config_set(g, "snsconfig", "imagetype", "odm_image")
rblf.soong_config_set(g, "snsconfig", "foo", "foo_value")
+ rblf.soong_config_set_bool(g, "snsconfig", "bar", "true")
rblf.soong_config_append(g, "snsconfig", "bar", "bar_value")
cfg["PRODUCT_COPY_FILES"] = rblf.copy_files(rblf.expand_wildcard("foo*.mk"), "etc")
cfg["PRODUCT_COPY_FILES"] = rblf.product_copy_files_by_pattern("from/%", "to/%", "a b c")
diff --git a/multitree/Android.bp b/multitree/Android.bp
deleted file mode 100644
index 78c4962..0000000
--- a/multitree/Android.bp
+++ /dev/null
@@ -1,20 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-bootstrap_go_package {
- name: "soong-multitree",
- pkgPath: "android/soong/multitree",
- deps: [
- "blueprint",
- "soong-android",
- ],
- srcs: [
- "api_imports.go",
- "api_surface.go",
- "export.go",
- "metadata.go",
- "import.go",
- ],
- pluginFor: ["soong_build"],
-}
diff --git a/multitree/api_imports.go b/multitree/api_imports.go
deleted file mode 100644
index 51b9e07..0000000
--- a/multitree/api_imports.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2022 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 multitree
-
-import (
- "android/soong/android"
- "strings"
-
- "github.com/google/blueprint"
-)
-
-var (
- apiImportNameSuffix = ".apiimport"
-)
-
-func init() {
- RegisterApiImportsModule(android.InitRegistrationContext)
- android.RegisterMakeVarsProvider(pctx, makeVarsProvider)
-}
-
-func RegisterApiImportsModule(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("api_imports", apiImportsFactory)
-}
-
-type ApiImports struct {
- android.ModuleBase
- properties apiImportsProperties
-}
-
-type apiImportsProperties struct {
- Shared_libs []string // List of C shared libraries from API surfaces
- Header_libs []string // List of C header libraries from API surfaces
- Apex_shared_libs []string // List of C shared libraries with APEX stubs
-}
-
-// 'api_imports' is a module which describes modules available from API surfaces.
-// This module is required to get the list of all imported API modules, because
-// it is discouraged to loop and fetch all modules from its type information. The
-// only module with name 'api_imports' will be used from the build.
-func apiImportsFactory() android.Module {
- module := &ApiImports{}
- module.AddProperties(&module.properties)
- android.InitAndroidModule(module)
- return module
-}
-
-func (imports *ApiImports) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // ApiImport module does not generate any build actions
-}
-
-type ApiImportInfo struct {
- SharedLibs, HeaderLibs, ApexSharedLibs map[string]string
-}
-
-var ApiImportsProvider = blueprint.NewMutatorProvider[ApiImportInfo]("deps")
-
-// Store module lists into ApiImportInfo and share it over mutator provider.
-func (imports *ApiImports) DepsMutator(ctx android.BottomUpMutatorContext) {
- generateNameMapWithSuffix := func(names []string) map[string]string {
- moduleNameMap := make(map[string]string)
- for _, name := range names {
- moduleNameMap[name] = name + apiImportNameSuffix
- }
-
- return moduleNameMap
- }
-
- sharedLibs := generateNameMapWithSuffix(imports.properties.Shared_libs)
- headerLibs := generateNameMapWithSuffix(imports.properties.Header_libs)
- apexSharedLibs := generateNameMapWithSuffix(imports.properties.Apex_shared_libs)
-
- android.SetProvider(ctx, ApiImportsProvider, ApiImportInfo{
- SharedLibs: sharedLibs,
- HeaderLibs: headerLibs,
- ApexSharedLibs: apexSharedLibs,
- })
-}
-
-func GetApiImportSuffix() string {
- return apiImportNameSuffix
-}
-
-func makeVarsProvider(ctx android.MakeVarsContext) {
- ctx.VisitAllModules(func(m android.Module) {
- if i, ok := m.(*ApiImports); ok {
- ctx.Strict("API_IMPORTED_SHARED_LIBRARIES", strings.Join(i.properties.Shared_libs, " "))
- ctx.Strict("API_IMPORTED_HEADER_LIBRARIES", strings.Join(i.properties.Header_libs, " "))
- }
- })
-}
diff --git a/multitree/api_surface.go b/multitree/api_surface.go
deleted file mode 100644
index 0f605d8..0000000
--- a/multitree/api_surface.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package multitree
-
-import (
- "android/soong/android"
- "github.com/google/blueprint"
-)
-
-var (
- pctx = android.NewPackageContext("android/soong/multitree")
-)
-
-func init() {
- RegisterApiSurfaceBuildComponents(android.InitRegistrationContext)
-}
-
-var PrepareForTestWithApiSurface = android.FixtureRegisterWithContext(RegisterApiSurfaceBuildComponents)
-
-func RegisterApiSurfaceBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("api_surface", ApiSurfaceFactory)
-}
-
-type ApiSurface struct {
- android.ModuleBase
- ExportableModuleBase
- properties apiSurfaceProperties
-
- taggedOutputs map[string]android.Paths
-}
-
-type apiSurfaceProperties struct {
- Contributions []string
-}
-
-func ApiSurfaceFactory() android.Module {
- module := &ApiSurface{}
- module.AddProperties(&module.properties)
- android.InitAndroidModule(module)
- InitExportableModule(module)
- return module
-}
-
-func (surface *ApiSurface) DepsMutator(ctx android.BottomUpMutatorContext) {
- if surface.properties.Contributions != nil {
- ctx.AddVariationDependencies(nil, nil, surface.properties.Contributions...)
- }
-
-}
-func (surface *ApiSurface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- contributionFiles := make(map[string]android.Paths)
- var allOutputs android.Paths
- ctx.WalkDeps(func(child, parent android.Module) bool {
- if contribution, ok := child.(ApiContribution); ok {
- copied := contribution.CopyFilesWithTag(ctx)
- for tag, files := range copied {
- contributionFiles[child.Name()+"#"+tag] = files
- }
- for _, paths := range copied {
- allOutputs = append(allOutputs, paths...)
- }
- return false // no transitive dependencies
- }
- return false
- })
-
- // phony target
- ctx.Build(pctx, android.BuildParams{
- Rule: blueprint.Phony,
- Output: android.PathForPhony(ctx, ctx.ModuleName()),
- Inputs: allOutputs,
- })
-
- surface.taggedOutputs = contributionFiles
-
- ctx.SetOutputFiles(allOutputs, "")
-}
-
-func (surface *ApiSurface) TaggedOutputs() map[string]android.Paths {
- return surface.taggedOutputs
-}
-
-func (surface *ApiSurface) Exportable() bool {
- return true
-}
-
-var _ Exportable = (*ApiSurface)(nil)
-
-type ApiContribution interface {
- // copy files necessaryt to construct an API surface
- // For C, it will be map.txt and .h files
- // For Java, it will be api.txt
- CopyFilesWithTag(ctx android.ModuleContext) map[string]android.Paths // output paths
-
- // Generate Android.bp in out/ to use the exported .txt files
- // GenerateBuildFiles(ctx ModuleContext) Paths //output paths
-}
diff --git a/multitree/export.go b/multitree/export.go
deleted file mode 100644
index 8be8f70..0000000
--- a/multitree/export.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2022 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 multitree
-
-import (
- "android/soong/android"
-
- "github.com/google/blueprint/proptools"
-)
-
-type moduleExportProperty struct {
- // True if the module is exported to the other components in a multi-tree.
- // Any components in the multi-tree can import this module to use.
- Export *bool
-}
-
-type ExportableModuleBase struct {
- properties moduleExportProperty
-}
-
-type Exportable interface {
- // Properties for the exporable module.
- exportableModuleProps() *moduleExportProperty
-
- // Check if this module can be exported.
- // If this returns false, the module will not be exported regardless of the 'export' value.
- Exportable() bool
-
- // Returns 'true' if this module has 'export: true'
- // This module will not be exported if it returns 'false' to 'Exportable()' interface even if
- // it has 'export: true'.
- IsExported() bool
-
- // Map from tags to outputs.
- // Each module can tag their outputs for convenience.
- TaggedOutputs() map[string]android.Paths
-}
-
-type ExportableModule interface {
- android.Module
- Exportable
-}
-
-func InitExportableModule(module ExportableModule) {
- module.AddProperties(module.exportableModuleProps())
-}
-
-func (m *ExportableModuleBase) exportableModuleProps() *moduleExportProperty {
- return &m.properties
-}
-
-func (m *ExportableModuleBase) IsExported() bool {
- return proptools.Bool(m.properties.Export)
-}
diff --git a/multitree/import.go b/multitree/import.go
deleted file mode 100644
index 1e5c421..0000000
--- a/multitree/import.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2022 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 multitree
-
-import (
- "android/soong/android"
-)
-
-var (
- nameSuffix = ".imported"
-)
-
-type MultitreeImportedModuleInterface interface {
- GetMultitreeImportedModuleName() string
-}
-
-func init() {
- android.RegisterModuleType("imported_filegroup", importedFileGroupFactory)
-
- android.PreArchMutators(RegisterMultitreePreArchMutators)
-}
-
-type importedFileGroupProperties struct {
- // Imported modules from the other components in a multi-tree
- Imported []string
-}
-
-type importedFileGroup struct {
- android.ModuleBase
-
- properties importedFileGroupProperties
- srcs android.Paths
-}
-
-func (ifg *importedFileGroup) Name() string {
- return ifg.BaseModuleName() + nameSuffix
-}
-
-func importedFileGroupFactory() android.Module {
- module := &importedFileGroup{}
- module.AddProperties(&module.properties)
-
- android.InitAndroidModule(module)
- return module
-}
-
-var _ MultitreeImportedModuleInterface = (*importedFileGroup)(nil)
-
-func (ifg *importedFileGroup) GetMultitreeImportedModuleName() string {
- // The base module name of the imported filegroup is used as the imported module name
- return ifg.BaseModuleName()
-}
-
-var _ android.SourceFileProducer = (*importedFileGroup)(nil)
-
-func (ifg *importedFileGroup) Srcs() android.Paths {
- return ifg.srcs
-}
-
-func (ifg *importedFileGroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // srcs from this module must not be used. Adding a dot path to avoid the empty
- // source failure. Still soong returns error when a module wants to build against
- // this source, which is intended.
- ifg.srcs = android.PathsForModuleSrc(ctx, []string{"."})
-}
-
-func RegisterMultitreePreArchMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("multitree_imported_rename", MultitreeImportedRenameMutator).Parallel()
-}
-
-func MultitreeImportedRenameMutator(ctx android.BottomUpMutatorContext) {
- if m, ok := ctx.Module().(MultitreeImportedModuleInterface); ok {
- name := m.GetMultitreeImportedModuleName()
- if !ctx.OtherModuleExists(name) {
- // Provide an empty filegroup not to break the build while updating the metadata.
- // In other cases, soong will report an error to guide users to run 'm update-meta'
- // first.
- if !ctx.Config().TargetMultitreeUpdateMeta() {
- ctx.ModuleErrorf("\"%s\" filegroup must be imported.\nRun 'm update-meta' first to import the filegroup.", name)
- }
- ctx.Rename(name)
- }
- }
-}
diff --git a/multitree/metadata.go b/multitree/metadata.go
deleted file mode 100644
index 0eb0efc..0000000
--- a/multitree/metadata.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2022 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 multitree
-
-import (
- "android/soong/android"
- "encoding/json"
-)
-
-func init() {
- android.RegisterParallelSingletonType("update-meta", UpdateMetaSingleton)
-}
-
-func UpdateMetaSingleton() android.Singleton {
- return &updateMetaSingleton{}
-}
-
-type jsonImported struct {
- FileGroups map[string][]string `json:",omitempty"`
-}
-
-type metadataJsonFlags struct {
- Imported jsonImported `json:",omitempty"`
- Exported map[string][]string `json:",omitempty"`
-}
-
-type updateMetaSingleton struct {
- importedModules []string
- generatedMetadataFile android.OutputPath
-}
-
-func (s *updateMetaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- metadata := metadataJsonFlags{
- Imported: jsonImported{
- FileGroups: make(map[string][]string),
- },
- Exported: make(map[string][]string),
- }
- ctx.VisitAllModules(func(module android.Module) {
- if ifg, ok := module.(*importedFileGroup); ok {
- metadata.Imported.FileGroups[ifg.BaseModuleName()] = ifg.properties.Imported
- }
- if e, ok := module.(ExportableModule); ok {
- if e.IsExported() && e.Exportable() {
- for tag, files := range e.TaggedOutputs() {
- // TODO(b/219846705): refactor this to a dictionary
- metadata.Exported[e.Name()+":"+tag] = append(metadata.Exported[e.Name()+":"+tag], files.Strings()...)
- }
- }
- }
- })
- jsonStr, err := json.Marshal(metadata)
- if err != nil {
- ctx.Errorf(err.Error())
- }
- s.generatedMetadataFile = android.PathForOutput(ctx, "multitree", "metadata.json")
- android.WriteFileRule(ctx, s.generatedMetadataFile, string(jsonStr))
-}
-
-func (s *updateMetaSingleton) MakeVars(ctx android.MakeVarsContext) {
- ctx.Strict("MULTITREE_METADATA", s.generatedMetadataFile.String())
-}
diff --git a/phony/Android.bp b/phony/Android.bp
index db5efc9..2e250c6 100644
--- a/phony/Android.bp
+++ b/phony/Android.bp
@@ -13,4 +13,5 @@
"phony.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/phony/phony.go b/phony/phony.go
index 5505a3a..807b95b 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -112,7 +112,7 @@
}
func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- p.phonyDepsModuleNames = p.properties.Phony_deps.GetOrDefault(p.ConfigurableEvaluator(ctx), nil)
+ p.phonyDepsModuleNames = p.properties.Phony_deps.GetOrDefault(ctx, nil)
}
func (p *PhonyRule) AndroidMk() android.AndroidMkData {
diff --git a/python/python.go b/python/python.go
index 8726f02..01ac86c 100644
--- a/python/python.go
+++ b/python/python.go
@@ -264,10 +264,9 @@
variants = append(variants, pyVersion3)
}
if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
- if !ctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() &&
- ctx.ModuleName() != "py2-cmd" &&
+ 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. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration")
+ ctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3.")
}
variants = append(variants, pyVersion2)
}
diff --git a/response/Android.bp b/response/Android.bp
index e19981f..2f319fe 100644
--- a/response/Android.bp
+++ b/response/Android.bp
@@ -13,4 +13,8 @@
testSrcs: [
"response_test.go",
],
+ visibility: [
+ "//build/make/tools/compliance",
+ "//build/soong:__subpackages__",
+ ],
}
diff --git a/rust/Android.bp b/rust/Android.bp
index 53c9462..781f325 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -61,4 +61,5 @@
"test_test.go",
],
pluginFor: ["soong_build"],
+ visibility: ["//visibility:public"],
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index f1579cc..abb5181 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -198,18 +198,20 @@
cflags = append(cflags, "-D__ANDROID_VNDK__")
if ctx.RustModule().InVendor() {
cflags = append(cflags, "-D__ANDROID_VENDOR__")
-
- vendorApiLevel := ctx.Config().VendorApiLevel()
- if vendorApiLevel == "" {
- // TODO(b/314036847): This is a fallback for UDC targets.
- // This must be a build failure when UDC is no longer built
- // from this source tree.
- vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
- }
- cflags = append(cflags, "-D__ANDROID_VENDOR_API__="+vendorApiLevel)
} else if ctx.RustModule().InProduct() {
cflags = append(cflags, "-D__ANDROID_PRODUCT__")
}
+
+ // Define __ANDROID_VENDOR_API__ for both product and vendor variants
+ // because they both use the same LLNDK libraries.
+ vendorApiLevel := ctx.Config().VendorApiLevel()
+ if vendorApiLevel == "" {
+ // TODO(b/314036847): This is a fallback for UDC targets.
+ // This must be a build failure when UDC is no longer built
+ // from this source tree.
+ vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
+ }
+ cflags = append(cflags, "-D__ANDROID_VENDOR_API__="+vendorApiLevel)
}
if ctx.RustModule().InRecovery() {
@@ -285,7 +287,7 @@
if isCpp {
cflags = append(cflags, "-x c++")
// Add any C++ only flags.
- cflags = append(cflags, esc(b.ClangProperties.Cppflags)...)
+ cflags = append(cflags, esc(b.ClangProperties.Cppflags.GetOrDefault(ctx, nil))...)
} else {
cflags = append(cflags, "-x c")
}
@@ -364,7 +366,7 @@
ClangProperties: cc.RustBindgenClangProperties{},
}
- module := NewSourceProviderModule(hod, bindgen, false, true)
+ module := NewSourceProviderModule(hod, bindgen, false, false)
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
type stub_props struct {
@@ -393,8 +395,8 @@
deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
}
- deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
- deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs...)
- deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs...)
+ deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs.GetOrDefault(ctx, nil)...)
+ deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs.GetOrDefault(ctx, nil)...)
+ deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs.GetOrDefault(ctx, nil)...)
return deps
}
diff --git a/rust/clippy.go b/rust/clippy.go
index 6f0ed7f..426fd73 100644
--- a/rust/clippy.go
+++ b/rust/clippy.go
@@ -38,11 +38,14 @@
}
func (c *clippy) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
- enabled, lints, err := config.ClippyLintsForDir(ctx.ModuleDir(), c.Properties.Clippy_lints)
+ dirEnabled, lints, err := config.ClippyLintsForDir(ctx.ModuleDir(), c.Properties.Clippy_lints)
if err != nil {
ctx.PropertyErrorf("clippy_lints", err.Error())
}
- flags.Clippy = enabled
+
+ envDisable := ctx.Config().IsEnvTrue("SOONG_DISABLE_CLIPPY")
+
+ flags.Clippy = dirEnabled && !envDisable
flags.ClippyFlags = append(flags.ClippyFlags, lints)
return flags, deps
}
diff --git a/rust/compiler.go b/rust/compiler.go
index a2546a1..5bce16b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -39,13 +39,13 @@
initialize(ctx ModuleContext)
compilerFlags(ctx ModuleContext, flags Flags) Flags
cfgFlags(ctx ModuleContext, flags Flags) Flags
- featureFlags(ctx ModuleContext, flags Flags) Flags
+ featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags
compilerProps() []interface{}
compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput
compilerDeps(ctx DepsContext, deps Deps) Deps
crateName() string
edition() string
- features() []string
+ features(ctx android.ConfigurableEvaluatorContext, module *Module) []string
rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath
Thinlto() bool
@@ -194,7 +194,7 @@
Crate_name string `android:"arch_variant"`
// list of features to enable for this crate
- Features []string `android:"arch_variant"`
+ Features proptools.Configurable[[]string] `android:"arch_variant"`
// list of configuration options to enable for this crate. To enable features, use the "features" property.
Cfgs proptools.Configurable[[]string] `android:"arch_variant"`
@@ -346,22 +346,23 @@
return flags
}
-func (compiler *baseCompiler) features() []string {
- return compiler.Properties.Features
+func (compiler *baseCompiler) features(ctx android.ConfigurableEvaluatorContext, module *Module) []string {
+ eval := module.ConfigurableEvaluator(ctx)
+ return compiler.Properties.Features.GetOrDefault(eval, nil)
}
-func (compiler *baseCompiler) featuresToFlags() []string {
+func (compiler *baseCompiler) featuresToFlags(ctx android.ConfigurableEvaluatorContext, module *Module) []string {
flags := []string{}
- for _, feature := range compiler.features() {
+ for _, feature := range compiler.features(ctx, module) {
flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
}
return flags
}
-func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags {
- flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags()...)
- flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags()...)
+func (compiler *baseCompiler) featureFlags(ctx ModuleContext, module *Module, flags Flags) Flags {
+ flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(ctx, module)...)
+ flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags(ctx, module)...)
return flags
}
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 79ea7a1..25f7580 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -24,4 +24,8 @@
"x86_64_device.go",
"arm64_linux_host.go",
],
+ visibility: [
+ "//build/soong:__subpackages__",
+ "//prebuilts/rust/soong",
+ ],
}
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 9850570..94a4457 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -35,8 +35,13 @@
},
"armv8-2a": []string{},
"armv8-2a-dotprod": []string{},
+
+ // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
"armv9-a": []string{
- // branch-protection=bti,pac-ret is equivalent to Clang's mbranch-protection=standard
+ "-Z branch-protection=bti,pac-ret",
+ "-Z stack-protector=none",
+ },
+ "armv9-2a": []string{
"-Z branch-protection=bti,pac-ret",
"-Z stack-protector=none",
},
diff --git a/rust/config/darwin_host.go b/rust/config/darwin_host.go
index a4bc187..df8c6ac 100644
--- a/rust/config/darwin_host.go
+++ b/rust/config/darwin_host.go
@@ -15,6 +15,7 @@
package config
import (
+ "runtime"
"strings"
"android/soong/android"
@@ -35,13 +36,15 @@
registerToolchainFactory(android.Darwin, android.Arm64, darwinArm64ToolchainFactory)
registerToolchainFactory(android.Darwin, android.X86_64, darwinX8664ToolchainFactory)
- pctx.StaticVariable("DarwinToolchainRustFlags", strings.Join(DarwinRustFlags, " "))
- pctx.StaticVariable("DarwinToolchainLinkFlags", strings.Join(DarwinRustLinkFlags, " "))
+ if runtime.GOOS == "darwin" {
+ pctx.StaticVariable("DarwinToolchainRustFlags", strings.Join(DarwinRustFlags, " "))
+ pctx.StaticVariable("DarwinToolchainLinkFlags", strings.Join(DarwinRustLinkFlags, " "))
- pctx.StaticVariable("DarwinToolchainArm64RustFlags", strings.Join(darwinArm64Rustflags, " "))
- pctx.StaticVariable("DarwinToolchainArm64LinkFlags", strings.Join(darwinArm64Linkflags, " "))
- pctx.StaticVariable("DarwinToolchainX8664RustFlags", strings.Join(darwinX8664Rustflags, " "))
- pctx.StaticVariable("DarwinToolchainX8664LinkFlags", strings.Join(darwinX8664Linkflags, " "))
+ pctx.StaticVariable("DarwinToolchainArm64RustFlags", strings.Join(darwinArm64Rustflags, " "))
+ pctx.StaticVariable("DarwinToolchainArm64LinkFlags", strings.Join(darwinArm64Linkflags, " "))
+ pctx.StaticVariable("DarwinToolchainX8664RustFlags", strings.Join(darwinX8664Rustflags, " "))
+ pctx.StaticVariable("DarwinToolchainX8664LinkFlags", strings.Join(darwinX8664Linkflags, " "))
+ }
}
diff --git a/rust/config/global.go b/rust/config/global.go
index 6943467..68a74c2 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var (
pctx = android.NewPackageContext("android/soong/rust/config")
- RustDefaultVersion = "1.78.0"
+ RustDefaultVersion = "1.81.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index fee1923..3c484d8 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -29,6 +29,7 @@
x86_64ArchVariantRustFlags = map[string][]string{
"": []string{},
+ "alderlake": []string{"-C target-cpu=alderlake"},
"broadwell": []string{"-C target-cpu=broadwell"},
"goldmont": []string{"-C target-cpu=goldmont"},
"goldmont-plus": []string{"-C target-cpu=goldmont-plus"},
diff --git a/rust/config/x86_device.go b/rust/config/x86_device.go
index 5d9d88a..3c597cc 100644
--- a/rust/config/x86_device.go
+++ b/rust/config/x86_device.go
@@ -27,6 +27,7 @@
x86ArchVariantRustFlags = map[string][]string{
"": []string{},
+ "alderlake": []string{"-C target-cpu=alderlake"},
"atom": []string{"-C target-cpu=atom"},
"broadwell": []string{"-C target-cpu=broadwell"},
"goldmont": []string{"-C target-cpu=goldmont"},
diff --git a/rust/coverage.go b/rust/coverage.go
index 91a7806..381fcf1 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -87,10 +87,6 @@
}
func (cov *coverage) begin(ctx BaseModuleContext) {
- if ctx.Host() {
- // Host coverage not yet supported.
- } else {
- // Update useSdk and sdkVersion args if Rust modules become SDK aware.
- cov.Properties = cc.SetCoverageProperties(ctx, cov.Properties, ctx.RustModule().nativeCoverage(), false, "")
- }
+ // Update useSdk and sdkVersion args if Rust modules become SDK aware.
+ cov.Properties = cc.SetCoverageProperties(ctx, cov.Properties, ctx.RustModule().nativeCoverage(), false, "")
}
diff --git a/rust/library.go b/rust/library.go
index 50d5a72..7db8f36 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -70,6 +70,10 @@
// 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.
+ Apex_exclude *bool
}
type LibraryMutatedProperties struct {
@@ -122,6 +126,7 @@
shared() bool
sysroot() bool
source() bool
+ apexExclude() bool
// Returns true if the build options for the module have selected a particular build type
buildRlib() bool
@@ -186,6 +191,10 @@
return library.MutatedProperties.VariantIsSource
}
+func (library *libraryDecorator) apexExclude() bool {
+ return Bool(library.Properties.Apex_exclude)
+}
+
func (library *libraryDecorator) buildRlib() bool {
return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true)
}
diff --git a/rust/project_json.go b/rust/project_json.go
index 24dcc89..6c1e320 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -151,7 +151,7 @@
crate.Env["OUT_DIR"] = rModule.compiler.cargoOutDir().String()
}
- for _, feature := range rModule.compiler.features() {
+ for _, feature := range rModule.compiler.features(ctx, rModule) {
crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"")
}
diff --git a/rust/rust.go b/rust/rust.go
index 3402adc..5602edc 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -29,7 +29,6 @@
"android/soong/cc"
cc_config "android/soong/cc/config"
"android/soong/fuzz"
- "android/soong/multitree"
"android/soong/rust/config"
)
@@ -294,6 +293,15 @@
return mod.StaticallyLinked()
}
+func (mod *Module) ApexExclude() bool {
+ if mod.compiler != nil {
+ if library, ok := mod.compiler.(libraryInterface); ok {
+ return library.apexExclude()
+ }
+ }
+ return false
+}
+
func (mod *Module) Object() bool {
// Rust has no modules which produce only object files.
return false
@@ -912,7 +920,7 @@
if mod.compiler != nil {
flags = mod.compiler.compilerFlags(ctx, flags)
flags = mod.compiler.cfgFlags(ctx, flags)
- flags = mod.compiler.featureFlags(ctx, flags)
+ flags = mod.compiler.featureFlags(ctx, mod, flags)
}
if mod.coverage != nil {
flags, deps = mod.coverage.flags(ctx, flags, deps)
@@ -938,6 +946,7 @@
sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
}
+ ctx.CheckbuildFile(mod.sourceProvider.Srcs()...)
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()})
}
@@ -948,15 +957,13 @@
return
}
mod.outputFile = android.OptionalPathForPath(buildOutput.outputFile)
+ ctx.CheckbuildFile(buildOutput.outputFile)
if buildOutput.kytheFile != nil {
mod.kytheFiles = append(mod.kytheFiles, buildOutput.kytheFile)
}
bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), android.OptionalPathForPath(mod.compiler.unstrippedOutputFilePath()))
mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps)
- if mod.docTimestampFile.Valid() {
- ctx.CheckbuildFile(mod.docTimestampFile.Path())
- }
apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() {
@@ -1210,47 +1217,6 @@
skipModuleList := map[string]bool{}
- var apiImportInfo multitree.ApiImportInfo
- hasApiImportInfo := false
-
- ctx.VisitDirectDeps(func(dep android.Module) {
- if dep.Name() == "api_imports" {
- apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
- hasApiImportInfo = true
- }
- })
-
- if hasApiImportInfo {
- targetStubModuleList := map[string]string{}
- targetOrigModuleList := map[string]string{}
-
- // Search for dependency which both original module and API imported library with APEX stub exists
- ctx.VisitDirectDeps(func(dep android.Module) {
- depName := ctx.OtherModuleName(dep)
- if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok {
- targetStubModuleList[apiLibrary] = depName
- }
- })
- ctx.VisitDirectDeps(func(dep android.Module) {
- depName := ctx.OtherModuleName(dep)
- if origLibrary, ok := targetStubModuleList[depName]; ok {
- targetOrigModuleList[origLibrary] = depName
- }
- })
-
- // Decide which library should be used between original and API imported library
- ctx.VisitDirectDeps(func(dep android.Module) {
- depName := ctx.OtherModuleName(dep)
- if apiLibrary, ok := targetOrigModuleList[depName]; ok {
- if cc.ShouldUseStubForApex(ctx, dep) {
- skipModuleList[depName] = true
- } else {
- skipModuleList[apiLibrary] = true
- }
- }
- })
- }
-
var transitiveAndroidMkSharedLibs []*android.DepSet[string]
var directAndroidMkSharedLibs []string
@@ -1601,13 +1567,6 @@
deps := mod.deps(ctx)
var commonDepVariations []blueprint.Variation
- apiImportInfo := cc.GetApiImports(mod, actx)
- if mod.usePublicApi() || mod.useVendorApi() {
- for idx, lib := range deps.SharedLibs {
- deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs)
- }
- }
-
if ctx.Os() == android.Android {
deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs)
}
@@ -1700,15 +1659,7 @@
variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
}
- // For core variant, add a dep on the implementation (if it exists) and its .apiimport (if it exists)
- // GenerateAndroidBuildActions will pick the correct impl/stub based on the api_domain boundary
- if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
- cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
- }
-
- if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
- cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, apiLibraryName, version, false)
- }
+ cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
}
for _, lib := range deps.WholeStaticLibs {
@@ -1863,6 +1814,10 @@
return false
}
+ if rustDep, ok := dep.(*Module); ok && rustDep.ApexExclude() {
+ return false
+ }
+
return true
}
diff --git a/rust/test_test.go b/rust/test_test.go
index dc796c8..1097da2 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -108,7 +108,7 @@
testingModule := ctx.ModuleForTests("main_test", "android_arm64_armv8-a")
testBinary := testingModule.Module().(*Module).compiler.(*testDecorator)
- outputFiles := testingModule.OutputFiles(t, "")
+ outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
@@ -168,7 +168,7 @@
testingModule := ctx.ModuleForTests("main_test", "android_arm64_armv8-a")
module := testingModule.Module()
testBinary := module.(*Module).compiler.(*testDecorator)
- outputFiles := testingModule.OutputFiles(t, "")
+ outputFiles := testingModule.OutputFiles(ctx, t, "")
if len(outputFiles) != 1 {
t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 91aa195..00b3ca5 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -184,12 +184,21 @@
libs: ["ninja_rsp"],
}
-python_test_host {
- name: "lint_project_xml_test",
- main: "lint_project_xml_test.py",
+python_binary_host {
+ name: "lint_strict_updatability_checks",
+ main: "lint_strict_updatability_checks.py",
srcs: [
- "lint_project_xml_test.py",
- "lint_project_xml.py",
+ "lint_strict_updatability_checks.py",
+ ],
+ libs: ["ninja_rsp"],
+}
+
+python_test_host {
+ name: "lint_strict_updatability_checks_test",
+ main: "lint_strict_updatability_checks_test.py",
+ srcs: [
+ "lint_strict_updatability_checks_test.py",
+ "lint_strict_updatability_checks.py",
],
libs: ["ninja_rsp"],
test_suites: ["general-tests"],
@@ -306,12 +315,6 @@
}
python_binary_host {
- name: "buildinfo",
- main: "buildinfo.py",
- srcs: ["buildinfo.py"],
-}
-
-python_binary_host {
name: "extra_install_zips_file_list",
main: "extra_install_zips_file_list.py",
srcs: ["extra_install_zips_file_list.py"],
diff --git a/scripts/buildinfo.py b/scripts/buildinfo.py
deleted file mode 100755
index 8a24b63..0000000
--- a/scripts/buildinfo.py
+++ /dev/null
@@ -1,191 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2024 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-"""A tool for generating buildinfo.prop"""
-
-import argparse
-import contextlib
-import json
-import os
-import subprocess
-
-TEST_KEY_DIR = "build/make/target/product/security"
-
-def get_build_variant(product_config):
- if product_config["Eng"]:
- return "eng"
- elif product_config["Debuggable"]:
- return "userdebug"
- else:
- return "user"
-
-def get_build_flavor(product_config):
- build_flavor = product_config["DeviceProduct"] + "-" + get_build_variant(product_config)
- if "address" in product_config.get("SanitizeDevice", []) and "_asan" not in build_flavor:
- build_flavor += "_asan"
- return build_flavor
-
-def get_build_keys(product_config):
- default_cert = product_config.get("DefaultAppCertificate", "")
- if default_cert == "" or default_cert == os.path.join(TEST_KEY_DIR, "testKey"):
- return "test-keys"
- return "dev-keys"
-
-def parse_args():
- """Parse commandline arguments."""
- parser = argparse.ArgumentParser()
- parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')),
- parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r'))
- parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r'))
- parser.add_argument('--build-username', required=True)
- parser.add_argument('--date-file', required=True, type=argparse.FileType('r'))
- parser.add_argument('--platform-preview-sdk-fingerprint-file',
- required=True,
- type=argparse.FileType('r'))
- parser.add_argument('--product-config', required=True, type=argparse.FileType('r'))
- parser.add_argument('--out', required=True, type=argparse.FileType('w'))
-
- option = parser.parse_args()
-
- product_config = json.load(option.product_config)
- build_flags = product_config["BuildFlags"]
-
- option.build_flavor = get_build_flavor(product_config)
- option.build_keys = get_build_keys(product_config)
- option.build_id = product_config["BuildId"]
- option.build_type = product_config["BuildType"]
- option.build_variant = get_build_variant(product_config)
- option.build_version_tags = product_config["BuildVersionTags"]
- option.cpu_abis = product_config["DeviceAbi"]
- option.default_locale = None
- if len(product_config.get("ProductLocales", [])) > 0:
- option.default_locale = product_config["ProductLocales"][0]
- option.default_wifi_channels = product_config.get("ProductDefaultWifiChannels", [])
- option.device = product_config["DeviceName"]
- option.display_build_number = product_config["DisplayBuildNumber"]
- option.platform_base_os = product_config["Platform_base_os"]
- option.platform_display_version = product_config["Platform_display_version_name"]
- option.platform_min_supported_target_sdk_version = build_flags["RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION"]
- option.platform_preview_sdk_version = product_config["Platform_preview_sdk_version"]
- option.platform_sdk_version = product_config["Platform_sdk_version"]
- option.platform_security_patch = product_config["Platform_security_patch"]
- option.platform_version = product_config["Platform_version_name"]
- option.platform_version_codename = product_config["Platform_sdk_codename"]
- option.platform_version_all_codenames = product_config["Platform_version_active_codenames"]
- option.platform_version_known_codenames = product_config["Platform_version_known_codenames"]
- option.platform_version_last_stable = product_config["Platform_version_last_stable"]
- option.product = product_config["DeviceProduct"]
- option.use_vbmeta_digest_in_fingerprint = product_config["BoardUseVbmetaDigestInFingerprint"]
-
- return option
-
-def main():
- option = parse_args()
-
- build_hostname = option.build_hostname_file.read().strip()
- build_number = option.build_number_file.read().strip()
- build_version_tags_list = option.build_version_tags
- if option.build_type == "debug":
- build_version_tags_list.append("debug")
- build_version_tags_list.append(option.build_keys)
- build_version_tags = ",".join(sorted(set(build_version_tags_list)))
-
- raw_date = option.date_file.read().strip()
- date = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip()
- date_utc = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip()
-
- # build_desc is human readable strings that describe this build. This has the same info as the
- # build fingerprint.
- # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys"
- build_desc = f"{option.product}-{option.build_variant} {option.platform_version} " \
- f"{option.build_id} {build_number} {build_version_tags}"
-
- platform_preview_sdk_fingerprint = option.platform_preview_sdk_fingerprint_file.read().strip()
-
- with contextlib.redirect_stdout(option.out):
- print("# begin build properties")
- print("# autogenerated by buildinfo.py")
-
- # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest.
- if option.use_vbmeta_digest_in_fingerprint:
- print(f"ro.build.legacy.id={option.build_id}")
- else:
- print(f"ro.build.id?={option.build_id}")
-
- # ro.build.display.id is shown under Settings -> About Phone
- if option.build_variant == "user":
- # User builds should show:
- # release build number or branch.buld_number non-release builds
-
- # Dev. branches should have DISPLAY_BUILD_NUMBER set
- if option.display_build_number:
- print(f"ro.build.display.id?={option.build_id}.{build_number} {option.build_keys}")
- else:
- print(f"ro.build.display.id?={option.build_id} {option.build_keys}")
- else:
- # Non-user builds should show detailed build information (See build desc above)
- print(f"ro.build.display.id?={build_desc}")
- print(f"ro.build.version.incremental={build_number}")
- print(f"ro.build.version.sdk={option.platform_sdk_version}")
- print(f"ro.build.version.preview_sdk={option.platform_preview_sdk_version}")
- print(f"ro.build.version.preview_sdk_fingerprint={platform_preview_sdk_fingerprint}")
- print(f"ro.build.version.codename={option.platform_version_codename}")
- print(f"ro.build.version.all_codenames={','.join(option.platform_version_all_codenames)}")
- print(f"ro.build.version.known_codenames={option.platform_version_known_codenames}")
- print(f"ro.build.version.release={option.platform_version_last_stable}")
- print(f"ro.build.version.release_or_codename={option.platform_version}")
- print(f"ro.build.version.release_or_preview_display={option.platform_display_version}")
- print(f"ro.build.version.security_patch={option.platform_security_patch}")
- print(f"ro.build.version.base_os={option.platform_base_os}")
- print(f"ro.build.version.min_supported_target_sdk={option.platform_min_supported_target_sdk_version}")
- print(f"ro.build.date={date}")
- print(f"ro.build.date.utc={date_utc}")
- print(f"ro.build.type={option.build_variant}")
- print(f"ro.build.user={option.build_username}")
- print(f"ro.build.host={build_hostname}")
- # TODO: Remove any tag-related optional property declarations once the goals
- # from go/arc-android-sigprop-changes have been achieved.
- print(f"ro.build.tags?={build_version_tags}")
- # ro.build.flavor are used only by the test harness to distinguish builds.
- # Only add _asan for a sanitized build if it isn't already a part of the
- # flavor (via a dedicated lunch config for example).
- print(f"ro.build.flavor={option.build_flavor}")
-
- # These values are deprecated, use "ro.product.cpu.abilist"
- # instead (see below).
- print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
- print(f"# use ro.product.cpu.abilist instead.")
- print(f"ro.product.cpu.abi={option.cpu_abis[0]}")
- if len(option.cpu_abis) > 1:
- print(f"ro.product.cpu.abi2={option.cpu_abis[1]}")
-
- if option.default_locale:
- print(f"ro.product.locale={option.default_locale}")
- print(f"ro.wifi.channels={' '.join(option.default_wifi_channels)}")
-
- print(f"# ro.build.product is obsolete; use ro.product.device")
- print(f"ro.build.product={option.device}")
-
- print(f"# Do not try to parse description or thumbprint")
- print(f"ro.build.description?={build_desc}")
- if option.build_thumbprint_file:
- build_thumbprint = option.build_thumbprint_file.read().strip()
- print(f"ro.build.thumbprint={build_thumbprint}")
-
- print(f"# end build properties")
-
-if __name__ == "__main__":
- main()
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index bb88cce..1d2fc64 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -3,7 +3,52 @@
###################################################
# core-libart.jar & core-oj.jar
-java(\..*)?
+java\.awt\.font
+java\.beans
+java\.io
+java\.lang
+java\.lang\.annotation
+java\.lang\.constant
+java\.lang\.invoke
+java\.lang\.ref
+java\.lang\.reflect
+java\.lang\.runtime
+java\.math
+java\.net
+java\.nio
+java\.nio\.file
+java\.nio\.file\.spi
+java\.nio\.file\.attribute
+java\.nio\.channels
+java\.nio\.channels\.spi
+java\.nio\.charset
+java\.nio\.charset\.spi
+java\.security
+java\.security\.acl
+java\.security\.cert
+java\.security\.interfaces
+java\.security\.spec
+java\.sql
+java\.text
+java\.text\.spi
+java\.time
+java\.time\.chrono
+java\.time\.format
+java\.time\.temporal
+java\.time\.zone
+java\.util
+java\.util\.concurrent
+java\.util\.concurrent\.atomic
+java\.util\.concurrent\.locks
+java\.util\.function
+java\.util\.jar
+java\.util\.logging
+java\.util\.prefs
+java\.util\.random
+java\.util\.regex
+java\.util\.spi
+java\.util\.stream
+java\.util\.zip
# TODO: Remove javax.annotation.processing if possible, see http://b/132338110:
javax\.annotation\.processing
javax\.crypto
@@ -27,7 +72,20 @@
javax\.xml\.transform\.stream
javax\.xml\.validation
javax\.xml\.xpath
-jdk\..*
+jdk\.internal
+jdk\.internal\.access
+jdk\.internal\.event
+jdk\.internal\.math
+jdk\.internal\.misc
+jdk\.internal\.ref
+jdk\.internal\.reflect
+jdk\.internal\.util
+jdk\.internal\.util\.jar
+jdk\.internal\.util\.random
+jdk\.internal\.vm
+jdk\.internal\.vm\.annotation
+jdk\.net
+jdk\.random
org\.w3c\.dom
org\.w3c\.dom\.ls
org\.w3c\.dom\.traversal
diff --git a/scripts/check_prebuilt_presigned_apk.py b/scripts/check_prebuilt_presigned_apk.py
index abab2e1..db64f90 100755
--- a/scripts/check_prebuilt_presigned_apk.py
+++ b/scripts/check_prebuilt_presigned_apk.py
@@ -36,7 +36,7 @@
if fail:
sys.exit(args.apk + ': Contains compressed JNI libraries')
return True
- # It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
+ # It's ok for non-privileged apps to have compressed dex files
if args.privileged and args.uncompress_priv_app_dex:
if info.filename.endswith('.dex') and info.compress_type != zipfile.ZIP_STORED:
if fail:
@@ -46,6 +46,10 @@
def main():
+ # This script enforces requirements for presigned apps as documented in:
+ # go/gms-uncompressed-jni-slides
+ # https://docs.partner.android.com/gms/building/integrating/jni-libs
+ # https://docs.partner.android.com/gms/policies/domains/mba#jni-lib
parser = argparse.ArgumentParser()
parser.add_argument('--aapt2', help = "the path to the aapt2 executable")
parser.add_argument('--zipalign', help = "the path to the zipalign executable")
diff --git a/scripts/gen-kotlin-build-file.py b/scripts/gen-kotlin-build-file.py
index 99afdca..8b7876f 100644
--- a/scripts/gen-kotlin-build-file.py
+++ b/scripts/gen-kotlin-build-file.py
@@ -37,7 +37,7 @@
parser.add_argument('--out', dest='out',
help='file to which the module.xml contents will be written.')
parser.add_argument('--classpath', dest='classpath', action='append', default=[],
- help='classpath to pass to kotlinc.')
+ help='file containing classpath to pass to kotlinc.')
parser.add_argument('--name', dest='name',
help='name of the module.')
parser.add_argument('--out_dir', dest='out_dir',
@@ -65,8 +65,8 @@
f.write(' <module name="%s" type="java-production" outputDir="%s">\n' % (args.name, args.out_dir or ''))
# Print classpath entries
- for c in args.classpath:
- for entry in c.split(':'):
+ for classpath_rsp_file in args.classpath:
+ for entry in NinjaRspFileReader(classpath_rsp_file):
path = os.path.abspath(entry)
f.write(' <classpath path="%s"/>\n' % path)
diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py
index 9ea56cb..c08a3fd 100644
--- a/scripts/gen_build_prop.py
+++ b/scripts/gen_build_prop.py
@@ -129,16 +129,16 @@
print(f"ro.product.{partition}.name={config['DeviceProduct']}")
if partition != "system":
- if config["ModelForAttestation"]:
- print(f"ro.product.model_for_attestation={config['ModelForAttestation']}")
- if config["BrandForAttestation"]:
- print(f"ro.product.brand_for_attestation={config['BrandForAttestation']}")
- if config["NameForAttestation"]:
- print(f"ro.product.name_for_attestation={config['NameForAttestation']}")
- if config["DeviceForAttestation"]:
- print(f"ro.product.device_for_attestation={config['DeviceForAttestation']}")
- if config["ManufacturerForAttestation"]:
- print(f"ro.product.manufacturer_for_attestation={config['ManufacturerForAttestation']}")
+ if config["ProductModelForAttestation"]:
+ print(f"ro.product.model_for_attestation={config['ProductModelForAttestation']}")
+ if config["ProductBrandForAttestation"]:
+ print(f"ro.product.brand_for_attestation={config['ProductBrandForAttestation']}")
+ if config["ProductNameForAttestation"]:
+ print(f"ro.product.name_for_attestation={config['ProductNameForAttestation']}")
+ if config["ProductDeviceForAttestation"]:
+ print(f"ro.product.device_for_attestation={config['ProductDeviceForAttestation']}")
+ if config["ProductManufacturerForAttestation"]:
+ print(f"ro.product.manufacturer_for_attestation={config['ProductManufacturerForAttestation']}")
if config["ZygoteForce64"]:
if partition == "vendor":
@@ -237,7 +237,7 @@
print(f"# Do not try to parse description or thumbprint")
print(f"ro.build.description?={config['BuildDesc']}")
- if "build_thumbprint" in config:
+ if "BuildThumbprint" in config:
print(f"ro.build.thumbprint={config['BuildThumbprint']}")
print(f"# end build properties")
@@ -279,7 +279,7 @@
config = args.config
# Add the product-defined properties to the build properties.
- if config["PropertySplitEnabled"] or config["VendorImageFileSystemType"]:
+ if not config["PropertySplitEnabled"] or not config["VendorImageFileSystemType"]:
if "PRODUCT_PROPERTY_OVERRIDES" in config:
props += config["PRODUCT_PROPERTY_OVERRIDES"]
@@ -311,6 +311,7 @@
props.append("ro.postinstall.fstab.prefix=/system")
enable_target_debugging = True
+ enable_dalvik_lock_contention_logging = True
if config["BuildVariant"] == "user" or config["BuildVariant"] == "userdebug":
# Target is secure in user builds.
props.append("ro.secure=1")
@@ -320,6 +321,12 @@
# Disable debugging in plain user builds.
props.append("ro.adb.secure=1")
enable_target_debugging = False
+ enable_dalvik_lock_contention_logging = False
+ else:
+ # Disable debugging in userdebug builds if PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
+ # is set.
+ if config["ProductNotDebuggableInUserdebug"]:
+ enable_target_debugging = False
# Disallow mock locations by default for user builds
props.append("ro.allow.mock.location=0")
@@ -331,10 +338,11 @@
# Allow mock locations by default for non user builds
props.append("ro.allow.mock.location=1")
- if enable_target_debugging:
+ if enable_dalvik_lock_contention_logging:
# Enable Dalvik lock contention logging.
props.append("dalvik.vm.lockprof.threshold=500")
+ if enable_target_debugging:
# Target is more debuggable and adbd is on by default
props.append("ro.debuggable=1")
else:
@@ -416,7 +424,7 @@
# This must not be defined for the non-GRF devices.
# The values of the GRF properties will be verified by post_process_props.py
if config["BoardShippingApiLevel"]:
- props.append(f"ro.board.first_api_level={config['ProductShippingApiLevel']}")
+ props.append(f"ro.board.first_api_level={config['BoardShippingApiLevel']}")
# Build system set BOARD_API_LEVEL to show the api level of the vendor API surface.
# This must not be altered outside of build system.
@@ -464,6 +472,8 @@
# Add the 16K developer args if it is defined for the product.
props.append(f"ro.product.build.16k_page.enabled={'true' if config['Product16KDeveloperOption'] else 'false'}")
+ props.append(f"ro.product.page_size={16384 if config['TargetBoots16K'] else 4096}")
+
props.append(f"ro.build.characteristics={config['AAPTCharacteristics']}")
if "AbOtaUpdater" in config and config["AbOtaUpdater"]:
@@ -475,6 +485,9 @@
if config["NoBionicPageSizeMacro"]:
props.append(f"ro.product.build.no_bionic_page_size_macro=true")
+ # This is a temporary system property that controls the ART module. The plan is
+ # to remove it by Aug 2025, at which time Mainline updates of the ART module
+ # will ignore it as well.
# If the value is "default", it will be mangled by post_process_props.py.
props.append(f"ro.dalvik.vm.enable_uffd_gc={config['EnableUffdGc']}")
@@ -500,6 +513,15 @@
build_prop(args, gen_build_info=True, gen_common_build_props=True, variables=variables)
+def build_system_ext_prop(args):
+ config = args.config
+
+ # Order matters here. When there are duplicates, the last one wins.
+ # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
+ variables = ["PRODUCT_SYSTEM_EXT_PROPERTIES"]
+
+ build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
+
'''
def build_vendor_prop(args):
config = args.config
@@ -517,6 +539,7 @@
]
build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
+'''
def build_product_prop(args):
config = args.config
@@ -527,8 +550,32 @@
"ADDITIONAL_PRODUCT_PROPERTIES",
"PRODUCT_PRODUCT_PROPERTIES",
]
+
+ gen_common_build_props = True
+
+ # Skip common /product properties generation if device released before R and
+ # has no product partition. This is the first part of the check.
+ if config["Shipping_api_level"] and int(config["Shipping_api_level"]) < 30:
+ gen_common_build_props = False
+
+ # The second part of the check - always generate common properties for the
+ # devices with product partition regardless of shipping level.
+ if config["UsesProductImage"]:
+ gen_common_build_props = True
+
build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
-'''
+
+ if config["OemProperties"]:
+ print("####################################")
+ print("# PRODUCT_OEM_PROPERTIES")
+ print("####################################")
+
+ for prop in config["OemProperties"]:
+ print(f"import /oem/oem.prop {prop}")
+
+def build_odm_prop(args):
+ variables = ["ADDITIONAL_ODM_PROPERTIES", "PRODUCT_ODM_PROPERTIES"]
+ build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
def build_prop(args, gen_build_info, gen_common_build_props, variables):
config = args.config
@@ -550,16 +597,19 @@
args = parse_args()
with contextlib.redirect_stdout(args.out):
- if args.partition == "system":
- build_system_prop(args)
- '''
- elif args.partition == "vendor":
- build_vendor_prop(args)
- elif args.partition == "product":
- build_product_prop(args)
- '''
- else:
- sys.exit(f"not supported partition {args.partition}")
+ match args.partition:
+ case "system":
+ build_system_prop(args)
+ case "system_ext":
+ build_system_ext_prop(args)
+ case "odm":
+ build_odm_prop(args)
+ case "product":
+ build_product_prop(args)
+ # case "vendor": # NOT IMPLEMENTED
+ # build_vendor_prop(args)
+ case _:
+ sys.exit(f"not supported partition {args.partition}")
if __name__ == "__main__":
main()
diff --git a/scripts/lint_project_xml.py b/scripts/lint_project_xml.py
index c40b07d..ce6aa21 100755
--- a/scripts/lint_project_xml.py
+++ b/scripts/lint_project_xml.py
@@ -75,8 +75,6 @@
help='file containing the module\'s manifest.')
parser.add_argument('--merged_manifest', dest='merged_manifest',
help='file containing merged manifest for the module and its dependencies.')
- parser.add_argument('--baseline', dest='baseline_path',
- help='file containing baseline lint issues.')
parser.add_argument('--library', dest='library', action='store_true',
help='mark the module as a library.')
parser.add_argument('--test', dest='test', action='store_true',
@@ -94,8 +92,6 @@
help='treat a lint issue as a warning.')
group.add_argument('--disable_check', dest='checks', action=check_action('ignore'), default=[],
help='disable a lint issue.')
- group.add_argument('--disallowed_issues', dest='disallowed_issues', default=[],
- help='lint issues disallowed in the baseline file')
return parser.parse_args()
@@ -140,30 +136,10 @@
f.write("</lint>\n")
-def check_baseline_for_disallowed_issues(baseline, forced_checks):
- issues_element = baseline.documentElement
- if issues_element.tagName != 'issues':
- raise RuntimeError('expected issues tag at root')
- issues = issues_element.getElementsByTagName('issue')
- disallowed = set()
- for issue in issues:
- id = issue.getAttribute('id')
- if id in forced_checks:
- disallowed.add(id)
- return disallowed
-
-
def main():
"""Program entry point."""
args = parse_args()
- if args.baseline_path:
- baseline = minidom.parse(args.baseline_path)
- disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
- if disallowed_issues:
- sys.exit('disallowed issues %s found in lint baseline file %s for module %s'
- % (disallowed_issues, args.baseline_path, args.name))
-
if args.project_out:
with open(args.project_out, 'w') as f:
write_project_xml(f, args)
diff --git a/scripts/lint_strict_updatability_checks.py b/scripts/lint_strict_updatability_checks.py
new file mode 100755
index 0000000..5b5dfd8
--- /dev/null
+++ b/scripts/lint_strict_updatability_checks.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018 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 file checks baselines passed to Android Lint for checks that must not be baselined."""
+
+import argparse
+import sys
+from xml.dom import minidom
+
+from ninja_rsp import NinjaRspFileReader
+
+
+def parse_args():
+ """Parse commandline arguments."""
+
+ def convert_arg_line_to_args(arg_line):
+ for arg in arg_line.split():
+ if arg.startswith('#'):
+ return
+ if not arg.strip():
+ continue
+ yield arg
+
+ parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
+ parser.convert_arg_line_to_args = convert_arg_line_to_args
+ parser.add_argument('--name', dest='name',
+ help='name of the module.')
+ parser.add_argument('--baselines', dest='baselines', action='append', default=[],
+ help='file containing whitespace separated list of baseline files.')
+ parser.add_argument('--disallowed_issues', dest='disallowed_issues', default=[],
+ help='lint issues disallowed in the baseline file')
+ return parser.parse_args()
+
+
+def check_baseline_for_disallowed_issues(baseline, forced_checks):
+ issues_element = baseline.documentElement
+ if issues_element.tagName != 'issues':
+ raise RuntimeError('expected issues tag at root')
+ issues = issues_element.getElementsByTagName('issue')
+ disallowed = set()
+ for issue in issues:
+ id = issue.getAttribute('id')
+ if id in forced_checks:
+ disallowed.add(id)
+ return disallowed
+
+
+def main():
+ """Program entry point."""
+ args = parse_args()
+
+ error = False
+ for baseline_rsp_file in args.baselines:
+ for baseline_path in NinjaRspFileReader(baseline_rsp_file):
+ baseline = minidom.parse(baseline_path)
+ disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
+ if disallowed_issues:
+ print('disallowed issues %s found in lint baseline file %s for module %s'
+ % (disallowed_issues, baseline_path, args.name))
+ error = True
+
+ if error:
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/lint_project_xml_test.py b/scripts/lint_strict_updatability_checks_test.py
old mode 100644
new mode 100755
similarity index 88%
rename from scripts/lint_project_xml_test.py
rename to scripts/lint_strict_updatability_checks_test.py
index 344691d..fd8610f
--- a/scripts/lint_project_xml_test.py
+++ b/scripts/lint_strict_updatability_checks_test.py
@@ -15,12 +15,12 @@
# limitations under the License.
#
-"""Unit tests for lint_project_xml.py."""
+"""Unit tests for lint_strict_updatability_checks.py."""
import unittest
from xml.dom import minidom
-import lint_project_xml
+import lint_strict_updatability_checks
class CheckBaselineForDisallowedIssuesTest(unittest.TestCase):
@@ -44,7 +44,7 @@
'</issues>\n')
def test_check_baseline_for_disallowed_issues(self):
- disallowed_issues = lint_project_xml.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"])
+ disallowed_issues = lint_strict_updatability_checks.check_baseline_for_disallowed_issues(self.baseline_xml, ["foo", "bar", "qux"])
self.assertEqual({"foo", "bar"}, disallowed_issues)
diff --git a/scripts/manifest.py b/scripts/manifest.py
index 81f9c61..32603e8 100755
--- a/scripts/manifest.py
+++ b/scripts/manifest.py
@@ -23,9 +23,40 @@
android_ns = 'http://schemas.android.com/apk/res/android'
+def get_or_create_applications(doc, manifest):
+ """Get all <application> tags from the manifest, or create one if none exist.
+ Multiple <application> tags may exist when manifest feature flagging is used.
+ """
+ applications = get_children_with_tag(manifest, 'application')
+ if len(applications) == 0:
+ application = doc.createElement('application')
+ indent = get_indent(manifest.firstChild, 1)
+ first = manifest.firstChild
+ manifest.insertBefore(doc.createTextNode(indent), first)
+ manifest.insertBefore(application, first)
+ applications.append(application)
+ return applications
+
+
+def get_or_create_uses_sdks(doc, manifest):
+ """Get all <uses-sdk> tags from the manifest, or create one if none exist.
+ Multiple <uses-sdk> tags may exist when manifest feature flagging is used.
+ """
+ uses_sdks = get_children_with_tag(manifest, 'uses-sdk')
+ if len(uses_sdks) == 0:
+ uses_sdk = doc.createElement('uses-sdk')
+ indent = get_indent(manifest.firstChild, 1)
+ manifest.insertBefore(uses_sdk, manifest.firstChild)
+
+ # Insert an indent before uses-sdk to line it up with the indentation of the
+ # other children of the <manifest> tag.
+ manifest.insertBefore(doc.createTextNode(indent), manifest.firstChild)
+ uses_sdks.append(uses_sdk)
+ return uses_sdks
+
def get_children_with_tag(parent, tag_name):
children = []
- for child in parent.childNodes:
+ for child in parent.childNodes:
if child.nodeType == minidom.Node.ELEMENT_NODE and \
child.tagName == tag_name:
children.append(child)
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index b101259..1e32d1d 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -25,10 +25,7 @@
import sys
from xml.dom import minidom
-from manifest import android_ns
-from manifest import get_children_with_tag
-from manifest import parse_manifest
-from manifest import write_xml
+from manifest import *
class ManifestMismatchError(Exception):
@@ -122,7 +119,7 @@
# handles module names specified in Android.bp properties. However not all
# <uses-library> entries in the manifest correspond to real modules: some of
# the optional libraries may be missing at build time. Therefor this script
- # accepts raw module names as spelled in Android.bp/Amdroid.mk and trims the
+ # accepts raw module names as spelled in Android.bp/Android.mk and trims the
# optional namespace part manually.
required = trim_namespace_parts(required)
optional = trim_namespace_parts(optional)
@@ -205,15 +202,9 @@
"""Extract <uses-library> tags from the manifest."""
manifest = parse_manifest(xml)
- elems = get_children_with_tag(manifest, 'application')
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- if not elems:
- return [], [], []
-
- application = elems[0]
-
- libs = get_children_with_tag(application, 'uses-library')
+ libs = [child
+ for application in get_or_create_applications(xml, manifest)
+ for child in get_children_with_tag(application, 'uses-library')]
required = [uses_library_name(x) for x in libs if uses_library_required(x)]
optional = [
@@ -266,7 +257,7 @@
manifest: manifest (either parsed XML or aapt dump of APK)
is_apk: if the manifest comes from an APK or an XML file
"""
- if is_apk: #pylint: disable=no-else-return
+ if is_apk: #pylint: disable=no-else-return
return extract_target_sdk_version_apk(manifest)
else:
return extract_target_sdk_version_xml(manifest)
@@ -376,7 +367,7 @@
# Create a status file that is empty on success, or contains an
# error message on failure. When exceptions are suppressed,
- # dexpreopt command command will check file size to determine if
+ # dexpreopt command will check file size to determine if
# the check has failed.
if args.enforce_uses_libraries_status:
with open(args.enforce_uses_libraries_status, 'w') as f:
@@ -386,7 +377,7 @@
if args.extract_target_sdk_version:
try:
print(extract_target_sdk_version(manifest, is_apk))
- except: #pylint: disable=bare-except
+ except: #pylint: disable=bare-except
# Failed; don't crash, return "any" SDK version. This will
# result in dexpreopt not adding any compatibility libraries.
print(10000)
diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
index 8003b3e..abe0d8b 100755
--- a/scripts/manifest_check_test.py
+++ b/scripts/manifest_check_test.py
@@ -44,8 +44,8 @@
class EnforceUsesLibrariesTest(unittest.TestCase):
"""Unit tests for add_extract_native_libs function."""
- def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[],
- missing_optional_uses_libraries=[]): #pylint: disable=dangerous-default-value
+ def run_test(self, xml, apk, uses_libraries=(), optional_uses_libraries=(),
+ missing_optional_uses_libraries=()): #pylint: disable=dangerous-default-value
doc = minidom.parseString(xml)
try:
relax = False
@@ -114,14 +114,14 @@
self.assertFalse(matches)
def test_missing_uses_library(self):
- xml = self.xml_tmpl % ('')
- apk = self.apk_tmpl % ('')
+ xml = self.xml_tmpl % ''
+ apk = self.apk_tmpl % ''
matches = self.run_test(xml, apk, uses_libraries=['foo'])
self.assertFalse(matches)
def test_missing_optional_uses_library(self):
- xml = self.xml_tmpl % ('')
- apk = self.apk_tmpl % ('')
+ xml = self.xml_tmpl % ''
+ apk = self.apk_tmpl % ''
matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
self.assertFalse(matches)
@@ -234,6 +234,32 @@
optional_uses_libraries=['//x/y/z:bar'])
self.assertTrue(matches)
+ def test_multiple_applications(self):
+ xml = """<?xml version="1.0" encoding="utf-8"?>
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <application android:featureFlag="foo">
+ <uses-library android:name="foo" />
+ <uses-library android:name="bar" android:required="false" />
+ </application>
+ <application android:featureFlag="!foo">
+ <uses-library android:name="foo" />
+ <uses-library android:name="qux" android:required="false" />
+ </application>
+ </manifest>
+ """
+ apk = self.apk_tmpl % ('\n'.join([
+ uses_library_apk('foo'),
+ uses_library_apk('bar', required_apk(False)),
+ uses_library_apk('foo'),
+ uses_library_apk('qux', required_apk(False))
+ ]))
+ matches = self.run_test(
+ xml,
+ apk,
+ uses_libraries=['//x/y/z:foo'],
+ optional_uses_libraries=['//x/y/z:bar', '//x/y/z:qux'])
+ self.assertTrue(matches)
+
class ExtractTargetSdkVersionTest(unittest.TestCase):
@@ -256,12 +282,12 @@
"targetSdkVersion:'%s'\n"
"uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n")
- def test_targert_sdk_version_28(self):
+ def test_target_sdk_version_28(self):
xml = self.xml_tmpl % '28'
apk = self.apk_tmpl % '28'
self.run_test(xml, apk, '28')
- def test_targert_sdk_version_29(self):
+ def test_target_sdk_version_29(self):
xml = self.xml_tmpl % '29'
apk = self.apk_tmpl % '29'
self.run_test(xml, apk, '29')
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 58079aa..9847ad5 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -23,15 +23,7 @@
from xml.dom import minidom
-from manifest import android_ns
-from manifest import compare_version_gt
-from manifest import ensure_manifest_android_ns
-from manifest import find_child_with_attribute
-from manifest import get_children_with_tag
-from manifest import get_indent
-from manifest import parse_manifest
-from manifest import write_xml
-
+from manifest import *
def parse_args():
"""Parse commandline arguments."""
@@ -48,9 +40,9 @@
parser.add_argument('--library', dest='library', action='store_true',
help='manifest is for a static library')
parser.add_argument('--uses-library', dest='uses_libraries', action='append',
- help='specify additional <uses-library> tag to add. android:requred is set to true')
+ help='specify additional <uses-library> tag to add. android:required is set to true')
parser.add_argument('--optional-uses-library', dest='optional_uses_libraries', action='append',
- help='specify additional <uses-library> tag to add. android:requred is set to false')
+ help='specify additional <uses-library> tag to add. android:required is set to false')
parser.add_argument('--uses-non-sdk-api', dest='uses_non_sdk_api', action='store_true',
help='manifest is for a package built against the platform')
parser.add_argument('--logging-parent', dest='logging_parent', default='',
@@ -91,47 +83,33 @@
manifest = parse_manifest(doc)
- # Get or insert the uses-sdk element
- uses_sdk = get_children_with_tag(manifest, 'uses-sdk')
- if len(uses_sdk) > 1:
- raise RuntimeError('found multiple uses-sdk elements')
- elif len(uses_sdk) == 1:
- element = uses_sdk[0]
- else:
- element = doc.createElement('uses-sdk')
- indent = get_indent(manifest.firstChild, 1)
- manifest.insertBefore(element, manifest.firstChild)
-
- # Insert an indent before uses-sdk to line it up with the indentation of the
- # other children of the <manifest> tag.
- manifest.insertBefore(doc.createTextNode(indent), manifest.firstChild)
-
- # Get or insert the minSdkVersion attribute. If it is already present, make
- # sure it as least the requested value.
- min_attr = element.getAttributeNodeNS(android_ns, 'minSdkVersion')
- if min_attr is None:
- min_attr = doc.createAttributeNS(android_ns, 'android:minSdkVersion')
- min_attr.value = min_sdk_version
- element.setAttributeNode(min_attr)
- else:
- if compare_version_gt(min_sdk_version, min_attr.value):
+ for uses_sdk in get_or_create_uses_sdks(doc, manifest):
+ # Get or insert the minSdkVersion attribute. If it is already present, make
+ # sure it as least the requested value.
+ min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion')
+ if min_attr is None:
+ min_attr = doc.createAttributeNS(android_ns, 'android:minSdkVersion')
min_attr.value = min_sdk_version
-
- # Insert the targetSdkVersion attribute if it is missing. If it is already
- # present leave it as is.
- target_attr = element.getAttributeNodeNS(android_ns, 'targetSdkVersion')
- if target_attr is None:
- target_attr = doc.createAttributeNS(android_ns, 'android:targetSdkVersion')
- if library:
- # TODO(b/117122200): libraries shouldn't set targetSdkVersion at all, but
- # ManifestMerger treats minSdkVersion="Q" as targetSdkVersion="Q" if it
- # is empty. Set it to something low so that it will be overriden by the
- # main manifest, but high enough that it doesn't cause implicit
- # permissions grants.
- target_attr.value = '16'
+ uses_sdk.setAttributeNode(min_attr)
else:
- target_attr.value = target_sdk_version
- element.setAttributeNode(target_attr)
+ if compare_version_gt(min_sdk_version, min_attr.value):
+ min_attr.value = min_sdk_version
+
+ # Insert the targetSdkVersion attribute if it is missing. If it is already
+ # present leave it as is.
+ target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion')
+ if target_attr is None:
+ target_attr = doc.createAttributeNS(android_ns, 'android:targetSdkVersion')
+ if library:
+ # TODO(b/117122200): libraries shouldn't set targetSdkVersion at all, but
+ # ManifestMerger treats minSdkVersion="Q" as targetSdkVersion="Q" if it
+ # is empty. Set it to something low so that it will be overridden by the
+ # main manifest, but high enough that it doesn't cause implicit
+ # permissions grants.
+ target_attr.value = '16'
+ else:
+ target_attr.value = target_sdk_version
+ uses_sdk.setAttributeNode(target_attr)
def add_logging_parent(doc, logging_parent_value):
@@ -147,37 +125,27 @@
manifest = parse_manifest(doc)
logging_parent_key = 'android.content.pm.LOGGING_PARENT'
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ indent = get_indent(application.firstChild, 2)
- indent = get_indent(application.firstChild, 2)
-
- last = application.lastChild
- if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
- last = None
-
- if not find_child_with_attribute(application, 'meta-data', android_ns,
- 'name', logging_parent_key):
- ul = doc.createElement('meta-data')
- ul.setAttributeNS(android_ns, 'android:name', logging_parent_key)
- ul.setAttributeNS(android_ns, 'android:value', logging_parent_value)
- application.insertBefore(doc.createTextNode(indent), last)
- application.insertBefore(ul, last)
last = application.lastChild
+ if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
+ last = None
- # align the closing tag with the opening tag if it's not
- # indented
- if last and last.nodeType != minidom.Node.TEXT_NODE:
- indent = get_indent(application.previousSibling, 1)
- application.appendChild(doc.createTextNode(indent))
+ if not find_child_with_attribute(application, 'meta-data', android_ns,
+ 'name', logging_parent_key):
+ ul = doc.createElement('meta-data')
+ ul.setAttributeNS(android_ns, 'android:name', logging_parent_key)
+ ul.setAttributeNS(android_ns, 'android:value', logging_parent_value)
+ application.insertBefore(doc.createTextNode(indent), last)
+ application.insertBefore(ul, last)
+ last = application.lastChild
+
+ # align the closing tag with the opening tag if it's not
+ # indented
+ if last and last.nodeType != minidom.Node.TEXT_NODE:
+ indent = get_indent(application.previousSibling, 1)
+ application.appendChild(doc.createTextNode(indent))
def add_uses_libraries(doc, new_uses_libraries, required):
@@ -192,42 +160,32 @@
"""
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ indent = get_indent(application.firstChild, 2)
- indent = get_indent(application.firstChild, 2)
+ last = application.lastChild
+ if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
+ last = None
- last = application.lastChild
- if last is not None and last.nodeType != minidom.Node.TEXT_NODE:
- last = None
+ for name in new_uses_libraries:
+ if find_child_with_attribute(application, 'uses-library', android_ns,
+ 'name', name) is not None:
+ # If the uses-library tag of the same 'name' attribute value exists,
+ # respect it.
+ continue
- for name in new_uses_libraries:
- if find_child_with_attribute(application, 'uses-library', android_ns,
- 'name', name) is not None:
- # If the uses-library tag of the same 'name' attribute value exists,
- # respect it.
- continue
+ ul = doc.createElement('uses-library')
+ ul.setAttributeNS(android_ns, 'android:name', name)
+ ul.setAttributeNS(android_ns, 'android:required', str(required).lower())
- ul = doc.createElement('uses-library')
- ul.setAttributeNS(android_ns, 'android:name', name)
- ul.setAttributeNS(android_ns, 'android:required', str(required).lower())
+ application.insertBefore(doc.createTextNode(indent), last)
+ application.insertBefore(ul, last)
- application.insertBefore(doc.createTextNode(indent), last)
- application.insertBefore(ul, last)
-
- # align the closing tag with the opening tag if it's not
- # indented
- if application.lastChild.nodeType != minidom.Node.TEXT_NODE:
- indent = get_indent(application.previousSibling, 1)
- application.appendChild(doc.createTextNode(indent))
+ # align the closing tag with the opening tag if it's not
+ # indented
+ if application.lastChild.nodeType != minidom.Node.TEXT_NODE:
+ indent = get_indent(application.previousSibling, 1)
+ application.appendChild(doc.createTextNode(indent))
def add_uses_non_sdk_api(doc):
@@ -240,111 +198,63 @@
"""
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
-
- attr = application.getAttributeNodeNS(android_ns, 'usesNonSdkApi')
- if attr is None:
- attr = doc.createAttributeNS(android_ns, 'android:usesNonSdkApi')
- attr.value = 'true'
- application.setAttributeNode(attr)
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'usesNonSdkApi')
+ if attr is None:
+ attr = doc.createAttributeNS(android_ns, 'android:usesNonSdkApi')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
def add_use_embedded_dex(doc):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
-
- attr = application.getAttributeNodeNS(android_ns, 'useEmbeddedDex')
- if attr is None:
- attr = doc.createAttributeNS(android_ns, 'android:useEmbeddedDex')
- attr.value = 'true'
- application.setAttributeNode(attr)
- elif attr.value != 'true':
- raise RuntimeError('existing attribute mismatches the option of --use-embedded-dex')
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'useEmbeddedDex')
+ if attr is None:
+ attr = doc.createAttributeNS(android_ns, 'android:useEmbeddedDex')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
+ elif attr.value != 'true':
+ raise RuntimeError('existing attribute mismatches the option of --use-embedded-dex')
def add_extract_native_libs(doc, extract_native_libs):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
-
- value = str(extract_native_libs).lower()
- attr = application.getAttributeNodeNS(android_ns, 'extractNativeLibs')
- if attr is None:
- attr = doc.createAttributeNS(android_ns, 'android:extractNativeLibs')
- attr.value = value
- application.setAttributeNode(attr)
- elif attr.value != value:
- raise RuntimeError('existing attribute extractNativeLibs="%s" conflicts with --extract-native-libs="%s"' %
- (attr.value, value))
+ for application in get_or_create_applications(doc, manifest):
+ value = str(extract_native_libs).lower()
+ attr = application.getAttributeNodeNS(android_ns, 'extractNativeLibs')
+ if attr is None:
+ attr = doc.createAttributeNS(android_ns, 'android:extractNativeLibs')
+ attr.value = value
+ application.setAttributeNode(attr)
+ elif attr.value != value:
+ raise RuntimeError('existing attribute extractNativeLibs="%s" conflicts with --extract-native-libs="%s"' %
+ (attr.value, value))
def set_has_code_to_false(doc):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'hasCode')
+ if attr is not None:
+ # Do nothing if the application already has a hasCode attribute.
+ continue
+ attr = doc.createAttributeNS(android_ns, 'android:hasCode')
+ attr.value = 'false'
+ application.setAttributeNode(attr)
- attr = application.getAttributeNodeNS(android_ns, 'hasCode')
- if attr is not None:
- # Do nothing if the application already has a hasCode attribute.
- return
- attr = doc.createAttributeNS(android_ns, 'android:hasCode')
- attr.value = 'false'
- application.setAttributeNode(attr)
def set_test_only_flag_to_true(doc):
manifest = parse_manifest(doc)
- elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1:
- raise RuntimeError('found multiple <application> tags')
- elif not elems:
- application = doc.createElement('application')
- indent = get_indent(manifest.firstChild, 1)
- first = manifest.firstChild
- manifest.insertBefore(doc.createTextNode(indent), first)
- manifest.insertBefore(application, first)
+ for application in get_or_create_applications(doc, manifest):
+ attr = application.getAttributeNodeNS(android_ns, 'testOnly')
+ if attr is not None:
+ # Do nothing If the application already has a testOnly attribute.
+ continue
+ attr = doc.createAttributeNS(android_ns, 'android:testOnly')
+ attr.value = 'true'
+ application.setAttributeNode(attr)
- attr = application.getAttributeNodeNS(android_ns, 'testOnly')
- if attr is not None:
- # Do nothing If the application already has a testOnly attribute.
- return
- attr = doc.createAttributeNS(android_ns, 'android:testOnly')
- attr.value = 'true'
- application.setAttributeNode(attr)
def set_max_sdk_version(doc, max_sdk_version):
"""Replace the maxSdkVersion attribute value for permission and
@@ -364,6 +274,7 @@
if max_attr and max_attr.value == 'current':
max_attr.value = max_sdk_version
+
def override_placeholder_version(doc, new_version):
"""Replace the versionCode attribute value if it\'s currently
set to the placeholder version of 0.
@@ -374,9 +285,10 @@
"""
manifest = parse_manifest(doc)
version = manifest.getAttribute("android:versionCode")
- if (version == '0'):
+ if version == '0':
manifest.setAttribute("android:versionCode", new_version)
+
def main():
"""Program entry point."""
try:
@@ -427,5 +339,6 @@
print('error: ' + str(err), file=sys.stderr)
sys.exit(-1)
+
if __name__ == '__main__':
main()
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 0a62b10..e4d8dc3 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -20,12 +20,13 @@
import sys
import unittest
from xml.dom import minidom
-import xml.etree.ElementTree as ET
+import xml.etree.ElementTree as ElementTree
import manifest_fixer
sys.dont_write_bytecode = True
+
class CompareVersionGtTest(unittest.TestCase):
"""Unit tests for compare_version_gt function."""
@@ -69,25 +70,24 @@
'%s'
'</manifest>\n')
- # pylint: disable=redefined-builtin
- def uses_sdk(self, min=None, target=None, extra=''):
+ def uses_sdk(self, min_sdk=None, target_sdk=None, extra=''):
attrs = ''
- if min:
- attrs += ' android:minSdkVersion="%s"' % (min)
- if target:
- attrs += ' android:targetSdkVersion="%s"' % (target)
+ if min_sdk:
+ attrs += ' android:minSdkVersion="%s"' % min_sdk
+ if target_sdk:
+ attrs += ' android:targetSdkVersion="%s"' % target_sdk
if extra:
attrs += ' ' + extra
- return ' <uses-sdk%s/>\n' % (attrs)
+ return ' <uses-sdk%s/>\n' % attrs
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def test_no_uses_sdk(self):
"""Tests inserting a uses-sdk element into a manifest."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
@@ -95,7 +95,7 @@
"""Tests inserting a minSdkVersion attribute into a uses-sdk element."""
manifest_input = self.manifest_tmpl % ' <uses-sdk extra="foo"/>\n'
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28',
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28',
extra='extra="foo"')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
@@ -103,64 +103,64 @@
def test_raise_min(self):
"""Tests inserting a minSdkVersion attribute into a uses-sdk element."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
def test_raise(self):
"""Tests raising a minSdkVersion attribute."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='28')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
def test_no_raise_min(self):
"""Tests a minSdkVersion that doesn't need raising."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='28')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='28')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '27', '27', False)
self.assert_xml_equal(output, expected)
def test_raise_codename(self):
"""Tests raising a minSdkVersion attribute to a codename."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='28')
- expected = self.manifest_tmpl % self.uses_sdk(min='P', target='P')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='28')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='P', target_sdk='P')
output = self.raise_min_sdk_version_test(manifest_input, 'P', 'P', False)
self.assert_xml_equal(output, expected)
def test_no_raise_codename(self):
"""Tests a minSdkVersion codename that doesn't need raising."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='P')
- expected = self.manifest_tmpl % self.uses_sdk(min='P', target='28')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='P')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='P', target_sdk='28')
output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
self.assert_xml_equal(output, expected)
def test_target(self):
"""Tests an existing targetSdkVersion is preserved."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='26', target='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='26', target_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
def test_no_target(self):
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='29')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='29')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
def test_target_no_min(self):
""""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(target='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(target_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
@@ -168,23 +168,23 @@
"""Tests inserting targetSdkVersion when minSdkVersion does not exist."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='29')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='29')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', False)
self.assert_xml_equal(output, expected)
def test_library_no_target(self):
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(min='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='16')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(min_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='16')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assert_xml_equal(output, expected)
def test_library_target_no_min(self):
"""Tests inserting targetSdkVersion when minSdkVersion exists."""
- manifest_input = self.manifest_tmpl % self.uses_sdk(target='27')
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='27')
+ manifest_input = self.manifest_tmpl % self.uses_sdk(target_sdk='27')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='27')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assert_xml_equal(output, expected)
@@ -192,7 +192,7 @@
"""Tests inserting targetSdkVersion when minSdkVersion does not exist."""
manifest_input = self.manifest_tmpl % ''
- expected = self.manifest_tmpl % self.uses_sdk(min='28', target='16')
+ expected = self.manifest_tmpl % self.uses_sdk(min_sdk='28', target_sdk='16')
output = self.raise_min_sdk_version_test(manifest_input, '28', '29', True)
self.assert_xml_equal(output, expected)
@@ -228,12 +228,24 @@
self.assert_xml_equal(output, expected)
+ def test_multiple_uses_sdks(self):
+ """Tests a manifest that contains multiple uses_sdks elements."""
+
+ manifest_input = self.manifest_tmpl % (
+ ' <uses-sdk android:featureFlag="foo" android:minSdkVersion="21" />\n'
+ ' <uses-sdk android:featureFlag="!foo" android:minSdkVersion="22" />\n')
+ expected = self.manifest_tmpl % (
+ ' <uses-sdk android:featureFlag="foo" android:minSdkVersion="28" android:targetSdkVersion="28" />\n'
+ ' <uses-sdk android:featureFlag="!foo" android:minSdkVersion="28" android:targetSdkVersion="28" />\n')
+
+ output = self.raise_min_sdk_version_test(manifest_input, '28', '28', False)
+ self.assert_xml_equal(output, expected)
class AddLoggingParentTest(unittest.TestCase):
"""Unit tests for add_logging_parent function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def add_logging_parent_test(self, input_manifest, logging_parent=None):
doc = minidom.parseString(input_manifest)
@@ -253,8 +265,8 @@
attrs = ''
if logging_parent:
meta_text = ('<meta-data android:name="android.content.pm.LOGGING_PARENT" '
- 'android:value="%s"/>\n') % (logging_parent)
- attrs += ' <application>\n %s </application>\n' % (meta_text)
+ 'android:value="%s"/>\n') % logging_parent
+ attrs += ' <application>\n %s </application>\n' % meta_text
return attrs
@@ -277,7 +289,7 @@
"""Unit tests for add_uses_libraries function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, new_uses_libraries):
doc = minidom.parseString(input_manifest)
@@ -289,18 +301,16 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application>\n'
'%s'
- ' </application>\n'
'</manifest>\n')
def uses_libraries(self, name_required_pairs):
- ret = ''
+ ret = ' <application>\n'
for name, required in name_required_pairs:
ret += (
' <uses-library android:name="%s" android:required="%s"/>\n'
) % (name, required)
-
+ ret += ' </application>\n'
return ret
def test_empty(self):
@@ -361,12 +371,23 @@
output = self.run_test(manifest_input, ['foo', 'bar'])
self.assert_xml_equal(output, expected)
+ def test_multiple_application(self):
+ """When there are multiple applications, the libs are added to each."""
+ manifest_input = self.manifest_tmpl % (
+ self.uses_libraries([('foo', 'false')]) +
+ self.uses_libraries([('bar', 'false')]))
+ expected = self.manifest_tmpl % (
+ self.uses_libraries([('foo', 'false'), ('bar', 'true')]) +
+ self.uses_libraries([('bar', 'false'), ('foo', 'true')]))
+ output = self.run_test(manifest_input, ['foo', 'bar'])
+ self.assert_xml_equal(output, expected)
+
class AddUsesNonSdkApiTest(unittest.TestCase):
"""Unit tests for add_uses_libraries function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -378,11 +399,11 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application%s/>\n'
+ ' %s\n'
'</manifest>\n')
def uses_non_sdk_api(self, value):
- return ' android:usesNonSdkApi="true"' if value else ''
+ return '<application %s/>' % ('android:usesNonSdkApi="true"' if value else '')
def test_set_true(self):
"""Empty new_uses_libraries must not touch the manifest."""
@@ -398,12 +419,19 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, expected)
+ def test_multiple_applications(self):
+ """new_uses_libraries must be added to all applications."""
+ manifest_input = self.manifest_tmpl % (self.uses_non_sdk_api(True) + self.uses_non_sdk_api(False))
+ expected = self.manifest_tmpl % (self.uses_non_sdk_api(True) + self.uses_non_sdk_api(True))
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class UseEmbeddedDexTest(unittest.TestCase):
"""Unit tests for add_use_embedded_dex function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -415,14 +443,14 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application%s/>\n'
+ ' %s\n'
'</manifest>\n')
def use_embedded_dex(self, value):
- return ' android:useEmbeddedDex="%s"' % value
+ return '<application android:useEmbeddedDex="%s" />' % value
def test_manifest_with_undeclared_preference(self):
- manifest_input = self.manifest_tmpl % ''
+ manifest_input = self.manifest_tmpl % '<application/>'
expected = self.manifest_tmpl % self.use_embedded_dex('true')
output = self.run_test(manifest_input)
self.assert_xml_equal(output, expected)
@@ -437,12 +465,24 @@
manifest_input = self.manifest_tmpl % self.use_embedded_dex('false')
self.assertRaises(RuntimeError, self.run_test, manifest_input)
+ def test_multiple_applications(self):
+ manifest_input = self.manifest_tmpl % (
+ self.use_embedded_dex('true') +
+ '<application/>'
+ )
+ expected = self.manifest_tmpl % (
+ self.use_embedded_dex('true') +
+ self.use_embedded_dex('true')
+ )
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class AddExtractNativeLibsTest(unittest.TestCase):
"""Unit tests for add_extract_native_libs function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, value):
doc = minidom.parseString(input_manifest)
@@ -454,20 +494,20 @@
manifest_tmpl = (
'<?xml version="1.0" encoding="utf-8"?>\n'
'<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
- ' <application%s/>\n'
+ ' %s\n'
'</manifest>\n')
def extract_native_libs(self, value):
- return ' android:extractNativeLibs="%s"' % value
+ return '<application android:extractNativeLibs="%s" />' % value
def test_set_true(self):
- manifest_input = self.manifest_tmpl % ''
+ manifest_input = self.manifest_tmpl % '<application/>'
expected = self.manifest_tmpl % self.extract_native_libs('true')
output = self.run_test(manifest_input, True)
self.assert_xml_equal(output, expected)
def test_set_false(self):
- manifest_input = self.manifest_tmpl % ''
+ manifest_input = self.manifest_tmpl % '<application/>'
expected = self.manifest_tmpl % self.extract_native_libs('false')
output = self.run_test(manifest_input, False)
self.assert_xml_equal(output, expected)
@@ -482,12 +522,18 @@
manifest_input = self.manifest_tmpl % self.extract_native_libs('true')
self.assertRaises(RuntimeError, self.run_test, manifest_input, False)
+ def test_multiple_applications(self):
+ manifest_input = self.manifest_tmpl % (self.extract_native_libs('true') + '<application/>')
+ expected = self.manifest_tmpl % (self.extract_native_libs('true') + self.extract_native_libs('true'))
+ output = self.run_test(manifest_input, True)
+ self.assert_xml_equal(output, expected)
+
class AddNoCodeApplicationTest(unittest.TestCase):
"""Unit tests for set_has_code_to_false function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -515,7 +561,7 @@
self.assert_xml_equal(output, expected)
def test_has_application_has_code_false(self):
- """ Do nothing if there's already an application elemeent. """
+ """ Do nothing if there's already an application element. """
manifest_input = self.manifest_tmpl % ' <application android:hasCode="false"/>\n'
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
@@ -527,12 +573,25 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
+ def test_multiple_applications(self):
+ """ Apply to all applications """
+ manifest_input = self.manifest_tmpl % (
+ ' <application android:hasCode="true" />\n' +
+ ' <application android:hasCode="false" />\n' +
+ ' <application/>\n')
+ expected = self.manifest_tmpl % (
+ ' <application android:hasCode="true" />\n' +
+ ' <application android:hasCode="false" />\n' +
+ ' <application android:hasCode="false" />\n')
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class AddTestOnlyApplicationTest(unittest.TestCase):
"""Unit tests for set_test_only_flag_to_true function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest):
doc = minidom.parseString(input_manifest)
@@ -571,12 +630,26 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
+ def test_multiple_applications(self):
+ manifest_input = self.manifest_tmpl % (
+ ' <application android:testOnly="true" />\n' +
+ ' <application android:testOnly="false" />\n' +
+ ' <application/>\n'
+ )
+ expected = self.manifest_tmpl % (
+ ' <application android:testOnly="true" />\n' +
+ ' <application android:testOnly="false" />\n' +
+ ' <application android:testOnly="true" />\n'
+ )
+ output = self.run_test(manifest_input)
+ self.assert_xml_equal(output, expected)
+
class SetMaxSdkVersionTest(unittest.TestCase):
"""Unit tests for set_max_sdk_version function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, max_sdk_version):
doc = minidom.parseString(input_manifest)
@@ -591,15 +664,15 @@
'%s'
'</manifest>\n')
- def permission(self, max=None):
- if max is None:
+ def permission(self, max_sdk=None):
+ if max_sdk is None:
return ' <permission/>'
- return ' <permission android:maxSdkVersion="%s"/>\n' % max
+ return ' <permission android:maxSdkVersion="%s"/>\n' % max_sdk
- def uses_permission(self, max=None):
- if max is None:
+ def uses_permission(self, max_sdk=None):
+ if max_sdk is None:
return ' <uses-permission/>'
- return ' <uses-permission android:maxSdkVersion="%s"/>\n' % max
+ return ' <uses-permission android:maxSdkVersion="%s"/>\n' % max_sdk
def test_permission_no_max_sdk_version(self):
"""Tests if permission has no maxSdkVersion attribute"""
@@ -643,11 +716,12 @@
output = self.run_test(manifest_input, '9000')
self.assert_xml_equal(output, expected)
+
class OverrideDefaultVersionTest(unittest.TestCase):
"""Unit tests for override_default_version function."""
def assert_xml_equal(self, output, expected):
- self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+ self.assertEqual(ElementTree.canonicalize(output), ElementTree.canonicalize(expected))
def run_test(self, input_manifest, version):
doc = minidom.parseString(input_manifest)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 7048a15..34e11f0 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -46,8 +46,9 @@
],
}
`, apex, fragment, extraFragments)),
- android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil),
- android.FixtureAddFile("frameworks/base/config/boot-image-profile.txt", nil),
+ android.FixtureAddFile("frameworks/base/boot/boot-profile.txt", nil),
+ android.FixtureAddFile("frameworks/base/boot/boot-image-profile.txt", nil),
+ android.FixtureAddFile("art/build/boot/boot-image-profile.txt", nil),
android.FixtureAddFile("build/soong/scripts/check_boot_jars/package_allowed_list.txt", nil),
)
}
@@ -204,7 +205,19 @@
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core1.jar
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core2.jar
`),
- snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
+ snapshotTestPreparer(checkSnapshotWithoutSource, android.GroupFixturePreparers(
+ preparerForSnapshot,
+ // Flag ART prebuilts
+ android.FixtureMergeMockFs(android.MockFS{
+ "apex_contributions/Android.bp": []byte(`
+ apex_contributions {
+ name: "prebuilt_art_contributions",
+ contents: ["prebuilt_com.android.art"],
+ api_domain: "com.android.art",
+ }
+ `)}),
+ android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"),
+ )),
// Check the behavior of the snapshot without the source.
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
@@ -212,8 +225,8 @@
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
- "out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
+ "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/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,
@@ -276,11 +289,7 @@
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
// Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi
// file creation.
java.FixtureConfigureBootJars("platform:foo"),
@@ -342,6 +351,7 @@
shared_library: false,
public: {enabled: true},
min_sdk_version: "2",
+ sdk_version: "current",
}
java_sdk_library {
@@ -352,6 +362,7 @@
public: {enabled: true},
min_sdk_version: "2",
permitted_packages: ["myothersdklibrary"],
+ sdk_version: "current",
}
java_sdk_library {
@@ -361,6 +372,7 @@
compile_dex: true,
public: {enabled: true},
min_sdk_version: "2",
+ sdk_version: "current",
}
`),
).RunTest(t)
@@ -628,6 +640,7 @@
min_sdk_version: "2",
permitted_packages: ["myothersdklibrary"],
compile_dex: true,
+ sdk_version: "current",
}
`),
@@ -659,6 +672,7 @@
shared_library: false,
public: {enabled: true},
min_sdk_version: "2",
+ sdk_version: "current",
}
`),
).RunTest(t)
@@ -799,11 +813,7 @@
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
android.MockFS{
"my-blocked.txt": nil,
@@ -885,6 +895,7 @@
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
min_sdk_version: "current",
+ sdk_version: "current",
}
java_sdk_library {
@@ -903,6 +914,7 @@
package_prefixes: ["newlibrary.all.mine"],
single_packages: ["newlibrary.mine"],
},
+ sdk_version: "current",
}
`),
).RunTest(t)
@@ -1053,11 +1065,7 @@
variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
android.FixtureWithRootAndroidBp(`
sdk {
@@ -1092,6 +1100,7 @@
shared_library: false,
public: {enabled: true},
min_sdk_version: "S",
+ sdk_version: "current",
}
java_sdk_library {
@@ -1102,6 +1111,7 @@
public: {enabled: true},
min_sdk_version: "Tiramisu",
permitted_packages: ["mynewsdklibrary"],
+ sdk_version: "current",
}
`),
).RunTest(t)
@@ -1299,6 +1309,7 @@
shared_library: false,
public: {enabled: true},
min_sdk_version: "Tiramisu",
+ sdk_version: "current",
}
java_sdk_library {
name: "mynewsdklibrary",
@@ -1308,6 +1319,7 @@
public: {enabled: true},
min_sdk_version: "Tiramisu",
permitted_packages: ["mynewsdklibrary"],
+ sdk_version: "current",
}
`),
).RunTest(t)
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 0a5483b..15e13db 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -45,11 +45,7 @@
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("myjavalib"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
)
// Contains tests for SDK members provided by the java package.
@@ -666,11 +662,7 @@
"1": {"myjavalib"},
"2": {"myjavalib"},
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1313,11 +1305,7 @@
func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -1372,10 +1360,9 @@
}
`),
snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) {
- ctx := android.ModuleInstallPathContextForTesting(result.Config)
dexJarBuildPath := func(name string, kind android.SdkKind) string {
- dep := result.Module(name, "android_common").(java.SdkLibraryDependency)
- path := dep.SdkApiExportableStubDexJar(ctx, kind).Path()
+ sdkLibInfo, _ := android.OtherModuleProvider(result.TestContext.OtherModuleProviderAdaptor(), result.Module(name, "android_common"), java.SdkLibraryInfoProvider)
+ path := sdkLibInfo.ExportableStubDexJarPaths[kind].Path()
return path.RelativeToTop().String()
}
@@ -1715,61 +1702,6 @@
)
}
-func TestSnapshotWithJavaSdkLibrary_NamingScheme(t *testing.T) {
- result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
- sdk {
- name: "mysdk",
- java_sdk_libs: ["myjavalib"],
- }
-
- java_sdk_library {
- name: "myjavalib",
- apex_available: ["//apex_available:anyapex"],
- srcs: ["Test.java"],
- sdk_version: "current",
- naming_scheme: "default",
- public: {
- enabled: true,
- },
- }
- `)
-
- CheckSnapshot(t, result, "mysdk", "",
- checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-apex_contributions_defaults {
- name: "mysdk.contributions",
- contents: ["prebuilt_myjavalib"],
-}
-
-java_sdk_library_import {
- name: "myjavalib",
- prefer: false,
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:anyapex"],
- naming_scheme: "default",
- shared_library: true,
- public: {
- jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
- current_api: "sdk_library/public/myjavalib.txt",
- removed_api: "sdk_library/public/myjavalib-removed.txt",
- sdk_version: "current",
- },
-}
-`),
- checkAllCopyRules(`
-.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
-`),
- checkMergeZips(
- ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
- ),
- )
-}
-
func TestSnapshotWithJavaSdkLibrary_DoctagFiles(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 5b644fd..aa82abb 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -84,20 +84,6 @@
// True if this is a module_exports (or module_exports_snapshot) module type.
Module_exports bool `blueprint:"mutated"`
-
- // The additional visibility to add to the prebuilt modules to allow them to
- // reference each other.
- //
- // This can only be used to widen the visibility of the members:
- //
- // * Specifying //visibility:public here will make all members visible and
- // essentially ignore their own visibility.
- // * Specifying //visibility:private here is an error.
- // * Specifying any other rule here will add it to the members visibility and
- // be output to the member prebuilt in the snapshot. Duplicates will be
- // dropped. Adding a rule to members that have //visibility:private will
- // cause the //visibility:private to be discarded.
- Prebuilt_visibility []string
}
// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
@@ -130,8 +116,6 @@
s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties, &traitsWrapper)
- // Make sure that the prebuilt visibility property is verified for errors.
- android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility)
android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(s)
android.AddLoadHook(s, func(ctx android.LoadHookContext) {
@@ -211,6 +195,11 @@
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) {
+ entries.SetBool("LOCAL_DONT_CHECK_MODULE", true)
+ },
+ },
ExtraFooters: []android.AndroidMkExtraFootersFunc{
func(w io.Writer, name, prefix, moduleDir string) {
// Allow the sdk to be built by simply passing its name on the command line.
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 4894210..2532a25 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -53,9 +53,6 @@
// generated sdk_snapshot.
":__subpackages__",
],
- prebuilt_visibility: [
- "//prebuilts/mysdk",
- ],
java_header_libs: [
"myjavalib",
"mypublicjavalib",
@@ -131,11 +128,7 @@
java_import {
name: "myjavalib",
prefer: false,
- visibility: [
- "//other/foo",
- "//package",
- "//prebuilts/mysdk",
- ],
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
jars: ["java/myjavalib.jar"],
}
@@ -151,11 +144,7 @@
java_import {
name: "mydefaultedjavalib",
prefer: false,
- visibility: [
- "//other/bar",
- "//package",
- "//prebuilts/mysdk",
- ],
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
jars: ["java/mydefaultedjavalib.jar"],
}
@@ -163,50 +152,13 @@
java_import {
name: "myprivatejavalib",
prefer: false,
- visibility: [
- "//package",
- "//prebuilts/mysdk",
- ],
+ visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
jars: ["java/myprivatejavalib.jar"],
}
`))
}
-func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) {
- testSdkError(t, `prebuilt_visibility: cannot mix "//visibility:private" with any other visibility rules`, `
- sdk {
- name: "mysdk",
- prebuilt_visibility: [
- "//foo",
- "//visibility:private",
- ],
- }
-`)
-}
-
-func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) {
- testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, `
- sdk {
- name: "mysdk",
- prebuilt_visibility: [
- "//visibility:private",
- ],
- java_header_libs: [
- "myjavalib",
- ],
- }
-
- java_library {
- name: "myjavalib",
- // Uses package default visibility
- srcs: ["Test.java"],
- system_modules: "none",
- sdk_version: "none",
- }
-`)
-}
-
func TestSdkInstall(t *testing.T) {
sdk := `
sdk {
@@ -457,11 +409,7 @@
android.FixtureMergeEnv(map[string]string{
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
}),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
- }),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTest(t)
CheckSnapshot(t, result, "mysdk", "",
@@ -573,11 +521,9 @@
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
}),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.BuildFlags = map[string]string{
- "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
- }
variables.Platform_version_active_codenames = []string{"UpsideDownCake", "Tiramisu", "S-V2"}
}),
+ android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
).RunTest(t)
CheckSnapshot(t, result, "mysdk", "",
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index c1c4ed6..fd6c4e7 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -80,6 +80,7 @@
dex_preopt: {
profile: "art-profile",
},
+ sdk_version: "current",
}
`),
).RunTest(t)
@@ -110,12 +111,14 @@
apex_available: ["myapex"],
srcs: ["Test.java"],
min_sdk_version: "33", // Tiramisu
+ sdk_version: "current",
}
java_sdk_library {
name: "mysdklibrary-future",
apex_available: ["myapex"],
srcs: ["Test.java"],
min_sdk_version: "34", // UpsideDownCake
+ sdk_version: "current",
}
sdk {
name: "mysdk",
@@ -199,6 +202,7 @@
apex_available: ["myapex"],
srcs: ["Test.java"],
min_sdk_version: "34", // UpsideDownCake
+ sdk_version: "current",
}
sdk {
name: "mysdk",
diff --git a/sdk/update.go b/sdk/update.go
index 198c8d4..7f4f80a 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -22,7 +22,6 @@
"sort"
"strings"
- "android/soong/apex"
"android/soong/cc"
"android/soong/java"
@@ -563,11 +562,11 @@
}
builder.infoContents = string(output)
android.WriteFileRuleVerbatim(ctx, info, builder.infoContents)
- installedInfo := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), info.Base(), info)
+ installedInfo := ctx.InstallFileWithoutCheckbuild(android.PathForMainlineSdksInstall(ctx), info.Base(), info)
s.infoFile = android.OptionalPathForPath(installedInfo)
// Install the zip, making sure that the info file has been installed as well.
- installedZip := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), outputZipFile.Base(), outputZipFile, installedInfo)
+ installedZip := ctx.InstallFileWithoutCheckbuild(android.PathForMainlineSdksInstall(ctx), outputZipFile.Base(), outputZipFile, installedInfo)
s.snapshotFile = android.OptionalPathForPath(installedZip)
}
@@ -1109,20 +1108,24 @@
// same package so can be marked as private.
m.AddProperty("visibility", []string{"//visibility:private"})
} else {
- // Extract visibility information from a member variant. All variants have the same
- // visibility so it doesn't matter which one is used.
- visibilityRules := android.EffectiveVisibilityRules(s.ctx, variant)
-
- // Add any additional visibility rules needed for the prebuilts to reference each other.
- err := visibilityRules.Widen(s.sdk.properties.Prebuilt_visibility)
- if err != nil {
- s.ctx.PropertyErrorf("prebuilt_visibility", "%s", err)
- }
-
- visibility := visibilityRules.Strings()
- if len(visibility) != 0 {
- m.AddProperty("visibility", visibility)
- }
+ // Change the visibility of the module SDK prebuilts to public.
+ // This includes
+ // 1. Stub libraries of `sdk` modules
+ // 2. Binaries and libraries of `module_exports` modules
+ //
+ // This is a workaround to improve maintainlibility of the module SDK.
+ // Since module sdks are generated from release branches and dropped to development
+ // branches, there might be a visibility skew between the sources and prebuilts
+ // of a specific module.
+ // To reconcile this potential skew, change the visibility to public.
+ //
+ // This means dependencies can bypass visibility restrictions when prebuilts are used, so we rely
+ // on source builds in CI to check them.
+ //
+ // TODO (b/361303067): This special case for category (2) can be removed if existing usages
+ // of host/test prebuilts of modules like conscrypt,tzdata,i18n are switched to source builds.
+ // It will also require ART switching to full manifests.
+ m.AddProperty("visibility", []string{"//visibility:public"})
}
// Where available copy apex_available properties from the member.
@@ -1133,9 +1136,6 @@
apexAvailable = []string{android.AvailableToPlatform}
}
- // Add in any baseline apex available settings.
- apexAvailable = append(apexAvailable, apex.BaselineApexAvailable(member.Name())...)
-
// Remove duplicates and sort.
apexAvailable = android.FirstUniqueStrings(apexAvailable)
sort.Strings(apexAvailable)
diff --git a/snapshot/Android.bp b/snapshot/Android.bp
index c384f8a..ae1869a 100644
--- a/snapshot/Android.bp
+++ b/snapshot/Android.bp
@@ -14,12 +14,8 @@
// Source file name convention is to include _snapshot as a
// file suffix for files that are generating snapshots.
srcs: [
- "host_snapshot.go",
"snapshot_base.go",
"util.go",
],
- testSrcs: [
- "host_test.go",
- ],
pluginFor: ["soong_build"],
}
diff --git a/snapshot/host_snapshot.go b/snapshot/host_snapshot.go
deleted file mode 100644
index 1ecab7d..0000000
--- a/snapshot/host_snapshot.go
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package snapshot
-
-import (
- "encoding/json"
- "fmt"
- "path/filepath"
- "sort"
- "strings"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
-
- "android/soong/android"
-)
-
-//
-// The host_snapshot module creates a snapshot of the modules defined in
-// the deps property. The modules within the deps property (host tools)
-// are ones that return a valid path via HostToolPath() of the
-// HostToolProvider. The created snapshot contains the binaries and any
-// transitive PackagingSpecs of the included host tools, along with a JSON
-// meta file.
-//
-// The snapshot is installed into a source tree via
-// development/vendor_snapshot/update.py, the included modules are
-// provided as preferred prebuilts.
-//
-// To determine which tools to include in the host snapshot see
-// host_fake_snapshot.go.
-
-func init() {
- registerHostBuildComponents(android.InitRegistrationContext)
-}
-
-func registerHostBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("host_snapshot", hostSnapshotFactory)
-}
-
-// Relative installation path
-type RelativeInstallPath interface {
- RelativeInstallPath() string
-}
-
-type hostSnapshot struct {
- android.ModuleBase
- android.PackagingBase
-
- outputFile android.OutputPath
- installDir android.InstallPath
-}
-
-type ProcMacro interface {
- ProcMacro() bool
- CrateName() string
-}
-
-func hostSnapshotFactory() android.Module {
- module := &hostSnapshot{}
- initHostToolsModule(module)
- return module
-}
-func initHostToolsModule(module *hostSnapshot) {
- android.InitPackageModule(module)
- android.InitAndroidMultiTargetsArchModule(module, android.HostSupported, android.MultilibCommon)
-}
-
-var dependencyTag = struct {
- blueprint.BaseDependencyTag
- android.InstallAlwaysNeededDependencyTag
- android.PackagingItemAlwaysDepTag
-}{}
-
-func (f *hostSnapshot) DepsMutator(ctx android.BottomUpMutatorContext) {
- f.AddDeps(ctx, dependencyTag)
-}
-func (f *hostSnapshot) installFileName() string {
- return f.Name() + ".zip"
-}
-
-// Create zipfile with JSON description, notice files... for dependent modules
-func (f *hostSnapshot) CreateMetaData(ctx android.ModuleContext, fileName string) android.OutputPath {
- var jsonData []SnapshotJsonFlags
- var metaPaths android.Paths
-
- installedNotices := make(map[string]bool)
- metaZipFile := android.PathForModuleOut(ctx, fileName).OutputPath
-
- // Create JSON file based on the direct dependencies
- ctx.VisitDirectDeps(func(dep android.Module) {
- desc := hostJsonDesc(ctx, dep)
- if desc != nil {
- jsonData = append(jsonData, *desc)
- }
- for _, notice := range dep.EffectiveLicenseFiles() {
- if _, ok := installedNotices[notice.String()]; !ok {
- installedNotices[notice.String()] = true
- noticeOut := android.PathForModuleOut(ctx, "NOTICE_FILES", notice.String()).OutputPath
- CopyFileToOutputPathRule(pctx, ctx, notice, noticeOut)
- metaPaths = append(metaPaths, noticeOut)
- }
- }
- })
- // Sort notice paths and json data for repeatble build
- sort.Slice(jsonData, func(i, j int) bool {
- return (jsonData[i].ModuleName < jsonData[j].ModuleName)
- })
- sort.Slice(metaPaths, func(i, j int) bool {
- return (metaPaths[i].String() < metaPaths[j].String())
- })
-
- marsh, err := json.Marshal(jsonData)
- if err != nil {
- ctx.ModuleErrorf("host snapshot json marshal failure: %#v", err)
- return android.OutputPath{}
- }
-
- jsonZipFile := android.PathForModuleOut(ctx, "host_snapshot.json").OutputPath
- metaPaths = append(metaPaths, jsonZipFile)
- rspFile := android.PathForModuleOut(ctx, "host_snapshot.rsp").OutputPath
- android.WriteFileRule(ctx, jsonZipFile, string(marsh))
-
- builder := android.NewRuleBuilder(pctx, ctx)
-
- builder.Command().
- BuiltTool("soong_zip").
- FlagWithArg("-C ", android.PathForModuleOut(ctx).OutputPath.String()).
- FlagWithOutput("-o ", metaZipFile).
- FlagWithRspFileInputList("-r ", rspFile, metaPaths)
- builder.Build("zip_meta", fmt.Sprintf("zipping meta data for %s", ctx.ModuleName()))
-
- return metaZipFile
-}
-
-// Create the host tool zip file
-func (f *hostSnapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Create a zip file for the binaries, and a zip of the meta data, then merge zips
- depsZipFile := android.PathForModuleOut(ctx, f.Name()+"_deps.zip").OutputPath
- modsZipFile := android.PathForModuleOut(ctx, f.Name()+"_mods.zip").OutputPath
- f.outputFile = android.PathForModuleOut(ctx, f.installFileName()).OutputPath
-
- f.installDir = android.PathForModuleInstall(ctx)
-
- f.CopyDepsToZip(ctx, f.GatherPackagingSpecs(ctx), depsZipFile)
-
- builder := android.NewRuleBuilder(pctx, ctx)
- builder.Command().
- BuiltTool("zip2zip").
- FlagWithInput("-i ", depsZipFile).
- FlagWithOutput("-o ", modsZipFile).
- Text("**/*:" + proptools.ShellEscape(f.installDir.String()))
-
- metaZipFile := f.CreateMetaData(ctx, f.Name()+"_meta.zip")
-
- builder.Command().
- BuiltTool("merge_zips").
- Output(f.outputFile).
- Input(metaZipFile).
- Input(modsZipFile)
-
- builder.Build("manifest", fmt.Sprintf("Adding manifest %s", f.installFileName()))
- ctx.InstallFile(f.installDir, f.installFileName(), f.outputFile)
-
-}
-
-// Implements android.AndroidMkEntriesProvider
-func (f *hostSnapshot) AndroidMkEntries() []android.AndroidMkEntries {
- return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "ETC",
- OutputFile: android.OptionalPathForPath(f.outputFile),
- DistFiles: android.MakeDefaultDistFiles(f.outputFile),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", f.installDir.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", f.installFileName())
- },
- },
- }}
-}
-
-// Get host tools path and relative install string helpers
-func hostToolPath(m android.Module) android.OptionalPath {
- if provider, ok := m.(android.HostToolProvider); ok {
- return provider.HostToolPath()
- }
- return android.OptionalPath{}
-
-}
-func hostRelativePathString(m android.Module) string {
- var outString string
- if rel, ok := m.(RelativeInstallPath); ok {
- outString = rel.RelativeInstallPath()
- }
- return outString
-}
-
-// Create JSON description for given module, only create descriptions for binary modules
-// and rust_proc_macro modules which provide a valid HostToolPath
-func hostJsonDesc(ctx android.ConfigAndErrorContext, m android.Module) *SnapshotJsonFlags {
- path := hostToolPath(m)
- relPath := hostRelativePathString(m)
- procMacro := false
- moduleStem := filepath.Base(path.String())
- crateName := ""
-
- if pm, ok := m.(ProcMacro); ok && pm.ProcMacro() {
- procMacro = pm.ProcMacro()
- moduleStem = strings.TrimSuffix(moduleStem, filepath.Ext(moduleStem))
- crateName = pm.CrateName()
- }
-
- if path.Valid() && path.String() != "" {
- props := &SnapshotJsonFlags{
- ModuleStemName: moduleStem,
- Filename: path.String(),
- Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames(ctx)...),
- RelativeInstallPath: relPath,
- RustProcMacro: procMacro,
- CrateName: crateName,
- }
- props.InitBaseSnapshotProps(m)
- return props
- }
- return nil
-}
diff --git a/snapshot/host_test.go b/snapshot/host_test.go
deleted file mode 100644
index c68fdaf..0000000
--- a/snapshot/host_test.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package snapshot
-
-import (
- "path/filepath"
- "testing"
-
- "android/soong/android"
-)
-
-// host_snapshot and host-fake-snapshot test functions
-
-type hostTestModule struct {
- android.ModuleBase
- props struct {
- Deps []string
- }
-}
-
-func hostTestBinOut(bin string) string {
- return filepath.Join("out", "bin", bin)
-}
-
-func (c *hostTestModule) HostToolPath() android.OptionalPath {
- return (android.OptionalPathForPath(android.PathForTesting(hostTestBinOut(c.Name()))))
-}
-
-func hostTestModuleFactory() android.Module {
- m := &hostTestModule{}
- m.AddProperties(&m.props)
- android.InitAndroidArchModule(m, android.HostSupported, android.MultilibFirst)
- return m
-}
-func (m *hostTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- builtFile := android.PathForModuleOut(ctx, m.Name())
- dir := ctx.Target().Arch.ArchType.Multilib
- installDir := android.PathForModuleInstall(ctx, dir)
- ctx.InstallFile(installDir, m.Name(), builtFile)
-}
-
-// Common blueprint used for testing
-var hostTestBp = `
- license_kind {
- name: "test_notice",
- conditions: ["notice"],
- }
- license {
- name: "host_test_license",
- visibility: ["//visibility:public"],
- license_kinds: [
- "test_notice"
- ],
- license_text: [
- "NOTICE",
- ],
- }
- component {
- name: "foo",
- deps: ["bar"],
- }
- component {
- name: "bar",
- licenses: ["host_test_license"],
- }
- `
-
-var hostTestModBp = `
- host_snapshot {
- name: "test-host-snapshot",
- deps: [
- "foo",
- ],
- }
- `
-
-var prepareForHostTest = android.GroupFixturePreparers(
- android.PrepareForTestWithAndroidBuildComponents,
- android.PrepareForTestWithLicenses,
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("component", hostTestModuleFactory)
- }),
-)
-
-// Prepare for host_snapshot test
-var prepareForHostModTest = android.GroupFixturePreparers(
- prepareForHostTest,
- android.FixtureWithRootAndroidBp(hostTestBp+hostTestModBp),
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- registerHostBuildComponents(ctx)
- }),
-)
-
-// Prepare for fake host snapshot test disabled
-var prepareForFakeHostTest = android.GroupFixturePreparers(
- prepareForHostTest,
- android.FixtureWithRootAndroidBp(hostTestBp),
-)
-
-// Validate that a hostSnapshot object is created containing zip files and JSON file
-// content of zip file is not validated as this is done by PackagingSpecs
-func TestHostSnapshot(t *testing.T) {
- result := prepareForHostModTest.RunTest(t)
- t.Helper()
- ctx := result.TestContext.ModuleForTests("test-host-snapshot", result.Config.BuildOS.String()+"_common")
- mod := ctx.Module().(*hostSnapshot)
- if ctx.MaybeOutput("host_snapshot.json").Rule == nil {
- t.Error("Manifest file not found")
- }
- zips := []string{"_deps.zip", "_mods.zip", ".zip"}
-
- for _, zip := range zips {
- zFile := mod.Name() + zip
- if ctx.MaybeOutput(zFile).Rule == nil {
- t.Error("Zip file ", zFile, "not found")
- }
-
- }
-}
diff --git a/soong_ui.bash b/soong_ui.bash
index 7737880..be78b68 100755
--- a/soong_ui.bash
+++ b/soong_ui.bash
@@ -14,18 +14,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../make/shell_utils.sh
+require_top
+
# To track how long we took to startup.
case $(uname -s) in
Darwin)
- export TRACE_BEGIN_SOONG=`$T/prebuilts/build-tools/path/darwin-x86/date +%s%3N`
+ export TRACE_BEGIN_SOONG=`$TOP/prebuilts/build-tools/path/darwin-x86/date +%s%3N`
;;
*)
export TRACE_BEGIN_SOONG=$(date +%s%N)
;;
esac
-source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../make/shell_utils.sh
-require_top
+setup_cog_env_if_needed
# Save the current PWD for use in soong_ui
export ORIGINAL_PWD=${PWD}
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
index a00a5e4..22cba3b 100644
--- a/sysprop/Android.bp
+++ b/sysprop/Android.bp
@@ -21,4 +21,6 @@
"sysprop_test.go",
],
pluginFor: ["soong_build"],
+ // Used by plugins
+ visibility: ["//visibility:public"],
}
diff --git a/testing/all_code_metadata.go b/testing/all_code_metadata.go
index 12aa7b5..e89b281 100644
--- a/testing/all_code_metadata.go
+++ b/testing/all_code_metadata.go
@@ -21,7 +21,7 @@
ctx.VisitAllModules(
func(module android.Module) {
- if metadata, ok := android.SingletonModuleProvider(ctx, module, CodeMetadataProviderKey); ok {
+ if metadata, ok := android.OtherModuleProvider(ctx, module, CodeMetadataProviderKey); ok {
intermediateMetadataPaths = append(intermediateMetadataPaths, metadata.IntermediatePath)
}
},
diff --git a/testing/all_test_specs.go b/testing/all_test_specs.go
index b035435..68f24d1 100644
--- a/testing/all_test_specs.go
+++ b/testing/all_test_specs.go
@@ -21,7 +21,7 @@
var intermediateMetadataPaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if metadata, ok := android.SingletonModuleProvider(ctx, module, TestSpecProviderKey); ok {
+ if metadata, ok := android.OtherModuleProvider(ctx, module, TestSpecProviderKey); ok {
intermediateMetadataPaths = append(intermediateMetadataPaths, metadata.IntermediatePath)
}
})
diff --git a/testing/code_metadata_internal_proto/Android.bp b/testing/code_metadata_internal_proto/Android.bp
index a534cc2..396e44f 100644
--- a/testing/code_metadata_internal_proto/Android.bp
+++ b/testing/code_metadata_internal_proto/Android.bp
@@ -20,10 +20,14 @@
name: "soong-testing-code_metadata_internal_proto",
pkgPath: "android/soong/testing/code_metadata_internal_proto",
deps: [
- "golang-protobuf-reflect-protoreflect",
- "golang-protobuf-runtime-protoimpl",
- ],
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
srcs: [
"code_metadata_internal.pb.go",
],
+ visibility: [
+ "//build/make/tools/metadata",
+ "//build/soong:__subpackages__",
+ ],
}
diff --git a/testing/code_metadata_proto/Android.bp b/testing/code_metadata_proto/Android.bp
index f07efff..ae41d4a 100644
--- a/testing/code_metadata_proto/Android.bp
+++ b/testing/code_metadata_proto/Android.bp
@@ -26,6 +26,7 @@
srcs: [
"code_metadata.pb.go",
],
+ visibility: ["//build/make/tools/metadata"],
}
python_library_host {
@@ -40,4 +41,5 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: ["//tools/asuite/team_build_scripts"],
}
diff --git a/testing/test_spec_proto/Android.bp b/testing/test_spec_proto/Android.bp
index d5ad70b..1070d1a 100644
--- a/testing/test_spec_proto/Android.bp
+++ b/testing/test_spec_proto/Android.bp
@@ -26,6 +26,11 @@
srcs: [
"test_spec.pb.go",
],
+ visibility: [
+ "//build/make/tools/metadata",
+ "//build/soong:__subpackages__",
+ "//vendor:__subpackages__",
+ ],
}
python_library_host {
@@ -40,4 +45,5 @@
proto: {
canonical_path_from_root: false,
},
+ visibility: ["//tools/asuite/team_build_scripts"],
}
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 2e40950..715f976 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -145,36 +145,19 @@
run_soong
local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
- local glob_deps_file=out/soong/globs/"${target_product}"/0.d
-
run_soong
local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
- # There is an ineffiencency in glob that requires bpglob to rerun once for each glob to update
- # the entry in the .ninja_log. It doesn't update the output file, but we can detect the rerun
- # by checking if the deps file was created.
- if [ ! -e "$glob_deps_file" ]; then
- fail "Glob deps file missing after second build"
- fi
-
- local -r glob_deps_mtime2=$(stat -c "%y" "$glob_deps_file")
-
if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
fail "Ninja file rewritten on null incremental build"
fi
run_soong
local -r ninja_mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
- local -r glob_deps_mtime3=$(stat -c "%y" "$glob_deps_file")
if [[ "$ninja_mtime2" != "$ninja_mtime3" ]]; then
fail "Ninja file rewritten on null incremental build"
fi
-
- # The bpglob commands should not rerun after the first incremental build.
- if [[ "$glob_deps_mtime2" != "$glob_deps_mtime3" ]]; then
- fail "Glob deps file rewritten on second null incremental build"
- fi
}
function test_add_file_to_glob() {
diff --git a/tests/build_action_caching_test.sh b/tests/build_action_caching_test.sh
new file mode 100755
index 0000000..8ecd037
--- /dev/null
+++ b/tests/build_action_caching_test.sh
@@ -0,0 +1,190 @@
+#!/bin/bash -u
+
+set -o pipefail
+
+# Test that the mk and ninja files generated by Soong don't change if some
+# incremental modules are restored from cache.
+
+OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)"
+
+echo ${OUTPUT_DIR}
+
+function cleanup {
+ rm -rf "${OUTPUT_DIR}"
+}
+trap cleanup EXIT
+
+function run_soong_build {
+ USE_RBE=false TARGET_PRODUCT=aosp_arm TARGET_RELEASE=trunk_staging TARGET_BUILD_VARIANT=userdebug build/soong/soong_ui.bash --make-mode "$@" nothing
+}
+
+function run_soong_clean {
+ build/soong/soong_ui.bash --make-mode clean
+}
+
+function assert_files_equal {
+ if [ $# -ne 2 ]; then
+ echo "Usage: assert_files_equal file1 file2"
+ exit 1
+ fi
+
+ if ! cmp -s "$1" "$2"; then
+ echo "Files are different: $1 $2"
+ exit 1
+ fi
+}
+
+function compare_mtimes() {
+ if [ $# -ne 2 ]; then
+ echo "Usage: compare_mtimes file1 file2"
+ exit 1
+ fi
+
+ file1_mtime=$(stat -c '%Y' $1)
+ file2_mtime=$(stat -c '%Y' $2)
+
+ if [ "$file1_mtime" -eq "$file2_mtime" ]; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+function test_build_action_restoring() {
+ local test_dir="${OUTPUT_DIR}/test_build_action_restoring"
+ mkdir -p ${test_dir}
+ run_soong_clean
+ cat > ${test_dir}/Android.bp <<'EOF'
+python_binary_host {
+ name: "my_little_binary_host",
+ srcs: ["my_little_binary_host.py"],
+}
+EOF
+ touch ${test_dir}/my_little_binary_host.py
+ run_soong_build --incremental-build-actions
+ local dir_before="${test_dir}/before"
+ mkdir -p ${dir_before}
+ cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/before
+ # add a comment to the bp file, this should force a new analysis but no module
+ # should be really impacted, so all the incremental modules should be skipped.
+ cat >> ${test_dir}/Android.bp <<'EOF'
+// new comments
+EOF
+ run_soong_build --incremental-build-actions
+ local dir_after="${test_dir}/after"
+ mkdir -p ${dir_after}
+ cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/after
+
+ compare_incremental_files $dir_before $dir_after
+ rm -rf "$test_dir"
+ echo "test_build_action_restoring test passed"
+}
+
+function test_incremental_build_parity() {
+ local test_dir="${OUTPUT_DIR}/test_incremental_build_parity"
+ run_soong_clean
+ run_soong_build
+ local dir_before="${test_dir}/before"
+ mkdir -p ${dir_before}
+ cp -pr out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/before
+
+ # Now run clean build with incremental enabled
+ run_soong_clean
+ run_soong_build --incremental-build-actions
+ local dir_after="${test_dir}/after"
+ mkdir -p ${dir_after}
+ cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm*.ninja ${test_dir}/after
+
+ compare_files_parity $dir_before $dir_after
+ rm -rf "$test_dir"
+ echo "test_incremental_build_parity test passed"
+}
+
+function compare_files_parity() {
+ local dir_before=$1; shift
+ local dir_after=$1; shift
+ count=0
+ for file_before in ${dir_before}/*.mk; do
+ file_after="${dir_after}/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ ((count++))
+ done
+ echo "Compared $count mk files"
+
+ combined_before_file="${dir_before}/combined_files.ninja"
+ count=0
+ for file in ${dir_before}/build.aosp_arm.*.ninja; do
+ cat $file >> $combined_before_file
+ ((count++))
+ done
+ echo "Combined $count ninja files from normal build"
+
+ combined_after_file="${dir_after}/combined_files.ninja"
+ count=0
+ for file in ${dir_after}/build.aosp_arm.*.ninja; do
+ cat $file >> $combined_after_file
+ ((count++))
+ done
+ echo "Combined $count ninja files from incremental build"
+
+ combined_incremental_ninjas="${dir_after}/combined_incremental_files.ninja"
+ count=0
+ for file in ${dir_after}/build_aosp_arm_ninja_incremental/*.ninja; do
+ cat $file >> $combined_incremental_ninjas
+ ((count++))
+ done
+ echo "Combined $count incremental ninja files"
+
+ cat $combined_incremental_ninjas >> $combined_after_file
+ sort $combined_after_file -o $combined_after_file
+ sort $combined_before_file -o $combined_before_file
+ assert_files_equal $combined_before_file $combined_after_file
+}
+
+function compare_incremental_files() {
+ local dir_before=$1; shift
+ local dir_after=$1; shift
+ count=0
+ for file_before in ${dir_before}/*.ninja; do
+ file_after="${dir_after}/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ compare_mtimes $file_before $file_after
+ if [ $? -ne 0 ]; then
+ echo "Files have identical mtime: $file_before $file_after"
+ exit 1
+ fi
+ ((count++))
+ done
+ echo "Compared $count ninja files"
+
+ count=0
+ for file_before in ${dir_before}/*.mk; do
+ file_after="${dir_after}/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ compare_mtimes $file_before $file_after
+ # mk files shouldn't be regenerated
+ if [ $? -ne 1 ]; then
+ echo "Files have different mtimes: $file_before $file_after"
+ exit 1
+ fi
+ ((count++))
+ done
+ echo "Compared $count mk files"
+
+ count=0
+ for file_before in ${dir_before}/build_aosp_arm_ninja_incremental/*.ninja; do
+ file_after="${dir_after}/build_aosp_arm_ninja_incremental/$(basename "$file_before")"
+ assert_files_equal $file_before $file_after
+ compare_mtimes $file_before $file_after
+ # ninja files of skipped modules shouldn't be regenerated
+ if [ $? -ne 1 ]; then
+ echo "Files have different mtimes: $file_before $file_after"
+ exit 1
+ fi
+ ((count++))
+ done
+ echo "Compared $count incremental ninja files"
+}
+
+test_incremental_build_parity
+test_build_action_restoring
diff --git a/tests/run_tool_with_logging_test.py b/tests/run_tool_with_logging_test.py
index 57a6d62..1a946a1 100644
--- a/tests/run_tool_with_logging_test.py
+++ b/tests/run_tool_with_logging_test.py
@@ -193,7 +193,7 @@
logger_path = self._import_executable("tool_event_logger")
self._run_script_and_wait(f"""
- TMPDIR="{self.working_dir.name}"
+ export TMPDIR="{self.working_dir.name}"
export ANDROID_TOOL_LOGGER="{logger_path}"
export ANDROID_TOOL_LOGGER_EXTRA_ARGS="--dry_run"
{self.logging_script_path} "FAKE_TOOL" {test_tool.executable} arg1 arg2
@@ -206,7 +206,7 @@
logger_path = self._import_executable("tool_event_logger")
self._run_script_and_wait(f"""
- TMPDIR="{self.working_dir.name}"
+ export TMPDIR="{self.working_dir.name}"
export ANDROID_TOOL_LOGGER="{logger_path}"
export ANDROID_TOOL_LOGGER_EXTRA_ARGS="--dry_run"
{self.logging_script_path} "FAKE_TOOL" {test_tool.executable} --tool-arg1
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 794003d..0471853 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -76,8 +76,8 @@
mkdir -p $sbom_test
cp $product_out/*.img $sbom_test
- # m sbom soong-sbom
- run_soong "${out_dir}" "sbom soong-sbom"
+ # m sbom
+ run_soong "${out_dir}" "sbom"
# Generate installed file list from .img files in PRODUCT_OUT
dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
@@ -118,7 +118,6 @@
for f in $EROFS_IMAGES; do
partition_name=$(basename $f | cut -d. -f1)
file_list_file="${sbom_test}/sbom-${partition_name}-files.txt"
- files_in_spdx_file="${sbom_test}/sbom-${partition_name}-files-in-spdx.txt"
files_in_soong_spdx_file="${sbom_test}/soong-sbom-${partition_name}-files-in-spdx.txt"
rm "$file_list_file" > /dev/null 2>&1 || true
all_dirs="/"
@@ -147,34 +146,22 @@
done
sort -n -o "$file_list_file" "$file_list_file"
- # Diff the file list from image and file list in SBOM created by Make
- grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' > "$files_in_spdx_file"
- if [ "$partition_name" = "system" ]; then
- # system partition is mounted to /, so include FileName starts with /root/ too.
- grep "FileName: /root/" $product_out/sbom.spdx | sed 's/^FileName: \/root//' >> "$files_in_spdx_file"
- fi
- sort -n -o "$files_in_spdx_file" "$files_in_spdx_file"
-
- echo ============ Diffing files in $f and SBOM
- diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name" ""
-
# Diff the file list from image and file list in SBOM created by Soong
grep "FileName: /${partition_name}/" $soong_sbom_out/sbom.spdx | sed 's/^FileName: //' > "$files_in_soong_spdx_file"
- if [ "$partition_name" = "system" ]; then
- # system partition is mounted to /, so include FileName starts with /root/ too.
- grep "FileName: /root/" $soong_sbom_out/sbom.spdx | sed 's/^FileName: \/root//' >> "$files_in_soong_spdx_file"
- fi
- sort -n -o "$files_in_soong_spdx_file" "$files_in_soong_spdx_file"
+ if [ "$partition_name" = "system" ]; then
+ # system partition is mounted to /, so include FileName starts with /root/ too.
+ grep "FileName: /root/" $soong_sbom_out/sbom.spdx | sed 's/^FileName: \/root//' >> "$files_in_soong_spdx_file"
+ fi
+ 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" ""
+ echo ============ Diffing files in $f and SBOM created by Soong
+ diff_files "$file_list_file" "$files_in_soong_spdx_file" "$partition_name" ""
done
RAMDISK_IMAGES="$product_out/ramdisk.img"
for f in $RAMDISK_IMAGES; do
partition_name=$(basename $f | cut -d. -f1)
file_list_file="${sbom_test}/sbom-${partition_name}-files.txt"
- files_in_spdx_file="${sbom_test}/sbom-${partition_name}-files-in-spdx.txt"
files_in_soong_spdx_file="${sbom_test}/sbom-${partition_name}-files-in-soong-spdx.txt"
# lz4 decompress $f to stdout
# cpio list all entries like ls -l
@@ -183,18 +170,12 @@
# sed remove partition name from entry names
$lz4 -c -d $f | cpio -tv 2>/dev/null | grep '^[-l]' | awk -F ' ' '{print $9}' | sed "s:^:/$partition_name/:" | sort -n > "$file_list_file"
- grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' | sort -n > "$files_in_spdx_file"
-
grep "FileName: /${partition_name}/" $soong_sbom_out/sbom.spdx | sed 's/^FileName: //' | sort -n > "$files_in_soong_spdx_file"
- echo ============ Diffing files in $f and SBOM
- diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name" ""
-
echo ============ Diffing files in $f and SBOM created by Soong
diff_files "$file_list_file" "$files_in_soong_spdx_file" "$partition_name" ""
done
- verify_package_verification_code "$product_out/sbom.spdx"
verify_package_verification_code "$soong_sbom_out/sbom.spdx"
verify_packages_licenses "$soong_sbom_out/sbom.spdx"
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index ddd0a80..e230795 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -196,16 +196,16 @@
}
var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{
- Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template ${extraConfigs}",
+ Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template ${extraConfigs} ${extraTestRunnerConfigs}",
CommandDeps: []string{
"${AutoGenTestConfigScript}",
"${EmptyTestConfig}",
"$template",
},
-}, "name", "template", "extraConfigs")
+}, "name", "template", "extraConfigs", "extraTestRunnerConfigs")
func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string,
- testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool, configs []Config) android.Path {
+ testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool, configs []Config, testRunnerConfigs []Option) android.Path {
path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
var configStrings []string
if autogenPath != nil {
@@ -220,15 +220,26 @@
extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent))
extraConfigs = fmt.Sprintf("--extra-configs '%s'", extraConfigs)
+ var testRunnerConfigStrings []string
+ for _, config := range testRunnerConfigs {
+ testRunnerConfigStrings = append(testRunnerConfigStrings, config.Config())
+ }
+ extraTestRunnerConfigs := strings.Join(testRunnerConfigStrings, fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent))
+ if len(extraTestRunnerConfigs) > 0 {
+ extraTestRunnerConfigs += fmt.Sprintf("\\n%s%s", test_xml_indent, test_xml_indent)
+ }
+ extraTestRunnerConfigs = fmt.Sprintf("--extra-test-runner-configs '%s'", extraTestRunnerConfigs)
+
ctx.Build(pctx, android.BuildParams{
Rule: autogenInstrumentationTest,
Description: "test config",
Input: manifest,
Output: autogenPath,
Args: map[string]string{
- "name": ctx.ModuleName(),
- "template": template,
- "extraConfigs": extraConfigs,
+ "name": ctx.ModuleName(),
+ "template": template,
+ "extraConfigs": extraConfigs,
+ "extraTestRunnerConfigs": extraTestRunnerConfigs,
},
})
return autogenPath
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
index f9622d3..7a04c19 100644
--- a/tradefed_modules/test_module_config.go
+++ b/tradefed_modules/test_module_config.go
@@ -6,6 +6,7 @@
"encoding/json"
"fmt"
"io"
+ "slices"
"strings"
"github.com/google/blueprint"
@@ -174,6 +175,20 @@
return false
}
+ var extra_derived_suites []string
+ // Ensure all suites listed are also in base.
+ for _, s := range m.tradefedProperties.Test_suites {
+ if !slices.Contains(m.provider.TestSuites, s) {
+ extra_derived_suites = append(extra_derived_suites, s)
+ }
+ }
+ if len(extra_derived_suites) != 0 {
+ ctx.ModuleErrorf("Suites: [%s] listed but do not exist in base module: %s",
+ strings.Join(extra_derived_suites, ", "),
+ *m.tradefedProperties.Base)
+ return false
+ }
+
return true
}
@@ -227,6 +242,7 @@
entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", m.provider.IsUnitTest)
entries.AddCompatibilityTestSuites(m.tradefedProperties.Test_suites...)
+ entries.AddStrings("LOCAL_HOST_REQUIRED_MODULES", m.provider.HostRequiredModuleNames...)
// The app_prebuilt_internal.mk files try create a copy of the OutputFile as an .apk.
// Normally, this copies the "package.apk" from the intermediate directory here.
diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go
index 97179f5..f76a152 100644
--- a/tradefed_modules/test_module_config_test.go
+++ b/tradefed_modules/test_module_config_test.go
@@ -40,6 +40,8 @@
name: "base",
sdk_version: "current",
data: [":HelperApp", "data/testfile"],
+ host_required: ["other-module"],
+ test_suites: ["general-tests"],
}
test_module_config {
@@ -79,6 +81,7 @@
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"], []string{})
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_REQUIRED_MODULES"], []string{"base"})
+ android.AssertArrayString(t, "", entries.EntryMap["LOCAL_HOST_REQUIRED_MODULES"], []string{"other-module"})
android.AssertArrayString(t, "", entries.EntryMap["LOCAL_CERTIFICATE"], []string{"build/make/target/product/security/testkey.x509.pem"})
android.AssertStringEquals(t, "", entries.Class, "APPS")
@@ -160,7 +163,7 @@
java.PrepareForTestWithJavaDefaultModules,
android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
).ExtendWithErrorHandler(
- android.FixtureExpectsOneErrorPattern("'base' module used as base but it is not a 'android_test' module.")).
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("'base' module used as base but it is not a 'android_test' module.")).
RunTestWithBp(t, badBp)
}
@@ -193,6 +196,7 @@
name: "base",
sdk_version: "current",
srcs: ["a.java"],
+ test_suites: ["general-tests"],
}
test_module_config {
@@ -218,6 +222,7 @@
sdk_version: "current",
srcs: ["a.java"],
data: [":HelperApp", "data/testfile"],
+ test_suites: ["general-tests"],
}
android_test_helper_app {
@@ -362,6 +367,31 @@
RunTestWithBp(t, badBp)
}
+func TestModuleConfigNonMatchingTestSuitesGiveErrors(t *testing.T) {
+ badBp := `
+ java_test_host {
+ name: "base",
+ srcs: ["a.java"],
+ test_suites: ["general-tests", "some-compat"],
+ }
+
+ test_module_config_host {
+ name: "derived_test",
+ base: "base",
+ exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"],
+ include_annotations: ["android.platform.test.annotations.LargeTest"],
+ test_suites: ["device-tests", "random-suite"],
+ }`
+
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents),
+ ).ExtendWithErrorHandler(
+ // Use \\ to escape bracket so it isn't used as [] set for regex.
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern("Suites: \\[device-tests, random-suite] listed but do not exist in base module")).
+ RunTestWithBp(t, badBp)
+}
+
func TestTestOnlyProvider(t *testing.T) {
t.Parallel()
ctx := android.GroupFixturePreparers(
@@ -389,6 +419,7 @@
name: "base",
sdk_version: "current",
data: ["data/testfile"],
+ test_suites: ["general-tests"],
}
java_test_host {
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index bbac2db..2ec8972 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -25,6 +25,8 @@
"dalvik/",
"developers/",
"development/",
+ "device/common/",
+ "device/google_car/",
"device/sample/",
"frameworks/",
// Do not block other directories in kernel/, see b/319658303.
@@ -33,6 +35,7 @@
"kernel/tests/",
"libcore/",
"libnativehelper/",
+ "packages/",
"pdk/",
"prebuilts/",
"sdk/",
@@ -40,6 +43,15 @@
"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/",
}
func blockAndroidMks(ctx Context, androidMks []string) {
diff --git a/ui/build/build.go b/ui/build/build.go
index 49ac791..28c3284 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -80,7 +80,7 @@
if username, ok = config.environ.Get("BUILD_USERNAME"); !ok {
ctx.Fatalln("Missing BUILD_USERNAME")
}
- buildNumber = fmt.Sprintf("eng.%.6s.00000000.000000", username)
+ buildNumber = fmt.Sprintf("eng.%.6s", username)
writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username)
}
// Write the build number to a file so it can be read back in
diff --git a/ui/build/config.go b/ui/build/config.go
index 631b76f..75edfcd 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -41,6 +41,7 @@
const (
envConfigDir = "vendor/google/tools/soong_config"
jsonSuffix = "json"
+ abfsSrcDir = "/src"
)
var (
@@ -53,6 +54,16 @@
rbeRandPrefix = rand.Intn(1000)
}
+// Which builder are we using?
+type ninjaCommandType = int
+
+const (
+ _ = iota
+ NINJA_NINJA
+ NINJA_N2
+ NINJA_SISO
+)
+
type Config struct{ *configImpl }
type configImpl struct {
@@ -87,6 +98,7 @@
buildFromSourceStub bool
incrementalBuildActions bool
ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
+ partialCompileFlags partialCompileFlags
// From the product config
katiArgs []string
@@ -122,9 +134,18 @@
// could consider merging them.
moduleDebugFile string
- // Whether to use n2 instead of ninja. This is controlled with the
- // environment variable SOONG_USE_N2
- useN2 bool
+ // Which builder are we using
+ ninjaCommand ninjaCommandType
+}
+
+type partialCompileFlags struct {
+ // Is partial compilation enabled at all?
+ enabled bool
+
+ // Whether to use d8 instead of r8
+ use_d8 bool
+
+ // Add others as needed.
}
type NinjaWeightListSource uint
@@ -214,6 +235,10 @@
sandboxConfig: &SandboxConfig{},
ninjaWeightListSource: DEFAULT,
}
+ wd, err := os.Getwd()
+ if err != nil {
+ ctx.Fatalln("Failed to get working directory:", err)
+ }
// Skip soong tests by default on Linux
if runtime.GOOS == "linux" {
@@ -245,17 +270,13 @@
// Make sure OUT_DIR is set appropriately
if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
- ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
+ ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, filepath.Clean(outDir)))
} else {
outDir := "out"
if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
- if wd, err := os.Getwd(); err != nil {
- ctx.Fatalln("Failed to get working directory:", err)
- } else {
- outDir = filepath.Join(baseDir, filepath.Base(wd))
- }
+ outDir = filepath.Join(baseDir, filepath.Base(wd))
}
- ret.environ.Set("OUT_DIR", outDir)
+ ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, outDir))
}
// loadEnvConfig needs to know what the OUT_DIR is, so it should
@@ -283,12 +304,22 @@
ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
}
+ ret.partialCompileFlags = parsePartialCompileFlags(ctx)
+
if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
}
- if os.Getenv("SOONG_USE_N2") == "true" {
- ret.useN2 = true
+ ret.ninjaCommand = NINJA_NINJA
+ switch os.Getenv("SOONG_NINJA") {
+ case "n2":
+ ret.ninjaCommand = NINJA_N2
+ case "siso":
+ ret.ninjaCommand = NINJA_SISO
+ default:
+ if os.Getenv("SOONG_USE_N2") == "true" {
+ ret.ninjaCommand = NINJA_N2
+ }
}
ret.environ.Unset(
@@ -348,8 +379,10 @@
// We read it here already, don't let others share in the fun
"GENERATE_SOONG_DEBUG",
- // Use config.useN2 instead.
+ // Use config.ninjaCommand instead.
+ "SOONG_NINJA",
"SOONG_USE_N2",
+ "SOONG_PARTIAL_COMPILE",
)
if ret.UseGoma() || ret.ForceUseGoma() {
@@ -361,12 +394,12 @@
ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
tmpDir := absPath(ctx, ret.TempDir())
- ret.environ.Set("TMPDIR", tmpDir)
+ ret.environ.Set("TMPDIR", ret.sandboxPath(wd, tmpDir))
// Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
"llvm-binutils-stable/llvm-symbolizer")
- ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
+ ret.environ.Set("ASAN_SYMBOLIZER_PATH", ret.sandboxPath(wd, absPath(ctx, symbolizerPath)))
// Precondition: the current directory is the top of the source tree
checkTopDir(ctx)
@@ -426,9 +459,9 @@
}
ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
- ret.environ.Set("JAVA_HOME", absJavaHome)
- ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
- ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
+ ret.environ.Set("JAVA_HOME", ret.sandboxPath(wd, absJavaHome))
+ ret.environ.Set("ANDROID_JAVA_HOME", ret.sandboxPath(wd, javaHome))
+ ret.environ.Set("ANDROID_JAVA8_HOME", ret.sandboxPath(wd, java8Home))
ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
// b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches
@@ -444,7 +477,7 @@
ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
}
- ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
+ ret.environ.Set("BUILD_DATETIME_FILE", ret.sandboxPath(wd, buildDateTimeFile))
if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok {
username := "unknown"
@@ -455,6 +488,7 @@
}
ret.environ.Set("BUILD_USERNAME", username)
}
+ ret.environ.Set("PWD", ret.sandboxPath(wd, wd))
if ret.UseRBE() {
for k, v := range getRBEVars(ctx, Config{ret}) {
@@ -467,6 +501,78 @@
return c
}
+// Parse SOONG_PARTIAL_COMPILE.
+//
+// The user-facing documentation shows:
+//
+// - empty or not set: "The current default state"
+// - "true" or "on": enable all stable partial compile features.
+// - "false" or "off": disable partial compile completely.
+//
+// What we actually allow is a comma separated list of tokens, whose first
+// character may be "+" (enable) or "-" (disable). If neither is present, "+"
+// is assumed. For example, "on,+use_d8" will enable partial compilation, and
+// additionally set the use_d8 flag (regardless of whether it is opt-in or
+// opt-out).
+//
+// 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.
+func parsePartialCompileFlags(ctx Context) partialCompileFlags {
+ defaultFlags := partialCompileFlags{
+ // Set any opt-out flags here. Opt-in flags are off by default.
+ enabled: false,
+ }
+ value, ok := os.LookupEnv("SOONG_PARTIAL_COMPILE")
+
+ if !ok {
+ return defaultFlags
+ }
+
+ ret := defaultFlags
+ tokens := strings.Split(strings.ToLower(value), ",")
+ makeVal := func(state string, defaultValue bool) bool {
+ switch state {
+ case "":
+ return defaultValue
+ case "-":
+ return false
+ case "+":
+ return true
+ }
+ return false
+ }
+ for _, tok := range tokens {
+ var state string
+ switch tok[0:1] {
+ case "":
+ // Ignore empty tokens.
+ continue
+ case "-", "+":
+ state = tok[0:1]
+ tok = tok[1:]
+ default:
+ // Treat `feature` as `+feature`.
+ state = "+"
+ }
+ switch tok {
+ case "true", "on", "yes":
+ ret = defaultFlags
+ ret.enabled = true
+ case "false", "off", "no":
+ // Set everything to false.
+ ret = partialCompileFlags{}
+ case "enabled":
+ ret.enabled = makeVal(state, defaultFlags.enabled)
+ case "use_d8":
+ ret.use_d8 = makeVal(state, defaultFlags.use_d8)
+ default:
+ ctx.Fatalln("Unknown SOONG_PARTIAL_COMPILE value:", value)
+ }
+ }
+ return ret
+}
+
// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
// processed based on the build action and extracts any arguments that belongs to the build action.
func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
@@ -1035,13 +1141,9 @@
}
}
-func (c *configImpl) NamedGlobFile(name string) string {
- return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
-}
-
func (c *configImpl) UsedEnvFile(tag string) string {
if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
- return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+"."+tag)
+ return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+c.CoverageSuffix()+"."+tag)
}
return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
}
@@ -1149,6 +1251,13 @@
return "", fmt.Errorf("TARGET_PRODUCT is not defined")
}
+func (c *configImpl) CoverageSuffix() string {
+ if v := c.environ.IsEnvTrue("EMMA_INSTRUMENT"); v {
+ return ".coverage"
+ }
+ return ""
+}
+
func (c *configImpl) TargetDevice() string {
return c.targetDevice
}
@@ -1289,6 +1398,19 @@
return err == nil
}
+func (c *configImpl) sandboxPath(base, in string) string {
+ if !c.UseABFS() {
+ return in
+ }
+
+ rel, err := filepath.Rel(base, in)
+ if err != nil {
+ return in
+ }
+
+ return filepath.Join(abfsSrcDir, rel)
+}
+
func (c *configImpl) UseRBE() bool {
// These alternate modes of running Soong do not use RBE / reclient.
if c.Queryview() || c.JsonModuleGraph() {
@@ -1341,8 +1463,7 @@
}
func (c *configImpl) rbeTmpDir() string {
- buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
- return filepath.Join(buildTmpDir, "rbe")
+ return filepath.Join(c.SoongOutDir(), "rbe")
}
func (c *configImpl) rbeCacheDir() string {
@@ -1358,8 +1479,10 @@
// Perform a log directory cleanup only when the log directory
// is auto created by the build rather than user-specified.
for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
- if _, ok := c.environ.Get(f); ok {
- return false
+ if v, ok := c.environ.Get(f); ok {
+ if v != c.rbeTmpDir() {
+ return false
+ }
}
}
return true
@@ -1521,7 +1644,7 @@
if err != nil {
return filepath.Join(c.SoongOutDir(), "soong.variables")
} else {
- return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".variables")
+ return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".variables")
}
}
@@ -1530,7 +1653,7 @@
if err != nil {
return filepath.Join(c.SoongOutDir(), "soong.extra.variables")
} else {
- return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".extra.variables")
+ return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".extra.variables")
}
}
@@ -1539,7 +1662,7 @@
if err != nil {
return filepath.Join(c.SoongOutDir(), "build.ninja")
} else {
- return filepath.Join(c.SoongOutDir(), "build."+targetProduct+".ninja")
+ return filepath.Join(c.SoongOutDir(), "build."+targetProduct+c.CoverageSuffix()+".ninja")
}
}
@@ -1551,11 +1674,11 @@
}
func (c *configImpl) SoongAndroidMk() string {
- return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
+ return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
}
func (c *configImpl) SoongMakeVarsMk() string {
- return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
+ return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
}
func (c *configImpl) SoongBuildMetrics() string {
@@ -1618,13 +1741,23 @@
return c.PrebuiltBuildTool(binName)
}
+func (c *configImpl) N2Bin() string {
+ path := c.PrebuiltBuildTool("n2")
+ // Use musl instead of glibc because glibc on the build server is old and has bugs
+ return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
+}
+
+func (c *configImpl) SisoBin() string {
+ path := c.PrebuiltBuildTool("siso")
+ // Use musl instead of glibc because glibc on the build server is old and has bugs
+ return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
+}
+
func (c *configImpl) PrebuiltBuildTool(name string) string {
- if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
- if sanitize := strings.Fields(v); inList("address", sanitize) {
- asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
- if _, err := os.Stat(asan); err == nil {
- return asan
- }
+ if c.environ.IsEnvTrue("SANITIZE_BUILD_TOOL_PREBUILTS") {
+ asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
+ if _, err := os.Stat(asan); err == nil {
+ return asan
}
}
return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
@@ -1710,6 +1843,11 @@
}
func (c *configImpl) SkipMetricsUpload() bool {
+ // b/362625275 - Metrics upload sometimes prevents abfs unmount
+ if c.UseABFS() {
+ return true
+ }
+
return c.skipMetricsUpload
}
@@ -1717,6 +1855,10 @@
return c.ensureAllowlistIntegrity
}
+func (c *configImpl) PartialCompileFlags() partialCompileFlags {
+ return c.partialCompileFlags
+}
+
// Returns a Time object if one was passed via a command-line flag.
// Otherwise returns the passed default.
func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index a0efd2c..5743ff7 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -41,7 +41,7 @@
// arguments.
func genKatiSuffix(ctx Context, config Config) {
// Construct the base suffix.
- katiSuffix := "-" + config.TargetProduct()
+ katiSuffix := "-" + config.TargetProduct() + config.CoverageSuffix()
// Append kati arguments to the suffix.
if args := config.KatiArgs(); len(args) > 0 {
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index b5e74b4..def0783 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -49,15 +49,11 @@
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close()
- executable := config.NinjaBin()
- args := []string{
- "-d", "keepdepfile",
- "-d", "keeprsp",
- "-d", "stats",
- "--frontend_file", fifo,
- }
- if config.useN2 {
- executable = config.PrebuiltBuildTool("n2")
+ var executable string
+ var args []string
+ switch config.ninjaCommand {
+ case NINJA_N2:
+ executable = config.N2Bin()
args = []string{
"-d", "trace",
// TODO: implement these features, or remove them.
@@ -66,8 +62,31 @@
//"-d", "stats",
"--frontend-file", fifo,
}
+ case NINJA_SISO:
+ executable = config.SisoBin()
+ args = []string{
+ "ninja",
+ "--log_dir", config.SoongOutDir(),
+ // TODO: implement these features, or remove them.
+ //"-d", "trace",
+ //"-d", "keepdepfile",
+ //"-d", "keeprsp",
+ //"-d", "stats",
+ //"--frontend-file", fifo,
+ }
+ default:
+ // NINJA_NINJA is the default.
+ executable = config.NinjaBin()
+ args = []string{
+ "-d", "keepdepfile",
+ "-d", "keeprsp",
+ "-d", "stats",
+ "--frontend_file", fifo,
+ "-o", "usesphonyoutputs=yes",
+ "-w", "dupbuild=err",
+ "-w", "missingdepfile=err",
+ }
}
-
args = append(args, config.NinjaArgs()...)
var parallel int
@@ -83,17 +102,10 @@
args = append(args, "-f", config.CombinedNinjaFile())
- if !config.useN2 {
- args = append(args,
- "-o", "usesphonyoutputs=yes",
- "-w", "dupbuild=err",
- "-w", "missingdepfile=err")
- }
-
if !config.BuildBrokenMissingOutputs() {
// Missing outputs will be treated as errors.
// BUILD_BROKEN_MISSING_OUTPUTS can be used to bypass this check.
- if !config.useN2 {
+ if config.ninjaCommand != NINJA_N2 {
args = append(args,
"-w", "missingoutfile=err",
)
@@ -110,21 +122,18 @@
cmd.Environment.AppendFromKati(config.KatiEnvFile())
}
- switch config.NinjaWeightListSource() {
- case NINJA_LOG:
- if !config.useN2 {
+ // TODO(b/346806126): implement this for the other ninjaCommand values.
+ if config.ninjaCommand == NINJA_NINJA {
+ switch config.NinjaWeightListSource() {
+ case NINJA_LOG:
cmd.Args = append(cmd.Args, "-o", "usesninjalogasweightlist=yes")
- }
- case EVENLY_DISTRIBUTED:
- // pass empty weight list means ninja considers every tasks's weight as 1(default value).
- if !config.useN2 {
+ case EVENLY_DISTRIBUTED:
+ // pass empty weight list means ninja considers every tasks's weight as 1(default value).
cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")
- }
- case EXTERNAL_FILE:
- fallthrough
- case HINT_FROM_SOONG:
- // The weight list is already copied/generated.
- if !config.useN2 {
+ case EXTERNAL_FILE:
+ fallthrough
+ case HINT_FROM_SOONG:
+ // The weight list is already copied/generated.
ninjaWeightListPath := filepath.Join(config.OutDir(), ninjaWeightListFileName)
cmd.Args = append(cmd.Args, "-o", "usesweightlist="+ninjaWeightListPath)
}
@@ -227,15 +236,21 @@
// We don't want this build broken flag to cause reanalysis, so allow it through to the
// actions.
"BUILD_BROKEN_INCORRECT_PARTITION_IMAGES",
+ // Do not do reanalysis just because we changed ninja commands.
+ "SOONG_NINJA",
"SOONG_USE_N2",
"RUST_BACKTRACE",
+ "RUST_LOG",
}, config.BuildBrokenNinjaUsesEnvVars()...)...)
}
cmd.Environment.Set("DIST_DIR", config.DistDir())
cmd.Environment.Set("SHELL", "/bin/bash")
- if config.useN2 {
+ switch config.ninjaCommand {
+ case NINJA_N2:
cmd.Environment.Set("RUST_BACKTRACE", "1")
+ default:
+ // Only set RUST_BACKTRACE for n2.
}
// Print the environment variables that Ninja is operating in.
diff --git a/ui/build/path.go b/ui/build/path.go
index 51ebff1..cc1d7e9 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -57,6 +57,22 @@
return ret
}
+func updatePathForSandbox(config Config) {
+ wd, err := os.Getwd()
+ if err != nil {
+ return
+ }
+
+ var newPath []string
+ if path, ok := config.Environment().Get("PATH"); ok && path != "" {
+ entries := strings.Split(path, string(filepath.ListSeparator))
+ for _, ent := range entries {
+ newPath = append(newPath, config.sandboxPath(wd, ent))
+ }
+ }
+ config.Environment().Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
+}
+
// SetupLitePath is the "lite" version of SetupPath used for dumpvars, or other
// places that does not need the full logging capabilities of path_interposer,
// wants the minimal performance overhead, and still get the benefits of $PATH
@@ -109,18 +125,10 @@
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
- if value, _ := config.Environment().Get("BUILD_BROKEN_PYTHON_IS_PYTHON2"); value == "true" {
- py2Path, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86/py2")
- if info, err := os.Stat(py2Path); err == nil && info.IsDir() {
- myPath = py2Path + string(os.PathListSeparator) + myPath
- }
- } else if value != "" {
- ctx.Fatalf("BUILD_BROKEN_PYTHON_IS_PYTHON2 can only be set to 'true' or an empty string, but got %s\n", value)
- }
-
// Set $PATH to be the directories containing the host tool symlinks, and
// the prebuilts directory for the current host OS.
config.Environment().Set("PATH", myPath)
+ updatePathForSandbox(config)
config.pathReplaced = true
}
@@ -253,17 +261,9 @@
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
- if value, _ := config.Environment().Get("BUILD_BROKEN_PYTHON_IS_PYTHON2"); value == "true" {
- py2Path, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86/py2")
- if info, err := os.Stat(py2Path); err == nil && info.IsDir() {
- myPath = py2Path + string(os.PathListSeparator) + myPath
- }
- } else if value != "" {
- ctx.Fatalf("BUILD_BROKEN_PYTHON_IS_PYTHON2 can only be set to 'true' or an empty string, but got %s\n", value)
- }
-
// Replace the $PATH variable with the path_interposer symlinks, and
// checked-in prebuilts.
config.Environment().Set("PATH", myPath)
+ updatePathForSandbox(config)
config.pathReplaced = true
}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 8fa147f..0a0f956 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -65,7 +65,7 @@
"RBE_platform": "container-image=" + remoteexec.DefaultImage,
}
if config.StartRBE() {
- name, err := config.rbeSockAddr(absPath(ctx, config.TempDir()))
+ name, err := config.rbeSockAddr(absPath(ctx, config.rbeTmpDir()))
if err != nil {
ctx.Fatalf("Error retrieving socket address: %v", err)
return nil
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 5c3fec1..95b71a7 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -48,7 +48,9 @@
}
)
-const nsjailPath = "prebuilts/build-tools/linux-x86/bin/nsjail"
+const (
+ nsjailPath = "prebuilts/build-tools/linux-x86/bin/nsjail"
+)
var sandboxConfig struct {
once sync.Once
@@ -145,10 +147,81 @@
return sandboxConfig.working
}
-func (c *Cmd) wrapSandbox() {
- wd, _ := os.Getwd()
+// Assumes input path is absolute, clean, and if applicable, an evaluated
+// symlink. If path is not a subdirectory of src dir or relative path
+// cannot be determined, return the input untouched.
+func (c *Cmd) relFromSrcDir(path string) string {
+ if !strings.HasPrefix(path, sandboxConfig.srcDir) {
+ return path
+ }
- sandboxArgs := []string{
+ rel, err := filepath.Rel(sandboxConfig.srcDir, path)
+ if err != nil {
+ return path
+ }
+
+ return rel
+}
+
+func (c *Cmd) dirArg(path string) string {
+ if !c.config.UseABFS() {
+ return path
+ }
+
+ rel := c.relFromSrcDir(path)
+
+ return path + ":" + filepath.Join(abfsSrcDir, rel)
+}
+
+func (c *Cmd) srcDirArg() string {
+ return c.dirArg(sandboxConfig.srcDir)
+}
+
+func (c *Cmd) outDirArg() string {
+ return c.dirArg(sandboxConfig.outDir)
+}
+
+func (c *Cmd) distDirArg() string {
+ return c.dirArg(sandboxConfig.distDir)
+}
+
+// When configured to use ABFS, we need to allow the creation of the /src
+// directory. Therefore, we cannot mount the root "/" directory as read-only.
+// Instead, we individually mount the children of "/" as RO.
+func (c *Cmd) readMountArgs() []string {
+ if !c.config.UseABFS() {
+ // For now, just map everything. Make most things readonly.
+ return []string{"-R", "/"}
+ }
+
+ entries, err := os.ReadDir("/")
+ if err != nil {
+ // If we can't read "/", just use the default non-ABFS behavior.
+ return []string{"-R", "/"}
+ }
+
+ args := make([]string, 0, 2*len(entries))
+ for _, ent := range entries {
+ args = append(args, "-R", "/"+ent.Name())
+ }
+
+ return args
+}
+
+func (c *Cmd) workDir() string {
+ if !c.config.UseABFS() {
+ wd, _ := os.Getwd()
+ return wd
+ }
+
+ return abfsSrcDir
+}
+
+func (c *Cmd) wrapSandbox() {
+ wd := c.workDir()
+
+ var sandboxArgs []string
+ sandboxArgs = append(sandboxArgs,
// The executable to run
"-x", c.Path,
@@ -180,18 +253,21 @@
"--rlimit_cpu", "soft",
"--rlimit_fsize", "soft",
"--rlimit_nofile", "soft",
+ )
- // For now, just map everything. Make most things readonly.
- "-R", "/",
+ sandboxArgs = append(sandboxArgs,
+ c.readMountArgs()...,
+ )
+ sandboxArgs = append(sandboxArgs,
// Mount a writable tmp dir
"-B", "/tmp",
// Mount source
- c.config.sandboxConfig.SrcDirMountFlag(), sandboxConfig.srcDir,
+ c.config.sandboxConfig.SrcDirMountFlag(), c.srcDirArg(),
//Mount out dir as read-write
- "-B", sandboxConfig.outDir,
+ "-B", c.outDirArg(),
// Disable newcgroup for now, since it may require newer kernels
// TODO: try out cgroups
@@ -199,7 +275,7 @@
// Only log important warnings / errors
"-q",
- }
+ )
if c.config.UseABFS() {
sandboxArgs = append(sandboxArgs, "-B", "{ABFS_DIR}")
}
@@ -218,7 +294,7 @@
if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
//Mount dist dir as read-write if it already exists
- sandboxArgs = append(sandboxArgs, "-B", sandboxConfig.distDir)
+ sandboxArgs = append(sandboxArgs, "-B", c.distDirArg())
}
if c.Sandbox.AllowBuildBrokenUsesNetwork && c.config.BuildBrokenUsesNetwork() {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 2ccdfec..f70d9b7 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,14 +15,19 @@
package build
import (
+ "encoding/json"
+ "errors"
"fmt"
"io/fs"
"os"
"path/filepath"
+ "runtime"
+ "slices"
"strconv"
"strings"
"sync"
"sync/atomic"
+ "syscall"
"time"
"android/soong/ui/tracer"
@@ -52,7 +57,7 @@
// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
// version of bootstrap and needs cleaning before continuing the build. Increment this for
- // incompatible changes, for example when moving the location of the bpglob binary that is
+ // incompatible changes, for example when moving the location of a microfactory binary that is
// executed during bootstrap before the primary builder has had a chance to update the path.
bootstrapEpoch = 1
)
@@ -226,10 +231,6 @@
var allArgs []string
allArgs = append(allArgs, pb.specificArgs...)
- globPathName := getGlobPathNameFromPrimaryBuilderFactory(config, pb)
- allArgs = append(allArgs,
- "--globListDir", globPathName,
- "--globFile", pb.config.NamedGlobFile(globPathName))
allArgs = append(allArgs, commonArgs...)
allArgs = append(allArgs, environmentArgs(pb.config, pb.name)...)
@@ -241,11 +242,8 @@
}
allArgs = append(allArgs, "Android.bp")
- globfiles := bootstrap.GlobFileListFiles(bootstrap.GlobDirectory(config.SoongOutDir(), globPathName))
-
return bootstrap.PrimaryBuilderInvocation{
- Inputs: []string{"Android.bp"},
- Implicits: globfiles,
+ Implicits: []string{pb.output + ".glob_results"},
Outputs: []string{pb.output},
Args: allArgs,
Description: pb.description,
@@ -277,24 +275,15 @@
os.Remove(file)
}
}
- for _, globFile := range bootstrapGlobFileList(config) {
- os.Remove(globFile)
- }
+ os.Remove(soongNinjaFile + ".globs")
+ os.Remove(soongNinjaFile + ".globs_time")
+ os.Remove(soongNinjaFile + ".glob_results")
// Mark the tree as up to date with the current epoch by writing the epoch marker file.
writeEmptyFile(ctx, epochPath)
}
}
-func bootstrapGlobFileList(config Config) []string {
- return []string{
- config.NamedGlobFile(getGlobPathName(config)),
- config.NamedGlobFile(jsonModuleGraphTag),
- config.NamedGlobFile(queryviewTag),
- config.NamedGlobFile(soongDocsTag),
- }
-}
-
func bootstrapBlueprint(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
defer ctx.EndTrace()
@@ -412,32 +401,9 @@
runGoTests: !config.skipSoongTests,
// If we want to debug soong_build, we need to compile it for debugging
debugCompilation: delvePort != "",
- subninjas: bootstrapGlobFileList(config),
primaryBuilderInvocations: invocations,
}
- // The glob ninja files are generated during the main build phase. However, the
- // primary buildifer invocation depends on all of its glob files, even before
- // it's been run. Generate a "empty" glob ninja file on the first run,
- // so that the files can be there to satisfy the dependency.
- for _, pb := range pbfs {
- globPathName := getGlobPathNameFromPrimaryBuilderFactory(config, pb)
- globNinjaFile := config.NamedGlobFile(globPathName)
- if _, err := os.Stat(globNinjaFile); os.IsNotExist(err) {
- err := bootstrap.WriteBuildGlobsNinjaFile(&bootstrap.GlobSingleton{
- GlobLister: func() pathtools.MultipleGlobResults { return nil },
- GlobFile: globNinjaFile,
- GlobDir: bootstrap.GlobDirectory(config.SoongOutDir(), globPathName),
- SrcDir: ".",
- }, blueprintConfig)
- if err != nil {
- ctx.Fatal(err)
- }
- } else if err != nil {
- ctx.Fatal(err)
- }
- }
-
// since `bootstrap.ninja` is regenerated unconditionally, we ignore the deps, i.e. little
// reason to write a `bootstrap.ninja.d` file
_, err := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
@@ -615,9 +581,6 @@
}
}()
- runMicrofactory(ctx, config, "bpglob", "github.com/google/blueprint/bootstrap/bpglob",
- map[string]string{"github.com/google/blueprint": "build/blueprint"})
-
ninja := func(targets ...string) {
ctx.BeginTrace(metrics.RunSoong, "bootstrap")
defer ctx.EndTrace()
@@ -626,19 +589,11 @@
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close()
- ninjaArgs := []string{
- "-d", "keepdepfile",
- "-d", "stats",
- "-o", "usesphonyoutputs=yes",
- "-o", "preremoveoutputs=yes",
- "-w", "dupbuild=err",
- "-w", "outputdir=err",
- "-w", "missingoutfile=err",
- "-j", strconv.Itoa(config.Parallel()),
- "--frontend_file", fifo,
- "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
- }
- if config.useN2 {
+ var ninjaCmd string
+ var ninjaArgs []string
+ switch config.ninjaCommand {
+ case NINJA_N2:
+ ninjaCmd = config.N2Bin()
ninjaArgs = []string{
// TODO: implement these features, or remove them.
//"-d", "keepdepfile",
@@ -653,6 +608,39 @@
"--frontend-file", fifo,
"-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
}
+ case NINJA_SISO:
+ ninjaCmd = config.SisoBin()
+ ninjaArgs = []string{
+ "ninja",
+ // TODO: implement these features, or remove them.
+ //"-d", "keepdepfile",
+ //"-d", "stats",
+ //"-o", "usesphonyoutputs=yes",
+ //"-o", "preremoveoutputs=yes",
+ //"-w", "dupbuild=err",
+ //"-w", "outputdir=err",
+ //"-w", "missingoutfile=err",
+ "-v",
+ "-j", strconv.Itoa(config.Parallel()),
+ //"--frontend-file", fifo,
+ "--log_dir", config.SoongOutDir(),
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
+ default:
+ // NINJA_NINJA is the default.
+ ninjaCmd = config.NinjaBin()
+ ninjaArgs = []string{
+ "-d", "keepdepfile",
+ "-d", "stats",
+ "-o", "usesphonyoutputs=yes",
+ "-o", "preremoveoutputs=yes",
+ "-w", "dupbuild=err",
+ "-w", "outputdir=err",
+ "-w", "missingoutfile=err",
+ "-j", strconv.Itoa(config.Parallel()),
+ "--frontend_file", fifo,
+ "-f", filepath.Join(config.SoongOutDir(), "bootstrap.ninja"),
+ }
}
if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
@@ -661,10 +649,6 @@
}
ninjaArgs = append(ninjaArgs, targets...)
- ninjaCmd := config.NinjaBin()
- if config.useN2 {
- ninjaCmd = config.PrebuiltBuildTool("n2")
- }
cmd := Command(ctx, config, "soong bootstrap",
ninjaCmd, ninjaArgs...)
@@ -699,6 +683,12 @@
targets = append(targets, config.SoongNinjaFile())
}
+ for _, target := range targets {
+ if err := checkGlobs(ctx, target); err != nil {
+ ctx.Fatalf("Error checking globs: %s", err.Error())
+ }
+ }
+
beforeSoongTimestamp := time.Now()
ninja(targets...)
@@ -725,6 +715,172 @@
}
}
+// checkGlobs manages the globs that cause soong to rerun.
+//
+// When soong_build runs, it will run globs. It will write all the globs
+// it ran into the "{finalOutFile}.globs" file. Then every build,
+// soong_ui will check that file, rerun the globs, and if they changed
+// from the results that soong_build got, update the ".glob_results"
+// file, causing soong_build to rerun. The ".glob_results" file will
+// be empty on the first run of soong_build, because we don't know
+// what the globs are yet, but also remain empty until the globs change
+// so that we don't run soong_build a second time unnecessarily.
+// Both soong_build and soong_ui will also update a ".globs_time" file
+// with the time that they ran at every build. When soong_ui checks
+// globs, it only reruns globs whose dependencies are newer than the
+// time in the ".globs_time" file.
+func checkGlobs(ctx Context, finalOutFile string) error {
+ ctx.BeginTrace(metrics.RunSoong, "check_globs")
+ defer ctx.EndTrace()
+ st := ctx.Status.StartTool()
+ st.Status("Running globs...")
+ defer st.Finish()
+
+ globsFile, err := os.Open(finalOutFile + ".globs")
+ if errors.Is(err, fs.ErrNotExist) {
+ // if the glob file doesn't exist, make sure the glob_results file exists and is empty.
+ if err := os.MkdirAll(filepath.Dir(finalOutFile), 0777); err != nil {
+ return err
+ }
+ f, err := os.Create(finalOutFile + ".glob_results")
+ if err != nil {
+ return err
+ }
+ return f.Close()
+ } else if err != nil {
+ return err
+ }
+ defer globsFile.Close()
+ globsFileDecoder := json.NewDecoder(globsFile)
+
+ globsTimeBytes, err := os.ReadFile(finalOutFile + ".globs_time")
+ if err != nil {
+ return err
+ }
+ globsTimeMicros, err := strconv.ParseInt(strings.TrimSpace(string(globsTimeBytes)), 10, 64)
+ if err != nil {
+ return err
+ }
+ globCheckStartTime := time.Now().UnixMicro()
+
+ globsChan := make(chan pathtools.GlobResult)
+ errorsChan := make(chan error)
+ wg := sync.WaitGroup{}
+
+ hasChangedGlobs := false
+ var changedGlobNameMutex sync.Mutex
+ var changedGlobName string
+
+ for i := 0; i < runtime.NumCPU()*2; i++ {
+ wg.Add(1)
+ go func() {
+ for cachedGlob := range globsChan {
+ // If we've already determined we have changed globs, just finish consuming
+ // the channel without doing any more checks.
+ if hasChangedGlobs {
+ continue
+ }
+ // First, check if any of the deps are newer than the last time globs were checked.
+ // If not, we don't need to rerun the glob.
+ hasNewDep := false
+ for _, dep := range cachedGlob.Deps {
+ info, err := os.Stat(dep)
+ if errors.Is(err, fs.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) {
+ hasNewDep = true
+ break
+ } else if err != nil {
+ errorsChan <- err
+ continue
+ }
+ if info.ModTime().UnixMicro() > globsTimeMicros {
+ hasNewDep = true
+ break
+ }
+ }
+ if !hasNewDep {
+ continue
+ }
+
+ // Then rerun the glob and check if we got the same result as before.
+ result, err := pathtools.Glob(cachedGlob.Pattern, cachedGlob.Excludes, pathtools.FollowSymlinks)
+ if err != nil {
+ errorsChan <- err
+ } else {
+ if !slices.Equal(result.Matches, cachedGlob.Matches) {
+ hasChangedGlobs = true
+
+ changedGlobNameMutex.Lock()
+ defer changedGlobNameMutex.Unlock()
+ changedGlobName = result.Pattern
+ if len(result.Excludes) > 0 {
+ changedGlobName += " (excluding " + strings.Join(result.Excludes, ", ") + ")"
+ }
+ }
+ }
+ }
+ wg.Done()
+ }()
+ }
+ go func() {
+ wg.Wait()
+ close(errorsChan)
+ }()
+
+ errorsWg := sync.WaitGroup{}
+ errorsWg.Add(1)
+ var errFromGoRoutines error
+ go func() {
+ for result := range errorsChan {
+ if errFromGoRoutines == nil {
+ errFromGoRoutines = result
+ }
+ }
+ errorsWg.Done()
+ }()
+
+ var cachedGlob pathtools.GlobResult
+ for globsFileDecoder.More() {
+ if err := globsFileDecoder.Decode(&cachedGlob); err != nil {
+ return err
+ }
+ // Need to clone the GlobResult because the json decoder will
+ // reuse the same slice allocations.
+ globsChan <- cachedGlob.Clone()
+ }
+ close(globsChan)
+ errorsWg.Wait()
+ if errFromGoRoutines != nil {
+ return errFromGoRoutines
+ }
+
+ // Update the globs_time file whether or not we found changed globs,
+ // so that we don't rerun globs in the future that we just saw didn't change.
+ err = os.WriteFile(
+ finalOutFile+".globs_time",
+ []byte(fmt.Sprintf("%d\n", globCheckStartTime)),
+ 0666,
+ )
+ if err != nil {
+ return err
+ }
+
+ if hasChangedGlobs {
+ fmt.Fprintf(os.Stdout, "Globs changed, rerunning soong...\n")
+ fmt.Fprintf(os.Stdout, "One culprit glob (may be more): %s\n", changedGlobName)
+ // Write the current time to the glob_results file. We just need
+ // some unique value to trigger a rerun, it doesn't matter what it is.
+ err = os.WriteFile(
+ finalOutFile+".glob_results",
+ []byte(fmt.Sprintf("%d\n", globCheckStartTime)),
+ 0666,
+ )
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// loadSoongBuildMetrics reads out/soong_build_metrics.pb if it was generated by soong_build and copies the
// events stored in it into the soong_ui trace to provide introspection into how long the different phases of
// soong_build are taking.
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 3faa94d..ba53119 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -79,9 +79,6 @@
// out/build_date.txt is considered a "source file"
buildDatetimeFilePath := filepath.Join(outDir, "build_date.txt")
- // bpglob is built explicitly using Microfactory
- bpglob := filepath.Join(config.SoongOutDir(), "bpglob")
-
// release-config files are generated from the initial lunch or Kati phase
// before running soong and ninja.
releaseConfigDir := filepath.Join(outDir, "soong", "release-config")
@@ -105,7 +102,6 @@
line == extraVariablesFilePath ||
line == dexpreoptConfigFilePath ||
line == buildDatetimeFilePath ||
- line == bpglob ||
strings.HasPrefix(line, releaseConfigDir) ||
buildFingerPrintFilePattern.MatchString(line) {
// Leaf node is in one of Soong's bootstrap directories, which do not have
diff --git a/zip/cmd/Android.bp b/zip/cmd/Android.bp
index 43bf232..16c3f69 100644
--- a/zip/cmd/Android.bp
+++ b/zip/cmd/Android.bp
@@ -24,4 +24,6 @@
srcs: [
"main.go",
],
+ // Used by genrules
+ visibility: ["//visibility:public"],
}