blob: b52a75a8409cb72eb3ca958a2155999715a44e21 [file] [log] [blame]
Colin Cross8e0c5112015-01-23 14:15:10 -08001// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Jamie Gennis1bc967e2014-05-27 16:34:41 -070015package blueprint
16
17import (
18 "fmt"
19 "path/filepath"
Jamie Gennis6a40c192014-07-02 16:40:31 -070020 "text/scanner"
Jamie Gennis1bc967e2014-05-27 16:34:41 -070021)
22
Jamie Gennisb9e87f62014-09-24 20:28:11 -070023// A Module handles generating all of the Ninja build actions needed to build a
Colin Crossc9028482014-12-18 16:28:54 -080024// single module based on properties defined in a Blueprints file. Module
25// objects are initially created during the parse phase of a Context using one
26// of the registered module types (and the associated ModuleFactory function).
27// The Module's properties struct is automatically filled in with the property
28// values specified in the Blueprints file (see Context.RegisterModuleType for more
Jamie Gennisb9e87f62014-09-24 20:28:11 -070029// information on this).
30//
Colin Crossc9028482014-12-18 16:28:54 -080031// A Module can be split into multiple Modules by a Mutator. All existing
32// properties set on the module will be duplicated to the new Module, and then
33// modified as necessary by the Mutator.
34//
Jamie Gennisb9e87f62014-09-24 20:28:11 -070035// The Module implementation can access the build configuration as well as any
36// modules on which on which it depends (as defined by the "deps" property
Colin Cross763b6f12015-10-29 15:32:56 -070037// specified in the Blueprints file, dynamically added by implementing the
38// (deprecated) DynamicDependerModule interface, or dynamically added by a
39// BottomUpMutator) using the ModuleContext passed to GenerateBuildActions.
40// This ModuleContext is also used to create Ninja build actions and to report
41// errors to the user.
Jamie Gennisb9e87f62014-09-24 20:28:11 -070042//
43// In addition to implementing the GenerateBuildActions method, a Module should
44// implement methods that provide dependant modules and singletons information
45// they need to generate their build actions. These methods will only be called
46// after GenerateBuildActions is called because the Context calls
47// GenerateBuildActions in dependency-order (and singletons are invoked after
48// all the Modules). The set of methods a Module supports will determine how
49// dependant Modules interact with it.
50//
51// For example, consider a Module that is responsible for generating a library
52// that other modules can link against. The library Module might implement the
53// following interface:
54//
55// type LibraryProducer interface {
56// LibraryFileName() string
57// }
58//
59// func IsLibraryProducer(module blueprint.Module) {
60// _, ok := module.(LibraryProducer)
61// return ok
62// }
63//
64// A binary-producing Module that depends on the library Module could then do:
65//
66// func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
67// ...
68// var libraryFiles []string
69// ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
70// func(module blueprint.Module) {
71// libProducer := module.(LibraryProducer)
72// libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
73// })
74// ...
75// }
76//
77// to build the list of library file names that should be included in its link
78// command.
Colin Cross691a60d2015-01-07 18:08:56 -080079//
80// GenerateBuildActions may be called from multiple threads. It is guaranteed to
81// be called after it has finished being called on all dependencies and on all
82// variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list.
83// Any accesses to global variables or to Module objects that are not dependencies
84// or variants of the current Module must be synchronized by the implementation of
85// GenerateBuildActions.
Jamie Gennis1bc967e2014-05-27 16:34:41 -070086type Module interface {
Jamie Gennisb9e87f62014-09-24 20:28:11 -070087 // GenerateBuildActions is called by the Context that created the Module
88 // during its generate phase. This call should generate all Ninja build
89 // actions (rules, pools, and build statements) needed to build the module.
Jamie Gennis1bc967e2014-05-27 16:34:41 -070090 GenerateBuildActions(ModuleContext)
91}
92
Jamie Gennisb9e87f62014-09-24 20:28:11 -070093// A DynamicDependerModule is a Module that may add dependencies that do not
94// appear in its "deps" property. Any Module that implements this interface
95// will have its DynamicDependencies method called by the Context that created
96// it during generate phase.
Colin Cross763b6f12015-10-29 15:32:56 -070097//
98// Deprecated, use a BottomUpMutator instead
Jamie Gennisb9e87f62014-09-24 20:28:11 -070099type DynamicDependerModule interface {
100 Module
101
102 // DynamicDependencies is called by the Context that created the
103 // DynamicDependerModule during its generate phase. This call should return
104 // the list of module names that the DynamicDependerModule depends on
105 // dynamically. Module names that already appear in the "deps" property may
106 // but do not need to be included in the returned list.
107 DynamicDependencies(DynamicDependerModuleContext) []string
108}
109
Colin Crossbe1a9a12014-12-18 11:05:45 -0800110type BaseModuleContext interface {
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700111 ModuleName() string
112 ModuleDir() string
Jamie Gennis6eb4d242014-06-11 18:31:16 -0700113 Config() interface{}
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700114
David Allison701fbad2014-10-29 14:51:13 -0700115 ContainsProperty(name string) bool
Jamie Gennis6a40c192014-07-02 16:40:31 -0700116 Errorf(pos scanner.Position, fmt string, args ...interface{})
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700117 ModuleErrorf(fmt string, args ...interface{})
118 PropertyErrorf(property, fmt string, args ...interface{})
Jamie Gennis6a40c192014-07-02 16:40:31 -0700119 Failed() bool
Colin Cross763b6f12015-10-29 15:32:56 -0700120
121 moduleInfo() *moduleInfo
Colin Cross0aa6a5f2016-01-07 13:43:09 -0800122 error(err error)
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700123}
124
Colin Cross763b6f12015-10-29 15:32:56 -0700125type DynamicDependerModuleContext BottomUpMutatorContext
Colin Crossbe1a9a12014-12-18 11:05:45 -0800126
Colin Cross1455a0f2014-12-17 13:23:56 -0800127type ModuleContext interface {
Colin Crossbe1a9a12014-12-18 11:05:45 -0800128 BaseModuleContext
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700129
130 OtherModuleName(m Module) string
131 OtherModuleErrorf(m Module, fmt string, args ...interface{})
Colin Cross2c1f3d12016-04-11 15:47:28 -0700132 OtherModuleDependencyTag(m Module) DependencyTag
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700133
Colin Crossc7ffa302015-02-10 11:24:52 -0800134 VisitDirectDeps(visit func(Module))
135 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
Colin Crossb2e7b5d2014-11-11 14:18:53 -0800136 VisitDepsDepthFirst(visit func(Module))
137 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
Yuchen Wu222e2452015-10-06 14:03:27 -0700138 WalkDeps(visit func(Module, Module) bool)
Colin Crossb2e7b5d2014-11-11 14:18:53 -0800139
Colin Crossc9028482014-12-18 16:28:54 -0800140 ModuleSubDir() string
141
Dan Willemsenaeffbf72015-11-25 15:29:32 -0800142 Variable(pctx PackageContext, name, value string)
143 Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
144 Build(pctx PackageContext, params BuildParams)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700145
Mathias Agopian5b8477d2014-06-25 17:21:54 -0700146 AddNinjaFileDeps(deps ...string)
Colin Crossc9028482014-12-18 16:28:54 -0800147
148 PrimaryModule() Module
Colin Cross80ad04d2015-01-06 16:19:59 -0800149 FinalModule() Module
150 VisitAllModuleVariants(visit func(Module))
Colin Cross036a1df2015-12-17 15:49:30 -0800151
152 GetMissingDependencies() []string
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700153}
154
Colin Crossbe1a9a12014-12-18 11:05:45 -0800155var _ BaseModuleContext = (*baseModuleContext)(nil)
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700156
Colin Crossbe1a9a12014-12-18 11:05:45 -0800157type baseModuleContext struct {
Colin Cross2c1f3d12016-04-11 15:47:28 -0700158 context *Context
159 config interface{}
160 module *moduleInfo
161 errs []error
162 visiting depInfo
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700163}
164
Colin Cross763b6f12015-10-29 15:32:56 -0700165func (d *baseModuleContext) moduleInfo() *moduleInfo {
166 return d.module
167}
168
Colin Crossbe1a9a12014-12-18 11:05:45 -0800169func (d *baseModuleContext) ModuleName() string {
Colin Crossed342d92015-03-11 00:57:25 -0700170 return d.module.properties.Name
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700171}
172
Colin Crossbe1a9a12014-12-18 11:05:45 -0800173func (d *baseModuleContext) ContainsProperty(name string) bool {
Colin Crossed342d92015-03-11 00:57:25 -0700174 _, ok := d.module.propertyPos[name]
David Allison701fbad2014-10-29 14:51:13 -0700175 return ok
176}
177
Colin Crossbe1a9a12014-12-18 11:05:45 -0800178func (d *baseModuleContext) ModuleDir() string {
Colin Crossed342d92015-03-11 00:57:25 -0700179 return filepath.Dir(d.module.relBlueprintsFile)
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700180}
181
Colin Crossbe1a9a12014-12-18 11:05:45 -0800182func (d *baseModuleContext) Config() interface{} {
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700183 return d.config
184}
185
Colin Cross0aa6a5f2016-01-07 13:43:09 -0800186func (d *baseModuleContext) error(err error) {
187 if err != nil {
188 d.errs = append(d.errs, err)
189 }
190}
191
Colin Crossbe1a9a12014-12-18 11:05:45 -0800192func (d *baseModuleContext) Errorf(pos scanner.Position,
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700193 format string, args ...interface{}) {
194
Colin Cross0aa6a5f2016-01-07 13:43:09 -0800195 d.error(&Error{
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700196 Err: fmt.Errorf(format, args...),
197 Pos: pos,
198 })
199}
200
Colin Crossbe1a9a12014-12-18 11:05:45 -0800201func (d *baseModuleContext) ModuleErrorf(format string,
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700202 args ...interface{}) {
203
Colin Cross0aa6a5f2016-01-07 13:43:09 -0800204 d.error(&Error{
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700205 Err: fmt.Errorf(format, args...),
Colin Crossed342d92015-03-11 00:57:25 -0700206 Pos: d.module.pos,
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700207 })
208}
209
Colin Crossbe1a9a12014-12-18 11:05:45 -0800210func (d *baseModuleContext) PropertyErrorf(property, format string,
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700211 args ...interface{}) {
212
Colin Crossa2ca92c2015-11-02 16:10:23 -0800213 pos := d.module.propertyPos[property]
214
215 if !pos.IsValid() {
216 pos = d.module.pos
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700217 }
218
Colin Crossa2ca92c2015-11-02 16:10:23 -0800219 format = property + ": " + format
220
Colin Cross0aa6a5f2016-01-07 13:43:09 -0800221 d.error(&Error{
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700222 Err: fmt.Errorf(format, args...),
223 Pos: pos,
224 })
225}
226
Colin Crossbe1a9a12014-12-18 11:05:45 -0800227func (d *baseModuleContext) Failed() bool {
Jamie Gennisb9e87f62014-09-24 20:28:11 -0700228 return len(d.errs) > 0
229}
230
Colin Cross1455a0f2014-12-17 13:23:56 -0800231var _ ModuleContext = (*moduleContext)(nil)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700232
Colin Cross1455a0f2014-12-17 13:23:56 -0800233type moduleContext struct {
Colin Crossbe1a9a12014-12-18 11:05:45 -0800234 baseModuleContext
Colin Cross036a1df2015-12-17 15:49:30 -0800235 scope *localScope
236 ninjaFileDeps []string
237 actionDefs localBuildActions
238 handledMissingDeps bool
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700239}
240
Colin Cross2c1f3d12016-04-11 15:47:28 -0700241func (m *baseModuleContext) OtherModuleName(logicModule Module) string {
Colin Crossed342d92015-03-11 00:57:25 -0700242 module := m.context.moduleInfo[logicModule]
243 return module.properties.Name
Jamie Gennisd4c53d82014-06-22 17:02:55 -0700244}
245
Colin Cross2c1f3d12016-04-11 15:47:28 -0700246func (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string,
Jamie Gennisd4c53d82014-06-22 17:02:55 -0700247 args ...interface{}) {
248
Colin Crossed342d92015-03-11 00:57:25 -0700249 module := m.context.moduleInfo[logicModule]
Jamie Gennisd4c53d82014-06-22 17:02:55 -0700250 m.errs = append(m.errs, &Error{
251 Err: fmt.Errorf(format, args...),
Colin Crossed342d92015-03-11 00:57:25 -0700252 Pos: module.pos,
Jamie Gennisd4c53d82014-06-22 17:02:55 -0700253 })
254}
255
Colin Cross2c1f3d12016-04-11 15:47:28 -0700256func (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag {
257 // fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps
258 if logicModule == m.visiting.module.logicModule {
259 return m.visiting.tag
260 }
261
262 for _, dep := range m.module.directDeps {
263 if dep.module.logicModule == logicModule {
264 return dep.tag
265 }
266 }
267
268 return nil
Colin Crossc7ffa302015-02-10 11:24:52 -0800269}
270
Colin Cross2c1f3d12016-04-11 15:47:28 -0700271func (m *baseModuleContext) VisitDirectDeps(visit func(Module)) {
272 defer func() {
273 if r := recover(); r != nil {
274 panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
275 m.module, funcName(visit), m.visiting.module))
276 }
277 }()
278
279 for _, dep := range m.module.directDeps {
280 m.visiting = dep
281 visit(dep.module.logicModule)
282 }
283 m.visiting = depInfo{}
Colin Crossc7ffa302015-02-10 11:24:52 -0800284}
285
Colin Cross2c1f3d12016-04-11 15:47:28 -0700286func (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
287 defer func() {
288 if r := recover(); r != nil {
289 panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
290 m.module, funcName(pred), funcName(visit), m.visiting.module))
291 }
292 }()
293
294 for _, dep := range m.module.directDeps {
295 m.visiting = dep
296 if pred(dep.module.logicModule) {
297 visit(dep.module.logicModule)
298 }
299 }
300 m.visiting = depInfo{}
301}
302
303func (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
Colin Crossb2e7b5d2014-11-11 14:18:53 -0800304 m.context.visitDepsDepthFirst(m.module, visit)
305}
306
Colin Cross2c1f3d12016-04-11 15:47:28 -0700307func (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
Colin Crossb2e7b5d2014-11-11 14:18:53 -0800308 visit func(Module)) {
309
310 m.context.visitDepsDepthFirstIf(m.module, pred, visit)
311}
312
Colin Cross2c1f3d12016-04-11 15:47:28 -0700313func (m *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
Yuchen Wu222e2452015-10-06 14:03:27 -0700314 m.context.walkDeps(m.module, visit)
315}
316
Colin Crossc9028482014-12-18 16:28:54 -0800317func (m *moduleContext) ModuleSubDir() string {
Colin Crosse7daa222015-03-11 14:35:41 -0700318 return m.module.variantName
Colin Crossc9028482014-12-18 16:28:54 -0800319}
320
Dan Willemsenaeffbf72015-11-25 15:29:32 -0800321func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
Jamie Gennis2fb20952014-10-03 02:49:58 -0700322 m.scope.ReparentTo(pctx)
Jamie Gennis0ed63ef2014-06-30 18:07:17 -0700323
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700324 v, err := m.scope.AddLocalVariable(name, value)
325 if err != nil {
326 panic(err)
327 }
328
329 m.actionDefs.variables = append(m.actionDefs.variables, v)
330}
331
Dan Willemsenaeffbf72015-11-25 15:29:32 -0800332func (m *moduleContext) Rule(pctx PackageContext, name string,
Jamie Gennis2fb20952014-10-03 02:49:58 -0700333 params RuleParams, argNames ...string) Rule {
Jamie Genniscbc6f862014-06-05 20:00:22 -0700334
Jamie Gennis2fb20952014-10-03 02:49:58 -0700335 m.scope.ReparentTo(pctx)
Jamie Gennis0ed63ef2014-06-30 18:07:17 -0700336
Jamie Genniscbc6f862014-06-05 20:00:22 -0700337 r, err := m.scope.AddLocalRule(name, &params, argNames...)
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700338 if err != nil {
339 panic(err)
340 }
341
342 m.actionDefs.rules = append(m.actionDefs.rules, r)
343
344 return r
345}
346
Dan Willemsenaeffbf72015-11-25 15:29:32 -0800347func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
Jamie Gennis2fb20952014-10-03 02:49:58 -0700348 m.scope.ReparentTo(pctx)
Jamie Gennis0ed63ef2014-06-30 18:07:17 -0700349
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700350 def, err := parseBuildParams(m.scope, &params)
351 if err != nil {
352 panic(err)
353 }
354
355 m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
356}
357
Mathias Agopian5b8477d2014-06-25 17:21:54 -0700358func (m *moduleContext) AddNinjaFileDeps(deps ...string) {
359 m.ninjaFileDeps = append(m.ninjaFileDeps, deps...)
360}
Colin Crossc9028482014-12-18 16:28:54 -0800361
362func (m *moduleContext) PrimaryModule() Module {
Colin Cross80ad04d2015-01-06 16:19:59 -0800363 return m.module.group.modules[0].logicModule
364}
365
366func (m *moduleContext) FinalModule() Module {
367 return m.module.group.modules[len(m.module.group.modules)-1].logicModule
368}
369
370func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
Colin Cross0aa6a5f2016-01-07 13:43:09 -0800371 m.context.visitAllModuleVariants(m.module, visit)
Colin Crossc9028482014-12-18 16:28:54 -0800372}
373
Colin Cross036a1df2015-12-17 15:49:30 -0800374func (m *moduleContext) GetMissingDependencies() []string {
375 m.handledMissingDeps = true
376 return m.module.missingDeps
377}
378
Colin Crossc9028482014-12-18 16:28:54 -0800379//
380// MutatorContext
381//
382
383type mutatorContext struct {
384 baseModuleContext
Colin Cross8d8a7af2015-11-03 16:41:29 -0800385 name string
Colin Cross2c1f3d12016-04-11 15:47:28 -0700386 reverseDeps map[*moduleInfo][]depInfo
Colin Crossc9028482014-12-18 16:28:54 -0800387}
388
389type baseMutatorContext interface {
390 BaseModuleContext
391
392 Module() Module
393}
394
Colin Cross65569e42015-03-10 20:08:19 -0700395type EarlyMutatorContext interface {
396 baseMutatorContext
397
Colin Crossf5e34b92015-03-13 16:02:36 -0700398 CreateVariations(...string) []Module
399 CreateLocalVariations(...string) []Module
Colin Cross65569e42015-03-10 20:08:19 -0700400}
401
Colin Crossc9028482014-12-18 16:28:54 -0800402type TopDownMutatorContext interface {
403 baseMutatorContext
404
Colin Cross8d222332015-11-02 16:11:32 -0800405 OtherModuleName(m Module) string
406 OtherModuleErrorf(m Module, fmt string, args ...interface{})
Colin Cross2c1f3d12016-04-11 15:47:28 -0700407 OtherModuleDependencyTag(m Module) DependencyTag
Colin Cross8d222332015-11-02 16:11:32 -0800408
Colin Crossc9028482014-12-18 16:28:54 -0800409 VisitDirectDeps(visit func(Module))
410 VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
411 VisitDepsDepthFirst(visit func(Module))
412 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
Yuchen Wu222e2452015-10-06 14:03:27 -0700413 WalkDeps(visit func(Module, Module) bool)
Colin Crossc9028482014-12-18 16:28:54 -0800414}
415
416type BottomUpMutatorContext interface {
417 baseMutatorContext
418
Colin Cross2c1f3d12016-04-11 15:47:28 -0700419 AddDependency(module Module, tag DependencyTag, name ...string)
420 AddReverseDependency(module Module, tag DependencyTag, name string)
Colin Crossf5e34b92015-03-13 16:02:36 -0700421 CreateVariations(...string) []Module
Jamie Gennis6a5825e2015-05-19 11:26:11 -0700422 CreateLocalVariations(...string) []Module
Colin Crossf5e34b92015-03-13 16:02:36 -0700423 SetDependencyVariation(string)
Colin Cross2c1f3d12016-04-11 15:47:28 -0700424 AddVariationDependencies([]Variation, DependencyTag, ...string)
425 AddFarVariationDependencies([]Variation, DependencyTag, ...string)
Colin Crossf1875462016-04-11 17:33:13 -0700426 AddInterVariantDependency(tag DependencyTag, from, to Module)
Colin Crossc9028482014-12-18 16:28:54 -0800427}
428
429// A Mutator function is called for each Module, and can use
Colin Crossf5e34b92015-03-13 16:02:36 -0700430// MutatorContext.CreateVariations to split a Module into multiple Modules,
Colin Crossc9028482014-12-18 16:28:54 -0800431// modifying properties on the new modules to differentiate them. It is called
432// after parsing all Blueprint files, but before generating any build rules,
433// and is always called on dependencies before being called on the depending module.
434//
435// The Mutator function should only modify members of properties structs, and not
436// members of the module struct itself, to ensure the modified values are copied
437// if a second Mutator chooses to split the module a second time.
438type TopDownMutator func(mctx TopDownMutatorContext)
439type BottomUpMutator func(mctx BottomUpMutatorContext)
Colin Cross65569e42015-03-10 20:08:19 -0700440type EarlyMutator func(mctx EarlyMutatorContext)
Colin Crossc9028482014-12-18 16:28:54 -0800441
Colin Cross2c1f3d12016-04-11 15:47:28 -0700442// DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag. It can be
443// used to transfer information on a dependency between the mutator that called AddDependency
444// and the GenerateBuildActions method. Variants created by CreateVariations have a copy of the
445// interface (pointing to the same concrete object) from their original module.
446type DependencyTag interface {
447 dependencyTag(DependencyTag)
448}
449
450type BaseDependencyTag struct {
451}
452
453func (BaseDependencyTag) dependencyTag(DependencyTag) {
454}
455
456var _ DependencyTag = BaseDependencyTag{}
457
Colin Crossf5e34b92015-03-13 16:02:36 -0700458// Split a module into mulitple variants, one for each name in the variationNames
459// parameter. It returns a list of new modules in the same order as the variationNames
Colin Crossc9028482014-12-18 16:28:54 -0800460// list.
461//
462// If any of the dependencies of the module being operated on were already split
Colin Crossf5e34b92015-03-13 16:02:36 -0700463// by calling CreateVariations with the same name, the dependency will automatically
Colin Crossc9028482014-12-18 16:28:54 -0800464// be updated to point the matching variant.
465//
466// If a module is split, and then a module depending on the first module is not split
467// when the Mutator is later called on it, the dependency of the depending module will
468// automatically be updated to point to the first variant.
Colin Crossf5e34b92015-03-13 16:02:36 -0700469func (mctx *mutatorContext) CreateVariations(variationNames ...string) []Module {
470 return mctx.createVariations(variationNames, false)
Colin Cross65569e42015-03-10 20:08:19 -0700471}
472
473// Split a module into mulitple variants, one for each name in the variantNames
474// parameter. It returns a list of new modules in the same order as the variantNames
475// list.
476//
Colin Crossf5e34b92015-03-13 16:02:36 -0700477// Local variations do not affect automatic dependency resolution - dependencies added
Colin Cross65569e42015-03-10 20:08:19 -0700478// to the split module via deps or DynamicDependerModule must exactly match a variant
Colin Crossf5e34b92015-03-13 16:02:36 -0700479// that contains all the non-local variations.
480func (mctx *mutatorContext) CreateLocalVariations(variationNames ...string) []Module {
481 return mctx.createVariations(variationNames, true)
Colin Cross65569e42015-03-10 20:08:19 -0700482}
483
Colin Crossf5e34b92015-03-13 16:02:36 -0700484func (mctx *mutatorContext) createVariations(variationNames []string, local bool) []Module {
Colin Crossc9028482014-12-18 16:28:54 -0800485 ret := []Module{}
Colin Crossf5e34b92015-03-13 16:02:36 -0700486 modules, errs := mctx.context.createVariations(mctx.module, mctx.name, variationNames)
Colin Cross174ae052015-03-03 17:37:03 -0800487 if len(errs) > 0 {
488 mctx.errs = append(mctx.errs, errs...)
489 }
Colin Crossc9028482014-12-18 16:28:54 -0800490
Colin Cross65569e42015-03-10 20:08:19 -0700491 for i, module := range modules {
Colin Crossc9028482014-12-18 16:28:54 -0800492 ret = append(ret, module.logicModule)
Colin Cross65569e42015-03-10 20:08:19 -0700493 if !local {
Colin Crossf5e34b92015-03-13 16:02:36 -0700494 module.dependencyVariant[mctx.name] = variationNames[i]
Colin Cross65569e42015-03-10 20:08:19 -0700495 }
Colin Crossc9028482014-12-18 16:28:54 -0800496 }
497
Colin Crossf5e34b92015-03-13 16:02:36 -0700498 if len(ret) != len(variationNames) {
Colin Crossc9028482014-12-18 16:28:54 -0800499 panic("oops!")
500 }
501
502 return ret
503}
504
Colin Crossf5e34b92015-03-13 16:02:36 -0700505// Set all dangling dependencies on the current module to point to the variation
Colin Crossc9028482014-12-18 16:28:54 -0800506// with given name.
Colin Crossf5e34b92015-03-13 16:02:36 -0700507func (mctx *mutatorContext) SetDependencyVariation(variationName string) {
508 mctx.context.convertDepsToVariation(mctx.module, mctx.name, variationName)
Colin Crossc9028482014-12-18 16:28:54 -0800509}
510
511func (mctx *mutatorContext) Module() Module {
512 return mctx.module.logicModule
513}
514
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700515// Add a dependency to the given module.
Colin Crossc9028482014-12-18 16:28:54 -0800516// Does not affect the ordering of the current mutator pass, but will be ordered
517// correctly for all future mutator passes.
Colin Cross2c1f3d12016-04-11 15:47:28 -0700518func (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) {
Colin Cross763b6f12015-10-29 15:32:56 -0700519 for _, dep := range deps {
Colin Cross2c1f3d12016-04-11 15:47:28 -0700520 errs := mctx.context.addDependency(mctx.context.moduleInfo[module], tag, dep)
Colin Cross763b6f12015-10-29 15:32:56 -0700521 if len(errs) > 0 {
522 mctx.errs = append(mctx.errs, errs...)
523 }
Colin Cross65569e42015-03-10 20:08:19 -0700524 }
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700525}
526
527// Add a dependency from the destination to the given module.
528// Does not affect the ordering of the current mutator pass, but will be ordered
Colin Cross8d8a7af2015-11-03 16:41:29 -0800529// correctly for all future mutator passes. All reverse dependencies for a destination module are
530// collected until the end of the mutator pass, sorted by name, and then appended to the destination
531// module's dependency list.
Colin Cross2c1f3d12016-04-11 15:47:28 -0700532func (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) {
Colin Cross8d8a7af2015-11-03 16:41:29 -0800533 destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], destName)
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700534 if len(errs) > 0 {
535 mctx.errs = append(mctx.errs, errs...)
Colin Cross8d8a7af2015-11-03 16:41:29 -0800536 return
Dan Willemsenfdeb7242015-07-24 16:53:27 -0700537 }
Colin Cross8d8a7af2015-11-03 16:41:29 -0800538
539 mctx.reverseDeps[destModule] = append(mctx.reverseDeps[destModule],
Colin Cross2c1f3d12016-04-11 15:47:28 -0700540 depInfo{mctx.context.moduleInfo[module], tag})
Colin Crossc9028482014-12-18 16:28:54 -0800541}
542
Colin Cross763b6f12015-10-29 15:32:56 -0700543// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
544// argument to select which variant of the dependency to use. A variant of the dependency must
545// exist that matches the all of the non-local variations of the current module, plus the variations
546// argument.
Colin Cross2c1f3d12016-04-11 15:47:28 -0700547func (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag,
Colin Cross763b6f12015-10-29 15:32:56 -0700548 deps ...string) {
549
550 for _, dep := range deps {
Colin Cross2c1f3d12016-04-11 15:47:28 -0700551 errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, false)
Colin Cross763b6f12015-10-29 15:32:56 -0700552 if len(errs) > 0 {
553 mctx.errs = append(mctx.errs, errs...)
554 }
555 }
556}
557
558// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
559// variations argument to select which variant of the dependency to use. A variant of the
560// dependency must exist that matches the variations argument, but may also have other variations.
561// For any unspecified variation the first variant will be used.
562//
563// Unlike AddVariationDependencies, the variations of the current module are ignored - the
564// depdendency only needs to match the supplied variations.
Colin Cross2c1f3d12016-04-11 15:47:28 -0700565func (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag,
Colin Cross763b6f12015-10-29 15:32:56 -0700566 deps ...string) {
567
568 for _, dep := range deps {
Colin Cross2c1f3d12016-04-11 15:47:28 -0700569 errs := mctx.context.addVariationDependency(mctx.module, variations, tag, dep, true)
Colin Cross763b6f12015-10-29 15:32:56 -0700570 if len(errs) > 0 {
571 mctx.errs = append(mctx.errs, errs...)
572 }
573 }
574}
Colin Crossf1875462016-04-11 17:33:13 -0700575
576func (mctx *mutatorContext) AddInterVariantDependency(tag DependencyTag, from, to Module) {
577 mctx.context.addInterVariantDependency(mctx.module, tag, from, to)
578}