blob: c348c82b6db668e83897f8c3aaf5d64292042934 [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"
Colin Cross1c35f242021-12-08 15:05:51 -080022 "github.com/google/blueprint/proptools"
Colin Cross77cdcfd2021-03-12 11:28:25 -080023
24 "android/soong/remoteexec"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070025)
26
Colin Cross0875c522017-11-28 17:34:01 -080027// PackageContext is a wrapper for blueprint.PackageContext that adds
Dan Willemsen34cc69e2015-09-23 15:26:20 -070028// some android-specific helper functions.
Colin Cross0875c522017-11-28 17:34:01 -080029type PackageContext struct {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070030 blueprint.PackageContext
31}
32
Colin Cross0875c522017-11-28 17:34:01 -080033func NewPackageContext(pkgPath string) PackageContext {
34 return PackageContext{blueprint.NewPackageContext(pkgPath)}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070035}
36
37// configErrorWrapper can be used with Path functions when a Context is not
38// available. A Config can be provided, and errors are stored as a list for
39// later retrieval.
40//
41// The most common use here will be with VariableFunc, where only a config is
42// provided, and an error should be returned.
43type configErrorWrapper struct {
Colin Cross0875c522017-11-28 17:34:01 -080044 pctx PackageContext
Dan Willemsen34cc69e2015-09-23 15:26:20 -070045 config Config
46 errors []error
47}
48
49var _ PathContext = &configErrorWrapper{}
50var _ errorfContext = &configErrorWrapper{}
Colin Cross662d6142022-11-03 20:38:01 -070051var _ PackageVarContext = &variableFuncContextWrapper{}
Dan Willemsen54daaf02018-03-12 13:24:09 -070052var _ PackagePoolContext = &configErrorWrapper{}
53var _ PackageRuleContext = &configErrorWrapper{}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070054
Colin Crossaabf6792017-11-29 00:27:14 -080055func (e *configErrorWrapper) Config() Config {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070056 return e.config
57}
58func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
59 e.errors = append(e.errors, fmt.Errorf(format, args...))
60}
Dan Willemsen7b310ee2015-12-18 15:11:17 -080061func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
Colin Cross12129292020-10-29 18:23:58 -070062 e.config.addNinjaFileDeps(deps...)
Dan Willemsen7b310ee2015-12-18 15:11:17 -080063}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070064
Colin Cross662d6142022-11-03 20:38:01 -070065type variableFuncContextWrapper struct {
66 configErrorWrapper
67 blueprint.VariableFuncContext
68}
69
70type PackagePoolContext interface {
Dan Willemsen54daaf02018-03-12 13:24:09 -070071 PathContext
72 errorfContext
73}
74
Colin Cross662d6142022-11-03 20:38:01 -070075type PackageRuleContext PackagePoolContext
76
77type PackageVarContext interface {
78 PackagePoolContext
79 PathGlobContext
80}
Dan Willemsen54daaf02018-03-12 13:24:09 -070081
Colin Cross0875c522017-11-28 17:34:01 -080082// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070083// argument to a PackageVarContext.
Colin Cross0875c522017-11-28 17:34:01 -080084func (p PackageContext) VariableFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070085 f func(PackageVarContext) string) blueprint.Variable {
Colin Cross0875c522017-11-28 17:34:01 -080086
Colin Cross662d6142022-11-03 20:38:01 -070087 return p.PackageContext.VariableFunc(name, func(bpctx blueprint.VariableFuncContext, config interface{}) (string, error) {
88 ctx := &variableFuncContextWrapper{
89 configErrorWrapper: configErrorWrapper{p, config.(Config), nil},
90 VariableFuncContext: bpctx,
91 }
Dan Willemsen54daaf02018-03-12 13:24:09 -070092 ret := f(ctx)
93 if len(ctx.errors) > 0 {
94 return "", ctx.errors[0]
95 }
96 return ret, nil
Colin Cross0875c522017-11-28 17:34:01 -080097 })
98}
99
100// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -0700101// argument to a Context that supports Config().
Colin Cross0875c522017-11-28 17:34:01 -0800102func (p PackageContext) PoolFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -0700103 f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool {
Colin Cross0875c522017-11-28 17:34:01 -0800104
105 return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700106 ctx := &configErrorWrapper{p, config.(Config), nil}
107 params := f(ctx)
108 if len(ctx.errors) > 0 {
109 return params, ctx.errors[0]
110 }
111 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -0800112 })
113}
114
115// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
Colin Cross2e2dbc22019-09-25 13:31:46 -0700116// argument to a Context that supports Config(), and provides a default Pool if none is
117// specified.
Colin Cross0875c522017-11-28 17:34:01 -0800118func (p PackageContext) RuleFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -0700119 f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
Colin Cross0875c522017-11-28 17:34:01 -0800120
121 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700122 ctx := &configErrorWrapper{p, config.(Config), nil}
123 params := f(ctx)
124 if len(ctx.errors) > 0 {
125 return params, ctx.errors[0]
126 }
Colin Cross8b8bec32019-11-15 13:18:43 -0800127 if ctx.Config().UseRemoteBuild() && params.Pool == nil {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500128 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by
129 // goma/RBE, restrict jobs to the local parallelism value
Colin Cross2e2dbc22019-09-25 13:31:46 -0700130 params.Pool = localPool
131 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700132 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -0800133 }, argNames...)
134}
135
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700136// SourcePathVariable returns a Variable whose value is the source directory
137// appended with the supplied path. It may only be called during a Go package's
138// initialization - either from the init() function or as part of a
139// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800140func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700141 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700142 p, err := safePathForSource(ctx, path)
143 if err != nil {
144 ctx.Errorf("%s", err.Error())
145 }
146 return p.String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700147 })
148}
149
Colin Crossc6bbef32017-08-14 14:16:06 -0700150// SourcePathsVariable returns a Variable whose value is the source directory
151// appended with the supplied paths, joined with separator. It may only be
152// called during a Go package's initialization - either from the init()
153// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800154func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700155 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossc6bbef32017-08-14 14:16:06 -0700156 var ret []string
157 for _, path := range paths {
Colin Crossfe4bc362018-09-12 10:02:13 -0700158 p, err := safePathForSource(ctx, path)
159 if err != nil {
160 ctx.Errorf("%s", err.Error())
161 }
Colin Crossc6bbef32017-08-14 14:16:06 -0700162 ret = append(ret, p.String())
163 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700164 return strings.Join(ret, separator)
Colin Crossc6bbef32017-08-14 14:16:06 -0700165 })
166}
167
Colin Cross64162712017-08-08 13:17:59 -0700168// SourcePathVariableWithEnvOverride returns a Variable whose value is the source directory
169// appended with the supplied path, or the value of the given environment variable if it is set.
170// The environment variable is not required to point to a path inside the source tree.
171// It may only be called during a Go package's initialization - either from the init() function or
172// as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800173func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700174 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700175 p, err := safePathForSource(ctx, path)
176 if err != nil {
177 ctx.Errorf("%s", err.Error())
178 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700179 return ctx.Config().GetenvWithDefault(env, p.String())
Colin Cross64162712017-08-08 13:17:59 -0700180 })
181}
182
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800183// HostBinToolVariable returns a Variable whose value is the path to a host tool
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700184// in the bin directory for host targets. It may only be called during a Go
185// package's initialization - either from the init() function or as part of a
186// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800187func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700188 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross1c35f242021-12-08 15:05:51 -0800189 return proptools.NinjaAndShellEscape(ctx.Config().HostToolPath(ctx, path).String())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700190 })
191}
192
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800193// HostJNIToolVariable returns a Variable whose value is the path to a host tool
194// in the lib directory for host targets. It may only be called during a Go
195// package's initialization - either from the init() function or as part of a
196// package-scoped variable's initialization.
197func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700198 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross1c35f242021-12-08 15:05:51 -0800199 return proptools.NinjaAndShellEscape(ctx.Config().HostJNIToolPath(ctx, path).String())
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800200 })
201}
202
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700203// HostJavaToolVariable returns a Variable whose value is the path to a host
204// tool in the frameworks directory for host targets. It may only be called
205// during a Go package's initialization - either from the init() function or as
206// part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800207func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700208 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross1c35f242021-12-08 15:05:51 -0800209 return proptools.NinjaAndShellEscape(ctx.Config().HostJavaToolPath(ctx, path).String())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700210 })
211}
212
213// IntermediatesPathVariable returns a Variable whose value is the intermediate
214// directory appended with the supplied path. It may only be called during a Go
215// package's initialization - either from the init() function or as part of a
216// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800217func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700218 return p.VariableFunc(name, func(ctx PackageVarContext) string {
219 return PathForIntermediates(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700220 })
221}
222
Jeff Gaston734e3802017-04-10 15:47:24 -0700223// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800224// list of present source paths prefixed with the supplied prefix. It may only
225// be called during a Go package's initialization - either from the init()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700226// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800227func (p PackageContext) PrefixedExistentPathsForSourcesVariable(
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800228 name, prefix string, paths []string) blueprint.Variable {
229
Dan Willemsen54daaf02018-03-12 13:24:09 -0700230 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross32f38982018-02-22 11:47:25 -0800231 paths := ExistentPathsForSources(ctx, paths)
Dan Willemsen54daaf02018-03-12 13:24:09 -0700232 return JoinWithPrefix(paths.Strings(), prefix)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700233 })
234}
Colin Cross9d45bb72016-08-29 16:14:13 -0700235
Colin Cross2e2dbc22019-09-25 13:31:46 -0700236// AndroidStaticRule is an alias for StaticRule.
Colin Cross0875c522017-11-28 17:34:01 -0800237func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700238 argNames ...string) blueprint.Rule {
Colin Cross2e2dbc22019-09-25 13:31:46 -0700239 return p.StaticRule(name, params, argNames...)
240}
241
242// StaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified.
243func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
244 argNames ...string) blueprint.Rule {
245 return p.RuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700246 return params
Colin Cross9d45bb72016-08-29 16:14:13 -0700247 }, argNames...)
248}
249
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500250// RemoteRuleSupports configures rules with whether they have Goma and/or RBE support.
251type RemoteRuleSupports struct {
Ramy Medhat1dcc27e2020-04-21 21:36:23 -0400252 Goma bool
253 RBE bool
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500254}
255
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500256// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
257// and the appropriate SUPPORTS_* flag is set.
258func (p PackageContext) AndroidRemoteStaticRule(name string, supports RemoteRuleSupports, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700259 argNames ...string) blueprint.Rule {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500260
261 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
262 ctx := &configErrorWrapper{p, config.(Config), nil}
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500263 if ctx.Config().UseGoma() && !supports.Goma {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500264 // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
265 // local parallelism value
266 params.Pool = localPool
267 }
268
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500269 if ctx.Config().UseRBE() && !supports.RBE {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500270 // When USE_RBE=true is set and the rule is not supported by RBE, restrict jobs to the
271 // local parallelism value
272 params.Pool = localPool
273 }
274
275 return params, nil
276 }, argNames...)
Colin Cross9d45bb72016-08-29 16:14:13 -0700277}
Colin Cross77cdcfd2021-03-12 11:28:25 -0800278
279// RemoteStaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
280// locally executable rule and the second rule is a remotely executable rule. commonArgs are args
281// used for both the local and remotely executable rules. reArgs are used only for remote
282// execution.
283func (p PackageContext) RemoteStaticRules(name string, ruleParams blueprint.RuleParams, reParams *remoteexec.REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
284 ruleParamsRE := ruleParams
285 ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "")
286 ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, "$reTemplate", reParams.Template())
287
288 return p.AndroidStaticRule(name, ruleParams, commonArgs...),
289 p.AndroidRemoteStaticRule(name+"RE", RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
290}
291
292// MultiCommandStaticRules returns a pair of rules based on the given RuleParams, where the first
293// rule is a locally executable rule and the second rule is a remotely executable rule. This
294// function supports multiple remote execution wrappers placed in the template when commands are
295// chained together with &&. commonArgs are args used for both the local and remotely executable
296// rules. reArgs are args used only for remote execution.
297func (p PackageContext) MultiCommandRemoteStaticRules(name string, ruleParams blueprint.RuleParams, reParams map[string]*remoteexec.REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
298 ruleParamsRE := ruleParams
299 for k, v := range reParams {
300 ruleParams.Command = strings.ReplaceAll(ruleParams.Command, k, "")
301 ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, k, v.Template())
302 }
303
304 return p.AndroidStaticRule(name, ruleParams, commonArgs...),
305 p.AndroidRemoteStaticRule(name+"RE", RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
306}
307
308// StaticVariableWithEnvOverride creates a static variable that evaluates to the value of the given
309// environment variable if set, otherwise the given default.
310func (p PackageContext) StaticVariableWithEnvOverride(name, envVar, defaultVal string) blueprint.Variable {
311 return p.VariableFunc(name, func(ctx PackageVarContext) string {
312 return ctx.Config().GetenvWithDefault(envVar, defaultVal)
313 })
314}