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