• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 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	"fmt"
19	"runtime"
20	"strings"
21
22	"github.com/google/blueprint"
23	"github.com/google/blueprint/pathtools"
24)
25
26// PackageContext is a wrapper for blueprint.PackageContext that adds
27// some android-specific helper functions.
28type PackageContext struct {
29	blueprint.PackageContext
30}
31
32func NewPackageContext(pkgPath string) PackageContext {
33	return PackageContext{blueprint.NewPackageContext(pkgPath)}
34}
35
36// configErrorWrapper can be used with Path functions when a Context is not
37// available. A Config can be provided, and errors are stored as a list for
38// later retrieval.
39//
40// The most common use here will be with VariableFunc, where only a config is
41// provided, and an error should be returned.
42type configErrorWrapper struct {
43	pctx   PackageContext
44	config Config
45	errors []error
46}
47
48var _ PathContext = &configErrorWrapper{}
49var _ errorfContext = &configErrorWrapper{}
50var _ PackageVarContext = &configErrorWrapper{}
51var _ PackagePoolContext = &configErrorWrapper{}
52var _ PackageRuleContext = &configErrorWrapper{}
53
54func (e *configErrorWrapper) Config() Config {
55	return e.config
56}
57func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
58	e.errors = append(e.errors, fmt.Errorf(format, args...))
59}
60func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
61	e.pctx.AddNinjaFileDeps(deps...)
62}
63
64func (e *configErrorWrapper) Fs() pathtools.FileSystem {
65	return nil
66}
67
68type PackageVarContext interface {
69	PathContext
70	errorfContext
71}
72
73type PackagePoolContext PackageVarContext
74type PackageRuleContext PackageVarContext
75
76// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
77// argument to a PackageVarContext.
78func (p PackageContext) VariableFunc(name string,
79	f func(PackageVarContext) string) blueprint.Variable {
80
81	return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
82		ctx := &configErrorWrapper{p, config.(Config), nil}
83		ret := f(ctx)
84		if len(ctx.errors) > 0 {
85			return "", ctx.errors[0]
86		}
87		return ret, nil
88	})
89}
90
91// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config
92// argument to a Context that supports Config().
93func (p PackageContext) PoolFunc(name string,
94	f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool {
95
96	return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) {
97		ctx := &configErrorWrapper{p, config.(Config), nil}
98		params := f(ctx)
99		if len(ctx.errors) > 0 {
100			return params, ctx.errors[0]
101		}
102		return params, nil
103	})
104}
105
106// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
107// argument to a Context that supports Config().
108func (p PackageContext) RuleFunc(name string,
109	f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
110
111	return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
112		ctx := &configErrorWrapper{p, config.(Config), nil}
113		params := f(ctx)
114		if len(ctx.errors) > 0 {
115			return params, ctx.errors[0]
116		}
117		return params, nil
118	}, argNames...)
119}
120
121// SourcePathVariable returns a Variable whose value is the source directory
122// appended with the supplied path. It may only be called during a Go package's
123// initialization - either from the init() function or as part of a
124// package-scoped variable's initialization.
125func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable {
126	return p.VariableFunc(name, func(ctx PackageVarContext) string {
127		p, err := safePathForSource(ctx, path)
128		if err != nil {
129			ctx.Errorf("%s", err.Error())
130		}
131		return p.String()
132	})
133}
134
135// SourcePathsVariable returns a Variable whose value is the source directory
136// appended with the supplied paths, joined with separator. It may only be
137// called during a Go package's initialization - either from the init()
138// function or as part of a package-scoped variable's initialization.
139func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable {
140	return p.VariableFunc(name, func(ctx PackageVarContext) string {
141		var ret []string
142		for _, path := range paths {
143			p, err := safePathForSource(ctx, path)
144			if err != nil {
145				ctx.Errorf("%s", err.Error())
146			}
147			ret = append(ret, p.String())
148		}
149		return strings.Join(ret, separator)
150	})
151}
152
153// SourcePathVariableWithEnvOverride returns a Variable whose value is the source directory
154// appended with the supplied path, or the value of the given environment variable if it is set.
155// The environment variable is not required to point to a path inside the source tree.
156// It may only be called during a Go package's initialization - either from the init() function or
157// as part of a package-scoped variable's initialization.
158func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable {
159	return p.VariableFunc(name, func(ctx PackageVarContext) string {
160		p, err := safePathForSource(ctx, path)
161		if err != nil {
162			ctx.Errorf("%s", err.Error())
163		}
164		return ctx.Config().GetenvWithDefault(env, p.String())
165	})
166}
167
168// HostBinToolVariable returns a Variable whose value is the path to a host tool
169// in the bin directory for host targets. It may only be called during a Go
170// package's initialization - either from the init() function or as part of a
171// package-scoped variable's initialization.
172func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
173	return p.VariableFunc(name, func(ctx PackageVarContext) string {
174		return p.HostBinToolPath(ctx, path).String()
175	})
176}
177
178func (p PackageContext) HostBinToolPath(ctx PackageVarContext, path string) Path {
179	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin", path)
180}
181
182// HostJNIToolVariable returns a Variable whose value is the path to a host tool
183// in the lib directory for host targets. It may only be called during a Go
184// package's initialization - either from the init() function or as part of a
185// package-scoped variable's initialization.
186func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
187	return p.VariableFunc(name, func(ctx PackageVarContext) string {
188		return p.HostJNIToolPath(ctx, path).String()
189	})
190}
191
192func (p PackageContext) HostJNIToolPath(ctx PackageVarContext, path string) Path {
193	ext := ".so"
194	if runtime.GOOS == "darwin" {
195		ext = ".dylib"
196	}
197	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "lib64", path+ext)
198}
199
200// HostJavaToolVariable returns a Variable whose value is the path to a host
201// tool in the frameworks directory for host targets. It may only be called
202// during a Go package's initialization - either from the init() function or as
203// part of a package-scoped variable's initialization.
204func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
205	return p.VariableFunc(name, func(ctx PackageVarContext) string {
206		return p.HostJavaToolPath(ctx, path).String()
207	})
208}
209
210func (p PackageContext) HostJavaToolPath(ctx PackageVarContext, path string) Path {
211	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", path)
212}
213
214// IntermediatesPathVariable returns a Variable whose value is the intermediate
215// directory appended with the supplied path. It may only be called during a Go
216// package's initialization - either from the init() function or as part of a
217// package-scoped variable's initialization.
218func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
219	return p.VariableFunc(name, func(ctx PackageVarContext) string {
220		return PathForIntermediates(ctx, path).String()
221	})
222}
223
224// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the
225// list of present source paths prefixed with the supplied prefix. It may only
226// be called during a Go package's initialization - either from the init()
227// function or as part of a package-scoped variable's initialization.
228func (p PackageContext) PrefixedExistentPathsForSourcesVariable(
229	name, prefix string, paths []string) blueprint.Variable {
230
231	return p.VariableFunc(name, func(ctx PackageVarContext) string {
232		paths := ExistentPathsForSources(ctx, paths)
233		return JoinWithPrefix(paths.Strings(), prefix)
234	})
235}
236
237// AndroidStaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified
238func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
239	argNames ...string) blueprint.Rule {
240	return p.AndroidRuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
241		return params
242	}, argNames...)
243}
244
245// AndroidGomaStaticRule wraps blueprint.StaticRule but uses goma's parallelism if goma is enabled
246func (p PackageContext) AndroidGomaStaticRule(name string, params blueprint.RuleParams,
247	argNames ...string) blueprint.Rule {
248	return p.StaticRule(name, params, argNames...)
249}
250
251func (p PackageContext) AndroidRuleFunc(name string,
252	f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
253	return p.RuleFunc(name, func(ctx PackageRuleContext) blueprint.RuleParams {
254		params := f(ctx)
255		if ctx.Config().UseGoma() && params.Pool == nil {
256			// When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
257			// local parallelism value
258			params.Pool = localPool
259		}
260		return params
261	}, argNames...)
262}
263