blob: f354db83f6f7d65eaa392efa020506c0090f91be [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{}
Dan Willemsen54daaf02018-03-12 13:24:09 -070051var _ PackageVarContext = &configErrorWrapper{}
52var _ 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
Dan Willemsen54daaf02018-03-12 13:24:09 -070065type PackageVarContext interface {
66 PathContext
67 errorfContext
68}
69
70type PackagePoolContext PackageVarContext
71type PackageRuleContext PackageVarContext
72
Colin Cross0875c522017-11-28 17:34:01 -080073// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070074// argument to a PackageVarContext.
Colin Cross0875c522017-11-28 17:34:01 -080075func (p PackageContext) VariableFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070076 f func(PackageVarContext) string) blueprint.Variable {
Colin Cross0875c522017-11-28 17:34:01 -080077
78 return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -070079 ctx := &configErrorWrapper{p, config.(Config), nil}
80 ret := f(ctx)
81 if len(ctx.errors) > 0 {
82 return "", ctx.errors[0]
83 }
84 return ret, nil
Colin Cross0875c522017-11-28 17:34:01 -080085 })
86}
87
88// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070089// argument to a Context that supports Config().
Colin Cross0875c522017-11-28 17:34:01 -080090func (p PackageContext) PoolFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070091 f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool {
Colin Cross0875c522017-11-28 17:34:01 -080092
93 return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -070094 ctx := &configErrorWrapper{p, config.(Config), nil}
95 params := f(ctx)
96 if len(ctx.errors) > 0 {
97 return params, ctx.errors[0]
98 }
99 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -0800100 })
101}
102
103// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
Colin Cross2e2dbc22019-09-25 13:31:46 -0700104// argument to a Context that supports Config(), and provides a default Pool if none is
105// specified.
Colin Cross0875c522017-11-28 17:34:01 -0800106func (p PackageContext) RuleFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -0700107 f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
Colin Cross0875c522017-11-28 17:34:01 -0800108
109 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700110 ctx := &configErrorWrapper{p, config.(Config), nil}
111 params := f(ctx)
112 if len(ctx.errors) > 0 {
113 return params, ctx.errors[0]
114 }
Colin Cross8b8bec32019-11-15 13:18:43 -0800115 if ctx.Config().UseRemoteBuild() && params.Pool == nil {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500116 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by
117 // goma/RBE, restrict jobs to the local parallelism value
Colin Cross2e2dbc22019-09-25 13:31:46 -0700118 params.Pool = localPool
119 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700120 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -0800121 }, argNames...)
122}
123
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700124// SourcePathVariable returns a Variable whose value is the source directory
125// appended with the supplied path. It may only be called during a Go package's
126// initialization - either from the init() function or as part of a
127// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800128func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700129 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700130 p, err := safePathForSource(ctx, path)
131 if err != nil {
132 ctx.Errorf("%s", err.Error())
133 }
134 return p.String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700135 })
136}
137
Colin Crossc6bbef32017-08-14 14:16:06 -0700138// SourcePathsVariable returns a Variable whose value is the source directory
139// appended with the supplied paths, joined with separator. It may only be
140// called during a Go package's initialization - either from the init()
141// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800142func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700143 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossc6bbef32017-08-14 14:16:06 -0700144 var ret []string
145 for _, path := range paths {
Colin Crossfe4bc362018-09-12 10:02:13 -0700146 p, err := safePathForSource(ctx, path)
147 if err != nil {
148 ctx.Errorf("%s", err.Error())
149 }
Colin Crossc6bbef32017-08-14 14:16:06 -0700150 ret = append(ret, p.String())
151 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700152 return strings.Join(ret, separator)
Colin Crossc6bbef32017-08-14 14:16:06 -0700153 })
154}
155
Colin Cross64162712017-08-08 13:17:59 -0700156// SourcePathVariableWithEnvOverride returns a Variable whose value is the source directory
157// appended with the supplied path, or the value of the given environment variable if it is set.
158// The environment variable is not required to point to a path inside the source tree.
159// It may only be called during a Go package's initialization - either from the init() function or
160// as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800161func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700162 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700163 p, err := safePathForSource(ctx, path)
164 if err != nil {
165 ctx.Errorf("%s", err.Error())
166 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700167 return ctx.Config().GetenvWithDefault(env, p.String())
Colin Cross64162712017-08-08 13:17:59 -0700168 })
169}
170
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800171// HostBinToolVariable returns a Variable whose value is the path to a host tool
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700172// in the bin directory for host targets. It may only be called during a Go
173// package's initialization - either from the init() function or as part of a
174// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800175func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700176 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross1c35f242021-12-08 15:05:51 -0800177 return proptools.NinjaAndShellEscape(ctx.Config().HostToolPath(ctx, path).String())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700178 })
179}
180
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800181// HostJNIToolVariable returns a Variable whose value is the path to a host tool
182// in the lib directory for host targets. It may only be called during a Go
183// package's initialization - either from the init() function or as part of a
184// package-scoped variable's initialization.
185func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700186 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross1c35f242021-12-08 15:05:51 -0800187 return proptools.NinjaAndShellEscape(ctx.Config().HostJNIToolPath(ctx, path).String())
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800188 })
189}
190
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700191// HostJavaToolVariable returns a Variable whose value is the path to a host
192// tool in the frameworks directory for host targets. It may only be called
193// during a Go package's initialization - either from the init() function or as
194// part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800195func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700196 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross1c35f242021-12-08 15:05:51 -0800197 return proptools.NinjaAndShellEscape(ctx.Config().HostJavaToolPath(ctx, path).String())
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700198 })
199}
200
201// IntermediatesPathVariable returns a Variable whose value is the intermediate
202// directory appended with the supplied path. It may only be called during a Go
203// package's initialization - either from the init() function or as part of a
204// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800205func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700206 return p.VariableFunc(name, func(ctx PackageVarContext) string {
207 return PathForIntermediates(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700208 })
209}
210
Jeff Gaston734e3802017-04-10 15:47:24 -0700211// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800212// list of present source paths prefixed with the supplied prefix. It may only
213// be called during a Go package's initialization - either from the init()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700214// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800215func (p PackageContext) PrefixedExistentPathsForSourcesVariable(
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800216 name, prefix string, paths []string) blueprint.Variable {
217
Dan Willemsen54daaf02018-03-12 13:24:09 -0700218 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross32f38982018-02-22 11:47:25 -0800219 paths := ExistentPathsForSources(ctx, paths)
Dan Willemsen54daaf02018-03-12 13:24:09 -0700220 return JoinWithPrefix(paths.Strings(), prefix)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700221 })
222}
Colin Cross9d45bb72016-08-29 16:14:13 -0700223
Colin Cross2e2dbc22019-09-25 13:31:46 -0700224// AndroidStaticRule is an alias for StaticRule.
Colin Cross0875c522017-11-28 17:34:01 -0800225func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700226 argNames ...string) blueprint.Rule {
Colin Cross2e2dbc22019-09-25 13:31:46 -0700227 return p.StaticRule(name, params, argNames...)
228}
229
230// StaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified.
231func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
232 argNames ...string) blueprint.Rule {
233 return p.RuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700234 return params
Colin Cross9d45bb72016-08-29 16:14:13 -0700235 }, argNames...)
236}
237
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500238// RemoteRuleSupports configures rules with whether they have Goma and/or RBE support.
239type RemoteRuleSupports struct {
Ramy Medhat1dcc27e2020-04-21 21:36:23 -0400240 Goma bool
241 RBE bool
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500242}
243
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500244// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
245// and the appropriate SUPPORTS_* flag is set.
246func (p PackageContext) AndroidRemoteStaticRule(name string, supports RemoteRuleSupports, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700247 argNames ...string) blueprint.Rule {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500248
249 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
250 ctx := &configErrorWrapper{p, config.(Config), nil}
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500251 if ctx.Config().UseGoma() && !supports.Goma {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500252 // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
253 // local parallelism value
254 params.Pool = localPool
255 }
256
Ramy Medhat8ea054a2020-01-27 14:19:44 -0500257 if ctx.Config().UseRBE() && !supports.RBE {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500258 // When USE_RBE=true is set and the rule is not supported by RBE, restrict jobs to the
259 // local parallelism value
260 params.Pool = localPool
261 }
262
263 return params, nil
264 }, argNames...)
Colin Cross9d45bb72016-08-29 16:14:13 -0700265}
Colin Cross77cdcfd2021-03-12 11:28:25 -0800266
267// RemoteStaticRules returns a pair of rules based on the given RuleParams, where the first rule is a
268// locally executable rule and the second rule is a remotely executable rule. commonArgs are args
269// used for both the local and remotely executable rules. reArgs are used only for remote
270// execution.
271func (p PackageContext) RemoteStaticRules(name string, ruleParams blueprint.RuleParams, reParams *remoteexec.REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
272 ruleParamsRE := ruleParams
273 ruleParams.Command = strings.ReplaceAll(ruleParams.Command, "$reTemplate", "")
274 ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, "$reTemplate", reParams.Template())
275
276 return p.AndroidStaticRule(name, ruleParams, commonArgs...),
277 p.AndroidRemoteStaticRule(name+"RE", RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
278}
279
280// MultiCommandStaticRules returns a pair of rules based on the given RuleParams, where the first
281// rule is a locally executable rule and the second rule is a remotely executable rule. This
282// function supports multiple remote execution wrappers placed in the template when commands are
283// chained together with &&. commonArgs are args used for both the local and remotely executable
284// rules. reArgs are args used only for remote execution.
285func (p PackageContext) MultiCommandRemoteStaticRules(name string, ruleParams blueprint.RuleParams, reParams map[string]*remoteexec.REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) {
286 ruleParamsRE := ruleParams
287 for k, v := range reParams {
288 ruleParams.Command = strings.ReplaceAll(ruleParams.Command, k, "")
289 ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, k, v.Template())
290 }
291
292 return p.AndroidStaticRule(name, ruleParams, commonArgs...),
293 p.AndroidRemoteStaticRule(name+"RE", RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...)
294}
295
296// StaticVariableWithEnvOverride creates a static variable that evaluates to the value of the given
297// environment variable if set, otherwise the given default.
298func (p PackageContext) StaticVariableWithEnvOverride(name, envVar, defaultVal string) blueprint.Variable {
299 return p.VariableFunc(name, func(ctx PackageVarContext) string {
300 return ctx.Config().GetenvWithDefault(envVar, defaultVal)
301 })
302}