Merge "Add more comments about soong config variables" into main
diff --git a/android/apex.go b/android/apex.go
index c0acada..dc0aeed 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -90,7 +90,13 @@
TestApexes []string
}
-var ApexInfoProvider = blueprint.NewMutatorProvider[ApexInfo]("apex")
+// 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")
func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
(*d)["Apex"] = map[string]interface{}{
@@ -586,75 +592,131 @@
return merged, aliases
}
-// CreateApexVariations mutates a given module into multiple apex variants each of which is for an
-// apexBundle (and/or the platform) where the module is part of.
-func CreateApexVariations(mctx BottomUpMutatorContext, module ApexModule) []Module {
+// 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 this module has no apex variations the use the platform variation.
+ if len(apexInfos) == 0 {
+ return ""
+ }
+
+ // Convert the list of apex infos into from the AllApexInfoProvider into the merged list
+ // of apex variations and the aliases from apex names to apex variations.
+ var aliases [][2]string
+ if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
+ apexInfos, aliases = mergeApexVariations(apexInfos)
+ }
+
+ // Check if the incoming variation matches an apex name, and if so use the corresponding
+ // apex variation.
+ aliasIndex := slices.IndexFunc(aliases, func(alias [2]string) bool {
+ return alias[0] == incomingVariation
+ })
+ if aliasIndex >= 0 {
+ return aliases[aliasIndex][1]
+ }
+
+ // Check if the incoming variation matches an apex variation.
+ apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
+ return info.ApexVariationName == incomingVariation
+ })
+ if apexIndex >= 0 {
+ return incomingVariation
+ }
+
+ return ""
+}
+
+func MutateApexTransition(ctx BaseModuleContext, variation string) {
+ module := ctx.Module().(ApexModule)
+ base := module.apexModuleBase()
+ platformVariation := variation == ""
+
+ var apexInfos []ApexInfo
+ if allApexInfos, ok := ModuleProvider(ctx, AllApexInfoProvider); ok {
+ apexInfos = allApexInfos.ApexInfos
+ }
+
// Shortcut
- if len(base.apexInfos) == 0 {
- return nil
+ if len(apexInfos) == 0 {
+ return
}
// Do some validity checks.
// TODO(jiyong): is this the right place?
- base.checkApexAvailableProperty(mctx)
+ base.checkApexAvailableProperty(ctx)
- apexInfos := base.apexInfos
- // base.apexInfos is only needed to propagate the list of apexes from apexInfoMutator to
- // apexMutator. It is no longer accurate after mergeApexVariations, and won't be copied to
- // all but the first created variant. Clear it so it doesn't accidentally get used later.
- base.apexInfos = nil
-
- slices.SortFunc(apexInfos, func(a, b ApexInfo) int {
- return strings.Compare(a.ApexVariationName, b.ApexVariationName)
- })
-
- var aliases [][2]string
- if !mctx.Module().(ApexModule).UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
- apexInfos, aliases = mergeApexVariations(apexInfos)
+ if !module.UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
+ apexInfos, _ = mergeApexVariations(apexInfos)
}
var inApex ApexMembership
for _, a := range apexInfos {
for _, apexContents := range a.ApexContents {
- inApex = inApex.merge(apexContents.contents[mctx.ModuleName()])
+ inApex = inApex.merge(apexContents.contents[ctx.ModuleName()])
}
}
base.ApexProperties.InAnyApex = true
base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex
- defaultVariation := ""
- mctx.SetDefaultDependencyVariation(&defaultVariation)
+ if platformVariation && !ctx.Host() && !module.AvailableFor(AvailableToPlatform) {
+ // Do not install the module for platform, but still allow it to output
+ // uninstallable AndroidMk entries in certain cases when they have side
+ // effects. TODO(jiyong): move this routine to somewhere else
+ module.MakeUninstallable()
+ }
+ if !platformVariation {
+ var thisApexInfo ApexInfo
- variations := []string{defaultVariation}
- testApexes := []string{}
+ apexIndex := slices.IndexFunc(apexInfos, func(info ApexInfo) bool {
+ return info.ApexVariationName == variation
+ })
+ if apexIndex >= 0 {
+ thisApexInfo = apexInfos[apexIndex]
+ } else {
+ panic(fmt.Errorf("failed to find apexInfo for incoming variation %q", variation))
+ }
+
+ SetProvider(ctx, ApexInfoProvider, thisApexInfo)
+ }
+
+ // Set the value of TestApexes in every single apex variant.
+ // This allows each apex variant to be aware of the test apexes in the user provided apex_available.
+ var testApexes []string
for _, a := range apexInfos {
- variations = append(variations, a.ApexVariationName)
testApexes = append(testApexes, a.TestApexes...)
}
- modules := mctx.CreateVariations(variations...)
- for i, mod := range modules {
- platformVariation := i == 0
- if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) {
- // 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
- mod.MakeUninstallable()
- }
- if !platformVariation {
- mctx.SetVariationProvider(mod, ApexInfoProvider, apexInfos[i-1])
- }
- // Set the value of TestApexes in every single apex variant.
- // This allows each apex variant to be aware of the test apexes in the user provided apex_available.
- mod.(ApexModule).apexModuleBase().ApexProperties.TestApexes = testApexes
- }
+ base.ApexProperties.TestApexes = testApexes
- for _, alias := range aliases {
- mctx.CreateAliasVariation(alias[0], alias[1])
- }
+}
- return modules
+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
@@ -665,13 +727,16 @@
// InApexVariants list in common. It is used instead of DepIsInSameApex because it needs to
// determine if the dep is in the same APEX due to being directly included, not only if it
// is included _because_ it is a dependency.
- anyInSameApex := func(a, b []ApexInfo) bool {
- collectApexes := func(infos []ApexInfo) []string {
- var ret []string
- for _, info := range infos {
- ret = append(ret, info.InApexVariants...)
+ 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 ret
+ return nil
}
aApexes := collectApexes(a)
@@ -689,7 +754,7 @@
// 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.apexModuleBase().apexInfos, am.apexModuleBase().apexInfos) &&
+ if anyInSameApex(depApexModule, am) &&
(depApexModule.UniqueApexVariations() ||
depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
diff --git a/android/arch.go b/android/arch.go
index 27ce4d4..3224c3a 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -16,16 +16,11 @@
import (
"encoding"
- "encoding/json"
"fmt"
"reflect"
"runtime"
- "sort"
"strings"
- "android/soong/bazel"
- "android/soong/starlark_fmt"
-
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
@@ -1899,428 +1894,8 @@
return buildTargets, nil
}
-func (m *ModuleBase) getArchPropertySet(propertySet interface{}, archType ArchType) interface{} {
- archString := archType.Field
- for i := range m.archProperties {
- if m.archProperties[i] == nil {
- // Skip over nil properties
- continue
- }
-
- // Not archProperties are usable; this function looks for properties of a very specific
- // form, and ignores the rest.
- for _, archProperty := range m.archProperties[i] {
- // archPropValue is a property struct, we are looking for the form:
- // `arch: { arm: { key: value, ... }}`
- archPropValue := reflect.ValueOf(archProperty).Elem()
-
- // Unwrap src so that it should looks like a pointer to `arm: { key: value, ... }`
- src := archPropValue.FieldByName("Arch").Elem()
-
- // Step into non-nil pointers to structs in the src value.
- if src.Kind() == reflect.Ptr {
- if src.IsNil() {
- continue
- }
- src = src.Elem()
- }
-
- // Find the requested field (e.g. arm, x86) in the src struct.
- src = src.FieldByName(archString)
-
- // We only care about structs.
- if !src.IsValid() || src.Kind() != reflect.Struct {
- continue
- }
-
- // If the value of the field is a struct then step into the
- // BlueprintEmbed field. The special "BlueprintEmbed" name is
- // used by createArchPropTypeDesc to embed the arch properties
- // in the parent struct, so the src arch prop should be in this
- // field.
- //
- // See createArchPropTypeDesc for more details on how Arch-specific
- // module properties are processed from the nested props and written
- // into the module's archProperties.
- src = src.FieldByName("BlueprintEmbed")
-
- // Clone the destination prop, since we want a unique prop struct per arch.
- propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
-
- // Copy the located property struct into the cloned destination property struct.
- err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace)
- if err != nil {
- // This is fine, it just means the src struct doesn't match the type of propertySet.
- continue
- }
-
- return propertySetClone
- }
- }
- // No property set was found specific to the given arch, so return an empty
- // property set.
- return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
-}
-
-// getMultilibPropertySet returns a property set struct matching the type of
-// `propertySet`, containing multilib-specific module properties for the given architecture.
-// If no multilib-specific properties exist for the given architecture, returns an empty property
-// set matching `propertySet`'s type.
-func (m *ModuleBase) getMultilibPropertySet(propertySet interface{}, archType ArchType) interface{} {
- // archType.Multilib is lowercase (for example, lib32) but property struct field is
- // capitalized, such as Lib32, so use strings.Title to capitalize it.
- multiLibString := strings.Title(archType.Multilib)
-
- for i := range m.archProperties {
- if m.archProperties[i] == nil {
- // Skip over nil properties
- continue
- }
-
- // Not archProperties are usable; this function looks for properties of a very specific
- // form, and ignores the rest.
- for _, archProperties := range m.archProperties[i] {
- // archPropValue is a property struct, we are looking for the form:
- // `multilib: { lib32: { key: value, ... }}`
- archPropValue := reflect.ValueOf(archProperties).Elem()
-
- // Unwrap src so that it should looks like a pointer to `lib32: { key: value, ... }`
- src := archPropValue.FieldByName("Multilib").Elem()
-
- // Step into non-nil pointers to structs in the src value.
- if src.Kind() == reflect.Ptr {
- if src.IsNil() {
- // Ignore nil pointers.
- continue
- }
- src = src.Elem()
- }
-
- // Find the requested field (e.g. lib32) in the src struct.
- src = src.FieldByName(multiLibString)
-
- // We only care about valid struct pointers.
- if !src.IsValid() || src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct {
- continue
- }
-
- // Get the zero value for the requested property set.
- propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
-
- // Copy the located property struct into the "zero" property set struct.
- err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace)
-
- if err != nil {
- // This is fine, it just means the src struct doesn't match.
- continue
- }
-
- return propertySetClone
- }
- }
-
- // There were no multilib properties specifically matching the given archtype.
- // Return zeroed value.
- return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
-}
-
// ArchVariantContext defines the limited context necessary to retrieve arch_variant properties.
type ArchVariantContext interface {
ModuleErrorf(fmt string, args ...interface{})
PropertyErrorf(property, fmt string, args ...interface{})
}
-
-// ArchVariantProperties represents a map of arch-variant config strings to a property interface{}.
-type ArchVariantProperties map[string]interface{}
-
-// ConfigurationAxisToArchVariantProperties represents a map of bazel.ConfigurationAxis to
-// ArchVariantProperties, such that each independent arch-variant axis maps to the
-// configs/properties for that axis.
-type ConfigurationAxisToArchVariantProperties map[bazel.ConfigurationAxis]ArchVariantProperties
-
-// GetArchVariantProperties returns a ConfigurationAxisToArchVariantProperties where the
-// arch-variant properties correspond to the values of the properties of the 'propertySet' struct
-// that are specific to that axis/configuration. Each axis is independent, containing
-// non-overlapping configs that correspond to the various "arch-variant" support, at this time:
-//
-// arches (including multilib)
-// oses
-// arch+os combinations
-//
-// For example, passing a struct { Foo bool, Bar string } will return an interface{} that can be
-// type asserted back into the same struct, containing the config-specific property value specified
-// by the module if defined.
-//
-// Arch-specific properties may come from an arch stanza or a multilib stanza; properties
-// in these stanzas are combined.
-// For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }`
-// will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given
-// propertyset contains `Foo []string`.
-func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySet interface{}) ConfigurationAxisToArchVariantProperties {
- // Return value of the arch types to the prop values for that arch.
- axisToProps := ConfigurationAxisToArchVariantProperties{}
-
- // Nothing to do for non-arch-specific modules.
- if !m.ArchSpecific() {
- return axisToProps
- }
-
- dstType := reflect.ValueOf(propertySet).Type()
- var archProperties []interface{}
-
- // First find the property set in the module that corresponds to the requested
- // one. m.archProperties[i] corresponds to m.GetProperties()[i].
- for i, generalProp := range m.GetProperties() {
- srcType := reflect.ValueOf(generalProp).Type()
- if srcType == dstType {
- archProperties = m.archProperties[i]
- axisToProps[bazel.NoConfigAxis] = ArchVariantProperties{"": generalProp}
- break
- }
- }
-
- if archProperties == nil {
- // This module does not have the property set requested
- return axisToProps
- }
-
- archToProp := ArchVariantProperties{}
- // For each arch type (x86, arm64, etc.)
- for _, arch := range ArchTypeList() {
- // Arch properties are sometimes sharded (see createArchPropTypeDesc() ).
- // Iterate over every shard and extract a struct with the same type as the
- // input one that contains the data specific to that arch.
- propertyStructs := make([]reflect.Value, 0)
- archFeaturePropertyStructs := make(map[string][]reflect.Value, 0)
- for _, archProperty := range archProperties {
- archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch)
- if ok {
- propertyStructs = append(propertyStructs, archTypeStruct)
-
- // For each feature this arch supports (arm: neon, x86: ssse3, sse4, ...)
- for _, feature := range archFeatures[arch] {
- prefix := "arch." + arch.Name + "." + feature
- if featureProperties, ok := getChildPropertyStruct(ctx, archTypeStruct, feature, prefix); ok {
- archFeaturePropertyStructs[feature] = append(archFeaturePropertyStructs[feature], featureProperties)
- }
- }
- }
- multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch)
- if ok {
- propertyStructs = append(propertyStructs, multilibStruct)
- }
- }
-
- archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, propertySet)
-
- // In soong, if multiple features match the current configuration, they're
- // all used. In bazel, we have to have unambiguous select() statements, so
- // we can't have two features that are both active in the same select().
- // One alternative is to split out each feature into a separate select(),
- // but then it's difficult to support exclude_srcs, which may need to
- // exclude things from the regular arch select() statement if a certain
- // feature is active. Instead, keep the features in the same select
- // statement as the arches, but emit the power set of all possible
- // combinations of features, so that bazel can match the most precise one.
- allFeatures := make([]string, 0, len(archFeaturePropertyStructs))
- for feature := range archFeaturePropertyStructs {
- allFeatures = append(allFeatures, feature)
- }
- for _, features := range bazel.PowerSetWithoutEmptySet(allFeatures) {
- sort.Strings(features)
- propsForCurrentFeatureSet := make([]reflect.Value, 0)
- propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, propertyStructs...)
- for _, feature := range features {
- propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, archFeaturePropertyStructs[feature]...)
- }
- archToProp[arch.Name+"-"+strings.Join(features, "-")] =
- mergeStructs(ctx, propsForCurrentFeatureSet, propertySet)
- }
- }
- axisToProps[bazel.ArchConfigurationAxis] = archToProp
-
- osToProp := ArchVariantProperties{}
- archOsToProp := ArchVariantProperties{}
-
- linuxStructs := getTargetStructs(ctx, archProperties, "Linux")
- bionicStructs := getTargetStructs(ctx, archProperties, "Bionic")
- hostStructs := getTargetStructs(ctx, archProperties, "Host")
- hostLinuxStructs := getTargetStructs(ctx, archProperties, "Host_linux")
- hostNotWindowsStructs := getTargetStructs(ctx, archProperties, "Not_windows")
-
- // For android, linux, ...
- for _, os := range osTypeList {
- if os == CommonOS {
- // It looks like this OS value is not used in Blueprint files
- continue
- }
- osStructs := make([]reflect.Value, 0)
-
- osSpecificStructs := getTargetStructs(ctx, archProperties, os.Field)
- if os.Class == Host {
- osStructs = append(osStructs, hostStructs...)
- }
- if os.Linux() {
- osStructs = append(osStructs, linuxStructs...)
- }
- if os.Bionic() {
- osStructs = append(osStructs, bionicStructs...)
- }
- if os.Linux() && os.Class == Host {
- osStructs = append(osStructs, hostLinuxStructs...)
- }
-
- if os == LinuxMusl {
- osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Musl")...)
- }
- if os == Linux {
- osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Glibc")...)
- }
-
- osStructs = append(osStructs, osSpecificStructs...)
-
- if os.Class == Host && os != Windows {
- osStructs = append(osStructs, hostNotWindowsStructs...)
- }
- osToProp[os.Name] = mergeStructs(ctx, osStructs, propertySet)
-
- // For arm, x86, ...
- for _, arch := range osArchTypeMap[os] {
- osArchStructs := make([]reflect.Value, 0)
-
- // Auto-combine with Linux_ and Bionic_ targets. This potentially results in
- // repetition and select() bloat, but use of Linux_* and Bionic_* targets is rare.
- // TODO(b/201423152): Look into cleanup.
- if os.Linux() {
- targetField := "Linux_" + arch.Name
- targetStructs := getTargetStructs(ctx, archProperties, targetField)
- osArchStructs = append(osArchStructs, targetStructs...)
- }
- if os.Bionic() {
- targetField := "Bionic_" + arch.Name
- targetStructs := getTargetStructs(ctx, archProperties, targetField)
- osArchStructs = append(osArchStructs, targetStructs...)
- }
- if os == LinuxMusl {
- targetField := "Musl_" + arch.Name
- targetStructs := getTargetStructs(ctx, archProperties, targetField)
- osArchStructs = append(osArchStructs, targetStructs...)
- }
- if os == Linux {
- targetField := "Glibc_" + arch.Name
- targetStructs := getTargetStructs(ctx, archProperties, targetField)
- osArchStructs = append(osArchStructs, targetStructs...)
- }
-
- targetField := GetCompoundTargetField(os, arch)
- targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name)
- targetStructs := getTargetStructs(ctx, archProperties, targetField)
- osArchStructs = append(osArchStructs, targetStructs...)
-
- archOsToProp[targetName] = mergeStructs(ctx, osArchStructs, propertySet)
- }
- }
-
- axisToProps[bazel.OsConfigurationAxis] = osToProp
- axisToProps[bazel.OsArchConfigurationAxis] = archOsToProp
- return axisToProps
-}
-
-// Returns a struct matching the propertySet interface, containing properties specific to the targetName
-// For example, given these arguments:
-//
-// propertySet = BaseCompilerProperties
-// targetName = "android_arm"
-//
-// And given this Android.bp fragment:
-//
-// target:
-// android_arm: {
-// srcs: ["foo.c"],
-// }
-// android_arm64: {
-// srcs: ["bar.c"],
-// }
-// }
-//
-// This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"]
-func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) []reflect.Value {
- var propertyStructs []reflect.Value
- for _, archProperty := range archProperties {
- archPropValues := reflect.ValueOf(archProperty).Elem()
- targetProp := archPropValues.FieldByName("Target").Elem()
- targetStruct, ok := getChildPropertyStruct(ctx, targetProp, targetName, targetName)
- if ok {
- propertyStructs = append(propertyStructs, targetStruct)
- } else {
- return []reflect.Value{}
- }
- }
-
- return propertyStructs
-}
-
-func mergeStructs(ctx ArchVariantContext, propertyStructs []reflect.Value, propertySet interface{}) interface{} {
- // Create a new instance of the requested property set
- value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
-
- // Merge all the structs together
- for _, propertyStruct := range propertyStructs {
- mergePropertyStruct(ctx, value, propertyStruct)
- }
-
- return value
-}
-
-func printArchTypeStarlarkDict(dict map[ArchType][]string) string {
- valDict := make(map[string]string, len(dict))
- for k, v := range dict {
- valDict[k.String()] = starlark_fmt.PrintStringList(v, 1)
- }
- return starlark_fmt.PrintDict(valDict, 0)
-}
-
-func printArchTypeNestedStarlarkDict(dict map[ArchType]map[string][]string) string {
- valDict := make(map[string]string, len(dict))
- for k, v := range dict {
- valDict[k.String()] = starlark_fmt.PrintStringListDict(v, 1)
- }
- return starlark_fmt.PrintDict(valDict, 0)
-}
-
-func printArchConfigList(arches []archConfig) string {
- jsonOut, err := json.MarshalIndent(arches, "", starlark_fmt.Indention(1))
- if err != nil {
- panic(fmt.Errorf("Error converting arch configs %#v to json: %q", arches, err))
- }
- return fmt.Sprintf("json.decode('''%s''')", string(jsonOut))
-}
-
-func StarlarkArchConfigurations() string {
- return fmt.Sprintf(`
-_arch_to_variants = %s
-
-_arch_to_cpu_variants = %s
-
-_arch_to_features = %s
-
-_android_arch_feature_for_arch_variant = %s
-
-_aml_arches = %s
-
-_ndk_arches = %s
-
-arch_to_variants = _arch_to_variants
-arch_to_cpu_variants = _arch_to_cpu_variants
-arch_to_features = _arch_to_features
-android_arch_feature_for_arch_variants = _android_arch_feature_for_arch_variant
-aml_arches = _aml_arches
-ndk_arches = _ndk_arches
-`, printArchTypeStarlarkDict(archVariants),
- printArchTypeStarlarkDict(cpuVariants),
- printArchTypeStarlarkDict(archFeatures),
- printArchTypeNestedStarlarkDict(androidArchFeatureMap),
- printArchConfigList(getAmlAbisConfig()),
- printArchConfigList(getNdkAbisConfig()),
- )
-}
diff --git a/android/variable.go b/android/variable.go
index 0040d83..599f88e 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -20,8 +20,6 @@
"runtime"
"strings"
- "android/soong/bazel"
-
"github.com/google/blueprint/proptools"
)
@@ -492,10 +490,6 @@
CheckVendorSeappViolations *bool `json:",omitempty"`
- // PartitionVarsForBazelMigrationOnlyDoNotUse are extra variables that are used to define the
- // partition images. They should not be read from soong modules.
- PartitionVarsForBazelMigrationOnlyDoNotUse PartitionVariables `json:",omitempty"`
-
BuildFlags map[string]string `json:",omitempty"`
BuildFromSourceStub *bool `json:",omitempty"`
@@ -644,387 +638,6 @@
return val == "true"
}
-// ProductConfigContext requires the access to the Module to get product config properties.
-type ProductConfigContext interface {
- Module() Module
-}
-
-// ProductConfigOrSoongConfigProperty represents either a soong config variable + its value
-// or a product config variable. You can get both a ConfigurationAxis and a SelectKey from it
-// for use in bazel attributes. ProductVariableProperties() will return a map from properties ->
-// this interface -> property structs for use in bp2build converters
-type ProductConfigOrSoongConfigProperty interface {
- // Name of the product variable or soong config variable
- Name() string
- // AlwaysEmit returns true for soong config variables but false for product variables. This
- // is intended to indicate if we need to always emit empty lists in the select statements.
- AlwaysEmit() bool
- // ConfigurationAxis returns the bazel.ConfigurationAxis that represents this variable. The
- // configuration axis will change depending on the variable and whether it's arch/os variant
- // as well.
- ConfigurationAxis() bazel.ConfigurationAxis
- // SelectKey returns a string that represents the key of a select branch, however, it is not
- // actually the real label written out to the build file.
- // this.ConfigurationAxis().SelectKey(this.SelectKey()) will give the actual label.
- SelectKey() string
-}
-
-// ProductConfigProperty represents a product config variable, and if it is arch-variant or not.
-type ProductConfigProperty struct {
- // The name of the product variable, e.g. "safestack", "malloc_not_svelte",
- // "board"
- name string
-
- arch string
-}
-
-func (p ProductConfigProperty) Name() string {
- return p.name
-}
-
-func (p ProductConfigProperty) AlwaysEmit() bool {
- return false
-}
-
-func (p ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
- return bazel.ProductVariableConfigurationAxis(p.arch != "", p.name+"__"+p.arch)
-}
-
-func (p ProductConfigProperty) SelectKey() string {
- if p.arch == "" {
- return strings.ToLower(p.name)
- } else {
- return strings.ToLower(p.name + "-" + p.arch)
- }
-}
-
-// SoongConfigProperty represents a soong config variable, its value if it's a string variable,
-// and if it's dependent on the OS or not
-type SoongConfigProperty struct {
- name string
- namespace string
- // Can be an empty string for bool/value soong config variables
- value string
- // If there is a target: field inside a soong config property struct, the os that it selects
- // on will be represented here.
- os string
-}
-
-func (p SoongConfigProperty) Name() string {
- return p.name
-}
-
-func (p SoongConfigProperty) AlwaysEmit() bool {
- return true
-}
-
-func (p SoongConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
- return bazel.ProductVariableConfigurationAxis(false, p.namespace+"__"+p.name+"__"+p.os)
-}
-
-// SelectKey returns the literal string that represents this variable in a BUILD
-// select statement.
-func (p SoongConfigProperty) SelectKey() string {
- // p.value being conditions_default can happen with or without a desired os. When not using
- // an os, we want to emit literally just //conditions:default in the select statement, but
- // when using an os, we want to emit namespace__name__conditions_default__os, so that
- // the branch is only taken if the variable is not set, and we're on the desired os.
- // ConfigurationAxis#SelectKey will map the conditions_default result of this function to
- // //conditions:default.
- if p.value == bazel.ConditionsDefaultConfigKey && p.os == "" {
- return bazel.ConditionsDefaultConfigKey
- }
-
- parts := []string{p.namespace, p.name}
- if p.value != "" && p.value != bazel.ConditionsDefaultSelectKey {
- parts = append(parts, p.value)
- }
- if p.os != "" {
- parts = append(parts, p.os)
- }
-
- // e.g. acme__feature1, android__board__soc_a, my_namespace__my_variables__my_value__my_os
- return strings.ToLower(strings.Join(parts, "__"))
-}
-
-// ProductConfigProperties is a map of maps to group property values according
-// their property name and the product config variable they're set under.
-//
-// The outer map key is the name of the property, like "cflags".
-//
-// The inner map key is a ProductConfigProperty, which is a struct of product
-// variable name, namespace, and the "full configuration" of the product
-// variable.
-//
-// e.g. product variable name: board, namespace: acme, full config: vendor_chip_foo
-//
-// The value of the map is the interface{} representing the value of the
-// property, like ["-DDEFINES"] for cflags.
-type ProductConfigProperties map[string]map[ProductConfigOrSoongConfigProperty]interface{}
-
-func (p *ProductConfigProperties) AddProductConfigProperty(
- propertyName, productVariableName, arch string, propertyValue interface{}) {
-
- productConfigProp := ProductConfigProperty{
- name: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board
- arch: arch, // e.g. "", x86, arm64
- }
-
- p.AddEitherProperty(propertyName, productConfigProp, propertyValue)
-}
-
-func (p *ProductConfigProperties) AddSoongConfigProperty(
- propertyName, namespace, variableName, value, os string, propertyValue interface{}) {
-
- soongConfigProp := SoongConfigProperty{
- namespace: namespace,
- name: variableName, // e.g. size, feature1, feature2, FEATURE3, board
- value: value,
- os: os, // e.g. android, linux_x86
- }
-
- p.AddEitherProperty(propertyName, soongConfigProp, propertyValue)
-}
-
-func (p *ProductConfigProperties) AddEitherProperty(
- propertyName string, key ProductConfigOrSoongConfigProperty, propertyValue interface{}) {
- if (*p)[propertyName] == nil {
- (*p)[propertyName] = make(map[ProductConfigOrSoongConfigProperty]interface{})
- }
-
- if existing, ok := (*p)[propertyName][key]; ok {
- switch dst := existing.(type) {
- case []string:
- src, ok := propertyValue.([]string)
- if !ok {
- panic("Conflicting types")
- }
- dst = append(dst, src...)
- (*p)[propertyName][key] = dst
- default:
- if existing != propertyValue {
- panic(fmt.Errorf("TODO: handle merging value %#v", existing))
- }
- }
- } else {
- (*p)[propertyName][key] = propertyValue
- }
-}
-
-// maybeExtractConfigVarProp attempts to read this value as a config var struct
-// wrapped by interfaces and ptrs. If it's not the right type, the second return
-// value is false.
-func maybeExtractConfigVarProp(v reflect.Value) (reflect.Value, bool) {
- if v.Kind() == reflect.Interface {
- // The conditions_default value can be either
- // 1) an ptr to an interface of a struct (bool config variables and product variables)
- // 2) an interface of 1) (config variables with nested structs, like string vars)
- v = v.Elem()
- }
- if v.Kind() != reflect.Ptr {
- return v, false
- }
- v = reflect.Indirect(v)
- if v.Kind() == reflect.Interface {
- // Extract the struct from the interface
- v = v.Elem()
- }
-
- if !v.IsValid() {
- return v, false
- }
-
- if v.Kind() != reflect.Struct {
- return v, false
- }
- return v, true
-}
-
-func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(variableValues reflect.Value, arch string) {
- // Example of product_variables:
- //
- // product_variables: {
- // malloc_not_svelte: {
- // shared_libs: ["malloc_not_svelte_shared_lib"],
- // whole_static_libs: ["malloc_not_svelte_whole_static_lib"],
- // exclude_static_libs: [
- // "malloc_not_svelte_static_lib_excludes",
- // "malloc_not_svelte_whole_static_lib_excludes",
- // ],
- // },
- // },
-
- for i := 0; i < variableValues.NumField(); i++ {
- // e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc.
- productVariableName := variableValues.Type().Field(i).Name
-
- variableValue := variableValues.Field(i)
- // Check if any properties were set for the module
- if variableValue.IsZero() {
- // e.g. feature1: {}, malloc_not_svelte: {}
- continue
- }
-
- for j := 0; j < variableValue.NumField(); j++ {
- property := variableValue.Field(j)
- // e.g. Asflags, Cflags, Enabled, etc.
- propertyName := variableValue.Type().Field(j).Name
- if property.Kind() != reflect.Interface {
- productConfigProperties.AddProductConfigProperty(propertyName, productVariableName, arch, property.Interface())
- }
- }
- }
-
-}
-
-func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) error {
- //
- // Example of soong_config_variables:
- //
- // soong_config_variables: {
- // feature1: {
- // conditions_default: {
- // ...
- // },
- // cflags: ...
- // },
- // feature2: {
- // cflags: ...
- // conditions_default: {
- // ...
- // },
- // },
- // board: {
- // soc_a: {
- // ...
- // },
- // soc_b: {
- // ...
- // },
- // soc_c: {},
- // conditions_default: {
- // ...
- // },
- // },
- // }
- for i := 0; i < soongConfigVariablesStruct.NumField(); i++ {
- // e.g. feature1, feature2, board
- variableName := soongConfigVariablesStruct.Type().Field(i).Name
- variableStruct := soongConfigVariablesStruct.Field(i)
- // Check if any properties were set for the module
- if variableStruct.IsZero() {
- // e.g. feature1: {}
- continue
- }
-
- // Unlike product variables, config variables require a few more
- // indirections to extract the struct from the reflect.Value.
- if v, ok := maybeExtractConfigVarProp(variableStruct); ok {
- variableStruct = v
- } else if !v.IsValid() {
- // Skip invalid variables which may not used, else leads to panic
- continue
- }
-
- for j := 0; j < variableStruct.NumField(); j++ {
- propertyOrStruct := variableStruct.Field(j)
- // propertyOrValueName can either be:
- // - A property, like: Asflags, Cflags, Enabled, etc.
- // - A soong config string variable's value, like soc_a, soc_b, soc_c in the example above
- // - "conditions_default"
- propertyOrValueName := variableStruct.Type().Field(j).Name
-
- // If the property wasn't set, no need to pass it along
- if propertyOrStruct.IsZero() {
- continue
- }
-
- if v, ok := maybeExtractConfigVarProp(propertyOrStruct); ok {
- // The field is a struct, which is used by:
- // 1) soong_config_string_variables
- //
- // soc_a: {
- // cflags: ...,
- // }
- //
- // soc_b: {
- // cflags: ...,
- // }
- //
- // 2) conditions_default structs for all soong config variable types.
- //
- // conditions_default: {
- // cflags: ...,
- // static_libs: ...
- // }
- //
- // This means that propertyOrValueName is either conditions_default, or a soong
- // config string variable's value.
- field := v
- // Iterate over fields of this struct prop.
- for k := 0; k < field.NumField(); k++ {
- // For product variables, zero values are irrelevant; however, for soong config variables,
- // empty values are relevant because there can also be a conditions default which is not
- // applied for empty variables.
- if field.Field(k).IsZero() && namespace == "" {
- continue
- }
-
- propertyName := field.Type().Field(k).Name
- if propertyName == "Target" {
- productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), field.Field(k))
- } else if propertyName == "Arch" || propertyName == "Multilib" {
- return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
- } else {
- productConfigProperties.AddSoongConfigProperty(propertyName, namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), "", field.Field(k).Interface())
- }
- }
- } else if propertyOrStruct.Kind() != reflect.Interface {
- // If not an interface, then this is not a conditions_default or
- // a struct prop. That is, this is a bool/value config variable.
- if propertyOrValueName == "Target" {
- productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, "", propertyOrStruct)
- } else if propertyOrValueName == "Arch" || propertyOrValueName == "Multilib" {
- return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
- } else {
- productConfigProperties.AddSoongConfigProperty(propertyOrValueName, namespace, variableName, "", "", propertyOrStruct.Interface())
- }
- }
- }
- }
- return nil
-}
-
-func (productConfigProperties *ProductConfigProperties) AddSoongConfigPropertiesFromTargetStruct(namespace, soongConfigVariableName string, soongConfigVariableValue string, targetStruct reflect.Value) {
- // targetStruct will be a struct with fields like "android", "host", "arm", "x86",
- // "android_arm", etc. The values of each of those fields will be a regular property struct.
- for i := 0; i < targetStruct.NumField(); i++ {
- targetFieldName := targetStruct.Type().Field(i).Name
- archOrOsSpecificStruct := targetStruct.Field(i)
- for j := 0; j < archOrOsSpecificStruct.NumField(); j++ {
- property := archOrOsSpecificStruct.Field(j)
- // e.g. Asflags, Cflags, Enabled, etc.
- propertyName := archOrOsSpecificStruct.Type().Field(j).Name
-
- if targetFieldName == "Android" {
- productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, "android", property.Interface())
- } else if targetFieldName == "Host" {
- for _, os := range osTypeList {
- if os.Class == Host {
- productConfigProperties.AddSoongConfigProperty(propertyName, namespace, soongConfigVariableName, soongConfigVariableValue, os.Name, property.Interface())
- }
- }
- } else if !archOrOsSpecificStruct.IsZero() {
- // One problem with supporting additional fields is that if multiple branches of
- // "target" overlap, we don't want them to be in the same select statement (aka
- // configuration axis). "android" and "host" are disjoint, so it's ok that we only
- // have 2 axes right now. (soongConfigVariables and soongConfigVariablesPlusOs)
- panic("TODO: support other target types in soong config variable structs: " + targetFieldName)
- }
- }
- }
-}
-
func VariableMutator(mctx BottomUpMutatorContext) {
var module Module
var ok bool
diff --git a/apex/apex.go b/apex/apex.go
index cb8449c..ef57d7e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -73,7 +73,7 @@
// 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).Parallel()
- ctx.BottomUp("apex", apexMutator).Parallel()
+ ctx.Transition("apex", &apexTransitionMutator{})
ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
// Register after apex_info mutator so that it can use ApexVariationName
@@ -1084,6 +1084,10 @@
if a, ok := mctx.Module().(ApexInfoMutator); ok {
a.ApexInfoMutator(mctx)
}
+
+ if am, ok := mctx.Module().(android.ApexModule); ok {
+ android.ApexInfoMutator(mctx, am)
+ }
enforceAppUpdatability(mctx)
}
@@ -1284,40 +1288,41 @@
}
}
-// apexMutator visits each module and creates apex variations if the module was marked in the
-// previous run of apexInfoMutator.
-func apexMutator(mctx android.BottomUpMutatorContext) {
- if !mctx.Module().Enabled() {
- return
- }
+type apexTransitionMutator struct{}
- // This is the usual path.
- if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
- android.CreateApexVariations(mctx, am)
- return
- }
-
+func (a *apexTransitionMutator) Split(ctx android.BaseModuleContext) []string {
// apexBundle itself is mutated so that it and its dependencies have the same apex variant.
- // Note that a default variation "" is also created as an alias, and the default dependency
- // variation is set to the default variation. This is to allow an apex to depend on another
- // module which is outside of the apex. This is because the dependent module is not mutated
- // for this apex variant.
- createApexVariation := func(apexBundleName string) {
- defaultVariation := ""
- mctx.SetDefaultDependencyVariation(&defaultVariation)
- mctx.CreateVariations(apexBundleName)
- mctx.CreateAliasVariation(defaultVariation, apexBundleName)
- }
-
- if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
- createApexVariation(ai.ApexVariationName())
- } else if o, ok := mctx.Module().(*OverrideApex); ok {
+ if ai, ok := ctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
+ return []string{ai.ApexVariationName()}
+ } else if o, ok := ctx.Module().(*OverrideApex); ok {
apexBundleName := o.GetOverriddenModuleName()
if apexBundleName == "" {
- mctx.ModuleErrorf("base property is not set")
- return
+ ctx.ModuleErrorf("base property is not set")
}
- createApexVariation(apexBundleName)
+ return []string{apexBundleName}
+ }
+ return []string{""}
+}
+
+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 {
+ return ai.ApexVariationName()
+ } else if o, ok := ctx.Module().(*OverrideApex); ok {
+ return o.GetOverriddenModuleName()
+ }
+
+ return ""
+}
+
+func (a *apexTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if am, ok := ctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
+ android.MutateApexTransition(ctx, variation)
}
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 870c643..9934994 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -708,8 +708,8 @@
return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
}
-func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
- srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
+func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
+ srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -739,14 +739,14 @@
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
Flag(config.MetalavaAddOpens).
- FlagWithArg("--java-source ", javaVersion.String()).
- FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
+ FlagWithArg("--java-source ", params.javaVersion.String()).
+ FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
FlagWithInput("@", srcJarList)
// Metalava does not differentiate between bootclasspath and classpath and has not done so for
// years, so it is unlikely to change any time soon.
- combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
- combinedPaths = append(combinedPaths, classpath.Paths()...)
+ combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
+ combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
if len(combinedPaths) > 0 {
cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
}
@@ -827,8 +827,7 @@
srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
- cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
- params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
+ cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
cmd.Implicits(d.Javadoc.implicits)
d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
diff --git a/java/java.go b/java/java.go
index 2834c5f..725e25a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -587,6 +587,7 @@
JAVA_VERSION_9 = 9
JAVA_VERSION_11 = 11
JAVA_VERSION_17 = 17
+ JAVA_VERSION_21 = 21
)
func (v javaVersion) String() string {
@@ -605,6 +606,8 @@
return "11"
case JAVA_VERSION_17:
return "17"
+ case JAVA_VERSION_21:
+ return "21"
default:
return "unsupported"
}
@@ -647,6 +650,8 @@
return JAVA_VERSION_11
case "17":
return JAVA_VERSION_17
+ case "21":
+ return JAVA_VERSION_21
case "10", "12", "13", "14", "15", "16":
ctx.PropertyErrorf("java_version", "Java language level %s is not supported", javaVersion)
return JAVA_VERSION_UNSUPPORTED
diff --git a/java/sdk_library.go b/java/sdk_library.go
index bb5730d..113071f 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -3316,6 +3316,7 @@
android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent)
module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir())
+ ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath)
}
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/testing.go b/java/testing.go
index 631d516..5ae326d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -711,7 +711,7 @@
func registerFakeApexMutator(ctx android.RegistrationContext) {
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex", fakeApexMutator).Parallel()
+ ctx.Transition("apex", &fakeApexMutator{})
})
}
@@ -726,16 +726,30 @@
// `apex_available`. It helps us avoid a dependency on the real mutator defined in "soong-apex",
// which will cause a cyclic dependency, and it provides an easy way to create an APEX variant for
// testing without dealing with all the complexities in the real mutator.
-func fakeApexMutator(mctx android.BottomUpMutatorContext) {
- switch mctx.Module().(type) {
+type fakeApexMutator struct{}
+
+func (f *fakeApexMutator) Split(ctx android.BaseModuleContext) []string {
+ switch ctx.Module().(type) {
case *Library, *SdkLibrary:
- if len(mctx.Module().(apexModuleBase).ApexAvailable()) > 0 {
- modules := mctx.CreateVariations("", "apex1000")
- apexInfo := android.ApexInfo{
- ApexVariationName: "apex1000",
- }
- mctx.SetVariationProvider(modules[1], android.ApexInfoProvider, apexInfo)
+ return []string{"", "apex1000"}
+ }
+ return []string{""}
+}
+
+func (f *fakeApexMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (f *fakeApexMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ return incomingVariation
+}
+
+func (f *fakeApexMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if variation != "" {
+ apexInfo := android.ApexInfo{
+ ApexVariationName: "apex1000",
}
+ android.SetProvider(ctx, android.ApexInfoProvider, apexInfo)
}
}
diff --git a/python/binary.go b/python/binary.go
index d6750c6..c84eeee 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -203,7 +203,7 @@
}
func (p *PythonBinaryModule) isEmbeddedLauncherEnabled() bool {
- return Bool(p.properties.Embedded_launcher)
+ return BoolDefault(p.properties.Embedded_launcher, true)
}
func (b *PythonBinaryModule) autorun() bool {
diff --git a/python/python.go b/python/python.go
index 621e429..e14fdf3 100644
--- a/python/python.go
+++ b/python/python.go
@@ -59,7 +59,7 @@
// list of the Python libraries used only for this Python version.
Libs []string `android:"arch_variant"`
- // whether the binary is required to be built with embedded launcher for this version, defaults to false.
+ // whether the binary is required to be built with embedded launcher for this version, defaults to true.
Embedded_launcher *bool // TODO(b/174041232): Remove this property
}