Merge "Add install_symlink_host Soong module type" into main
diff --git a/android/Android.bp b/android/Android.bp
index c2bef0b..eb8c64d 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -71,6 +71,7 @@
"module.go",
"module_context.go",
"module_info_json.go",
+ "module_proxy.go",
"mutator.go",
"namespace.go",
"neverallow.go",
diff --git a/android/arch.go b/android/arch.go
index 1ec971d..e2d0d0d 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1369,7 +1369,7 @@
// Returns the structs corresponding to the properties specific to the given
// architecture and OS in archProperties.
-func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value {
+func getArchProperties(ctx BaseModuleContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value {
result := make([]reflect.Value, 0)
archPropValues := reflect.ValueOf(archProperties).Elem()
diff --git a/android/base_module_context.go b/android/base_module_context.go
index c7d7573..670537f 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -33,6 +33,8 @@
blueprintBaseModuleContext() blueprint.BaseModuleContext
+ EqualModules(m1, m2 Module) bool
+
// OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
// It is intended for use inside the visit functions of Visit* and WalkDeps.
OtherModuleName(m blueprint.Module) string
@@ -130,6 +132,14 @@
// function, it may be invalidated by future mutators.
VisitDirectDepsAllowDisabled(visit func(Module))
+ // VisitDirectDepsProxyAllowDisabled calls visit for each direct dependency. If there are
+ // multiple direct dependencies on the same module visit will be called multiple times on
+ // that module and OtherModuleDependencyTag will return a different tag for each.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit function, it may be
+ // invalidated by future mutators.
+ VisitDirectDepsProxyAllowDisabled(visit func(proxy Module))
+
VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
// VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
@@ -155,6 +165,16 @@
// invalidated by future mutators.
WalkDeps(visit func(child, parent Module) bool)
+ // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
+ // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
+ // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
+ // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
+ // any dependencies that are not an android.Module.
+ //
+ // The Modules passed to the visit function should not be retained outside of the visit function, they may be
+ // invalidated by future mutators.
+ WalkDepsProxy(visit func(child, parent Module) bool)
+
// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
// and returns a top-down dependency path from a start module to current child module.
GetWalkPath() []Module
@@ -214,15 +234,26 @@
}
+func getWrappedModule(module blueprint.Module) blueprint.Module {
+ if mp, isProxy := module.(ModuleProxy); isProxy {
+ return mp.module
+ }
+ return module
+}
+
+func (b *baseModuleContext) EqualModules(m1, m2 Module) bool {
+ return b.bp.EqualModules(getWrappedModule(m1), getWrappedModule(m2))
+}
+
func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
- return b.bp.OtherModuleName(m)
+ return b.bp.OtherModuleName(getWrappedModule(m))
}
func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
b.bp.OtherModuleErrorf(m, fmt, args...)
}
func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
- return b.bp.OtherModuleDependencyTag(m)
+ return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
}
func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
@@ -395,6 +426,14 @@
})
}
+func (b *baseModuleContext) VisitDirectDepsProxyAllowDisabled(visit func(proxy Module)) {
+ b.bp.VisitDirectDepsProxy(func(module blueprint.ModuleProxy) {
+ visit(ModuleProxy{
+ module: module,
+ })
+ })
+}
+
func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
b.bp.VisitDirectDeps(func(module blueprint.Module) {
if b.bp.OtherModuleDependencyTag(module) == tag {
@@ -466,6 +505,23 @@
})
}
+func (b *baseModuleContext) WalkDepsProxy(visit func(Module, Module) bool) {
+ b.walkPath = []Module{ModuleProxy{blueprint.CreateModuleProxy(b.Module())}}
+ b.tagPath = []blueprint.DependencyTag{}
+ b.bp.WalkDepsProxy(func(child, parent blueprint.ModuleProxy) bool {
+ childAndroidModule := ModuleProxy{child}
+ parentAndroidModule := ModuleProxy{parent}
+ // record walkPath before visit
+ for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
+ b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
+ b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
+ }
+ b.walkPath = append(b.walkPath, childAndroidModule)
+ b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
+ return visit(childAndroidModule, parentAndroidModule)
+ })
+}
+
func (b *baseModuleContext) GetWalkPath() []Module {
return b.walkPath
}
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 38f1382..d28831e 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -17,7 +17,6 @@
import (
"bytes"
"encoding/csv"
- "encoding/gob"
"fmt"
"slices"
"strconv"
@@ -126,32 +125,32 @@
properties map[string]string
}
+type complianceMetadataInfoGob struct {
+ Properties map[string]string
+}
+
func NewComplianceMetadataInfo() *ComplianceMetadataInfo {
return &ComplianceMetadataInfo{
properties: map[string]string{},
}
}
-func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := encoder.Encode(c.properties)
- if err != nil {
- return nil, err
+func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob {
+ return &complianceMetadataInfoGob{
+ Properties: m.properties,
}
+}
- return w.Bytes(), nil
+func (m *ComplianceMetadataInfo) FromGob(data *complianceMetadataInfoGob) {
+ m.properties = data.Properties
+}
+
+func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[complianceMetadataInfoGob](c)
}
func (c *ComplianceMetadataInfo) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := decoder.Decode(&c.properties)
- if err != nil {
- return err
- }
-
- return nil
+ return blueprint.CustomGobDecode[complianceMetadataInfoGob](data, c)
}
func (c *ComplianceMetadataInfo) SetStringValue(propertyName string, value string) {
diff --git a/android/config.go b/android/config.go
index e519760..06d71c0 100644
--- a/android/config.go
+++ b/android/config.go
@@ -287,6 +287,10 @@
return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE")
}
+func (c Config) ReleaseCreateAconfigStorageFile() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_CREATE_ACONFIG_STORAGE_FILE")
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -2086,6 +2090,10 @@
return PathsForSource(ctx, c.productVariables.OdmPropFiles)
}
+func (c *config) ExtraAllowedDepsTxt() string {
+ return String(c.productVariables.ExtraAllowedDepsTxt)
+}
+
func (c *config) EnableUffdGc() string {
return String(c.productVariables.EnableUffdGc)
}
diff --git a/android/defaults.go b/android/defaults.go
index 3d06c69..8fe2879 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -274,7 +274,7 @@
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
- ctx.BottomUp("defaults", defaultsMutator).Parallel()
+ ctx.BottomUp("defaults", defaultsMutator).Parallel().UsesCreateModule()
}
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
diff --git a/android/depset_generic.go b/android/depset_generic.go
index 690987a..d04f88b 100644
--- a/android/depset_generic.go
+++ b/android/depset_generic.go
@@ -15,10 +15,9 @@
package android
import (
- "bytes"
- "encoding/gob"
- "errors"
"fmt"
+
+ "github.com/google/blueprint"
)
// DepSet is designed to be conceptually compatible with Bazel's depsets:
@@ -68,28 +67,38 @@
transitive []*DepSet[T]
}
-func (d *DepSet[T]) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(d.preorder), encoder.Encode(d.reverse),
- encoder.Encode(d.order), encoder.Encode(d.direct), encoder.Encode(d.transitive))
- if err != nil {
- return nil, err
- }
+type depSetGob[T depSettableType] struct {
+ Preorder bool
+ Reverse bool
+ Order DepSetOrder
+ Direct []T
+ Transitive []*DepSet[T]
+}
- return w.Bytes(), nil
+func (d *DepSet[T]) ToGob() *depSetGob[T] {
+ return &depSetGob[T]{
+ Preorder: d.preorder,
+ Reverse: d.reverse,
+ Order: d.order,
+ Direct: d.direct,
+ Transitive: d.transitive,
+ }
+}
+
+func (d *DepSet[T]) FromGob(data *depSetGob[T]) {
+ d.preorder = data.Preorder
+ d.reverse = data.Reverse
+ d.order = data.Order
+ d.direct = data.Direct
+ d.transitive = data.Transitive
+}
+
+func (d *DepSet[T]) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[depSetGob[T]](d)
}
func (d *DepSet[T]) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&d.preorder), decoder.Decode(&d.reverse),
- decoder.Decode(&d.order), decoder.Decode(&d.direct), decoder.Decode(&d.transitive))
- if err != nil {
- return err
- }
-
- return nil
+ return blueprint.CustomGobDecode[depSetGob[T]](data, d)
}
// NewDepSet returns an immutable DepSet with the given order, direct and transitive contents.
diff --git a/android/early_module_context.go b/android/early_module_context.go
index 11de771..9b1a9ea 100644
--- a/android/early_module_context.go
+++ b/android/early_module_context.go
@@ -29,7 +29,7 @@
Module() Module
// ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when
- // the module was created, but may have been modified by calls to BaseMutatorContext.Rename.
+ // the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename.
ModuleName() string
// ModuleDir returns the path to the directory that contains the definition of the module.
diff --git a/android/init.go b/android/init.go
index b462292..1ace344 100644
--- a/android/init.go
+++ b/android/init.go
@@ -17,7 +17,12 @@
import "encoding/gob"
func init() {
+ gob.Register(extraFilesZip{})
+ gob.Register(InstallPath{})
+ gob.Register(ModuleGenPath{})
gob.Register(ModuleOutPath{})
+ gob.Register(OutputPath{})
gob.Register(PhonyPath{})
+ gob.Register(SourcePath{})
gob.Register(unstableInfo{})
}
diff --git a/android/module.go b/android/module.go
index a1a9a4a..44f7583 100644
--- a/android/module.go
+++ b/android/module.go
@@ -15,9 +15,6 @@
package android
import (
- "bytes"
- "encoding/gob"
- "errors"
"fmt"
"net/url"
"path/filepath"
@@ -1006,14 +1003,6 @@
return
}
- // Do not create a dependency from common variant to arch variant for `common_first` modules
- if multilib, _ := decodeMultilib(ctx, ctx.Module().base()); multilib == string(MultilibCommonFirst) {
- commonVariant := ctx.Arch().ArchType.Multilib == ""
- if bothInAndroid && commonVariant && InList(target.Arch.ArchType.Multilib, []string{"lib32", "lib64"}) {
- return
- }
- }
-
variation := target.Variations()
if ctx.OtherModuleFarDependencyVariantExists(variation, depName) {
ctx.AddFarVariationDependencies(variation, RequiredDepTag, depName)
@@ -1806,6 +1795,26 @@
var FinalModuleBuildTargetsProvider = blueprint.NewProvider[FinalModuleBuildTargetsInfo]()
+type CommonPropertiesProviderData struct {
+ Enabled bool
+ // Whether the module has been replaced by a prebuilt
+ ReplacedByPrebuilt bool
+}
+
+var CommonPropertiesProviderKey = blueprint.NewProvider[CommonPropertiesProviderData]()
+
+type PrebuiltModuleProviderData struct {
+ // Empty for now
+}
+
+var PrebuiltModuleProviderKey = blueprint.NewProvider[PrebuiltModuleProviderData]()
+
+type HostToolProviderData struct {
+ HostToolPath OptionalPath
+}
+
+var HostToolProviderKey = blueprint.NewProvider[HostToolProviderData]()
+
func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
ctx := &moduleContext{
module: m.module,
@@ -2051,6 +2060,23 @@
})
}
buildComplianceMetadataProvider(ctx, m)
+
+ commonData := CommonPropertiesProviderData{
+ ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
+ }
+ if m.commonProperties.ForcedDisabled {
+ commonData.Enabled = false
+ } else {
+ commonData.Enabled = m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
+ }
+ SetProvider(ctx, CommonPropertiesProviderKey, commonData)
+ if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
+ SetProvider(ctx, PrebuiltModuleProviderKey, PrebuiltModuleProviderData{})
+ }
+ if h, ok := m.module.(HostToolProvider); ok {
+ SetProvider(ctx, HostToolProviderKey, HostToolProviderData{
+ HostToolPath: h.HostToolPath()})
+ }
}
func SetJarJarPrefixHandler(handler func(ModuleContext)) {
@@ -2130,36 +2156,47 @@
orderOnlyDeps Paths
executable bool
extraFiles *extraFilesZip
-
- absFrom string
+ absFrom string
}
-func (p *katiInstall) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.from), encoder.Encode(p.to),
- encoder.Encode(p.implicitDeps), encoder.Encode(p.orderOnlyDeps),
- encoder.Encode(p.executable), encoder.Encode(p.extraFiles),
- encoder.Encode(p.absFrom))
- if err != nil {
- return nil, err
- }
-
- return w.Bytes(), nil
+type katiInstallGob struct {
+ From Path
+ To InstallPath
+ ImplicitDeps Paths
+ OrderOnlyDeps Paths
+ Executable bool
+ ExtraFiles *extraFilesZip
+ AbsFrom string
}
-func (p *katiInstall) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.from), decoder.Decode(&p.to),
- decoder.Decode(&p.implicitDeps), decoder.Decode(&p.orderOnlyDeps),
- decoder.Decode(&p.executable), decoder.Decode(&p.extraFiles),
- decoder.Decode(&p.absFrom))
- if err != nil {
- return err
+func (k *katiInstall) ToGob() *katiInstallGob {
+ return &katiInstallGob{
+ From: k.from,
+ To: k.to,
+ ImplicitDeps: k.implicitDeps,
+ OrderOnlyDeps: k.orderOnlyDeps,
+ Executable: k.executable,
+ ExtraFiles: k.extraFiles,
+ AbsFrom: k.absFrom,
}
+}
- return nil
+func (k *katiInstall) FromGob(data *katiInstallGob) {
+ k.from = data.From
+ k.to = data.To
+ k.implicitDeps = data.ImplicitDeps
+ k.orderOnlyDeps = data.OrderOnlyDeps
+ k.executable = data.Executable
+ k.extraFiles = data.ExtraFiles
+ k.absFrom = data.AbsFrom
+}
+
+func (k *katiInstall) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[katiInstallGob](k)
+}
+
+func (k *katiInstall) GobDecode(data []byte) error {
+ return blueprint.CustomGobDecode[katiInstallGob](data, k)
}
type extraFilesZip struct {
@@ -2167,26 +2204,29 @@
dir InstallPath
}
-func (p *extraFilesZip) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.zip), encoder.Encode(p.dir))
- if err != nil {
- return nil, err
- }
-
- return w.Bytes(), nil
+type extraFilesZipGob struct {
+ Zip Path
+ Dir InstallPath
}
-func (p *extraFilesZip) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.zip), decoder.Decode(&p.dir))
- if err != nil {
- return err
+func (e *extraFilesZip) ToGob() *extraFilesZipGob {
+ return &extraFilesZipGob{
+ Zip: e.zip,
+ Dir: e.dir,
}
+}
- return nil
+func (e *extraFilesZip) FromGob(data *extraFilesZipGob) {
+ e.zip = data.Zip
+ e.dir = data.Dir
+}
+
+func (e *extraFilesZip) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[extraFilesZipGob](e)
+}
+
+func (e *extraFilesZip) GobDecode(data []byte) error {
+ return blueprint.CustomGobDecode[extraFilesZipGob](data, e)
}
type katiInstalls []katiInstall
diff --git a/android/module_proxy.go b/android/module_proxy.go
new file mode 100644
index 0000000..bc5090e
--- /dev/null
+++ b/android/module_proxy.go
@@ -0,0 +1,203 @@
+package android
+
+import (
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+type ModuleProxy struct {
+ module blueprint.ModuleProxy
+}
+
+func (m ModuleProxy) Name() string {
+ return m.module.Name()
+}
+
+func (m ModuleProxy) GenerateBuildActions(context blueprint.ModuleContext) {
+ m.module.GenerateBuildActions(context)
+}
+
+func (m ModuleProxy) GenerateAndroidBuildActions(context ModuleContext) {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) ComponentDepsMutator(ctx BottomUpMutatorContext) {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) DepsMutator(context BottomUpMutatorContext) {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) base() *ModuleBase {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) Disable() {
+
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) Enabled(ctx ConfigurableEvaluatorContext) bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) Target() Target {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) MultiTargets() []Target {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) ImageVariation() blueprint.Variation {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) Owner() string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInData() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInTestcases() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInSanitizerDir() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInRamdisk() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInVendorRamdisk() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInDebugRamdisk() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInRecovery() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInRoot() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInOdm() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInProduct() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInVendor() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallInSystemExt() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) InstallForceOS() (*OsType, *ArchType) {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) PartitionTag(d DeviceConfig) string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) HideFromMake() {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) IsHideFromMake() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) IsSkipInstall() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) MakeUninstallable() {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) ReplacedByPrebuilt() {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) IsReplacedByPrebuilt() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) ExportedToMake() bool {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) EffectiveLicenseKinds() []string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) EffectiveLicenseFiles() Paths {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) AddProperties(props ...interface{}) {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) GetProperties() []interface{} {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) BuildParamsForTests() []BuildParams {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) VariablesForTests() map[string]string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) String() string {
+ return m.module.Name()
+}
+
+func (m ModuleProxy) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) visibilityProperties() []visibilityProperty {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) HostRequiredModuleNames() []string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) TargetRequiredModuleNames() []string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) VintfFragmentModuleNames(ctx ConfigurableEvaluatorContext) []string {
+ panic("method is not implemented on ModuleProxy")
+}
+
+func (m ModuleProxy) ConfigurableEvaluator(ctx ConfigurableEvaluatorContext) proptools.ConfigurableEvaluator {
+ panic("method is not implemented on ModuleProxy")
+}
diff --git a/android/mutator.go b/android/mutator.go
index 8265458..0da3ec7 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -192,25 +192,10 @@
finalDeps = append(finalDeps, f)
}
-type BaseMutatorContext interface {
- BaseModuleContext
-
- // MutatorName returns the name that this mutator was registered with.
- MutatorName() string
-
- // Rename all variants of a module. The new name is not visible to calls to ModuleName,
- // AddDependency or OtherModuleName until after this mutator pass is complete.
- Rename(name string)
-
- // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
- // the specified property structs to it as if the properties were set in a blueprint file.
- CreateModule(ModuleFactory, ...interface{}) Module
-}
-
type TopDownMutator func(TopDownMutatorContext)
type TopDownMutatorContext interface {
- BaseMutatorContext
+ BaseModuleContext
}
type topDownMutatorContext struct {
@@ -221,7 +206,7 @@
type BottomUpMutator func(BottomUpMutatorContext)
type BottomUpMutatorContext interface {
- BaseMutatorContext
+ BaseModuleContext
// AddDependency adds a dependency to the given module. It returns a slice of modules for each
// dependency (some entries may be nil).
@@ -236,7 +221,8 @@
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
- // module's dependency list.
+ // module's dependency list. May only be called by mutators that were marked with
+ // UsesReverseDependencies during registration.
AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
@@ -250,14 +236,15 @@
// be ordered correctly for all future mutator passes.
AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag, names ...string) []blueprint.Module
- // AddReverseVariationDependencies adds a dependency from the named module to the current
+ // AddReverseVariationDependency adds a dependency from the named module to the current
// module. The given variations will be added to the current module's varations, and then the
// result will be used to find the correct variation of the depending module, which must exist.
//
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
// collected until the end of the mutator pass, sorted by name, and then appended to the destination
- // module's dependency list.
+ // module's dependency list. May only be called by mutators that were marked with
+ // UsesReverseDependencies during registration.
AddReverseVariationDependency([]blueprint.Variation, blueprint.DependencyTag, string)
// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
@@ -277,14 +264,26 @@
// ReplaceDependencies finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module.
- // Replacements don't take effect until after the mutator pass is finished.
+ // Replacements don't take effect until after the mutator pass is finished. May only
+ // be called by mutators that were marked with UsesReplaceDependencies during registration.
ReplaceDependencies(string)
// ReplaceDependenciesIf finds all the variants of the module with the specified name, then
// replaces all dependencies onto those variants with the current variant of this module
// as long as the supplied predicate returns true.
- // Replacements don't take effect until after the mutator pass is finished.
+ // Replacements don't take effect until after the mutator pass is finished. May only
+ // be called by mutators that were marked with UsesReplaceDependencies during registration.
ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
+
+ // Rename all variants of a module. The new name is not visible to calls to ModuleName,
+ // AddDependency or OtherModuleName until after this mutator pass is complete. May only be called
+ // by mutators that were marked with UsesRename during registration.
+ Rename(name string)
+
+ // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
+ // the specified property structs to it as if the properties were set in a blueprint file. May only
+ // be called by mutators that were marked with UsesCreateModule during registration.
+ CreateModule(ModuleFactory, ...interface{}) Module
}
// An outgoingTransitionContextImpl and incomingTransitionContextImpl is created for every dependency of every module
@@ -627,13 +626,60 @@
} else if mutator.transitionMutator != nil {
blueprintCtx.RegisterTransitionMutator(mutator.name, mutator.transitionMutator)
}
+
+ // Forward booleans set on the MutatorHandle to the blueprint.MutatorHandle.
if mutator.parallel {
handle.Parallel()
}
+ if mutator.usesRename {
+ handle.UsesRename()
+ }
+ if mutator.usesReverseDependencies {
+ handle.UsesReverseDependencies()
+ }
+ if mutator.usesReplaceDependencies {
+ handle.UsesReplaceDependencies()
+ }
+ if mutator.usesCreateModule {
+ handle.UsesCreateModule()
+ }
+ if mutator.mutatesDependencies {
+ handle.MutatesDependencies()
+ }
+ if mutator.mutatesGlobalState {
+ handle.MutatesGlobalState()
+ }
}
type MutatorHandle interface {
+ // Parallel sets the mutator to visit modules in parallel while maintaining ordering. Calling any
+ // method on the mutator context is thread-safe, but the mutator must handle synchronization
+ // for any modifications to global state or any modules outside the one it was invoked on.
Parallel() MutatorHandle
+
+ // UsesRename marks the mutator as using the BottomUpMutatorContext.Rename method, which prevents
+ // coalescing adjacent mutators into a single mutator pass.
+ UsesRename() MutatorHandle
+
+ // UsesReverseDependencies marks the mutator as using the BottomUpMutatorContext.AddReverseDependency
+ // method, which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesReverseDependencies() MutatorHandle
+
+ // UsesReplaceDependencies marks the mutator as using the BottomUpMutatorContext.ReplaceDependencies
+ // method, which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesReplaceDependencies() MutatorHandle
+
+ // UsesCreateModule marks the mutator as using the BottomUpMutatorContext.CreateModule method,
+ // which prevents coalescing adjacent mutators into a single mutator pass.
+ UsesCreateModule() MutatorHandle
+
+ // MutatesDependencies marks the mutator as modifying properties in dependencies, which prevents
+ // coalescing adjacent mutators into a single mutator pass.
+ MutatesDependencies() MutatorHandle
+
+ // MutatesGlobalState marks the mutator as modifying global state, which prevents coalescing
+ // adjacent mutators into a single mutator pass.
+ MutatesGlobalState() MutatorHandle
}
func (mutator *mutator) Parallel() MutatorHandle {
@@ -641,6 +687,36 @@
return mutator
}
+func (mutator *mutator) UsesRename() MutatorHandle {
+ mutator.usesRename = true
+ return mutator
+}
+
+func (mutator *mutator) UsesReverseDependencies() MutatorHandle {
+ mutator.usesReverseDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) UsesReplaceDependencies() MutatorHandle {
+ mutator.usesReplaceDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) UsesCreateModule() MutatorHandle {
+ mutator.usesCreateModule = true
+ return mutator
+}
+
+func (mutator *mutator) MutatesDependencies() MutatorHandle {
+ mutator.mutatesDependencies = true
+ return mutator
+}
+
+func (mutator *mutator) MutatesGlobalState() MutatorHandle {
+ mutator.mutatesGlobalState = true
+ return mutator
+}
+
func RegisterComponentsMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("component-deps", componentDepsMutator).Parallel()
}
@@ -660,7 +736,7 @@
}
func registerDepsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("deps", depsMutator).Parallel()
+ ctx.BottomUp("deps", depsMutator).Parallel().UsesReverseDependencies()
}
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
@@ -669,32 +745,6 @@
// non-overridden method has to be forwarded. There are fewer non-overridden methods, so use the latter. The following
// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
-func (t *topDownMutatorContext) MutatorName() string {
- return t.bp.MutatorName()
-}
-
-func (t *topDownMutatorContext) Rename(name string) {
- t.bp.Rename(name)
- t.Module().base().commonProperties.DebugName = name
-}
-
-func (t *topDownMutatorContext) createModule(factory blueprint.ModuleFactory, name string, props ...interface{}) blueprint.Module {
- return t.bp.CreateModule(factory, name, props...)
-}
-
-func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...interface{}) Module {
- return createModule(t, factory, "_topDownMutatorModule", props...)
-}
-
-func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module {
- module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), "", props...).(Module)
- return module
-}
-
-func (b *bottomUpMutatorContext) MutatorName() string {
- return b.bp.MutatorName()
-}
-
func (b *bottomUpMutatorContext) Rename(name string) {
b.bp.Rename(name)
b.Module().base().commonProperties.DebugName = name
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 5d4074a..33fca9e 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -134,10 +134,6 @@
return []string{"a", "b"}
},
})
- ctx.TopDown("rename_top_down", func(ctx TopDownMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed1")
- })
})
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
@@ -161,8 +157,8 @@
})
ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed2")
- })
+ ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+ }).UsesRename()
ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
moduleStrings = append(moduleStrings, ctx.Module().String())
})
@@ -181,17 +177,23 @@
"foo{pre_arch:b}",
"foo{pre_arch:a}",
- // After rename_top_down (reversed because pre_deps TransitionMutator.Split is TopDown).
- "foo_renamed1{pre_arch:b}",
- "foo_renamed1{pre_arch:a}",
-
// After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
- "foo_renamed1{pre_arch:b,pre_deps:d}",
- "foo_renamed1{pre_arch:b,pre_deps:c}",
- "foo_renamed1{pre_arch:a,pre_deps:d}",
- "foo_renamed1{pre_arch:a,pre_deps:c}",
+ "foo{pre_arch:b,pre_deps:d}",
+ "foo{pre_arch:b,pre_deps:c}",
+ "foo{pre_arch:a,pre_deps:d}",
+ "foo{pre_arch:a,pre_deps:c}",
// After post_deps.
+ "foo{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:f}",
+
+ // After rename_bottom_up.
"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
"foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
"foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
@@ -200,16 +202,6 @@
"foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
"foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
-
- // After rename_bottom_up.
- "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:e}",
- "foo_renamed2{pre_arch:a,pre_deps:c,post_deps:f}",
- "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:e}",
- "foo_renamed2{pre_arch:a,pre_deps:d,post_deps:f}",
- "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:e}",
- "foo_renamed2{pre_arch:b,pre_deps:c,post_deps:f}",
- "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:e}",
- "foo_renamed2{pre_arch:b,pre_deps:d,post_deps:f}",
}
AssertDeepEquals(t, "module String() values", want, moduleStrings)
diff --git a/android/namespace.go b/android/namespace.go
index ebf85a1..866d125 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -457,7 +457,7 @@
}
func RegisterNamespaceMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("namespace_deps", namespaceMutator).Parallel()
+ ctx.BottomUp("namespace_deps", namespaceMutator).Parallel().MutatesGlobalState()
}
func namespaceMutator(ctx BottomUpMutatorContext) {
diff --git a/android/namespace_test.go b/android/namespace_test.go
index ea51c6e..0327e78 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -646,7 +646,7 @@
ctx.RegisterModuleType("test_module", newTestModule)
ctx.Context.RegisterModuleType("blueprint_test_module", newBlueprintTestModule)
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.BottomUp("rename", renameMutator)
+ ctx.BottomUp("rename", renameMutator).UsesRename()
})
}),
)
@@ -709,9 +709,6 @@
}
func (m *testModule) DepsMutator(ctx BottomUpMutatorContext) {
- if m.properties.Rename != "" {
- ctx.Rename(m.properties.Rename)
- }
for _, d := range m.properties.Deps {
ctx.AddDependency(ctx.Module(), nil, d)
}
diff --git a/android/override_module.go b/android/override_module.go
index f69f963..d844da6 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -234,8 +234,9 @@
// Mutators for override/overridable modules. All the fun happens in these functions. It is critical
// to keep them in this order and not put any order mutators between them.
func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
+ ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel().MutatesDependencies() // modifies deps via addOverride
ctx.Transition("override", &overrideTransitionMutator{})
+ ctx.BottomUp("override_apply", overrideApplyMutator).Parallel().MutatesDependencies()
// overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
// add deps from overridable properties.
ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
@@ -243,8 +244,8 @@
// prebuilt's ReplaceDependencies doesn't affect to those deps added by overridable properties.
// By running PrebuiltPostDepsMutator again after overridableModuleDepsMutator, deps via overridable properties
// can be replaced with prebuilts.
- ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel()
- ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel()
+ ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel().UsesReplaceDependencies()
+ ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel().UsesReplaceDependencies()
}
type overrideBaseDependencyTag struct {
@@ -330,6 +331,9 @@
}
func (overrideTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+}
+
+func overrideApplyMutator(ctx BottomUpMutatorContext) {
if o, ok := ctx.Module().(OverrideModule); ok {
overridableDeps := ctx.GetDirectDepsWithTag(overrideBaseDepTag)
if len(overridableDeps) > 1 {
diff --git a/android/packaging.go b/android/packaging.go
index 0909936..3c64d56 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -15,9 +15,6 @@
package android
import (
- "bytes"
- "encoding/gob"
- "errors"
"fmt"
"path/filepath"
"sort"
@@ -67,34 +64,53 @@
owner string
}
-func (p *PackagingSpec) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.relPathInPackage), encoder.Encode(p.srcPath),
- encoder.Encode(p.symlinkTarget), encoder.Encode(p.executable),
- encoder.Encode(p.effectiveLicenseFiles), encoder.Encode(p.partition),
- encoder.Encode(p.skipInstall), encoder.Encode(p.aconfigPaths),
- encoder.Encode(p.archType))
- if err != nil {
- return nil, err
- }
+type packagingSpecGob struct {
+ RelPathInPackage string
+ SrcPath Path
+ SymlinkTarget string
+ Executable bool
+ Partition string
+ SkipInstall bool
+ AconfigPaths *Paths
+ ArchType ArchType
+ Overrides *[]string
+ Owner string
+}
- return w.Bytes(), nil
+func (p *PackagingSpec) ToGob() *packagingSpecGob {
+ return &packagingSpecGob{
+ RelPathInPackage: p.relPathInPackage,
+ SrcPath: p.srcPath,
+ SymlinkTarget: p.symlinkTarget,
+ Executable: p.executable,
+ Partition: p.partition,
+ SkipInstall: p.skipInstall,
+ AconfigPaths: p.aconfigPaths,
+ ArchType: p.archType,
+ Overrides: p.overrides,
+ Owner: p.owner,
+ }
+}
+
+func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
+ p.relPathInPackage = data.RelPathInPackage
+ p.srcPath = data.SrcPath
+ p.symlinkTarget = data.SymlinkTarget
+ p.executable = data.Executable
+ p.partition = data.Partition
+ p.skipInstall = data.SkipInstall
+ p.aconfigPaths = data.AconfigPaths
+ p.archType = data.ArchType
+ p.overrides = data.Overrides
+ p.owner = data.Owner
+}
+
+func (p *PackagingSpec) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[packagingSpecGob](p)
}
func (p *PackagingSpec) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.relPathInPackage), decoder.Decode(&p.srcPath),
- decoder.Decode(&p.symlinkTarget), decoder.Decode(&p.executable),
- decoder.Decode(&p.effectiveLicenseFiles), decoder.Decode(&p.partition),
- decoder.Decode(&p.skipInstall), decoder.Decode(&p.aconfigPaths),
- decoder.Decode(&p.archType))
- if err != nil {
- return err
- }
-
- return nil
+ return blueprint.CustomGobDecode[packagingSpecGob](data, p)
}
func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
diff --git a/android/paths.go b/android/paths.go
index 1c8258e..9c2df65 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -15,9 +15,6 @@
package android
import (
- "bytes"
- "encoding/gob"
- "errors"
"fmt"
"os"
"path/filepath"
@@ -342,6 +339,11 @@
invalidReason string // Not applicable if path != nil. "" if the reason is unknown.
}
+type optionalPathGob struct {
+ Path Path
+ InvalidReason string
+}
+
// OptionalPathForPath returns an OptionalPath containing the path.
func OptionalPathForPath(path Path) OptionalPath {
return OptionalPath{path: path}
@@ -353,6 +355,26 @@
return OptionalPath{invalidReason: reason}
}
+func (p *OptionalPath) ToGob() *optionalPathGob {
+ return &optionalPathGob{
+ Path: p.path,
+ InvalidReason: p.invalidReason,
+ }
+}
+
+func (p *OptionalPath) FromGob(data *optionalPathGob) {
+ p.path = data.Path
+ p.invalidReason = data.InvalidReason
+}
+
+func (p OptionalPath) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[optionalPathGob](&p)
+}
+
+func (p *OptionalPath) GobDecode(data []byte) error {
+ return blueprint.CustomGobDecode[optionalPathGob](data, p)
+}
+
// Valid returns whether there is a valid path
func (p OptionalPath) Valid() bool {
return p.path != nil
@@ -1065,26 +1087,29 @@
rel string
}
-func (p basePath) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.path), encoder.Encode(p.rel))
- if err != nil {
- return nil, err
- }
+type basePathGob struct {
+ Path string
+ Rel string
+}
- return w.Bytes(), nil
+func (p *basePath) ToGob() *basePathGob {
+ return &basePathGob{
+ Path: p.path,
+ Rel: p.rel,
+ }
+}
+
+func (p *basePath) FromGob(data *basePathGob) {
+ p.path = data.Path
+ p.rel = data.Rel
+}
+
+func (p basePath) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[basePathGob](&p)
}
func (p *basePath) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.path), decoder.Decode(&p.rel))
- if err != nil {
- return err
- }
-
- return nil
+ return blueprint.CustomGobDecode[basePathGob](data, p)
}
func (p basePath) Ext() string {
@@ -1337,26 +1362,32 @@
fullPath string
}
-func (p OutputPath) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.basePath), encoder.Encode(p.outDir), encoder.Encode(p.fullPath))
- if err != nil {
- return nil, err
- }
+type outputPathGob struct {
+ basePath
+ OutDir string
+ FullPath string
+}
- return w.Bytes(), nil
+func (p *OutputPath) ToGob() *outputPathGob {
+ return &outputPathGob{
+ basePath: p.basePath,
+ OutDir: p.outDir,
+ FullPath: p.fullPath,
+ }
+}
+
+func (p *OutputPath) FromGob(data *outputPathGob) {
+ p.basePath = data.basePath
+ p.outDir = data.OutDir
+ p.fullPath = data.FullPath
+}
+
+func (p OutputPath) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[outputPathGob](&p)
}
func (p *OutputPath) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.basePath), decoder.Decode(&p.outDir), decoder.Decode(&p.fullPath))
- if err != nil {
- return err
- }
-
- return nil
+ return blueprint.CustomGobDecode[outputPathGob](data, p)
}
func (p OutputPath) withRel(rel string) OutputPath {
@@ -1756,30 +1787,41 @@
fullPath string
}
-func (p *InstallPath) GobEncode() ([]byte, error) {
- w := new(bytes.Buffer)
- encoder := gob.NewEncoder(w)
- err := errors.Join(encoder.Encode(p.basePath), encoder.Encode(p.soongOutDir),
- encoder.Encode(p.partitionDir), encoder.Encode(p.partition),
- encoder.Encode(p.makePath), encoder.Encode(p.fullPath))
- if err != nil {
- return nil, err
- }
+type installPathGob struct {
+ basePath
+ SoongOutDir string
+ PartitionDir string
+ Partition string
+ MakePath bool
+ FullPath string
+}
- return w.Bytes(), nil
+func (p *InstallPath) ToGob() *installPathGob {
+ return &installPathGob{
+ basePath: p.basePath,
+ SoongOutDir: p.soongOutDir,
+ PartitionDir: p.partitionDir,
+ Partition: p.partition,
+ MakePath: p.makePath,
+ FullPath: p.fullPath,
+ }
+}
+
+func (p *InstallPath) FromGob(data *installPathGob) {
+ p.basePath = data.basePath
+ p.soongOutDir = data.SoongOutDir
+ p.partitionDir = data.PartitionDir
+ p.partition = data.Partition
+ p.makePath = data.MakePath
+ p.fullPath = data.FullPath
+}
+
+func (p InstallPath) GobEncode() ([]byte, error) {
+ return blueprint.CustomGobEncode[installPathGob](&p)
}
func (p *InstallPath) GobDecode(data []byte) error {
- r := bytes.NewBuffer(data)
- decoder := gob.NewDecoder(r)
- err := errors.Join(decoder.Decode(&p.basePath), decoder.Decode(&p.soongOutDir),
- decoder.Decode(&p.partitionDir), decoder.Decode(&p.partition),
- decoder.Decode(&p.makePath), decoder.Decode(&p.fullPath))
- if err != nil {
- return err
- }
-
- return nil
+ return blueprint.CustomGobDecode[installPathGob](data, p)
}
// Will panic if called from outside a test environment.
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 4f04d05..017ba76 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -400,13 +400,13 @@
}
func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel()
+ ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel().UsesRename()
}
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
- ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel()
+ ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel().UsesReverseDependencies()
ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
- ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
+ ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel().UsesReplaceDependencies()
}
// Returns the name of the source module corresponding to a prebuilt module
@@ -677,7 +677,7 @@
//
// Even though this is a cc_prebuilt_library_shared, we create both the variants today
// https://source.corp.google.com/h/googleplex-android/platform/build/soong/+/e08e32b45a18a77bc3c3e751f730539b1b374f1b:cc/library.go;l=2113-2116;drc=2c4a9779cd1921d0397a12b3d3521f4c9b30d747;bpv=1;bpt=0
-func (p *Prebuilt) variantIsDisabled(ctx BaseMutatorContext, prebuilt Module) bool {
+func (p *Prebuilt) variantIsDisabled(ctx BaseModuleContext, prebuilt Module) bool {
return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0
}
@@ -687,7 +687,7 @@
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
-func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool {
+func (p *Prebuilt) usePrebuilt(ctx BaseModuleContext, source Module, prebuilt Module) bool {
isMainlinePrebuilt := func(prebuilt Module) bool {
apex, ok := prebuilt.(apexVariationName)
if !ok {
diff --git a/android/provider.go b/android/provider.go
index 5ded4cc..81d17a1 100644
--- a/android/provider.go
+++ b/android/provider.go
@@ -24,7 +24,7 @@
// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
// TopDownMutatorContext.
func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
- value, ok := ctx.otherModuleProvider(module, provider)
+ value, ok := ctx.otherModuleProvider(getWrappedModule(module), provider)
if !ok {
var k K
return k, false
diff --git a/android/register.go b/android/register.go
index 2ce6025..94d875d 100644
--- a/android/register.go
+++ b/android/register.go
@@ -91,7 +91,14 @@
bottomUpMutator blueprint.BottomUpMutator
topDownMutator blueprint.TopDownMutator
transitionMutator blueprint.TransitionMutator
- parallel bool
+
+ parallel bool
+ usesRename bool
+ usesReverseDependencies bool
+ usesReplaceDependencies bool
+ usesCreateModule bool
+ mutatesDependencies bool
+ mutatesGlobalState bool
}
var _ sortableComponent = &mutator{}
diff --git a/android/variable.go b/android/variable.go
index 1aaa70a..417ba89 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -522,6 +522,10 @@
DeviceProductCompatibilityMatrixFile []string `json:",omitempty"`
PartitionVarsForSoongMigrationOnlyDoNotUse PartitionVariables
+
+ ExtraAllowedDepsTxt *string `json:",omitempty"`
+
+ AdbKeys *string `json:",omitempty"`
}
type PartitionQualifiedVariablesType struct {
diff --git a/androidmk/parser/parser_test.go b/androidmk/parser/parser_test.go
index e238f8b..21baf6b 100644
--- a/androidmk/parser/parser_test.go
+++ b/androidmk/parser/parser_test.go
@@ -142,7 +142,7 @@
t.Fatalf("Unexpected errors while parsing: %v", errs)
}
- if got[0].End() < got[len(got) -1].Pos() {
- t.Errorf("Rule's end (%d) is smaller than directive that inside of rule's start (%v)\n", got[0].End(), got[len(got) -1].Pos())
+ if got[0].End() < got[len(got)-1].Pos() {
+ t.Errorf("Rule's end (%d) is smaller than directive that inside of rule's start (%v)\n", got[0].End(), got[len(got)-1].Pos())
}
}
diff --git a/apex/apex.go b/apex/apex.go
index d7dc6d7..6bb2a1a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -29,6 +29,7 @@
"android/soong/android"
"android/soong/bpf"
"android/soong/cc"
+ "android/soong/dexpreopt"
prebuilt_etc "android/soong/etc"
"android/soong/filesystem"
"android/soong/java"
@@ -54,7 +55,7 @@
}
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+ ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel().UsesReverseDependencies()
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -66,7 +67,7 @@
// it should create a platform variant.
ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
ctx.Transition("apex", &apexTransitionMutator{})
- ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
+ ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel().MutatesDependencies()
ctx.BottomUp("apex_dcla_deps", apexDCLADepsMutator).Parallel()
}
@@ -291,7 +292,7 @@
}
// Merge combines another ApexNativeDependencies into this one
-func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
+func (a *ResolvedApexNativeDependencies) Merge(ctx android.BaseModuleContext, b ApexNativeDependencies) {
a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs.GetOrDefault(ctx, nil)...)
a.Jni_libs = append(a.Jni_libs, b.Jni_libs.GetOrDefault(ctx, nil)...)
a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
@@ -1919,6 +1920,32 @@
})
}
+// enforcePartitionTagOnApexSystemServerJar checks that the partition tags of an apex system server jar matches
+// the partition tags of the top-level apex.
+// e.g. if the top-level apex sets system_ext_specific to true, the javalib must set this property to true as well.
+// This check ensures that the dexpreopt artifacts of the apex system server jar is installed in the same partition
+// as the apex.
+func (a *apexBundle) enforcePartitionTagOnApexSystemServerJar(ctx android.ModuleContext) {
+ global := dexpreopt.GetGlobalConfig(ctx)
+ ctx.VisitDirectDepsWithTag(sscpfTag, func(child android.Module) {
+ info, ok := android.OtherModuleProvider(ctx, child, java.LibraryNameToPartitionInfoProvider)
+ if !ok {
+ ctx.ModuleErrorf("Could not find partition info of apex system server jars.")
+ }
+ apexPartition := ctx.Module().PartitionTag(ctx.DeviceConfig())
+ for javalib, javalibPartition := range info.LibraryNameToPartition {
+ if !global.AllApexSystemServerJars(ctx).ContainsJar(javalib) {
+ continue // not an apex system server jar
+ }
+ if apexPartition != javalibPartition {
+ ctx.ModuleErrorf(`
+%s is an apex systemserver jar, but its partition does not match the partition of its containing apex. Expected %s, Got %s`,
+ javalib, apexPartition, javalibPartition)
+ }
+ }
+ })
+}
+
func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent android.Module) bool {
depTag := ctx.OtherModuleDependencyTag(child)
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
@@ -2341,6 +2368,7 @@
a.required = append(a.required, a.VintfFragmentModuleNames(ctx)...)
a.setOutputFiles(ctx)
+ a.enforcePartitionTagOnApexSystemServerJar(ctx)
}
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index f405cb2..00dd446 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -18,6 +18,7 @@
import (
"encoding/json"
+ "strings"
"github.com/google/blueprint"
@@ -58,9 +59,9 @@
// Diff two given lists while ignoring comments in the allowed deps file.
diffAllowedApexDepsInfoRule = pctx.AndroidStaticRule("diffAllowedApexDepsInfoRule", blueprint.RuleParams{
- Description: "Diff ${allowed_deps} and ${new_allowed_deps}",
+ Description: "Diff ${allowed_deps_list} and ${new_allowed_deps}",
Command: `
- if grep -v '^#' ${allowed_deps} | diff -B - ${new_allowed_deps}; then
+ if grep -v -h '^#' ${allowed_deps_list} | sort -u -f| diff -B -u - ${new_allowed_deps}; then
touch ${out};
else
echo -e "\n******************************";
@@ -81,10 +82,15 @@
exit 1;
fi;
`,
- }, "allowed_deps", "new_allowed_deps")
+ }, "allowed_deps_list", "new_allowed_deps")
)
func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ allowedDepsSources := []android.OptionalPath{android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")}
+ extraAllowedDepsPath := ctx.Config().ExtraAllowedDepsTxt()
+ if extraAllowedDepsPath != "" {
+ allowedDepsSources = append(allowedDepsSources, android.ExistentPathForSource(ctx, extraAllowedDepsPath))
+ }
updatableFlatLists := android.Paths{}
ctx.VisitAllModules(func(module android.Module) {
if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
@@ -96,37 +102,42 @@
}
}
})
-
- allowedDepsSource := android.ExistentPathForSource(ctx, "packages/modules/common/build/allowed_deps.txt")
newAllowedDeps := android.PathForOutput(ctx, "apex", "depsinfo", "new-allowed-deps.txt")
s.allowedApexDepsInfoCheckResult = android.PathForOutput(ctx, newAllowedDeps.Rel()+".check")
-
- if !allowedDepsSource.Valid() {
+ hasOneValidDepsPath := false
+ for _, allowedDepsSource := range allowedDepsSources {
+ if allowedDepsSource.Valid() {
+ hasOneValidDepsPath = true
+ updatableFlatLists = append(updatableFlatLists, allowedDepsSource.Path())
+ }
+ }
+ allowedDepsStrList := make([]string, len(allowedDepsSources))
+ for _, value := range allowedDepsSources {
+ allowedDepsStrList = append(allowedDepsStrList, value.String())
+ }
+ allowedDepsListString := strings.Join(allowedDepsStrList, " ")
+ if !hasOneValidDepsPath {
// Unbundled projects may not have packages/modules/common/ checked out; ignore those.
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
Output: s.allowedApexDepsInfoCheckResult,
})
} else {
- allowedDeps := allowedDepsSource.Path()
-
ctx.Build(pctx, android.BuildParams{
Rule: generateApexDepsInfoFilesRule,
- Inputs: append(updatableFlatLists, allowedDeps),
+ Inputs: updatableFlatLists,
Output: newAllowedDeps,
})
-
ctx.Build(pctx, android.BuildParams{
Rule: diffAllowedApexDepsInfoRule,
Input: newAllowedDeps,
Output: s.allowedApexDepsInfoCheckResult,
Args: map[string]string{
- "allowed_deps": allowedDeps.String(),
- "new_allowed_deps": newAllowedDeps.String(),
+ "allowed_deps_list": allowedDepsListString,
+ "new_allowed_deps": newAllowedDeps.String(),
},
})
}
-
ctx.Phony("apex-allowed-deps-check", s.allowedApexDepsInfoCheckResult)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index da6214d..1d2f3fb 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2185,6 +2185,151 @@
flatlist, "yourlib(minSdkVersion:29)")
}
+func TestTrackCustomAllowedDepsInvalidDefaultTxt(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ native_shared_libs: [
+ "mylib",
+ "yourlib",
+ ],
+ min_sdk_version: "29",
+ }
+
+ apex {
+ name: "myapex2",
+ key: "myapex.key",
+ updatable: false,
+ native_shared_libs: ["yourlib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libbar"],
+ min_sdk_version: "29",
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stubs: { versions: ["29", "30"] },
+ }
+
+ cc_library {
+ name: "yourlib",
+ srcs: ["mylib.cpp"],
+ min_sdk_version: "29",
+ apex_available: ["myapex", "myapex2", "//apex_available:platform"],
+ }
+ `, withFiles(android.MockFS{
+ "packages/modules/common/build/custom_allowed_deps.txt": nil,
+ }),
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.ExtraAllowedDepsTxt = proptools.StringPtr("packages/modules/common/build/custom_allowed_deps.txt")
+ },
+ ))
+
+ depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+ inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
+ android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
+ android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
+
+ myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+ flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ myapex.Output("depsinfo/flatlist.txt")), "\n")
+ android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+ flatlist, "libbar(minSdkVersion:(no version)) (external)")
+ android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+ flatlist, "mylib:(minSdkVersion:29)")
+ android.AssertStringListContains(t, "track platform-available lib",
+ flatlist, "yourlib(minSdkVersion:29)")
+}
+
+func TestTrackCustomAllowedDepsWithDefaultTxt(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ native_shared_libs: [
+ "mylib",
+ "yourlib",
+ ],
+ min_sdk_version: "29",
+ }
+
+ apex {
+ name: "myapex2",
+ key: "myapex.key",
+ updatable: false,
+ native_shared_libs: ["yourlib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libbar"],
+ min_sdk_version: "29",
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stubs: { versions: ["29", "30"] },
+ }
+
+ cc_library {
+ name: "yourlib",
+ srcs: ["mylib.cpp"],
+ min_sdk_version: "29",
+ apex_available: ["myapex", "myapex2", "//apex_available:platform"],
+ }
+ `, withFiles(android.MockFS{
+ "packages/modules/common/build/custom_allowed_deps.txt": nil,
+ "packages/modules/common/build/allowed_deps.txt": nil,
+ }),
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.ExtraAllowedDepsTxt = proptools.StringPtr("packages/modules/common/build/custom_allowed_deps.txt")
+ },
+ ))
+
+ depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+ inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
+ android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
+ android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
+
+ myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+ flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ myapex.Output("depsinfo/flatlist.txt")), "\n")
+ android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+ flatlist, "libbar(minSdkVersion:(no version)) (external)")
+ android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+ flatlist, "mylib:(minSdkVersion:29)")
+ android.AssertStringListContains(t, "track platform-available lib",
+ flatlist, "yourlib(minSdkVersion:29)")
+}
+
func TestTrackAllowedDeps_SkipWithoutAllowedDepsTxt(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -11670,3 +11815,48 @@
}
`)
}
+
+// If an apex sets system_ext_specific: true, its systemserverclasspath libraries must set this property as well.
+func TestApexSSCPJarMustBeInSamePartitionAsApex(t *testing.T) {
+ testApexError(t, `foo is an apex systemserver jar, but its partition does not match the partition of its containing apex`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: [
+ "mysystemserverclasspathfragment",
+ ],
+ min_sdk_version: "29",
+ updatable: true,
+ system_ext_specific: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ min_sdk_version: "29",
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ sdk_version: "current",
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: [
+ "foo",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `,
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+ )
+}
diff --git a/cc/cc.go b/cc/cc.go
index a8ff474..1b7624d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -76,9 +76,9 @@
ctx.BottomUp("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
- ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.PostApexMutators(func(ctx android.RegisterMutatorsContext) {
// sabi mutator needs to be run after apex mutator finishes.
- ctx.TopDown("sabi_deps", sabiDepsMutator)
+ ctx.Transition("sabi", &sabiTransitionMutator{})
})
ctx.RegisterParallelSingletonType("kythe_extract_all", kytheExtractAllFactory)
diff --git a/cc/library.go b/cc/library.go
index 988d55a..988a7fa 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -548,8 +548,7 @@
return flags
}
-func (library *libraryDecorator) getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties {
- m := ctx.Module().(*Module)
+func (library *libraryDecorator) getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties {
variantProps := &library.Properties.Target.Platform.Header_abi_checker
if m.InVendor() {
variantProps = &library.Properties.Target.Vendor.Header_abi_checker
@@ -559,7 +558,7 @@
props := library.Properties.Header_abi_checker
err := proptools.AppendProperties(&props, variantProps, nil)
if err != nil {
- ctx.ModuleErrorf("Cannot merge headerAbiCheckerProperties: %s", err.Error())
+ panic(fmt.Errorf("Cannot merge headerAbiCheckerProperties: %s", err.Error()))
}
return props
}
@@ -718,7 +717,7 @@
setShared()
// Gets the ABI properties for vendor, product, or platform variant
- getHeaderAbiCheckerProperties(ctx android.BaseModuleContext) headerAbiCheckerProperties
+ getHeaderAbiCheckerProperties(m *Module) headerAbiCheckerProperties
// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
@@ -1365,7 +1364,7 @@
sourceVersion, errorMessage string) {
extraFlags := []string{"-target-version", sourceVersion}
- headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module))
if Bool(headerAbiChecker.Check_all_apis) {
extraFlags = append(extraFlags, "-check-all-apis")
} else {
@@ -1437,7 +1436,7 @@
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathDeps, objs Objects, fileName string, soFile android.Path) {
if library.sabi.shouldCreateSourceAbiDump() {
exportedIncludeDirs := library.exportedIncludeDirsForAbiCheck(ctx)
- headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module))
currSdkVersion := currRefAbiDumpSdkVersion(ctx)
currVendorVersion := ctx.Config().VendorApiLevel()
@@ -1451,7 +1450,7 @@
[]string{} /* includeSymbolTags */, currSdkVersion, false /* isLlndk */)
var llndkDump, apexVariantDump android.Path
- tags := classifySourceAbiDump(ctx)
+ tags := classifySourceAbiDump(ctx.Module().(*Module))
optInTags := []lsdumpTag{}
for _, tag := range tags {
if tag == llndkLsdumpTag && currVendorVersion != "" {
@@ -1868,7 +1867,7 @@
}
func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *string {
- if props := library.getHeaderAbiCheckerProperties(ctx); props.Symbol_file != nil {
+ if props := library.getHeaderAbiCheckerProperties(ctx.Module().(*Module)); props.Symbol_file != nil {
return props.Symbol_file
}
if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil {
diff --git a/cc/sabi.go b/cc/sabi.go
index 64eab41..2caf0d4 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -84,8 +84,8 @@
type SAbiProperties struct {
// Whether ABI dump should be created for this module.
- // Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static
- // library that is depended on by an ABI checked library.
+ // Set by `sabiTransitionMutator` if this module is a shared library that needs ABI check,
+ // or a static library that is depended on by an ABI checked library.
ShouldCreateSourceAbiDump bool `blueprint:"mutated"`
// Include directories that may contain ABI information exported by a library.
@@ -121,10 +121,9 @@
}
// Returns a slice of strings that represent the ABI dumps generated for this module.
-func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag {
+func classifySourceAbiDump(m *Module) []lsdumpTag {
result := []lsdumpTag{}
- m := ctx.Module().(*Module)
- headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
+ headerAbiChecker := m.library.getHeaderAbiCheckerProperties(m)
if headerAbiChecker.explicitlyDisabled() {
return result
}
@@ -149,24 +148,37 @@
return result
}
-// Called from sabiDepsMutator to check whether ABI dumps should be created for this module.
+type shouldCreateAbiDumpContext interface {
+ android.ModuleProviderContext
+ Module() android.Module
+ Config() android.Config
+}
+
+var _ shouldCreateAbiDumpContext = android.ModuleContext(nil)
+var _ shouldCreateAbiDumpContext = android.OutgoingTransitionContext(nil)
+
+// Called from sabiTransitionMutator to check whether ABI dumps should be created for this module.
// ctx should be wrapping a native library type module.
-func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool {
- // Only generate ABI dump for device modules.
- if !ctx.Device() {
+func shouldCreateSourceAbiDumpForLibrary(ctx shouldCreateAbiDumpContext) bool {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
return false
}
- m := ctx.Module().(*Module)
+ // Only generate ABI dump for device modules.
+ if !m.Device() {
+ return false
+ }
// Only create ABI dump for native library module types.
if m.library == nil {
return false
}
- // Create ABI dump for static libraries only if they are dependencies of ABI checked libraries.
+ // Don't create ABI dump for static libraries
+ // The sabi variant will be propagated to dependencies of ABI checked libraries.
if m.library.static() {
- return m.sabi.shouldCreateSourceAbiDump()
+ return false
}
// Module is shared library type.
@@ -215,31 +227,64 @@
return false
}
}
- return len(classifySourceAbiDump(ctx)) > 0
+ return len(classifySourceAbiDump(m)) > 0
}
// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
// of their dependencies would be generated.
-func sabiDepsMutator(mctx android.TopDownMutatorContext) {
+type sabiTransitionMutator struct{}
+
+func (s *sabiTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{""}
+}
+
+func (s *sabiTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
// Escape hatch to not check any ABI dump.
- if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
- return
+ if ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+ return ""
}
+
// Only create ABI dump for native shared libraries and their static library dependencies.
- if m, ok := mctx.Module().(*Module); ok && m.sabi != nil {
- if shouldCreateSourceAbiDumpForLibrary(mctx) {
- // Mark this module so that .sdump / .lsdump for this library can be generated.
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ if shouldCreateSourceAbiDumpForLibrary(ctx) {
+ if IsStaticDepTag(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
+ return "sabi"
+ }
+ } else if sourceVariation == "sabi" {
+ if IsWholeStaticLib(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
+ return "sabi"
+ }
+ }
+ }
+
+ return ""
+}
+
+func (s *sabiTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if incomingVariation == "" {
+ return ""
+ }
+
+ if incomingVariation == "sabi" {
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ return "sabi"
+ }
+ }
+
+ return ""
+}
+
+func (s *sabiTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
+ if variation == "sabi" {
m.sabi.Properties.ShouldCreateSourceAbiDump = true
- // Mark all of its static library dependencies.
- mctx.VisitDirectDeps(func(child android.Module) {
- depTag := mctx.OtherModuleDependencyTag(child)
- if IsStaticDepTag(depTag) || depTag == reuseObjTag {
- if c, ok := child.(*Module); ok && c.sabi != nil {
- // Mark this module so that .sdump for this static library can be generated.
- c.sabi.Properties.ShouldCreateSourceAbiDump = true
- }
- }
- })
+ m.HideFromMake()
+ m.Properties.PreventInstall = true
+ } else if shouldCreateSourceAbiDumpForLibrary(ctx) {
+ // Escape hatch to not check any ABI dump.
+ if !ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
+ m.sabi.Properties.ShouldCreateSourceAbiDump = true
+ }
}
}
}
diff --git a/cc/sabi_test.go b/cc/sabi_test.go
index 849fc36..6b8cc17 100644
--- a/cc/sabi_test.go
+++ b/cc/sabi_test.go
@@ -48,13 +48,13 @@
PrepareForTestWithCcDefaultModules,
).RunTestWithBp(t, bp)
- libsabiStatic := result.ModuleForTests("libsabi", "android_arm64_armv8-a_static")
+ libsabiStatic := result.ModuleForTests("libsabi", "android_arm64_armv8-a_static_sabi")
sabiObjSDump := libsabiStatic.Output("obj/sabi.sdump")
- libDirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static")
+ libDirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static_sabi")
directObjSDump := libDirect.Output("obj/direct.sdump")
- libTransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static")
+ libTransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static_sabi")
transitiveObjSDump := libTransitive.Output("obj/transitive.sdump")
libsabiShared := result.ModuleForTests("libsabi", "android_arm64_armv8-a_shared")
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 7f52ce1..85fdb02 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -176,7 +176,7 @@
switch t {
case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack:
sanitizer := &sanitizerSplitMutator{t}
- ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
+ ctx.BottomUp(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator).Parallel()
ctx.Transition(t.variationName(), sanitizer)
case Memtag_heap, Memtag_globals, intOverflow:
// do nothing
diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go
index adf0e62..ee71336 100644
--- a/cmd/release_config/release_config_lib/release_config.go
+++ b/cmd/release_config/release_config_lib/release_config.go
@@ -280,11 +280,28 @@
directories := []string{}
valueDirectories := []string{}
+ // These path prefixes are exclusive for a release config.
+ // "A release config shall exist in at most one of these."
+ // If we find a benefit to generalizing this, we can do so at that time.
+ exclusiveDirPrefixes := []string{
+ "build/release",
+ "vendor/google_shared/build/release",
+ }
+ var exclusiveDir string
for idx, confDir := range configs.configDirs {
if _, ok := myDirsMap[idx]; ok {
directories = append(directories, confDir)
}
if _, ok := myValueDirsMap[idx]; ok {
+ for _, dir := range exclusiveDirPrefixes {
+ if strings.HasPrefix(confDir, dir) {
+ if exclusiveDir != "" && !strings.HasPrefix(exclusiveDir, dir) {
+ return fmt.Errorf("%s is declared in both %s and %s",
+ config.Name, exclusiveDir, confDir)
+ }
+ exclusiveDir = confDir
+ }
+ }
valueDirectories = append(valueDirectories, confDir)
}
}
diff --git a/compliance/notice_test.go b/compliance/notice_test.go
index 6187e53..e8578ec 100644
--- a/compliance/notice_test.go
+++ b/compliance/notice_test.go
@@ -35,4 +35,4 @@
m := result.Module("notice_xml_system", "android_arm64_armv8-a").(*NoticeXmlModule)
android.AssertStringEquals(t, "output file", "NOTICE.xml.gz", m.outputFile.Base())
-}
\ No newline at end of file
+}
diff --git a/etc/Android.bp b/etc/Android.bp
index 580c54f..8e043b8 100644
--- a/etc/Android.bp
+++ b/etc/Android.bp
@@ -11,6 +11,7 @@
"soong-android",
],
srcs: [
+ "adb_keys.go",
"install_symlink.go",
"otacerts_zip.go",
"prebuilt_etc.go",
diff --git a/etc/adb_keys.go b/etc/adb_keys.go
new file mode 100644
index 0000000..1bce2f1
--- /dev/null
+++ b/etc/adb_keys.go
@@ -0,0 +1,66 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package etc
+
+import (
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterModuleType("adb_keys", AdbKeysModuleFactory)
+}
+
+type AdbKeysModule struct {
+ android.ModuleBase
+ outputPath android.OutputPath
+ installPath android.InstallPath
+}
+
+func AdbKeysModuleFactory() android.Module {
+ module := &AdbKeysModule{}
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+func (m *AdbKeysModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ productVariables := ctx.Config().ProductVariables()
+ if !(android.Bool(productVariables.Debuggable) && len(android.String(productVariables.AdbKeys)) > 0) {
+ m.Disable()
+ m.SkipInstall()
+ return
+ }
+
+ m.outputPath = android.PathForModuleOut(ctx, "adb_keys").OutputPath
+ input := android.ExistentPathForSource(ctx, android.String(productVariables.AdbKeys))
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: m.outputPath,
+ Input: input.Path(),
+ })
+ m.installPath = android.PathForModuleInPartitionInstall(ctx, ctx.DeviceConfig().ProductPath(), "etc/security")
+ ctx.InstallFile(m.installPath, "adb_keys", m.outputPath)
+}
+
+func (m *AdbKeysModule) AndroidMkEntries() []android.AndroidMkEntries {
+ if m.IsSkipInstall() {
+ return []android.AndroidMkEntries{}
+ }
+
+ return []android.AndroidMkEntries{
+ {
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(m.outputPath),
+ }}
+}
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 8af2ffa..608fccd 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -76,10 +76,13 @@
cmd.ImplicitOutput(outputPath)
f.appendToEntry(ctx, outputPath)
}
- generatePartitionAconfigStorageFile("package_map", "package.map")
- generatePartitionAconfigStorageFile("flag_map", "flag.map")
- generatePartitionAconfigStorageFile("flag_val", "flag.val")
- generatePartitionAconfigStorageFile("flag_info", "flag.info")
+
+ if ctx.Config().ReleaseCreateAconfigStorageFile() {
+ generatePartitionAconfigStorageFile("package_map", "package.map")
+ generatePartitionAconfigStorageFile("flag_map", "flag.map")
+ generatePartitionAconfigStorageFile("flag_val", "flag.val")
+ generatePartitionAconfigStorageFile("flag_info", "flag.info")
+ }
android.WriteExecutableFileRuleVerbatim(ctx, aconfigFlagsBuilderPath, sb.String())
}
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index eb4f318..a9f4256 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -161,16 +161,16 @@
makeFileList := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partitionType))
// For now, don't allowlist anything. The test will fail, but that's fine in the current
// early stages where we're just figuring out what we need
- emptyAllowlistFile := android.PathForModuleOut(ctx, "allowlist_%s.txt", partitionModuleName)
+ emptyAllowlistFile := android.PathForModuleOut(ctx, fmt.Sprintf("allowlist_%s.txt", partitionModuleName))
android.WriteFileRule(ctx, emptyAllowlistFile, "")
- diffTestResultFile := android.PathForModuleOut(ctx, "diff_test_%s.txt", partitionModuleName)
+ diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", partitionModuleName))
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().BuiltTool("file_list_diff").
Input(makeFileList).
Input(filesystemInfo.FileListFile).
- Input(emptyAllowlistFile).
- Text(partitionModuleName)
+ Text(partitionModuleName).
+ FlagWithInput("--allowlists ", emptyAllowlistFile)
builder.Command().Text("touch").Output(diffTestResultFile)
builder.Build(partitionModuleName+" diff test", partitionModuleName+" diff test")
return diffTestResultFile
diff --git a/genrule/genrule.go b/genrule/genrule.go
index e5222a4..18ec0a4 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -139,8 +139,7 @@
Export_include_dirs []string
// list of input files
- Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
- ResolvedSrcs []string `blueprint:"mutated"`
+ Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
// input files to exclude
Exclude_srcs []string `android:"path,arch_variant"`
@@ -426,8 +425,8 @@
}
return srcFiles
}
- g.properties.ResolvedSrcs = g.properties.Srcs.GetOrDefault(ctx, nil)
- srcFiles := addLabelsForInputs("srcs", g.properties.ResolvedSrcs, g.properties.Exclude_srcs)
+ srcs := g.properties.Srcs.GetOrDefault(ctx, nil)
+ srcFiles := addLabelsForInputs("srcs", srcs, g.properties.Exclude_srcs)
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
var copyFrom android.Paths
@@ -659,7 +658,7 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (g *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
dpInfo.Srcs = append(dpInfo.Srcs, g.Srcs().Strings()...)
- for _, src := range g.properties.ResolvedSrcs {
+ for _, src := range g.properties.Srcs.GetOrDefault(ctx, nil) {
if strings.HasPrefix(src, ":") {
src = strings.Trim(src, ":")
dpInfo.Deps = append(dpInfo.Deps, src)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 9278f15..f190750 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -24,6 +24,7 @@
"android/soong/android"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -694,8 +695,12 @@
expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
+ srcsFileProvider, ok := android.OtherModuleProvider(result.TestContext, gen, blueprint.SrcsFileProviderKey)
+ if !ok {
+ t.Fatal("Expected genrule to have a SrcsFileProviderData, but did not")
+ }
expectedSrcs := []string{"in1"}
- android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.ResolvedSrcs)
+ android.AssertDeepEquals(t, "srcs", expectedSrcs, srcsFileProvider.SrcPaths)
}
func TestGenruleAllowMissingDependencies(t *testing.T) {
diff --git a/golang/golang.go b/golang/golang.go
index 618a085..6ee924f 100644
--- a/golang/golang.go
+++ b/golang/golang.go
@@ -22,6 +22,7 @@
import (
"android/soong/android"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
)
@@ -46,7 +47,7 @@
func goPackageModuleFactory() android.Module {
module := &GoPackage{}
module.AddProperties(module.Properties()...)
- android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst)
return module
}
diff --git a/golang/golang_test.go b/golang/golang_test.go
index b512144..b909f59 100644
--- a/golang/golang_test.go
+++ b/golang/golang_test.go
@@ -39,7 +39,7 @@
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
RegisterGoModuleTypes(ctx)
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps)
+ ctx.BottomUpBlueprint("bootstrap_deps", bootstrap.BootstrapDeps).UsesReverseDependencies()
})
}),
).RunTestWithBp(t, bp)
diff --git a/java/aar.go b/java/aar.go
index 7d73b03..41cc24a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -483,9 +483,9 @@
}
linkFlags = append(linkFlags, "--no-static-lib-packages")
- if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
- // When building an android_library using ResourceProcessorBusyBox pass --merge-only to skip resource
- // references validation until the final app link step when all static libraries are present.
+ if a.isLibrary {
+ // Pass --merge-only to skip resource references validation until the final
+ // app link step when when all static libraries are present.
linkFlags = append(linkFlags, "--merge-only")
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 0539d25..2dff6cd 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -313,6 +313,7 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_STRIP_MODULE", false)
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", binary.androidMkNamesOfJniLibs...)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
diff --git a/java/base.go b/java/base.go
index fc21c44..a9399cb 100644
--- a/java/base.go
+++ b/java/base.go
@@ -1628,7 +1628,7 @@
if j.ravenizer.enabled {
ravenizerInput := outputFile
- ravenizerOutput := android.PathForModuleOut(ctx, "ravenizer", jarName)
+ ravenizerOutput := android.PathForModuleOut(ctx, "ravenizer", "", jarName)
ravenizerArgs := ""
if proptools.Bool(j.properties.Ravenizer.Strip_mockito) {
ravenizerArgs = "--strip-mockito"
@@ -1637,6 +1637,14 @@
outputFile = ravenizerOutput
localImplementationJars = android.Paths{ravenizerOutput}
completeStaticLibsImplementationJars = android.NewDepSet(android.PREORDER, localImplementationJars, nil)
+ if combinedResourceJar != nil {
+ ravenizerInput = combinedResourceJar
+ ravenizerOutput = android.PathForModuleOut(ctx, "ravenizer", "resources", jarName)
+ TransformRavenizer(ctx, ravenizerOutput, ravenizerInput, ravenizerArgs)
+ combinedResourceJar = ravenizerOutput
+ localResourceJars = android.Paths{ravenizerOutput}
+ completeStaticLibsResourceJars = android.NewDepSet(android.PREORDER, localResourceJars, nil)
+ }
}
if j.shouldApiMapper() {
@@ -2164,16 +2172,14 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (j *Module) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
- // jarjar rules will repackage the sources. To prevent misleading results, IdeInfo should contain the
- // repackaged jar instead of the input sources.
if j.expandJarjarRules != nil {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
+ // Add the header jar so that the rdeps can be resolved to the repackaged classes.
dpInfo.Jars = append(dpInfo.Jars, j.headerJarFile.String())
- } else {
- dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
- dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
}
+ dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
dpInfo.Static_libs = append(dpInfo.Static_libs, j.staticLibs(ctx)...)
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index 1cca7ad..da86540 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -41,10 +41,50 @@
is_stubs_module: true,
}
+soong_config_module_type {
+ name: "core_current_stubs_soong_config_defaults",
+ module_type: "java_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "release_hidden_api_exportable_stubs",
+ ],
+ properties: [
+ "dist.targets",
+ "dist.dest",
+ ],
+}
+
+core_current_stubs_soong_config_defaults {
+ name: "core_current_stubs_everything_soong_config_defaults",
+ soong_config_variables: {
+ release_hidden_api_exportable_stubs: {
+ conditions_default: {
+ dist: {
+ targets: dist_targets,
+ dest: "core.current.stubs.jar",
+ },
+ },
+ },
+ },
+}
+
+core_current_stubs_soong_config_defaults {
+ name: "core_current_stubs_exportable_soong_config_defaults",
+ soong_config_variables: {
+ release_hidden_api_exportable_stubs: {
+ dist: {
+ targets: dist_targets,
+ dest: "core.current.stubs.jar",
+ },
+ },
+ },
+}
+
java_library {
name: "core.current.stubs",
defaults: [
"core.current.stubs.defaults",
+ "core_current_stubs_everything_soong_config_defaults",
],
static_libs: [
"art.module.public.api.stubs",
@@ -76,16 +116,13 @@
name: "core.current.stubs.exportable",
defaults: [
"core.current.stubs.defaults",
+ "core_current_stubs_exportable_soong_config_defaults",
],
static_libs: [
"art.module.public.api.stubs.exportable",
"conscrypt.module.public.api.stubs.exportable",
"i18n.module.public.api.stubs.exportable",
],
- dist: {
- targets: dist_targets,
- dest: "core.current.stubs.jar",
- },
}
// Distributed with the SDK for turning into system modules to compile apps
diff --git a/java/java.go b/java/java.go
index 661422b..018850f 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1795,8 +1795,7 @@
// Name of the class containing main to be inserted into the manifest as Main-Class.
Main_class *string
- // Names of modules containing JNI libraries that should be installed alongside the host
- // variant of the binary.
+ // Names of modules containing JNI libraries that should be installed alongside the binary.
Jni_libs []string `android:"arch_variant"`
}
@@ -1809,6 +1808,8 @@
wrapperFile android.Path
binaryFile android.InstallPath
+
+ androidMkNamesOfJniLibs []string
}
func (j *Binary) HostToolPath() android.OptionalPath {
@@ -1880,6 +1881,21 @@
ctx.ModuleName()+ext, j.wrapperFile)
setOutputFiles(ctx, j.Library.Module)
+
+ // Set the jniLibs of this binary.
+ // These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will
+ // install these alongside the java binary.
+ ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) {
+ // Use the BaseModuleName of the dependency (without any prebuilt_ prefix)
+ bmn, _ := jni.(interface{ BaseModuleName() string })
+ j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness())
+ })
+ // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead.
+ ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo {
+ ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name())
+ }
+ })
}
}
@@ -1888,11 +1904,9 @@
j.deps(ctx)
}
// These dependencies ensure the installation rules will install the jar file when the
- // wrapper is installed, and the jni libraries on host when the wrapper is installed.
- if ctx.Arch().ArchType != android.Common && ctx.Os().Class == android.Host {
- ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
- }
+ // wrapper is installed, and the jni libraries when the wrapper is installed.
if ctx.Arch().ArchType != android.Common {
+ ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
ctx.AddVariationDependencies(
[]blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
binaryInstallTag, ctx.ModuleName())
diff --git a/java/java_test.go b/java/java_test.go
index db154ce..24dabdb1 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -3102,7 +3102,7 @@
}
}
-// Test that a dependency edge is created to the "first" variant of a native library listed in `required` of java_binary
+// Test that a dependency edge is created to the matching variant of a native library listed in `jni_libs` of java_binary
func TestNativeRequiredDepOfJavaBinary(t *testing.T) {
findDepsOfModule := func(ctx *android.TestContext, module android.Module, depName string) []blueprint.Module {
var ret []blueprint.Module
@@ -3118,7 +3118,7 @@
java_binary {
name: "myjavabin",
main_class: "com.android.MyJava",
- required: ["mynativelib"],
+ jni_libs: ["mynativelib"],
}
cc_library_shared {
name: "mynativelib",
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index d282f19..7a0fb10 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -109,7 +109,7 @@
module := ctx.ModuleForTests("javalib", "android_common").Module().(*Library)
dpInfo, _ := android.OtherModuleProvider(ctx, module, android.IdeInfoProviderKey)
- android.AssertBoolEquals(t, "IdeInfo.Srcs of repackaged library should be empty", true, len(dpInfo.Srcs) == 0)
+ android.AssertStringEquals(t, "IdeInfo.Srcs of repackaged library should not be empty", "foo.java", dpInfo.Srcs[0])
android.AssertStringEquals(t, "IdeInfo.Jar_rules of repackaged library should not be empty", "jarjar_rules.txt", dpInfo.Jarjar_rules[0])
if !android.SubstringInList(dpInfo.Jars, "soong/.intermediates/javalib/android_common/jarjar/turbine/javalib.jar") {
t.Errorf("IdeInfo.Jars of repackaged library should contain the output of jarjar-ing. All outputs: %v\n", dpInfo.Jars)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index f308772..dfbde0e 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2481,19 +2481,3 @@
propertySet.AddProperty("doctag_files", dests)
}
}
-
-// TODO(b/358613520): This can be removed when modules are no longer allowed to depend on the top-level library.
-func (s *SdkLibrary) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
- s.Library.IDEInfo(ctx, dpInfo)
- if s.implLibraryModule != nil {
- dpInfo.Deps = append(dpInfo.Deps, s.implLibraryModule.Name())
- } else {
- // This java_sdk_library does not have an implementation (it sets `api_only` to true).
- // Examples of this are `art.module.intra.core.api` (IntraCore api surface).
- // Return the "public" stubs for these.
- stubPaths := s.findClosestScopePath(apiScopePublic)
- if len(stubPaths.stubsHeaderPath) > 0 {
- dpInfo.Jars = append(dpInfo.Jars, stubPaths.stubsHeaderPath[0].String())
- }
- }
-}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 924abd4..aad1060 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -127,6 +127,26 @@
configuredJars = configuredJars.AppendList(&standaloneConfiguredJars)
classpathJars = append(classpathJars, standaloneClasspathJars...)
s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
+ s.setPartitionInfoOfLibraries(ctx)
+}
+
+// Map of java library name to their install partition.
+type LibraryNameToPartitionInfo struct {
+ LibraryNameToPartition map[string]string
+}
+
+// LibraryNameToPartitionInfoProvider will be used by the top-level apex to enforce that dexpreopt files
+// of apex system server jars are installed in the same partition as the top-level apex.
+var LibraryNameToPartitionInfoProvider = blueprint.NewProvider[LibraryNameToPartitionInfo]()
+
+func (s *SystemServerClasspathModule) setPartitionInfoOfLibraries(ctx android.ModuleContext) {
+ libraryNameToPartition := map[string]string{}
+ ctx.VisitDirectDepsWithTag(systemServerClasspathFragmentContentDepTag, func(m android.Module) {
+ libraryNameToPartition[m.Name()] = m.PartitionTag(ctx.DeviceConfig())
+ })
+ android.SetProvider(ctx, LibraryNameToPartitionInfoProvider, LibraryNameToPartitionInfo{
+ LibraryNameToPartition: libraryNameToPartition,
+ })
}
func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
diff --git a/rust/compiler.go b/rust/compiler.go
index 5bce16b..fd86917 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -154,7 +154,7 @@
// list of rust automatic crate dependencies.
// Rustlibs linkage is rlib for host targets and dylib for device targets.
- Rustlibs []string `android:"arch_variant"`
+ Rustlibs proptools.Configurable[[]string] `android:"arch_variant"`
// list of rust proc_macro crate dependencies
Proc_macros []string `android:"arch_variant"`
@@ -497,7 +497,7 @@
func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
- deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...)
+ deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs.GetOrDefault(ctx, nil)...)
deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...)
diff --git a/rust/rust.go b/rust/rust.go
index 5602edc..a044a99 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1756,6 +1756,16 @@
var _ android.ApexModule = (*Module)(nil)
+// If a module is marked for exclusion from apexes, don't provide apex variants.
+// TODO(b/362509506): remove this once stubs are properly supported by rust_ffi targets.
+func (m *Module) CanHaveApexVariants() bool {
+ if m.ApexExclude() {
+ return false
+ } else {
+ return m.ApexModuleBase.CanHaveApexVariants()
+ }
+}
+
func (mod *Module) MinSdkVersion() string {
return String(mod.Properties.Min_sdk_version)
}