blob: b0a7d7ad16bf79182bd6f16b4eb29705b755adaf [file] [log] [blame]
Dan Willemsen1e704462016-08-21 15:17:17 -07001// Copyright 2017 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 build
16
17import (
18 "path/filepath"
19 "runtime"
20 "strconv"
21 "strings"
22)
23
24type Config struct{ *configImpl }
25
26type configImpl struct {
27 // From the environment
28 arguments []string
29 goma bool
30 environ *Environment
31
32 // From the arguments
33 parallel int
34 keepGoing int
35 verbose bool
36
37 // From the product config
38 katiArgs []string
39 ninjaArgs []string
40 katiSuffix string
41}
42
43func NewConfig(ctx Context, args ...string) Config {
44 ret := &configImpl{
45 environ: OsEnvironment(),
46 }
47
48 ret.environ.Unset(
49 // We're already using it
50 "USE_SOONG_UI",
51
52 // We should never use GOROOT/GOPATH from the shell environment
53 "GOROOT",
54 "GOPATH",
55
56 // These should only come from Soong, not the environment.
57 "CLANG",
58 "CLANG_CXX",
59 "CCC_CC",
60 "CCC_CXX",
61
62 // Used by the goma compiler wrapper, but should only be set by
63 // gomacc
64 "GOMACC_PATH",
65 )
66
67 // Tell python not to spam the source tree with .pyc files.
68 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
69
70 // Sane default matching ninja
71 ret.parallel = runtime.NumCPU() + 2
72 ret.keepGoing = 1
73
74 for _, arg := range args {
75 arg = strings.TrimSpace(arg)
76 if arg == "--make-mode" {
77 continue
78 } else if arg == "showcommands" {
79 ret.verbose = true
80 continue
81 }
82 if arg[0] == '-' {
83 var err error
84 if arg[1] == 'j' {
85 // TODO: handle space between j and number
86 // Unnecessary if used with makeparallel
87 ret.parallel, err = strconv.Atoi(arg[2:])
88 } else if arg[1] == 'k' {
89 // TODO: handle space between k and number
90 // Unnecessary if used with makeparallel
91 ret.keepGoing, err = strconv.Atoi(arg[2:])
92 } else {
93 ctx.Fatalln("Unknown option:", arg)
94 }
95 if err != nil {
96 ctx.Fatalln("Argument error:", err, arg)
97 }
98 } else {
99 ret.arguments = append(ret.arguments, arg)
100 }
101 }
102
103 return Config{ret}
104}
105
106// Lunch configures the environment for a specific product similarly to the
107// `lunch` bash function.
108func (c *configImpl) Lunch(ctx Context, product, variant string) {
109 if variant != "eng" && variant != "userdebug" && variant != "user" {
110 ctx.Fatalf("Invalid variant %q. Must be one of 'user', 'userdebug' or 'eng'", variant)
111 }
112
113 c.environ.Set("TARGET_PRODUCT", product)
114 c.environ.Set("TARGET_BUILD_VARIANT", variant)
115 c.environ.Set("TARGET_BUILD_TYPE", "release")
116 c.environ.Unset("TARGET_BUILD_APPS")
117}
118
119// Tapas configures the environment to build one or more unbundled apps,
120// similarly to the `tapas` bash function.
121func (c *configImpl) Tapas(ctx Context, apps []string, arch, variant string) {
122 if len(apps) == 0 {
123 apps = []string{"all"}
124 }
125 if variant == "" {
126 variant = "eng"
127 }
128
129 if variant != "eng" && variant != "userdebug" && variant != "user" {
130 ctx.Fatalf("Invalid variant %q. Must be one of 'user', 'userdebug' or 'eng'", variant)
131 }
132
133 var product string
134 switch arch {
135 case "armv5":
136 product = "generic_armv5"
137 case "arm", "":
138 product = "aosp_arm"
139 case "arm64":
140 product = "aosm_arm64"
141 case "mips":
142 product = "aosp_mips"
143 case "mips64":
144 product = "aosp_mips64"
145 case "x86":
146 product = "aosp_x86"
147 case "x86_64":
148 product = "aosp_x86_64"
149 default:
150 ctx.Fatalf("Invalid architecture: %q", arch)
151 }
152
153 c.environ.Set("TARGET_PRODUCT", product)
154 c.environ.Set("TARGET_BUILD_VARIANT", variant)
155 c.environ.Set("TARGET_BUILD_TYPE", "release")
156 c.environ.Set("TARGET_BUILD_APPS", strings.Join(apps, " "))
157}
158
159func (c *configImpl) Environment() *Environment {
160 return c.environ
161}
162
163func (c *configImpl) Arguments() []string {
164 return c.arguments
165}
166
167func (c *configImpl) OutDir() string {
168 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
169 return outDir
170 }
171 return "out"
172}
173
174func (c *configImpl) NinjaArgs() []string {
175 return c.ninjaArgs
176}
177
178func (c *configImpl) SoongOutDir() string {
179 return filepath.Join(c.OutDir(), "soong")
180}
181
182func (c *configImpl) KatiSuffix() string {
183 if c.katiSuffix != "" {
184 return c.katiSuffix
185 }
186 panic("SetKatiSuffix has not been called")
187}
188
189func (c *configImpl) IsVerbose() bool {
190 return c.verbose
191}
192
193func (c *configImpl) TargetProduct() string {
194 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
195 return v
196 }
197 panic("TARGET_PRODUCT is not defined")
198}
199
200func (c *configImpl) KatiArgs() []string {
201 return c.katiArgs
202}
203
204func (c *configImpl) Parallel() int {
205 return c.parallel
206}
207
208func (c *configImpl) UseGoma() bool {
209 if v, ok := c.environ.Get("USE_GOMA"); ok {
210 v = strings.TrimSpace(v)
211 if v != "" && v != "false" {
212 return true
213 }
214 }
215 return false
216}
217
218// RemoteParallel controls how many remote jobs (i.e., commands which contain
219// gomacc) are run in parallel. Note the paralleism of all other jobs is
220// still limited by Parallel()
221func (c *configImpl) RemoteParallel() int {
222 if v, ok := c.environ.Get("NINJA_REMOTE_NUM_JOBS"); ok {
223 if i, err := strconv.Atoi(v); err == nil {
224 return i
225 }
226 }
227 return 500
228}
229
230func (c *configImpl) SetKatiArgs(args []string) {
231 c.katiArgs = args
232}
233
234func (c *configImpl) SetNinjaArgs(args []string) {
235 c.ninjaArgs = args
236}
237
238func (c *configImpl) SetKatiSuffix(suffix string) {
239 c.katiSuffix = suffix
240}
241
242func (c *configImpl) KatiEnvFile() string {
243 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
244}
245
246func (c *configImpl) KatiNinjaFile() string {
247 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+".ninja")
248}
249
250func (c *configImpl) SoongNinjaFile() string {
251 return filepath.Join(c.SoongOutDir(), "build.ninja")
252}
253
254func (c *configImpl) CombinedNinjaFile() string {
255 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
256}
257
258func (c *configImpl) SoongAndroidMk() string {
259 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
260}
261
262func (c *configImpl) SoongMakeVarsMk() string {
263 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
264}
265
266func (c *configImpl) HostPrebuiltTag() string {
267 if runtime.GOOS == "linux" {
268 return "linux-x86"
269 } else if runtime.GOOS == "darwin" {
270 return "darwin-x86"
271 } else {
272 panic("Unsupported OS")
273 }
274}