blob: cf8facef49f31abfcf309a58fd761d630e065629 [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 Cross5ab4e6d2017-11-22 16:20:45 -080019 "runtime"
Colin Crossc6bbef32017-08-14 14:16:06 -070020 "strings"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070021
22 "github.com/google/blueprint"
Colin Cross294941b2017-02-01 14:10:36 -080023 "github.com/google/blueprint/pathtools"
Dan Willemsen34cc69e2015-09-23 15:26:20 -070024)
25
Colin Cross0875c522017-11-28 17:34:01 -080026// PackageContext is a wrapper for blueprint.PackageContext that adds
Dan Willemsen34cc69e2015-09-23 15:26:20 -070027// some android-specific helper functions.
Colin Cross0875c522017-11-28 17:34:01 -080028type PackageContext struct {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070029 blueprint.PackageContext
30}
31
Colin Cross0875c522017-11-28 17:34:01 -080032func NewPackageContext(pkgPath string) PackageContext {
33 return PackageContext{blueprint.NewPackageContext(pkgPath)}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070034}
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 {
Colin Cross0875c522017-11-28 17:34:01 -080043 pctx PackageContext
Dan Willemsen34cc69e2015-09-23 15:26:20 -070044 config Config
45 errors []error
46}
47
48var _ PathContext = &configErrorWrapper{}
49var _ errorfContext = &configErrorWrapper{}
Dan Willemsen54daaf02018-03-12 13:24:09 -070050var _ PackageVarContext = &configErrorWrapper{}
51var _ PackagePoolContext = &configErrorWrapper{}
52var _ PackageRuleContext = &configErrorWrapper{}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070053
Colin Crossaabf6792017-11-29 00:27:14 -080054func (e *configErrorWrapper) Config() Config {
Dan Willemsen34cc69e2015-09-23 15:26:20 -070055 return e.config
56}
57func (e *configErrorWrapper) Errorf(format string, args ...interface{}) {
58 e.errors = append(e.errors, fmt.Errorf(format, args...))
59}
Dan Willemsen7b310ee2015-12-18 15:11:17 -080060func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
61 e.pctx.AddNinjaFileDeps(deps...)
62}
Dan Willemsen34cc69e2015-09-23 15:26:20 -070063
Colin Cross294941b2017-02-01 14:10:36 -080064func (e *configErrorWrapper) Fs() pathtools.FileSystem {
65 return nil
66}
67
Dan Willemsen54daaf02018-03-12 13:24:09 -070068type PackageVarContext interface {
69 PathContext
70 errorfContext
71}
72
73type PackagePoolContext PackageVarContext
74type PackageRuleContext PackageVarContext
75
Colin Cross0875c522017-11-28 17:34:01 -080076// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070077// argument to a PackageVarContext.
Colin Cross0875c522017-11-28 17:34:01 -080078func (p PackageContext) VariableFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070079 f func(PackageVarContext) string) blueprint.Variable {
Colin Cross0875c522017-11-28 17:34:01 -080080
81 return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -070082 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
Colin Cross0875c522017-11-28 17:34:01 -080088 })
89}
90
91// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config
Dan Willemsen54daaf02018-03-12 13:24:09 -070092// argument to a Context that supports Config().
Colin Cross0875c522017-11-28 17:34:01 -080093func (p PackageContext) PoolFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -070094 f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool {
Colin Cross0875c522017-11-28 17:34:01 -080095
96 return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -070097 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
Colin Cross0875c522017-11-28 17:34:01 -0800103 })
104}
105
106// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config
Colin Cross2e2dbc22019-09-25 13:31:46 -0700107// argument to a Context that supports Config(), and provides a default Pool if none is
108// specified.
Colin Cross0875c522017-11-28 17:34:01 -0800109func (p PackageContext) RuleFunc(name string,
Dan Willemsen54daaf02018-03-12 13:24:09 -0700110 f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule {
Colin Cross0875c522017-11-28 17:34:01 -0800111
112 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700113 ctx := &configErrorWrapper{p, config.(Config), nil}
114 params := f(ctx)
115 if len(ctx.errors) > 0 {
116 return params, ctx.errors[0]
117 }
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500118 if (ctx.Config().UseGoma() || ctx.Config().UseRBE()) && params.Pool == nil {
119 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by
120 // goma/RBE, restrict jobs to the local parallelism value
Colin Cross2e2dbc22019-09-25 13:31:46 -0700121 params.Pool = localPool
122 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700123 return params, nil
Colin Cross0875c522017-11-28 17:34:01 -0800124 }, argNames...)
125}
126
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700127// SourcePathVariable returns a Variable whose value is the source directory
128// appended with the supplied path. It may only be called during a Go package's
129// initialization - either from the init() function or as part of a
130// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800131func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700132 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700133 p, err := safePathForSource(ctx, path)
134 if err != nil {
135 ctx.Errorf("%s", err.Error())
136 }
137 return p.String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700138 })
139}
140
Colin Crossc6bbef32017-08-14 14:16:06 -0700141// SourcePathsVariable returns a Variable whose value is the source directory
142// appended with the supplied paths, joined with separator. It may only be
143// called during a Go package's initialization - either from the init()
144// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800145func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700146 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossc6bbef32017-08-14 14:16:06 -0700147 var ret []string
148 for _, path := range paths {
Colin Crossfe4bc362018-09-12 10:02:13 -0700149 p, err := safePathForSource(ctx, path)
150 if err != nil {
151 ctx.Errorf("%s", err.Error())
152 }
Colin Crossc6bbef32017-08-14 14:16:06 -0700153 ret = append(ret, p.String())
154 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700155 return strings.Join(ret, separator)
Colin Crossc6bbef32017-08-14 14:16:06 -0700156 })
157}
158
Colin Cross64162712017-08-08 13:17:59 -0700159// SourcePathVariableWithEnvOverride returns a Variable whose value is the source directory
160// appended with the supplied path, or the value of the given environment variable if it is set.
161// The environment variable is not required to point to a path inside the source tree.
162// It may only be called during a Go package's initialization - either from the init() function or
163// as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800164func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700165 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Crossfe4bc362018-09-12 10:02:13 -0700166 p, err := safePathForSource(ctx, path)
167 if err != nil {
168 ctx.Errorf("%s", err.Error())
169 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700170 return ctx.Config().GetenvWithDefault(env, p.String())
Colin Cross64162712017-08-08 13:17:59 -0700171 })
172}
173
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800174// HostBinToolVariable returns a Variable whose value is the path to a host tool
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700175// in the bin directory for host targets. It may only be called during a Go
176// package's initialization - either from the init() function or as part of a
177// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800178func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700179 return p.VariableFunc(name, func(ctx PackageVarContext) string {
180 return p.HostBinToolPath(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700181 })
182}
183
Dan Willemsen54daaf02018-03-12 13:24:09 -0700184func (p PackageContext) HostBinToolPath(ctx PackageVarContext, path string) Path {
185 return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin", path)
Alan Leung1d476fc2017-10-17 18:50:50 -0700186}
187
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800188// HostJNIToolVariable returns a Variable whose value is the path to a host tool
189// in the lib directory for host targets. It may only be called during a Go
190// package's initialization - either from the init() function or as part of a
191// package-scoped variable's initialization.
192func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700193 return p.VariableFunc(name, func(ctx PackageVarContext) string {
194 return p.HostJNIToolPath(ctx, path).String()
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800195 })
196}
197
Dan Willemsen54daaf02018-03-12 13:24:09 -0700198func (p PackageContext) HostJNIToolPath(ctx PackageVarContext, path string) Path {
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800199 ext := ".so"
200 if runtime.GOOS == "darwin" {
201 ext = ".dylib"
202 }
Dan Willemsen54daaf02018-03-12 13:24:09 -0700203 return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "lib64", path+ext)
Colin Cross5ab4e6d2017-11-22 16:20:45 -0800204}
205
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700206// HostJavaToolVariable returns a Variable whose value is the path to a host
207// tool in the frameworks directory for host targets. It may only be called
208// during a Go package's initialization - either from the init() function or as
209// part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800210func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700211 return p.VariableFunc(name, func(ctx PackageVarContext) string {
212 return p.HostJavaToolPath(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700213 })
214}
215
Dan Willemsen54daaf02018-03-12 13:24:09 -0700216func (p PackageContext) HostJavaToolPath(ctx PackageVarContext, path string) Path {
217 return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", path)
Nan Zhang9a364182017-10-25 11:11:37 -0700218}
219
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700220// IntermediatesPathVariable returns a Variable whose value is the intermediate
221// directory appended with the supplied path. It may only be called during a Go
222// package's initialization - either from the init() function or as part of a
223// package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800224func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700225 return p.VariableFunc(name, func(ctx PackageVarContext) string {
226 return PathForIntermediates(ctx, path).String()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700227 })
228}
229
Jeff Gaston734e3802017-04-10 15:47:24 -0700230// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800231// list of present source paths prefixed with the supplied prefix. It may only
232// be called during a Go package's initialization - either from the init()
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700233// function or as part of a package-scoped variable's initialization.
Colin Cross0875c522017-11-28 17:34:01 -0800234func (p PackageContext) PrefixedExistentPathsForSourcesVariable(
Dan Willemsen7b310ee2015-12-18 15:11:17 -0800235 name, prefix string, paths []string) blueprint.Variable {
236
Dan Willemsen54daaf02018-03-12 13:24:09 -0700237 return p.VariableFunc(name, func(ctx PackageVarContext) string {
Colin Cross32f38982018-02-22 11:47:25 -0800238 paths := ExistentPathsForSources(ctx, paths)
Dan Willemsen54daaf02018-03-12 13:24:09 -0700239 return JoinWithPrefix(paths.Strings(), prefix)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700240 })
241}
Colin Cross9d45bb72016-08-29 16:14:13 -0700242
Colin Cross2e2dbc22019-09-25 13:31:46 -0700243// AndroidStaticRule is an alias for StaticRule.
Colin Cross0875c522017-11-28 17:34:01 -0800244func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700245 argNames ...string) blueprint.Rule {
Colin Cross2e2dbc22019-09-25 13:31:46 -0700246 return p.StaticRule(name, params, argNames...)
247}
248
249// StaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified.
250func (p PackageContext) StaticRule(name string, params blueprint.RuleParams,
251 argNames ...string) blueprint.Rule {
252 return p.RuleFunc(name, func(PackageRuleContext) blueprint.RuleParams {
Dan Willemsen54daaf02018-03-12 13:24:09 -0700253 return params
Colin Cross9d45bb72016-08-29 16:14:13 -0700254 }, argNames...)
255}
256
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500257// RemoteRuleSupports selects if a AndroidRemoteStaticRule supports goma, RBE, or both.
258type RemoteRuleSupports int
259
260const (
261 SUPPORTS_NONE = 0
262 SUPPORTS_GOMA = 1 << iota
263 SUPPORTS_RBE = 1 << iota
264 SUPPORTS_BOTH = SUPPORTS_GOMA | SUPPORTS_RBE
265)
266
267// AndroidRemoteStaticRule wraps blueprint.StaticRule but uses goma or RBE's parallelism if goma or RBE are enabled
268// and the appropriate SUPPORTS_* flag is set.
269func (p PackageContext) AndroidRemoteStaticRule(name string, supports RemoteRuleSupports, params blueprint.RuleParams,
Colin Cross9d45bb72016-08-29 16:14:13 -0700270 argNames ...string) blueprint.Rule {
Ramy Medhatdd0418a2019-11-04 18:16:11 -0500271
272 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) {
273 ctx := &configErrorWrapper{p, config.(Config), nil}
274 if ctx.Config().UseGoma() && supports&SUPPORTS_GOMA == 0 {
275 // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the
276 // local parallelism value
277 params.Pool = localPool
278 }
279
280 if ctx.Config().UseRBE() && supports&SUPPORTS_RBE == 0 {
281 // When USE_RBE=true is set and the rule is not supported by RBE, restrict jobs to the
282 // local parallelism value
283 params.Pool = localPool
284 }
285
286 return params, nil
287 }, argNames...)
Colin Cross9d45bb72016-08-29 16:14:13 -0700288}