blob: a03ea74aa6f3dba839b0f53ca44d7d542afece1d [file] [log] [blame]
Colin Cross0875c522017-11-28 17:34:01 -08001// Copyright 2017 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
15package android
16
17import (
Cole Faustf2aab5e2025-02-11 13:32:51 -080018 "slices"
19 "sync"
20
Colin Cross0875c522017-11-28 17:34:01 -080021 "github.com/google/blueprint"
Colin Cross0875c522017-11-28 17:34:01 -080022)
23
24// SingletonContext
25type SingletonContext interface {
Colin Cross3c0a83d2023-12-12 14:13:26 -080026 blueprintSingletonContext() blueprint.SingletonContext
27
Colin Crossaabf6792017-11-29 00:27:14 -080028 Config() Config
Colin Cross65494b92019-02-07 14:25:51 -080029 DeviceConfig() DeviceConfig
Colin Cross0875c522017-11-28 17:34:01 -080030
31 ModuleName(module blueprint.Module) string
32 ModuleDir(module blueprint.Module) string
33 ModuleSubDir(module blueprint.Module) string
34 ModuleType(module blueprint.Module) string
35 BlueprintFile(module blueprint.Module) string
36
Bob Badoureef4c1c2022-05-16 12:20:04 -070037 // ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer` enforcing visibility rules.
38 // Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
39 ModuleVariantsFromName(referer Module, name string) []Module
40
Yu Liu663e4502024-08-12 18:23:59 +000041 otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
Colin Crossd27e7b82020-07-02 11:38:17 -070042
Colin Cross0875c522017-11-28 17:34:01 -080043 ModuleErrorf(module blueprint.Module, format string, args ...interface{})
44 Errorf(format string, args ...interface{})
45 Failed() bool
46
47 Variable(pctx PackageContext, name, value string)
Colin Cross59014392017-12-12 11:05:06 -080048 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
Colin Cross0875c522017-11-28 17:34:01 -080049 Build(pctx PackageContext, params BuildParams)
Colin Crossc3d87d32020-06-04 13:25:17 -070050
51 // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
52 // phony rules or real files. Phony can be called on the same name multiple times to add
53 // additional dependencies.
54 Phony(name string, deps ...Path)
55
Colin Cross0875c522017-11-28 17:34:01 -080056 RequireNinjaVersion(major, minor, micro int)
57
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +020058 // SetOutDir sets the value of the top-level "builddir" Ninja variable
Colin Cross0875c522017-11-28 17:34:01 -080059 // that controls where Ninja stores its build log files. This value can be
60 // set at most one time for a single build, later calls are ignored.
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +020061 SetOutDir(pctx PackageContext, value string)
Colin Cross0875c522017-11-28 17:34:01 -080062
63 // Eval takes a string with embedded ninja variables, and returns a string
64 // with all of the variables recursively expanded. Any variables references
65 // are expanded in the scope of the PackageContext.
66 Eval(pctx PackageContext, ninjaStr string) (string, error)
67
Colin Cross2465c3d2018-09-28 10:19:18 -070068 VisitAllModulesBlueprint(visit func(blueprint.Module))
Colin Cross0875c522017-11-28 17:34:01 -080069 VisitAllModules(visit func(Module))
Yu Liuec7043d2024-11-05 18:22:20 +000070 VisitAllModuleProxies(visit func(proxy ModuleProxy))
Colin Cross0875c522017-11-28 17:34:01 -080071 VisitAllModulesIf(pred func(Module) bool, visit func(Module))
Mitch Phillips3a7a31b2019-10-16 15:00:12 -070072
73 VisitDirectDeps(module Module, visit func(Module))
74 VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))
75
Colin Cross6b753602018-06-21 13:03:07 -070076 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
Colin Cross0875c522017-11-28 17:34:01 -080077 VisitDepsDepthFirst(module Module, visit func(Module))
Colin Cross6b753602018-06-21 13:03:07 -070078 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
Colin Cross0875c522017-11-28 17:34:01 -080079 VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
80 visit func(Module))
81
82 VisitAllModuleVariants(module Module, visit func(Module))
83
Yu Liuec7043d2024-11-05 18:22:20 +000084 VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy))
85
Colin Cross0875c522017-11-28 17:34:01 -080086 PrimaryModule(module Module) Module
Yu Liu367827f2025-02-15 00:18:33 +000087
88 PrimaryModuleProxy(module ModuleProxy) ModuleProxy
89
Yu Liu88ea9ff2024-11-07 19:19:42 +000090 IsFinalModule(module Module) bool
Colin Cross0875c522017-11-28 17:34:01 -080091
92 AddNinjaFileDeps(deps ...string)
93
94 // GlobWithDeps returns a list of files that match the specified pattern but do not match any
95 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
96 // builder whenever a file matching the pattern as added or removed, without rerunning if a
97 // file that does not match the pattern is added to a searched directory.
98 GlobWithDeps(pattern string, excludes []string) ([]string, error)
Cole Faust02987bd2024-03-21 17:58:43 -070099
100 // OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
101 OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})
Cole Faust4e2bf9f2024-09-11 13:26:20 -0700102
103 // HasMutatorFinished returns true if the given mutator has finished running.
104 // It will panic if given an invalid mutator name.
105 HasMutatorFinished(mutatorName string) bool
Cole Faustf2aab5e2025-02-11 13:32:51 -0800106
107 // DistForGoals creates a rule to copy one or more Paths to the artifacts
108 // directory on the build server when any of the specified goals are built.
109 DistForGoal(goal string, paths ...Path)
110
111 // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
112 // directory on the build server with the given filename when the specified
113 // goal is built.
114 DistForGoalWithFilename(goal string, path Path, filename string)
115
116 // DistForGoals creates a rule to copy one or more Paths to the artifacts
117 // directory on the build server when any of the specified goals are built.
118 DistForGoals(goals []string, paths ...Path)
119
120 // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
121 // directory on the build server with the given filename when any of the
122 // specified goals are built.
123 DistForGoalsWithFilename(goals []string, path Path, filename string)
Colin Cross0875c522017-11-28 17:34:01 -0800124}
125
126type singletonAdaptor struct {
127 Singleton
Colin Cross4c83e5c2019-02-25 14:54:28 -0800128
129 buildParams []BuildParams
130 ruleParams map[blueprint.Rule]blueprint.RuleParams
Colin Cross0875c522017-11-28 17:34:01 -0800131}
132
Colin Cross4c83e5c2019-02-25 14:54:28 -0800133var _ testBuildProvider = (*singletonAdaptor)(nil)
134
135func (s *singletonAdaptor) GenerateBuildActions(ctx blueprint.SingletonContext) {
136 sctx := &singletonContextAdaptor{SingletonContext: ctx}
137 if sctx.Config().captureBuild {
138 sctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)
139 }
140
141 s.Singleton.GenerateBuildActions(sctx)
142
143 s.buildParams = sctx.buildParams
144 s.ruleParams = sctx.ruleParams
Cole Faustf2aab5e2025-02-11 13:32:51 -0800145
146 if len(sctx.dists) > 0 {
147 dists := getSingletonDists(sctx.Config())
148 dists.lock.Lock()
149 defer dists.lock.Unlock()
150 dists.dists = append(dists.dists, sctx.dists...)
151 }
Colin Cross4c83e5c2019-02-25 14:54:28 -0800152}
153
154func (s *singletonAdaptor) BuildParamsForTests() []BuildParams {
155 return s.buildParams
156}
157
158func (s *singletonAdaptor) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams {
159 return s.ruleParams
Colin Cross0875c522017-11-28 17:34:01 -0800160}
161
Cole Faustf2aab5e2025-02-11 13:32:51 -0800162var singletonDistsKey = NewOnceKey("singletonDistsKey")
163
164type singletonDistsAndLock struct {
165 dists []dist
166 lock sync.Mutex
167}
168
169func getSingletonDists(config Config) *singletonDistsAndLock {
170 return config.Once(singletonDistsKey, func() interface{} {
171 return &singletonDistsAndLock{}
172 }).(*singletonDistsAndLock)
173}
174
Colin Cross0875c522017-11-28 17:34:01 -0800175type Singleton interface {
176 GenerateBuildActions(SingletonContext)
177}
178
179type singletonContextAdaptor struct {
180 blueprint.SingletonContext
Colin Cross4c83e5c2019-02-25 14:54:28 -0800181
182 buildParams []BuildParams
183 ruleParams map[blueprint.Rule]blueprint.RuleParams
Cole Faustf2aab5e2025-02-11 13:32:51 -0800184 dists []dist
Colin Cross0875c522017-11-28 17:34:01 -0800185}
186
Colin Cross3c0a83d2023-12-12 14:13:26 -0800187func (s *singletonContextAdaptor) blueprintSingletonContext() blueprint.SingletonContext {
188 return s.SingletonContext
189}
190
Colin Cross4c83e5c2019-02-25 14:54:28 -0800191func (s *singletonContextAdaptor) Config() Config {
Colin Crossaabf6792017-11-29 00:27:14 -0800192 return s.SingletonContext.Config().(Config)
193}
194
Colin Cross4c83e5c2019-02-25 14:54:28 -0800195func (s *singletonContextAdaptor) DeviceConfig() DeviceConfig {
Colin Cross65494b92019-02-07 14:25:51 -0800196 return DeviceConfig{s.Config().deviceConfig}
197}
198
Colin Cross4c83e5c2019-02-25 14:54:28 -0800199func (s *singletonContextAdaptor) Variable(pctx PackageContext, name, value string) {
Colin Cross0875c522017-11-28 17:34:01 -0800200 s.SingletonContext.Variable(pctx.PackageContext, name, value)
201}
202
Colin Cross4c83e5c2019-02-25 14:54:28 -0800203func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule {
Ramy Medhat944839a2020-03-31 22:14:52 -0400204 if s.Config().UseRemoteBuild() {
205 if params.Pool == nil {
206 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
207 // jobs to the local parallelism value
208 params.Pool = localPool
209 } else if params.Pool == remotePool {
210 // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
211 // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
212 // parallelism.
213 params.Pool = nil
214 }
Colin Cross2e2dbc22019-09-25 13:31:46 -0700215 }
Colin Cross4c83e5c2019-02-25 14:54:28 -0800216 rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...)
217 if s.Config().captureBuild {
218 s.ruleParams[rule] = params
219 }
220 return rule
Colin Cross0875c522017-11-28 17:34:01 -0800221}
222
Colin Cross4c83e5c2019-02-25 14:54:28 -0800223func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) {
224 if s.Config().captureBuild {
225 s.buildParams = append(s.buildParams, params)
226 }
Colin Cross0875c522017-11-28 17:34:01 -0800227 bparams := convertBuildParams(params)
228 s.SingletonContext.Build(pctx.PackageContext, bparams)
Colin Cross0875c522017-11-28 17:34:01 -0800229}
230
Colin Crossc3d87d32020-06-04 13:25:17 -0700231func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
Yu Liu54513622024-08-19 20:00:32 +0000232 addSingletonPhony(s.Config(), name, deps...)
Colin Crossc3d87d32020-06-04 13:25:17 -0700233}
234
Lukacs T. Berki9f6c24a2021-08-26 15:07:24 +0200235func (s *singletonContextAdaptor) SetOutDir(pctx PackageContext, value string) {
236 s.SingletonContext.SetOutDir(pctx.PackageContext, value)
Colin Cross0875c522017-11-28 17:34:01 -0800237}
238
Colin Cross4c83e5c2019-02-25 14:54:28 -0800239func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (string, error) {
Colin Cross0875c522017-11-28 17:34:01 -0800240 return s.SingletonContext.Eval(pctx.PackageContext, ninjaStr)
241}
242
243// visitAdaptor wraps a visit function that takes an android.Module parameter into
Yu Liuec7043d2024-11-05 18:22:20 +0000244// a function that takes a blueprint.Module parameter and only calls the visit function if the
Colin Cross0875c522017-11-28 17:34:01 -0800245// blueprint.Module is an android.Module.
246func visitAdaptor(visit func(Module)) func(blueprint.Module) {
247 return func(module blueprint.Module) {
248 if aModule, ok := module.(Module); ok {
249 visit(aModule)
250 }
251 }
252}
253
Yu Liuec7043d2024-11-05 18:22:20 +0000254// visitProxyAdaptor wraps a visit function that takes an android.ModuleProxy parameter into
255// a function that takes a blueprint.ModuleProxy parameter.
256func visitProxyAdaptor(visit func(proxy ModuleProxy)) func(proxy blueprint.ModuleProxy) {
257 return func(module blueprint.ModuleProxy) {
258 visit(ModuleProxy{
259 module: module,
260 })
261 }
262}
263
Colin Cross0875c522017-11-28 17:34:01 -0800264// predAdaptor wraps a pred function that takes an android.Module parameter
265// into a function that takes an blueprint.Module parameter and only calls the visit function if the
266// blueprint.Module is an android.Module, otherwise returns false.
267func predAdaptor(pred func(Module) bool) func(blueprint.Module) bool {
268 return func(module blueprint.Module) bool {
269 if aModule, ok := module.(Module); ok {
270 return pred(aModule)
271 } else {
272 return false
273 }
274 }
275}
276
Yu Liu367827f2025-02-15 00:18:33 +0000277func (s *singletonContextAdaptor) ModuleName(module blueprint.Module) string {
278 return s.SingletonContext.ModuleName(getWrappedModule(module))
279}
280
281func (s *singletonContextAdaptor) ModuleDir(module blueprint.Module) string {
282 return s.SingletonContext.ModuleDir(getWrappedModule(module))
283}
284
285func (s *singletonContextAdaptor) ModuleSubDir(module blueprint.Module) string {
286 return s.SingletonContext.ModuleSubDir(getWrappedModule(module))
287}
288
289func (s *singletonContextAdaptor) ModuleType(module blueprint.Module) string {
290 return s.SingletonContext.ModuleType(getWrappedModule(module))
291}
292
Colin Cross4c83e5c2019-02-25 14:54:28 -0800293func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
Colin Cross2465c3d2018-09-28 10:19:18 -0700294 s.SingletonContext.VisitAllModules(visit)
295}
296
Colin Cross4c83e5c2019-02-25 14:54:28 -0800297func (s *singletonContextAdaptor) VisitAllModules(visit func(Module)) {
Colin Cross0875c522017-11-28 17:34:01 -0800298 s.SingletonContext.VisitAllModules(visitAdaptor(visit))
299}
300
Yu Liuec7043d2024-11-05 18:22:20 +0000301func (s *singletonContextAdaptor) VisitAllModuleProxies(visit func(proxy ModuleProxy)) {
302 s.SingletonContext.VisitAllModuleProxies(visitProxyAdaptor(visit))
303}
304
Colin Cross4c83e5c2019-02-25 14:54:28 -0800305func (s *singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) {
Colin Cross0875c522017-11-28 17:34:01 -0800306 s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit))
307}
308
Mitch Phillips3a7a31b2019-10-16 15:00:12 -0700309func (s *singletonContextAdaptor) VisitDirectDeps(module Module, visit func(Module)) {
310 s.SingletonContext.VisitDirectDeps(module, visitAdaptor(visit))
311}
312
313func (s *singletonContextAdaptor) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
314 s.SingletonContext.VisitDirectDepsIf(module, predAdaptor(pred), visitAdaptor(visit))
315}
316
Colin Cross4c83e5c2019-02-25 14:54:28 -0800317func (s *singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) {
Colin Cross0875c522017-11-28 17:34:01 -0800318 s.SingletonContext.VisitDepsDepthFirst(module, visitAdaptor(visit))
319}
320
Colin Cross4c83e5c2019-02-25 14:54:28 -0800321func (s *singletonContextAdaptor) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
Colin Cross0875c522017-11-28 17:34:01 -0800322 s.SingletonContext.VisitDepsDepthFirstIf(module, predAdaptor(pred), visitAdaptor(visit))
323}
324
Colin Cross4c83e5c2019-02-25 14:54:28 -0800325func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit func(Module)) {
Colin Cross0875c522017-11-28 17:34:01 -0800326 s.SingletonContext.VisitAllModuleVariants(module, visitAdaptor(visit))
327}
328
Yu Liuec7043d2024-11-05 18:22:20 +0000329func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) {
330 s.SingletonContext.VisitAllModuleVariantProxies(module, visitProxyAdaptor(visit))
331}
332
Colin Cross4c83e5c2019-02-25 14:54:28 -0800333func (s *singletonContextAdaptor) PrimaryModule(module Module) Module {
Colin Cross0875c522017-11-28 17:34:01 -0800334 return s.SingletonContext.PrimaryModule(module).(Module)
335}
336
Yu Liu367827f2025-02-15 00:18:33 +0000337func (s *singletonContextAdaptor) PrimaryModuleProxy(module ModuleProxy) ModuleProxy {
338 return ModuleProxy{s.SingletonContext.PrimaryModuleProxy(module.module)}
339}
340
Yu Liu88ea9ff2024-11-07 19:19:42 +0000341func (s *singletonContextAdaptor) IsFinalModule(module Module) bool {
342 return s.SingletonContext.IsFinalModule(module)
Colin Cross0875c522017-11-28 17:34:01 -0800343}
Bob Badoureef4c1c2022-05-16 12:20:04 -0700344
345func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module {
Cole Faust894bb3b2024-02-07 11:28:26 -0800346 // get module reference for visibility enforcement
Cole Faust9a24d902024-03-18 15:38:12 -0700347 qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), referer)
Bob Badoureef4c1c2022-05-16 12:20:04 -0700348
349 modules := s.SingletonContext.ModuleVariantsFromName(referer, name)
350 result := make([]Module, 0, len(modules))
351 for _, m := range modules {
352 if module, ok := m.(Module); ok {
353 // enforce visibility
354 depName := s.ModuleName(module)
355 depDir := s.ModuleDir(module)
356 depQualified := qualifiedModuleName{depDir, depName}
357 // Targets are always visible to other targets in their own package.
Cole Faust894bb3b2024-02-07 11:28:26 -0800358 if depQualified.pkg != qualified.name.pkg {
Bob Badoureef4c1c2022-05-16 12:20:04 -0700359 rule := effectiveVisibilityRules(s.Config(), depQualified)
360 if !rule.matches(qualified) {
Bob Badoura5ea2472022-05-20 16:37:26 -0700361 s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility",
362 referer.Name(), depQualified, "//"+s.ModuleDir(referer))
Bob Badoureef4c1c2022-05-16 12:20:04 -0700363 continue
364 }
365 }
366 result = append(result, module)
367 }
368 }
369 return result
370}
Colin Cross3c0a83d2023-12-12 14:13:26 -0800371
Yu Liu663e4502024-08-12 18:23:59 +0000372func (s *singletonContextAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
Colin Cross3c0a83d2023-12-12 14:13:26 -0800373 return s.SingletonContext.ModuleProvider(module, provider)
374}
Cole Faust02987bd2024-03-21 17:58:43 -0700375
376func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) {
Cole Fausta963b942024-04-11 17:43:00 -0700377 s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args...)
Cole Faust02987bd2024-03-21 17:58:43 -0700378}
Cole Faust4e2bf9f2024-09-11 13:26:20 -0700379
380func (s *singletonContextAdaptor) HasMutatorFinished(mutatorName string) bool {
381 return s.blueprintSingletonContext().HasMutatorFinished(mutatorName)
382}
Cole Faustf2aab5e2025-02-11 13:32:51 -0800383func (s *singletonContextAdaptor) DistForGoal(goal string, paths ...Path) {
384 s.DistForGoals([]string{goal}, paths...)
385}
386
387func (s *singletonContextAdaptor) DistForGoalWithFilename(goal string, path Path, filename string) {
388 s.DistForGoalsWithFilename([]string{goal}, path, filename)
389}
390
391func (s *singletonContextAdaptor) DistForGoals(goals []string, paths ...Path) {
392 var copies distCopies
393 for _, path := range paths {
394 copies = append(copies, distCopy{
395 from: path,
396 dest: path.Base(),
397 })
398 }
399 s.dists = append(s.dists, dist{
400 goals: slices.Clone(goals),
401 paths: copies,
402 })
403}
404
405func (s *singletonContextAdaptor) DistForGoalsWithFilename(goals []string, path Path, filename string) {
406 s.dists = append(s.dists, dist{
407 goals: slices.Clone(goals),
408 paths: distCopies{{from: path, dest: filename}},
409 })
410}