1// 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 ( 18 "github.com/google/blueprint" 19 "github.com/google/blueprint/pathtools" 20) 21 22// SingletonContext 23type SingletonContext interface { 24 Config() Config 25 DeviceConfig() DeviceConfig 26 27 ModuleName(module blueprint.Module) string 28 ModuleDir(module blueprint.Module) string 29 ModuleSubDir(module blueprint.Module) string 30 ModuleType(module blueprint.Module) string 31 BlueprintFile(module blueprint.Module) string 32 33 ModuleErrorf(module blueprint.Module, format string, args ...interface{}) 34 Errorf(format string, args ...interface{}) 35 Failed() bool 36 37 Variable(pctx PackageContext, name, value string) 38 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule 39 Build(pctx PackageContext, params BuildParams) 40 RequireNinjaVersion(major, minor, micro int) 41 42 // SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable 43 // that controls where Ninja stores its build log files. This value can be 44 // set at most one time for a single build, later calls are ignored. 45 SetNinjaBuildDir(pctx PackageContext, value string) 46 47 // Eval takes a string with embedded ninja variables, and returns a string 48 // with all of the variables recursively expanded. Any variables references 49 // are expanded in the scope of the PackageContext. 50 Eval(pctx PackageContext, ninjaStr string) (string, error) 51 52 VisitAllModulesBlueprint(visit func(blueprint.Module)) 53 VisitAllModules(visit func(Module)) 54 VisitAllModulesIf(pred func(Module) bool, visit func(Module)) 55 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module 56 VisitDepsDepthFirst(module Module, visit func(Module)) 57 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module 58 VisitDepsDepthFirstIf(module Module, pred func(Module) bool, 59 visit func(Module)) 60 61 VisitAllModuleVariants(module Module, visit func(Module)) 62 63 PrimaryModule(module Module) Module 64 FinalModule(module Module) Module 65 66 AddNinjaFileDeps(deps ...string) 67 68 // GlobWithDeps returns a list of files that match the specified pattern but do not match any 69 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary 70 // builder whenever a file matching the pattern as added or removed, without rerunning if a 71 // file that does not match the pattern is added to a searched directory. 72 GlobWithDeps(pattern string, excludes []string) ([]string, error) 73 74 Fs() pathtools.FileSystem 75} 76 77type singletonAdaptor struct { 78 Singleton 79 80 buildParams []BuildParams 81 ruleParams map[blueprint.Rule]blueprint.RuleParams 82} 83 84var _ testBuildProvider = (*singletonAdaptor)(nil) 85 86func (s *singletonAdaptor) GenerateBuildActions(ctx blueprint.SingletonContext) { 87 sctx := &singletonContextAdaptor{SingletonContext: ctx} 88 if sctx.Config().captureBuild { 89 sctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams) 90 } 91 92 s.Singleton.GenerateBuildActions(sctx) 93 94 s.buildParams = sctx.buildParams 95 s.ruleParams = sctx.ruleParams 96} 97 98func (s *singletonAdaptor) BuildParamsForTests() []BuildParams { 99 return s.buildParams 100} 101 102func (s *singletonAdaptor) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams { 103 return s.ruleParams 104} 105 106type Singleton interface { 107 GenerateBuildActions(SingletonContext) 108} 109 110type singletonContextAdaptor struct { 111 blueprint.SingletonContext 112 113 buildParams []BuildParams 114 ruleParams map[blueprint.Rule]blueprint.RuleParams 115} 116 117func (s *singletonContextAdaptor) Config() Config { 118 return s.SingletonContext.Config().(Config) 119} 120 121func (s *singletonContextAdaptor) DeviceConfig() DeviceConfig { 122 return DeviceConfig{s.Config().deviceConfig} 123} 124 125func (s *singletonContextAdaptor) Variable(pctx PackageContext, name, value string) { 126 s.SingletonContext.Variable(pctx.PackageContext, name, value) 127} 128 129func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule { 130 rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...) 131 if s.Config().captureBuild { 132 s.ruleParams[rule] = params 133 } 134 return rule 135} 136 137func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) { 138 if s.Config().captureBuild { 139 s.buildParams = append(s.buildParams, params) 140 } 141 bparams := convertBuildParams(params) 142 s.SingletonContext.Build(pctx.PackageContext, bparams) 143 144} 145 146func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) { 147 s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value) 148} 149 150func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (string, error) { 151 return s.SingletonContext.Eval(pctx.PackageContext, ninjaStr) 152} 153 154// visitAdaptor wraps a visit function that takes an android.Module parameter into 155// a function that takes an blueprint.Module parameter and only calls the visit function if the 156// blueprint.Module is an android.Module. 157func visitAdaptor(visit func(Module)) func(blueprint.Module) { 158 return func(module blueprint.Module) { 159 if aModule, ok := module.(Module); ok { 160 visit(aModule) 161 } 162 } 163} 164 165// predAdaptor wraps a pred function that takes an android.Module parameter 166// into a function that takes an blueprint.Module parameter and only calls the visit function if the 167// blueprint.Module is an android.Module, otherwise returns false. 168func predAdaptor(pred func(Module) bool) func(blueprint.Module) bool { 169 return func(module blueprint.Module) bool { 170 if aModule, ok := module.(Module); ok { 171 return pred(aModule) 172 } else { 173 return false 174 } 175 } 176} 177 178func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) { 179 s.SingletonContext.VisitAllModules(visit) 180} 181 182func (s *singletonContextAdaptor) VisitAllModules(visit func(Module)) { 183 s.SingletonContext.VisitAllModules(visitAdaptor(visit)) 184} 185 186func (s *singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) { 187 s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit)) 188} 189 190func (s *singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) { 191 s.SingletonContext.VisitDepsDepthFirst(module, visitAdaptor(visit)) 192} 193 194func (s *singletonContextAdaptor) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) { 195 s.SingletonContext.VisitDepsDepthFirstIf(module, predAdaptor(pred), visitAdaptor(visit)) 196} 197 198func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit func(Module)) { 199 s.SingletonContext.VisitAllModuleVariants(module, visitAdaptor(visit)) 200} 201 202func (s *singletonContextAdaptor) PrimaryModule(module Module) Module { 203 return s.SingletonContext.PrimaryModule(module).(Module) 204} 205 206func (s *singletonContextAdaptor) FinalModule(module Module) Module { 207 return s.SingletonContext.FinalModule(module).(Module) 208} 209