diff options
Diffstat (limited to 'android/module.go')
| -rw-r--r-- | android/module.go | 252 |
1 files changed, 211 insertions, 41 deletions
diff --git a/android/module.go b/android/module.go index 337ae4076..c4e43c219 100644 --- a/android/module.go +++ b/android/module.go @@ -61,18 +61,44 @@ type ModuleBuildParams BuildParams // EarlyModuleContext provides methods that can be called early, as soon as the properties have // been parsed into the module and before any mutators have run. type EarlyModuleContext interface { + // Module returns the current module as a Module. It should rarely be necessary, as the module already has a + // reference to itself. 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. ModuleName() string + + // ModuleDir returns the path to the directory that contains the definition of the module. ModuleDir() string + + // ModuleType returns the name of the module type that was used to create the module, as specified in + // RegisterModuleType. ModuleType() string + + // BlueprintFile returns the name of the blueprint file that contains the definition of this + // module. BlueprintsFile() string + // ContainsProperty returns true if the specified property name was set in the module definition. ContainsProperty(name string) bool + + // Errorf reports an error at the specified position of the module definition file. Errorf(pos scanner.Position, fmt string, args ...interface{}) + + // ModuleErrorf reports an error at the line number of the module type in the module definition. ModuleErrorf(fmt string, args ...interface{}) + + // PropertyErrorf reports an error at the line number of a property in the module definition. PropertyErrorf(property, fmt string, args ...interface{}) + + // Failed returns true if any errors have been reported. In most cases the module can continue with generating + // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error + // has prevented the module from creating necessary data it can return early when Failed returns true. Failed() bool + // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The + // primary builder will be rerun whenever the specified files are modified. AddNinjaFileDeps(deps ...string) DeviceSpecific() bool @@ -98,6 +124,8 @@ type EarlyModuleContext interface { IsSymlink(path Path) bool Readlink(path Path) string + // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the + // default SimpleNameInterface if Context.SetNameInterface was not called. Namespace() *Namespace } @@ -110,33 +138,156 @@ type BaseModuleContext interface { blueprintBaseModuleContext() blueprint.BaseModuleContext + // 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 + + // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleDir(m blueprint.Module) string + + // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) + + // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency + // on the module. When called inside a Visit* method with current module being visited, and there are multiple + // dependencies on the module being visited, it returns the dependency tag used for the current dependency. OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag + + // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface + // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called. OtherModuleExists(name string) bool + + // OtherModuleDependencyVariantExists returns true if a module with the + // specified name and variant exists. The variant must match the given + // variations. It must also match all the non-local variations of the current + // module. In other words, it checks for the module AddVariationDependencies + // would add a dependency on with the same arguments. OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool + + // OtherModuleReverseDependencyVariantExists returns true if a module with the + // specified name exists with the same variations as the current module. In + // other words, it checks for the module AddReverseDependency would add a + // dependency on with the same argument. OtherModuleReverseDependencyVariantExists(name string) bool + + // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information. + // It is intended for use inside the visit functions of Visit* and WalkDeps. OtherModuleType(m blueprint.Module) string + // OtherModuleProvider returns the value for a provider for the given module. If the value is + // not set it returns the zero value of the type of the provider, so the return value can always + // be type asserted to the type of the provider. The value returned may be a deep copy of the + // value originally passed to SetProvider. + OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} + + // OtherModuleHasProvider returns true if the provider for the given module has been set. + OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool + + // Provider returns the value for a provider for the current module. If the value is + // not set it returns the zero value of the type of the provider, so the return value can always + // be type asserted to the type of the provider. It panics if called before the appropriate + // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep + // copy of the value originally passed to SetProvider. + Provider(provider blueprint.ProviderKey) interface{} + + // HasProvider returns true if the provider for the current module has been set. + HasProvider(provider blueprint.ProviderKey) bool + + // SetProvider sets the value for a provider for the current module. It panics if not called + // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value + // is not of the appropriate type, or if the value has already been set. The value should not + // be modified after being passed to SetProvider. + SetProvider(provider blueprint.ProviderKey, value interface{}) + GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module + + // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if + // none exists. It panics if the dependency does not have the specified tag. It skips any + // dependencies that are not an android.Module. GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module + + // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified + // name, or nil if none exists. If there are multiple dependencies on the same module it returns + // the first DependencyTag. It skips any dependencies that are not an android.Module. GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) + // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple + // direct dependencies on the same module visit will be called multiple times on that module + // and OtherModuleDependencyTag will return a different tag for each. + // + // The Module passed to the visit function should not be retained outside of the visit + // function, it may be invalidated by future mutators. VisitDirectDepsBlueprint(visit func(blueprint.Module)) + + // VisitDirectDeps calls visit for each direct dependency. If there are multiple + // direct dependencies on the same module visit will be called multiple times on that module + // and OtherModuleDependencyTag will return a different tag for each. It skips any + // dependencies that are not an android.Module. + // + // The Module passed to the visit function should not be retained outside of the visit + // function, it may be invalidated by future mutators. VisitDirectDeps(visit func(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 + // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and + // OtherModuleDependencyTag will return a different tag for each. It skips any + // dependencies that are not an android.Module. + // + // The Module passed to the visit function should not be retained outside of the visit function, it may be + // invalidated by future mutators. VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module VisitDepsDepthFirst(visit func(Module)) // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) + + // 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. WalkDeps(visit func(Module, Module) bool) + + // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency + // tree in top down order. visit may be called multiple times for the same (child, parent) + // pair if there are multiple direct dependencies between the child and parent with different + // tags. OtherModuleDependencyTag will return the tag for the currently visited + // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down + // to child. + // + // The Modules passed to the visit function should not be retained outside of the visit function, they may be + // invalidated by future mutators. WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) + // GetWalkPath is supposed to be called in visit function passed in WalkDeps() // and returns a top-down dependency path from a start module to current child module. GetWalkPath() []Module + // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the + // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are + // only done once for all variants of a module. + PrimaryModule() Module + + // FinalModule returns the last variant of the current module. Variants of a module are always visited in + // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all + // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform + // singleton actions that are only done once for all variants of a module. + FinalModule() Module + + // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always + // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read + // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any + // data modified by the current mutator. + VisitAllModuleVariants(visit func(Module)) + // GetTagPath is supposed to be called in visit function passed in WalkDeps() // and returns a top-down dependency tags path from a start module to current child module. // It has one less entry than GetWalkPath() as it contains the dependency tags that @@ -216,10 +367,8 @@ type ModuleContext interface { // additional dependencies. Phony(phony string, deps ...Path) - PrimaryModule() Module - FinalModule() Module - VisitAllModuleVariants(visit func(Module)) - + // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods, + // but do not exist. GetMissingDependencies() []string } @@ -417,7 +566,7 @@ type commonProperties struct { // control whether this module compiles for 32-bit, 64-bit, or both. Possible values // are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both // architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit - // platform + // platform). Compile_multilib *string `android:"arch_variant"` Target struct { @@ -476,7 +625,7 @@ type commonProperties struct { Native_bridge_supported *bool `android:"arch_variant"` // init.rc files to be installed if this module is installed - Init_rc []string `android:"path"` + Init_rc []string `android:"arch_variant,path"` // VINTF manifest fragments to be installed if this module is installed Vintf_fragments []string `android:"path"` @@ -799,7 +948,7 @@ type ModuleBase struct { initRcPaths Paths vintfFragmentsPaths Paths - prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool + prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool } func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {} @@ -826,7 +975,7 @@ func (m *ModuleBase) VariablesForTests() map[string]string { return m.variables } -func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool) { +func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool) { m.prefer32 = prefer32 } @@ -922,7 +1071,7 @@ func (m *ModuleBase) Os() OsType { } func (m *ModuleBase) Host() bool { - return m.Os().Class == Host || m.Os().Class == HostCross + return m.Os().Class == Host } func (m *ModuleBase) Device() bool { @@ -942,28 +1091,28 @@ func (m *ModuleBase) IsCommonOSVariant() bool { return m.commonProperties.CommonOSVariant } -func (m *ModuleBase) OsClassSupported() []OsClass { +func (m *ModuleBase) supportsTarget(target Target, config Config) bool { switch m.commonProperties.HostOrDeviceSupported { case HostSupported: - return []OsClass{Host, HostCross} + return target.Os.Class == Host case HostSupportedNoCross: - return []OsClass{Host} + return target.Os.Class == Host && !target.HostCross case DeviceSupported: - return []OsClass{Device} + return target.Os.Class == Device case HostAndDeviceSupported, HostAndDeviceDefault: - var supported []OsClass + supported := false if Bool(m.hostAndDeviceProperties.Host_supported) || (m.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault && m.hostAndDeviceProperties.Host_supported == nil) { - supported = append(supported, Host, HostCross) + supported = supported || target.Os.Class == Host } if m.hostAndDeviceProperties.Device_supported == nil || *m.hostAndDeviceProperties.Device_supported { - supported = append(supported, Device) + supported = supported || target.Os.Class == Device } return supported default: - return nil + return false } } @@ -1557,6 +1706,21 @@ func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name strin func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string { return b.bp.OtherModuleType(m) } +func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} { + return b.bp.OtherModuleProvider(m, provider) +} +func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool { + return b.bp.OtherModuleHasProvider(m, provider) +} +func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} { + return b.bp.Provider(provider) +} +func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool { + return b.bp.HasProvider(provider) +} +func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) { + b.bp.SetProvider(provider, value) +} func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module { return b.bp.GetDirectDepWithTag(name, tag) @@ -1877,6 +2041,20 @@ func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag { return b.tagPath } +func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) { + b.bp.VisitAllModuleVariants(func(module blueprint.Module) { + visit(module.(Module)) + }) +} + +func (b *baseModuleContext) PrimaryModule() Module { + return b.bp.PrimaryModule().(Module) +} + +func (b *baseModuleContext) FinalModule() Module { + return b.bp.FinalModule().(Module) +} + // A regexp for removing boilerplate from BaseDependencyTag from the string representation of // a dependency tag. var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`) @@ -1912,20 +2090,6 @@ func (b *baseModuleContext) GetPathString(skipFirst bool) string { return sb.String() } -func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) { - m.bp.VisitAllModuleVariants(func(module blueprint.Module) { - visit(module.(Module)) - }) -} - -func (m *moduleContext) PrimaryModule() Module { - return m.bp.PrimaryModule().(Module) -} - -func (m *moduleContext) FinalModule() Module { - return m.bp.FinalModule().(Module) -} - func (m *moduleContext) ModuleSubDir() string { return m.bp.ModuleSubDir() } @@ -1951,7 +2115,7 @@ func (b *baseModuleContext) Os() OsType { } func (b *baseModuleContext) Host() bool { - return b.os.Class == Host || b.os.Class == HostCross + return b.os.Class == Host } func (b *baseModuleContext) Device() bool { @@ -2411,30 +2575,36 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { } // Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild. - osDeps := map[OsType]Paths{} + type osAndCross struct { + os OsType + hostCross bool + } + osDeps := map[osAndCross]Paths{} ctx.VisitAllModules(func(module Module) { if module.Enabled() { - os := module.Target().Os - osDeps[os] = append(osDeps[os], module.base().checkbuildFiles...) + key := osAndCross{os: module.Target().Os, hostCross: module.Target().HostCross} + osDeps[key] = append(osDeps[key], module.base().checkbuildFiles...) } }) osClass := make(map[string]Paths) - for os, deps := range osDeps { + for key, deps := range osDeps { var className string - switch os.Class { + switch key.os.Class { case Host: - className = "host" - case HostCross: - className = "host-cross" + if key.hostCross { + className = "host-cross" + } else { + className = "host" + } case Device: className = "target" default: continue } - name := className + "-" + os.Name + name := className + "-" + key.os.Name osClass[className] = append(osClass[className], PathForPhony(ctx, name)) ctx.Phony(name, deps...) |