Merge "Install VINTF fragment modules in the APEX" into main
diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go
index 3b40755..e76db49 100644
--- a/aconfig/build_flags/build_flags_singleton.go
+++ b/aconfig/build_flags/build_flags_singleton.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "fmt"
)
// A singleton module that collects all of the build flags declared in the
@@ -120,4 +121,26 @@
ctx.DistForGoalWithFilename(goal, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb")
ctx.DistForGoalWithFilename(goal, this.configsTextProtoPath, "build_flags/all_release_config_contributions.textproto")
}
+
+ if ctx.Config().HasDeviceProduct() {
+ flagsDir := android.PathForOutput(ctx, "release-config")
+ baseAllRelease := fmt.Sprintf("all_release_configs-%s", ctx.Config().DeviceProduct())
+
+ distAllReleaseConfigsArtifact := func(ext string) {
+ ctx.DistForGoalWithFilename(
+ "droid",
+ flagsDir.Join(ctx, fmt.Sprintf("%s.%s", baseAllRelease, ext)),
+ fmt.Sprintf("build_flags/all_release_configs.%s", ext),
+ )
+ }
+
+ distAllReleaseConfigsArtifact("pb")
+ distAllReleaseConfigsArtifact("textproto")
+ distAllReleaseConfigsArtifact("json")
+ ctx.DistForGoalWithFilename(
+ "droid",
+ flagsDir.Join(ctx, fmt.Sprintf("inheritance_graph-%s.dot", ctx.Config().DeviceProduct())),
+ fmt.Sprintf("build_flags/inheritance_graph-%s.dot", ctx.Config().DeviceProduct()),
+ )
+ }
}
diff --git a/android/Android.bp b/android/Android.bp
index 75027b1..540d65b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -125,7 +125,6 @@
"all_teams_test.go",
"android_test.go",
"androidmk_test.go",
- "apex_test.go",
"arch_test.go",
"blueprint_e2e_test.go",
"build_prop_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index db1b9e7..951e03c 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -719,22 +719,26 @@
type androidMkSingleton struct{}
-func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
- var androidMkModulesList []blueprint.Module
+func allModulesSorted(ctx SingletonContext) []blueprint.Module {
+ var allModules []blueprint.Module
ctx.VisitAllModulesBlueprint(func(module blueprint.Module) {
- androidMkModulesList = append(androidMkModulesList, module)
+ allModules = append(allModules, module)
})
// Sort the module list by the module names to eliminate random churns, which may erroneously
// invoke additional build processes.
- sort.SliceStable(androidMkModulesList, func(i, j int) bool {
- return ctx.ModuleName(androidMkModulesList[i]) < ctx.ModuleName(androidMkModulesList[j])
+ sort.SliceStable(allModules, func(i, j int) bool {
+ return ctx.ModuleName(allModules[i]) < ctx.ModuleName(allModules[j])
})
- // If running in soong-only mode, do a different, more limited version of this singleton
+ return allModules
+}
+
+func (c *androidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // If running in soong-only mode, more limited version of this singleton is run as
+ // soong only androidmk singleton
if !ctx.Config().KatiEnabled() {
- c.soongOnlyBuildActions(ctx, androidMkModulesList)
return
}
@@ -745,7 +749,7 @@
moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json")
- err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList)
+ err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, allModulesSorted(ctx))
if err != nil {
ctx.Errorf(err.Error())
}
@@ -756,13 +760,27 @@
})
}
+type soongOnlyAndroidMkSingleton struct {
+ Singleton
+}
+
+func soongOnlyAndroidMkSingletonFactory() Singleton {
+ return &soongOnlyAndroidMkSingleton{}
+}
+
+func (so *soongOnlyAndroidMkSingleton) GenerateBuildActions(ctx SingletonContext) {
+ if !ctx.Config().KatiEnabled() {
+ so.soongOnlyBuildActions(ctx, allModulesSorted(ctx))
+ }
+}
+
// In soong-only mode, we don't do most of the androidmk stuff. But disted files are still largely
// defined through the androidmk mechanisms, so this function is an alternate implementation of
// the androidmk singleton that just focuses on getting the dist contributions
-func (c *androidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []blueprint.Module) {
+func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []blueprint.Module) {
allDistContributions, moduleInfoJSONs := getSoongOnlyDataFromMods(ctx, mods)
- for _, provider := range makeVarsInitProviders {
+ for _, provider := range append(makeVarsInitProviders, *getSingletonMakevarsProviders(ctx.Config())...) {
mctx := &makeVarsContext{
SingletonContext: ctx,
pctx: provider.pctx,
@@ -773,6 +791,13 @@
}
}
+ singletonDists := getSingletonDists(ctx.Config())
+ singletonDists.lock.Lock()
+ if contribution := distsToDistContributions(singletonDists.dists); contribution != nil {
+ allDistContributions = append(allDistContributions, *contribution)
+ }
+ singletonDists.lock.Unlock()
+
// Build module-info.json. Only in builds with HasDeviceProduct(), as we need a named
// device to have a TARGET_OUT folder.
if ctx.Config().HasDeviceProduct() {
diff --git a/android/apex.go b/android/apex.go
index a5ccd52..68d0ce8 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -17,7 +17,6 @@
import (
"fmt"
"slices"
- "sort"
"strconv"
"strings"
"sync"
@@ -55,18 +54,30 @@
// to true.
UsePlatformApis bool
- // List of Apex variant names that this module is associated with. This initially is the
- // same as the `ApexVariationName` field. Then when multiple apex variants are merged in
- // mergeApexVariations, ApexInfo struct of the merged variant holds the list of apexBundles
- // that are merged together.
- InApexVariants []string
-
// True if this is for a prebuilt_apex.
//
// If true then this will customize the apex processing to make it suitable for handling
// prebuilt_apex, e.g. it will prevent ApexInfos from being merged together.
//
- // See Prebuilt.ApexInfoMutator for more information.
+ // Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
+ // across prebuilt_apex modules. That is because there is no way to determine whether two
+ // prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
+ // been built from different source at different times or they could have been built with different
+ // build options that affect the libraries.
+ //
+ // While it may be possible to provide sufficient information to determine whether two prebuilt_apex
+ // modules were compatible it would be a lot of work and would not provide much benefit for a couple
+ // of reasons:
+ // - The number of prebuilt_apex modules that will be exporting files for the same module will be
+ // low as the prebuilt_apex only exports files for the direct dependencies that require it and
+ // very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
+ // few com.android.art* apex files that contain the same contents and could export files for the
+ // same modules but only one of them needs to do so. Contrast that with source apex modules which
+ // need apex specific variants for every module that contributes code to the apex, whether direct
+ // or indirect.
+ // - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
+ // extra copying of files. Contrast that with source apex modules that has to build each variant
+ // from source.
ForPrebuiltApex bool
// Returns the name of the overridden apex (com.android.foo)
@@ -74,24 +85,36 @@
// Returns the value of `apex_available_name`
ApexAvailableName string
+}
+func (a ApexInfo) Variation() string {
+ return a.ApexVariationName
+}
+
+// Minimize is called during a transition from a module with a unique variation per apex to a module that should
+// share variations between apexes. It returns a minimized ApexInfo that removes any apex names and replaces
+// the variation name with one computed from the remaining properties.
+func (a ApexInfo) Minimize() ApexInfo {
+ info := ApexInfo{
+ MinSdkVersion: a.MinSdkVersion,
+ UsePlatformApis: a.UsePlatformApis,
+ }
+ info.ApexVariationName = info.mergedName()
+ return info
+}
+
+type ApexAvailableInfo struct {
// Returns the apex names that this module is available for
ApexAvailableFor []string
}
-// AllApexInfo holds the ApexInfo of all apexes that include this module.
-type AllApexInfo struct {
- ApexInfos []ApexInfo
-}
-
var ApexInfoProvider = blueprint.NewMutatorProvider[ApexInfo]("apex_mutate")
-var AllApexInfoProvider = blueprint.NewMutatorProvider[*AllApexInfo]("apex_info")
+var ApexAvailableInfoProvider = blueprint.NewMutatorProvider[ApexAvailableInfo]("apex_mutate")
func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
(*d)["Apex"] = map[string]interface{}{
"ApexVariationName": i.ApexVariationName,
"MinSdkVersion": i.MinSdkVersion,
- "InApexVariants": i.InApexVariants,
"ForPrebuiltApex": i.ForPrebuiltApex,
}
}
@@ -117,32 +140,20 @@
return i.ApexVariationName == ""
}
-// InApexVariant tells whether this apex variant of the module is part of the given apexVariant or
-// not.
-func (i ApexInfo) InApexVariant(apexVariant string) bool {
- for _, a := range i.InApexVariants {
- if a == apexVariant {
- return true
- }
- }
- return false
-}
-
// To satisfy the comparable interface
func (i ApexInfo) Equal(other any) bool {
otherApexInfo, ok := other.(ApexInfo)
return ok && i.ApexVariationName == otherApexInfo.ApexVariationName &&
i.MinSdkVersion == otherApexInfo.MinSdkVersion &&
i.Updatable == otherApexInfo.Updatable &&
- i.UsePlatformApis == otherApexInfo.UsePlatformApis &&
- slices.Equal(i.InApexVariants, otherApexInfo.InApexVariants)
+ i.UsePlatformApis == otherApexInfo.UsePlatformApis
}
// ApexBundleInfo contains information about the dependencies of an apex
type ApexBundleInfo struct {
}
-var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_info")
+var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_mutate")
// DepIsInSameApex defines an interface that should be used to determine whether a given dependency
// should be considered as part of the same APEX as the current module or not. Note: this was
@@ -315,6 +326,61 @@
apexInfosLock sync.Mutex // protects apexInfos during parallel apexInfoMutator
}
+func (m *ApexModuleBase) ApexTransitionMutatorSplit(ctx BaseModuleContext) []ApexInfo {
+ return []ApexInfo{{}}
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorOutgoing(ctx OutgoingTransitionContext, info ApexInfo) ApexInfo {
+ if !ctx.Module().(DepIsInSameApex).OutgoingDepIsInSameApex(ctx.DepTag()) {
+ return ApexInfo{}
+ }
+ return info
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorIncoming(ctx IncomingTransitionContext, info ApexInfo) ApexInfo {
+ module := ctx.Module().(ApexModule)
+ if !module.CanHaveApexVariants() {
+ return ApexInfo{}
+ }
+
+ if !ctx.Module().(DepIsInSameApex).IncomingDepIsInSameApex(ctx.DepTag()) {
+ return ApexInfo{}
+ }
+
+ if info.ApexVariationName == "" {
+ return ApexInfo{}
+ }
+
+ if !ctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps && !info.ForPrebuiltApex {
+ return info.Minimize()
+ }
+ return info
+}
+
+func (m *ApexModuleBase) ApexTransitionMutatorMutate(ctx BottomUpMutatorContext, info ApexInfo) {
+ SetProvider(ctx, ApexInfoProvider, info)
+
+ module := ctx.Module().(ApexModule)
+ base := module.apexModuleBase()
+
+ platformVariation := info.ApexVariationName == ""
+ if !platformVariation {
+ // Do some validity checks.
+ // TODO(jiyong): is this the right place?
+ base.checkApexAvailableProperty(ctx)
+
+ SetProvider(ctx, ApexAvailableInfoProvider, ApexAvailableInfo{
+ ApexAvailableFor: module.ApexAvailableFor(),
+ })
+ }
+ if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
+ // Do not install the module for platform, but still allow it to output
+ // uninstallable AndroidMk entries in certain cases when they have side
+ // effects. TODO(jiyong): move this routine to somewhere else
+ module.MakeUninstallable()
+ }
+}
+
// Initializes ApexModuleBase struct. Not calling this (even when inheriting from ApexModuleBase)
// prevents the module from being mutated for apexBundle.
func InitApexModule(m ApexModule) {
@@ -514,195 +580,14 @@
return true
}
-// mergeApexVariations deduplicates apex variations that would build identically into a common
-// variation. It returns the reduced list of variations and a list of aliases from the original
-// variation names to the new variation names.
-func mergeApexVariations(apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
- seen := make(map[string]int)
- for _, apexInfo := range apexInfos {
- // If this is for a prebuilt apex then use the actual name of the apex variation to prevent this
- // from being merged with other ApexInfo. See Prebuilt.ApexInfoMutator for more information.
- if apexInfo.ForPrebuiltApex {
- merged = append(merged, apexInfo)
- continue
- }
-
- // Merge the ApexInfo together. If a compatible ApexInfo exists then merge the information from
- // this one into it, otherwise create a new merged ApexInfo from this one and save it away so
- // other ApexInfo instances can be merged into it.
- variantName := apexInfo.ApexVariationName
- mergedName := apexInfo.mergedName()
- if index, exists := seen[mergedName]; exists {
- // Variants having the same mergedName are deduped
- merged[index].InApexVariants = append(merged[index].InApexVariants, variantName)
- merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
- // Platform APIs is allowed for this module only when all APEXes containing
- // the module are with `use_platform_apis: true`.
- merged[index].UsePlatformApis = merged[index].UsePlatformApis && apexInfo.UsePlatformApis
- } else {
- seen[mergedName] = len(merged)
- apexInfo.ApexVariationName = mergedName
- apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants)
- merged = append(merged, apexInfo)
- }
- aliases = append(aliases, [2]string{variantName, mergedName})
- }
- return merged, aliases
-}
-
-// IncomingApexTransition is called by apexTransitionMutator.IncomingTransition on modules that can be in apexes.
-// The incomingVariation can be either the name of an apex if the dependency is coming directly from an apex
-// module, or it can be the name of an apex variation (e.g. apex10000) if it is coming from another module that
-// is in the apex.
-func IncomingApexTransition(ctx IncomingTransitionContext, incomingVariation string) string {
- module := ctx.Module().(ApexModule)
- base := module.apexModuleBase()
-
- var apexInfos []ApexInfo
- if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- apexInfos = allApexInfos.ApexInfos
- }
-
- // Dependencies from platform variations go to the platform variation.
- if incomingVariation == "" {
- return ""
- }
-
- if len(apexInfos) == 0 {
- if ctx.IsAddingDependency() {
- // If this module has no apex variations we can't do any mapping on the incoming variation, just return it
- // and let the caller get a "missing variant" error.
- return incomingVariation
- } else {
- // If this module has no apex variations the use the platform variation.
- return ""
- }
- }
-
- // Convert the list of apex infos into from the AllApexInfoProvider into the merged list
- // of apex variations and the aliases from apex names to apex variations.
- var aliases [][2]string
- if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, aliases = mergeApexVariations(apexInfos)
- }
-
- // Check if the incoming variation matches an apex name, and if so use the corresponding
- // apex variation.
- aliasIndex := slices.IndexFunc(aliases, func(alias [2]string) bool {
- return alias[0] == incomingVariation
- })
- if aliasIndex >= 0 {
- return aliases[aliasIndex][1]
- }
-
- // Check if the incoming variation matches an apex variation.
- apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
- return info.ApexVariationName == incomingVariation
- })
- if apexIndex >= 0 {
- return incomingVariation
- }
-
- return ""
-}
-
-func MutateApexTransition(ctx BaseModuleContext, variation string) {
- module := ctx.Module().(ApexModule)
- base := module.apexModuleBase()
- platformVariation := variation == ""
-
- var apexInfos []ApexInfo
- if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- apexInfos = allApexInfos.ApexInfos
- }
-
- if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) && module.NotAvailableForPlatform() {
- // Do not install the module for platform, but still allow it to output
- // uninstallable AndroidMk entries in certain cases when they have side
- // effects. TODO(jiyong): move this routine to somewhere else
- module.MakeUninstallable()
- }
-
- // Do some validity checks.
- // TODO(jiyong): is this the right place?
- base.checkApexAvailableProperty(ctx)
-
- // Shortcut
- if len(apexInfos) == 0 {
- return
- }
-
- if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, _ = mergeApexVariations(apexInfos)
- }
-
- if !platformVariation {
- var thisApexInfo ApexInfo
-
- apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
- return info.ApexVariationName == variation
- })
- if apexIndex >= 0 {
- thisApexInfo = apexInfos[apexIndex]
- } else {
- panic(fmt.Errorf("failed to find apexInfo for incoming variation %q", variation))
- }
- thisApexInfo.ApexAvailableFor = module.ApexAvailableFor()
-
- SetProvider(ctx, ApexInfoProvider, thisApexInfo)
- }
-}
-
-func ApexInfoMutator(ctx TopDownMutatorContext, module ApexModule) {
- base := module.apexModuleBase()
- if len(base.apexInfos) > 0 {
- apexInfos := slices.Clone(base.apexInfos)
- slices.SortFunc(apexInfos, func(a, b ApexInfo) int {
- return strings.Compare(a.ApexVariationName, b.ApexVariationName)
- })
- SetProvider(ctx, AllApexInfoProvider, &AllApexInfo{apexInfos})
- // base.apexInfos is only needed to propagate the list of apexes from the apex module to its
- // contents within apexInfoMutator. Clear it so it doesn't accidentally get used later.
- base.apexInfos = nil
- }
-}
-
// UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies that are
// in the same APEX have unique APEX variations so that the module can link against the right
// variant.
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
- // anyInSameApex returns true if the two ApexInfo lists contain any values in an
- // InApexVariants list in common. It is used instead of OutgoingDepIsInSameApex because it needs to
- // determine if the dep is in the same APEX due to being directly included, not only if it
- // is included _because_ it is a dependency.
- anyInSameApex := func(a, b ApexModule) bool {
- collectApexes := func(m ApexModule) []string {
- if allApexInfo, ok := OtherModuleProvider(mctx, m, AllApexInfoProvider); ok {
- var ret []string
- for _, info := range allApexInfo.ApexInfos {
- ret = append(ret, info.InApexVariants...)
- }
- return ret
- }
- return nil
- }
-
- aApexes := collectApexes(a)
- bApexes := collectApexes(b)
- sort.Strings(bApexes)
- for _, aApex := range aApexes {
- index := sort.SearchStrings(bApexes, aApex)
- if index < len(bApexes) && bApexes[index] == aApex {
- return true
- }
- }
- return false
- }
-
// If any of the dependencies requires unique apex variations, so does this module.
mctx.VisitDirectDeps(func(dep Module) {
if depApexModule, ok := dep.(ApexModule); ok {
- if anyInSameApex(depApexModule, am) &&
+ if IsDepInSameApex(mctx, am, depApexModule) &&
(depApexModule.UniqueApexVariations() ||
depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
@@ -849,8 +734,14 @@
})
}
+type MinSdkVersionFromValueContext interface {
+ Config() Config
+ DeviceConfig() DeviceConfig
+ ModuleErrorContext
+}
+
// Construct ApiLevel object from min_sdk_version string value
-func MinSdkVersionFromValue(ctx EarlyModuleContext, value string) ApiLevel {
+func MinSdkVersionFromValue(ctx MinSdkVersionFromValueContext, value string) ApiLevel {
if value == "" {
return NoneApiLevel
}
@@ -891,3 +782,21 @@
// to generate the mainline module prebuilt.
Prebuilt_info_file_path string `json:",omitempty"`
}
+
+// FragmentInApexTag is embedded into a dependency tag to allow apex modules to annotate
+// their fragments in a way that allows the java bootclasspath modules to traverse from
+// the apex to the fragment.
+type FragmentInApexTag struct{}
+
+func (FragmentInApexTag) isFragmentInApexTag() {}
+
+type isFragmentInApexTagIntf interface {
+ isFragmentInApexTag()
+}
+
+// IsFragmentInApexTag returns true if the dependency tag embeds FragmentInApexTag,
+// signifying that it is a dependency from an apex module to its fragment.
+func IsFragmentInApexTag(tag blueprint.DependencyTag) bool {
+ _, ok := tag.(isFragmentInApexTagIntf)
+ return ok
+}
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index ce34278..fe7a835 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -104,19 +104,8 @@
AcDepTag = apexContributionsDepTag{}
)
-// Creates a dep to each selected apex_contributions
-func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) {
- // Skip apex_contributions if BuildApexContributionContents is true
- // This product config var allows some products in the same family to use mainline modules from source
- // (e.g. shiba and shiba_fullmte)
- // Eventually these product variants will have their own release config maps.
- if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) {
- ctx.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...)
- }
-}
-
// Set PrebuiltSelectionInfoProvider in post deps phase
-func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
+func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BottomUpMutatorContext) {
addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
for _, content := range m.Contents() {
// Verify that the module listed in contents exists in the tree
@@ -135,13 +124,23 @@
}
p := PrebuiltSelectionInfoMap{}
- ctx.VisitDirectDepsWithTag(AcDepTag, func(child Module) {
- if m, ok := child.(*apexContributions); ok {
- addContentsToProvider(&p, m)
- } else {
- ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
+ // Skip apex_contributions if BuildApexContributionContents is true
+ // This product config var allows some products in the same family to use mainline modules from source
+ // (e.g. shiba and shiba_fullmte)
+ // Eventually these product variants will have their own release config maps.
+ if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) {
+ deps := ctx.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...)
+ for _, child := range deps {
+ if child == nil {
+ continue
+ }
+ if m, ok := child.(*apexContributions); ok {
+ addContentsToProvider(&p, m)
+ } else {
+ ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
+ }
}
- })
+ }
SetProvider(ctx, PrebuiltSelectionInfoProvider, p)
}
diff --git a/android/apex_test.go b/android/apex_test.go
deleted file mode 100644
index acc195d..0000000
--- a/android/apex_test.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android
-
-import (
- "reflect"
- "testing"
-)
-
-func Test_mergeApexVariations(t *testing.T) {
- const (
- ForPrebuiltApex = true
- NotForPrebuiltApex = false
- )
- tests := []struct {
- name string
- in []ApexInfo
- wantMerged []ApexInfo
- wantAliases [][2]string
- }{
- {
- name: "single",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- },
- },
- {
- name: "merge",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo", "bar"},
- }},
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge version",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: uncheckedFinalApiLevel(30),
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "apex30",
- MinSdkVersion: uncheckedFinalApiLevel(30),
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex30"},
- },
- },
- {
- name: "merge updatable",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge when for prebuilt_apex",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- // This one should not be merged in with the others because it is for
- // a prebuilt_apex.
- {
- ApexVariationName: "baz",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"baz"},
- ForPrebuiltApex: ForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "baz",
- MinSdkVersion: FutureApiLevel,
- Updatable: true,
- InApexVariants: []string{"baz"},
- ForPrebuiltApex: ForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000"},
- },
- },
- {
- name: "don't merge different UsePlatformApis",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000",
- MinSdkVersion: FutureApiLevel,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "apex10000_p",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000"},
- {"bar", "apex10000_p"},
- },
- },
- {
- name: "merge same UsePlatformApis and allow using platform api",
- in: []ApexInfo{
- {
- ApexVariationName: "foo",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"foo"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- {
- ApexVariationName: "bar",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantMerged: []ApexInfo{
- {
- ApexVariationName: "apex10000_p",
- MinSdkVersion: FutureApiLevel,
- UsePlatformApis: true,
- InApexVariants: []string{"foo", "bar"},
- ForPrebuiltApex: NotForPrebuiltApex,
- },
- },
- wantAliases: [][2]string{
- {"foo", "apex10000_p"},
- {"bar", "apex10000_p"},
- },
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- gotMerged, gotAliases := mergeApexVariations(tt.in)
- if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
- t.Errorf("mergeApexVariations() gotMerged = %v, want %v", gotMerged, tt.wantMerged)
- }
- if !reflect.DeepEqual(gotAliases, tt.wantAliases) {
- t.Errorf("mergeApexVariations() gotAliases = %v, want %v", gotAliases, tt.wantAliases)
- }
- })
- }
-}
diff --git a/android/api_levels.go b/android/api_levels.go
index 2b1d01d..b4fa251 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -311,7 +311,7 @@
// ApiLevelFrom converts the given string `raw` to an ApiLevel.
// If `raw` is invalid (empty string, unrecognized codename etc.) it returns an invalid ApiLevel
-func ApiLevelFrom(ctx PathContext, raw string) ApiLevel {
+func ApiLevelFrom(ctx ConfigContext, raw string) ApiLevel {
ret, err := ApiLevelFromUser(ctx, raw)
if err != nil {
return NewInvalidApiLevel(raw)
@@ -333,7 +333,7 @@
//
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
-func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
+func ApiLevelFromUser(ctx ConfigContext, raw string) (ApiLevel, error) {
return ApiLevelFromUserWithConfig(ctx.Config(), raw)
}
@@ -413,7 +413,7 @@
// Converts an API level string `raw` into an ApiLevel in the same method as
// `ApiLevelFromUser`, but the input is assumed to have no errors and any errors
// will panic instead of returning an error.
-func ApiLevelOrPanic(ctx PathContext, raw string) ApiLevel {
+func ApiLevelOrPanic(ctx ConfigContext, raw string) ApiLevel {
value, err := ApiLevelFromUser(ctx, raw)
if err != nil {
panic(err.Error())
diff --git a/android/container.go b/android/container.go
index eb2fc18..5dc97d3 100644
--- a/android/container.go
+++ b/android/container.go
@@ -167,8 +167,8 @@
}
var apexContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
- _, ok := ModuleProvider(mctx, AllApexInfoProvider)
- return ok
+ // TODO(b/394955484): a module can't determine the apexes it belongs to any more
+ return false
}
var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
@@ -380,7 +380,7 @@
func (c *ContainersInfo) ApexNames() (ret []string) {
for _, apex := range c.belongingApexes {
- ret = append(ret, apex.InApexVariants...)
+ ret = append(ret, apex.BaseApexName)
}
slices.Sort(ret)
return ret
@@ -441,14 +441,10 @@
}
}
- var belongingApexes []ApexInfo
- if apexInfo, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
- belongingApexes = apexInfo.ApexInfos
- }
-
return ContainersInfo{
belongingContainers: containers,
- belongingApexes: belongingApexes,
+ // TODO(b/394955484): a module can't determine the apexes it belongs to any more
+ belongingApexes: nil,
}
}
diff --git a/android/deapexer.go b/android/deapexer.go
index 4049d2b..6d00dcd 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -75,8 +75,6 @@
// map from the name of an exported file from a prebuilt_apex to the path to that file. The
// exported file name is the apex relative path, e.g. javalib/core-libart.jar.
- //
- // See Prebuilt.ApexInfoMutator for more information.
exports map[string]WritablePath
// name of the java libraries exported from the apex
diff --git a/android/makevars.go b/android/makevars.go
index 3a60bbb..45fd0d0 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -266,6 +266,11 @@
dists = append(dists, mctx.dists...)
}
+ singletonDists := getSingletonDists(ctx.Config())
+ singletonDists.lock.Lock()
+ dists = append(dists, singletonDists.dists...)
+ singletonDists.lock.Unlock()
+
ctx.VisitAllModules(func(m Module) {
if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled(ctx) {
mctx := &makeVarsContext{
diff --git a/android/makevars_test.go b/android/makevars_test.go
index 5e4499f..95e4b59 100644
--- a/android/makevars_test.go
+++ b/android/makevars_test.go
@@ -9,6 +9,8 @@
result := GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterModuleType("my_module_type", newDistFileModule)
+ ctx.RegisterParallelSingletonType("my_singleton", newDistFileSingleton)
+ ctx.RegisterParallelSingletonModuleType("my_singleton_module", newDistFileSingletonModule)
}),
FixtureModifyConfig(SetKatiEnabledForTests),
PrepareForTestWithMakevars,
@@ -16,12 +18,27 @@
my_module_type {
name: "foo",
}
+ my_singleton_module {
+ name: "bar"
+ }
`)
lateContents := string(result.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).lateForTesting)
matched, err := regexp.MatchString(`call dist-for-goals,my_goal,.*/my_file.txt:my_file.txt\)`, lateContents)
if err != nil || !matched {
- t.Fatalf("Expected a dist, but got: %s", lateContents)
+ t.Fatalf("Expected a dist of my_file.txt, but got: %s", lateContents)
+ }
+ matched, err = regexp.MatchString(`call dist-for-goals,my_singleton_goal,.*/my_singleton_file.txt:my_singleton_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_singleton_file.txt, but got: %s", lateContents)
+ }
+ matched, err = regexp.MatchString(`call dist-for-goals,my_singleton_module_module_goal,.*/my_singleton_module_module_file.txt:my_singleton_module_module_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_singleton_module_module_file.txt, but got: %s", lateContents)
+ }
+ matched, err = regexp.MatchString(`call dist-for-goals,my_singleton_module_singleton_goal,.*/my_singleton_module_singleton_file.txt:my_singleton_module_singleton_file.txt\)`, lateContents)
+ if err != nil || !matched {
+ t.Fatalf("Expected a dist of my_singleton_module_singleton_file.txt, but got: %s", lateContents)
}
}
@@ -40,3 +57,40 @@
WriteFileRule(ctx, out, "Hello, world!")
ctx.DistForGoal("my_goal", out)
}
+
+type distFileSingleton struct {
+}
+
+func newDistFileSingleton() Singleton {
+ return &distFileSingleton{}
+}
+
+func (d *distFileSingleton) GenerateBuildActions(ctx SingletonContext) {
+ out := PathForOutput(ctx, "my_singleton_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_singleton_goal", out)
+}
+
+type distFileSingletonModule struct {
+ SingletonModuleBase
+}
+
+func newDistFileSingletonModule() SingletonModule {
+ sm := &distFileSingletonModule{}
+ InitAndroidSingletonModule(sm)
+ return sm
+}
+
+// GenerateAndroidBuildActions implements SingletonModule.
+func (d *distFileSingletonModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ out := PathForModuleOut(ctx, "my_singleton_module_module_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_singleton_module_module_goal", out)
+}
+
+// GenerateSingletonBuildActions implements SingletonModule.
+func (d *distFileSingletonModule) GenerateSingletonBuildActions(ctx SingletonContext) {
+ out := PathForOutput(ctx, "my_singleton_module_singleton_file.txt")
+ WriteFileRule(ctx, out, "Hello, world!")
+ ctx.DistForGoal("my_singleton_module_singleton_goal", out)
+}
diff --git a/android/mutator.go b/android/mutator.go
index 1b0700a..76487fb 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -159,6 +159,7 @@
var preDeps = []RegisterMutatorFunc{
registerArchMutator,
+ RegisterPrebuiltsPreDepsMutators,
}
var postDeps = []RegisterMutatorFunc{
diff --git a/android/prebuilt.go b/android/prebuilt.go
index bf27178..6b076b7 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -28,6 +28,7 @@
func RegisterPrebuiltMutators(ctx RegistrationContext) {
ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators)
+ ctx.PreDepsMutators(RegisterPrebuiltsPreDepsMutators)
ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
}
@@ -195,6 +196,10 @@
return p.properties.UsePrebuilt
}
+func (p *Prebuilt) SetUsePrebuilt(use bool) {
+ p.properties.UsePrebuilt = use
+}
+
// Called to provide the srcs value for the prebuilt module.
//
// This can be called with a context for any module not just the prebuilt one itself. It can also be
@@ -422,9 +427,12 @@
ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).UsesRename()
}
-func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
+func RegisterPrebuiltsPreDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).UsesReverseDependencies()
ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator)
+}
+
+func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies()
}
@@ -468,7 +476,7 @@
bmn, _ := m.(baseModuleName)
name := bmn.BaseModuleName()
if ctx.OtherModuleReverseDependencyVariantExists(name) {
- ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
+ ctx.AddReverseVariationDependency(nil, PrebuiltDepTag, name)
p.properties.SourceExists = true
}
}
@@ -604,6 +612,13 @@
}
}
+func IsDontReplaceSourceWithPrebuiltTag(tag blueprint.DependencyTag) bool {
+ if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
+ return !t.ReplaceSourceWithPrebuilt()
+ }
+ return false
+}
+
// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the
// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not
// be used, disable installing it.
diff --git a/android/register.go b/android/register.go
index 8d2f19e..332ec27 100644
--- a/android/register.go
+++ b/android/register.go
@@ -192,6 +192,11 @@
func collateGloballyRegisteredSingletons() sortableComponents {
allSingletons := append(sortableComponents(nil), singletons...)
allSingletons = append(allSingletons,
+ // Soong only androidmk is registered later than other singletons in order to collect
+ // dist contributions from other singletons. This singleton is registered just before
+ // phony so that its phony rules can be collected by the phony singleton.
+ singleton{parallel: false, name: "soongonlyandroidmk", factory: soongOnlyAndroidMkSingletonFactory},
+
// Register phony just before makevars so it can write out its phony rules as Make rules
singleton{parallel: false, name: "phony", factory: phonySingletonFactory},
diff --git a/android/singleton.go b/android/singleton.go
index 0754b0c..df22045 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -15,6 +15,9 @@
package android
import (
+ "slices"
+ "sync"
+
"github.com/google/blueprint"
)
@@ -97,6 +100,24 @@
// HasMutatorFinished returns true if the given mutator has finished running.
// It will panic if given an invalid mutator name.
HasMutatorFinished(mutatorName string) bool
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoal(goal string, paths ...Path)
+
+ // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when the specified
+ // goal is built.
+ DistForGoalWithFilename(goal string, path Path, filename string)
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoals(goals []string, paths ...Path)
+
+ // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when any of the
+ // specified goals are built.
+ DistForGoalsWithFilename(goals []string, path Path, filename string)
}
type singletonAdaptor struct {
@@ -118,6 +139,13 @@
s.buildParams = sctx.buildParams
s.ruleParams = sctx.ruleParams
+
+ if len(sctx.dists) > 0 {
+ dists := getSingletonDists(sctx.Config())
+ dists.lock.Lock()
+ defer dists.lock.Unlock()
+ dists.dists = append(dists.dists, sctx.dists...)
+ }
}
func (s *singletonAdaptor) BuildParamsForTests() []BuildParams {
@@ -128,6 +156,19 @@
return s.ruleParams
}
+var singletonDistsKey = NewOnceKey("singletonDistsKey")
+
+type singletonDistsAndLock struct {
+ dists []dist
+ lock sync.Mutex
+}
+
+func getSingletonDists(config Config) *singletonDistsAndLock {
+ return config.Once(singletonDistsKey, func() interface{} {
+ return &singletonDistsAndLock{}
+ }).(*singletonDistsAndLock)
+}
+
type Singleton interface {
GenerateBuildActions(SingletonContext)
}
@@ -137,6 +178,7 @@
buildParams []BuildParams
ruleParams map[blueprint.Rule]blueprint.RuleParams
+ dists []dist
}
func (s *singletonContextAdaptor) blueprintSingletonContext() blueprint.SingletonContext {
@@ -315,3 +357,31 @@
func (s *singletonContextAdaptor) HasMutatorFinished(mutatorName string) bool {
return s.blueprintSingletonContext().HasMutatorFinished(mutatorName)
}
+func (s *singletonContextAdaptor) DistForGoal(goal string, paths ...Path) {
+ s.DistForGoals([]string{goal}, paths...)
+}
+
+func (s *singletonContextAdaptor) DistForGoalWithFilename(goal string, path Path, filename string) {
+ s.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (s *singletonContextAdaptor) DistForGoals(goals []string, paths ...Path) {
+ var copies distCopies
+ for _, path := range paths {
+ copies = append(copies, distCopy{
+ from: path,
+ dest: path.Base(),
+ })
+ }
+ s.dists = append(s.dists, dist{
+ goals: slices.Clone(goals),
+ paths: copies,
+ })
+}
+
+func (s *singletonContextAdaptor) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+ s.dists = append(s.dists, dist{
+ goals: slices.Clone(goals),
+ paths: distCopies{{from: path, dest: filename}},
+ })
+}
diff --git a/android/visibility.go b/android/visibility.go
index cee465e..4837c7d 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -529,7 +529,7 @@
rule := effectiveVisibilityRules(ctx.Config(), depQualified)
if !rule.matches(qualified) {
- ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility", depQualified, "//"+ctx.ModuleDir())
+ ctx.ModuleErrorf("depends on %s which is not visible to this module\nYou may need to add %q to its visibility, %#v", depQualified, "//"+ctx.ModuleDir(), ctx.OtherModuleDependencyTag(dep))
}
})
}
diff --git a/apex/apex.go b/apex/apex.go
index cb9dc49..0481658 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -61,12 +61,11 @@
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_info", apexInfoMutator)
ctx.BottomUp("apex_unique", apexUniqueVariationsMutator)
// Run mark_platform_availability before the apexMutator as the apexMutator needs to know whether
// it should create a platform variant.
ctx.BottomUp("mark_platform_availability", markPlatformAvailability)
- ctx.Transition("apex", &apexTransitionMutator{})
+ ctx.InfoBasedTransition("apex", android.NewGenericTransitionMutatorAdapter(&apexTransitionMutator{}))
}
type apexBundleProperties struct {
@@ -768,6 +767,17 @@
shBinaryTag = &dependencyTag{name: "shBinary", payload: true}
)
+type fragmentInApexDepTag struct {
+ blueprint.BaseDependencyTag
+ android.FragmentInApexTag
+}
+
+func (fragmentInApexDepTag) ExcludeFromVisibilityEnforcement() {}
+
+// fragmentInApexTag is used by apex modules to depend on their fragments. Java bootclasspath
+// modules can traverse from the apex to the fragment using android.IsFragmentInApexTag.
+var fragmentInApexTag = fragmentInApexDepTag{}
+
// TODO(jiyong): shorten this function signature
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeModules ResolvedApexNativeDependencies, target android.Target, imageVariation string) {
binVariations := target.Variations()
@@ -916,6 +926,7 @@
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...)
ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments.GetOrDefault(ctx, nil)...)
+ ctx.AddFarVariationDependencies(commonVariation, fragmentInApexTag, a.properties.Bootclasspath_fragments.GetOrDefault(ctx, nil)...)
ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments.GetOrDefault(ctx, nil)...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
@@ -984,45 +995,29 @@
}
}
-var _ ApexInfoMutator = (*apexBundle)(nil)
+var _ ApexTransitionMutator = (*apexBundle)(nil)
func (a *apexBundle) ApexVariationName() string {
return a.properties.ApexVariationName
}
-// ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
-// identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
-// indirect) dependencies are collected. But a few types of modules that shouldn't be included in
-// the apexBundle (e.g. stub libraries) are not collected. Note that a single module can be depended
-// on by multiple apexBundles. In that case, the module is collected for all of the apexBundles.
-//
-// For each dependency between an apex and an ApexModule an ApexInfo object describing the apex
-// is passed to that module's BuildForApex(ApexInfo) method which collates them all in a list.
-// The apexMutator uses that list to create module variants for the apexes to which it belongs.
-// The relationship between module variants and apexes is not one-to-one as variants will be
-// shared between compatible apexes.
-func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
+type generateApexInfoContext interface {
+ android.MinSdkVersionFromValueContext
+ Module() android.Module
+ ModuleName() string
+}
+// generateApexInfo returns an android.ApexInfo configuration that should be used for dependencies of this apex.
+func (a *apexBundle) generateApexInfo(ctx generateApexInfoContext) android.ApexInfo {
// The VNDK APEX is special. For the APEX, the membership is described in a very different
// way. There is no dependency from the VNDK APEX to the VNDK libraries. Instead, VNDK
// libraries are self-identified by their vndk.enabled properties. There is no need to run
- // this mutator for the APEX as nothing will be collected. So, let's return fast.
+ // this mutator for the APEX as nothing will be collected so return an empty ApexInfo.
if a.vndkApex {
- return
+ return android.ApexInfo{}
}
- continueApexDepsWalk := func(child, parent android.Module) bool {
- am, ok := child.(android.ApexModule)
- if !ok || !am.CanHaveApexVariants() {
- return false
- }
-
- return android.IsDepInSameApex(mctx, parent, child)
- }
-
- android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
-
- minSdkVersion := a.minSdkVersion(mctx)
+ minSdkVersion := a.minSdkVersion(ctx)
// When min_sdk_version is not set, the apex is built against FutureApiLevel.
if minSdkVersion.IsNone() {
minSdkVersion = android.FutureApiLevel
@@ -1031,56 +1026,45 @@
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
- apexVariationName := mctx.ModuleName() // could be com.android.foo
+ apexVariationName := ctx.ModuleName() // could be com.android.foo
if a.GetOverriddenBy() != "" {
// use the overridden name com.mycompany.android.foo
apexVariationName = a.GetOverriddenBy()
}
- a.properties.ApexVariationName = apexVariationName
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
MinSdkVersion: minSdkVersion,
Updatable: a.Updatable(),
UsePlatformApis: a.UsePlatformApis(),
- InApexVariants: []string{apexVariationName},
- BaseApexName: mctx.ModuleName(),
+ BaseApexName: ctx.ModuleName(),
ApexAvailableName: proptools.String(a.properties.Apex_available_name),
}
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if !continueApexDepsWalk(child, parent) {
- return false
- }
- child.(android.ApexModule).BuildForApex(apexInfo) // leave a mark!
- return true
- })
+ return apexInfo
}
-type ApexInfoMutator interface {
- // ApexVariationName returns the name of the APEX variation to use in the apex
- // mutator etc. It is the same name as ApexInfo.ApexVariationName.
- ApexVariationName() string
-
- // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
- // depended upon by an apex and which require an apex specific variant.
- ApexInfoMutator(android.TopDownMutatorContext)
+func (a *apexBundle) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{a.generateApexInfo(ctx)}
}
-// apexInfoMutator delegates the work of identifying which modules need an ApexInfo and apex
-// specific variant to modules that support the ApexInfoMutator.
-// It also propagates updatable=true to apps of updatable apexes
-func apexInfoMutator(mctx android.TopDownMutatorContext) {
- if !mctx.Module().Enabled(mctx) {
- return
- }
+func (a *apexBundle) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
- if a, ok := mctx.Module().(ApexInfoMutator); ok {
- a.ApexInfoMutator(mctx)
- }
+func (a *apexBundle) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return a.generateApexInfo(ctx)
+}
- if am, ok := mctx.Module().(android.ApexModule); ok {
- android.ApexInfoMutator(mctx, am)
- }
+func (a *apexBundle) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
+ a.properties.ApexVariationName = info.ApexVariationName
+}
+
+type ApexTransitionMutator interface {
+ ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo
+ ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo
+ ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo
+ ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo)
}
// TODO: b/215736885 Whittle the denylist
@@ -1195,49 +1179,35 @@
type apexTransitionMutator struct{}
-func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
- // apexBundle itself is mutated so that it and its dependencies have the same apex variant.
- if ai, ok := ctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
- if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
- return []string{overridable.GetOverriddenBy()}
- }
- return []string{ai.ApexVariationName()}
+func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorSplit(ctx)
}
- return []string{""}
+ return []android.ApexInfo{{}}
}
-func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
- return sourceVariation
-}
-
-func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
- if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- return android.IncomingApexTransition(ctx, incomingVariation)
- } else if ai, ok := ctx.Module().(ApexInfoMutator); ok {
- if overridable, ok := ctx.Module().(android.OverridableModule); ok && overridable.GetOverriddenBy() != "" {
- return overridable.GetOverriddenBy()
- }
- return ai.ApexVariationName()
+func (a *apexTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorOutgoing(ctx, sourceInfo)
}
-
- return ""
+ return android.ApexInfo{}
}
-func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
- if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- android.MutateApexTransition(ctx, variation)
+func (a *apexTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ return ai.ApexTransitionMutatorIncoming(ctx, outgoingInfo)
+ }
+ return android.ApexInfo{}
+}
+
+func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ if ai, ok := ctx.Module().(ApexTransitionMutator); ok {
+ ai.ApexTransitionMutatorMutate(ctx, info)
}
}
-// apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
-// variant.
-func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
- if a, ok := module.(*apexBundle); ok {
- // TODO(jiyong): document the reason why the VNDK APEX is an exception here.
- return !a.vndkApex
- }
-
- return true
+func (a *apexTransitionMutator) TransitionInfoFromVariation(variation string) android.ApexInfo {
+ panic(fmt.Errorf("adding dependencies on explicit apex variations is not supported"))
}
const (
@@ -1665,10 +1635,6 @@
// to the child modules. Returning false makes the visit to continue in the sibling or the parent
// modules. This is used in check* functions below.
func (a *apexBundle) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
- apexVariationName := ctx.ModuleName()
- if overrideName := a.GetOverriddenBy(); overrideName != "" {
- apexVariationName = overrideName
- }
ctx.WalkDeps(func(child, parent android.Module) bool {
am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() {
@@ -1687,8 +1653,7 @@
return false
}
- ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- externalDep := !android.InList(apexVariationName, ai.InApexVariants)
+ externalDep := !android.IsDepInSameApex(ctx, parent, child)
// Visit actually
return do(ctx, parent, am, externalDep)
@@ -1713,8 +1678,7 @@
return false
}
- ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
+ externalDep := !android.IsDepInSameApex(ctx, parent, child)
// Visit actually
return do(ctx, parent, child, externalDep)
@@ -2567,7 +2531,7 @@
}
// Returns apex's min_sdk_version string value, honoring overrides
-func (a *apexBundle) minSdkVersionValue(ctx android.EarlyModuleContext) string {
+func (a *apexBundle) minSdkVersionValue(ctx android.MinSdkVersionFromValueContext) string {
// Only override the minSdkVersion value on Apexes which already specify
// a min_sdk_version (it's optional for non-updatable apexes), and that its
// min_sdk_version value is lower than the one to override with.
@@ -2591,7 +2555,7 @@
}
// Returns apex's min_sdk_version ApiLevel, honoring overrides
-func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+func (a *apexBundle) minSdkVersion(ctx android.MinSdkVersionFromValueContext) android.ApiLevel {
return android.MinSdkVersionFromValue(ctx, a.minSdkVersionValue(ctx))
}
@@ -2607,7 +2571,7 @@
librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true
})
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool {
if info, ok := android.OtherModuleProvider(ctx, to, cc.LinkableInfoProvider); ok {
// If `to` is not actually in the same APEX as `from` then it does not need
// apex_available and neither do any of its dependencies.
@@ -2721,7 +2685,7 @@
return
}
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.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
@@ -2739,7 +2703,7 @@
toName := ctx.OtherModuleName(to)
if android.CheckAvailableForApex(apexName,
- android.OtherModuleProviderOrDefault(ctx, to, android.ApexInfoProvider).ApexAvailableFor) {
+ android.OtherModuleProviderOrDefault(ctx, to, android.ApexAvailableInfoProvider).ApexAvailableFor) {
return true
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8515792..6c1a2d6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5190,7 +5190,7 @@
}
`)
- testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ testingModule := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
prebuilt := testingModule.Module().(*Prebuilt)
expectedInput := "myapex-arm64.apex"
@@ -5211,7 +5211,7 @@
func TestPrebuiltMissingSrc(t *testing.T) {
t.Parallel()
- testApexError(t, `module "myapex" variant "android_common_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
+ testApexError(t, `module "myapex" variant "android_common_prebuilt_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
prebuilt_apex {
name: "myapex",
}
@@ -5228,7 +5228,7 @@
}
`)
- testingModule := ctx.ModuleForTests("myapex", "android_common_myapex")
+ testingModule := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
p := testingModule.Module().(*Prebuilt)
expected := "notmyapex.apex"
@@ -5251,7 +5251,7 @@
set: "company-myapex.apks",
filename: "com.company.android.myapex.apex"
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApex(t, `
apex_set {
@@ -5260,7 +5260,7 @@
set: "company-myapex.apks",
filename: "com.company.android.myapex.capex"
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApexError(t, `filename should end in .apex or .capex for apex_set`, `
apex_set {
@@ -5284,7 +5284,7 @@
}
`)
- testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt")
+ testingModule := ctx.ModuleForTests("myapex.prebuilt", "android_common_prebuilt_myapex.prebuilt")
p := testingModule.Module().(*Prebuilt)
expected := []string{"myapex"}
@@ -5307,7 +5307,7 @@
apex_name: "com.android.myapex",
src: "company-myapex-arm.apex",
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
testApex(t, `
apex_set {
@@ -5315,7 +5315,7 @@
apex_name: "com.android.myapex",
set: "company-myapex.apks",
}
- `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+ `).ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
}
func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
@@ -5341,6 +5341,12 @@
exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
}
+ prebuilt_apex {
+ name: "com.android.art",
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
prebuilt_bootclasspath_fragment {
name: "art-bootclasspath-fragment",
image_name: "art",
@@ -5549,7 +5555,7 @@
out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
`)
- myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
+ myApex := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex").Module()
overrideNames := []string{
"",
@@ -5633,7 +5639,7 @@
// prebuilt_apex module always depends on the prebuilt, and so it doesn't
// find the dex boot jar in it. We either need to disable the source libfoo
// or make the prebuilt libfoo preferred.
- testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer, fragment)
+ testDexpreoptWithApexes(t, bp, `module "platform-bootclasspath" variant ".*": module libfoo{.*} does not provide a dex jar`, preparer, fragment)
// dexbootjar check is skipped if AllowMissingDependencies is true
preparerAllowMissingDeps := android.GroupFixturePreparers(
preparer,
@@ -5669,6 +5675,7 @@
prebuilt_apex {
name: "myapex",
+ prefer: true,
arch: {
arm64: {
src: "myapex-arm64.apex",
@@ -6603,16 +6610,10 @@
testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
.*via tag apex\.dependencyTag\{"sharedLib"\}
.*-> libfoo.*link:shared.*
-.*via tag cc\.dependencyTag.*
-.*-> libfoo.*link:static.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
.*-> libbar.*link:shared.*
-.*via tag cc\.dependencyTag.*
-.*-> libbar.*link:static.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
-.*-> libbaz.*link:shared.*
-.*via tag cc\.dependencyTag.*
-.*-> libbaz.*link:static.*`, `
+.*-> libbaz.*link:shared.*`, `
apex {
name: "myapex",
key: "myapex.key",
@@ -7872,7 +7873,7 @@
})
// The bar library should depend on the implementation jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+ barLibrary := ctx.ModuleForTests("bar", "android_common_apex10000").Rule("javac")
if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
@@ -8018,7 +8019,7 @@
})
// The bar library should depend on the implementation jar.
- barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+ barLibrary := ctx.ModuleForTests("bar", "android_common_apex10000").Rule("javac")
if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
@@ -8498,31 +8499,6 @@
ensureListContains(t, names(rule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
}
-func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
- t.Parallel()
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- updatable: false,
- }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
- `,
- android.FixtureModifyConfig(func(config android.Config) {
- delete(config.Targets, android.Android)
- config.AndroidCommonTarget = android.Target{}
- }),
- )
-
- if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
- t.Errorf("Expected variants: %v, but got: %v", expected, got)
- }
-}
-
func TestAppBundle(t *testing.T) {
t.Parallel()
ctx := testApex(t, `
@@ -8609,16 +8585,16 @@
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
- extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
// Ditto for the apex.
- m = ctx.ModuleForTests("myapex", "android_common_myapex")
- copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_myapex/foo_v2.apex")
+ m = ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
+ copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_prebuilt_myapex/foo_v2.apex")
android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
}
@@ -8637,10 +8613,10 @@
}
`)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -9029,7 +9005,7 @@
}),
)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -9044,7 +9020,7 @@
t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
}
- m = ctx.ModuleForTests("myapex", "android_common_myapex")
+ m = ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
a := m.Module().(*ApexSet)
expectedOverrides := []string{"foo"}
actualOverrides := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
@@ -9071,7 +9047,7 @@
}),
)
- m := ctx.ModuleForTests("myapex", "android_common_myapex")
+ m := ctx.ModuleForTests("myapex", "android_common_prebuilt_myapex")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -9179,7 +9155,7 @@
ctx.ModuleForTests("myapex", "android_common_myapex").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
content = android.ContentFromFileRuleForTests(t, ctx,
- ctx.ModuleForTests("myapex_set", "android_common_myapex_set").Output("apexkeys.txt"))
+ ctx.ModuleForTests("myapex_set", "android_common_prebuilt_myapex_set").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
}
@@ -9358,7 +9334,7 @@
}),
)
- build := ctx.ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex").Output("com.company.android.myapex.apex")
+ build := ctx.ModuleForTests("com.company.android.myapex", "android_common_prebuilt_com.android.myapex").Output("com.company.android.myapex.apex")
if compressionEnabled {
ensureEquals(t, build.Rule.String(), "android/soong/android.Cp")
} else {
@@ -11305,12 +11281,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/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
},
{
desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedApexContributions: "foo.prebuilt.v2.contributions",
- expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_com.android.foo/deapexer/javalib/framework-foo.jar",
+ expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
},
}
@@ -11355,7 +11331,7 @@
// for a mainline module family, check that only the flagged soong module is visible to make
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
- ret := "android_common_com.android.foo"
+ ret := "android_common_prebuilt_com.android.foo"
if moduleName == "com.google.android.foo" {
ret = "android_common_com.google.android.foo"
}
@@ -11502,8 +11478,8 @@
checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleNames []string, hiddenModuleNames []string) {
variation := func(moduleName string) string {
ret := "android_common_com.android.adservices"
- if moduleName == "com.google.android.foo" {
- ret = "android_common_com.google.android.foo_com.google.android.foo"
+ if moduleName == "com.google.android.adservices" || moduleName == "com.google.android.adservices.v2" {
+ ret = "android_common_prebuilt_com.android.adservices"
}
return ret
}
@@ -11578,13 +11554,13 @@
expectedHiddenModuleNames: []string{"com.google.android.adservices", "com.google.android.adservices.v2"},
},
{
- desc: "Prebuilt apex prebuilt_com.android.foo is selected",
+ desc: "Prebuilt apex prebuilt_com.android.adservices is selected",
selectedApexContributions: "adservices.prebuilt.contributions",
expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices"},
expectedHiddenModuleNames: []string{"com.google.android.adservices.v2"},
},
{
- desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected",
+ desc: "Prebuilt apex prebuilt_com.android.adservices.v2 is selected",
selectedApexContributions: "adservices.prebuilt.v2.contributions",
expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices.v2"},
expectedHiddenModuleNames: []string{"com.google.android.adservices"},
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index c7674b5..60d111f 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -292,6 +292,7 @@
apex_available: [
"com.android.art",
],
+ min_sdk_version: "33",
compile_dex: true,
}
`, content, prefer)
@@ -420,7 +421,7 @@
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
- ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_com.android.art", []string{
+ ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_prebuilt_com.android.art", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
@@ -431,6 +432,7 @@
`art-bootclasspath-fragment`,
`com.android.art.key`,
`dex2oatd`,
+ `prebuilt_art-bootclasspath-fragment`,
`prebuilt_com.android.art`,
})
@@ -589,13 +591,13 @@
t.Parallel()
result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
- java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_prebuilt_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
})
- java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
+ java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_prebuilt_com.android.art", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_bar`,
@@ -862,8 +864,8 @@
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1039,8 +1041,8 @@
"android-non-updatable.stubs.module_lib",
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1213,8 +1215,8 @@
"android-non-updatable.stubs.system",
"android-non-updatable.stubs.test",
"android-non-updatable.stubs.test_module_lib",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
})
@@ -1364,8 +1366,8 @@
java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_myapex", []string{
"all_apex_contributions",
- "art-bootclasspath-fragment",
"bar",
+ "com.android.art",
"dex2oatd",
"foo",
"prebuilt_sdk_module-lib_current_android-non-updatable",
diff --git a/apex/builder.go b/apex/builder.go
index 63efa63..03a0bb9 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -1105,7 +1105,7 @@
}
depInfos := android.DepNameToDepInfoMap{}
- a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.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.
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index 55f1475..c2f2fc5 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -205,8 +205,6 @@
myFragment := result.Module("mybootclasspath-fragment", "android_common_myapex")
myBar := result.Module("bar", "android_common_apex10000")
- other := result.Module("othersdklibrary", "android_common_apex10000")
-
otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
platformFoo := result.Module("quuz", "android_common")
@@ -240,7 +238,11 @@
t.Run("art:baz, art:quuz, my:bar, foo", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, artQuuz, myBar, platformFoo}, []android.Module{artFragment, myFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, artQuuz, myBar, platformFoo},
+ []android.Module{artFragment, myFragment},
+ map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectFragmentElement(myFragment, myBar),
@@ -249,32 +251,16 @@
assertElementsEquals(t, "elements", expectedElements, elements)
})
- // Verify that CreateClasspathElements detects when an apex has multiple fragments.
- t.Run("multiple fragments for same apex", func(t *testing.T) {
- t.Parallel()
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{artFragment, artFragment})
- android.FailIfNoMatchingErrors(t, "apex com.android.art has multiple fragments, art-bootclasspath-fragment{.*} and art-bootclasspath-fragment{.*}", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
-
- // Verify that CreateClasspathElements detects when a library is in multiple fragments.
- t.Run("library from multiple fragments", func(t *testing.T) {
- t.Parallel()
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{other}, []android.Module{artFragment, myFragment})
- android.FailIfNoMatchingErrors(t, "library othersdklibrary{.*} is in two separate fragments, art-bootclasspath-fragment{.*} and mybootclasspath-fragment{.*}", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
-
// Verify that CreateClasspathElements detects when a fragment's contents are not contiguous and
// are separated by a library from another fragment.
t.Run("discontiguous separated by fragment", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, myBar, artQuuz, platformFoo}, []android.Module{artFragment, myFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, myBar, artQuuz, platformFoo},
+ []android.Module{artFragment, myFragment},
+ map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectFragmentElement(myFragment, myBar),
@@ -289,7 +275,11 @@
t.Run("discontiguous separated by library", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, platformFoo, artQuuz, myBar}, []android.Module{artFragment, myFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, platformFoo, artQuuz, myBar},
+ []android.Module{artFragment, myFragment},
+ map[android.Module]string{artBaz: "com.android.art", artQuuz: "com.android.art", myBar: "myapex"},
+ map[string]android.Module{"com.android.art": artFragment, "myapex": myFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz, artQuuz),
expectLibraryElement(platformFoo),
@@ -305,7 +295,11 @@
t.Run("no fragment for apex", func(t *testing.T) {
t.Parallel()
ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, otherApexLibrary}, []android.Module{artFragment})
+ elements := java.CreateClasspathElements(ctx,
+ []android.Module{artBaz, otherApexLibrary},
+ []android.Module{artFragment},
+ map[android.Module]string{artBaz: "com.android.art", otherApexLibrary: "otherapex"},
+ map[string]android.Module{"com.android.art": artFragment})
expectedElements := java.ClasspathElements{
expectFragmentElement(artFragment, artBaz),
}
diff --git a/apex/container_test.go b/apex/container_test.go
index 395793f..bf9445b 100644
--- a/apex/container_test.go
+++ b/apex/container_test.go
@@ -29,6 +29,7 @@
func TestApexDepsContainers(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -166,6 +167,7 @@
func TestNonUpdatableApexDepsContainers(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -281,6 +283,7 @@
func TestUpdatableAndNonUpdatableApexesIdenticalMinSdkVersion(t *testing.T) {
t.Parallel()
+ t.Skip("TODO(b/394955484): this probably has to be moved to a check by the apex")
result := android.GroupFixturePreparers(
prepareForApexTest,
java.PrepareForTestWithJavaSdkLibraryFiles,
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index 6fa1fe2..5abad81 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -215,7 +215,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ "out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
"out/soong/dexpreopt/uffd_gc_flag.txt",
}
@@ -401,12 +401,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/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
},
{
desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt",
selectedArtApexContributions: "art.prebuilt.v2.contributions",
- expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_com.android.art/deapexer/etc/boot-image.prof",
+ expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_prebuilt_com.android.art/deapexer/etc/boot-image.prof",
},
}
for _, tc := range testCases {
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 8b5fce9..d79af86 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -23,7 +23,6 @@
"android/soong/dexpreopt"
"android/soong/java"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -240,8 +239,8 @@
pbcp := result.Module("myplatform-bootclasspath", "android_common")
info, _ := android.OtherModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
- android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
- android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
+ android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
}
func TestPlatformBootclasspathDependencies(t *testing.T) {
@@ -388,7 +387,7 @@
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
- CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
// source vs prebuilt selection metadata module
`platform:all_apex_contributions`,
@@ -401,17 +400,17 @@
// Needed for generating the boot image.
`platform:dex2oatd`,
- // The configured contents of BootJars.
- `com.android.art:baz`,
- `com.android.art:quuz`,
+ // The configured contents of BootJars, via their apexes if necessary.
+ `platform:com.android.art`,
+ `platform:com.android.art`,
`platform:foo`,
- // The configured contents of ApexBootJars.
- `myapex:bar`,
+ // The configured contents of ApexBootJars, via their apex.
+ `platform:myapex`,
- // The fragments.
- `com.android.art:art-bootclasspath-fragment`,
- `myapex:my-bootclasspath-fragment`,
+ // The fragments via their apexes.
+ `platform:com.android.art`,
+ `platform:myapex`,
// Impl lib of sdk_library for transitive srcjar generation
`platform:foo.impl`,
@@ -429,7 +428,7 @@
// of AlwaysUsePrebuiltsSdk(). The second is a normal library that is unaffected. The order
// matters, so that the dependencies resolved by the platform_bootclasspath matches the
// configured list.
- java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
+ java.FixtureConfigureApexBootJars("myapex:foo"),
java.PrepareForTestWithJavaSdkLibraryFiles,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
@@ -479,6 +478,7 @@
name: "myapex",
src: "myapex.apex",
exported_bootclasspath_fragments: ["mybootclasspath-fragment"],
+ prefer: true,
}
// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
@@ -544,12 +544,11 @@
java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
// The configured contents of BootJars.
- "myapex:prebuilt_foo",
- "myapex:bar",
+ "prebuilt_myapex:prebuilt_foo",
})
// Make sure that the myplatform-bootclasspath has the correct dependencies.
- CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
// source vs prebuilt selection metadata module
`platform:all_apex_contributions`,
@@ -561,39 +560,17 @@
// Not a prebuilt as no prebuilt existed when it was added.
"platform:legacy.core.platform.api.stubs.exportable",
- // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
- // modules when available as it does not know which one will be preferred.
- "myapex:foo",
- "myapex:prebuilt_foo",
+ // The prebuilt library via the apex.
+ "platform:prebuilt_myapex",
- // Only a source module exists.
- "myapex:bar",
-
- // The fragments.
- "myapex:mybootclasspath-fragment",
- "myapex:prebuilt_mybootclasspath-fragment",
+ // The fragments via the apex.
+ "platform:prebuilt_myapex",
// Impl lib of sdk_library for transitive srcjar generation
"platform:foo.impl",
})
}
-// CheckModuleDependencies checks the dependencies of the selected module against the expected list.
-//
-// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
-// name of the apex, or platform is it is not part of an apex and <module> is the module name.
-func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
- t.Helper()
- module := ctx.ModuleForTests(name, variant).Module()
- modules := []android.Module{}
- ctx.VisitDirectDeps(module, func(m blueprint.Module) {
- modules = append(modules, m.(android.Module))
- })
-
- pairs := java.ApexNamePairsFromModules(ctx, modules)
- android.AssertDeepEquals(t, "module dependencies", expected, pairs)
-}
-
// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
// by setting generate_classpaths_proto property to false.
@@ -665,7 +642,7 @@
prepareForTestWithMyapex,
java.FixtureConfigureApexBootJars("myapex:foo"),
).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- `dependency "foo" of "myplatform-bootclasspath" missing variant`)).
+ `module "myplatform-bootclasspath" variant ".*": failed to find module "foo" in apex "myapex"`)).
RunTestWithBp(t, `
apex {
name: "myapex",
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 4fa43ba..e7d92c3 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -291,6 +291,7 @@
for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
prebuiltDep := android.PrebuiltNameFromSource(dep)
ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep)
+ ctx.AddDependency(module, fragmentInApexTag, prebuiltDep)
}
for _, dep := range p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments {
@@ -309,89 +310,34 @@
return true
}
-// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
-// specific variant and checks that they are supported.
-//
-// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are
-// associated with the apex specific variant using the ApexInfoProvider for later retrieval.
-//
-// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
-// across prebuilt_apex modules. That is because there is no way to determine whether two
-// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
-// been built from different source at different times or they could have been built with different
-// build options that affect the libraries.
-//
-// While it may be possible to provide sufficient information to determine whether two prebuilt_apex
-// modules were compatible it would be a lot of work and would not provide much benefit for a couple
-// of reasons:
-// - The number of prebuilt_apex modules that will be exporting files for the same module will be
-// low as the prebuilt_apex only exports files for the direct dependencies that require it and
-// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
-// few com.android.art* apex files that contain the same contents and could export files for the
-// same modules but only one of them needs to do so. Contrast that with source apex modules which
-// need apex specific variants for every module that contributes code to the apex, whether direct
-// or indirect.
-// - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
-// extra copying of files. Contrast that with source apex modules that has to build each variant
-// from source.
-func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
- // Collect the list of dependencies.
- var dependencies []android.ApexModule
- mctx.WalkDeps(func(child, parent android.Module) bool {
- // If the child is not in the same apex as the parent then exit immediately and do not visit
- // any of the child's dependencies.
- if !android.IsDepInSameApex(mctx, parent, child) {
- return false
- }
-
- tag := mctx.OtherModuleDependencyTag(child)
- depName := mctx.OtherModuleName(child)
+func (p *prebuiltCommon) checkExportedDependenciesArePrebuilts(ctx android.ModuleContext) {
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ tag := ctx.OtherModuleDependencyTag(dep)
+ depName := ctx.OtherModuleName(dep)
if exportedTag, ok := tag.(exportedDependencyTag); ok {
propertyName := exportedTag.name
// It is an error if the other module is not a prebuilt.
- if !android.IsModulePrebuilt(child) {
- mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
- return false
+ if !android.IsModulePrebuilt(dep) {
+ ctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
}
// It is an error if the other module is not an ApexModule.
- if _, ok := child.(android.ApexModule); !ok {
- mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
- return false
+ if _, ok := dep.(android.ApexModule); !ok {
+ ctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
}
}
- // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific
- // variant.
- if _, ok := child.(android.ApexModule); !ok {
- return false
- }
-
- // Strip off the prebuilt_ prefix if present before storing content to ensure consistent
- // behavior whether there is a corresponding source module present or not.
- depName = android.RemoveOptionalPrebuiltPrefix(depName)
-
- // Add the module to the list of dependencies that need to have an APEX variant.
- dependencies = append(dependencies, child.(android.ApexModule))
-
- return true
})
+}
- android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
-
- // Create an ApexInfo for the prebuilt_apex.
- apexVariationName := p.ApexVariationName()
- apexInfo := android.ApexInfo{
- ApexVariationName: apexVariationName,
- InApexVariants: []string{apexVariationName},
+// generateApexInfo returns an android.ApexInfo configuration suitable for dependencies of this apex.
+func (p *prebuiltCommon) generateApexInfo(ctx generateApexInfoContext) android.ApexInfo {
+ return android.ApexInfo{
+ ApexVariationName: "prebuilt_" + p.ApexVariationName(),
+ BaseApexName: p.ApexVariationName(),
ForPrebuiltApex: true,
}
-
- // Mark the dependencies of this module as requiring a variant for this module.
- for _, am := range dependencies {
- am.BuildForApex(apexInfo)
- }
}
type Prebuilt struct {
@@ -595,10 +541,22 @@
p.prebuiltApexContentsDeps(ctx)
}
-var _ ApexInfoMutator = (*Prebuilt)(nil)
+var _ ApexTransitionMutator = (*Prebuilt)(nil)
-func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
- p.apexInfoMutator(mctx)
+func (p *Prebuilt) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{p.generateApexInfo(ctx)}
+}
+
+func (p *Prebuilt) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
+
+func (p *Prebuilt) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return p.generateApexInfo(ctx)
+}
+
+func (p *Prebuilt) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
}
// creates the build rules to deapex the prebuilt, and returns a deapexerInfo
@@ -664,6 +622,8 @@
validateApexClasspathFragments(ctx)
}
+ p.checkExportedDependenciesArePrebuilts(ctx)
+
p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module()))
@@ -824,10 +784,22 @@
a.prebuiltApexContentsDeps(ctx)
}
-var _ ApexInfoMutator = (*ApexSet)(nil)
+var _ ApexTransitionMutator = (*ApexSet)(nil)
-func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) {
- a.apexInfoMutator(mctx)
+func (a *ApexSet) ApexTransitionMutatorSplit(ctx android.BaseModuleContext) []android.ApexInfo {
+ return []android.ApexInfo{a.generateApexInfo(ctx)}
+}
+
+func (a *ApexSet) ApexTransitionMutatorOutgoing(ctx android.OutgoingTransitionContext, sourceInfo android.ApexInfo) android.ApexInfo {
+ return sourceInfo
+}
+
+func (a *ApexSet) ApexTransitionMutatorIncoming(ctx android.IncomingTransitionContext, outgoingInfo android.ApexInfo) android.ApexInfo {
+ return a.generateApexInfo(ctx)
+}
+
+func (a *ApexSet) ApexTransitionMutatorMutate(ctx android.BottomUpMutatorContext, info android.ApexInfo) {
+ android.SetProvider(ctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
}
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index c643a8c..81f287f 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -280,19 +280,19 @@
ctx := result.TestContext
- java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`dex2oatd`,
`prebuilt_mysystemserverclasspathfragment`,
})
- java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -440,13 +440,13 @@
ctx := result.TestContext
- java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_prebuilt_myapex", []string{
`all_apex_contributions`,
`prebuilt_bar`,
`prebuilt_foo`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{
+ ensureExactDeapexedContents(t, ctx, "myapex", "android_common_prebuilt_myapex", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
@@ -465,7 +465,7 @@
}
func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) {
- dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName)
+ dexpreopt := ctx.ModuleForTests(apexName, "android_common_prebuilt_"+apexName).Rule("dexpreopt." + moduleName)
actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
if expected != actual {
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
diff --git a/cc/cc.go b/cc/cc.go
index dd557b5..cb11fb8 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -4084,6 +4084,9 @@
}
func (c *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if c.Host() {
+ return false
+ }
if c.HasStubsVariants() {
if IsSharedDepTag(depTag) && !IsExplicitImplSharedDepTag(depTag) {
// dynamic dep to a stubs lib crosses APEX boundary
@@ -4224,7 +4227,6 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
- android.ApexModuleBase
}
// cc_defaults provides a set of properties that can be inherited by other cc
diff --git a/cc/library.go b/cc/library.go
index 789190c..dce3b92 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -2229,6 +2229,9 @@
}
func (linkageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
@@ -2285,11 +2288,13 @@
library.setStatic()
if !library.buildStatic() {
library.disablePrebuilt()
+ ctx.Module().(*Module).Prebuilt().SetUsePrebuilt(false)
}
} else if variation == "shared" {
library.setShared()
if !library.buildShared() {
library.disablePrebuilt()
+ ctx.Module().(*Module).Prebuilt().SetUsePrebuilt(false)
}
}
} else if library, ok := ctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() {
@@ -2402,6 +2407,9 @@
}
func (versionTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
diff --git a/cmd/javac_wrapper/javac_wrapper.go b/cmd/javac_wrapper/javac_wrapper.go
index 4679906..49bcedf 100644
--- a/cmd/javac_wrapper/javac_wrapper.go
+++ b/cmd/javac_wrapper/javac_wrapper.go
@@ -200,6 +200,9 @@
var warningFilters = []*regexp.Regexp{
regexp.MustCompile(`bootstrap class path not set in conjunction with -source`),
+ regexp.MustCompile(`source value 8 is obsolete and will be removed in a future release`),
+ regexp.MustCompile(`target value 8 is obsolete and will be removed in a future release`),
+ regexp.MustCompile(`To suppress warnings about obsolete options, use -Xlint:-options.`),
}
var filters = []*regexp.Regexp{
diff --git a/cmd/javac_wrapper/javac_wrapper_test.go b/cmd/javac_wrapper/javac_wrapper_test.go
index ad23001..5e26786 100644
--- a/cmd/javac_wrapper/javac_wrapper_test.go
+++ b/cmd/javac_wrapper/javac_wrapper_test.go
@@ -90,6 +90,15 @@
`,
out: "\n\x1b[1m\x1b[35mwarning:\x1b[0m\x1b[1m foo\x1b[0m\n1 warning\n",
},
+ {
+ in: `
+warning: [options] source value 8 is obsolete and will be removed in a future release
+warning: [options] target value 8 is obsolete and will be removed in a future release
+warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
+3 warnings
+`,
+ out: "\n",
+ },
}
func TestJavacColorize(t *testing.T) {
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 6c04828..b783d0f 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -79,6 +79,8 @@
partitionProps PartitionNameProperties
deviceProps DeviceProperties
+
+ allImagesZip android.Path
}
func AndroidDeviceFactory() android.Module {
@@ -202,6 +204,17 @@
deps = append(deps, imageOutput.DefaultOutputFiles[0])
})
+ allImagesZip := android.PathForModuleOut(ctx, "all_images.zip")
+ allImagesZipBuilder := android.NewRuleBuilder(pctx, ctx)
+ cmd := allImagesZipBuilder.Command().BuiltTool("soong_zip").Flag("--sort_entries")
+ for _, dep := range deps {
+ cmd.FlagWithArg("-e ", dep.Base())
+ cmd.FlagWithInput("-f ", dep)
+ }
+ cmd.FlagWithOutput("-o ", allImagesZip)
+ allImagesZipBuilder.Build("soong_all_images_zip", "all_images.zip")
+ a.allImagesZip = allImagesZip
+
allImagesStamp := android.PathForModuleOut(ctx, "all_images_stamp")
var validations android.Paths
if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) {
@@ -226,6 +239,12 @@
a.setVbmetaPhonyTargets(ctx)
}
+func (a *androidDevice) MakeVars(ctx android.MakeVarsModuleContext) {
+ if proptools.Bool(a.deviceProps.Main_device) {
+ ctx.StrictRaw("SOONG_ONLY_ALL_IMAGES_ZIP", a.allImagesZip.String())
+ }
+}
+
// Helper structs for target_files.zip creation
type targetFilesZipCopy struct {
srcModule *string
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 0ce31b2..ecc1524 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -131,7 +131,7 @@
// The index used to prevent rollback of the image. Only used if use_avb is true.
Rollback_index *int64
- // Rollback index location of this image. Must be 0, 1, 2, etc.
+ // Rollback index location of this image. Must be 1, 2, 3, etc.
Rollback_index_location *int64
// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
@@ -1373,3 +1373,9 @@
return true
})
}
+
+func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) {
+ if f.Name() == ctx.Config().SoongDefinedSystemImage() {
+ ctx.StrictRaw("SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String())
+ }
+}
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index 5332462..da007bb 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -181,7 +181,7 @@
}
func (s *superImage) installFileName() string {
- return s.BaseModuleName() + ".img"
+ return "super.img"
}
func (s *superImage) buildMiscInfo(ctx android.ModuleContext) (android.Path, android.Paths, map[string]FilesystemInfo) {
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index 91826b2..e5809d3 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -97,7 +97,7 @@
// Name of the chained partition
Name *string
- // Rollback index location of the chained partition. Must be 0, 1, 2, etc. Default is the
+ // Rollback index location of the chained partition. Must be 1, 2, 3, etc. Default is the
// index of this partition in the list + 1.
Rollback_index_location *int64
@@ -225,8 +225,8 @@
}
ril := info.RollbackIndexLocation
- if ril < 0 {
- ctx.PropertyErrorf("chained_partitions", "rollback index location must be 0, 1, 2, ...")
+ if ril < 1 {
+ ctx.PropertyErrorf("chained_partitions", "rollback index location must be 1, 2, 3, ...")
continue
} else if seenRils[ril] {
ctx.PropertyErrorf("chained_partitions", "Multiple chained partitions with the same rollback index location %d", ril)
@@ -241,13 +241,13 @@
for _, cpm := range v.properties.Chained_partition_metadata {
name := proptools.String(cpm.Name)
if name == "" {
- ctx.PropertyErrorf("chained_partitions", "name must be specified")
+ ctx.PropertyErrorf("chained_partition_metadata", "name must be specified")
continue
}
- ril := proptools.IntDefault(cpm.Rollback_index_location, -1)
- if ril < 0 {
- ctx.PropertyErrorf("chained_partition_metadata", "rollback index location must be 0, 1, 2, ...")
+ ril := proptools.IntDefault(cpm.Rollback_index_location, 0)
+ if ril < 1 {
+ ctx.PropertyErrorf("chained_partition_metadata", "rollback index location must be 1, 2, 3, ...")
continue
} else if seenRils[ril] {
ctx.PropertyErrorf("chained_partition_metadata", "Multiple chained partitions with the same rollback index location %d", ril)
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 63d0791..2c2da17 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -1037,13 +1037,6 @@
}
result.avbRollbackIndex = &parsed
}
- if specificPartitionVars.BoardAvbRollbackIndex != "" {
- parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64)
- if err != nil {
- panic(fmt.Sprintf("Rollback index must be an int, got %s", specificPartitionVars.BoardAvbRollbackIndex))
- }
- result.avbRollbackIndex = &parsed
- }
if specificPartitionVars.BoardAvbRollbackIndexLocation != "" {
parsed, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndexLocation, 10, 64)
if err != nil {
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 3413cf3..98fb417 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -15,6 +15,8 @@
package java
import (
+ "fmt"
+
"android/soong/android"
"github.com/google/blueprint"
@@ -23,36 +25,9 @@
// Contains code that is common to both platform_bootclasspath and bootclasspath_fragment.
-func init() {
- registerBootclasspathBuildComponents(android.InitRegistrationContext)
-}
-
-func registerBootclasspathBuildComponents(ctx android.RegistrationContext) {
- ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator)
- })
-}
-
-// BootclasspathDepsMutator is the interface that a module must implement if it wants to add
-// dependencies onto APEX specific variants of bootclasspath fragments or bootclasspath contents.
-type BootclasspathDepsMutator interface {
- // BootclasspathDepsMutator implementations should add dependencies using
- // addDependencyOntoApexModulePair and addDependencyOntoApexVariants.
- BootclasspathDepsMutator(ctx android.BottomUpMutatorContext)
-}
-
-// bootclasspathDepsMutator is called during the final deps phase after all APEX variants have
-// been created so can add dependencies onto specific APEX variants of modules.
-func bootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
- m := ctx.Module()
- if p, ok := m.(BootclasspathDepsMutator); ok {
- p.BootclasspathDepsMutator(ctx)
- }
-}
-
// addDependencyOntoApexVariants adds dependencies onto the appropriate apex specific variants of
// the module as specified in the ApexVariantReference list.
-func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tag blueprint.DependencyTag) {
+func addDependencyOntoApexVariants(ctx android.BottomUpMutatorContext, propertyName string, refs []ApexVariantReference, tagType bootclasspathDependencyTagType) {
for i, ref := range refs {
apex := proptools.StringDefault(ref.Apex, "platform")
@@ -62,7 +37,7 @@
}
name := proptools.String(ref.Module)
- addDependencyOntoApexModulePair(ctx, apex, name, tag)
+ addDependencyOntoApexModulePair(ctx, apex, name, tagType)
}
}
@@ -75,68 +50,154 @@
// module when both source and prebuilt modules are available.
//
// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
-func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) {
- var variations []blueprint.Variation
- if !android.IsConfiguredJarForPlatform(apex) {
- // Pick the correct apex variant.
- variations = []blueprint.Variation{
- {Mutator: "apex", Variation: apex},
- }
+func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tagType bootclasspathDependencyTagType) {
+ tag := bootclasspathDependencyTag{
+ typ: tagType,
}
-
target := ctx.Module().Target()
- variations = append(variations, target.Variations()...)
-
- addedDep := false
- if ctx.OtherModuleDependencyVariantExists(variations, name) {
- ctx.AddFarVariationDependencies(variations, tag, name)
- addedDep = true
+ if android.IsConfiguredJarForPlatform(apex) {
+ // Platform variant, add a direct dependency.
+ ctx.AddFarVariationDependencies(target.Variations(), tag, name)
+ } else {
+ // A module in an apex. Dependencies can't be added directly onto an apex variation, as that would
+ // require constructing a full ApexInfo configuration, which can't be predicted here. Add a dependency
+ // on the apex instead, and annotate the dependency tag with the desired module in the apex.
+ tag.moduleInApex = name
+ ctx.AddFarVariationDependencies(target.Variations(), tag, apex)
}
- // Add a dependency on the prebuilt module if it exists.
- prebuiltName := android.PrebuiltNameFromSource(name)
- if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) {
- ctx.AddVariationDependencies(variations, tag, prebuiltName)
- addedDep = true
- }
-
- // If no appropriate variant existing for this, so no dependency could be added, then it is an
- // error, unless missing dependencies are allowed. The simplest way to handle that is to add a
- // dependency that will not be satisfied and the default behavior will handle it.
- if !addedDep {
- // Add dependency on the unprefixed (i.e. source or renamed prebuilt) module which we know does
- // not exist. The resulting error message will contain useful information about the available
- // variants.
- reportMissingVariationDependency(ctx, variations, name)
-
- // Add dependency on the missing prefixed prebuilt variant too if a module with that name exists
- // so that information about its available variants will be reported too.
- if ctx.OtherModuleExists(prebuiltName) {
- reportMissingVariationDependency(ctx, variations, prebuiltName)
- }
- }
}
-// reportMissingVariationDependency intentionally adds a dependency on a missing variation in order
-// to generate an appropriate error message with information about the available variations.
-func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variations []blueprint.Variation, name string) {
- ctx.AddFarVariationDependencies(variations, nil, name)
+// gatherFragments collects fragments that are direct dependencies of this module, as well as
+// any fragments in apexes via the dependency on the apex. It returns a list of the fragment
+// modules and map from apex name to the fragment in that apex.
+func gatherFragments(ctx android.BaseModuleContext) ([]android.Module, map[string]android.Module) {
+ var fragments []android.Module
+
+ type fragmentInApex struct {
+ module string
+ apex string
+ }
+
+ var fragmentsInApexes []fragmentInApex
+
+ // Find any direct dependencies, as well as a list of the modules in apexes.
+ ctx.VisitDirectDeps(func(module android.Module) {
+ t := ctx.OtherModuleDependencyTag(module)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
+ if bcpTag.moduleInApex != "" {
+ fragmentsInApexes = append(fragmentsInApexes, fragmentInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
+ } else {
+ fragments = append(fragments, module)
+ }
+ }
+ })
+
+ fragmentsMap := make(map[string]android.Module)
+ for _, fragmentInApex := range fragmentsInApexes {
+ var found android.Module
+ // Find a desired module in an apex.
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if parent == ctx.Module() {
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment && ctx.OtherModuleName(child) == fragmentInApex.apex {
+ // This is the dependency from this module to the apex, recurse into it.
+ return true
+ }
+ } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
+ return false
+ } else if t == android.PrebuiltDepTag {
+ return false
+ } else if IsBootclasspathFragmentContentDepTag(t) {
+ return false
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == fragmentInApex.module {
+ // This is the desired module inside the apex.
+ if found != nil && child != found {
+ panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
+ fragmentInApex.module, fragmentInApex.apex, found, child))
+ }
+ found = child
+ }
+ return false
+ })
+ if found != nil {
+ if existing, exists := fragmentsMap[fragmentInApex.apex]; exists {
+ ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", fragmentInApex.apex, fragmentInApex.module, existing)
+ } else {
+ fragmentsMap[fragmentInApex.apex] = found
+ fragments = append(fragments, found)
+ }
+ } else if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("failed to find fragment %q in apex %q\n",
+ fragmentInApex.module, fragmentInApex.apex)
+ }
+ }
+ return fragments, fragmentsMap
}
// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
// added by addDependencyOntoApexModulePair.
-func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module {
+func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tagType bootclasspathDependencyTagType) ([]android.Module, map[android.Module]string) {
var modules []android.Module
- isActiveModulePred := func(module android.Module) bool {
- return isActiveModule(ctx, module)
+ modulesToApex := make(map[android.Module]string)
+
+ type moduleInApex struct {
+ module string
+ apex string
}
- ctx.VisitDirectDepsIf(isActiveModulePred, func(module android.Module) {
+
+ var modulesInApexes []moduleInApex
+
+ ctx.VisitDirectDeps(func(module android.Module) {
t := ctx.OtherModuleDependencyTag(module)
- if t == tag {
- modules = append(modules, module)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType {
+ if bcpTag.moduleInApex != "" {
+ modulesInApexes = append(modulesInApexes, moduleInApex{bcpTag.moduleInApex, ctx.OtherModuleName(module)})
+ } else {
+ modules = append(modules, module)
+ }
}
})
- return modules
+
+ for _, moduleInApex := range modulesInApexes {
+ var found android.Module
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if parent == ctx.Module() {
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok && bcpTag.typ == tagType && ctx.OtherModuleName(child) == moduleInApex.apex {
+ // recurse into the apex
+ return true
+ }
+ } else if tagType != fragment && android.IsFragmentInApexTag(t) {
+ return true
+ } else if android.IsDontReplaceSourceWithPrebuiltTag(t) {
+ return false
+ } else if t == android.PrebuiltDepTag {
+ return false
+ } else if IsBootclasspathFragmentContentDepTag(t) {
+ return false
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
+ if found != nil && child != found {
+ panic(fmt.Errorf("found two conflicting modules %q in apex %q: %s and %s",
+ moduleInApex.module, moduleInApex.apex, found, child))
+ }
+ found = child
+ }
+ return false
+ })
+ if found != nil {
+ modules = append(modules, found)
+ if existing, exists := modulesToApex[found]; exists && existing != moduleInApex.apex {
+ ctx.ModuleErrorf("module %s is in two apexes, %s and %s", moduleInApex.module, existing, moduleInApex.apex)
+ } else {
+ modulesToApex[found] = moduleInApex.apex
+ }
+ } else if !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("failed to find module %q in apex %q\n",
+ moduleInApex.module, moduleInApex.apex)
+ }
+ }
+ return modules, modulesToApex
}
// ApexVariantReference specifies a particular apex variant of a module.
@@ -165,7 +226,7 @@
// addDependenciesOntoFragments adds dependencies to the fragments specified in this properties
// structure.
func (p *BootclasspathFragmentsDepsProperties) addDependenciesOntoFragments(ctx android.BottomUpMutatorContext) {
- addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, bootclasspathFragmentDepTag)
+ addDependencyOntoApexVariants(ctx, "fragments", p.Fragments, fragment)
}
// bootclasspathDependencyTag defines dependencies from/to bootclasspath_fragment,
@@ -174,23 +235,38 @@
type bootclasspathDependencyTag struct {
blueprint.BaseDependencyTag
- name string
+ typ bootclasspathDependencyTagType
+
+ // moduleInApex is set to the name of the desired module when this dependency points
+ // to the apex that the modules is contained in.
+ moduleInApex string
}
+type bootclasspathDependencyTagType int
+
+const (
+ // The tag used for dependencies onto bootclasspath_fragments.
+ fragment bootclasspathDependencyTagType = iota
+ // The tag used for dependencies onto platform_bootclasspath.
+ platform
+ dexpreoptBootJar
+ artBootJar
+ platformBootJar
+ apexBootJar
+)
+
func (t bootclasspathDependencyTag) ExcludeFromVisibilityEnforcement() {
}
+func (t bootclasspathDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
+ return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
+}
+
// Dependencies that use the bootclasspathDependencyTag instances are only added after all the
// visibility checking has been done so this has no functional effect. However, it does make it
// clear that visibility is not being enforced on these tags.
var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathDependencyTag{}
-// The tag used for dependencies onto bootclasspath_fragments.
-var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"}
-
-// The tag used for dependencies onto platform_bootclasspath.
-var platformBootclasspathDepTag = bootclasspathDependencyTag{name: "platform"}
-
// BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the
// bootclasspath that are nested within the main BootclasspathAPIProperties.
type BootclasspathNestedAPIProperties struct {
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index f6d6cad..65a0579 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -89,6 +89,19 @@
// The tag used for the dependency between the bootclasspath_fragment module and its contents.
var bootclasspathFragmentContentDepTag = bootclasspathFragmentContentDependencyTag{}
+type moduleInFragmentDependencyTag struct {
+ blueprint.DependencyTag
+}
+
+func (m moduleInFragmentDependencyTag) ExcludeFromVisibilityEnforcement() {
+}
+
+// moduleInFragmentDepTag is added alongside bootclasspathFragmentContentDependencyTag,
+// but doesn't set ReplaceSourceWithPrebuilt. It is used to find modules in the fragment
+// by traversing from the apex to the fragment to the module, which prevents having to
+// construct a dependency on the apex variant of the fragment directly.
+var moduleInFragmentDepTag = moduleInFragmentDependencyTag{}
+
var _ android.ExcludeFromVisibilityEnforcementTag = bootclasspathFragmentContentDepTag
var _ android.ReplaceSourceWithPrebuilt = bootclasspathFragmentContentDepTag
var _ android.SdkMemberDependencyTag = bootclasspathFragmentContentDepTag
@@ -410,11 +423,25 @@
// Cross-cutting metadata dependencies are metadata.
return false
}
+ if tag == moduleInFragmentDepTag {
+ return true
+ }
// Dependency to the bootclasspath fragment of another apex
// e.g. concsrypt-bootclasspath-fragment --> art-bootclasspath-fragment
- if tag == bootclasspathFragmentDepTag {
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == fragment {
return false
-
+ }
+ if tag == moduleInFragmentDepTag {
+ return false
+ }
+ if tag == dexpreopt.Dex2oatDepTag {
+ return false
+ }
+ if tag == android.PrebuiltDepTag {
+ return false
+ }
+ if _, ok := tag.(hiddenAPIStubsDependencyTag); ok {
+ return false
}
panic(fmt.Errorf("boot_image module %q should not have a dependency tag %s", b, android.PrettyPrintTag(tag)))
}
@@ -458,24 +485,24 @@
}
}
- if !dexpreopt.IsDex2oatNeeded(ctx) {
- return
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
}
- // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
- // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
- dexpreopt.RegisterToolDeps(ctx)
-
// Add a dependency to `all_apex_contributions` to determine if prebuilts are active.
// If prebuilts are active, `contents` validation on the source bootclasspath fragment should be disabled.
if _, isPrebuiltModule := ctx.Module().(*PrebuiltBootclasspathFragmentModule); !isPrebuiltModule {
ctx.AddDependency(b, android.AcDepTag, "all_apex_contributions")
}
-}
-func (b *BootclasspathFragmentModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies on all the fragments.
b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx)
+
+ for _, name := range b.properties.Contents.GetOrDefault(ctx, nil) {
+ ctx.AddDependency(ctx.Module(), moduleInFragmentDepTag, name)
+ }
}
func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -498,7 +525,7 @@
}
})
- fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
+ fragments, _ := gatherFragments(ctx)
// Perform hidden API processing.
hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
@@ -606,7 +633,7 @@
if android.IsModulePrebuilt(ctx.Module()) {
// prebuilt bcpf. the validation of this will be done at the top-level apex
providerClasspathFragmentValidationInfoProvider(ctx, unknown)
- } else if !disableSourceApexVariant(ctx) {
+ } else if !disableSourceApexVariant(ctx) && android.IsModulePreferred(ctx.Module()) {
// source bcpf, and prebuilt apex are not selected.
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
}
@@ -1142,6 +1169,13 @@
android.InitPrebuiltModule(m, &[]string{"placeholder"})
android.InitApexModule(m)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(m)
+
+ m.SetDefaultableHook(func(mctx android.DefaultableHookContext) {
+ if mctx.Config().AlwaysUsePrebuiltSdks() {
+ m.prebuilt.ForcePrefer()
+ }
+ })
return m
}
diff --git a/java/classpath_element.go b/java/classpath_element.go
index abbcae7..4af2770 100644
--- a/java/classpath_element.go
+++ b/java/classpath_element.go
@@ -108,33 +108,18 @@
//
// e.g. Given the following input:
//
-// libraries: com.android.art:core-oj, com.android.art:core-libart, framework, ext
-// fragments: com.android.art:art-bootclasspath-fragment
+// libraries: core-oj, core-libart, framework, ext
+// fragments: art-bootclasspath-fragment
+// libraryToApex: core-oj: com.android.art, core-libart: com.android.art
+// apexNameToFragment: com.android.art: art-bootclasspath-fragment
//
// Then this will return:
//
// ClasspathFragmentElement(art-bootclasspath-fragment, [core-oj, core-libart]),
// ClasspathLibraryElement(framework),
// ClasspathLibraryElement(ext),
-func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module) ClasspathElements {
- // Create a map from apex name to the fragment module. This makes it easy to find the fragment
- // associated with a particular apex.
- apexToFragment := map[string]android.Module{}
- for _, fragment := range fragments {
- apexInfo, ok := android.OtherModuleProvider(ctx, fragment, android.ApexInfoProvider)
- if !ok {
- ctx.ModuleErrorf("fragment %s is not part of an apex", fragment)
- continue
- }
-
- for _, apex := range apexInfo.InApexVariants {
- if existing, ok := apexToFragment[apex]; ok {
- ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", apex, fragment, existing)
- continue
- }
- apexToFragment[apex] = fragment
- }
- }
+func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module,
+ libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) ClasspathElements {
fragmentToElement := map[android.Module]*ClasspathFragmentElement{}
elements := []ClasspathElement{}
@@ -144,31 +129,28 @@
// Iterate over the libraries to construct the ClasspathElements list.
for _, library := range libraries {
var element ClasspathElement
- if apexInfo, ok := android.OtherModuleProvider(ctx, library, android.ApexInfoProvider); ok {
-
+ if libraryApex, ok := libraryToApex[library]; ok {
var fragment android.Module
// Make sure that the library is in only one fragment of the classpath.
- for _, apex := range apexInfo.InApexVariants {
- if f, ok := apexToFragment[apex]; ok {
- if fragment == nil {
- // This is the first fragment so just save it away.
- fragment = f
- } else if f != fragment {
- // This apex variant of the library is in a different fragment.
- ctx.ModuleErrorf("library %s is in two separate fragments, %s and %s", library, fragment, f)
- // Skip over this library entirely as otherwise the resulting classpath elements would
- // be invalid.
- continue skipLibrary
- }
- } else {
- // There is no fragment associated with the library's apex.
+ if f, ok := apexNameToFragment[libraryApex]; ok {
+ if fragment == nil {
+ // This is the first fragment so just save it away.
+ fragment = f
+ } else if f != fragment {
+ // This apex variant of the library is in a different fragment.
+ ctx.ModuleErrorf("library %s is in two separate fragments, %s and %s", library, fragment, f)
+ // Skip over this library entirely as otherwise the resulting classpath elements would
+ // be invalid.
+ continue skipLibrary
}
+ } else {
+ // There is no fragment associated with the library's apex.
}
if fragment == nil {
ctx.ModuleErrorf("library %s is from apexes %s which have no corresponding fragment in %s",
- library, apexInfo.InApexVariants, fragments)
+ library, []string{libraryApex}, fragments)
// Skip over this library entirely as otherwise the resulting classpath elements would
// be invalid.
continue skipLibrary
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 15e40ba..5755dec 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -177,10 +177,7 @@
// Find the apex variant for this module
apexVariants := []string{}
if apexInfo.BaseApexName != "" {
- // This is a transitive dependency of an override_apex
apexVariants = append(apexVariants, apexInfo.BaseApexName)
- } else {
- apexVariants = append(apexVariants, apexInfo.InApexVariants...)
}
if apexInfo.ApexAvailableName != "" {
apexVariants = append(apexVariants, apexInfo.ApexAvailableName)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 093cc87..27027f0 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"path/filepath"
"strings"
@@ -225,7 +226,6 @@
}
var (
- dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
apexContributionsMetadataDepTag = dependencyTag{name: "all_apex_contributions"}
)
@@ -467,9 +467,6 @@
func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
ctx.RegisterModuleType("art_boot_images", artBootImagesFactory)
- ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("dex_bootjars_deps", DexpreoptBootJarsMutator)
- })
}
func SkipDexpreoptBootJars(ctx android.PathContext) bool {
@@ -505,12 +502,6 @@
func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) {
// Create a dependency on all_apex_contributions to determine the selected mainline module
ctx.AddDependency(ctx.Module(), apexContributionsMetadataDepTag, "all_apex_contributions")
-}
-
-func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
- if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
- return
- }
if dexpreopt.IsDex2oatNeeded(ctx) {
// Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
@@ -524,7 +515,7 @@
continue
}
// For accessing the boot jars.
- addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJar)
// Create a dependency on the apex selected using RELEASE_APEX_CONTRIBUTIONS_*
// TODO: b/308174306 - Remove the direct depedendency edge to the java_library (source/prebuilt) once all mainline modules
// have been flagged using RELEASE_APEX_CONTRIBUTIONS_*
@@ -537,11 +528,11 @@
if ctx.OtherModuleExists("platform-bootclasspath") {
// For accessing all bootclasspath fragments.
- addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platformBootclasspathDepTag)
+ addDependencyOntoApexModulePair(ctx, "platform", "platform-bootclasspath", platform)
} else if ctx.OtherModuleExists("art-bootclasspath-fragment") {
// For accessing the ART bootclasspath fragment on a thin manifest (e.g., master-art) where
// platform-bootclasspath doesn't exist.
- addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", bootclasspathFragmentDepTag)
+ addDependencyOntoApexModulePair(ctx, "com.android.art", "art-bootclasspath-fragment", fragment)
}
}
@@ -559,17 +550,11 @@
// We need to add a dep on only the apex listed in `contents` of the selected apex_contributions module
// This is not available in a structured format in `apex_contributions`, so this hack adds a dep on all `contents`
// (some modules like art.module.public.api do not have an apex variation since it is a pure stub module that does not get installed)
- apexVariationOfSelected := append(ctx.Target().Variations(), blueprint.Variation{Mutator: "apex", Variation: apex})
- if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, selected) {
- ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected)
- } else if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, android.RemoveOptionalPrebuiltPrefix(selected)) {
- // The prebuilt might have been renamed by prebuilt_rename mutator if the source module does not exist.
- // Remove the prebuilt_ prefix.
- ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, android.RemoveOptionalPrebuiltPrefix(selected))
- } else {
- // Couldn't find a dependency, do it again to report an error.
- ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected)
+ tag := bootclasspathDependencyTag{
+ typ: dexpreoptBootJar,
}
+
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, android.RemoveOptionalPrebuiltPrefix(selected))
}
}
}
@@ -577,23 +562,55 @@
func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
fragments := make(map[string]android.Module)
+
+ type moduleInApexPair struct {
+ module string
+ apex string
+ }
+
+ var modulesInApexes []moduleInApexPair
+
+ // Find the list of modules in apexes.
ctx.WalkDeps(func(child, parent android.Module) bool {
if !isActiveModule(ctx, child) {
return false
}
tag := ctx.OtherModuleDependencyTag(child)
- if tag == platformBootclasspathDepTag {
- return true
- }
- if tag == bootclasspathFragmentDepTag {
- apexInfo, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
- for _, apex := range apexInfo.InApexVariants {
- fragments[apex] = child
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok {
+ if bcpTag.typ == platform {
+ return true
}
- return false
+ if bcpTag.typ == fragment {
+ if bcpTag.moduleInApex == "" {
+ panic(fmt.Errorf("expected fragment to be in apex"))
+ }
+ modulesInApexes = append(modulesInApexes, moduleInApexPair{bcpTag.moduleInApex, ctx.OtherModuleName(child)})
+ return true
+ }
}
return false
})
+
+ for _, moduleInApex := range modulesInApexes {
+ // Find a desired module in an apex.
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ t := ctx.OtherModuleDependencyTag(child)
+ if bcpTag, ok := t.(bootclasspathDependencyTag); ok {
+ if bcpTag.typ == platform {
+ return true
+ }
+ if bcpTag.typ == fragment && ctx.OtherModuleName(child) == moduleInApex.apex {
+ // This is the dependency from this module to the apex, recurse into it.
+ return true
+ }
+ } else if android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) == moduleInApex.module {
+ // This is the desired module inside the apex.
+ fragments[android.RemoveOptionalPrebuiltPrefix(moduleInApex.apex)] = child
+ }
+ return false
+ })
+ }
+
return fragments
}).(map[string]android.Module)
}
@@ -717,7 +734,8 @@
modules := make([]apexJarModulePair, 0, imageConfig.modules.Len())
for i := 0; i < imageConfig.modules.Len(); i++ {
found := false
- for _, module := range gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJarDepTag) {
+ dexpreoptBootJarModules, _ := gatherApexModulePairDepsWithTag(ctx, dexpreoptBootJar)
+ for _, module := range dexpreoptBootJarModules {
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
if name == imageConfig.modules.Jar(i) {
modules = append(modules, apexJarModulePair{
@@ -800,11 +818,16 @@
"APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
pair.jarModule.Name(),
pair.apex)
+ return nil
}
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider)
jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
if err != nil {
- ctx.ModuleErrorf("%s", err)
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{pair.jarModule.String()})
+ } else {
+ ctx.ModuleErrorf("%s", err)
+ }
}
return jar
}
@@ -963,9 +986,16 @@
func getApexNameToApexExportsInfoMap(ctx android.ModuleContext) apexNameToApexExportsInfoMap {
apexNameToApexExportsInfoMap := apexNameToApexExportsInfoMap{}
- ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) {
- if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
- apexNameToApexExportsInfoMap[info.ApexName] = info
+
+ ctx.VisitDirectDeps(func(am android.Module) {
+ tag := ctx.OtherModuleDependencyTag(am)
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
+ if bcpTag.moduleInApex == "" {
+ info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider)
+ if exists {
+ apexNameToApexExportsInfoMap[info.ApexName] = info
+ }
+ }
}
})
return apexNameToApexExportsInfoMap
@@ -1448,24 +1478,33 @@
func (dbj *artBootImages) DepsMutator(ctx android.BottomUpMutatorContext) {
// Create a dependency on `dex_bootjars` to access the intermediate locations of host art boot image.
- ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), dexpreoptBootJarDepTag, "dex_bootjars")
+ tag := bootclasspathDependencyTag{
+ typ: dexpreoptBootJar,
+ }
+ ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), tag, "dex_bootjars")
}
func (d *artBootImages) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(m android.Module) {
- hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider)
- if !ok {
- ctx.ModuleErrorf("Could not find information about the host variant of ART boot image")
- }
- installs := d.installFile(ctx, hostInstallsInfo.installs)
- if len(installs) > 0 {
- d.outputFile = android.OptionalPathForPath(installs[0])
- // Create a phony target that can ART run-tests can depend on.
- ctx.Phony(d.Name(), installs...)
- } else {
- // this might be true e.g. when building with `WITH_DEXPREOPT=false`
- // create an empty file so that the `art_boot_images` is known to the packaging system.
- d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images"))
+ ctx.VisitDirectDeps(func(m android.Module) {
+ tag := ctx.OtherModuleDependencyTag(m)
+ if bcpTag, ok := tag.(bootclasspathDependencyTag); ok && bcpTag.typ == dexpreoptBootJar {
+ if bcpTag.moduleInApex != "" {
+ panic("unhandled moduleInApex")
+ }
+ hostInstallsInfo, ok := android.OtherModuleProvider(ctx, m, artBootImageHostInfoProvider)
+ if !ok {
+ ctx.ModuleErrorf("Could not find information about the host variant of ART boot image")
+ }
+ installs := d.installFile(ctx, hostInstallsInfo.installs)
+ if len(installs) > 0 {
+ d.outputFile = android.OptionalPathForPath(installs[0])
+ // Create a phony target that can ART run-tests can depend on.
+ ctx.Phony(d.Name(), installs...)
+ } else {
+ // this might be true e.g. when building with `WITH_DEXPREOPT=false`
+ // create an empty file so that the `art_boot_images` is known to the packaging system.
+ d.outputFile = android.OptionalPathForPath(android.PathForModuleOut(ctx, "undefined_art_boot_images"))
+ }
}
})
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 7d21b7a..2c86942 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -171,11 +171,11 @@
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
if android.IsConfiguredJarForPlatform(requiredApex) {
- if len(apexInfo.InApexVariants) != 0 {
+ if apexInfo.ApexVariationName != "" {
// A platform variant is required but this is for an apex so ignore it.
return false
}
- } else if !apexInfo.InApexVariant(requiredApex) {
+ } else if apexInfo.BaseApexName != requiredApex {
// An apex variant for a specific apex is required but this is the wrong apex.
return false
}
diff --git a/java/java.go b/java/java.go
index c1ce880..91b7cf2 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1194,7 +1194,7 @@
for _, paths := range ctx.GetOutputFiles().TaggedOutputFiles {
builtFiles = append(builtFiles, paths.Strings()...)
}
- complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.BUILT_FILES, android.FirstUniqueStrings(builtFiles))
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.BUILT_FILES, android.SortedUniqueStrings(builtFiles))
// Static deps
staticDepNames := make([]string, 0)
@@ -1207,8 +1207,8 @@
staticDepFiles = append(staticDepFiles, dep.ResourceJars...)
}
})
- complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.FirstUniqueStrings(staticDepNames))
- complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.FirstUniqueStrings(staticDepFiles.Strings()))
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEPS, android.SortedUniqueStrings(staticDepNames))
+ complianceMetadataInfo.SetListValue(android.ComplianceMetadataProp.STATIC_DEP_FILES, android.SortedUniqueStrings(staticDepFiles.Strings()))
}
func (j *Library) getJarInstallDir(ctx android.ModuleContext) android.InstallPath {
@@ -3546,7 +3546,6 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
- android.ApexModuleBase
}
// java_defaults provides a set of properties that can be inherited by other java or android modules.
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 86062d4..155afc6 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -15,6 +15,9 @@
package java
import (
+ "maps"
+ "slices"
+
"github.com/google/blueprint"
"android/soong/android"
@@ -31,12 +34,6 @@
// The tags used for the dependencies between the platform bootclasspath and any configured boot
// jars.
-var (
- platformBootclasspathArtBootJarDepTag = bootclasspathDependencyTag{name: "art-boot-jar"}
- platformBootclasspathBootJarDepTag = bootclasspathDependencyTag{name: "platform-boot-jar"}
- platformBootclasspathApexBootJarDepTag = bootclasspathDependencyTag{name: "apex-boot-jar"}
-)
-
type platformBootclasspathImplLibDepTagType struct {
blueprint.BaseDependencyTag
}
@@ -59,6 +56,12 @@
// The apex:module pairs obtained from the fragments.
fragments []android.Module
+ // The map of apex to the fragments they contain.
+ apexNameToFragment map[string]android.Module
+
+ // The map of library modules in the bootclasspath to the fragments that contain them.
+ libraryToApex map[android.Module]string
+
// Path to the monolithic hiddenapi-flags.csv file.
hiddenAPIFlagsCSV android.OutputPath
@@ -100,26 +103,12 @@
b.hiddenAPIDepsMutator(ctx)
- if !dexpreopt.IsDex2oatNeeded(ctx) {
- return
+ if dexpreopt.IsDex2oatNeeded(ctx) {
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
}
- // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
- // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
- dexpreopt.RegisterToolDeps(ctx)
-}
-
-func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Config().DisableHiddenApiChecks() {
- return
- }
-
- // Add dependencies onto the stub lib modules.
- apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
- hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
-}
-
-func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies on all the ART jars.
global := dexpreopt.GetGlobalConfig(ctx)
addDependenciesOntoSelectedBootImageApexes(ctx, "com.android.art")
@@ -127,13 +116,13 @@
var bootImageModuleNames []string
// TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
- addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, artBootJar)
bootImageModuleNames = append(bootImageModuleNames, global.ArtApexJars.CopyOfJars()...)
// Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
// APEXes.
platformJars := b.platformJars(ctx)
- addDependenciesOntoBootImageModules(ctx, platformJars, platformBootclasspathBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, platformJars, platformBootJar)
bootImageModuleNames = append(bootImageModuleNames, platformJars.CopyOfJars()...)
// Add dependencies on all the updatable jars, except the ART jars.
@@ -144,7 +133,7 @@
}
addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
// TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
- addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
+ addDependenciesOntoBootImageModules(ctx, apexJars, apexBootJar)
bootImageModuleNames = append(bootImageModuleNames, apexJars.CopyOfJars()...)
// Add dependencies on all the fragments.
@@ -158,27 +147,37 @@
}
}
-func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tag bootclasspathDependencyTag) {
+func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
+ if ctx.Config().DisableHiddenApiChecks() {
+ return
+ }
+
+ // Add dependencies onto the stub lib modules.
+ apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
+ hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
+}
+
+func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tagType bootclasspathDependencyTagType) {
for i := 0; i < modules.Len(); i++ {
apex := modules.Apex(i)
name := modules.Jar(i)
- addDependencyOntoApexModulePair(ctx, apex, name, tag)
+ addDependencyOntoApexModulePair(ctx, apex, name, tagType)
}
}
func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Gather all the dependencies from the art, platform, and apex boot jars.
- artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag)
- platformModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathBootJarDepTag)
- apexModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathApexBootJarDepTag)
+ artModules, artModulesToApex := gatherApexModulePairDepsWithTag(ctx, artBootJar)
+ platformModules, platformModulesToApex := gatherApexModulePairDepsWithTag(ctx, platformBootJar)
+ apexModules, apexModulesToApex := gatherApexModulePairDepsWithTag(ctx, apexBootJar)
// Concatenate them all, in order as they would appear on the bootclasspath.
- var allModules []android.Module
- allModules = append(allModules, artModules...)
- allModules = append(allModules, platformModules...)
- allModules = append(allModules, apexModules...)
+ allModules := slices.Concat(artModules, platformModules, apexModules)
b.configuredModules = allModules
+ b.libraryToApex = maps.Clone(artModulesToApex)
+ maps.Copy(b.libraryToApex, platformModulesToApex)
+ maps.Copy(b.libraryToApex, apexModulesToApex)
// Do not add implLibModule to allModules as the impl lib is only used to collect the
// transitive source files
@@ -199,7 +198,7 @@
TransformResourcesToJar(ctx, srcjar, jarArgs, transitiveSrcFiles)
// Gather all the fragments dependencies.
- b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
+ b.fragments, b.apexNameToFragment = gatherFragments(ctx)
// Check the configuration of the boot modules.
// ART modules are checked by the art-bootclasspath-fragment.
@@ -208,7 +207,7 @@
b.generateClasspathProtoBuildActions(ctx)
- bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
+ bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments, b.libraryToApex, b.apexNameToFragment)
buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
ctx.SetOutputFiles(android.Paths{b.hiddenAPIFlagsCSV}, "hiddenapi-flags.csv")
@@ -259,7 +258,7 @@
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// error: this jar is part of an updatable apex
- ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.InApexVariants)
+ ctx.ModuleErrorf("module %q from updatable apex %q is not allowed in the platform bootclasspath", ctx.OtherModuleName(m), apexInfo.BaseApexName)
} else {
// ok: this jar is part of the platform or a non-updatable apex
}
@@ -283,7 +282,11 @@
// modules is complete.
if !ctx.Config().AlwaysUsePrebuiltSdks() {
// error: this jar is part of the platform
- ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name)
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{"module_" + name + "_from_platform_is_not_allowed_in_the_apex_boot_jars_list"})
+ } else {
+ ctx.ModuleErrorf("module %q from platform is not allowed in the apex boot jars list", name)
+ }
}
} else {
// TODO(b/177892522): Treat this as an error.
@@ -295,7 +298,8 @@
}
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
-func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) bootDexJarByModule {
+func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module,
+ fragments []android.Module, libraryToApex map[android.Module]string, apexNameToFragment map[string]android.Module) bootDexJarByModule {
createEmptyHiddenApiFiles := func() {
paths := android.OutputPaths{b.hiddenAPIFlagsCSV, b.hiddenAPIIndexCSV, b.hiddenAPIMetadataCSV}
for _, path := range paths {
@@ -322,7 +326,7 @@
}
// Construct a list of ClasspathElement objects from the modules and fragments.
- classpathElements := CreateClasspathElements(ctx, modules, fragments)
+ classpathElements := CreateClasspathElements(ctx, modules, fragments, libraryToApex, apexNameToFragment)
monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, classpathElements)
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 0aed4b8..0d872f0 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -993,8 +993,6 @@
CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{
// Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib.
`prebuilt_sdklib`,
- `prebuilt_sdklib`,
- `prebuilt_sdklib`,
`prebuilt_sdklib.stubs`,
`prebuilt_sdklib.stubs.source`,
})
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index f3074ed..6f746b4 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -119,6 +119,7 @@
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
}
+
func (m *SystemServerClasspathModule) UniqueApexVariations() bool {
return true
}
diff --git a/java/testing.go b/java/testing.go
index 0ea4e64..b3e5526 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -18,7 +18,6 @@
"fmt"
"reflect"
"regexp"
- "sort"
"strings"
"testing"
@@ -378,7 +377,6 @@
RegisterAppBuildComponents(ctx)
RegisterAppImportBuildComponents(ctx)
RegisterAppSetBuildComponents(ctx)
- registerBootclasspathBuildComponents(ctx)
registerBootclasspathFragmentBuildComponents(ctx)
RegisterDexpreoptBootJarsComponents(ctx)
RegisterDocsBuildComponents(ctx)
@@ -612,14 +610,13 @@
ctx.VisitDirectDeps(module, func(m blueprint.Module) {
deps = append(deps, m.Name())
})
- sort.Strings(deps)
-
- return deps
+ return android.SortedUniqueStrings(deps)
}
// CheckModuleDependencies checks if the expected dependencies of the module are
// identical to the actual dependencies.
func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+ t.Helper()
deps := getModuleDependencies(t, ctx, name, variant)
if actual := deps; !reflect.DeepEqual(expected, actual) {
@@ -654,7 +651,7 @@
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
- pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules)
+ pairs := apexNamePairsFromModules(result.TestContext, platformBootclasspath.configuredModules, platformBootclasspath.libraryToApex)
android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs)
}
@@ -669,23 +666,54 @@
android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir)
}
-// ApexNamePairsFromModules returns the apex:module pair for the supplied modules.
-func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string {
+// CheckPlatformBootclasspathDependencies checks the dependencies of the selected module against the expected list.
+//
+// The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the
+// name of the apex, or platform is it is not part of an apex and <module> is the module name.
+func CheckPlatformBootclasspathDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+ t.Helper()
+ platformBootclasspath := ctx.ModuleForTests(name, variant).Module().(*platformBootclasspathModule)
+ modules := []android.Module{}
+ ctx.VisitDirectDeps(platformBootclasspath, func(m blueprint.Module) {
+ modules = append(modules, m.(android.Module))
+ })
+
+ pairs := apexNamePairsFromModules(ctx, modules, platformBootclasspath.libraryToApex)
+ android.AssertDeepEquals(t, "module dependencies", expected, pairs)
+}
+
+// apexNamePairsFromModules returns the apex:module pair for the supplied modules.
+func apexNamePairsFromModules(ctx *android.TestContext, modules []android.Module, modulesToApex map[android.Module]string) []string {
pairs := []string{}
for _, module := range modules {
- pairs = append(pairs, apexNamePairFromModule(ctx, module))
+ pairs = append(pairs, apexNamePairFromModule(ctx, module, modulesToApex))
}
return pairs
}
-func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
+// ApexFragmentPairsFromModules returns the apex:fragment pair for the supplied fragments.
+func ApexFragmentPairsFromModules(ctx *android.TestContext, fragments []android.Module, apexNameToFragment map[string]android.Module) []string {
+ pairs := []string{}
+ for _, fragment := range fragments {
+ found := false
+ for apex, apexFragment := range apexNameToFragment {
+ if apexFragment == fragment {
+ pairs = append(pairs, apex+":"+ctx.ModuleName(fragment))
+ found = true
+ }
+ }
+ if !found {
+ pairs = append(pairs, "platform:"+ctx.ModuleName(fragment))
+ }
+ }
+ return pairs
+}
+
+func apexNamePairFromModule(ctx *android.TestContext, module android.Module, modulesToApex map[android.Module]string) string {
name := module.Name()
- var apex string
- apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
- if apexInfo.IsForPlatform() {
+ apex := modulesToApex[module]
+ if apex == "" {
apex = "platform"
- } else {
- apex = apexInfo.InApexVariants[0]
}
return fmt.Sprintf("%s:%s", apex, name)
@@ -696,7 +724,7 @@
func CheckPlatformBootclasspathFragments(t *testing.T, result *android.TestResult, name string, expected []string) {
t.Helper()
platformBootclasspath := result.Module(name, "android_common").(*platformBootclasspathModule)
- pairs := ApexNamePairsFromModules(result.TestContext, platformBootclasspath.fragments)
+ pairs := ApexFragmentPairsFromModules(result.TestContext, platformBootclasspath.fragments, platformBootclasspath.apexNameToFragment)
android.AssertDeepEquals(t, fmt.Sprintf("%s fragments", "platform-bootclasspath"), expected, pairs)
}
diff --git a/phony/phony.go b/phony/phony.go
index 807b95b..4f61c45 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -38,9 +38,11 @@
type phony struct {
android.ModuleBase
+
requiredModuleNames []string
hostRequiredModuleNames []string
targetRequiredModuleNames []string
+ outputDeps android.Paths
}
func PhonyFactory() android.Module {
@@ -54,6 +56,14 @@
p.requiredModuleNames = ctx.RequiredModuleNames(ctx)
p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
+
+ ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ if o, ok := android.OtherModuleProvider(ctx, dep, android.OutputFilesProvider); ok {
+ p.outputDeps = append(p.outputDeps, o.DefaultOutputFiles...)
+ }
+ })
+
+ ctx.Phony(p.Name(), p.outputDeps...)
}
func (p *phony) AndroidMk() android.AndroidMkData {
@@ -77,6 +87,10 @@
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=",
strings.Join(p.targetRequiredModuleNames, " "))
}
+ if len(p.outputDeps) > 0 {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=",
+ strings.Join(p.outputDeps.Strings(), " "))
+ }
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
for _, extra := range data.Extra {
extra(w, nil)
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 8accd03..2f84168 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -398,7 +398,7 @@
//
// This is necessary to avoid a circular dependency between the source variant and the
// dependent cc module.
- deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, String(b.Properties.Static_inline_library))
}
deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs.GetOrDefault(ctx, nil)...)
diff --git a/rust/library.go b/rust/library.go
index 94f5730..24ae8b0 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -771,7 +771,7 @@
cc.AddStubDependencyProviders(ctx)
// Set our flagexporter provider to export relevant Rust flags
- library.flagExporter.setProvider(ctx)
+ library.flagExporter.setRustProvider(ctx)
return ret
}
@@ -945,6 +945,9 @@
}
func (libraryTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
@@ -1012,6 +1015,12 @@
},
sourceDepTag, ctx.ModuleName())
}
+
+ if prebuilt, ok := m.compiler.(*prebuiltLibraryDecorator); ok {
+ if Bool(prebuilt.Properties.Force_use_prebuilt) && len(prebuilt.prebuiltSrcs()) > 0 {
+ m.Prebuilt().SetUsePrebuilt(true)
+ }
+ }
}
type libstdTransitionMutator struct{}
@@ -1029,6 +1038,9 @@
}
func (libstdTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if ctx.DepTag() == android.PrebuiltDepTag {
+ return sourceVariation
+ }
return ""
}
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index e35e510..7c92dda 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -30,6 +30,8 @@
Srcs []string `android:"path,arch_variant"`
// directories containing associated rlib dependencies
Link_dirs []string `android:"path,arch_variant"`
+
+ Force_use_prebuilt *bool `android:"arch_variant"`
}
type prebuiltLibraryDecorator struct {
@@ -158,7 +160,7 @@
func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
- prebuilt.flagExporter.setProvider(ctx)
+ prebuilt.flagExporter.setRustProvider(ctx)
srcPath := prebuiltPath(ctx, prebuilt)
prebuilt.baseCompiler.unstrippedOutputFile = srcPath
return buildOutput{outputFile: srcPath}
@@ -211,7 +213,7 @@
func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
- prebuilt.flagExporter.setProvider(ctx)
+ prebuilt.flagExporter.setRustProvider(ctx)
srcPath := prebuiltPath(ctx, prebuilt)
prebuilt.baseCompiler.unstrippedOutputFile = srcPath
return buildOutput{outputFile: srcPath}
diff --git a/rust/rust.go b/rust/rust.go
index 90e5277..ad68d60 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -573,8 +573,8 @@
flagExporter.wholeStaticLibObjects = android.FirstUniqueStrings(append(flagExporter.wholeStaticLibObjects, flags...))
}
-func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
- android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
+func (flagExporter *flagExporter) setRustProvider(ctx ModuleContext) {
+ android.SetProvider(ctx, RustFlagExporterInfoProvider, RustFlagExporterInfo{
LinkDirs: flagExporter.linkDirs,
RustLibObjects: flagExporter.rustLibPaths,
StaticLibObjects: flagExporter.staticLibObjects,
@@ -589,7 +589,7 @@
return &flagExporter{}
}
-type FlagExporterInfo struct {
+type RustFlagExporterInfo struct {
Flags []string
LinkDirs []string
RustLibObjects []string
@@ -598,7 +598,7 @@
SharedLibPaths []string
}
-var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
+var RustFlagExporterInfoProvider = blueprint.NewProvider[RustFlagExporterInfo]()
func (mod *Module) isCoverageVariant() bool {
return mod.coverage.Properties.IsCoverageVariant
@@ -1574,7 +1574,7 @@
directSrcProvidersDeps = append(directSrcProvidersDeps, &dep)
}
- exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, RustFlagExporterInfoProvider)
//Append the dependencies exported objects, except for proc-macros which target a different arch/OS
if depTag != procMacroDepTag {
@@ -2124,6 +2124,9 @@
}
func (mod *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ if mod.Host() {
+ return false
+ }
// TODO(b/362509506): remove once all apex_exclude uses are switched to stubs.
if mod.ApexExclude() {
return false
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 858c4db..4390f55 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -432,7 +432,7 @@
}
}
-func TestRustRlibs(t *testing.T) {
+func TestRustFFIRlibs(t *testing.T) {
ctx := testRust(t, `
rust_ffi_static {
name: "libbar",
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index ef0f44a..b600443 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -23,9 +23,18 @@
# TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the riscv64
# dependencies exist (currently blocked by http://b/273792258).
# TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports riscv64 (http://b/262192655).
+#
+# LTO is disabled because the NDK compiler is not necessarily in-sync with the
+# compiler used to build the platform sysroot, and the sysroot includes static
+# libraries which would be incompatible with mismatched compilers when built
+# with LTO. Disabling LTO globally for the NDK sysroot is okay because the only
+# compiled code in the sysroot that will end up in apps is those static
+# libraries.
+# https://github.com/android/ndk/issues/1591
TARGET_RELEASE=trunk_staging \
ALLOW_MISSING_DEPENDENCIES=true \
BUILD_BROKEN_DISABLE_BAZEL=1 \
+DISABLE_LTO=true \
TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
if [ -n "${DIST_DIR}" ]; then
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index ad315bf..ca63020 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -66,6 +66,7 @@
exported_bootclasspath_fragments: [
"%s",
],
+ prefer: false,
}
`, apex, apexFile, fragment)),
android.FixtureAddFile(filepath.Join(dir, apexFile), nil),
@@ -226,8 +227,8 @@
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
- "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_com.android.art/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_prebuilt_com.android.art/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art/android_common_prebuilt_com.android.art/deapexer/javalib/core2.jar",
"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,
@@ -744,6 +745,7 @@
android.GroupFixturePreparers(
prepareForSdkTestWithApex,
prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
android.FixtureMergeMockFs(android.MockFS{
"java/mybootlib.jar": nil,
"hiddenapi/annotation-flags.csv": nil,
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 5bac67d..bf4ac13 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -1405,8 +1405,6 @@
.intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
`),
- // TODO(b/183315522): Remove this and fix the issue.
- snapshotTestErrorHandler(checkSnapshotPreferredWithSource, android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\Qunrecognized property "arch.arm.shared.export_include_dirs"\E`)),
)
}
diff --git a/sdk/testing.go b/sdk/testing.go
index f5518c4..cd7bbf5 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -281,7 +281,7 @@
// Run the snapshot with the snapshot preparer and the extra preparer, which must come after as
// it may need to modify parts of the MockFS populated by the snapshot preparer.
- result := android.GroupFixturePreparers(snapshotPreparer, extraPreparer, customizedPreparers).
+ result := android.GroupFixturePreparers(snapshotPreparer, customizedPreparers, extraPreparer).
ExtendWithErrorHandler(customization.errorHandler).
RunTest(t)
@@ -314,6 +314,11 @@
snapshotBpFile := filepath.Join(snapshotSubDir, "Android.bp")
unpreferred := string(fs[snapshotBpFile])
fs[snapshotBpFile] = []byte(strings.ReplaceAll(unpreferred, "prefer: false,", "prefer: true,"))
+
+ prebuiltApexBpFile := "prebuilts/apex/Android.bp"
+ if prebuiltApexBp, ok := fs[prebuiltApexBpFile]; ok {
+ fs[prebuiltApexBpFile] = []byte(strings.ReplaceAll(string(prebuiltApexBp), "prefer: false,", "prefer: true,"))
+ }
})
runSnapshotTestWithCheckers(t, checkSnapshotPreferredWithSource, preferPrebuilts)
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 4ea8a0b..89c69bd 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -197,10 +197,10 @@
return autogenPath
}
if len(options.OptionsForAutogenerated) > 0 {
- ctx.ModuleErrorf("Extra tradefed configurations (%v) were provided for an autogenerated xml file, but the autogenerated xml file was not used.", options.OptionsForAutogenerated)
+ ctx.ModuleErrorf("You likely need to delete your soong modules local AndroidTest.xml file. Extra tradefed configurations (%v) were provided for an autogenerated xml file, but the autogenerated xml file was not used.", options.OptionsForAutogenerated)
}
if len(options.TestRunnerOptions) > 0 {
- ctx.ModuleErrorf("Extra test runner options (%v) were provided for an autogenerated xml file, but the autogenerated xml file was not used.", options.TestRunnerOptions)
+ ctx.ModuleErrorf("You likely need to delete your soong modules local AndroidTest.xml file. Extra test runner options (%v) were provided for an autogenerated xml file, but the autogenerated xml file was not used.", options.TestRunnerOptions)
}
return path
}
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index 37537ab..831f6d4 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -164,6 +164,7 @@
directories := flags.Bool("d", false, "include directories in zip")
compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
+ sortEntries := flags.Bool("sort_entries", false, "sort the zip entries")
writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist")
symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them")
@@ -228,6 +229,7 @@
FileArgs: fileArgsBuilder.FileArgs(),
OutputFilePath: *out,
EmulateJar: *emulateJar,
+ SortEntries: *sortEntries,
SrcJar: *srcJar,
AddDirectoryEntriesToZip: *directories,
CompressionLevel: *compLevel,
diff --git a/zip/zip.go b/zip/zip.go
index f91a5f2..e4e9585 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -272,6 +272,7 @@
FileArgs []FileArg
OutputFilePath string
EmulateJar bool
+ SortEntries bool
SrcJar bool
AddDirectoryEntriesToZip bool
CompressionLevel int
@@ -394,7 +395,7 @@
}
}
- return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.SrcJar, args.NumParallelJobs)
+ return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.SortEntries, args.SrcJar, args.NumParallelJobs)
}
// Zip creates an output zip archive from given sources.
@@ -481,7 +482,8 @@
})
}
-func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string, emulateJar, srcJar bool,
+func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string,
+ emulateJar, sortEntries, srcJar bool,
parallelJobs int) error {
z.errors = make(chan error)
@@ -511,12 +513,20 @@
return errors.New("must specify --jar when specifying a manifest via -m")
}
+ if emulateJar && sortEntries {
+ return errors.New("Cannot specify both --jar and --sort_entries (--jar implies sorting with a different algorithm)")
+ }
if emulateJar {
// manifest may be empty, in which case addManifest will fill in a default
pathMappings = append(pathMappings, pathMapping{jar.ManifestFile, manifest, zip.Deflate})
jarSort(pathMappings)
}
+ if sortEntries {
+ sort.SliceStable(pathMappings, func(i int, j int) bool {
+ return pathMappings[i].dest < pathMappings[j].dest
+ })
+ }
go func() {
var err error