diff options
69 files changed, 1666 insertions, 448 deletions
diff --git a/aconfig/build_flags/build_flags_singleton.go b/aconfig/build_flags/build_flags_singleton.go index ba27a8515..3b407556f 100644 --- a/aconfig/build_flags/build_flags_singleton.go +++ b/aconfig/build_flags/build_flags_singleton.go @@ -114,7 +114,7 @@ func (this *allBuildFlagDeclarationsSingleton) GenerateBuildActions(ctx android. func (this *allBuildFlagDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) { ctx.DistForGoal("droid", this.flagsBinaryProtoPath) - for _, goal := range []string{"docs", "droid", "sdk"} { + for _, goal := range []string{"docs", "droid", "sdk", "release_config_metadata"} { ctx.DistForGoalWithFilename(goal, this.flagsBinaryProtoPath, "build_flags/all_flags.pb") ctx.DistForGoalWithFilename(goal, this.flagsTextProtoPath, "build_flags/all_flags.textproto") ctx.DistForGoalWithFilename(goal, this.configsBinaryProtoPath, "build_flags/all_release_config_contributions.pb") diff --git a/android/Android.bp b/android/Android.bp index c2bef0bfe..eb8c64d85 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -71,6 +71,7 @@ bootstrap_go_package { "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 1ec971d15..e2d0d0dbb 100644 --- a/android/arch.go +++ b/android/arch.go @@ -1369,7 +1369,7 @@ func GetCompoundTargetField(os OsType, arch ArchType) string { // 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 c7d7573f1..670537fb5 100644 --- a/android/base_module_context.go +++ b/android/base_module_context.go @@ -33,6 +33,8 @@ type BaseModuleContext interface { 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 @@ type BaseModuleContext interface { // 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 @@ type BaseModuleContext interface { // 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 @@ type baseModuleContext struct { } +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) VisitDirectDepsAllowDisabled(visit func(Module)) { }) } +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) WalkDeps(visit func(Module, Module) bool) { }) } +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 38f138237..d28831e62 100644 --- a/android/compliance_metadata.go +++ b/android/compliance_metadata.go @@ -17,7 +17,6 @@ package android import ( "bytes" "encoding/csv" - "encoding/gob" "fmt" "slices" "strconv" @@ -126,32 +125,32 @@ type ComplianceMetadataInfo struct { 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) GobDecode(data []byte) error { - r := bytes.NewBuffer(data) - decoder := gob.NewDecoder(r) - err := decoder.Decode(&c.properties) - if err != nil { - return err - } +func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[complianceMetadataInfoGob](c) +} - return nil +func (c *ComplianceMetadataInfo) GobDecode(data []byte) error { + 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 10e43cee9..06d71c06d 100644 --- a/android/config.go +++ b/android/config.go @@ -287,6 +287,10 @@ func (c Config) ReleaseReadFromNewStorage() bool { 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 @@ func (c *config) OdmPropFiles(ctx PathContext) Paths { 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) } @@ -2105,3 +2113,10 @@ func (c *config) BoardAvbEnable() bool { func (c *config) BoardAvbSystemAddHashtreeFooterArgs() []string { return c.productVariables.BoardAvbSystemAddHashtreeFooterArgs } + +// Returns true if RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION is set to true. +// If true, dexpreopt files of apex system server jars will be installed in the same partition as the parent apex. +// If false, all these files will be installed in /system partition. +func (c Config) InstallApexSystemServerDexpreoptSamePartition() bool { + return c.config.productVariables.GetBuildFlagBool("RELEASE_INSTALL_APEX_SYSTEMSERVER_DEXPREOPT_SAME_PARTITION") +} diff --git a/android/defaults.go b/android/defaults.go index 3d06c69c9..8fe28796e 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -274,7 +274,7 @@ func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx BottomUpMut 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 690987a0c..d04f88b5b 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 @@ type DepSet[T depSettableType] struct { 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] +} + +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, } +} - return w.Bytes(), nil +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]) 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 - } +func (d *DepSet[T]) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[depSetGob[T]](d) +} - return nil +func (d *DepSet[T]) GobDecode(data []byte) error { + 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 11de77146..9b1a9ea7e 100644 --- a/android/early_module_context.go +++ b/android/early_module_context.go @@ -29,7 +29,7 @@ type EarlyModuleContext interface { 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 b46229282..1ace34494 100644 --- a/android/init.go +++ b/android/init.go @@ -17,7 +17,12 @@ package android 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 20caae2d8..44f7583a2 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" @@ -81,6 +78,7 @@ type Module interface { InstallInOdm() bool InstallInProduct() bool InstallInVendor() bool + InstallInSystemExt() bool InstallForceOS() (*OsType, *ArchType) PartitionTag(DeviceConfig) string HideFromMake() @@ -1005,14 +1003,6 @@ func addRequiredDeps(ctx BottomUpMutatorContext) { 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) @@ -1514,6 +1504,10 @@ func (m *ModuleBase) InstallInVendor() bool { return Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Soc_specific) || Bool(m.commonProperties.Proprietary) } +func (m *ModuleBase) InstallInSystemExt() bool { + return Bool(m.commonProperties.System_ext_specific) +} + func (m *ModuleBase) InstallInRoot() bool { return false } @@ -1801,6 +1795,26 @@ type FinalModuleBuildTargetsInfo struct { 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, @@ -2046,6 +2060,23 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) }) } 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)) { @@ -2125,36 +2156,47 @@ type katiInstall struct { orderOnlyDeps Paths executable bool extraFiles *extraFilesZip + absFrom string +} - absFrom string +type katiInstallGob struct { + From Path + To InstallPath + ImplicitDeps Paths + OrderOnlyDeps Paths + Executable bool + ExtraFiles *extraFilesZip + 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 +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 w.Bytes(), 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 (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) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[katiInstallGob](k) +} - return nil +func (k *katiInstall) GobDecode(data []byte) error { + return blueprint.CustomGobDecode[katiInstallGob](data, k) } type extraFilesZip struct { @@ -2162,26 +2204,29 @@ type extraFilesZip struct { 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 +type extraFilesZipGob struct { + Zip Path + Dir InstallPath +} + +func (e *extraFilesZip) ToGob() *extraFilesZipGob { + return &extraFilesZipGob{ + Zip: e.zip, + Dir: e.dir, } +} - return w.Bytes(), nil +func (e *extraFilesZip) FromGob(data *extraFilesZipGob) { + e.zip = data.Zip + e.dir = data.Dir } -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) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[extraFilesZipGob](e) +} - return nil +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 000000000..bc5090ecb --- /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 a8b5c7db6..0da3ec7d0 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -32,11 +32,11 @@ import ( // collateGloballyRegisteredMutators constructs the list of mutators that have been registered // with the InitRegistrationContext and will be used at runtime. func collateGloballyRegisteredMutators() sortableComponents { - return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps) + return collateRegisteredMutators(preArch, preDeps, postDeps, postApex, finalDeps) } // collateRegisteredMutators constructs a single list of mutators from the separate lists. -func collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) sortableComponents { +func collateRegisteredMutators(preArch, preDeps, postDeps, postApex, finalDeps []RegisterMutatorFunc) sortableComponents { mctx := ®isterMutatorsContext{} register := func(funcs []RegisterMutatorFunc) { @@ -53,6 +53,8 @@ func collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps []RegisterM register(postDeps) + register(postApex) + mctx.finalPhase = true register(finalDeps) @@ -166,6 +168,8 @@ var postDeps = []RegisterMutatorFunc{ RegisterOverridePostDepsMutators, } +var postApex = []RegisterMutatorFunc{} + var finalDeps = []RegisterMutatorFunc{} func PreArchMutators(f RegisterMutatorFunc) { @@ -180,29 +184,18 @@ func PostDepsMutators(f RegisterMutatorFunc) { postDeps = append(postDeps, f) } -func FinalDepsMutators(f RegisterMutatorFunc) { - finalDeps = append(finalDeps, f) +func PostApexMutators(f RegisterMutatorFunc) { + postApex = append(postApex, 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 +func FinalDepsMutators(f RegisterMutatorFunc) { + finalDeps = append(finalDeps, f) } type TopDownMutator func(TopDownMutatorContext) type TopDownMutatorContext interface { - BaseMutatorContext + BaseModuleContext } type topDownMutatorContext struct { @@ -213,7 +206,7 @@ type topDownMutatorContext struct { 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). @@ -228,7 +221,8 @@ type BottomUpMutatorContext interface { // 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 @@ -242,14 +236,15 @@ type BottomUpMutatorContext interface { // 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 @@ -269,14 +264,26 @@ type BottomUpMutatorContext interface { // 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 @@ -619,13 +626,60 @@ func (mutator *mutator) register(ctx *Context) { } 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 { @@ -633,6 +687,36 @@ func (mutator *mutator) Parallel() MutatorHandle { 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() } @@ -652,7 +736,7 @@ func depsMutator(ctx BottomUpMutatorContext) { } 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 @@ -661,32 +745,6 @@ func registerDepsMutator(ctx RegisterMutatorsContext) { // 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 5d4074a54..33fca9e8b 100644 --- a/android/mutator_test.go +++ b/android/mutator_test.go @@ -134,10 +134,6 @@ func TestModuleString(t *testing.T) { 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 @@ func TestModuleString(t *testing.T) { }) 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 @@ func TestModuleString(t *testing.T) { "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 @@ func TestModuleString(t *testing.T) { "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 ebf85a1fd..866d12594 100644 --- a/android/namespace.go +++ b/android/namespace.go @@ -457,7 +457,7 @@ func NamespaceFactory() Module { } 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 ea51c6eae..0327e7824 100644 --- a/android/namespace_test.go +++ b/android/namespace_test.go @@ -646,7 +646,7 @@ var prepareForTestWithNamespace = GroupFixturePreparers( 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 @@ type testModule struct { } 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 f69f96309..d844da616 100644 --- a/android/override_module.go +++ b/android/override_module.go @@ -234,8 +234,9 @@ func (b *OverridableModuleBase) OverridablePropertiesDepsMutator(ctx BottomUpMut // 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 @@ func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) { // 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) IncomingTransition(ctx IncomingTransitionContex } 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 0909936c6..3c64d56f0 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 @@ type PackagingSpec struct { 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 +} + +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, } +} - return w.Bytes(), nil +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) 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 - } +func (p *PackagingSpec) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[packagingSpecGob](p) +} - return nil +func (p *PackagingSpec) GobDecode(data []byte) error { + return blueprint.CustomGobDecode[packagingSpecGob](data, p) } func (p *PackagingSpec) Equals(other *PackagingSpec) bool { diff --git a/android/paths.go b/android/paths.go index 1c8258ede..9c2df6589 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 @@ type OptionalPath struct { 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 @@ func InvalidOptionalPath(reason string) OptionalPath { 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 @@ type basePath struct { 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 +} + +func (p *basePath) ToGob() *basePathGob { + return &basePathGob{ + Path: p.path, + Rel: p.rel, } +} - return w.Bytes(), nil +func (p *basePath) FromGob(data *basePathGob) { + p.path = data.Path + p.rel = data.Rel } -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 - } +func (p basePath) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[basePathGob](&p) +} - return nil +func (p *basePath) GobDecode(data []byte) error { + return blueprint.CustomGobDecode[basePathGob](data, p) } func (p basePath) Ext() string { @@ -1337,26 +1362,32 @@ type OutputPath struct { 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 +} + +func (p *OutputPath) ToGob() *outputPathGob { + return &outputPathGob{ + basePath: p.basePath, + OutDir: p.outDir, + FullPath: p.fullPath, } +} - return w.Bytes(), nil +func (p *OutputPath) FromGob(data *outputPathGob) { + p.basePath = data.basePath + p.outDir = data.OutDir + p.fullPath = data.FullPath } -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 - } +func (p OutputPath) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[outputPathGob](&p) +} - return nil +func (p *OutputPath) GobDecode(data []byte) error { + return blueprint.CustomGobDecode[outputPathGob](data, p) } func (p OutputPath) withRel(rel string) OutputPath { @@ -1756,30 +1787,41 @@ type InstallPath struct { 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 +} + +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, } +} - return w.Bytes(), nil +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) 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 - } +func (p InstallPath) GobEncode() ([]byte, error) { + return blueprint.CustomGobEncode[installPathGob](&p) +} - return nil +func (p *InstallPath) GobDecode(data []byte) error { + 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 4f04d057b..017ba76c3 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -400,13 +400,13 @@ func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module { } 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 @@ type createdByJavaSdkLibraryName interface { // // 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 @@ type apexVariationName interface { // 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 5ded4cc14..81d17a175 100644 --- a/android/provider.go +++ b/android/provider.go @@ -24,7 +24,7 @@ var _ OtherModuleProviderContext = (*TestContext)(nil) // 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 eb6a35e05..94d875d19 100644 --- a/android/register.go +++ b/android/register.go @@ -91,7 +91,14 @@ type mutator struct { 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{} @@ -235,6 +242,7 @@ type RegistrationContext interface { PreDepsMutators(f RegisterMutatorFunc) PostDepsMutators(f RegisterMutatorFunc) + PostApexMutators(f RegisterMutatorFunc) FinalDepsMutators(f RegisterMutatorFunc) } @@ -326,6 +334,10 @@ func (ctx *initRegistrationContext) PostDepsMutators(f RegisterMutatorFunc) { PostDepsMutators(f) } +func (ctx *initRegistrationContext) PostApexMutators(f RegisterMutatorFunc) { + PostApexMutators(f) +} + func (ctx *initRegistrationContext) FinalDepsMutators(f RegisterMutatorFunc) { FinalDepsMutators(f) } diff --git a/android/testing.go b/android/testing.go index 196b22e3e..7440869f3 100644 --- a/android/testing.go +++ b/android/testing.go @@ -197,8 +197,8 @@ func NewTestArchContext(config Config) *TestContext { type TestContext struct { *Context - preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc - NameResolver *NameResolver + preArch, preDeps, postDeps, postApex, finalDeps []RegisterMutatorFunc + NameResolver *NameResolver // The list of singletons registered for the test. singletons sortableComponents @@ -229,6 +229,10 @@ func (ctx *TestContext) PostDepsMutators(f RegisterMutatorFunc) { ctx.postDeps = append(ctx.postDeps, f) } +func (ctx *TestContext) PostApexMutators(f RegisterMutatorFunc) { + ctx.postApex = append(ctx.postApex, f) +} + func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) { ctx.finalDeps = append(ctx.finalDeps, f) } @@ -449,7 +453,7 @@ func globallyRegisteredComponentsOrder() *registrationSorter { func (ctx *TestContext) Register() { globalOrder := globallyRegisteredComponentsOrder() - mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps) + mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.postApex, ctx.finalDeps) // Ensure that the mutators used in the test are in the same order as they are used at runtime. globalOrder.mutatorOrder.enforceOrdering(mutators) mutators.registerAll(ctx.Context) diff --git a/android/variable.go b/android/variable.go index 1aaa70a0e..417ba8978 100644 --- a/android/variable.go +++ b/android/variable.go @@ -522,6 +522,10 @@ type ProductVariables struct { 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 e238f8b11..21baf6bf9 100644 --- a/androidmk/parser/parser_test.go +++ b/androidmk/parser/parser_test.go @@ -142,7 +142,7 @@ endif 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 d7dc6d718..6bb2a1a5b 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -29,6 +29,7 @@ import ( "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 registerApexBuildComponents(ctx android.RegistrationContext) { } 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 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { // 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 @@ type ResolvedApexNativeDependencies struct { } // 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 @@ func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) { }) } +// 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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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 f405cb2fe..00dd44648 100644 --- a/apex/apex_singleton.go +++ b/apex/apex_singleton.go @@ -18,6 +18,7 @@ package apex import ( "encoding/json" + "strings" "github.com/google/blueprint" @@ -58,9 +59,9 @@ var ( // 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 @@ var ( 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 @@ func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContex } } }) - - 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 da6214db3..1d2f3fb9d 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -2185,6 +2185,151 @@ func TestTrackAllowedDeps(t *testing.T) { 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 @@ func TestSdkLibraryTransitiveClassLoaderContext(t *testing.T) { } `) } + +// 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/Android.bp b/cc/Android.bp index 3688c8a9a..88a793cd8 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -102,6 +102,7 @@ bootstrap_go_package { "orderfile_test.go", "prebuilt_test.go", "proto_test.go", + "sabi_test.go", "sanitize_test.go", "sdk_test.go", "test_data_test.go", @@ -76,9 +76,9 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { 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/compiler.go b/cc/compiler.go index a6f623f5b..022b712e9 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -228,9 +228,6 @@ type BaseCompilerProperties struct { Static *bool `android:"arch_variant"` } `android:"arch_variant"` - // Stores the original list of source files before being cleared by library reuse - OriginalSrcs proptools.Configurable[[]string] `blueprint:"mutated"` - // Build and link with OpenMP Openmp *bool `android:"arch_variant"` } @@ -363,10 +360,20 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps tc := ctx.toolchain() modulePath := ctx.ModuleDir() - srcs := compiler.Properties.Srcs.GetOrDefault(ctx, nil) - exclude_srcs := compiler.Properties.Exclude_srcs.GetOrDefault(ctx, nil) - compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs) - compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...) + reuseObjs := false + if len(ctx.GetDirectDepsWithTag(reuseObjTag)) > 0 { + reuseObjs = true + } + + // If a reuseObjTag dependency exists then this module is reusing the objects (generally the shared variant + // reusing objects from the static variant), and doesn't need to compile any sources of its own. + var srcs []string + if !reuseObjs { + srcs = compiler.Properties.Srcs.GetOrDefault(ctx, nil) + exclude_srcs := compiler.Properties.Exclude_srcs.GetOrDefault(ctx, nil) + compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, srcs, exclude_srcs) + compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...) + } cflags := compiler.Properties.Cflags.GetOrDefault(ctx, nil) cppflags := compiler.Properties.Cppflags.GetOrDefault(ctx, nil) @@ -721,11 +728,6 @@ func (compiler *baseCompiler) hasSrcExt(ctx BaseModuleContext, ext string) bool return true } } - for _, src := range compiler.Properties.OriginalSrcs.GetOrDefault(ctx, nil) { - if filepath.Ext(src) == ext { - return true - } - } return false } diff --git a/cc/library.go b/cc/library.go index 3833b9846..988a7fa0b 100644 --- a/cc/library.go +++ b/cc/library.go @@ -548,8 +548,7 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags, d 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 @@ func (library *libraryDecorator) getHeaderAbiCheckerProperties(ctx android.BaseM 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 @@ type libraryInterface interface { 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 @@ func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext, 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) optInAbiDiff(ctx android.ModuleContext, 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 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathD []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) buildStubs() bool { } 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 { @@ -2071,12 +2070,7 @@ func reuseStaticLibrary(ctx android.BottomUpMutatorContext, shared *Module) { sharedCompiler.StaticProperties.Static.System_shared_libs == nil && sharedCompiler.SharedProperties.Shared.System_shared_libs == nil { - // TODO: namespaces? ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, reuseObjTag, ctx.ModuleName()) - sharedCompiler.baseCompiler.Properties.OriginalSrcs = - sharedCompiler.baseCompiler.Properties.Srcs - sharedCompiler.baseCompiler.Properties.Srcs = proptools.NewConfigurable[[]string](nil, nil) - sharedCompiler.baseCompiler.Properties.Generated_sources = nil } // This dep is just to reference static variant from shared variant diff --git a/cc/sabi.go b/cc/sabi.go index 64eab4160..2caf0d470 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -84,8 +84,8 @@ func (props *headerAbiCheckerProperties) explicitlyDisabled() bool { 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 @@ func (sabi *sabi) shouldCreateSourceAbiDump() bool { } // 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 @@ func classifySourceAbiDump(ctx android.BaseModuleContext) []lsdumpTag { 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 @@ func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool { return false } } - return len(classifySourceAbiDump(ctx)) > 0 + return len(classifySourceAbiDump(m)) > 0 } // Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps // of their dependencies would be generated. -func sabiDepsMutator(mctx android.TopDownMutatorContext) { +type sabiTransitionMutator struct{} + +func (s *sabiTransitionMutator) Split(ctx android.BaseModuleContext) []string { + return []string{""} +} + +func (s *sabiTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string { // Escape hatch to not check any ABI dump. - if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { - return + if ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { + return "" } + // Only create ABI dump for native shared libraries and their static library dependencies. - if m, ok := mctx.Module().(*Module); ok && m.sabi != nil { - if shouldCreateSourceAbiDumpForLibrary(mctx) { - // Mark this module so that .sdump / .lsdump for this library can be generated. + if m, ok := ctx.Module().(*Module); ok && m.sabi != nil { + if shouldCreateSourceAbiDumpForLibrary(ctx) { + if IsStaticDepTag(ctx.DepTag()) || ctx.DepTag() == reuseObjTag { + return "sabi" + } + } else if sourceVariation == "sabi" { + if IsWholeStaticLib(ctx.DepTag()) || ctx.DepTag() == reuseObjTag { + return "sabi" + } + } + } + + return "" +} + +func (s *sabiTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string { + if incomingVariation == "" { + return "" + } + + if incomingVariation == "sabi" { + if m, ok := ctx.Module().(*Module); ok && m.sabi != nil { + return "sabi" + } + } + + return "" +} + +func (s *sabiTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) { + if m, ok := ctx.Module().(*Module); ok && m.sabi != nil { + if variation == "sabi" { m.sabi.Properties.ShouldCreateSourceAbiDump = true - // Mark all of its static library dependencies. - mctx.VisitDirectDeps(func(child android.Module) { - depTag := mctx.OtherModuleDependencyTag(child) - if IsStaticDepTag(depTag) || depTag == reuseObjTag { - if c, ok := child.(*Module); ok && c.sabi != nil { - // Mark this module so that .sdump for this static library can be generated. - c.sabi.Properties.ShouldCreateSourceAbiDump = true - } - } - }) + m.HideFromMake() + m.Properties.PreventInstall = true + } else if shouldCreateSourceAbiDumpForLibrary(ctx) { + // Escape hatch to not check any ABI dump. + if !ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { + m.sabi.Properties.ShouldCreateSourceAbiDump = true + } } } } diff --git a/cc/sabi_test.go b/cc/sabi_test.go new file mode 100644 index 000000000..6b8cc1759 --- /dev/null +++ b/cc/sabi_test.go @@ -0,0 +1,66 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cc + +import ( + "android/soong/android" + "testing" +) + +func TestSabi(t *testing.T) { + bp := ` + cc_library { + name: "libsabi", + srcs: ["sabi.cpp"], + static_libs: ["libdirect"], + header_abi_checker: { + enabled: true, + symbol_file: "libsabi.map.txt", + ref_dump_dirs: ["abi-dumps"], + }, + } + + cc_library { + name: "libdirect", + srcs: ["direct.cpp"], + whole_static_libs: ["libtransitive"], + } + + cc_library { + name: "libtransitive", + srcs: ["transitive.cpp"], + } + ` + + result := android.GroupFixturePreparers( + PrepareForTestWithCcDefaultModules, + ).RunTestWithBp(t, bp) + + libsabiStatic := result.ModuleForTests("libsabi", "android_arm64_armv8-a_static_sabi") + sabiObjSDump := libsabiStatic.Output("obj/sabi.sdump") + + libDirect := result.ModuleForTests("libdirect", "android_arm64_armv8-a_static_sabi") + directObjSDump := libDirect.Output("obj/direct.sdump") + + libTransitive := result.ModuleForTests("libtransitive", "android_arm64_armv8-a_static_sabi") + transitiveObjSDump := libTransitive.Output("obj/transitive.sdump") + + libsabiShared := result.ModuleForTests("libsabi", "android_arm64_armv8-a_shared") + sabiLink := libsabiShared.Rule("sAbiLink") + + android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), sabiObjSDump.Output.String()) + android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), directObjSDump.Output.String()) + android.AssertStringListContains(t, "sabi link inputs", sabiLink.Inputs.Strings(), transitiveObjSDump.Output.String()) +} diff --git a/cc/sanitize.go b/cc/sanitize.go index 7f52ce1c7..85fdb023f 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -176,7 +176,7 @@ func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) { 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 adf0e62da..ee71336c5 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 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro 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 6187e5332..e8578ec3b 100644 --- a/compliance/notice_test.go +++ b/compliance/notice_test.go @@ -35,4 +35,4 @@ func TestPrebuiltEtcOutputFile(t *testing.T) { 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/dexpreopt/config.go b/dexpreopt/config.go index fe6317cb2..84d4f10c1 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -191,6 +191,10 @@ type ModuleConfig struct { ForceCreateAppImage bool PresignedPrebuilt bool + + // ApexPartition is the partition in which the dexpreopt files of apex system server jars (if any) are installed. + // This is a noop unless the module is apex system server jar. + ApexPartition string } type globalSoongConfigSingleton struct{} diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 56164834a..7a39fa1d7 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -219,9 +219,9 @@ func GetSystemServerDexLocation(ctx android.PathContext, global *GlobalConfig, l } // Returns the location to the odex file for the dex file at `path`. -func ToOdexPath(path string, arch android.ArchType) string { +func ToOdexPath(path string, arch android.ArchType, partition string) string { if strings.HasPrefix(path, "/apex/") { - return filepath.Join("/system/framework/oat", arch.String(), + return filepath.Join(partition, "framework/oat", arch.String(), strings.ReplaceAll(path[1:], "/", "@")+"@classes.odex") } @@ -245,7 +245,7 @@ func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig odexPath := module.BuildPath.InSameDir(ctx, "oat", arch.String(), pathtools.ReplaceExtension(base, "odex")) odexSymbolsPath := odexPath.ReplaceExtension(ctx, "symbols.odex") - odexInstallPath := ToOdexPath(module.DexLocation, arch) + odexInstallPath := ToOdexPath(module.DexLocation, arch, module.ApexPartition) if odexOnSystemOther(module, global) { odexInstallPath = filepath.Join(SystemOtherPartition, odexInstallPath) } diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go index 6f7d3bb67..7b0f51fbd 100644 --- a/dexpreopt/dexpreopt_test.go +++ b/dexpreopt/dexpreopt_test.go @@ -42,12 +42,14 @@ func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleCo } func testApexModuleConfig(ctx android.PathContext, name, apexName string) *ModuleConfig { - return createTestModuleConfig( + ret := createTestModuleConfig( name, fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, name), android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)), android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)), android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name))) + ret.ApexPartition = "/system" + return ret } func testPlatformSystemServerModuleConfig(ctx android.PathContext, name string) *ModuleConfig { @@ -221,6 +223,49 @@ func TestDexPreoptApexSystemServerJars(t *testing.T) { DexpreoptRunningInSoong = oldDexpreoptRunningInSoong } +// Same as `TestDexPreoptApexSystemServerJars`, but the apex jar is in /system_ext +func TestDexPreoptApexSystemServerJarsSystemExt(t *testing.T) { + // modify the global variable for test + var oldDexpreoptRunningInSoong = DexpreoptRunningInSoong + DexpreoptRunningInSoong = true + + // test begin + config := android.TestConfig("out", nil, "", nil) + ctx := android.BuilderContextForTesting(config) + globalSoong := globalSoongConfigForTests(ctx) + global := GlobalConfigForTests(ctx) + module := testApexModuleConfig(ctx, "service-A", "com.android.apex1") + module.ApexPartition = "/system_ext" + productPackages := android.PathForTesting("product_packages.txt") + + global.ApexSystemServerJars = android.CreateTestConfiguredJarList( + []string{"com.android.apex1:service-A"}) + + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + if err != nil { + t.Fatal(err) + } + + wantInstalls := android.RuleBuilderInstalls{ + {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system_ext/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.odex"}, + {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system_ext/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.vdex"}, + } + + android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String()) + + android.AssertStringListContains(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar") + + // rule with apex sscp cp as false + rule, err = GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, false) + if err != nil { + t.Fatal(err) + } + android.AssertStringListDoesNotContain(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar") + + // cleanup the global variable for test + DexpreoptRunningInSoong = oldDexpreoptRunningInSoong +} + func TestDexPreoptStandaloneSystemServerJars(t *testing.T) { config := android.TestConfig("out", nil, "", nil) ctx := android.BuilderContextForTesting(config) diff --git a/etc/Android.bp b/etc/Android.bp index 580c54f9b..8e043b86e 100644 --- a/etc/Android.bp +++ b/etc/Android.bp @@ -11,6 +11,7 @@ bootstrap_go_package { "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 000000000..1bce2f124 --- /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/etc/install_symlink.go b/etc/install_symlink.go index 2182b8669..aa33445e1 100644 --- a/etc/install_symlink.go +++ b/etc/install_symlink.go @@ -26,6 +26,7 @@ func init() { func RegisterInstallSymlinkBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("install_symlink", InstallSymlinkFactory) + ctx.RegisterModuleType("install_symlink_host", InstallSymlinkHostFactory) } // install_symlink can be used to install an symlink with an arbitrary target to an arbitrary path @@ -37,6 +38,14 @@ func InstallSymlinkFactory() android.Module { return module } +// install_symlink can be used to install an symlink to an arbitrary path on the host. +func InstallSymlinkHostFactory() android.Module { + module := &InstallSymlink{} + module.AddProperties(&module.properties) + android.InitAndroidMultiTargetsArchModule(module, android.HostSupported, android.MultilibCommon) + return module +} + type InstallSymlinkProperties struct { // Where to install this symlink, relative to the partition it's installed on. // Which partition it's installed on can be controlled by the vendor, system_ext, ramdisk, etc. diff --git a/etc/install_symlink_test.go b/etc/install_symlink_test.go index d7165e5de..c97d97c65 100644 --- a/etc/install_symlink_test.go +++ b/etc/install_symlink_test.go @@ -133,3 +133,39 @@ func TestErrorOnInstalledPathStartingWithSlash(t *testing.T) { } `) } + +var prepareForInstallSymlinkHostTest = android.GroupFixturePreparers( + android.PrepareForTestWithAndroidBuildComponents, + android.FixtureRegisterWithContext(RegisterInstallSymlinkBuildComponents), +) + +func TestInstallSymlinkHostBasic(t *testing.T) { + result := prepareForInstallSymlinkHostTest.RunTestWithBp(t, ` + install_symlink_host { + name: "foo", + installed_location: "bin/foo", + symlink_target: "aa/bb/cc", + } + `) + + buildOS := result.Config.BuildOS.String() + foo := result.ModuleForTests("foo", buildOS+"_common").Module() + + androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, foo) + if len(androidMkEntries) != 1 { + t.Fatalf("expected 1 androidmkentry, got %d", len(androidMkEntries)) + } + + symlinks := androidMkEntries[0].EntryMap["LOCAL_SOONG_INSTALL_SYMLINKS"] + if len(symlinks) != 1 { + t.Fatalf("Expected 1 symlink, got %d", len(symlinks)) + } + + if !strings.HasSuffix(symlinks[0], "bin/foo") { + t.Fatalf("Expected symlink install path to end in bin/foo, got: %s", symlinks[0]) + } + + if !strings.Contains(symlinks[0], "host") { + t.Fatalf("Expected symlink install path to contain `host`, got: %s", symlinks[0]) + } +} diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go index 8af2ffaab..608fccdad 100644 --- a/filesystem/aconfig_files.go +++ b/filesystem/aconfig_files.go @@ -76,10 +76,13 @@ func (f *filesystem) buildAconfigFlagsFiles(ctx android.ModuleContext, builder * 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/filesystem/filesystem.go b/filesystem/filesystem.go index a26fac7fc..09d8fba5e 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -35,7 +35,7 @@ func init() { } func registerBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterModuleType("android_filesystem", filesystemFactory) + ctx.RegisterModuleType("android_filesystem", FilesystemFactory) ctx.RegisterModuleType("android_filesystem_defaults", filesystemDefaultsFactory) ctx.RegisterModuleType("android_system_image", SystemImageFactory) ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory) @@ -137,6 +137,12 @@ type FilesystemProperties struct { Gen_aconfig_flags_pb *bool Fsverity fsverityProperties + + // If this property is set to true, the filesystem will call ctx.UncheckedModule(), causing + // it to not be built on checkbuilds. Used for the automatic migration from make to soong + // build modules, where we want to emit some not-yet-working filesystems and we don't want them + // to be built. + Unchecked_module *bool `blueprint:"mutated"` } // android_filesystem packages a set of modules and their transitive dependencies into a filesystem @@ -144,7 +150,7 @@ type FilesystemProperties struct { // modules in the filesystem image are built for the target device (i.e. Android, not Linux host). // The modules are placed in the filesystem image just like they are installed to the ordinary // partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory. -func filesystemFactory() android.Module { +func FilesystemFactory() android.Module { module := &filesystem{} module.filterPackagingSpec = module.filterInstallablePackagingSpec initFilesystemModule(module, module) @@ -177,6 +183,13 @@ const ( unknown ) +type FilesystemInfo struct { + // A text file containing the list of paths installed on the partition. + FileListFile android.Path +} + +var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]() + func (f *filesystem) fsType(ctx android.ModuleContext) fsType { typeStr := proptools.StringDefault(f.properties.Type, "ext4") switch typeStr { @@ -227,6 +240,14 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { f.fileListFile = android.PathForModuleOut(ctx, "fileList").OutputPath android.WriteFileRule(ctx, f.fileListFile, f.installedFilesList()) + + android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{ + FileListFile: f.fileListFile, + }) + + if proptools.Bool(f.properties.Unchecked_module) { + ctx.UncheckedModule() + } } func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.OutputPath) { diff --git a/fsgen/Android.bp b/fsgen/Android.bp index aa8881f8e..9fa955779 100644 --- a/fsgen/Android.bp +++ b/fsgen/Android.bp @@ -19,3 +19,7 @@ bootstrap_go_package { ], pluginFor: ["soong_build"], } + +soong_filesystem_creator { + name: "soong_filesystem_creator", +} diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go index ca948f406..a9f4256ec 100644 --- a/fsgen/filesystem_creator.go +++ b/fsgen/filesystem_creator.go @@ -17,12 +17,16 @@ package fsgen import ( "android/soong/android" "android/soong/filesystem" + "crypto/sha256" "fmt" "strconv" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) +var pctx = android.NewPackageContext("android/soong/fsgen") + func init() { registerBuildComponents(android.InitRegistrationContext) } @@ -31,14 +35,22 @@ func registerBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("soong_filesystem_creator", filesystemCreatorFactory) } +type filesystemCreatorProps struct { + Generated_partition_types []string `blueprint:"mutated"` + Unsupported_partition_types []string `blueprint:"mutated"` +} + type filesystemCreator struct { android.ModuleBase + + properties filesystemCreatorProps } func filesystemCreatorFactory() android.Module { module := &filesystemCreator{} android.InitAndroidModule(module) + module.AddProperties(&module.properties) android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) }) @@ -47,36 +59,62 @@ func filesystemCreatorFactory() android.Module { } func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) { - f.createSystemImage(ctx) + for _, partitionType := range []string{"system"} { + if f.createPartition(ctx, partitionType) { + f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType) + } else { + f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType) + } + } } -func (f *filesystemCreator) createSystemImage(ctx android.LoadHookContext) { +func (f *filesystemCreator) generatedModuleNameForPartition(cfg android.Config, partitionType string) string { + prefix := "soong" + if cfg.HasDeviceProduct() { + prefix = cfg.DeviceProduct() + } + return fmt.Sprintf("%s_generated_%s_image", prefix, partitionType) +} + +// Creates a soong module to build the given partition. Returns false if we can't support building +// it. +func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partitionType string) bool { baseProps := &struct { Name *string }{ - Name: proptools.StringPtr(fmt.Sprintf("%s_generated_system_image", ctx.Config().DeviceProduct())), + Name: proptools.StringPtr(f.generatedModuleNameForPartition(ctx.Config(), partitionType)), } - fsProps := &(filesystem.FilesystemProperties{}) + fsProps := &filesystem.FilesystemProperties{} + + // Don't build this module on checkbuilds, the soong-built partitions are still in-progress + // and sometimes don't build. + fsProps.Unchecked_module = proptools.BoolPtr(true) + partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse - systemPartitionVars := partitionVars.PartitionQualifiedVariables["system"] + specificPartitionVars := partitionVars.PartitionQualifiedVariables[partitionType] // BOARD_AVB_ENABLE fsProps.Use_avb = proptools.BoolPtr(partitionVars.BoardAvbEnable) // BOARD_AVB_KEY_PATH - fsProps.Avb_private_key = proptools.StringPtr(systemPartitionVars.BoardAvbKeyPath) + fsProps.Avb_private_key = proptools.StringPtr(specificPartitionVars.BoardAvbKeyPath) // BOARD_AVB_ALGORITHM - fsProps.Avb_algorithm = proptools.StringPtr(systemPartitionVars.BoardAvbAlgorithm) + fsProps.Avb_algorithm = proptools.StringPtr(specificPartitionVars.BoardAvbAlgorithm) // BOARD_AVB_SYSTEM_ROLLBACK_INDEX - if rollbackIndex, err := strconv.ParseInt(systemPartitionVars.BoardAvbRollbackIndex, 10, 64); err == nil { + if rollbackIndex, err := strconv.ParseInt(specificPartitionVars.BoardAvbRollbackIndex, 10, 64); err == nil { fsProps.Rollback_index = proptools.Int64Ptr(rollbackIndex) } - fsProps.Partition_name = proptools.StringPtr("system") + fsProps.Partition_name = proptools.StringPtr(partitionType) // BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE - fsProps.Type = proptools.StringPtr(systemPartitionVars.BoardFileSystemType) + fsProps.Type = proptools.StringPtr(specificPartitionVars.BoardFileSystemType) + if *fsProps.Type != "ext4" { + // Currently the android_filesystem module type only supports ext4: + // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/filesystem/filesystem.go;l=416;drc=98047cfd07944b297a12d173453bc984806760d2 + return false + } - fsProps.Base_dir = proptools.StringPtr("system") + fsProps.Base_dir = proptools.StringPtr(partitionType) fsProps.Gen_aconfig_flags_pb = proptools.BoolPtr(true) @@ -103,9 +141,77 @@ func (f *filesystemCreator) createSystemImage(ctx android.LoadHookContext) { // - filesystemProperties.Build_logtags // - filesystemProperties.Fsverity.Libs // - systemImageProperties.Linker_config_src - ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps) + var module android.Module + if partitionType == "system" { + module = ctx.CreateModule(filesystem.SystemImageFactory, baseProps, fsProps) + } else { + module = ctx.CreateModule(filesystem.FilesystemFactory, baseProps, fsProps) + } + module.HideFromMake() + return true +} + +func (f *filesystemCreator) createDiffTest(ctx android.ModuleContext, partitionType string) android.Path { + partitionModuleName := f.generatedModuleNameForPartition(ctx.Config(), partitionType) + systemImage := ctx.GetDirectDepWithTag(partitionModuleName, generatedFilesystemDepTag) + filesystemInfo, ok := android.OtherModuleProvider(ctx, systemImage, filesystem.FilesystemProvider) + if !ok { + ctx.ModuleErrorf("Expected module %s to provide FileysystemInfo", partitionModuleName) + } + makeFileList := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partitionType)) + // For now, don't allowlist anything. The test will fail, but that's fine in the current + // early stages where we're just figuring out what we need + emptyAllowlistFile := android.PathForModuleOut(ctx, fmt.Sprintf("allowlist_%s.txt", partitionModuleName)) + android.WriteFileRule(ctx, emptyAllowlistFile, "") + 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). + Text(partitionModuleName). + FlagWithInput("--allowlists ", emptyAllowlistFile) + builder.Command().Text("touch").Output(diffTestResultFile) + builder.Build(partitionModuleName+" diff test", partitionModuleName+" diff test") + return diffTestResultFile +} + +func createFailingCommand(ctx android.ModuleContext, message string) android.Path { + hasher := sha256.New() + hasher.Write([]byte(message)) + filename := fmt.Sprintf("failing_command_%x.txt", hasher.Sum(nil)) + file := android.PathForModuleOut(ctx, filename) + builder := android.NewRuleBuilder(pctx, ctx) + builder.Command().Textf("echo %s", proptools.NinjaAndShellEscape(message)) + builder.Command().Text("exit 1 #").Output(file) + builder.Build("failing command "+filename, "failing command "+filename) + return file +} + +type systemImageDepTagType struct { + blueprint.BaseDependencyTag +} + +var generatedFilesystemDepTag systemImageDepTagType + +func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) { + for _, partitionType := range f.properties.Generated_partition_types { + ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, f.generatedModuleNameForPartition(ctx.Config(), partitionType)) + } } func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if ctx.ModuleDir() != "build/soong/fsgen" { + ctx.ModuleErrorf("There can only be one soong_filesystem_creator in build/soong/fsgen") + } + f.HideFromMake() + var diffTestFiles []android.Path + for _, partitionType := range f.properties.Generated_partition_types { + diffTestFiles = append(diffTestFiles, f.createDiffTest(ctx, partitionType)) + } + for _, partitionType := range f.properties.Unsupported_partition_types { + diffTestFiles = append(diffTestFiles, createFailingCommand(ctx, fmt.Sprintf("Couldn't build %s partition", partitionType))) + } + ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...) } diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go index 6bb0e775b..554b66b7a 100644 --- a/fsgen/filesystem_creator_test.go +++ b/fsgen/filesystem_creator_test.go @@ -44,12 +44,13 @@ func TestFileSystemCreatorSystemImageProps(t *testing.T) { }), android.FixtureMergeMockFs(android.MockFS{ "external/avb/test/data/testkey_rsa4096.pem": nil, + "build/soong/fsgen/Android.bp": []byte(` + soong_filesystem_creator { + name: "foo", + } + `), }), - ).RunTestWithBp(t, ` - soong_filesystem_creator { - name: "foo", - } - `) + ).RunTest(t) fooSystem := result.ModuleForTests("test_product_generated_system_image", "android_common").Module().(interface { FsProps() filesystem.FilesystemProperties diff --git a/genrule/genrule.go b/genrule/genrule.go index e5222a432..18ec0a40c 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -139,8 +139,7 @@ type generatorProperties struct { 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 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { } 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 @@ func (g *Module) setOutputFiles(ctx android.ModuleContext) { // 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 9278f1574..f190750d1 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -24,6 +24,7 @@ import ( "android/soong/android" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -694,8 +695,12 @@ func TestGenruleDefaults(t *testing.T) { 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 618a0852b..6ee924f1d 100644 --- a/golang/golang.go +++ b/golang/golang.go @@ -22,6 +22,7 @@ package golang import ( "android/soong/android" + "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" ) @@ -46,7 +47,7 @@ type GoPackage struct { 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 9c5b809c1..0a4baedb4 100644 --- a/golang/golang_test.go +++ b/golang/golang_test.go @@ -40,7 +40,7 @@ func TestGolang(t *testing.T) { 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 7d73b03e4..41cc24a0d 100644 --- a/java/aar.go +++ b/java/aar.go @@ -483,9 +483,9 @@ func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptio } 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 0539d25aa..2dff6cd9f 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -313,6 +313,7 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { 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/app.go b/java/app.go index 1358fafec..dd9967516 100644 --- a/java/app.go +++ b/java/app.go @@ -172,7 +172,7 @@ type overridableAppProperties struct { RotationMinSdkVersion *string // the package name of this app. The package name in the manifest file is used if one was not given. - Package_name *string + Package_name proptools.Configurable[string] // the logging parent of this app. Logging_parent *string @@ -386,7 +386,8 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon checkMinSdkVersionMts(ctx, a.MinSdkVersion(ctx)) applicationId := a.appTestHelperAppProperties.Manifest_values.ApplicationId if applicationId != nil { - if a.overridableAppProperties.Package_name != nil { + packageName := a.overridableAppProperties.Package_name.Get(ctx) + if packageName.IsPresent() { ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.") } a.aapt.manifestValues.applicationId = *applicationId @@ -586,10 +587,11 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { } manifestPackageName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(ctx.ModuleName()) - if overridden || a.overridableAppProperties.Package_name != nil { + packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) + if overridden || packageNameProp.IsPresent() { // The product override variable has a priority over the package_name property. if !overridden { - manifestPackageName = *a.overridableAppProperties.Package_name + manifestPackageName = packageNameProp.Get() } aaptLinkFlags = append(aaptLinkFlags, generateAaptRenamePackageFlags(manifestPackageName, a.renameResourcesPackage())...) a.overriddenManifestPackageName = manifestPackageName @@ -829,11 +831,12 @@ func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.P return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist) } - if a.overridableAppProperties.Package_name == nil { + packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) + if packageNameProp.IsEmpty() { ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist") } - packageName := *a.overridableAppProperties.Package_name + packageName := packageNameProp.Get() fileName := "privapp_allowlist_" + packageName + ".xml" outPath := android.PathForModuleOut(ctx, fileName).OutputPath ctx.Build(pctx, android.BuildParams{ @@ -1418,7 +1421,8 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } applicationId := a.appTestProperties.Manifest_values.ApplicationId if applicationId != nil { - if a.overridableAppProperties.Package_name != nil { + packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) + if packageNameProp.IsPresent() { ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.") } a.aapt.manifestValues.applicationId = *applicationId @@ -1469,10 +1473,11 @@ func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig androi command.FlagWithArg("--test-file-name ", a.installApkName+".apk") } - if a.overridableAppProperties.Package_name != nil { + packageNameProp := a.overridableAppProperties.Package_name.Get(ctx) + if packageNameProp.IsPresent() { fixNeeded = true command.FlagWithInput("--manifest ", a.manifestPath). - FlagWithArg("--package-name ", *a.overridableAppProperties.Package_name) + FlagWithArg("--package-name ", packageNameProp.Get()) } if a.appTestProperties.Mainline_package_name != nil { diff --git a/java/base.go b/java/base.go index fc21c44e5..a9399cbd3 100644 --- a/java/base.go +++ b/java/base.go @@ -1628,7 +1628,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath 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 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath 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 @@ func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { // 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 1cca7ad49..da865404b 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -41,10 +41,50 @@ java_defaults { 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 @@ java_library { 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/dex.go b/java/dex.go index e16b05208..a3f699bf0 100644 --- a/java/dex.go +++ b/java/dex.go @@ -133,7 +133,7 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", `$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in && ` + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` + - `rm -f "$outDir/classes*.dex" "$outDir/classes.dex.jar"`, + `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`, CommandDeps: []string{ "${config.D8Cmd}", "${config.SoongZipCmd}", @@ -172,7 +172,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", `rm -rf ${outUsageDir} && ` + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` + - `rm -f "$outDir/classes*.dex" "$outDir/classes.dex.jar"`, + `rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`, Depfile: "${out}.d", Deps: blueprint.DepsGCC, CommandDeps: []string{ diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 63a863497..637da363c 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -494,6 +494,12 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa PresignedPrebuilt: d.isPresignedPrebuilt, } + if ctx.Config().InstallApexSystemServerDexpreoptSamePartition() { + dexpreoptConfig.ApexPartition = android.PathForModuleInstall(ctx).Partition() + } else { + dexpreoptConfig.ApexPartition = "system" + } + d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config") dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath) ctx.CheckbuildFile(d.configPath) diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go index 33be60352..c97156541 100644 --- a/java/dexpreopt_check.go +++ b/java/dexpreopt_check.go @@ -17,6 +17,8 @@ package java import ( "strings" + "github.com/google/blueprint" + "android/soong/android" "android/soong/dexpreopt" @@ -43,16 +45,12 @@ func RegisterDexpreoptCheckBuildComponents(ctx android.RegistrationContext) { type dexpreoptSystemserverCheck struct { android.SingletonModuleBase - // Mapping from the module name to the install paths to the compilation artifacts. - artifactsByModuleName map[string][]string - // The install paths to the compilation artifacts. artifacts []string } func dexpreoptSystemserverCheckFactory() android.SingletonModule { m := &dexpreoptSystemserverCheck{} - m.artifactsByModuleName = make(map[string][]string) android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) return m } @@ -62,7 +60,25 @@ func getInstallPath(ctx android.ModuleContext, location string) android.InstallP ctx, "", strings.TrimPrefix(location, "/")) } -func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.ModuleContext) { +type systemServerDependencyTag struct { + blueprint.BaseDependencyTag +} + +// systemServerJarDepTag willl be used for validation. Skip visiblility. +func (b systemServerDependencyTag) ExcludeFromVisibilityEnforcement() { +} + +var ( + // dep tag for platform and apex system server jars + systemServerJarDepTag = systemServerDependencyTag{} +) + +var _ android.ExcludeFromVisibilityEnforcementTag = systemServerJarDepTag + +// Add a depenendency on the system server jars. The dexpreopt files of those will be emitted to make. +// The kati packaging system will verify that those files appear in installed files. +// Adding the dependency allows the singleton module to determine whether an apex system server jar is system_ext specific. +func (m *dexpreoptSystemserverCheck) DepsMutator(ctx android.BottomUpMutatorContext) { global := dexpreopt.GetGlobalConfig(ctx) targets := ctx.Config().Targets[android.Android] @@ -72,23 +88,27 @@ func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.Mod return } - systemServerJars := global.AllSystemServerJars(ctx) - for _, jar := range systemServerJars.CopyOfJars() { - dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, jar) - odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType) + ctx.AddDependency(ctx.Module(), systemServerJarDepTag, global.AllSystemServerJars(ctx).CopyOfJars()...) +} + +func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.ModuleContext) { + global := dexpreopt.GetGlobalConfig(ctx) + targets := ctx.Config().Targets[android.Android] + + ctx.VisitDirectDepsWithTag(systemServerJarDepTag, func(systemServerJar android.Module) { + partition := "system" + if systemServerJar.InstallInSystemExt() && ctx.Config().InstallApexSystemServerDexpreoptSamePartition() { + partition = ctx.DeviceConfig().SystemExtPath() // system_ext + } + dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, systemServerJar.Name()) + odexLocation := dexpreopt.ToOdexPath(dexLocation, targets[0].Arch.ArchType, partition) odexPath := getInstallPath(ctx, odexLocation) vdexPath := getInstallPath(ctx, pathtools.ReplaceExtension(odexLocation, "vdex")) - m.artifactsByModuleName[jar] = []string{odexPath.String(), vdexPath.String()} - } + m.artifacts = append(m.artifacts, odexPath.String(), vdexPath.String()) + }) } func (m *dexpreoptSystemserverCheck) GenerateSingletonBuildActions(ctx android.SingletonContext) { - // Only keep modules defined in Soong. - ctx.VisitAllModules(func(module android.Module) { - if artifacts, ok := m.artifactsByModuleName[module.Name()]; ok { - m.artifacts = append(m.artifacts, artifacts...) - } - }) } func (m *dexpreoptSystemserverCheck) MakeVars(ctx android.MakeVarsContext) { diff --git a/java/java.go b/java/java.go index 661422b54..018850fef 100644 --- a/java/java.go +++ b/java/java.go @@ -1795,8 +1795,7 @@ type binaryProperties struct { // 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 @@ type Binary struct { wrapperFile android.Path binaryFile android.InstallPath + + androidMkNamesOfJniLibs []string } func (j *Binary) HostToolPath() android.OptionalPath { @@ -1880,6 +1881,21 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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 @@ func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) { 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 db154ce98..24dabdb10 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -3102,7 +3102,7 @@ func assertTestOnlyAndTopLevel(t *testing.T, ctx *android.TestResult, expectedTe } } -// 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 @@ func TestNativeRequiredDepOfJavaBinary(t *testing.T) { 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 d282f1976..7a0fb10cb 100644 --- a/java/jdeps_test.go +++ b/java/jdeps_test.go @@ -109,7 +109,7 @@ func TestCollectJavaLibraryWithJarJarRules(t *testing.T) { 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 f30877258..dfbde0e54 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2481,19 +2481,3 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo 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 924abd460..aad106007 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -127,6 +127,26 @@ func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.Mo 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 5bce16b8d..fd869174c 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -154,7 +154,7 @@ type BaseCompilerProperties struct { // 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) strippedOutputFilePath() android.OptionalPath { 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 5602edc79..a044a99dd 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -1756,6 +1756,16 @@ func (mod *Module) HostToolPath() android.OptionalPath { 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) } diff --git a/ui/build/config.go b/ui/build/config.go index bd20442f7..75edfcd8a 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -1754,12 +1754,10 @@ func (c *configImpl) SisoBin() string { } func (c *configImpl) PrebuiltBuildTool(name string) string { - if v, ok := c.environ.Get("SANITIZE_HOST"); ok { - if sanitize := strings.Fields(v); inList("address", sanitize) { - asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name) - if _, err := os.Stat(asan); err == nil { - return asan - } + if c.environ.IsEnvTrue("SANITIZE_BUILD_TOOL_PREBUILTS") { + asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name) + if _, err := os.Stat(asan); err == nil { + return asan } } return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name) |