blob: 0b93b189c935bb6d04867e53022e95ab1a73a242 [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 (
Ramy Medhat0fc67eb2020-08-12 01:26:23 -040018 "fmt"
Dan Willemsenc2af0be2017-01-20 14:10:01 -080019 "os"
Dan Willemsen1e704462016-08-21 15:17:17 -070020 "path/filepath"
21 "runtime"
22 "strconv"
23 "strings"
Nan Zhang2e6a4ff2018-02-14 13:27:26 -080024 "time"
Jeff Gastonefc1b412017-03-29 17:29:06 -070025
26 "android/soong/shared"
Kousik Kumarec478642020-09-21 13:39:24 -040027
Dan Willemsen4591b642021-05-24 14:24:12 -070028 "google.golang.org/protobuf/proto"
Patrice Arruda96850362020-08-11 20:41:11 +000029
30 smpb "android/soong/ui/metrics/metrics_proto"
Dan Willemsen1e704462016-08-21 15:17:17 -070031)
32
33type Config struct{ *configImpl }
34
35type configImpl struct {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020036 // Some targets that are implemented in soong_build
37 // (bp2build, json-module-graph) are not here and have their own bits below.
Colin Cross28f527c2019-11-26 16:19:04 -080038 arguments []string
39 goma bool
40 environ *Environment
41 distDir string
42 buildDateTime string
Dan Willemsen1e704462016-08-21 15:17:17 -070043
44 // From the arguments
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020045 parallel int
46 keepGoing int
47 verbose bool
48 checkbuild bool
49 dist bool
50 jsonModuleGraph bool
51 bp2build bool
52 skipConfig bool
53 skipKati bool
54 skipKatiNinja bool
55 skipSoong bool
56 skipNinja bool
57 skipSoongTests bool
Dan Willemsen1e704462016-08-21 15:17:17 -070058
59 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -070060 katiArgs []string
61 ninjaArgs []string
62 katiSuffix string
63 targetDevice string
64 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +000065 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -070066
Dan Willemsen2bb82d02019-12-27 09:35:42 -080067 // Autodetected
68 totalRAM uint64
69
Dan Willemsene3336352020-01-02 19:10:38 -080070 brokenDupRules bool
71 brokenUsesNetwork bool
72 brokenNinjaEnvVars []string
Dan Willemsen18490112018-05-25 16:30:04 -070073
74 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +000075
76 useBazel bool
77
78 // During Bazel execution, Bazel cannot write outside OUT_DIR.
79 // So if DIST_DIR is set to an external dir (outside of OUT_DIR), we need to rig it temporarily and then migrate files at the end of the build.
80 riggedDistDirForBazel string
Colin Crossf3bdbcb2021-06-01 11:43:55 -070081
82 // Set by multiproduct_kati
83 emptyNinjaFile bool
Dan Willemsen1e704462016-08-21 15:17:17 -070084}
85
Dan Willemsenc2af0be2017-01-20 14:10:01 -080086const srcDirFileCheck = "build/soong/root.bp"
87
Patrice Arruda9450d0b2019-07-08 11:06:46 -070088var buildFiles = []string{"Android.mk", "Android.bp"}
89
Patrice Arruda13848222019-04-22 17:12:02 -070090type BuildAction uint
91
92const (
93 // Builds all of the modules and their dependencies of a specified directory, relative to the root
94 // directory of the source tree.
95 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
96
97 // Builds all of the modules and their dependencies of a list of specified directories. All specified
98 // directories are relative to the root directory of the source tree.
99 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700100
101 // Build a list of specified modules. If none was specified, simply build the whole source tree.
102 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700103)
104
Chris Parsonsec1a3dc2021-04-20 15:32:07 -0400105type bazelBuildMode int
106
107// Bazel-related build modes.
108const (
109 // Don't use bazel at all.
110 noBazel bazelBuildMode = iota
111
112 // Only generate build files (in a subdirectory of the out directory) and exit.
113 generateBuildFiles
114
115 // Generate synthetic build files and incorporate these files into a build which
116 // partially uses Bazel. Build metadata may come from Android.bp or BUILD files.
117 mixedBuild
118)
119
Patrice Arruda13848222019-04-22 17:12:02 -0700120// checkTopDir validates that the current directory is at the root directory of the source tree.
121func checkTopDir(ctx Context) {
122 if _, err := os.Stat(srcDirFileCheck); err != nil {
123 if os.IsNotExist(err) {
124 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
125 }
126 ctx.Fatalln("Error verifying tree state:", err)
127 }
128}
129
Dan Willemsen1e704462016-08-21 15:17:17 -0700130func NewConfig(ctx Context, args ...string) Config {
131 ret := &configImpl{
Spandan Dasa3639e62021-05-25 19:14:02 +0000132 environ: OsEnvironment(),
133 sandboxConfig: &SandboxConfig{},
Dan Willemsen1e704462016-08-21 15:17:17 -0700134 }
135
Patrice Arruda90109172020-07-28 18:07:27 +0000136 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700137 ret.parallel = runtime.NumCPU() + 2
138 ret.keepGoing = 1
139
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800140 ret.totalRAM = detectTotalRAM(ctx)
141
Dan Willemsen9b587492017-07-10 22:13:00 -0700142 ret.parseArgs(ctx, args)
143
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800144 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700145 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
146 ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
147 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800148 outDir := "out"
149 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
150 if wd, err := os.Getwd(); err != nil {
151 ctx.Fatalln("Failed to get working directory:", err)
152 } else {
153 outDir = filepath.Join(baseDir, filepath.Base(wd))
154 }
155 }
156 ret.environ.Set("OUT_DIR", outDir)
157 }
158
Dan Willemsen2d31a442018-10-20 21:33:41 -0700159 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
160 ret.distDir = filepath.Clean(distDir)
161 } else {
162 ret.distDir = filepath.Join(ret.OutDir(), "dist")
163 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700164
Spandan Das05063612021-06-25 01:39:04 +0000165 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
166 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
167 }
168
Dan Willemsen1e704462016-08-21 15:17:17 -0700169 ret.environ.Unset(
170 // We're already using it
171 "USE_SOONG_UI",
172
173 // We should never use GOROOT/GOPATH from the shell environment
174 "GOROOT",
175 "GOPATH",
176
177 // These should only come from Soong, not the environment.
178 "CLANG",
179 "CLANG_CXX",
180 "CCC_CC",
181 "CCC_CXX",
182
183 // Used by the goma compiler wrapper, but should only be set by
184 // gomacc
185 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800186
187 // We handle this above
188 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700189
Dan Willemsen2d31a442018-10-20 21:33:41 -0700190 // This is handled above too, and set for individual commands later
191 "DIST_DIR",
192
Dan Willemsen68a09852017-04-18 13:56:57 -0700193 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000194 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700195 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700196 "DISPLAY",
197 "GREP_OPTIONS",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700198 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700199 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700200
201 // Drop make flags
202 "MAKEFLAGS",
203 "MAKELEVEL",
204 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700205
206 // Set in envsetup.sh, reset in makefiles
207 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700208
209 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
210 "ANDROID_BUILD_TOP",
211 "ANDROID_HOST_OUT",
212 "ANDROID_PRODUCT_OUT",
213 "ANDROID_HOST_OUT_TESTCASES",
214 "ANDROID_TARGET_OUT_TESTCASES",
215 "ANDROID_TOOLCHAIN",
216 "ANDROID_TOOLCHAIN_2ND_ARCH",
217 "ANDROID_DEV_SCRIPTS",
218 "ANDROID_EMULATOR_PREBUILTS",
219 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700220 )
221
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400222 if ret.UseGoma() || ret.ForceUseGoma() {
223 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
224 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400225 }
226
Dan Willemsen1e704462016-08-21 15:17:17 -0700227 // Tell python not to spam the source tree with .pyc files.
228 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
229
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400230 tmpDir := absPath(ctx, ret.TempDir())
231 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800232
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700233 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
234 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
235 "llvm-binutils-stable/llvm-symbolizer")
236 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
237
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800238 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700239 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800240
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700241 if srcDir := absPath(ctx, "."); strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700242 ctx.Println("You are building in a directory whose absolute path contains a space character:")
243 ctx.Println()
244 ctx.Printf("%q\n", srcDir)
245 ctx.Println()
246 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700247 }
248
249 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700250 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
251 ctx.Println()
252 ctx.Printf("%q\n", outDir)
253 ctx.Println()
254 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700255 }
256
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000257 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700258 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
259 ctx.Println()
260 ctx.Printf("%q\n", distDir)
261 ctx.Println()
262 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700263 }
264
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700265 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000266 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
267 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100268 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700269 javaHome := func() string {
270 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
271 return override
272 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000273 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
274 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
Pete Gillin1f52e932019-10-09 17:10:08 +0100275 }
Pete Gillinabbcdda2019-10-28 16:15:33 +0000276 return java11Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700277 }()
278 absJavaHome := absPath(ctx, javaHome)
279
Dan Willemsened869522018-01-08 14:58:46 -0800280 ret.configureLocale(ctx)
281
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700282 newPath := []string{filepath.Join(absJavaHome, "bin")}
283 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
284 newPath = append(newPath, path)
285 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100286
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700287 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
288 ret.environ.Set("JAVA_HOME", absJavaHome)
289 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000290 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
291 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100292 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700293 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
294
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800295 outDir := ret.OutDir()
296 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800297 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800298 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800299 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800300 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800301 }
Colin Cross28f527c2019-11-26 16:19:04 -0800302
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800303 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
304
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400305 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400306 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400307 ret.environ.Set(k, v)
308 }
309 }
310
Patrice Arruda83842d72020-12-08 19:42:08 +0000311 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800312 if err := os.RemoveAll(bpd); err != nil {
313 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
314 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000315
316 ret.useBazel = ret.environ.IsEnvTrue("USE_BAZEL")
317
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800318 if ret.UseBazel() {
319 if err := os.MkdirAll(bpd, 0777); err != nil {
320 ctx.Fatalf("Failed to create bazel profile directory %q: %v", bpd, err)
321 }
322 }
323
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000324 if ret.UseBazel() {
325 ret.riggedDistDirForBazel = filepath.Join(ret.OutDir(), "dist")
326 } else {
327 // Not rigged
328 ret.riggedDistDirForBazel = ret.distDir
329 }
330
Patrice Arruda96850362020-08-11 20:41:11 +0000331 c := Config{ret}
332 storeConfigMetrics(ctx, c)
333 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700334}
335
Patrice Arruda13848222019-04-22 17:12:02 -0700336// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
337// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700338func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
339 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700340}
341
Patrice Arruda96850362020-08-11 20:41:11 +0000342// storeConfigMetrics selects a set of configuration information and store in
343// the metrics system for further analysis.
344func storeConfigMetrics(ctx Context, config Config) {
345 if ctx.Metrics == nil {
346 return
347 }
348
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400349 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000350
351 s := &smpb.SystemResourceInfo{
352 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
353 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
354 }
355 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000356}
357
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400358func buildConfig(config Config) *smpb.BuildConfig {
359 return &smpb.BuildConfig{
360 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
361 UseGoma: proto.Bool(config.UseGoma()),
362 UseRbe: proto.Bool(config.UseRBE()),
363 BazelAsNinja: proto.Bool(config.UseBazel()),
364 BazelMixedBuild: proto.Bool(config.bazelBuildMode() == mixedBuild),
365 }
366}
367
Patrice Arruda13848222019-04-22 17:12:02 -0700368// getConfigArgs processes the command arguments based on the build action and creates a set of new
369// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700370func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700371 // The next block of code verifies that the current directory is the root directory of the source
372 // tree. It then finds the relative path of dir based on the root directory of the source tree
373 // and verify that dir is inside of the source tree.
374 checkTopDir(ctx)
375 topDir, err := os.Getwd()
376 if err != nil {
377 ctx.Fatalf("Error retrieving top directory: %v", err)
378 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700379 dir, err = filepath.EvalSymlinks(dir)
380 if err != nil {
381 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
382 }
Patrice Arruda13848222019-04-22 17:12:02 -0700383 dir, err = filepath.Abs(dir)
384 if err != nil {
385 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
386 }
387 relDir, err := filepath.Rel(topDir, dir)
388 if err != nil {
389 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
390 }
391 // If there are ".." in the path, it's not in the source tree.
392 if strings.Contains(relDir, "..") {
393 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
394 }
395
396 configArgs := args[:]
397
398 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
399 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
400 targetNamePrefix := "MODULES-IN-"
401 if inList("GET-INSTALL-PATH", configArgs) {
402 targetNamePrefix = "GET-INSTALL-PATH-IN-"
403 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
404 }
405
Patrice Arruda13848222019-04-22 17:12:02 -0700406 var targets []string
407
408 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700409 case BUILD_MODULES:
410 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700411 case BUILD_MODULES_IN_A_DIRECTORY:
412 // If dir is the root source tree, all the modules are built of the source tree are built so
413 // no need to find the build file.
414 if topDir == dir {
415 break
416 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700417
Patrice Arruda13848222019-04-22 17:12:02 -0700418 buildFile := findBuildFile(ctx, relDir)
419 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700420 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700421 }
Patrice Arruda13848222019-04-22 17:12:02 -0700422 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
423 case BUILD_MODULES_IN_DIRECTORIES:
424 newConfigArgs, dirs := splitArgs(configArgs)
425 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700426 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700427 }
428
429 // Tidy only override all other specified targets.
430 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
431 if tidyOnly == "true" || tidyOnly == "1" {
432 configArgs = append(configArgs, "tidy_only")
433 } else {
434 configArgs = append(configArgs, targets...)
435 }
436
437 return configArgs
438}
439
440// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
441func convertToTarget(dir string, targetNamePrefix string) string {
442 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
443}
444
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700445// hasBuildFile returns true if dir contains an Android build file.
446func hasBuildFile(ctx Context, dir string) bool {
447 for _, buildFile := range buildFiles {
448 _, err := os.Stat(filepath.Join(dir, buildFile))
449 if err == nil {
450 return true
451 }
452 if !os.IsNotExist(err) {
453 ctx.Fatalf("Error retrieving the build file stats: %v", err)
454 }
455 }
456 return false
457}
458
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700459// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
460// in the current and any sub directory of dir. If a build file is not found, traverse the path
461// up by one directory and repeat again until either a build file is found or reached to the root
462// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
463// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700464func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700465 // If the string is empty or ".", assume it is top directory of the source tree.
466 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700467 return ""
468 }
469
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700470 found := false
471 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
472 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
473 if err != nil {
474 return err
475 }
476 if found {
477 return filepath.SkipDir
478 }
479 if info.IsDir() {
480 return nil
481 }
482 for _, buildFile := range buildFiles {
483 if info.Name() == buildFile {
484 found = true
485 return filepath.SkipDir
486 }
487 }
488 return nil
489 })
490 if err != nil {
491 ctx.Fatalf("Error finding Android build file: %v", err)
492 }
493
494 if found {
495 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700496 }
497 }
498
499 return ""
500}
501
502// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
503func splitArgs(args []string) (newArgs []string, dirs []string) {
504 specialArgs := map[string]bool{
505 "showcommands": true,
506 "snod": true,
507 "dist": true,
508 "checkbuild": true,
509 }
510
511 newArgs = []string{}
512 dirs = []string{}
513
514 for _, arg := range args {
515 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
516 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
517 newArgs = append(newArgs, arg)
518 continue
519 }
520
521 if _, ok := specialArgs[arg]; ok {
522 newArgs = append(newArgs, arg)
523 continue
524 }
525
526 dirs = append(dirs, arg)
527 }
528
529 return newArgs, dirs
530}
531
532// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
533// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
534// source root tree where the build action command was invoked. Each directory is validated if the
535// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700536func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700537 for _, dir := range dirs {
538 // The directory may have specified specific modules to build. ":" is the separator to separate
539 // the directory and the list of modules.
540 s := strings.Split(dir, ":")
541 l := len(s)
542 if l > 2 { // more than one ":" was specified.
543 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
544 }
545
546 dir = filepath.Join(relDir, s[0])
547 if _, err := os.Stat(dir); err != nil {
548 ctx.Fatalf("couldn't find directory %s", dir)
549 }
550
551 // Verify that if there are any targets specified after ":". Each target is separated by ",".
552 var newTargets []string
553 if l == 2 && s[1] != "" {
554 newTargets = strings.Split(s[1], ",")
555 if inList("", newTargets) {
556 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
557 }
558 }
559
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700560 // If there are specified targets to build in dir, an android build file must exist for the one
561 // shot build. For the non-targets case, find the appropriate build file and build all the
562 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700563 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700564 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700565 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
566 }
567 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700568 buildFile := findBuildFile(ctx, dir)
569 if buildFile == "" {
570 ctx.Fatalf("Build file not found for %s directory", dir)
571 }
572 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700573 }
574
Patrice Arruda13848222019-04-22 17:12:02 -0700575 targets = append(targets, newTargets...)
576 }
577
Dan Willemsence41e942019-07-29 23:39:30 -0700578 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700579}
580
Dan Willemsen9b587492017-07-10 22:13:00 -0700581func (c *configImpl) parseArgs(ctx Context, args []string) {
582 for i := 0; i < len(args); i++ {
583 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100584 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700585 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200586 } else if arg == "--empty-ninja-file" {
587 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100588 } else if arg == "--skip-ninja" {
589 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700590 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700591 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
592 // but it does run a Kati ninja file if the .kati_enabled marker file was created
593 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000594 c.skipConfig = true
595 c.skipKati = true
596 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100597 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000598 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100599 } else if arg == "--soong-only" {
600 c.skipKati = true
601 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200602 } else if arg == "--config-only" {
603 c.skipKati = true
604 c.skipKatiNinja = true
605 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700606 } else if arg == "--skip-config" {
607 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700608 } else if arg == "--skip-soong-tests" {
609 c.skipSoongTests = true
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700610 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700611 parseArgNum := func(def int) int {
612 if len(arg) > 2 {
613 p, err := strconv.ParseUint(arg[2:], 10, 31)
614 if err != nil {
615 ctx.Fatalf("Failed to parse %q: %v", arg, err)
616 }
617 return int(p)
618 } else if i+1 < len(args) {
619 p, err := strconv.ParseUint(args[i+1], 10, 31)
620 if err == nil {
621 i++
622 return int(p)
623 }
624 }
625 return def
626 }
627
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700628 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700629 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700630 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700631 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700632 } else {
633 ctx.Fatalln("Unknown option:", arg)
634 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700635 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700636 if k == "OUT_DIR" {
637 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
638 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700639 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700640 } else if arg == "dist" {
641 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200642 } else if arg == "json-module-graph" {
643 c.jsonModuleGraph = true
644 } else if arg == "bp2build" {
645 c.bp2build = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700646 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700647 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800648 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700649 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700650 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700651 }
652 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700653}
654
Dan Willemsened869522018-01-08 14:58:46 -0800655func (c *configImpl) configureLocale(ctx Context) {
656 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
657 output, err := cmd.Output()
658
659 var locales []string
660 if err == nil {
661 locales = strings.Split(string(output), "\n")
662 } else {
663 // If we're unable to list the locales, let's assume en_US.UTF-8
664 locales = []string{"en_US.UTF-8"}
665 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
666 }
667
668 // gettext uses LANGUAGE, which is passed directly through
669
670 // For LANG and LC_*, only preserve the evaluated version of
671 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800672 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800673 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800674 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800675 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800676 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800677 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800678 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800679 }
680
681 c.environ.UnsetWithPrefix("LC_")
682
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800683 if userLang != "" {
684 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800685 }
686
687 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
688 // for others)
689 if inList("C.UTF-8", locales) {
690 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500691 } else if inList("C.utf8", locales) {
692 // These normalize to the same thing
693 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800694 } else if inList("en_US.UTF-8", locales) {
695 c.environ.Set("LANG", "en_US.UTF-8")
696 } else if inList("en_US.utf8", locales) {
697 // These normalize to the same thing
698 c.environ.Set("LANG", "en_US.UTF-8")
699 } else {
700 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
701 }
702}
703
Dan Willemsen1e704462016-08-21 15:17:17 -0700704func (c *configImpl) Environment() *Environment {
705 return c.environ
706}
707
708func (c *configImpl) Arguments() []string {
709 return c.arguments
710}
711
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200712func (c *configImpl) SoongBuildInvocationNeeded() bool {
713 if c.Dist() {
714 return true
715 }
716
717 if len(c.Arguments()) > 0 {
718 // Explicit targets requested that are not special targets like b2pbuild
719 // or the JSON module graph
720 return true
721 }
722
723 if !c.JsonModuleGraph() && !c.Bp2Build() {
724 // Command line was empty, the default Ninja target is built
725 return true
726 }
727
728 // build.ninja doesn't need to be generated
729 return false
730}
731
Dan Willemsen1e704462016-08-21 15:17:17 -0700732func (c *configImpl) OutDir() string {
733 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700734 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700735 }
736 return "out"
737}
738
Dan Willemsen8a073a82017-02-04 17:30:44 -0800739func (c *configImpl) DistDir() string {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000740 if c.UseBazel() {
741 return c.riggedDistDirForBazel
742 } else {
743 return c.distDir
744 }
745}
746
747func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700748 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800749}
750
Dan Willemsen1e704462016-08-21 15:17:17 -0700751func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000752 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700753 return c.arguments
754 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700755 return c.ninjaArgs
756}
757
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500758func (c *configImpl) BazelOutDir() string {
759 return filepath.Join(c.OutDir(), "bazel")
760}
761
Dan Willemsen1e704462016-08-21 15:17:17 -0700762func (c *configImpl) SoongOutDir() string {
763 return filepath.Join(c.OutDir(), "soong")
764}
765
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200766func (c *configImpl) PrebuiltOS() string {
767 switch runtime.GOOS {
768 case "linux":
769 return "linux-x86"
770 case "darwin":
771 return "darwin-x86"
772 default:
773 panic("Unknown GOOS")
774 }
775}
776func (c *configImpl) HostToolDir() string {
777 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
778}
779
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200780func (c *configImpl) MainNinjaFile() string {
781 return shared.JoinPath(c.SoongOutDir(), "build.ninja")
782}
783
784func (c *configImpl) Bp2BuildMarkerFile() string {
785 return shared.JoinPath(c.SoongOutDir(), ".bootstrap/bp2build_workspace_marker")
786}
787
Lukacs T. Berkie571dc32021-08-25 14:14:13 +0200788func (c *configImpl) ModuleGraphFile() string {
789 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
790}
791
Jeff Gastonefc1b412017-03-29 17:29:06 -0700792func (c *configImpl) TempDir() string {
793 return shared.TempDirForOutDir(c.SoongOutDir())
794}
795
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700796func (c *configImpl) FileListDir() string {
797 return filepath.Join(c.OutDir(), ".module_paths")
798}
799
Dan Willemsen1e704462016-08-21 15:17:17 -0700800func (c *configImpl) KatiSuffix() string {
801 if c.katiSuffix != "" {
802 return c.katiSuffix
803 }
804 panic("SetKatiSuffix has not been called")
805}
806
Colin Cross37193492017-11-16 17:55:00 -0800807// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
808// user is interested in additional checks at the expense of build time.
809func (c *configImpl) Checkbuild() bool {
810 return c.checkbuild
811}
812
Dan Willemsen8a073a82017-02-04 17:30:44 -0800813func (c *configImpl) Dist() bool {
814 return c.dist
815}
816
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200817func (c *configImpl) JsonModuleGraph() bool {
818 return c.jsonModuleGraph
819}
820
821func (c *configImpl) Bp2Build() bool {
822 return c.bp2build
823}
824
Dan Willemsen1e704462016-08-21 15:17:17 -0700825func (c *configImpl) IsVerbose() bool {
826 return c.verbose
827}
828
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000829func (c *configImpl) SkipKati() bool {
830 return c.skipKati
831}
832
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100833func (c *configImpl) SkipKatiNinja() bool {
834 return c.skipKatiNinja
835}
836
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200837func (c *configImpl) SkipSoong() bool {
838 return c.skipSoong
839}
840
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100841func (c *configImpl) SkipNinja() bool {
842 return c.skipNinja
843}
844
Anton Hansson5a7861a2021-06-04 10:09:01 +0100845func (c *configImpl) SetSkipNinja(v bool) {
846 c.skipNinja = v
847}
848
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000849func (c *configImpl) SkipConfig() bool {
850 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -0700851}
852
Dan Willemsen1e704462016-08-21 15:17:17 -0700853func (c *configImpl) TargetProduct() string {
854 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
855 return v
856 }
857 panic("TARGET_PRODUCT is not defined")
858}
859
Dan Willemsen02781d52017-05-12 19:28:13 -0700860func (c *configImpl) TargetDevice() string {
861 return c.targetDevice
862}
863
864func (c *configImpl) SetTargetDevice(device string) {
865 c.targetDevice = device
866}
867
868func (c *configImpl) TargetBuildVariant() string {
869 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
870 return v
871 }
872 panic("TARGET_BUILD_VARIANT is not defined")
873}
874
Dan Willemsen1e704462016-08-21 15:17:17 -0700875func (c *configImpl) KatiArgs() []string {
876 return c.katiArgs
877}
878
879func (c *configImpl) Parallel() int {
880 return c.parallel
881}
882
Colin Cross8b8bec32019-11-15 13:18:43 -0800883func (c *configImpl) HighmemParallel() int {
884 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
885 return i
886 }
887
888 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
889 parallel := c.Parallel()
890 if c.UseRemoteBuild() {
891 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
892 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
893 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
894 // Return 1/16th of the size of the local pool, rounding up.
895 return (parallel + 15) / 16
896 } else if c.totalRAM == 0 {
897 // Couldn't detect the total RAM, don't restrict highmem processes.
898 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -0700899 } else if c.totalRAM <= 16*1024*1024*1024 {
900 // Less than 16GB of ram, restrict to 1 highmem processes
901 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -0800902 } else if c.totalRAM <= 32*1024*1024*1024 {
903 // Less than 32GB of ram, restrict to 2 highmem processes
904 return 2
905 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
906 // If less than 8GB total RAM per process, reduce the number of highmem processes
907 return p
908 }
909 // No restriction on highmem processes
910 return parallel
911}
912
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800913func (c *configImpl) TotalRAM() uint64 {
914 return c.totalRAM
915}
916
Kousik Kumarec478642020-09-21 13:39:24 -0400917// ForceUseGoma determines whether we should override Goma deprecation
918// and use Goma for the current build or not.
919func (c *configImpl) ForceUseGoma() bool {
920 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
921 v = strings.TrimSpace(v)
922 if v != "" && v != "false" {
923 return true
924 }
925 }
926 return false
927}
928
Dan Willemsen1e704462016-08-21 15:17:17 -0700929func (c *configImpl) UseGoma() bool {
930 if v, ok := c.environ.Get("USE_GOMA"); ok {
931 v = strings.TrimSpace(v)
932 if v != "" && v != "false" {
933 return true
934 }
935 }
936 return false
937}
938
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +0900939func (c *configImpl) StartGoma() bool {
940 if !c.UseGoma() {
941 return false
942 }
943
944 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
945 v = strings.TrimSpace(v)
946 if v != "" && v != "false" {
947 return false
948 }
949 }
950 return true
951}
952
Ramy Medhatbbf25672019-07-17 12:30:04 +0000953func (c *configImpl) UseRBE() bool {
954 if v, ok := c.environ.Get("USE_RBE"); ok {
955 v = strings.TrimSpace(v)
956 if v != "" && v != "false" {
957 return true
958 }
959 }
960 return false
961}
962
Patrice Arruda0c1c4562020-11-11 13:01:25 -0800963func (c *configImpl) UseBazel() bool {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000964 return c.useBazel
Patrice Arruda0c1c4562020-11-11 13:01:25 -0800965}
966
Chris Parsonsec1a3dc2021-04-20 15:32:07 -0400967func (c *configImpl) bazelBuildMode() bazelBuildMode {
968 if c.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") {
969 return mixedBuild
Chris Parsonsec1a3dc2021-04-20 15:32:07 -0400970 } else {
971 return noBazel
972 }
973}
974
Ramy Medhatbbf25672019-07-17 12:30:04 +0000975func (c *configImpl) StartRBE() bool {
976 if !c.UseRBE() {
977 return false
978 }
979
980 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
981 v = strings.TrimSpace(v)
982 if v != "" && v != "false" {
983 return false
984 }
985 }
986 return true
987}
988
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000989func (c *configImpl) rbeLogDir() string {
Kousik Kumar0d15a722020-09-23 02:54:11 -0400990 for _, f := range []string{"RBE_log_dir", "FLAG_log_dir"} {
991 if v, ok := c.environ.Get(f); ok {
992 return v
993 }
994 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400995 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000996 return c.LogsDir()
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400997 }
998 return c.OutDir()
999}
1000
1001func (c *configImpl) rbeStatsOutputDir() string {
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001002 for _, f := range []string{"RBE_output_dir", "FLAG_output_dir"} {
1003 if v, ok := c.environ.Get(f); ok {
1004 return v
1005 }
1006 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001007 return c.rbeLogDir()
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001008}
1009
1010func (c *configImpl) rbeLogPath() string {
1011 for _, f := range []string{"RBE_log_path", "FLAG_log_path"} {
1012 if v, ok := c.environ.Get(f); ok {
1013 return v
1014 }
1015 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001016 return fmt.Sprintf("text://%v/reproxy_log.txt", c.rbeLogDir())
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001017}
1018
1019func (c *configImpl) rbeExecRoot() string {
1020 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1021 if v, ok := c.environ.Get(f); ok {
1022 return v
1023 }
1024 }
1025 wd, err := os.Getwd()
1026 if err != nil {
1027 return ""
1028 }
1029 return wd
1030}
1031
1032func (c *configImpl) rbeDir() string {
1033 if v, ok := c.environ.Get("RBE_DIR"); ok {
1034 return v
1035 }
1036 return "prebuilts/remoteexecution-client/live/"
1037}
1038
1039func (c *configImpl) rbeReproxy() string {
1040 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1041 if v, ok := c.environ.Get(f); ok {
1042 return v
1043 }
1044 }
1045 return filepath.Join(c.rbeDir(), "reproxy")
1046}
1047
1048func (c *configImpl) rbeAuth() (string, string) {
1049 credFlags := []string{"use_application_default_credentials", "use_gce_credentials", "credential_file"}
1050 for _, cf := range credFlags {
1051 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1052 if v, ok := c.environ.Get(f); ok {
1053 v = strings.TrimSpace(v)
1054 if v != "" && v != "false" && v != "0" {
1055 return "RBE_" + cf, v
1056 }
1057 }
1058 }
1059 }
1060 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001061}
1062
Colin Cross9016b912019-11-11 14:57:42 -08001063func (c *configImpl) UseRemoteBuild() bool {
1064 return c.UseGoma() || c.UseRBE()
1065}
1066
Dan Willemsen1e704462016-08-21 15:17:17 -07001067// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001068// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001069// still limited by Parallel()
1070func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001071 if !c.UseRemoteBuild() {
1072 return 0
1073 }
1074 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1075 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001076 }
1077 return 500
1078}
1079
1080func (c *configImpl) SetKatiArgs(args []string) {
1081 c.katiArgs = args
1082}
1083
1084func (c *configImpl) SetNinjaArgs(args []string) {
1085 c.ninjaArgs = args
1086}
1087
1088func (c *configImpl) SetKatiSuffix(suffix string) {
1089 c.katiSuffix = suffix
1090}
1091
Dan Willemsene0879fc2017-08-04 15:06:27 -07001092func (c *configImpl) LastKatiSuffixFile() string {
1093 return filepath.Join(c.OutDir(), "last_kati_suffix")
1094}
1095
1096func (c *configImpl) HasKatiSuffix() bool {
1097 return c.katiSuffix != ""
1098}
1099
Dan Willemsen1e704462016-08-21 15:17:17 -07001100func (c *configImpl) KatiEnvFile() string {
1101 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1102}
1103
Dan Willemsen29971232018-09-26 14:58:30 -07001104func (c *configImpl) KatiBuildNinjaFile() string {
1105 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001106}
1107
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001108func (c *configImpl) KatiPackageNinjaFile() string {
1109 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1110}
1111
Dan Willemsen1e704462016-08-21 15:17:17 -07001112func (c *configImpl) SoongNinjaFile() string {
1113 return filepath.Join(c.SoongOutDir(), "build.ninja")
1114}
1115
1116func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001117 if c.katiSuffix == "" {
1118 return filepath.Join(c.OutDir(), "combined.ninja")
1119 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001120 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1121}
1122
1123func (c *configImpl) SoongAndroidMk() string {
1124 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1125}
1126
1127func (c *configImpl) SoongMakeVarsMk() string {
1128 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1129}
1130
Dan Willemsenf052f782017-05-18 15:29:04 -07001131func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001132 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001133}
1134
Dan Willemsen02781d52017-05-12 19:28:13 -07001135func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001136 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1137}
1138
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001139func (c *configImpl) KatiPackageMkDir() string {
1140 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1141}
1142
Dan Willemsenf052f782017-05-18 15:29:04 -07001143func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001144 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001145}
1146
1147func (c *configImpl) HostOut() string {
1148 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1149}
1150
1151// This probably needs to be multi-valued, so not exporting it for now
1152func (c *configImpl) hostCrossOut() string {
1153 if runtime.GOOS == "linux" {
1154 return filepath.Join(c.hostOutRoot(), "windows-x86")
1155 } else {
1156 return ""
1157 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001158}
1159
Dan Willemsen1e704462016-08-21 15:17:17 -07001160func (c *configImpl) HostPrebuiltTag() string {
1161 if runtime.GOOS == "linux" {
1162 return "linux-x86"
1163 } else if runtime.GOOS == "darwin" {
1164 return "darwin-x86"
1165 } else {
1166 panic("Unsupported OS")
1167 }
1168}
Dan Willemsenf173d592017-04-27 14:28:00 -07001169
Dan Willemsen8122bd52017-10-12 20:20:41 -07001170func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001171 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1172 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001173 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1174 if _, err := os.Stat(asan); err == nil {
1175 return asan
1176 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001177 }
1178 }
1179 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1180}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001181
1182func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1183 c.brokenDupRules = val
1184}
1185
1186func (c *configImpl) BuildBrokenDupRules() bool {
1187 return c.brokenDupRules
1188}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001189
Dan Willemsen25e6f092019-04-09 10:22:43 -07001190func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1191 c.brokenUsesNetwork = val
1192}
1193
1194func (c *configImpl) BuildBrokenUsesNetwork() bool {
1195 return c.brokenUsesNetwork
1196}
1197
Dan Willemsene3336352020-01-02 19:10:38 -08001198func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1199 c.brokenNinjaEnvVars = val
1200}
1201
1202func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1203 return c.brokenNinjaEnvVars
1204}
1205
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001206func (c *configImpl) SetTargetDeviceDir(dir string) {
1207 c.targetDeviceDir = dir
1208}
1209
1210func (c *configImpl) TargetDeviceDir() string {
1211 return c.targetDeviceDir
1212}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001213
Patrice Arruda219eef32020-06-01 17:29:30 +00001214func (c *configImpl) BuildDateTime() string {
1215 return c.buildDateTime
1216}
1217
1218func (c *configImpl) MetricsUploaderApp() string {
1219 if p, ok := c.environ.Get("ANDROID_ENABLE_METRICS_UPLOAD"); ok {
1220 return p
1221 }
1222 return ""
1223}
Patrice Arruda83842d72020-12-08 19:42:08 +00001224
1225// LogsDir returns the logs directory where build log and metrics
1226// files are located. By default, the logs directory is the out
1227// directory. If the argument dist is specified, the logs directory
1228// is <dist_dir>/logs.
1229func (c *configImpl) LogsDir() string {
1230 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001231 // Always write logs to the real dist dir, even if Bazel is using a rigged dist dir for other files
1232 return filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001233 }
1234 return c.OutDir()
1235}
1236
1237// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1238// where the bazel profiles are located.
1239func (c *configImpl) BazelMetricsDir() string {
1240 return filepath.Join(c.LogsDir(), "bazel_metrics")
1241}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001242
1243func (c *configImpl) SetEmptyNinjaFile(v bool) {
1244 c.emptyNinjaFile = v
1245}
1246
1247func (c *configImpl) EmptyNinjaFile() bool {
1248 return c.emptyNinjaFile
1249}