blob: 635066767f17bb07ebcf8fa468ccd700624edb59 [file] [log] [blame]
Dan Willemsen34cc69e2015-09-23 15:26:20 -07001// 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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Dan Willemsen34cc69e2015-09-23 15:26:20 -070016
17import (
18 "fmt"
Colin Crossc6bbef32017-08-14 14:16:06 -070019 "strings"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070020
21 "github.com/google/blueprint"
22)
23
Colin Cross0875c522017-11-28 17:34:01 -080024// PackageContext is a wrapper for blueprint.PackageContext that adds
Dan Willemsen34cc69e2015-09-23 15:26:20 -070025// some android-specific helper functions.
Colin Cross0875c522017-11-28 17:34:01 -080026type PackageContext struct {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070027 blueprint.PackageContext
28}
29
Colin Cross0875c522017-11-28 17:34:01 -080030func NewPackageContext(pkgPath string) PackageContext {
31 return PackageContext{blueprint.NewPackageContext(pkgPath)}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070032}
33
34// configErrorWrapper can be used with Path functions when a Context is not
35// available. A Config can be provided, and errors are stored as a list for
36// later retrieval.
37//
38// The most common use here will be with VariableFunc, where only a config is
39// provided, and an error should be returned.
40type configErrorWrapper struct {
Colin Cross0875c522017-11-28 17:34:01 -080041 pctx PackageContext
Dan Willemsen34cc69e2015-09-23 15:26:20 -070042 config Config
43 errors []error
44}
45
46var _ PathContext = &configErrorWrapper{}
47var _ errorfContext = &configErrorWrapper{}
Dan Willemsen54daaf02018-03-12 13:24:09 -070048var _ PackageVarContext = &configErrorWrapper{}
49var _ PackagePoolContext = &configErrorWrapper{}
50var _ PackageRuleContext = &configErrorWrapper{}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070051
Colin Crossaabf6792017-11-29 00:27:14 -080052func (e *configErrorWrapper) Config() Config {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070053 return e.config
54}
55func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
56 e.errors = append(e.errors, fmt.Errorf(format, args...))
57}
Dan Willemsen7b310ee2015-12-18 15:11:17 -080058func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
59 e.pctx.AddNinjaFileDeps(deps...)
60}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070061
Dan Willemsen54daaf02018-03-12 13:24:09 -070062type PackageVarContext interface {
63 PathContext
64 errorfContext
65}
66
67type PackagePoolContext PackageVarContext
68type PackageRuleContext PackageVarContext
69
Colin Cross0875c522017-11-28 17:34:01 -080070// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070071// argument to a PackageVarContext.
Colin Cross0875c522017-11-28 17:34:01 -080072func (p PackageContext) VariableFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070073 f func(PackageVarContext) string) blueprint.Variable {
Colin Cross0875c522017-11-28 17:34:01 -080074
75 return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -070076 ctx := &configErrorWrapper{p, config.(Config), nil}
77 ret := f(ctx)
78 if len(ctx.errors) > 0 {
79 return "", ctx.errors[0]
80 }
81 return ret, nil
Colin Cross0875c522017-11-28 17:34:01 -080082 })
83}
84
85// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070086// argument to a Context that supports Config().
Colin Cross0875c522017-11-28 17:34:01 -080087func (p PackageContext) PoolFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070088 f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool {
Colin Cross0875c522017-11-28 17:34:01 -080089
90 return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -070091 ctx := &configErrorWrapper{p, config.(Config), nil}
92 params := f(ctx)
93 if len(ctx.errors) > 0 {
94 return params, ctx.errors[0]
95 }
96 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -080097 })
98}
99
100// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
Colin Cross2e2dbc22019-09-25 13:31:46 -0700101// argument to a Context that supports Config(), and provides a default Pool if none is
102// specified.
Colin Cross0875c522017-11-28 17:34:01 -0800103func (p PackageContext) RuleFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -0700104 f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
Colin Cross0875c522017-11-28 17:34:01 -0800105
106 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700107 ctx := &configErrorWrapper{p, config.(Config), nil}
108 params := f(ctx)
109 if len(ctx.errors) > 0 {
110 return params, ctx.errors[0]
111 }
Colin Cross8b8bec32019-11-15 13:18:43 -0800112 if ctx.Config().UseRemoteBuild() && params.Pool == nil {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500113 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by
114 // goma/RBE, restrict jobs to the local parallelism value
Colin Cross2e2dbc22019-09-25 13:31:46 -0700115 params.Pool = localPool
116 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700117 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -0800118 }, argNames...)
119}
120
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700121// 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.
Colin Cross0875c522017-11-28 17:34:01 -0800125func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700126 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700127 p, err := safePathForSource(ctx, path)
128 if err != nil {
129 ctx.Errorf("%s", err.Error())
130 }
131 return p.String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700132 })
133}
134
Colin Crossc6bbef32017-08-14 14:16:06 -0700135// 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.
Colin Cross0875c522017-11-28 17:34:01 -0800139func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700140 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossc6bbef32017-08-14 14:16:06 -0700141 var ret []string
142 for _, path := range paths {
Colin Crossfe4bc362018-09-12 10:02:13 -0700143 p, err := safePathForSource(ctx, path)
144 if err != nil {
145 ctx.Errorf("%s", err.Error())
146 }
Colin Crossc6bbef32017-08-14 14:16:06 -0700147 ret = append(ret, p.String())
148 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700149 return strings.Join(ret, separator)
Colin Crossc6bbef32017-08-14 14:16:06 -0700150 })
151}
152
Colin Cross64162712017-08-08 13:17:59 -0700153// 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.
Colin Cross0875c522017-11-28 17:34:01 -0800158func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700159 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700160 p, err := safePathForSource(ctx, path)
161 if err != nil {
162 ctx.Errorf("%s", err.Error())
163 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700164 return ctx.Config().GetenvWithDefault(env, p.String())
Colin Cross64162712017-08-08 13:17:59 -0700165 })
166}
167
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800168// HostBinToolVariable returns a Variable whose value is the path to a host tool
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700169// 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.
Colin Cross0875c522017-11-28 17:34:01 -0800172func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700173 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Martin Stjernholm7260d062019-12-09 21:47:14 +0000174 return ctx.Config().HostToolPath(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700175 })
176}
177
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800178// HostJNIToolVariable returns a Variable whose value is the path to a host tool
179// in the lib directory for host targets. It may only be called during a Go
180// package's initialization - either from the init() function or as part of a
181// package-scoped variable's initialization.
182func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700183 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Martin Stjernholm7260d062019-12-09 21:47:14 +0000184 return ctx.Config().HostJNIToolPath(ctx, path).String()
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800185 })
186}
187
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700188// HostJavaToolVariable returns a Variable whose value is the path to a host
189// tool in the frameworks directory for host targets. It may only be called
190// during a Go package's initialization - either from the init() function or as
191// part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800192func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700193 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Martin Stjernholm7260d062019-12-09 21:47:14 +0000194 return ctx.Config().HostJavaToolPath(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700195 })
196}
197
198// IntermediatesPathVariable returns a Variable whose value is the intermediate
199// directory appended with the supplied path. It may only be called during a Go
200// package's initialization - either from the init() function or as part of a
201// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800202func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700203 return p.VariableFunc(name, func(ctx PackageVarContext) string {
204 return PathForIntermediates(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700205 })
206}
207
Jeff Gaston734e3802017-04-10 15:47:24 -0700208// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800209// list of present source paths prefixed with the supplied prefix. It may only
210// be called during a Go package's initialization - either from the init()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700211// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800212func (p PackageContext) PrefixedExistentPathsForSourcesVariable(
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800213 name, prefix string, paths []string) blueprint.Variable {
214
Dan Willemsen54daaf02018-03-12 13:24:09 -0700215 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross32f38982018-02-22 11:47:25 -0800216 paths := ExistentPathsForSources(ctx, paths)
Dan Willemsen54daaf02018-03-12 13:24:09 -0700217 return JoinWithPrefix(paths.Strings(), prefix)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700218 })
219}
Colin Cross9d45bb72016-08-29 16:14:13 -0700220
Colin Cross2e2dbc22019-09-25 13:31:46 -0700221// AndroidStaticRule is an alias for StaticRule.
Colin Cross0875c522017-11-28 17:34:01 -0800222func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700223 argNames ...string) blueprint.Rule {
Colin Cross2e2dbc22019-09-25 13:31:46 -0700224 return p.StaticRule(name, params, argNames...)
225}
226
227// StaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified.
228func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
229 argNames ...string) blueprint.Rule {
230 return p.RuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700231 return params
Colin Cross9d45bb72016-08-29 16:14:13 -0700232 }, argNames...)
233}
234
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500235// RemoteRuleSupports selects if a AndroidRemoteStaticRule supports goma, RBE, or both.
236type RemoteRuleSupports int
237
238const (
239 SUPPORTS_NONE = 0
240 SUPPORTS_GOMA = 1 << iota
241 SUPPORTS_RBE = 1 << iota
242 SUPPORTS_BOTH = SUPPORTS_GOMA | SUPPORTS_RBE
243)
244
245// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
246// and the appropriate SUPPORTS_* flag is set.
247func (p PackageContext) AndroidRemoteStaticRule(name string, supports RemoteRuleSupports, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700248 argNames ...string) blueprint.Rule {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500249
250 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
251 ctx := &configErrorWrapper{p, config.(Config), nil}
252 if ctx.Config().UseGoma() && supports&SUPPORTS_GOMA == 0 {
253 // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
254 // local parallelism value
255 params.Pool = localPool
256 }
257
258 if ctx.Config().UseRBE() && supports&SUPPORTS_RBE == 0 {
259 // When USE_RBE=true is set and the rule is not supported by RBE, restrict jobs to the
260 // local parallelism value
261 params.Pool = localPool
262 }
263
264 return params, nil
265 }, argNames...)
Colin Cross9d45bb72016-08-29 16:14:13 -0700266}