• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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
15package blueprint
16
17import (
18	"fmt"
19	"github.com/google/blueprint/pathtools"
20)
21
22type Singleton interface {
23	GenerateBuildActions(SingletonContext)
24}
25
26type SingletonContext interface {
27	Config() interface{}
28
29	ModuleName(module Module) string
30	ModuleDir(module Module) string
31	ModuleSubDir(module Module) string
32	ModuleType(module Module) string
33	BlueprintFile(module Module) string
34
35	ModuleErrorf(module Module, format string, args ...interface{})
36	Errorf(format string, args ...interface{})
37	Failed() bool
38
39	Variable(pctx PackageContext, name, value string)
40	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
41	Build(pctx PackageContext, params BuildParams)
42	RequireNinjaVersion(major, minor, micro int)
43
44	// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
45	// that controls where Ninja stores its build log files.  This value can be
46	// set at most one time for a single build, later calls are ignored.
47	SetNinjaBuildDir(pctx PackageContext, value string)
48
49	// Eval takes a string with embedded ninja variables, and returns a string
50	// with all of the variables recursively expanded. Any variables references
51	// are expanded in the scope of the PackageContext.
52	Eval(pctx PackageContext, ninjaStr string) (string, error)
53
54	VisitAllModules(visit func(Module))
55	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
56	VisitDepsDepthFirst(module Module, visit func(Module))
57	VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
58		visit func(Module))
59
60	VisitAllModuleVariants(module Module, visit func(Module))
61
62	PrimaryModule(module Module) Module
63	FinalModule(module Module) Module
64
65	AddNinjaFileDeps(deps ...string)
66
67	// GlobWithDeps returns a list of files that match the specified pattern but do not match any
68	// of the patterns in excludes.  It also adds efficient dependencies to rerun the primary
69	// builder whenever a file matching the pattern as added or removed, without rerunning if a
70	// file that does not match the pattern is added to a searched directory.
71	GlobWithDeps(pattern string, excludes []string) ([]string, error)
72
73	Fs() pathtools.FileSystem
74}
75
76var _ SingletonContext = (*singletonContext)(nil)
77
78type singletonContext struct {
79	context *Context
80	config  interface{}
81	scope   *localScope
82	globals *liveTracker
83
84	ninjaFileDeps []string
85	errs          []error
86
87	actionDefs localBuildActions
88}
89
90func (s *singletonContext) Config() interface{} {
91	return s.config
92}
93
94func (s *singletonContext) ModuleName(logicModule Module) string {
95	return s.context.ModuleName(logicModule)
96}
97
98func (s *singletonContext) ModuleDir(logicModule Module) string {
99	return s.context.ModuleDir(logicModule)
100}
101
102func (s *singletonContext) ModuleSubDir(logicModule Module) string {
103	return s.context.ModuleSubDir(logicModule)
104}
105
106func (s *singletonContext) ModuleType(logicModule Module) string {
107	return s.context.ModuleType(logicModule)
108}
109
110func (s *singletonContext) BlueprintFile(logicModule Module) string {
111	return s.context.BlueprintFile(logicModule)
112}
113
114func (s *singletonContext) error(err error) {
115	if err != nil {
116		s.errs = append(s.errs, err)
117	}
118}
119
120func (s *singletonContext) ModuleErrorf(logicModule Module, format string,
121	args ...interface{}) {
122
123	s.error(s.context.ModuleErrorf(logicModule, format, args...))
124}
125
126func (s *singletonContext) Errorf(format string, args ...interface{}) {
127	// TODO: Make this not result in the error being printed as "internal error"
128	s.error(fmt.Errorf(format, args...))
129}
130
131func (s *singletonContext) Failed() bool {
132	return len(s.errs) > 0
133}
134
135func (s *singletonContext) Variable(pctx PackageContext, name, value string) {
136	s.scope.ReparentTo(pctx)
137
138	v, err := s.scope.AddLocalVariable(name, value)
139	if err != nil {
140		panic(err)
141	}
142
143	s.actionDefs.variables = append(s.actionDefs.variables, v)
144}
145
146func (s *singletonContext) Rule(pctx PackageContext, name string,
147	params RuleParams, argNames ...string) Rule {
148
149	s.scope.ReparentTo(pctx)
150
151	r, err := s.scope.AddLocalRule(name, &params, argNames...)
152	if err != nil {
153		panic(err)
154	}
155
156	s.actionDefs.rules = append(s.actionDefs.rules, r)
157
158	return r
159}
160
161func (s *singletonContext) Build(pctx PackageContext, params BuildParams) {
162	s.scope.ReparentTo(pctx)
163
164	def, err := parseBuildParams(s.scope, &params)
165	if err != nil {
166		panic(err)
167	}
168
169	s.actionDefs.buildDefs = append(s.actionDefs.buildDefs, def)
170}
171
172func (s *singletonContext) Eval(pctx PackageContext, str string) (string, error) {
173	s.scope.ReparentTo(pctx)
174
175	ninjaStr, err := parseNinjaString(s.scope, str)
176	if err != nil {
177		return "", err
178	}
179
180	err = s.globals.addNinjaStringDeps(ninjaStr)
181	if err != nil {
182		return "", err
183	}
184
185	return ninjaStr.Eval(s.globals.variables)
186}
187
188func (s *singletonContext) RequireNinjaVersion(major, minor, micro int) {
189	s.context.requireNinjaVersion(major, minor, micro)
190}
191
192func (s *singletonContext) SetNinjaBuildDir(pctx PackageContext, value string) {
193	s.scope.ReparentTo(pctx)
194
195	ninjaValue, err := parseNinjaString(s.scope, value)
196	if err != nil {
197		panic(err)
198	}
199
200	s.context.setNinjaBuildDir(ninjaValue)
201}
202
203func (s *singletonContext) VisitAllModules(visit func(Module)) {
204	s.context.VisitAllModules(visit)
205}
206
207func (s *singletonContext) VisitAllModulesIf(pred func(Module) bool,
208	visit func(Module)) {
209
210	s.context.VisitAllModulesIf(pred, visit)
211}
212
213func (s *singletonContext) VisitDepsDepthFirst(module Module,
214	visit func(Module)) {
215
216	s.context.VisitDepsDepthFirst(module, visit)
217}
218
219func (s *singletonContext) VisitDepsDepthFirstIf(module Module,
220	pred func(Module) bool, visit func(Module)) {
221
222	s.context.VisitDepsDepthFirstIf(module, pred, visit)
223}
224
225func (s *singletonContext) PrimaryModule(module Module) Module {
226	return s.context.PrimaryModule(module)
227}
228
229func (s *singletonContext) FinalModule(module Module) Module {
230	return s.context.FinalModule(module)
231}
232
233func (s *singletonContext) VisitAllModuleVariants(module Module, visit func(Module)) {
234	s.context.VisitAllModuleVariants(module, visit)
235}
236
237func (s *singletonContext) AddNinjaFileDeps(deps ...string) {
238	s.ninjaFileDeps = append(s.ninjaFileDeps, deps...)
239}
240
241func (s *singletonContext) GlobWithDeps(pattern string,
242	excludes []string) ([]string, error) {
243	return s.context.glob(pattern, excludes)
244}
245
246func (s *singletonContext) Fs() pathtools.FileSystem {
247	return s.context.fs
248}
249