1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved. 2*1fa6dee9SAndroid Build Coastguard Worker// 3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*1fa6dee9SAndroid Build Coastguard Worker// 7*1fa6dee9SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*1fa6dee9SAndroid Build Coastguard Worker// 9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License. 14*1fa6dee9SAndroid Build Coastguard Worker 15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint 16*1fa6dee9SAndroid Build Coastguard Worker 17*1fa6dee9SAndroid Build Coastguard Workerimport ( 18*1fa6dee9SAndroid Build Coastguard Worker "errors" 19*1fa6dee9SAndroid Build Coastguard Worker "fmt" 20*1fa6dee9SAndroid Build Coastguard Worker "path/filepath" 21*1fa6dee9SAndroid Build Coastguard Worker "sort" 22*1fa6dee9SAndroid Build Coastguard Worker "strings" 23*1fa6dee9SAndroid Build Coastguard Worker "sync" 24*1fa6dee9SAndroid Build Coastguard Worker "text/scanner" 25*1fa6dee9SAndroid Build Coastguard Worker 26*1fa6dee9SAndroid Build Coastguard Worker "github.com/google/blueprint/parser" 27*1fa6dee9SAndroid Build Coastguard Worker "github.com/google/blueprint/pathtools" 28*1fa6dee9SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 29*1fa6dee9SAndroid Build Coastguard Worker) 30*1fa6dee9SAndroid Build Coastguard Worker 31*1fa6dee9SAndroid Build Coastguard Worker// A Module handles generating all of the Ninja build actions needed to build a 32*1fa6dee9SAndroid Build Coastguard Worker// single module based on properties defined in a Blueprints file. Module 33*1fa6dee9SAndroid Build Coastguard Worker// objects are initially created during the parse phase of a Context using one 34*1fa6dee9SAndroid Build Coastguard Worker// of the registered module types (and the associated ModuleFactory function). 35*1fa6dee9SAndroid Build Coastguard Worker// The Module's properties struct is automatically filled in with the property 36*1fa6dee9SAndroid Build Coastguard Worker// values specified in the Blueprints file (see Context.RegisterModuleType for more 37*1fa6dee9SAndroid Build Coastguard Worker// information on this). 38*1fa6dee9SAndroid Build Coastguard Worker// 39*1fa6dee9SAndroid Build Coastguard Worker// A Module can be split into multiple Modules by a Mutator. All existing 40*1fa6dee9SAndroid Build Coastguard Worker// properties set on the module will be duplicated to the new Module, and then 41*1fa6dee9SAndroid Build Coastguard Worker// modified as necessary by the Mutator. 42*1fa6dee9SAndroid Build Coastguard Worker// 43*1fa6dee9SAndroid Build Coastguard Worker// The Module implementation can access the build configuration as well as any 44*1fa6dee9SAndroid Build Coastguard Worker// modules on which it depends (as defined by the "deps" property 45*1fa6dee9SAndroid Build Coastguard Worker// specified in the Blueprints file, dynamically added by implementing the 46*1fa6dee9SAndroid Build Coastguard Worker// (deprecated) DynamicDependerModule interface, or dynamically added by a 47*1fa6dee9SAndroid Build Coastguard Worker// BottomUpMutator) using the ModuleContext passed to GenerateBuildActions. 48*1fa6dee9SAndroid Build Coastguard Worker// This ModuleContext is also used to create Ninja build actions and to report 49*1fa6dee9SAndroid Build Coastguard Worker// errors to the user. 50*1fa6dee9SAndroid Build Coastguard Worker// 51*1fa6dee9SAndroid Build Coastguard Worker// In addition to implementing the GenerateBuildActions method, a Module should 52*1fa6dee9SAndroid Build Coastguard Worker// implement methods that provide dependant modules and singletons information 53*1fa6dee9SAndroid Build Coastguard Worker// they need to generate their build actions. These methods will only be called 54*1fa6dee9SAndroid Build Coastguard Worker// after GenerateBuildActions is called because the Context calls 55*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions in dependency-order (and singletons are invoked after 56*1fa6dee9SAndroid Build Coastguard Worker// all the Modules). The set of methods a Module supports will determine how 57*1fa6dee9SAndroid Build Coastguard Worker// dependant Modules interact with it. 58*1fa6dee9SAndroid Build Coastguard Worker// 59*1fa6dee9SAndroid Build Coastguard Worker// For example, consider a Module that is responsible for generating a library 60*1fa6dee9SAndroid Build Coastguard Worker// that other modules can link against. The library Module might implement the 61*1fa6dee9SAndroid Build Coastguard Worker// following interface: 62*1fa6dee9SAndroid Build Coastguard Worker// 63*1fa6dee9SAndroid Build Coastguard Worker// type LibraryProducer interface { 64*1fa6dee9SAndroid Build Coastguard Worker// LibraryFileName() string 65*1fa6dee9SAndroid Build Coastguard Worker// } 66*1fa6dee9SAndroid Build Coastguard Worker// 67*1fa6dee9SAndroid Build Coastguard Worker// func IsLibraryProducer(module blueprint.Module) { 68*1fa6dee9SAndroid Build Coastguard Worker// _, ok := module.(LibraryProducer) 69*1fa6dee9SAndroid Build Coastguard Worker// return ok 70*1fa6dee9SAndroid Build Coastguard Worker// } 71*1fa6dee9SAndroid Build Coastguard Worker// 72*1fa6dee9SAndroid Build Coastguard Worker// A binary-producing Module that depends on the library Module could then do: 73*1fa6dee9SAndroid Build Coastguard Worker// 74*1fa6dee9SAndroid Build Coastguard Worker// func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) { 75*1fa6dee9SAndroid Build Coastguard Worker// ... 76*1fa6dee9SAndroid Build Coastguard Worker// var libraryFiles []string 77*1fa6dee9SAndroid Build Coastguard Worker// ctx.VisitDepsDepthFirstIf(IsLibraryProducer, 78*1fa6dee9SAndroid Build Coastguard Worker// func(module blueprint.Module) { 79*1fa6dee9SAndroid Build Coastguard Worker// libProducer := module.(LibraryProducer) 80*1fa6dee9SAndroid Build Coastguard Worker// libraryFiles = append(libraryFiles, libProducer.LibraryFileName()) 81*1fa6dee9SAndroid Build Coastguard Worker// }) 82*1fa6dee9SAndroid Build Coastguard Worker// ... 83*1fa6dee9SAndroid Build Coastguard Worker// } 84*1fa6dee9SAndroid Build Coastguard Worker// 85*1fa6dee9SAndroid Build Coastguard Worker// to build the list of library file names that should be included in its link 86*1fa6dee9SAndroid Build Coastguard Worker// command. 87*1fa6dee9SAndroid Build Coastguard Worker// 88*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions may be called from multiple threads. It is guaranteed to 89*1fa6dee9SAndroid Build Coastguard Worker// be called after it has finished being called on all dependencies and on all 90*1fa6dee9SAndroid Build Coastguard Worker// variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list. 91*1fa6dee9SAndroid Build Coastguard Worker// Any accesses to global variables or to Module objects that are not dependencies 92*1fa6dee9SAndroid Build Coastguard Worker// or variants of the current Module must be synchronized by the implementation of 93*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions. 94*1fa6dee9SAndroid Build Coastguard Workertype Module interface { 95*1fa6dee9SAndroid Build Coastguard Worker // Name returns a string used to uniquely identify each module. The return 96*1fa6dee9SAndroid Build Coastguard Worker // value must be unique across all modules. It is only called once, during 97*1fa6dee9SAndroid Build Coastguard Worker // initial blueprint parsing. To change the name later a mutator must call 98*1fa6dee9SAndroid Build Coastguard Worker // MutatorContext.Rename 99*1fa6dee9SAndroid Build Coastguard Worker // 100*1fa6dee9SAndroid Build Coastguard Worker // In most cases, Name should return the contents of a "name:" property from 101*1fa6dee9SAndroid Build Coastguard Worker // the blueprint file. An embeddable SimpleName object can be used for this 102*1fa6dee9SAndroid Build Coastguard Worker // case. 103*1fa6dee9SAndroid Build Coastguard Worker Name() string 104*1fa6dee9SAndroid Build Coastguard Worker 105*1fa6dee9SAndroid Build Coastguard Worker // GenerateBuildActions is called by the Context that created the Module 106*1fa6dee9SAndroid Build Coastguard Worker // during its generate phase. This call should generate all Ninja build 107*1fa6dee9SAndroid Build Coastguard Worker // actions (rules, pools, and build statements) needed to build the module. 108*1fa6dee9SAndroid Build Coastguard Worker GenerateBuildActions(ModuleContext) 109*1fa6dee9SAndroid Build Coastguard Worker} 110*1fa6dee9SAndroid Build Coastguard Worker 111*1fa6dee9SAndroid Build Coastguard Workertype ModuleProxy struct { 112*1fa6dee9SAndroid Build Coastguard Worker module Module 113*1fa6dee9SAndroid Build Coastguard Worker} 114*1fa6dee9SAndroid Build Coastguard Worker 115*1fa6dee9SAndroid Build Coastguard Workerfunc CreateModuleProxy(module Module) ModuleProxy { 116*1fa6dee9SAndroid Build Coastguard Worker return ModuleProxy{ 117*1fa6dee9SAndroid Build Coastguard Worker module: module, 118*1fa6dee9SAndroid Build Coastguard Worker } 119*1fa6dee9SAndroid Build Coastguard Worker} 120*1fa6dee9SAndroid Build Coastguard Worker 121*1fa6dee9SAndroid Build Coastguard Workerfunc (m ModuleProxy) Name() string { 122*1fa6dee9SAndroid Build Coastguard Worker return m.module.Name() 123*1fa6dee9SAndroid Build Coastguard Worker} 124*1fa6dee9SAndroid Build Coastguard Worker 125*1fa6dee9SAndroid Build Coastguard Workerfunc (m ModuleProxy) GenerateBuildActions(context ModuleContext) { 126*1fa6dee9SAndroid Build Coastguard Worker m.module.GenerateBuildActions(context) 127*1fa6dee9SAndroid Build Coastguard Worker} 128*1fa6dee9SAndroid Build Coastguard Worker 129*1fa6dee9SAndroid Build Coastguard Worker// A DynamicDependerModule is a Module that may add dependencies that do not 130*1fa6dee9SAndroid Build Coastguard Worker// appear in its "deps" property. Any Module that implements this interface 131*1fa6dee9SAndroid Build Coastguard Worker// will have its DynamicDependencies method called by the Context that created 132*1fa6dee9SAndroid Build Coastguard Worker// it during generate phase. 133*1fa6dee9SAndroid Build Coastguard Worker// 134*1fa6dee9SAndroid Build Coastguard Worker// Deprecated, use a BottomUpMutator instead 135*1fa6dee9SAndroid Build Coastguard Workertype DynamicDependerModule interface { 136*1fa6dee9SAndroid Build Coastguard Worker Module 137*1fa6dee9SAndroid Build Coastguard Worker 138*1fa6dee9SAndroid Build Coastguard Worker // DynamicDependencies is called by the Context that created the 139*1fa6dee9SAndroid Build Coastguard Worker // DynamicDependerModule during its generate phase. This call should return 140*1fa6dee9SAndroid Build Coastguard Worker // the list of module names that the DynamicDependerModule depends on 141*1fa6dee9SAndroid Build Coastguard Worker // dynamically. Module names that already appear in the "deps" property may 142*1fa6dee9SAndroid Build Coastguard Worker // but do not need to be included in the returned list. 143*1fa6dee9SAndroid Build Coastguard Worker DynamicDependencies(DynamicDependerModuleContext) []string 144*1fa6dee9SAndroid Build Coastguard Worker} 145*1fa6dee9SAndroid Build Coastguard Worker 146*1fa6dee9SAndroid Build Coastguard Workertype EarlyModuleContext interface { 147*1fa6dee9SAndroid Build Coastguard Worker // Module returns the current module as a Module. It should rarely be necessary, as the module already has a 148*1fa6dee9SAndroid Build Coastguard Worker // reference to itself. 149*1fa6dee9SAndroid Build Coastguard Worker Module() Module 150*1fa6dee9SAndroid Build Coastguard Worker 151*1fa6dee9SAndroid Build Coastguard Worker // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when 152*1fa6dee9SAndroid Build Coastguard Worker // the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename. 153*1fa6dee9SAndroid Build Coastguard Worker ModuleName() string 154*1fa6dee9SAndroid Build Coastguard Worker 155*1fa6dee9SAndroid Build Coastguard Worker // ModuleDir returns the path to the directory that contains the definition of the module. 156*1fa6dee9SAndroid Build Coastguard Worker ModuleDir() string 157*1fa6dee9SAndroid Build Coastguard Worker 158*1fa6dee9SAndroid Build Coastguard Worker // ModuleType returns the name of the module type that was used to create the module, as specified in 159*1fa6dee9SAndroid Build Coastguard Worker // Context.RegisterModuleType(). 160*1fa6dee9SAndroid Build Coastguard Worker ModuleType() string 161*1fa6dee9SAndroid Build Coastguard Worker 162*1fa6dee9SAndroid Build Coastguard Worker // ModuleTags returns the tags for this module that should be passed to 163*1fa6dee9SAndroid Build Coastguard Worker // ninja for analysis. For example: 164*1fa6dee9SAndroid Build Coastguard Worker // [ 165*1fa6dee9SAndroid Build Coastguard Worker // "module_name": "libfoo", 166*1fa6dee9SAndroid Build Coastguard Worker // "module_type": "cc_library", 167*1fa6dee9SAndroid Build Coastguard Worker // ] 168*1fa6dee9SAndroid Build Coastguard Worker ModuleTags() map[string]string 169*1fa6dee9SAndroid Build Coastguard Worker 170*1fa6dee9SAndroid Build Coastguard Worker // BlueprintsFile returns the name of the blueprint file that contains the definition of this 171*1fa6dee9SAndroid Build Coastguard Worker // module. 172*1fa6dee9SAndroid Build Coastguard Worker BlueprintsFile() string 173*1fa6dee9SAndroid Build Coastguard Worker 174*1fa6dee9SAndroid Build Coastguard Worker // Config returns the config object that was passed to Context.PrepareBuildActions. 175*1fa6dee9SAndroid Build Coastguard Worker Config() interface{} 176*1fa6dee9SAndroid Build Coastguard Worker 177*1fa6dee9SAndroid Build Coastguard Worker // ContainsProperty returns true if the specified property name was set in the module definition. 178*1fa6dee9SAndroid Build Coastguard Worker ContainsProperty(name string) bool 179*1fa6dee9SAndroid Build Coastguard Worker 180*1fa6dee9SAndroid Build Coastguard Worker // Errorf reports an error at the specified position of the module definition file. 181*1fa6dee9SAndroid Build Coastguard Worker Errorf(pos scanner.Position, fmt string, args ...interface{}) 182*1fa6dee9SAndroid Build Coastguard Worker 183*1fa6dee9SAndroid Build Coastguard Worker // ModuleErrorf reports an error at the line number of the module type in the module definition. 184*1fa6dee9SAndroid Build Coastguard Worker ModuleErrorf(fmt string, args ...interface{}) 185*1fa6dee9SAndroid Build Coastguard Worker 186*1fa6dee9SAndroid Build Coastguard Worker // PropertyErrorf reports an error at the line number of a property in the module definition. 187*1fa6dee9SAndroid Build Coastguard Worker PropertyErrorf(property, fmt string, args ...interface{}) 188*1fa6dee9SAndroid Build Coastguard Worker 189*1fa6dee9SAndroid Build Coastguard Worker // OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition. 190*1fa6dee9SAndroid Build Coastguard Worker OtherModulePropertyErrorf(logicModule Module, property string, format string, args ...interface{}) 191*1fa6dee9SAndroid Build Coastguard Worker 192*1fa6dee9SAndroid Build Coastguard Worker // Failed returns true if any errors have been reported. In most cases the module can continue with generating 193*1fa6dee9SAndroid Build Coastguard Worker // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error 194*1fa6dee9SAndroid Build Coastguard Worker // has prevented the module from creating necessary data it can return early when Failed returns true. 195*1fa6dee9SAndroid Build Coastguard Worker Failed() bool 196*1fa6dee9SAndroid Build Coastguard Worker 197*1fa6dee9SAndroid Build Coastguard Worker // GlobWithDeps returns a list of files and directories that match the 198*1fa6dee9SAndroid Build Coastguard Worker // specified pattern but do not match any of the patterns in excludes. 199*1fa6dee9SAndroid Build Coastguard Worker // Any directories will have a '/' suffix. It also adds efficient 200*1fa6dee9SAndroid Build Coastguard Worker // dependencies to rerun the primary builder whenever a file matching 201*1fa6dee9SAndroid Build Coastguard Worker // the pattern as added or removed, without rerunning if a file that 202*1fa6dee9SAndroid Build Coastguard Worker // does not match the pattern is added to a searched directory. 203*1fa6dee9SAndroid Build Coastguard Worker GlobWithDeps(pattern string, excludes []string) ([]string, error) 204*1fa6dee9SAndroid Build Coastguard Worker 205*1fa6dee9SAndroid Build Coastguard Worker // Fs returns a pathtools.Filesystem that can be used to interact with files. Using the Filesystem interface allows 206*1fa6dee9SAndroid Build Coastguard Worker // the module to be used in build system tests that run against a mock filesystem. 207*1fa6dee9SAndroid Build Coastguard Worker Fs() pathtools.FileSystem 208*1fa6dee9SAndroid Build Coastguard Worker 209*1fa6dee9SAndroid Build Coastguard Worker // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The 210*1fa6dee9SAndroid Build Coastguard Worker // primary builder will be rerun whenever the specified files are modified. 211*1fa6dee9SAndroid Build Coastguard Worker AddNinjaFileDeps(deps ...string) 212*1fa6dee9SAndroid Build Coastguard Worker 213*1fa6dee9SAndroid Build Coastguard Worker moduleInfo() *moduleInfo 214*1fa6dee9SAndroid Build Coastguard Worker 215*1fa6dee9SAndroid Build Coastguard Worker error(err error) 216*1fa6dee9SAndroid Build Coastguard Worker 217*1fa6dee9SAndroid Build Coastguard Worker // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the 218*1fa6dee9SAndroid Build Coastguard Worker // default SimpleNameInterface if Context.SetNameInterface was not called. 219*1fa6dee9SAndroid Build Coastguard Worker Namespace() Namespace 220*1fa6dee9SAndroid Build Coastguard Worker 221*1fa6dee9SAndroid Build Coastguard Worker // ModuleFactories returns a map of all of the global ModuleFactories by name. 222*1fa6dee9SAndroid Build Coastguard Worker ModuleFactories() map[string]ModuleFactory 223*1fa6dee9SAndroid Build Coastguard Worker 224*1fa6dee9SAndroid Build Coastguard Worker // HasMutatorFinished returns true if the given mutator has finished running. 225*1fa6dee9SAndroid Build Coastguard Worker // It will panic if given an invalid mutator name. 226*1fa6dee9SAndroid Build Coastguard Worker HasMutatorFinished(mutatorName string) bool 227*1fa6dee9SAndroid Build Coastguard Worker} 228*1fa6dee9SAndroid Build Coastguard Worker 229*1fa6dee9SAndroid Build Coastguard Workertype BaseModuleContext interface { 230*1fa6dee9SAndroid Build Coastguard Worker EarlyModuleContext 231*1fa6dee9SAndroid Build Coastguard Worker 232*1fa6dee9SAndroid Build Coastguard Worker // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if 233*1fa6dee9SAndroid Build Coastguard Worker // none exists. It panics if the dependency does not have the specified tag. 234*1fa6dee9SAndroid Build Coastguard Worker GetDirectDepWithTag(name string, tag DependencyTag) Module 235*1fa6dee9SAndroid Build Coastguard Worker 236*1fa6dee9SAndroid Build Coastguard Worker // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified 237*1fa6dee9SAndroid Build Coastguard Worker // name, or nil if none exists. If there are multiple dependencies on the same module it returns 238*1fa6dee9SAndroid Build Coastguard Worker // the first DependencyTag. 239*1fa6dee9SAndroid Build Coastguard Worker GetDirectDep(name string) (Module, DependencyTag) 240*1fa6dee9SAndroid Build Coastguard Worker 241*1fa6dee9SAndroid Build Coastguard Worker // VisitDirectDeps calls visit for each direct dependency. If there are multiple direct dependencies on the same 242*1fa6dee9SAndroid Build Coastguard Worker // module visit will be called multiple times on that module and OtherModuleDependencyTag will return a different 243*1fa6dee9SAndroid Build Coastguard Worker // tag for each. 244*1fa6dee9SAndroid Build Coastguard Worker // 245*1fa6dee9SAndroid Build Coastguard Worker // The Module passed to the visit function should not be retained outside of the visit function, it may be 246*1fa6dee9SAndroid Build Coastguard Worker // invalidated by future mutators. 247*1fa6dee9SAndroid Build Coastguard Worker VisitDirectDeps(visit func(Module)) 248*1fa6dee9SAndroid Build Coastguard Worker 249*1fa6dee9SAndroid Build Coastguard Worker VisitDirectDepsProxy(visit func(proxy ModuleProxy)) 250*1fa6dee9SAndroid Build Coastguard Worker 251*1fa6dee9SAndroid Build Coastguard Worker // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are 252*1fa6dee9SAndroid Build Coastguard Worker // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and 253*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleDependencyTag will return a different tag for each. 254*1fa6dee9SAndroid Build Coastguard Worker // 255*1fa6dee9SAndroid Build Coastguard Worker // The Module passed to the visit function should not be retained outside of the visit function, it may be 256*1fa6dee9SAndroid Build Coastguard Worker // invalidated by future mutators. 257*1fa6dee9SAndroid Build Coastguard Worker VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) 258*1fa6dee9SAndroid Build Coastguard Worker 259*1fa6dee9SAndroid Build Coastguard Worker // VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first 260*1fa6dee9SAndroid Build Coastguard Worker // order. visit will only be called once for any given module, even if there are multiple paths through the 261*1fa6dee9SAndroid Build Coastguard Worker // dependency tree to the module or multiple direct dependencies with different tags. OtherModuleDependencyTag will 262*1fa6dee9SAndroid Build Coastguard Worker // return the tag for the first path found to the module. 263*1fa6dee9SAndroid Build Coastguard Worker // 264*1fa6dee9SAndroid Build Coastguard Worker // The Module passed to the visit function should not be retained outside of the visit function, it may be 265*1fa6dee9SAndroid Build Coastguard Worker // invalidated by future mutators. 266*1fa6dee9SAndroid Build Coastguard Worker VisitDepsDepthFirst(visit func(Module)) 267*1fa6dee9SAndroid Build Coastguard Worker 268*1fa6dee9SAndroid Build Coastguard Worker // VisitDepsDepthFirstIf calls pred for each transitive dependency, and if pred returns true calls visit, traversing 269*1fa6dee9SAndroid Build Coastguard Worker // the dependency tree in depth first order. visit will only be called once for any given module, even if there are 270*1fa6dee9SAndroid Build Coastguard Worker // multiple paths through the dependency tree to the module or multiple direct dependencies with different tags. 271*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleDependencyTag will return the tag for the first path found to the module. The return value of pred 272*1fa6dee9SAndroid Build Coastguard Worker // does not affect which branches of the tree are traversed. 273*1fa6dee9SAndroid Build Coastguard Worker // 274*1fa6dee9SAndroid Build Coastguard Worker // The Module passed to the visit function should not be retained outside of the visit function, it may be 275*1fa6dee9SAndroid Build Coastguard Worker // invalidated by future mutators. 276*1fa6dee9SAndroid Build Coastguard Worker VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) 277*1fa6dee9SAndroid Build Coastguard Worker 278*1fa6dee9SAndroid Build Coastguard Worker // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may 279*1fa6dee9SAndroid Build Coastguard Worker // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the 280*1fa6dee9SAndroid Build Coastguard Worker // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited 281*1fa6dee9SAndroid Build Coastguard Worker // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. 282*1fa6dee9SAndroid Build Coastguard Worker // 283*1fa6dee9SAndroid Build Coastguard Worker // The Modules passed to the visit function should not be retained outside of the visit function, they may be 284*1fa6dee9SAndroid Build Coastguard Worker // invalidated by future mutators. 285*1fa6dee9SAndroid Build Coastguard Worker WalkDeps(visit func(Module, Module) bool) 286*1fa6dee9SAndroid Build Coastguard Worker 287*1fa6dee9SAndroid Build Coastguard Worker WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool) 288*1fa6dee9SAndroid Build Coastguard Worker 289*1fa6dee9SAndroid Build Coastguard Worker // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in 290*1fa6dee9SAndroid Build Coastguard Worker // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the 291*1fa6dee9SAndroid Build Coastguard Worker // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are 292*1fa6dee9SAndroid Build Coastguard Worker // only done once for all variants of a module. 293*1fa6dee9SAndroid Build Coastguard Worker PrimaryModule() Module 294*1fa6dee9SAndroid Build Coastguard Worker 295*1fa6dee9SAndroid Build Coastguard Worker // FinalModule returns the last variant of the current module. Variants of a module are always visited in 296*1fa6dee9SAndroid Build Coastguard Worker // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all 297*1fa6dee9SAndroid Build Coastguard Worker // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform 298*1fa6dee9SAndroid Build Coastguard Worker // singleton actions that are only done once for all variants of a module. 299*1fa6dee9SAndroid Build Coastguard Worker FinalModule() Module 300*1fa6dee9SAndroid Build Coastguard Worker 301*1fa6dee9SAndroid Build Coastguard Worker // IsFinalModule returns if the current module is the last variant. Variants of a module are always visited in 302*1fa6dee9SAndroid Build Coastguard Worker // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all 303*1fa6dee9SAndroid Build Coastguard Worker // variants using VisitAllModuleVariants if the current module is the last one. This can be used to perform 304*1fa6dee9SAndroid Build Coastguard Worker // singleton actions that are only done once for all variants of a module. 305*1fa6dee9SAndroid Build Coastguard Worker IsFinalModule(module Module) bool 306*1fa6dee9SAndroid Build Coastguard Worker 307*1fa6dee9SAndroid Build Coastguard Worker // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always 308*1fa6dee9SAndroid Build Coastguard Worker // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read 309*1fa6dee9SAndroid Build Coastguard Worker // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 310*1fa6dee9SAndroid Build Coastguard Worker // data modified by the current mutator. 311*1fa6dee9SAndroid Build Coastguard Worker VisitAllModuleVariants(visit func(Module)) 312*1fa6dee9SAndroid Build Coastguard Worker 313*1fa6dee9SAndroid Build Coastguard Worker // VisitAllModuleVariantProxies calls visit for each variant of the current module. Variants of a module are always 314*1fa6dee9SAndroid Build Coastguard Worker // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read 315*1fa6dee9SAndroid Build Coastguard Worker // from all variants if the current module is the last one. Otherwise, care must be taken to not access any 316*1fa6dee9SAndroid Build Coastguard Worker // data modified by the current mutator. 317*1fa6dee9SAndroid Build Coastguard Worker VisitAllModuleVariantProxies(visit func(proxy ModuleProxy)) 318*1fa6dee9SAndroid Build Coastguard Worker 319*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information. 320*1fa6dee9SAndroid Build Coastguard Worker // It is intended for use inside the visit functions of Visit* and WalkDeps. 321*1fa6dee9SAndroid Build Coastguard Worker OtherModuleName(m Module) string 322*1fa6dee9SAndroid Build Coastguard Worker 323*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information. 324*1fa6dee9SAndroid Build Coastguard Worker // It is intended for use inside the visit functions of Visit* and WalkDeps. 325*1fa6dee9SAndroid Build Coastguard Worker OtherModuleDir(m Module) string 326*1fa6dee9SAndroid Build Coastguard Worker 327*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information. 328*1fa6dee9SAndroid Build Coastguard Worker // It is intended for use inside the visit functions of Visit* and WalkDeps. 329*1fa6dee9SAndroid Build Coastguard Worker OtherModuleType(m Module) string 330*1fa6dee9SAndroid Build Coastguard Worker 331*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information. 332*1fa6dee9SAndroid Build Coastguard Worker // It is intended for use inside the visit functions of Visit* and WalkDeps. 333*1fa6dee9SAndroid Build Coastguard Worker OtherModuleErrorf(m Module, fmt string, args ...interface{}) 334*1fa6dee9SAndroid Build Coastguard Worker 335*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency 336*1fa6dee9SAndroid Build Coastguard Worker // on the module. When called inside a Visit* method with current module being visited, and there are multiple 337*1fa6dee9SAndroid Build Coastguard Worker // dependencies on the module being visited, it returns the dependency tag used for the current dependency. 338*1fa6dee9SAndroid Build Coastguard Worker OtherModuleDependencyTag(m Module) DependencyTag 339*1fa6dee9SAndroid Build Coastguard Worker 340*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface 341*1fa6dee9SAndroid Build Coastguard Worker // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called. 342*1fa6dee9SAndroid Build Coastguard Worker OtherModuleExists(name string) bool 343*1fa6dee9SAndroid Build Coastguard Worker 344*1fa6dee9SAndroid Build Coastguard Worker // ModuleFromName returns (module, true) if a module exists by the given name and same context namespace, 345*1fa6dee9SAndroid Build Coastguard Worker // or (nil, false) if it does not exist. It panics if there is either more than one 346*1fa6dee9SAndroid Build Coastguard Worker // module of the given name, or if the given name refers to an alias instead of a module. 347*1fa6dee9SAndroid Build Coastguard Worker // There are no guarantees about which variant of the module will be returned. 348*1fa6dee9SAndroid Build Coastguard Worker // Prefer retrieving the module using GetDirectDep or a visit function, when possible, as 349*1fa6dee9SAndroid Build Coastguard Worker // this will guarantee the appropriate module-variant dependency is returned. 350*1fa6dee9SAndroid Build Coastguard Worker // 351*1fa6dee9SAndroid Build Coastguard Worker // WARNING: This should _only_ be used within the context of bp2build, where variants and 352*1fa6dee9SAndroid Build Coastguard Worker // dependencies are not created. 353*1fa6dee9SAndroid Build Coastguard Worker ModuleFromName(name string) (Module, bool) 354*1fa6dee9SAndroid Build Coastguard Worker 355*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleDependencyVariantExists returns true if a module with the 356*1fa6dee9SAndroid Build Coastguard Worker // specified name and variant exists. The variant must match the given 357*1fa6dee9SAndroid Build Coastguard Worker // variations. It must also match all the non-local variations of the current 358*1fa6dee9SAndroid Build Coastguard Worker // module. In other words, it checks for the module that AddVariationDependencies 359*1fa6dee9SAndroid Build Coastguard Worker // would add a dependency on with the same arguments. 360*1fa6dee9SAndroid Build Coastguard Worker OtherModuleDependencyVariantExists(variations []Variation, name string) bool 361*1fa6dee9SAndroid Build Coastguard Worker 362*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleFarDependencyVariantExists returns true if a module with the 363*1fa6dee9SAndroid Build Coastguard Worker // specified name and variant exists. The variant must match the given 364*1fa6dee9SAndroid Build Coastguard Worker // variations, but not the non-local variations of the current module. In 365*1fa6dee9SAndroid Build Coastguard Worker // other words, it checks for the module that AddFarVariationDependencies 366*1fa6dee9SAndroid Build Coastguard Worker // would add a dependency on with the same arguments. 367*1fa6dee9SAndroid Build Coastguard Worker OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool 368*1fa6dee9SAndroid Build Coastguard Worker 369*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleReverseDependencyVariantExists returns true if a module with the 370*1fa6dee9SAndroid Build Coastguard Worker // specified name exists with the same variations as the current module. In 371*1fa6dee9SAndroid Build Coastguard Worker // other words, it checks for the module that AddReverseDependency would add a 372*1fa6dee9SAndroid Build Coastguard Worker // dependency on with the same argument. 373*1fa6dee9SAndroid Build Coastguard Worker OtherModuleReverseDependencyVariantExists(name string) bool 374*1fa6dee9SAndroid Build Coastguard Worker 375*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleProvider returns the value for a provider for the given module. If the value is 376*1fa6dee9SAndroid Build Coastguard Worker // not set it returns nil and false. The value returned may be a deep copy of the value originally 377*1fa6dee9SAndroid Build Coastguard Worker // passed to SetProvider. 378*1fa6dee9SAndroid Build Coastguard Worker // 379*1fa6dee9SAndroid Build Coastguard Worker // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead. 380*1fa6dee9SAndroid Build Coastguard Worker OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool) 381*1fa6dee9SAndroid Build Coastguard Worker 382*1fa6dee9SAndroid Build Coastguard Worker // OtherModuleIsAutoGenerated returns true if a module has been generated from another module, 383*1fa6dee9SAndroid Build Coastguard Worker // instead of being defined in Android.bp file 384*1fa6dee9SAndroid Build Coastguard Worker OtherModuleIsAutoGenerated(m Module) bool 385*1fa6dee9SAndroid Build Coastguard Worker 386*1fa6dee9SAndroid Build Coastguard Worker // Provider returns the value for a provider for the current module. If the value is 387*1fa6dee9SAndroid Build Coastguard Worker // not set it returns nil and false. It panics if called before the appropriate 388*1fa6dee9SAndroid Build Coastguard Worker // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep 389*1fa6dee9SAndroid Build Coastguard Worker // copy of the value originally passed to SetProvider. 390*1fa6dee9SAndroid Build Coastguard Worker // 391*1fa6dee9SAndroid Build Coastguard Worker // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead. 392*1fa6dee9SAndroid Build Coastguard Worker Provider(provider AnyProviderKey) (any, bool) 393*1fa6dee9SAndroid Build Coastguard Worker 394*1fa6dee9SAndroid Build Coastguard Worker // SetProvider sets the value for a provider for the current module. It panics if not called 395*1fa6dee9SAndroid Build Coastguard Worker // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value 396*1fa6dee9SAndroid Build Coastguard Worker // is not of the appropriate type, or if the value has already been set. The value should not 397*1fa6dee9SAndroid Build Coastguard Worker // be modified after being passed to SetProvider. 398*1fa6dee9SAndroid Build Coastguard Worker // 399*1fa6dee9SAndroid Build Coastguard Worker // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead. 400*1fa6dee9SAndroid Build Coastguard Worker SetProvider(provider AnyProviderKey, value any) 401*1fa6dee9SAndroid Build Coastguard Worker 402*1fa6dee9SAndroid Build Coastguard Worker EarlyGetMissingDependencies() []string 403*1fa6dee9SAndroid Build Coastguard Worker 404*1fa6dee9SAndroid Build Coastguard Worker EqualModules(m1, m2 Module) bool 405*1fa6dee9SAndroid Build Coastguard Worker 406*1fa6dee9SAndroid Build Coastguard Worker base() *baseModuleContext 407*1fa6dee9SAndroid Build Coastguard Worker} 408*1fa6dee9SAndroid Build Coastguard Worker 409*1fa6dee9SAndroid Build Coastguard Workertype DynamicDependerModuleContext BottomUpMutatorContext 410*1fa6dee9SAndroid Build Coastguard Worker 411*1fa6dee9SAndroid Build Coastguard Workertype ModuleContext interface { 412*1fa6dee9SAndroid Build Coastguard Worker BaseModuleContext 413*1fa6dee9SAndroid Build Coastguard Worker 414*1fa6dee9SAndroid Build Coastguard Worker // ModuleSubDir returns a unique name for the current variant of a module that can be used as part of the path 415*1fa6dee9SAndroid Build Coastguard Worker // to ensure that each variant of a module gets its own intermediates directory to write to. 416*1fa6dee9SAndroid Build Coastguard Worker ModuleSubDir() string 417*1fa6dee9SAndroid Build Coastguard Worker 418*1fa6dee9SAndroid Build Coastguard Worker ModuleCacheKey() string 419*1fa6dee9SAndroid Build Coastguard Worker 420*1fa6dee9SAndroid Build Coastguard Worker // Variable creates a new ninja variable scoped to the module. It can be referenced by calls to Rule and Build 421*1fa6dee9SAndroid Build Coastguard Worker // in the same module. 422*1fa6dee9SAndroid Build Coastguard Worker Variable(pctx PackageContext, name, value string) 423*1fa6dee9SAndroid Build Coastguard Worker 424*1fa6dee9SAndroid Build Coastguard Worker // Rule creates a new ninja rule scoped to the module. It can be referenced by calls to Build in the same module. 425*1fa6dee9SAndroid Build Coastguard Worker Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule 426*1fa6dee9SAndroid Build Coastguard Worker 427*1fa6dee9SAndroid Build Coastguard Worker // Build creates a new ninja build statement. 428*1fa6dee9SAndroid Build Coastguard Worker Build(pctx PackageContext, params BuildParams) 429*1fa6dee9SAndroid Build Coastguard Worker 430*1fa6dee9SAndroid Build Coastguard Worker // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods, 431*1fa6dee9SAndroid Build Coastguard Worker // but do not exist. It can be used with Context.SetAllowMissingDependencies to allow the primary builder to 432*1fa6dee9SAndroid Build Coastguard Worker // handle missing dependencies on its own instead of having Blueprint treat them as an error. 433*1fa6dee9SAndroid Build Coastguard Worker GetMissingDependencies() []string 434*1fa6dee9SAndroid Build Coastguard Worker} 435*1fa6dee9SAndroid Build Coastguard Worker 436*1fa6dee9SAndroid Build Coastguard Workervar _ BaseModuleContext = (*baseModuleContext)(nil) 437*1fa6dee9SAndroid Build Coastguard Worker 438*1fa6dee9SAndroid Build Coastguard Workertype baseModuleContext struct { 439*1fa6dee9SAndroid Build Coastguard Worker context *Context 440*1fa6dee9SAndroid Build Coastguard Worker config interface{} 441*1fa6dee9SAndroid Build Coastguard Worker module *moduleInfo 442*1fa6dee9SAndroid Build Coastguard Worker errs []error 443*1fa6dee9SAndroid Build Coastguard Worker visitingParent *moduleInfo 444*1fa6dee9SAndroid Build Coastguard Worker visitingDep depInfo 445*1fa6dee9SAndroid Build Coastguard Worker ninjaFileDeps []string 446*1fa6dee9SAndroid Build Coastguard Worker} 447*1fa6dee9SAndroid Build Coastguard Worker 448*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) moduleInfo() *moduleInfo { 449*1fa6dee9SAndroid Build Coastguard Worker return d.module 450*1fa6dee9SAndroid Build Coastguard Worker} 451*1fa6dee9SAndroid Build Coastguard Worker 452*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Module() Module { 453*1fa6dee9SAndroid Build Coastguard Worker return d.module.logicModule 454*1fa6dee9SAndroid Build Coastguard Worker} 455*1fa6dee9SAndroid Build Coastguard Worker 456*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleName() string { 457*1fa6dee9SAndroid Build Coastguard Worker return d.module.Name() 458*1fa6dee9SAndroid Build Coastguard Worker} 459*1fa6dee9SAndroid Build Coastguard Worker 460*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleType() string { 461*1fa6dee9SAndroid Build Coastguard Worker return d.module.typeName 462*1fa6dee9SAndroid Build Coastguard Worker} 463*1fa6dee9SAndroid Build Coastguard Worker 464*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleTags() map[string]string { 465*1fa6dee9SAndroid Build Coastguard Worker return map[string]string{ 466*1fa6dee9SAndroid Build Coastguard Worker "module_name": d.ModuleName(), 467*1fa6dee9SAndroid Build Coastguard Worker "module_type": d.ModuleType(), 468*1fa6dee9SAndroid Build Coastguard Worker } 469*1fa6dee9SAndroid Build Coastguard Worker} 470*1fa6dee9SAndroid Build Coastguard Worker 471*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ContainsProperty(name string) bool { 472*1fa6dee9SAndroid Build Coastguard Worker _, ok := d.module.propertyPos[name] 473*1fa6dee9SAndroid Build Coastguard Worker return ok 474*1fa6dee9SAndroid Build Coastguard Worker} 475*1fa6dee9SAndroid Build Coastguard Worker 476*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleDir() string { 477*1fa6dee9SAndroid Build Coastguard Worker return filepath.Dir(d.module.relBlueprintsFile) 478*1fa6dee9SAndroid Build Coastguard Worker} 479*1fa6dee9SAndroid Build Coastguard Worker 480*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) BlueprintsFile() string { 481*1fa6dee9SAndroid Build Coastguard Worker return d.module.relBlueprintsFile 482*1fa6dee9SAndroid Build Coastguard Worker} 483*1fa6dee9SAndroid Build Coastguard Worker 484*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Config() interface{} { 485*1fa6dee9SAndroid Build Coastguard Worker return d.config 486*1fa6dee9SAndroid Build Coastguard Worker} 487*1fa6dee9SAndroid Build Coastguard Worker 488*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) error(err error) { 489*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 490*1fa6dee9SAndroid Build Coastguard Worker d.errs = append(d.errs, err) 491*1fa6dee9SAndroid Build Coastguard Worker } 492*1fa6dee9SAndroid Build Coastguard Worker} 493*1fa6dee9SAndroid Build Coastguard Worker 494*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Errorf(pos scanner.Position, 495*1fa6dee9SAndroid Build Coastguard Worker format string, args ...interface{}) { 496*1fa6dee9SAndroid Build Coastguard Worker 497*1fa6dee9SAndroid Build Coastguard Worker d.error(&BlueprintError{ 498*1fa6dee9SAndroid Build Coastguard Worker Err: fmt.Errorf(format, args...), 499*1fa6dee9SAndroid Build Coastguard Worker Pos: pos, 500*1fa6dee9SAndroid Build Coastguard Worker }) 501*1fa6dee9SAndroid Build Coastguard Worker} 502*1fa6dee9SAndroid Build Coastguard Worker 503*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleErrorf(format string, 504*1fa6dee9SAndroid Build Coastguard Worker args ...interface{}) { 505*1fa6dee9SAndroid Build Coastguard Worker 506*1fa6dee9SAndroid Build Coastguard Worker d.error(d.context.moduleErrorf(d.module, format, args...)) 507*1fa6dee9SAndroid Build Coastguard Worker} 508*1fa6dee9SAndroid Build Coastguard Worker 509*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) PropertyErrorf(property, format string, 510*1fa6dee9SAndroid Build Coastguard Worker args ...interface{}) { 511*1fa6dee9SAndroid Build Coastguard Worker 512*1fa6dee9SAndroid Build Coastguard Worker d.error(d.context.PropertyErrorf(d.module.logicModule, property, format, args...)) 513*1fa6dee9SAndroid Build Coastguard Worker} 514*1fa6dee9SAndroid Build Coastguard Worker 515*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) OtherModulePropertyErrorf(logicModule Module, property string, format string, 516*1fa6dee9SAndroid Build Coastguard Worker args ...interface{}) { 517*1fa6dee9SAndroid Build Coastguard Worker 518*1fa6dee9SAndroid Build Coastguard Worker d.error(d.context.PropertyErrorf(logicModule, property, format, args...)) 519*1fa6dee9SAndroid Build Coastguard Worker} 520*1fa6dee9SAndroid Build Coastguard Worker 521*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Failed() bool { 522*1fa6dee9SAndroid Build Coastguard Worker return len(d.errs) > 0 523*1fa6dee9SAndroid Build Coastguard Worker} 524*1fa6dee9SAndroid Build Coastguard Worker 525*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) GlobWithDeps(pattern string, 526*1fa6dee9SAndroid Build Coastguard Worker excludes []string) ([]string, error) { 527*1fa6dee9SAndroid Build Coastguard Worker return d.context.glob(pattern, excludes) 528*1fa6dee9SAndroid Build Coastguard Worker} 529*1fa6dee9SAndroid Build Coastguard Worker 530*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Fs() pathtools.FileSystem { 531*1fa6dee9SAndroid Build Coastguard Worker return d.context.fs 532*1fa6dee9SAndroid Build Coastguard Worker} 533*1fa6dee9SAndroid Build Coastguard Worker 534*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Namespace() Namespace { 535*1fa6dee9SAndroid Build Coastguard Worker return d.context.nameInterface.GetNamespace(newNamespaceContext(d.module)) 536*1fa6dee9SAndroid Build Coastguard Worker} 537*1fa6dee9SAndroid Build Coastguard Worker 538*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) HasMutatorFinished(mutatorName string) bool { 539*1fa6dee9SAndroid Build Coastguard Worker return d.context.HasMutatorFinished(mutatorName) 540*1fa6dee9SAndroid Build Coastguard Worker} 541*1fa6dee9SAndroid Build Coastguard Worker 542*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleContext = (*moduleContext)(nil) 543*1fa6dee9SAndroid Build Coastguard Worker 544*1fa6dee9SAndroid Build Coastguard Workertype moduleContext struct { 545*1fa6dee9SAndroid Build Coastguard Worker baseModuleContext 546*1fa6dee9SAndroid Build Coastguard Worker scope *localScope 547*1fa6dee9SAndroid Build Coastguard Worker actionDefs localBuildActions 548*1fa6dee9SAndroid Build Coastguard Worker handledMissingDeps bool 549*1fa6dee9SAndroid Build Coastguard Worker} 550*1fa6dee9SAndroid Build Coastguard Worker 551*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) EqualModules(m1, m2 Module) bool { 552*1fa6dee9SAndroid Build Coastguard Worker return getWrappedModule(m1) == getWrappedModule(m2) 553*1fa6dee9SAndroid Build Coastguard Worker} 554*1fa6dee9SAndroid Build Coastguard Worker 555*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleName(logicModule Module) string { 556*1fa6dee9SAndroid Build Coastguard Worker module := m.context.moduleInfo[getWrappedModule(logicModule)] 557*1fa6dee9SAndroid Build Coastguard Worker return module.Name() 558*1fa6dee9SAndroid Build Coastguard Worker} 559*1fa6dee9SAndroid Build Coastguard Worker 560*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleDir(logicModule Module) string { 561*1fa6dee9SAndroid Build Coastguard Worker module := m.context.moduleInfo[getWrappedModule(logicModule)] 562*1fa6dee9SAndroid Build Coastguard Worker return filepath.Dir(module.relBlueprintsFile) 563*1fa6dee9SAndroid Build Coastguard Worker} 564*1fa6dee9SAndroid Build Coastguard Worker 565*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleType(logicModule Module) string { 566*1fa6dee9SAndroid Build Coastguard Worker module := m.context.moduleInfo[getWrappedModule(logicModule)] 567*1fa6dee9SAndroid Build Coastguard Worker return module.typeName 568*1fa6dee9SAndroid Build Coastguard Worker} 569*1fa6dee9SAndroid Build Coastguard Worker 570*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string, 571*1fa6dee9SAndroid Build Coastguard Worker args ...interface{}) { 572*1fa6dee9SAndroid Build Coastguard Worker 573*1fa6dee9SAndroid Build Coastguard Worker module := m.context.moduleInfo[getWrappedModule(logicModule)] 574*1fa6dee9SAndroid Build Coastguard Worker m.errs = append(m.errs, &ModuleError{ 575*1fa6dee9SAndroid Build Coastguard Worker BlueprintError: BlueprintError{ 576*1fa6dee9SAndroid Build Coastguard Worker Err: fmt.Errorf(format, args...), 577*1fa6dee9SAndroid Build Coastguard Worker Pos: module.pos, 578*1fa6dee9SAndroid Build Coastguard Worker }, 579*1fa6dee9SAndroid Build Coastguard Worker module: module, 580*1fa6dee9SAndroid Build Coastguard Worker }) 581*1fa6dee9SAndroid Build Coastguard Worker} 582*1fa6dee9SAndroid Build Coastguard Worker 583*1fa6dee9SAndroid Build Coastguard Workerfunc getWrappedModule(module Module) Module { 584*1fa6dee9SAndroid Build Coastguard Worker if mp, isProxy := module.(ModuleProxy); isProxy { 585*1fa6dee9SAndroid Build Coastguard Worker return mp.module 586*1fa6dee9SAndroid Build Coastguard Worker } 587*1fa6dee9SAndroid Build Coastguard Worker return module 588*1fa6dee9SAndroid Build Coastguard Worker} 589*1fa6dee9SAndroid Build Coastguard Worker 590*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag { 591*1fa6dee9SAndroid Build Coastguard Worker // fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps 592*1fa6dee9SAndroid Build Coastguard Worker if m.visitingDep.module != nil && getWrappedModule(logicModule) == m.visitingDep.module.logicModule { 593*1fa6dee9SAndroid Build Coastguard Worker return m.visitingDep.tag 594*1fa6dee9SAndroid Build Coastguard Worker } 595*1fa6dee9SAndroid Build Coastguard Worker 596*1fa6dee9SAndroid Build Coastguard Worker if m.visitingParent == nil { 597*1fa6dee9SAndroid Build Coastguard Worker return nil 598*1fa6dee9SAndroid Build Coastguard Worker } 599*1fa6dee9SAndroid Build Coastguard Worker 600*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range m.visitingParent.directDeps { 601*1fa6dee9SAndroid Build Coastguard Worker if dep.module.logicModule == getWrappedModule(logicModule) { 602*1fa6dee9SAndroid Build Coastguard Worker return dep.tag 603*1fa6dee9SAndroid Build Coastguard Worker } 604*1fa6dee9SAndroid Build Coastguard Worker } 605*1fa6dee9SAndroid Build Coastguard Worker 606*1fa6dee9SAndroid Build Coastguard Worker return nil 607*1fa6dee9SAndroid Build Coastguard Worker} 608*1fa6dee9SAndroid Build Coastguard Worker 609*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) ModuleFromName(name string) (Module, bool) { 610*1fa6dee9SAndroid Build Coastguard Worker moduleGroup, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace()) 611*1fa6dee9SAndroid Build Coastguard Worker if exists { 612*1fa6dee9SAndroid Build Coastguard Worker if len(moduleGroup.modules) != 1 { 613*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("Expected exactly one module named %q, but got %d", name, len(moduleGroup.modules))) 614*1fa6dee9SAndroid Build Coastguard Worker } 615*1fa6dee9SAndroid Build Coastguard Worker moduleInfo := moduleGroup.modules[0] 616*1fa6dee9SAndroid Build Coastguard Worker if moduleInfo != nil { 617*1fa6dee9SAndroid Build Coastguard Worker return moduleInfo.logicModule, true 618*1fa6dee9SAndroid Build Coastguard Worker } else { 619*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf(`Expected actual module named %q, but group did not contain a module. 620*1fa6dee9SAndroid Build Coastguard Worker There may instead be an alias by that name.`, name)) 621*1fa6dee9SAndroid Build Coastguard Worker } 622*1fa6dee9SAndroid Build Coastguard Worker } 623*1fa6dee9SAndroid Build Coastguard Worker return nil, exists 624*1fa6dee9SAndroid Build Coastguard Worker} 625*1fa6dee9SAndroid Build Coastguard Worker 626*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleExists(name string) bool { 627*1fa6dee9SAndroid Build Coastguard Worker _, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace()) 628*1fa6dee9SAndroid Build Coastguard Worker return exists 629*1fa6dee9SAndroid Build Coastguard Worker} 630*1fa6dee9SAndroid Build Coastguard Worker 631*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleDependencyVariantExists(variations []Variation, name string) bool { 632*1fa6dee9SAndroid Build Coastguard Worker possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace()) 633*1fa6dee9SAndroid Build Coastguard Worker if possibleDeps == nil { 634*1fa6dee9SAndroid Build Coastguard Worker return false 635*1fa6dee9SAndroid Build Coastguard Worker } 636*1fa6dee9SAndroid Build Coastguard Worker found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, variations, false, false) 637*1fa6dee9SAndroid Build Coastguard Worker if errs != nil { 638*1fa6dee9SAndroid Build Coastguard Worker panic(errors.Join(errs...)) 639*1fa6dee9SAndroid Build Coastguard Worker } 640*1fa6dee9SAndroid Build Coastguard Worker return found != nil 641*1fa6dee9SAndroid Build Coastguard Worker} 642*1fa6dee9SAndroid Build Coastguard Worker 643*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool { 644*1fa6dee9SAndroid Build Coastguard Worker possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace()) 645*1fa6dee9SAndroid Build Coastguard Worker if possibleDeps == nil { 646*1fa6dee9SAndroid Build Coastguard Worker return false 647*1fa6dee9SAndroid Build Coastguard Worker } 648*1fa6dee9SAndroid Build Coastguard Worker found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, variations, true, false) 649*1fa6dee9SAndroid Build Coastguard Worker if errs != nil { 650*1fa6dee9SAndroid Build Coastguard Worker panic(errors.Join(errs...)) 651*1fa6dee9SAndroid Build Coastguard Worker } 652*1fa6dee9SAndroid Build Coastguard Worker return found != nil 653*1fa6dee9SAndroid Build Coastguard Worker} 654*1fa6dee9SAndroid Build Coastguard Worker 655*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool { 656*1fa6dee9SAndroid Build Coastguard Worker possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace()) 657*1fa6dee9SAndroid Build Coastguard Worker if possibleDeps == nil { 658*1fa6dee9SAndroid Build Coastguard Worker return false 659*1fa6dee9SAndroid Build Coastguard Worker } 660*1fa6dee9SAndroid Build Coastguard Worker found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, nil, false, true) 661*1fa6dee9SAndroid Build Coastguard Worker if errs != nil { 662*1fa6dee9SAndroid Build Coastguard Worker panic(errors.Join(errs...)) 663*1fa6dee9SAndroid Build Coastguard Worker } 664*1fa6dee9SAndroid Build Coastguard Worker return found != nil 665*1fa6dee9SAndroid Build Coastguard Worker} 666*1fa6dee9SAndroid Build Coastguard Worker 667*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) { 668*1fa6dee9SAndroid Build Coastguard Worker module := m.context.moduleInfo[getWrappedModule(logicModule)] 669*1fa6dee9SAndroid Build Coastguard Worker return m.context.provider(module, provider.provider()) 670*1fa6dee9SAndroid Build Coastguard Worker} 671*1fa6dee9SAndroid Build Coastguard Worker 672*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) Provider(provider AnyProviderKey) (any, bool) { 673*1fa6dee9SAndroid Build Coastguard Worker return m.context.provider(m.module, provider.provider()) 674*1fa6dee9SAndroid Build Coastguard Worker} 675*1fa6dee9SAndroid Build Coastguard Worker 676*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) SetProvider(provider AnyProviderKey, value interface{}) { 677*1fa6dee9SAndroid Build Coastguard Worker m.context.setProvider(m.module, provider.provider(), value) 678*1fa6dee9SAndroid Build Coastguard Worker} 679*1fa6dee9SAndroid Build Coastguard Worker 680*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) cacheModuleBuildActions(key *BuildActionCacheKey) { 681*1fa6dee9SAndroid Build Coastguard Worker var providers []CachedProvider 682*1fa6dee9SAndroid Build Coastguard Worker for i, p := range m.module.providers { 683*1fa6dee9SAndroid Build Coastguard Worker if p != nil && providerRegistry[i].mutator == "" { 684*1fa6dee9SAndroid Build Coastguard Worker providers = append(providers, 685*1fa6dee9SAndroid Build Coastguard Worker CachedProvider{ 686*1fa6dee9SAndroid Build Coastguard Worker Id: providerRegistry[i], 687*1fa6dee9SAndroid Build Coastguard Worker Value: &p, 688*1fa6dee9SAndroid Build Coastguard Worker }) 689*1fa6dee9SAndroid Build Coastguard Worker } 690*1fa6dee9SAndroid Build Coastguard Worker } 691*1fa6dee9SAndroid Build Coastguard Worker 692*1fa6dee9SAndroid Build Coastguard Worker // These show up in the ninja file, so we need to cache these to ensure we 693*1fa6dee9SAndroid Build Coastguard Worker // re-generate ninja file if they changed. 694*1fa6dee9SAndroid Build Coastguard Worker relPos := m.module.pos 695*1fa6dee9SAndroid Build Coastguard Worker relPos.Filename = m.module.relBlueprintsFile 696*1fa6dee9SAndroid Build Coastguard Worker data := BuildActionCachedData{ 697*1fa6dee9SAndroid Build Coastguard Worker Providers: providers, 698*1fa6dee9SAndroid Build Coastguard Worker Pos: &relPos, 699*1fa6dee9SAndroid Build Coastguard Worker } 700*1fa6dee9SAndroid Build Coastguard Worker 701*1fa6dee9SAndroid Build Coastguard Worker m.context.updateBuildActionsCache(key, &data) 702*1fa6dee9SAndroid Build Coastguard Worker} 703*1fa6dee9SAndroid Build Coastguard Worker 704*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) restoreModuleBuildActions() (bool, *BuildActionCacheKey) { 705*1fa6dee9SAndroid Build Coastguard Worker // Whether the incremental flag is set and the module type supports 706*1fa6dee9SAndroid Build Coastguard Worker // incremental, this will decide weather to cache the data for the module. 707*1fa6dee9SAndroid Build Coastguard Worker incrementalEnabled := false 708*1fa6dee9SAndroid Build Coastguard Worker // Whether the above conditions are true and we can try to restore from 709*1fa6dee9SAndroid Build Coastguard Worker // the cache for this module, i.e., no env, product variables and Soong 710*1fa6dee9SAndroid Build Coastguard Worker // code changes. 711*1fa6dee9SAndroid Build Coastguard Worker incrementalAnalysis := false 712*1fa6dee9SAndroid Build Coastguard Worker var cacheKey *BuildActionCacheKey = nil 713*1fa6dee9SAndroid Build Coastguard Worker if m.context.GetIncrementalEnabled() { 714*1fa6dee9SAndroid Build Coastguard Worker if im, ok := m.module.logicModule.(Incremental); ok { 715*1fa6dee9SAndroid Build Coastguard Worker incrementalEnabled = im.IncrementalSupported() 716*1fa6dee9SAndroid Build Coastguard Worker incrementalAnalysis = m.context.GetIncrementalAnalysis() && incrementalEnabled 717*1fa6dee9SAndroid Build Coastguard Worker } 718*1fa6dee9SAndroid Build Coastguard Worker } 719*1fa6dee9SAndroid Build Coastguard Worker if incrementalEnabled { 720*1fa6dee9SAndroid Build Coastguard Worker hash, err := proptools.CalculateHash(m.module.properties) 721*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 722*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(err, "failed to calculate properties hash")) 723*1fa6dee9SAndroid Build Coastguard Worker } 724*1fa6dee9SAndroid Build Coastguard Worker cacheInput := new(BuildActionCacheInput) 725*1fa6dee9SAndroid Build Coastguard Worker cacheInput.PropertiesHash = hash 726*1fa6dee9SAndroid Build Coastguard Worker m.VisitDirectDeps(func(module Module) { 727*1fa6dee9SAndroid Build Coastguard Worker cacheInput.ProvidersHash = 728*1fa6dee9SAndroid Build Coastguard Worker append(cacheInput.ProvidersHash, m.context.moduleInfo[module].providerInitialValueHashes) 729*1fa6dee9SAndroid Build Coastguard Worker }) 730*1fa6dee9SAndroid Build Coastguard Worker hash, err = proptools.CalculateHash(&cacheInput) 731*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 732*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(err, "failed to calculate cache input hash")) 733*1fa6dee9SAndroid Build Coastguard Worker } 734*1fa6dee9SAndroid Build Coastguard Worker cacheKey = &BuildActionCacheKey{ 735*1fa6dee9SAndroid Build Coastguard Worker Id: m.ModuleCacheKey(), 736*1fa6dee9SAndroid Build Coastguard Worker InputHash: hash, 737*1fa6dee9SAndroid Build Coastguard Worker } 738*1fa6dee9SAndroid Build Coastguard Worker m.module.buildActionCacheKey = cacheKey 739*1fa6dee9SAndroid Build Coastguard Worker } 740*1fa6dee9SAndroid Build Coastguard Worker 741*1fa6dee9SAndroid Build Coastguard Worker restored := false 742*1fa6dee9SAndroid Build Coastguard Worker if incrementalAnalysis && cacheKey != nil { 743*1fa6dee9SAndroid Build Coastguard Worker // Try to restore from cache if there is a cache hit 744*1fa6dee9SAndroid Build Coastguard Worker data := m.context.getBuildActionsFromCache(cacheKey) 745*1fa6dee9SAndroid Build Coastguard Worker relPos := m.module.pos 746*1fa6dee9SAndroid Build Coastguard Worker relPos.Filename = m.module.relBlueprintsFile 747*1fa6dee9SAndroid Build Coastguard Worker if data != nil && data.Pos != nil && relPos == *data.Pos { 748*1fa6dee9SAndroid Build Coastguard Worker for _, provider := range data.Providers { 749*1fa6dee9SAndroid Build Coastguard Worker m.context.setProvider(m.module, provider.Id, *provider.Value) 750*1fa6dee9SAndroid Build Coastguard Worker } 751*1fa6dee9SAndroid Build Coastguard Worker m.module.incrementalRestored = true 752*1fa6dee9SAndroid Build Coastguard Worker m.module.orderOnlyStrings = data.OrderOnlyStrings 753*1fa6dee9SAndroid Build Coastguard Worker restored = true 754*1fa6dee9SAndroid Build Coastguard Worker } 755*1fa6dee9SAndroid Build Coastguard Worker } 756*1fa6dee9SAndroid Build Coastguard Worker 757*1fa6dee9SAndroid Build Coastguard Worker return restored, cacheKey 758*1fa6dee9SAndroid Build Coastguard Worker} 759*1fa6dee9SAndroid Build Coastguard Worker 760*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) GetDirectDep(name string) (Module, DependencyTag) { 761*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range m.module.directDeps { 762*1fa6dee9SAndroid Build Coastguard Worker if dep.module.Name() == name { 763*1fa6dee9SAndroid Build Coastguard Worker return dep.module.logicModule, dep.tag 764*1fa6dee9SAndroid Build Coastguard Worker } 765*1fa6dee9SAndroid Build Coastguard Worker } 766*1fa6dee9SAndroid Build Coastguard Worker 767*1fa6dee9SAndroid Build Coastguard Worker return nil, nil 768*1fa6dee9SAndroid Build Coastguard Worker} 769*1fa6dee9SAndroid Build Coastguard Worker 770*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) GetDirectDepWithTag(name string, tag DependencyTag) Module { 771*1fa6dee9SAndroid Build Coastguard Worker var deps []depInfo 772*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range m.module.directDeps { 773*1fa6dee9SAndroid Build Coastguard Worker if dep.module.Name() == name { 774*1fa6dee9SAndroid Build Coastguard Worker if dep.tag == tag { 775*1fa6dee9SAndroid Build Coastguard Worker return dep.module.logicModule 776*1fa6dee9SAndroid Build Coastguard Worker } 777*1fa6dee9SAndroid Build Coastguard Worker deps = append(deps, dep) 778*1fa6dee9SAndroid Build Coastguard Worker } 779*1fa6dee9SAndroid Build Coastguard Worker } 780*1fa6dee9SAndroid Build Coastguard Worker 781*1fa6dee9SAndroid Build Coastguard Worker if len(deps) != 0 { 782*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("Unable to find dependency %q with requested tag %#v. Found: %#v", deps[0].module, tag, deps)) 783*1fa6dee9SAndroid Build Coastguard Worker } 784*1fa6dee9SAndroid Build Coastguard Worker 785*1fa6dee9SAndroid Build Coastguard Worker return nil 786*1fa6dee9SAndroid Build Coastguard Worker} 787*1fa6dee9SAndroid Build Coastguard Worker 788*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDirectDeps(visit func(Module)) { 789*1fa6dee9SAndroid Build Coastguard Worker defer func() { 790*1fa6dee9SAndroid Build Coastguard Worker if r := recover(); r != nil { 791*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s", 792*1fa6dee9SAndroid Build Coastguard Worker m.module, funcName(visit), m.visitingDep.module)) 793*1fa6dee9SAndroid Build Coastguard Worker } 794*1fa6dee9SAndroid Build Coastguard Worker }() 795*1fa6dee9SAndroid Build Coastguard Worker 796*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = m.module 797*1fa6dee9SAndroid Build Coastguard Worker 798*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range m.module.directDeps { 799*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 800*1fa6dee9SAndroid Build Coastguard Worker visit(dep.module.logicModule) 801*1fa6dee9SAndroid Build Coastguard Worker } 802*1fa6dee9SAndroid Build Coastguard Worker 803*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 804*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 805*1fa6dee9SAndroid Build Coastguard Worker} 806*1fa6dee9SAndroid Build Coastguard Worker 807*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDirectDepsProxy(visit func(proxy ModuleProxy)) { 808*1fa6dee9SAndroid Build Coastguard Worker defer func() { 809*1fa6dee9SAndroid Build Coastguard Worker if r := recover(); r != nil { 810*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s", 811*1fa6dee9SAndroid Build Coastguard Worker m.module, funcName(visit), m.visitingDep.module)) 812*1fa6dee9SAndroid Build Coastguard Worker } 813*1fa6dee9SAndroid Build Coastguard Worker }() 814*1fa6dee9SAndroid Build Coastguard Worker 815*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = m.module 816*1fa6dee9SAndroid Build Coastguard Worker 817*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range m.module.directDeps { 818*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 819*1fa6dee9SAndroid Build Coastguard Worker visit(ModuleProxy{dep.module.logicModule}) 820*1fa6dee9SAndroid Build Coastguard Worker } 821*1fa6dee9SAndroid Build Coastguard Worker 822*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 823*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 824*1fa6dee9SAndroid Build Coastguard Worker} 825*1fa6dee9SAndroid Build Coastguard Worker 826*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { 827*1fa6dee9SAndroid Build Coastguard Worker defer func() { 828*1fa6dee9SAndroid Build Coastguard Worker if r := recover(); r != nil { 829*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s", 830*1fa6dee9SAndroid Build Coastguard Worker m.module, funcName(pred), funcName(visit), m.visitingDep.module)) 831*1fa6dee9SAndroid Build Coastguard Worker } 832*1fa6dee9SAndroid Build Coastguard Worker }() 833*1fa6dee9SAndroid Build Coastguard Worker 834*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = m.module 835*1fa6dee9SAndroid Build Coastguard Worker 836*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range m.module.directDeps { 837*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 838*1fa6dee9SAndroid Build Coastguard Worker if pred(dep.module.logicModule) { 839*1fa6dee9SAndroid Build Coastguard Worker visit(dep.module.logicModule) 840*1fa6dee9SAndroid Build Coastguard Worker } 841*1fa6dee9SAndroid Build Coastguard Worker } 842*1fa6dee9SAndroid Build Coastguard Worker 843*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 844*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 845*1fa6dee9SAndroid Build Coastguard Worker} 846*1fa6dee9SAndroid Build Coastguard Worker 847*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) { 848*1fa6dee9SAndroid Build Coastguard Worker defer func() { 849*1fa6dee9SAndroid Build Coastguard Worker if r := recover(); r != nil { 850*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s", 851*1fa6dee9SAndroid Build Coastguard Worker m.module, funcName(visit), m.visitingDep.module)) 852*1fa6dee9SAndroid Build Coastguard Worker } 853*1fa6dee9SAndroid Build Coastguard Worker }() 854*1fa6dee9SAndroid Build Coastguard Worker 855*1fa6dee9SAndroid Build Coastguard Worker m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) { 856*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = parent 857*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 858*1fa6dee9SAndroid Build Coastguard Worker visit(dep.module.logicModule) 859*1fa6dee9SAndroid Build Coastguard Worker }) 860*1fa6dee9SAndroid Build Coastguard Worker 861*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 862*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 863*1fa6dee9SAndroid Build Coastguard Worker} 864*1fa6dee9SAndroid Build Coastguard Worker 865*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, 866*1fa6dee9SAndroid Build Coastguard Worker visit func(Module)) { 867*1fa6dee9SAndroid Build Coastguard Worker 868*1fa6dee9SAndroid Build Coastguard Worker defer func() { 869*1fa6dee9SAndroid Build Coastguard Worker if r := recover(); r != nil { 870*1fa6dee9SAndroid Build Coastguard Worker panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s", 871*1fa6dee9SAndroid Build Coastguard Worker m.module, funcName(pred), funcName(visit), m.visitingDep.module)) 872*1fa6dee9SAndroid Build Coastguard Worker } 873*1fa6dee9SAndroid Build Coastguard Worker }() 874*1fa6dee9SAndroid Build Coastguard Worker 875*1fa6dee9SAndroid Build Coastguard Worker m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) { 876*1fa6dee9SAndroid Build Coastguard Worker if pred(dep.module.logicModule) { 877*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = parent 878*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 879*1fa6dee9SAndroid Build Coastguard Worker visit(dep.module.logicModule) 880*1fa6dee9SAndroid Build Coastguard Worker } 881*1fa6dee9SAndroid Build Coastguard Worker }) 882*1fa6dee9SAndroid Build Coastguard Worker 883*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 884*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 885*1fa6dee9SAndroid Build Coastguard Worker} 886*1fa6dee9SAndroid Build Coastguard Worker 887*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) WalkDeps(visit func(child, parent Module) bool) { 888*1fa6dee9SAndroid Build Coastguard Worker m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool { 889*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = parent 890*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 891*1fa6dee9SAndroid Build Coastguard Worker return visit(dep.module.logicModule, parent.logicModule) 892*1fa6dee9SAndroid Build Coastguard Worker }, nil) 893*1fa6dee9SAndroid Build Coastguard Worker 894*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 895*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 896*1fa6dee9SAndroid Build Coastguard Worker} 897*1fa6dee9SAndroid Build Coastguard Worker 898*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) WalkDepsProxy(visit func(child, parent ModuleProxy) bool) { 899*1fa6dee9SAndroid Build Coastguard Worker m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool { 900*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = parent 901*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = dep 902*1fa6dee9SAndroid Build Coastguard Worker return visit(ModuleProxy{dep.module.logicModule}, ModuleProxy{parent.logicModule}) 903*1fa6dee9SAndroid Build Coastguard Worker }, nil) 904*1fa6dee9SAndroid Build Coastguard Worker 905*1fa6dee9SAndroid Build Coastguard Worker m.visitingParent = nil 906*1fa6dee9SAndroid Build Coastguard Worker m.visitingDep = depInfo{} 907*1fa6dee9SAndroid Build Coastguard Worker} 908*1fa6dee9SAndroid Build Coastguard Worker 909*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) PrimaryModule() Module { 910*1fa6dee9SAndroid Build Coastguard Worker return m.module.group.modules.firstModule().logicModule 911*1fa6dee9SAndroid Build Coastguard Worker} 912*1fa6dee9SAndroid Build Coastguard Worker 913*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) FinalModule() Module { 914*1fa6dee9SAndroid Build Coastguard Worker return m.module.group.modules.lastModule().logicModule 915*1fa6dee9SAndroid Build Coastguard Worker} 916*1fa6dee9SAndroid Build Coastguard Worker 917*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) IsFinalModule(module Module) bool { 918*1fa6dee9SAndroid Build Coastguard Worker return m.module.group.modules.lastModule().logicModule == module 919*1fa6dee9SAndroid Build Coastguard Worker} 920*1fa6dee9SAndroid Build Coastguard Worker 921*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitAllModuleVariants(visit func(Module)) { 922*1fa6dee9SAndroid Build Coastguard Worker m.context.visitAllModuleVariants(m.module, visit) 923*1fa6dee9SAndroid Build Coastguard Worker} 924*1fa6dee9SAndroid Build Coastguard Worker 925*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitAllModuleVariantProxies(visit func(proxy ModuleProxy)) { 926*1fa6dee9SAndroid Build Coastguard Worker m.context.visitAllModuleVariants(m.module, visitProxyAdaptor(visit)) 927*1fa6dee9SAndroid Build Coastguard Worker} 928*1fa6dee9SAndroid Build Coastguard Worker 929*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) AddNinjaFileDeps(deps ...string) { 930*1fa6dee9SAndroid Build Coastguard Worker m.ninjaFileDeps = append(m.ninjaFileDeps, deps...) 931*1fa6dee9SAndroid Build Coastguard Worker} 932*1fa6dee9SAndroid Build Coastguard Worker 933*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) ModuleFactories() map[string]ModuleFactory { 934*1fa6dee9SAndroid Build Coastguard Worker return m.context.ModuleTypeFactories() 935*1fa6dee9SAndroid Build Coastguard Worker} 936*1fa6dee9SAndroid Build Coastguard Worker 937*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) base() *baseModuleContext { 938*1fa6dee9SAndroid Build Coastguard Worker return m 939*1fa6dee9SAndroid Build Coastguard Worker} 940*1fa6dee9SAndroid Build Coastguard Worker 941*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleIsAutoGenerated(logicModule Module) bool { 942*1fa6dee9SAndroid Build Coastguard Worker module := m.context.moduleInfo[getWrappedModule(logicModule)] 943*1fa6dee9SAndroid Build Coastguard Worker if module == nil { 944*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("Module %s not found in baseModuleContext", logicModule.Name())) 945*1fa6dee9SAndroid Build Coastguard Worker } 946*1fa6dee9SAndroid Build Coastguard Worker return module.createdBy != nil 947*1fa6dee9SAndroid Build Coastguard Worker} 948*1fa6dee9SAndroid Build Coastguard Worker 949*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) ModuleSubDir() string { 950*1fa6dee9SAndroid Build Coastguard Worker return m.module.variant.name 951*1fa6dee9SAndroid Build Coastguard Worker} 952*1fa6dee9SAndroid Build Coastguard Worker 953*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) ModuleCacheKey() string { 954*1fa6dee9SAndroid Build Coastguard Worker return m.module.ModuleCacheKey() 955*1fa6dee9SAndroid Build Coastguard Worker} 956*1fa6dee9SAndroid Build Coastguard Worker 957*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) Variable(pctx PackageContext, name, value string) { 958*1fa6dee9SAndroid Build Coastguard Worker m.scope.ReparentTo(pctx) 959*1fa6dee9SAndroid Build Coastguard Worker 960*1fa6dee9SAndroid Build Coastguard Worker v, err := m.scope.AddLocalVariable(name, value) 961*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 962*1fa6dee9SAndroid Build Coastguard Worker panic(err) 963*1fa6dee9SAndroid Build Coastguard Worker } 964*1fa6dee9SAndroid Build Coastguard Worker 965*1fa6dee9SAndroid Build Coastguard Worker m.actionDefs.variables = append(m.actionDefs.variables, v) 966*1fa6dee9SAndroid Build Coastguard Worker} 967*1fa6dee9SAndroid Build Coastguard Worker 968*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) Rule(pctx PackageContext, name string, 969*1fa6dee9SAndroid Build Coastguard Worker params RuleParams, argNames ...string) Rule { 970*1fa6dee9SAndroid Build Coastguard Worker 971*1fa6dee9SAndroid Build Coastguard Worker m.scope.ReparentTo(pctx) 972*1fa6dee9SAndroid Build Coastguard Worker 973*1fa6dee9SAndroid Build Coastguard Worker r, err := m.scope.AddLocalRule(name, ¶ms, argNames...) 974*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 975*1fa6dee9SAndroid Build Coastguard Worker panic(err) 976*1fa6dee9SAndroid Build Coastguard Worker } 977*1fa6dee9SAndroid Build Coastguard Worker 978*1fa6dee9SAndroid Build Coastguard Worker m.actionDefs.rules = append(m.actionDefs.rules, r) 979*1fa6dee9SAndroid Build Coastguard Worker 980*1fa6dee9SAndroid Build Coastguard Worker return r 981*1fa6dee9SAndroid Build Coastguard Worker} 982*1fa6dee9SAndroid Build Coastguard Worker 983*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) Build(pctx PackageContext, params BuildParams) { 984*1fa6dee9SAndroid Build Coastguard Worker m.scope.ReparentTo(pctx) 985*1fa6dee9SAndroid Build Coastguard Worker 986*1fa6dee9SAndroid Build Coastguard Worker def, err := parseBuildParams(m.scope, ¶ms, m.ModuleTags()) 987*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 988*1fa6dee9SAndroid Build Coastguard Worker panic(err) 989*1fa6dee9SAndroid Build Coastguard Worker } 990*1fa6dee9SAndroid Build Coastguard Worker 991*1fa6dee9SAndroid Build Coastguard Worker m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def) 992*1fa6dee9SAndroid Build Coastguard Worker} 993*1fa6dee9SAndroid Build Coastguard Worker 994*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) GetMissingDependencies() []string { 995*1fa6dee9SAndroid Build Coastguard Worker m.handledMissingDeps = true 996*1fa6dee9SAndroid Build Coastguard Worker return m.module.missingDeps 997*1fa6dee9SAndroid Build Coastguard Worker} 998*1fa6dee9SAndroid Build Coastguard Worker 999*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) EarlyGetMissingDependencies() []string { 1000*1fa6dee9SAndroid Build Coastguard Worker return m.module.missingDeps 1001*1fa6dee9SAndroid Build Coastguard Worker} 1002*1fa6dee9SAndroid Build Coastguard Worker 1003*1fa6dee9SAndroid Build Coastguard Worker// 1004*1fa6dee9SAndroid Build Coastguard Worker// MutatorContext 1005*1fa6dee9SAndroid Build Coastguard Worker// 1006*1fa6dee9SAndroid Build Coastguard Worker 1007*1fa6dee9SAndroid Build Coastguard Workertype mutatorContext struct { 1008*1fa6dee9SAndroid Build Coastguard Worker baseModuleContext 1009*1fa6dee9SAndroid Build Coastguard Worker mutator *mutatorInfo 1010*1fa6dee9SAndroid Build Coastguard Worker reverseDeps []reverseDep 1011*1fa6dee9SAndroid Build Coastguard Worker rename []rename 1012*1fa6dee9SAndroid Build Coastguard Worker replace []replace 1013*1fa6dee9SAndroid Build Coastguard Worker newVariations moduleList // new variants of existing modules 1014*1fa6dee9SAndroid Build Coastguard Worker newModules []*moduleInfo // brand new modules 1015*1fa6dee9SAndroid Build Coastguard Worker defaultVariation *string 1016*1fa6dee9SAndroid Build Coastguard Worker pauseCh chan<- pauseSpec 1017*1fa6dee9SAndroid Build Coastguard Worker} 1018*1fa6dee9SAndroid Build Coastguard Worker 1019*1fa6dee9SAndroid Build Coastguard Workertype TopDownMutatorContext interface { 1020*1fa6dee9SAndroid Build Coastguard Worker BaseModuleContext 1021*1fa6dee9SAndroid Build Coastguard Worker} 1022*1fa6dee9SAndroid Build Coastguard Worker 1023*1fa6dee9SAndroid Build Coastguard Workertype BottomUpMutatorContext interface { 1024*1fa6dee9SAndroid Build Coastguard Worker BaseModuleContext 1025*1fa6dee9SAndroid Build Coastguard Worker 1026*1fa6dee9SAndroid Build Coastguard Worker // AddDependency adds a dependency to the given module. It returns a slice of modules for each 1027*1fa6dee9SAndroid Build Coastguard Worker // dependency (some entries may be nil). Does not affect the ordering of the current mutator 1028*1fa6dee9SAndroid Build Coastguard Worker // pass, but will be ordered correctly for all future mutator passes. 1029*1fa6dee9SAndroid Build Coastguard Worker // 1030*1fa6dee9SAndroid Build Coastguard Worker // This method will pause until the new dependencies have had the current mutator called on them. 1031*1fa6dee9SAndroid Build Coastguard Worker AddDependency(module Module, tag DependencyTag, name ...string) []Module 1032*1fa6dee9SAndroid Build Coastguard Worker 1033*1fa6dee9SAndroid Build Coastguard Worker // AddReverseDependency adds a dependency from the destination to the given module. 1034*1fa6dee9SAndroid Build Coastguard Worker // Does not affect the ordering of the current mutator pass, but will be ordered 1035*1fa6dee9SAndroid Build Coastguard Worker // correctly for all future mutator passes. All reverse dependencies for a destination module are 1036*1fa6dee9SAndroid Build Coastguard Worker // collected until the end of the mutator pass, sorted by name, and then appended to the destination 1037*1fa6dee9SAndroid Build Coastguard Worker // module's dependency list. May only be called by mutators that were marked with 1038*1fa6dee9SAndroid Build Coastguard Worker // UsesReverseDependencies during registration. 1039*1fa6dee9SAndroid Build Coastguard Worker AddReverseDependency(module Module, tag DependencyTag, name string) 1040*1fa6dee9SAndroid Build Coastguard Worker 1041*1fa6dee9SAndroid Build Coastguard Worker // AddVariationDependencies adds deps as dependencies of the current module, but uses the variations 1042*1fa6dee9SAndroid Build Coastguard Worker // argument to select which variant of the dependency to use. It returns a slice of modules for 1043*1fa6dee9SAndroid Build Coastguard Worker // each dependency (some entries may be nil). A variant of the dependency must exist that matches 1044*1fa6dee9SAndroid Build Coastguard Worker // the all of the non-local variations of the current module, plus the variations argument. 1045*1fa6dee9SAndroid Build Coastguard Worker // 1046*1fa6dee9SAndroid Build Coastguard Worker // 1047*1fa6dee9SAndroid Build Coastguard Worker // This method will pause until the new dependencies have had the current mutator called on them. 1048*1fa6dee9SAndroid Build Coastguard Worker AddVariationDependencies([]Variation, DependencyTag, ...string) []Module 1049*1fa6dee9SAndroid Build Coastguard Worker 1050*1fa6dee9SAndroid Build Coastguard Worker // AddReverseVariationDependency adds a dependency from the named module to the current 1051*1fa6dee9SAndroid Build Coastguard Worker // module. The given variations will be added to the current module's varations, and then the 1052*1fa6dee9SAndroid Build Coastguard Worker // result will be used to find the correct variation of the depending module, which must exist. 1053*1fa6dee9SAndroid Build Coastguard Worker // 1054*1fa6dee9SAndroid Build Coastguard Worker // Does not affect the ordering of the current mutator pass, but will be ordered 1055*1fa6dee9SAndroid Build Coastguard Worker // correctly for all future mutator passes. All reverse dependencies for a destination module are 1056*1fa6dee9SAndroid Build Coastguard Worker // collected until the end of the mutator pass, sorted by name, and then appended to the destination 1057*1fa6dee9SAndroid Build Coastguard Worker // module's dependency list. May only be called by mutators that were marked with 1058*1fa6dee9SAndroid Build Coastguard Worker // UsesReverseDependencies during registration. 1059*1fa6dee9SAndroid Build Coastguard Worker AddReverseVariationDependency([]Variation, DependencyTag, string) 1060*1fa6dee9SAndroid Build Coastguard Worker 1061*1fa6dee9SAndroid Build Coastguard Worker // AddFarVariationDependencies adds deps as dependencies of the current module, but uses the 1062*1fa6dee9SAndroid Build Coastguard Worker // variations argument to select which variant of the dependency to use. It returns a slice of 1063*1fa6dee9SAndroid Build Coastguard Worker // modules for each dependency (some entries may be nil). A variant of the dependency must 1064*1fa6dee9SAndroid Build Coastguard Worker // exist that matches the variations argument, but may also have other variations. 1065*1fa6dee9SAndroid Build Coastguard Worker // For any unspecified variation the first variant will be used. 1066*1fa6dee9SAndroid Build Coastguard Worker // 1067*1fa6dee9SAndroid Build Coastguard Worker // Unlike AddVariationDependencies, the variations of the current module are ignored - the 1068*1fa6dee9SAndroid Build Coastguard Worker // dependency only needs to match the supplied variations. 1069*1fa6dee9SAndroid Build Coastguard Worker // 1070*1fa6dee9SAndroid Build Coastguard Worker // 1071*1fa6dee9SAndroid Build Coastguard Worker // This method will pause until the new dependencies have had the current mutator called on them. 1072*1fa6dee9SAndroid Build Coastguard Worker AddFarVariationDependencies([]Variation, DependencyTag, ...string) []Module 1073*1fa6dee9SAndroid Build Coastguard Worker 1074*1fa6dee9SAndroid Build Coastguard Worker // ReplaceDependencies finds all the variants of the module with the specified name, then 1075*1fa6dee9SAndroid Build Coastguard Worker // replaces all dependencies onto those variants with the current variant of this module. 1076*1fa6dee9SAndroid Build Coastguard Worker // Replacements don't take effect until after the mutator pass is finished. May only 1077*1fa6dee9SAndroid Build Coastguard Worker // be called by mutators that were marked with UsesReplaceDependencies during registration. 1078*1fa6dee9SAndroid Build Coastguard Worker ReplaceDependencies(string) 1079*1fa6dee9SAndroid Build Coastguard Worker 1080*1fa6dee9SAndroid Build Coastguard Worker // ReplaceDependenciesIf finds all the variants of the module with the specified name, then 1081*1fa6dee9SAndroid Build Coastguard Worker // replaces all dependencies onto those variants with the current variant of this module 1082*1fa6dee9SAndroid Build Coastguard Worker // as long as the supplied predicate returns true. 1083*1fa6dee9SAndroid Build Coastguard Worker // Replacements don't take effect until after the mutator pass is finished. May only 1084*1fa6dee9SAndroid Build Coastguard Worker // be called by mutators that were marked with UsesReplaceDependencies during registration. 1085*1fa6dee9SAndroid Build Coastguard Worker ReplaceDependenciesIf(string, ReplaceDependencyPredicate) 1086*1fa6dee9SAndroid Build Coastguard Worker 1087*1fa6dee9SAndroid Build Coastguard Worker // Rename all variants of a module. The new name is not visible to calls to ModuleName, 1088*1fa6dee9SAndroid Build Coastguard Worker // AddDependency or OtherModuleName until after this mutator pass is complete. May only be called 1089*1fa6dee9SAndroid Build Coastguard Worker // by mutators that were marked with UsesRename during registration. 1090*1fa6dee9SAndroid Build Coastguard Worker Rename(name string) 1091*1fa6dee9SAndroid Build Coastguard Worker 1092*1fa6dee9SAndroid Build Coastguard Worker // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies 1093*1fa6dee9SAndroid Build Coastguard Worker // the specified property structs to it as if the properties were set in a blueprint file. May only 1094*1fa6dee9SAndroid Build Coastguard Worker // be called by mutators that were marked with UsesCreateModule during registration. 1095*1fa6dee9SAndroid Build Coastguard Worker CreateModule(ModuleFactory, string, ...interface{}) Module 1096*1fa6dee9SAndroid Build Coastguard Worker} 1097*1fa6dee9SAndroid Build Coastguard Worker 1098*1fa6dee9SAndroid Build Coastguard Worker// A Mutator function is called for each Module, and can modify properties on the modules. 1099*1fa6dee9SAndroid Build Coastguard Worker// It is called after parsing all Blueprint files, but before generating any build rules, 1100*1fa6dee9SAndroid Build Coastguard Worker// and is always called on dependencies before being called on the depending module. 1101*1fa6dee9SAndroid Build Coastguard Worker// 1102*1fa6dee9SAndroid Build Coastguard Worker// The Mutator function should only modify members of properties structs, and not 1103*1fa6dee9SAndroid Build Coastguard Worker// members of the module struct itself, to ensure the modified values are copied 1104*1fa6dee9SAndroid Build Coastguard Worker// if a second Mutator chooses to split the module a second time. 1105*1fa6dee9SAndroid Build Coastguard Workertype TopDownMutator func(mctx TopDownMutatorContext) 1106*1fa6dee9SAndroid Build Coastguard Workertype BottomUpMutator func(mctx BottomUpMutatorContext) 1107*1fa6dee9SAndroid Build Coastguard Worker 1108*1fa6dee9SAndroid Build Coastguard Worker// DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag. It can be 1109*1fa6dee9SAndroid Build Coastguard Worker// used to transfer information on a dependency between the mutator that called AddDependency 1110*1fa6dee9SAndroid Build Coastguard Worker// and the GenerateBuildActions method. 1111*1fa6dee9SAndroid Build Coastguard Workertype DependencyTag interface { 1112*1fa6dee9SAndroid Build Coastguard Worker dependencyTag(DependencyTag) 1113*1fa6dee9SAndroid Build Coastguard Worker} 1114*1fa6dee9SAndroid Build Coastguard Worker 1115*1fa6dee9SAndroid Build Coastguard Workertype BaseDependencyTag struct { 1116*1fa6dee9SAndroid Build Coastguard Worker} 1117*1fa6dee9SAndroid Build Coastguard Worker 1118*1fa6dee9SAndroid Build Coastguard Workerfunc (BaseDependencyTag) dependencyTag(DependencyTag) { 1119*1fa6dee9SAndroid Build Coastguard Worker} 1120*1fa6dee9SAndroid Build Coastguard Worker 1121*1fa6dee9SAndroid Build Coastguard Workervar _ DependencyTag = BaseDependencyTag{} 1122*1fa6dee9SAndroid Build Coastguard Worker 1123*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) createVariationsWithTransition(variationNames []string, outgoingTransitions [][]string) []Module { 1124*1fa6dee9SAndroid Build Coastguard Worker return mctx.createVariations(variationNames, chooseDepByIndexes(mctx.mutator.name, outgoingTransitions)) 1125*1fa6dee9SAndroid Build Coastguard Worker} 1126*1fa6dee9SAndroid Build Coastguard Worker 1127*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) createVariations(variationNames []string, depChooser depChooser) []Module { 1128*1fa6dee9SAndroid Build Coastguard Worker var ret []Module 1129*1fa6dee9SAndroid Build Coastguard Worker modules, errs := mctx.context.createVariations(mctx.module, mctx.mutator, depChooser, variationNames) 1130*1fa6dee9SAndroid Build Coastguard Worker if len(errs) > 0 { 1131*1fa6dee9SAndroid Build Coastguard Worker mctx.errs = append(mctx.errs, errs...) 1132*1fa6dee9SAndroid Build Coastguard Worker } 1133*1fa6dee9SAndroid Build Coastguard Worker 1134*1fa6dee9SAndroid Build Coastguard Worker for _, module := range modules { 1135*1fa6dee9SAndroid Build Coastguard Worker ret = append(ret, module.logicModule) 1136*1fa6dee9SAndroid Build Coastguard Worker } 1137*1fa6dee9SAndroid Build Coastguard Worker 1138*1fa6dee9SAndroid Build Coastguard Worker if mctx.newVariations != nil { 1139*1fa6dee9SAndroid Build Coastguard Worker panic("module already has variations from this mutator") 1140*1fa6dee9SAndroid Build Coastguard Worker } 1141*1fa6dee9SAndroid Build Coastguard Worker mctx.newVariations = modules 1142*1fa6dee9SAndroid Build Coastguard Worker 1143*1fa6dee9SAndroid Build Coastguard Worker if len(ret) != len(variationNames) { 1144*1fa6dee9SAndroid Build Coastguard Worker panic("oops!") 1145*1fa6dee9SAndroid Build Coastguard Worker } 1146*1fa6dee9SAndroid Build Coastguard Worker 1147*1fa6dee9SAndroid Build Coastguard Worker return ret 1148*1fa6dee9SAndroid Build Coastguard Worker} 1149*1fa6dee9SAndroid Build Coastguard Worker 1150*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) Module() Module { 1151*1fa6dee9SAndroid Build Coastguard Worker return mctx.module.logicModule 1152*1fa6dee9SAndroid Build Coastguard Worker} 1153*1fa6dee9SAndroid Build Coastguard Worker 1154*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) []Module { 1155*1fa6dee9SAndroid Build Coastguard Worker depInfos := make([]Module, 0, len(deps)) 1156*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range deps { 1157*1fa6dee9SAndroid Build Coastguard Worker modInfo := mctx.context.moduleInfo[module] 1158*1fa6dee9SAndroid Build Coastguard Worker depInfo, errs := mctx.context.addVariationDependency(modInfo, mctx.mutator, mctx.config, nil, tag, dep, false) 1159*1fa6dee9SAndroid Build Coastguard Worker if len(errs) > 0 { 1160*1fa6dee9SAndroid Build Coastguard Worker mctx.errs = append(mctx.errs, errs...) 1161*1fa6dee9SAndroid Build Coastguard Worker } 1162*1fa6dee9SAndroid Build Coastguard Worker if !mctx.pause(depInfo) { 1163*1fa6dee9SAndroid Build Coastguard Worker // Pausing not supported by this mutator, new dependencies can't be returned. 1164*1fa6dee9SAndroid Build Coastguard Worker depInfo = nil 1165*1fa6dee9SAndroid Build Coastguard Worker } 1166*1fa6dee9SAndroid Build Coastguard Worker depInfos = append(depInfos, maybeLogicModule(depInfo)) 1167*1fa6dee9SAndroid Build Coastguard Worker } 1168*1fa6dee9SAndroid Build Coastguard Worker return depInfos 1169*1fa6dee9SAndroid Build Coastguard Worker} 1170*1fa6dee9SAndroid Build Coastguard Worker 1171*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) { 1172*1fa6dee9SAndroid Build Coastguard Worker if !mctx.mutator.usesReverseDependencies { 1173*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("method AddReverseDependency called from mutator that was not marked UsesReverseDependencies")) 1174*1fa6dee9SAndroid Build Coastguard Worker } 1175*1fa6dee9SAndroid Build Coastguard Worker 1176*1fa6dee9SAndroid Build Coastguard Worker if _, ok := tag.(BaseDependencyTag); ok { 1177*1fa6dee9SAndroid Build Coastguard Worker panic("BaseDependencyTag is not allowed to be used directly!") 1178*1fa6dee9SAndroid Build Coastguard Worker } 1179*1fa6dee9SAndroid Build Coastguard Worker 1180*1fa6dee9SAndroid Build Coastguard Worker destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], mctx.config, nil, destName) 1181*1fa6dee9SAndroid Build Coastguard Worker if len(errs) > 0 { 1182*1fa6dee9SAndroid Build Coastguard Worker mctx.errs = append(mctx.errs, errs...) 1183*1fa6dee9SAndroid Build Coastguard Worker return 1184*1fa6dee9SAndroid Build Coastguard Worker } 1185*1fa6dee9SAndroid Build Coastguard Worker 1186*1fa6dee9SAndroid Build Coastguard Worker if destModule == nil { 1187*1fa6dee9SAndroid Build Coastguard Worker // allowMissingDependencies is true and the module wasn't found 1188*1fa6dee9SAndroid Build Coastguard Worker return 1189*1fa6dee9SAndroid Build Coastguard Worker } 1190*1fa6dee9SAndroid Build Coastguard Worker 1191*1fa6dee9SAndroid Build Coastguard Worker mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{ 1192*1fa6dee9SAndroid Build Coastguard Worker destModule, 1193*1fa6dee9SAndroid Build Coastguard Worker depInfo{mctx.context.moduleInfo[module], tag}, 1194*1fa6dee9SAndroid Build Coastguard Worker }) 1195*1fa6dee9SAndroid Build Coastguard Worker} 1196*1fa6dee9SAndroid Build Coastguard Worker 1197*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddReverseVariationDependency(variations []Variation, tag DependencyTag, destName string) { 1198*1fa6dee9SAndroid Build Coastguard Worker if !mctx.mutator.usesReverseDependencies { 1199*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("method AddReverseVariationDependency called from mutator that was not marked UsesReverseDependencies")) 1200*1fa6dee9SAndroid Build Coastguard Worker } 1201*1fa6dee9SAndroid Build Coastguard Worker 1202*1fa6dee9SAndroid Build Coastguard Worker if _, ok := tag.(BaseDependencyTag); ok { 1203*1fa6dee9SAndroid Build Coastguard Worker panic("BaseDependencyTag is not allowed to be used directly!") 1204*1fa6dee9SAndroid Build Coastguard Worker } 1205*1fa6dee9SAndroid Build Coastguard Worker 1206*1fa6dee9SAndroid Build Coastguard Worker destModule, errs := mctx.context.findReverseDependency(mctx.module, mctx.config, variations, destName) 1207*1fa6dee9SAndroid Build Coastguard Worker if len(errs) > 0 { 1208*1fa6dee9SAndroid Build Coastguard Worker mctx.errs = append(mctx.errs, errs...) 1209*1fa6dee9SAndroid Build Coastguard Worker return 1210*1fa6dee9SAndroid Build Coastguard Worker } 1211*1fa6dee9SAndroid Build Coastguard Worker 1212*1fa6dee9SAndroid Build Coastguard Worker if destModule == nil { 1213*1fa6dee9SAndroid Build Coastguard Worker // allowMissingDependencies is true and the module wasn't found 1214*1fa6dee9SAndroid Build Coastguard Worker return 1215*1fa6dee9SAndroid Build Coastguard Worker } 1216*1fa6dee9SAndroid Build Coastguard Worker 1217*1fa6dee9SAndroid Build Coastguard Worker mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{ 1218*1fa6dee9SAndroid Build Coastguard Worker destModule, 1219*1fa6dee9SAndroid Build Coastguard Worker depInfo{mctx.module, tag}, 1220*1fa6dee9SAndroid Build Coastguard Worker }) 1221*1fa6dee9SAndroid Build Coastguard Worker} 1222*1fa6dee9SAndroid Build Coastguard Worker 1223*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag, 1224*1fa6dee9SAndroid Build Coastguard Worker deps ...string) []Module { 1225*1fa6dee9SAndroid Build Coastguard Worker 1226*1fa6dee9SAndroid Build Coastguard Worker depInfos := make([]Module, 0, len(deps)) 1227*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range deps { 1228*1fa6dee9SAndroid Build Coastguard Worker depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.mutator, mctx.config, variations, tag, dep, false) 1229*1fa6dee9SAndroid Build Coastguard Worker if len(errs) > 0 { 1230*1fa6dee9SAndroid Build Coastguard Worker mctx.errs = append(mctx.errs, errs...) 1231*1fa6dee9SAndroid Build Coastguard Worker } 1232*1fa6dee9SAndroid Build Coastguard Worker if !mctx.pause(depInfo) { 1233*1fa6dee9SAndroid Build Coastguard Worker // Pausing not supported by this mutator, new dependencies can't be returned. 1234*1fa6dee9SAndroid Build Coastguard Worker depInfo = nil 1235*1fa6dee9SAndroid Build Coastguard Worker } 1236*1fa6dee9SAndroid Build Coastguard Worker depInfos = append(depInfos, maybeLogicModule(depInfo)) 1237*1fa6dee9SAndroid Build Coastguard Worker } 1238*1fa6dee9SAndroid Build Coastguard Worker return depInfos 1239*1fa6dee9SAndroid Build Coastguard Worker} 1240*1fa6dee9SAndroid Build Coastguard Worker 1241*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag, 1242*1fa6dee9SAndroid Build Coastguard Worker deps ...string) []Module { 1243*1fa6dee9SAndroid Build Coastguard Worker 1244*1fa6dee9SAndroid Build Coastguard Worker depInfos := make([]Module, 0, len(deps)) 1245*1fa6dee9SAndroid Build Coastguard Worker for _, dep := range deps { 1246*1fa6dee9SAndroid Build Coastguard Worker depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.mutator, mctx.config, variations, tag, dep, true) 1247*1fa6dee9SAndroid Build Coastguard Worker if len(errs) > 0 { 1248*1fa6dee9SAndroid Build Coastguard Worker mctx.errs = append(mctx.errs, errs...) 1249*1fa6dee9SAndroid Build Coastguard Worker } 1250*1fa6dee9SAndroid Build Coastguard Worker if !mctx.pause(depInfo) { 1251*1fa6dee9SAndroid Build Coastguard Worker // Pausing not supported by this mutator, new dependencies can't be returned. 1252*1fa6dee9SAndroid Build Coastguard Worker depInfo = nil 1253*1fa6dee9SAndroid Build Coastguard Worker } 1254*1fa6dee9SAndroid Build Coastguard Worker depInfos = append(depInfos, maybeLogicModule(depInfo)) 1255*1fa6dee9SAndroid Build Coastguard Worker } 1256*1fa6dee9SAndroid Build Coastguard Worker return depInfos 1257*1fa6dee9SAndroid Build Coastguard Worker} 1258*1fa6dee9SAndroid Build Coastguard Worker 1259*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) ReplaceDependencies(name string) { 1260*1fa6dee9SAndroid Build Coastguard Worker mctx.ReplaceDependenciesIf(name, nil) 1261*1fa6dee9SAndroid Build Coastguard Worker} 1262*1fa6dee9SAndroid Build Coastguard Worker 1263*1fa6dee9SAndroid Build Coastguard Workertype ReplaceDependencyPredicate func(from Module, tag DependencyTag, to Module) bool 1264*1fa6dee9SAndroid Build Coastguard Worker 1265*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) ReplaceDependenciesIf(name string, predicate ReplaceDependencyPredicate) { 1266*1fa6dee9SAndroid Build Coastguard Worker if !mctx.mutator.usesReplaceDependencies { 1267*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("method ReplaceDependenciesIf called from mutator that was not marked UsesReplaceDependencies")) 1268*1fa6dee9SAndroid Build Coastguard Worker } 1269*1fa6dee9SAndroid Build Coastguard Worker 1270*1fa6dee9SAndroid Build Coastguard Worker targets := mctx.context.moduleVariantsThatDependOn(name, mctx.module) 1271*1fa6dee9SAndroid Build Coastguard Worker 1272*1fa6dee9SAndroid Build Coastguard Worker if len(targets) == 0 { 1273*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("ReplaceDependencies could not find identical variant {%s} for module %s\n"+ 1274*1fa6dee9SAndroid Build Coastguard Worker "available variants:\n %s", 1275*1fa6dee9SAndroid Build Coastguard Worker mctx.context.prettyPrintVariant(mctx.module.variant.variations), 1276*1fa6dee9SAndroid Build Coastguard Worker name, 1277*1fa6dee9SAndroid Build Coastguard Worker mctx.context.prettyPrintGroupVariants(mctx.context.moduleGroupFromName(name, mctx.module.namespace())))) 1278*1fa6dee9SAndroid Build Coastguard Worker } 1279*1fa6dee9SAndroid Build Coastguard Worker 1280*1fa6dee9SAndroid Build Coastguard Worker for _, target := range targets { 1281*1fa6dee9SAndroid Build Coastguard Worker mctx.replace = append(mctx.replace, replace{target, mctx.module, predicate}) 1282*1fa6dee9SAndroid Build Coastguard Worker } 1283*1fa6dee9SAndroid Build Coastguard Worker} 1284*1fa6dee9SAndroid Build Coastguard Worker 1285*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) Rename(name string) { 1286*1fa6dee9SAndroid Build Coastguard Worker if !mctx.mutator.usesRename { 1287*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("method Rename called from mutator that was not marked UsesRename")) 1288*1fa6dee9SAndroid Build Coastguard Worker } 1289*1fa6dee9SAndroid Build Coastguard Worker mctx.rename = append(mctx.rename, rename{mctx.module.group, name}) 1290*1fa6dee9SAndroid Build Coastguard Worker} 1291*1fa6dee9SAndroid Build Coastguard Worker 1292*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module { 1293*1fa6dee9SAndroid Build Coastguard Worker if !mctx.mutator.usesCreateModule { 1294*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("method CreateModule called from mutator that was not marked UsesCreateModule")) 1295*1fa6dee9SAndroid Build Coastguard Worker } 1296*1fa6dee9SAndroid Build Coastguard Worker 1297*1fa6dee9SAndroid Build Coastguard Worker module := newModule(factory) 1298*1fa6dee9SAndroid Build Coastguard Worker 1299*1fa6dee9SAndroid Build Coastguard Worker module.relBlueprintsFile = mctx.module.relBlueprintsFile 1300*1fa6dee9SAndroid Build Coastguard Worker module.pos = mctx.module.pos 1301*1fa6dee9SAndroid Build Coastguard Worker module.propertyPos = mctx.module.propertyPos 1302*1fa6dee9SAndroid Build Coastguard Worker module.createdBy = mctx.module 1303*1fa6dee9SAndroid Build Coastguard Worker module.typeName = typeName 1304*1fa6dee9SAndroid Build Coastguard Worker 1305*1fa6dee9SAndroid Build Coastguard Worker for _, p := range props { 1306*1fa6dee9SAndroid Build Coastguard Worker err := proptools.AppendMatchingProperties(module.properties, p, nil) 1307*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 1308*1fa6dee9SAndroid Build Coastguard Worker panic(err) 1309*1fa6dee9SAndroid Build Coastguard Worker } 1310*1fa6dee9SAndroid Build Coastguard Worker } 1311*1fa6dee9SAndroid Build Coastguard Worker 1312*1fa6dee9SAndroid Build Coastguard Worker mctx.newModules = append(mctx.newModules, module) 1313*1fa6dee9SAndroid Build Coastguard Worker 1314*1fa6dee9SAndroid Build Coastguard Worker return module.logicModule 1315*1fa6dee9SAndroid Build Coastguard Worker} 1316*1fa6dee9SAndroid Build Coastguard Worker 1317*1fa6dee9SAndroid Build Coastguard Worker// pause waits until the given dependency has been visited by the mutator's parallelVisit call. 1318*1fa6dee9SAndroid Build Coastguard Worker// It returns true if the pause was supported, false if the pause was not supported and did not 1319*1fa6dee9SAndroid Build Coastguard Worker// occur, which will happen when the mutator is not parallelizable. If the dependency is nil 1320*1fa6dee9SAndroid Build Coastguard Worker// it returns true if pausing is supported or false if it is not. 1321*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) pause(dep *moduleInfo) bool { 1322*1fa6dee9SAndroid Build Coastguard Worker if mctx.pauseCh != nil { 1323*1fa6dee9SAndroid Build Coastguard Worker if dep != nil { 1324*1fa6dee9SAndroid Build Coastguard Worker unpause := make(unpause) 1325*1fa6dee9SAndroid Build Coastguard Worker mctx.pauseCh <- pauseSpec{ 1326*1fa6dee9SAndroid Build Coastguard Worker paused: mctx.module, 1327*1fa6dee9SAndroid Build Coastguard Worker until: dep, 1328*1fa6dee9SAndroid Build Coastguard Worker unpause: unpause, 1329*1fa6dee9SAndroid Build Coastguard Worker } 1330*1fa6dee9SAndroid Build Coastguard Worker <-unpause 1331*1fa6dee9SAndroid Build Coastguard Worker } 1332*1fa6dee9SAndroid Build Coastguard Worker return true 1333*1fa6dee9SAndroid Build Coastguard Worker } 1334*1fa6dee9SAndroid Build Coastguard Worker return false 1335*1fa6dee9SAndroid Build Coastguard Worker} 1336*1fa6dee9SAndroid Build Coastguard Worker 1337*1fa6dee9SAndroid Build Coastguard Worker// SimpleName is an embeddable object to implement the ModuleContext.Name method using a property 1338*1fa6dee9SAndroid Build Coastguard Worker// called "name". Modules that embed it must also add SimpleName.Properties to their property 1339*1fa6dee9SAndroid Build Coastguard Worker// structure list. 1340*1fa6dee9SAndroid Build Coastguard Workertype SimpleName struct { 1341*1fa6dee9SAndroid Build Coastguard Worker Properties struct { 1342*1fa6dee9SAndroid Build Coastguard Worker Name string 1343*1fa6dee9SAndroid Build Coastguard Worker } 1344*1fa6dee9SAndroid Build Coastguard Worker} 1345*1fa6dee9SAndroid Build Coastguard Worker 1346*1fa6dee9SAndroid Build Coastguard Workerfunc (s *SimpleName) Name() string { 1347*1fa6dee9SAndroid Build Coastguard Worker return s.Properties.Name 1348*1fa6dee9SAndroid Build Coastguard Worker} 1349*1fa6dee9SAndroid Build Coastguard Worker 1350*1fa6dee9SAndroid Build Coastguard Worker// Load Hooks 1351*1fa6dee9SAndroid Build Coastguard Worker 1352*1fa6dee9SAndroid Build Coastguard Workertype LoadHookContext interface { 1353*1fa6dee9SAndroid Build Coastguard Worker EarlyModuleContext 1354*1fa6dee9SAndroid Build Coastguard Worker 1355*1fa6dee9SAndroid Build Coastguard Worker // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies 1356*1fa6dee9SAndroid Build Coastguard Worker // the specified property structs to it as if the properties were set in a blueprint file. 1357*1fa6dee9SAndroid Build Coastguard Worker CreateModule(ModuleFactory, string, ...interface{}) Module 1358*1fa6dee9SAndroid Build Coastguard Worker 1359*1fa6dee9SAndroid Build Coastguard Worker // CreateModuleInDirectory creates a new module in the specified directory by calling the 1360*1fa6dee9SAndroid Build Coastguard Worker // factory method for the specified moduleType, and applies the specified property structs 1361*1fa6dee9SAndroid Build Coastguard Worker // to it as if the properties were set in a blueprint file. 1362*1fa6dee9SAndroid Build Coastguard Worker CreateModuleInDirectory(ModuleFactory, string, string, ...interface{}) Module 1363*1fa6dee9SAndroid Build Coastguard Worker 1364*1fa6dee9SAndroid Build Coastguard Worker // RegisterScopedModuleType creates a new module type that is scoped to the current Blueprints 1365*1fa6dee9SAndroid Build Coastguard Worker // file. 1366*1fa6dee9SAndroid Build Coastguard Worker RegisterScopedModuleType(name string, factory ModuleFactory) 1367*1fa6dee9SAndroid Build Coastguard Worker} 1368*1fa6dee9SAndroid Build Coastguard Worker 1369*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) createModule(factory ModuleFactory, typeName, moduleDir string, props ...interface{}) Module { 1370*1fa6dee9SAndroid Build Coastguard Worker module := newModule(factory) 1371*1fa6dee9SAndroid Build Coastguard Worker 1372*1fa6dee9SAndroid Build Coastguard Worker module.relBlueprintsFile = moduleDir 1373*1fa6dee9SAndroid Build Coastguard Worker module.pos = l.module.pos 1374*1fa6dee9SAndroid Build Coastguard Worker module.propertyPos = l.module.propertyPos 1375*1fa6dee9SAndroid Build Coastguard Worker module.createdBy = l.module 1376*1fa6dee9SAndroid Build Coastguard Worker module.typeName = typeName 1377*1fa6dee9SAndroid Build Coastguard Worker 1378*1fa6dee9SAndroid Build Coastguard Worker for _, p := range props { 1379*1fa6dee9SAndroid Build Coastguard Worker err := proptools.AppendMatchingProperties(module.properties, p, nil) 1380*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 1381*1fa6dee9SAndroid Build Coastguard Worker panic(err) 1382*1fa6dee9SAndroid Build Coastguard Worker } 1383*1fa6dee9SAndroid Build Coastguard Worker } 1384*1fa6dee9SAndroid Build Coastguard Worker 1385*1fa6dee9SAndroid Build Coastguard Worker l.newModules = append(l.newModules, module) 1386*1fa6dee9SAndroid Build Coastguard Worker 1387*1fa6dee9SAndroid Build Coastguard Worker return module.logicModule 1388*1fa6dee9SAndroid Build Coastguard Worker} 1389*1fa6dee9SAndroid Build Coastguard Worker 1390*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module { 1391*1fa6dee9SAndroid Build Coastguard Worker return l.createModule(factory, typeName, l.module.relBlueprintsFile, props...) 1392*1fa6dee9SAndroid Build Coastguard Worker} 1393*1fa6dee9SAndroid Build Coastguard Worker 1394*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) CreateModuleInDirectory(factory ModuleFactory, typeName, moduleDir string, props ...interface{}) Module { 1395*1fa6dee9SAndroid Build Coastguard Worker if moduleDir != filepath.Clean(moduleDir) { 1396*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("Cannot create a module in %s", moduleDir)) 1397*1fa6dee9SAndroid Build Coastguard Worker } 1398*1fa6dee9SAndroid Build Coastguard Worker 1399*1fa6dee9SAndroid Build Coastguard Worker filePath := filepath.Join(moduleDir, "Android.bp") 1400*1fa6dee9SAndroid Build Coastguard Worker return l.createModule(factory, typeName, filePath, props...) 1401*1fa6dee9SAndroid Build Coastguard Worker} 1402*1fa6dee9SAndroid Build Coastguard Worker 1403*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) RegisterScopedModuleType(name string, factory ModuleFactory) { 1404*1fa6dee9SAndroid Build Coastguard Worker if _, exists := l.context.moduleFactories[name]; exists { 1405*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("A global module type named %q already exists", name)) 1406*1fa6dee9SAndroid Build Coastguard Worker } 1407*1fa6dee9SAndroid Build Coastguard Worker 1408*1fa6dee9SAndroid Build Coastguard Worker if _, exists := (*l.scopedModuleFactories)[name]; exists { 1409*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("A module type named %q already exists in this scope", name)) 1410*1fa6dee9SAndroid Build Coastguard Worker } 1411*1fa6dee9SAndroid Build Coastguard Worker 1412*1fa6dee9SAndroid Build Coastguard Worker if *l.scopedModuleFactories == nil { 1413*1fa6dee9SAndroid Build Coastguard Worker *l.scopedModuleFactories = make(map[string]ModuleFactory) 1414*1fa6dee9SAndroid Build Coastguard Worker } 1415*1fa6dee9SAndroid Build Coastguard Worker 1416*1fa6dee9SAndroid Build Coastguard Worker (*l.scopedModuleFactories)[name] = factory 1417*1fa6dee9SAndroid Build Coastguard Worker} 1418*1fa6dee9SAndroid Build Coastguard Worker 1419*1fa6dee9SAndroid Build Coastguard Workertype loadHookContext struct { 1420*1fa6dee9SAndroid Build Coastguard Worker baseModuleContext 1421*1fa6dee9SAndroid Build Coastguard Worker newModules []*moduleInfo 1422*1fa6dee9SAndroid Build Coastguard Worker scopedModuleFactories *map[string]ModuleFactory 1423*1fa6dee9SAndroid Build Coastguard Worker} 1424*1fa6dee9SAndroid Build Coastguard Worker 1425*1fa6dee9SAndroid Build Coastguard Workertype LoadHook func(ctx LoadHookContext) 1426*1fa6dee9SAndroid Build Coastguard Worker 1427*1fa6dee9SAndroid Build Coastguard Worker// LoadHookWithPriority is a wrapper around LoadHook and allows hooks to be sorted by priority. 1428*1fa6dee9SAndroid Build Coastguard Worker// hooks with higher value of `priority` run last. 1429*1fa6dee9SAndroid Build Coastguard Worker// hooks with equal value of `priority` run in the order they were registered. 1430*1fa6dee9SAndroid Build Coastguard Workertype LoadHookWithPriority struct { 1431*1fa6dee9SAndroid Build Coastguard Worker priority int 1432*1fa6dee9SAndroid Build Coastguard Worker loadHook LoadHook 1433*1fa6dee9SAndroid Build Coastguard Worker} 1434*1fa6dee9SAndroid Build Coastguard Worker 1435*1fa6dee9SAndroid Build Coastguard Worker// Load hooks need to be added by module factories, which don't have any parameter to get to the 1436*1fa6dee9SAndroid Build Coastguard Worker// Context, and only produce a Module interface with no base implementation, so the load hooks 1437*1fa6dee9SAndroid Build Coastguard Worker// must be stored in a global map. The key is a pointer allocated by the module factory, so there 1438*1fa6dee9SAndroid Build Coastguard Worker// is no chance of collisions even if tests are running in parallel with multiple contexts. The 1439*1fa6dee9SAndroid Build Coastguard Worker// contents should be short-lived, they are added during a module factory and removed immediately 1440*1fa6dee9SAndroid Build Coastguard Worker// after the module factory returns. 1441*1fa6dee9SAndroid Build Coastguard Workervar pendingHooks sync.Map 1442*1fa6dee9SAndroid Build Coastguard Worker 1443*1fa6dee9SAndroid Build Coastguard Workerfunc AddLoadHook(module Module, hook LoadHook) { 1444*1fa6dee9SAndroid Build Coastguard Worker // default priority is 0 1445*1fa6dee9SAndroid Build Coastguard Worker AddLoadHookWithPriority(module, hook, 0) 1446*1fa6dee9SAndroid Build Coastguard Worker} 1447*1fa6dee9SAndroid Build Coastguard Worker 1448*1fa6dee9SAndroid Build Coastguard Worker// AddLoadhHookWithPriority adds a load hook with a specified priority. 1449*1fa6dee9SAndroid Build Coastguard Worker// Hooks with higher priority run last. 1450*1fa6dee9SAndroid Build Coastguard Worker// Hooks with equal priority run in the order they were registered. 1451*1fa6dee9SAndroid Build Coastguard Workerfunc AddLoadHookWithPriority(module Module, hook LoadHook, priority int) { 1452*1fa6dee9SAndroid Build Coastguard Worker // Only one goroutine can be processing a given module, so no additional locking is required 1453*1fa6dee9SAndroid Build Coastguard Worker // for the slice stored in the sync.Map. 1454*1fa6dee9SAndroid Build Coastguard Worker v, exists := pendingHooks.Load(module) 1455*1fa6dee9SAndroid Build Coastguard Worker if !exists { 1456*1fa6dee9SAndroid Build Coastguard Worker v, _ = pendingHooks.LoadOrStore(module, new([]LoadHookWithPriority)) 1457*1fa6dee9SAndroid Build Coastguard Worker } 1458*1fa6dee9SAndroid Build Coastguard Worker hooks := v.(*[]LoadHookWithPriority) 1459*1fa6dee9SAndroid Build Coastguard Worker *hooks = append(*hooks, LoadHookWithPriority{priority, hook}) 1460*1fa6dee9SAndroid Build Coastguard Worker} 1461*1fa6dee9SAndroid Build Coastguard Worker 1462*1fa6dee9SAndroid Build Coastguard Workerfunc runAndRemoveLoadHooks(ctx *Context, config interface{}, module *moduleInfo, 1463*1fa6dee9SAndroid Build Coastguard Worker scopedModuleFactories *map[string]ModuleFactory) (newModules []*moduleInfo, deps []string, errs []error) { 1464*1fa6dee9SAndroid Build Coastguard Worker 1465*1fa6dee9SAndroid Build Coastguard Worker if v, exists := pendingHooks.Load(module.logicModule); exists { 1466*1fa6dee9SAndroid Build Coastguard Worker hooks := v.(*[]LoadHookWithPriority) 1467*1fa6dee9SAndroid Build Coastguard Worker // Sort the hooks by priority. 1468*1fa6dee9SAndroid Build Coastguard Worker // Use SliceStable so that hooks with equal priority run in the order they were registered. 1469*1fa6dee9SAndroid Build Coastguard Worker sort.SliceStable(*hooks, func(i, j int) bool { return (*hooks)[i].priority < (*hooks)[j].priority }) 1470*1fa6dee9SAndroid Build Coastguard Worker 1471*1fa6dee9SAndroid Build Coastguard Worker for _, hook := range *hooks { 1472*1fa6dee9SAndroid Build Coastguard Worker mctx := &loadHookContext{ 1473*1fa6dee9SAndroid Build Coastguard Worker baseModuleContext: baseModuleContext{ 1474*1fa6dee9SAndroid Build Coastguard Worker context: ctx, 1475*1fa6dee9SAndroid Build Coastguard Worker config: config, 1476*1fa6dee9SAndroid Build Coastguard Worker module: module, 1477*1fa6dee9SAndroid Build Coastguard Worker }, 1478*1fa6dee9SAndroid Build Coastguard Worker scopedModuleFactories: scopedModuleFactories, 1479*1fa6dee9SAndroid Build Coastguard Worker } 1480*1fa6dee9SAndroid Build Coastguard Worker hook.loadHook(mctx) 1481*1fa6dee9SAndroid Build Coastguard Worker newModules = append(newModules, mctx.newModules...) 1482*1fa6dee9SAndroid Build Coastguard Worker deps = append(deps, mctx.ninjaFileDeps...) 1483*1fa6dee9SAndroid Build Coastguard Worker errs = append(errs, mctx.errs...) 1484*1fa6dee9SAndroid Build Coastguard Worker } 1485*1fa6dee9SAndroid Build Coastguard Worker pendingHooks.Delete(module.logicModule) 1486*1fa6dee9SAndroid Build Coastguard Worker 1487*1fa6dee9SAndroid Build Coastguard Worker return newModules, deps, errs 1488*1fa6dee9SAndroid Build Coastguard Worker } 1489*1fa6dee9SAndroid Build Coastguard Worker 1490*1fa6dee9SAndroid Build Coastguard Worker return nil, nil, nil 1491*1fa6dee9SAndroid Build Coastguard Worker} 1492*1fa6dee9SAndroid Build Coastguard Worker 1493*1fa6dee9SAndroid Build Coastguard Worker// Check the syntax of a generated blueprint file. 1494*1fa6dee9SAndroid Build Coastguard Worker// 1495*1fa6dee9SAndroid Build Coastguard Worker// This is intended to perform a quick syntactic check for generated blueprint 1496*1fa6dee9SAndroid Build Coastguard Worker// code, where syntactically correct means: 1497*1fa6dee9SAndroid Build Coastguard Worker// * No variable definitions. 1498*1fa6dee9SAndroid Build Coastguard Worker// * Valid module types. 1499*1fa6dee9SAndroid Build Coastguard Worker// * Valid property names. 1500*1fa6dee9SAndroid Build Coastguard Worker// * Valid values for the property type. 1501*1fa6dee9SAndroid Build Coastguard Worker// 1502*1fa6dee9SAndroid Build Coastguard Worker// It does not perform any semantic checking of properties, existence of referenced 1503*1fa6dee9SAndroid Build Coastguard Worker// files, or dependencies. 1504*1fa6dee9SAndroid Build Coastguard Worker// 1505*1fa6dee9SAndroid Build Coastguard Worker// At a low level it: 1506*1fa6dee9SAndroid Build Coastguard Worker// * Parses the contents. 1507*1fa6dee9SAndroid Build Coastguard Worker// * Invokes relevant factory to create Module instances. 1508*1fa6dee9SAndroid Build Coastguard Worker// * Unpacks the properties into the Module. 1509*1fa6dee9SAndroid Build Coastguard Worker// * Does not invoke load hooks or any mutators. 1510*1fa6dee9SAndroid Build Coastguard Worker// 1511*1fa6dee9SAndroid Build Coastguard Worker// The filename is only used for reporting errors. 1512*1fa6dee9SAndroid Build Coastguard Workerfunc CheckBlueprintSyntax(moduleFactories map[string]ModuleFactory, filename string, contents string) []error { 1513*1fa6dee9SAndroid Build Coastguard Worker file, errs := parser.Parse(filename, strings.NewReader(contents)) 1514*1fa6dee9SAndroid Build Coastguard Worker if len(errs) != 0 { 1515*1fa6dee9SAndroid Build Coastguard Worker return errs 1516*1fa6dee9SAndroid Build Coastguard Worker } 1517*1fa6dee9SAndroid Build Coastguard Worker 1518*1fa6dee9SAndroid Build Coastguard Worker for _, def := range file.Defs { 1519*1fa6dee9SAndroid Build Coastguard Worker switch def := def.(type) { 1520*1fa6dee9SAndroid Build Coastguard Worker case *parser.Module: 1521*1fa6dee9SAndroid Build Coastguard Worker _, moduleErrs := processModuleDef(def, filename, moduleFactories, nil, false) 1522*1fa6dee9SAndroid Build Coastguard Worker errs = append(errs, moduleErrs...) 1523*1fa6dee9SAndroid Build Coastguard Worker 1524*1fa6dee9SAndroid Build Coastguard Worker default: 1525*1fa6dee9SAndroid Build Coastguard Worker panic(fmt.Errorf("unknown definition type: %T", def)) 1526*1fa6dee9SAndroid Build Coastguard Worker } 1527*1fa6dee9SAndroid Build Coastguard Worker } 1528*1fa6dee9SAndroid Build Coastguard Worker 1529*1fa6dee9SAndroid Build Coastguard Worker return errs 1530*1fa6dee9SAndroid Build Coastguard Worker} 1531*1fa6dee9SAndroid Build Coastguard Worker 1532*1fa6dee9SAndroid Build Coastguard Workerfunc maybeLogicModule(module *moduleInfo) Module { 1533*1fa6dee9SAndroid Build Coastguard Worker if module != nil { 1534*1fa6dee9SAndroid Build Coastguard Worker return module.logicModule 1535*1fa6dee9SAndroid Build Coastguard Worker } else { 1536*1fa6dee9SAndroid Build Coastguard Worker return nil 1537*1fa6dee9SAndroid Build Coastguard Worker } 1538*1fa6dee9SAndroid Build Coastguard Worker} 1539