blob: 61f6b1c9a7b7562d21e9bffa23db64f361a7a1cd [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 (
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050018 "context"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050019 "encoding/json"
Ramy Medhat0fc67eb2020-08-12 01:26:23 -040020 "fmt"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050021 "io/ioutil"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040022 "math/rand"
Dan Willemsenc2af0be2017-01-20 14:10:01 -080023 "os"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050024 "os/exec"
Dan Willemsen1e704462016-08-21 15:17:17 -070025 "path/filepath"
26 "runtime"
27 "strconv"
28 "strings"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040029 "syscall"
Nan Zhang2e6a4ff2018-02-14 13:27:26 -080030 "time"
Jeff Gastonefc1b412017-03-29 17:29:06 -070031
32 "android/soong/shared"
Kousik Kumarec478642020-09-21 13:39:24 -040033
Dan Willemsen4591b642021-05-24 14:24:12 -070034 "google.golang.org/protobuf/proto"
Patrice Arruda96850362020-08-11 20:41:11 +000035
36 smpb "android/soong/ui/metrics/metrics_proto"
Dan Willemsen1e704462016-08-21 15:17:17 -070037)
38
Kousik Kumar3ff037e2022-01-25 22:11:01 -050039const (
Chris Parsons53f68ae2022-03-03 12:01:40 -050040 envConfigDir = "vendor/google/tools/soong_config"
41 jsonSuffix = "json"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050042
Chris Parsons53f68ae2022-03-03 12:01:40 -050043 configFetcher = "vendor/google/tools/soong/expconfigfetcher"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050044 envConfigFetchTimeout = 10 * time.Second
Kousik Kumar3ff037e2022-01-25 22:11:01 -050045)
46
Kousik Kumar4c180ad2022-05-27 07:48:37 -040047var (
48 rbeRandPrefix int
49)
50
51func init() {
52 rand.Seed(time.Now().UnixNano())
53 rbeRandPrefix = rand.Intn(1000)
54}
55
Dan Willemsen1e704462016-08-21 15:17:17 -070056type Config struct{ *configImpl }
57
58type configImpl struct {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020059 // Some targets that are implemented in soong_build
60 // (bp2build, json-module-graph) are not here and have their own bits below.
Colin Cross28f527c2019-11-26 16:19:04 -080061 arguments []string
62 goma bool
63 environ *Environment
64 distDir string
65 buildDateTime string
MarkDacek6614d9c2022-12-07 21:57:38 +000066 logsPrefix string
Dan Willemsen1e704462016-08-21 15:17:17 -070067
68 // From the arguments
MarkDacekd0e7cd32022-12-02 22:22:40 +000069 parallel int
70 keepGoing int
71 verbose bool
72 checkbuild bool
73 dist bool
74 jsonModuleGraph bool
75 apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
76 bp2build bool
77 queryview bool
78 reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
79 soongDocs bool
80 skipConfig bool
81 skipKati bool
82 skipKatiNinja bool
83 skipSoong bool
84 skipNinja bool
85 skipSoongTests bool
86 searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
87 skipMetricsUpload bool
MarkDacek6614d9c2022-12-07 21:57:38 +000088 buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
Dan Willemsen1e704462016-08-21 15:17:17 -070089
90 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -070091 katiArgs []string
92 ninjaArgs []string
93 katiSuffix string
94 targetDevice string
95 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +000096 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -070097
Dan Willemsen2bb82d02019-12-27 09:35:42 -080098 // Autodetected
99 totalRAM uint64
100
Dan Willemsene3336352020-01-02 19:10:38 -0800101 brokenDupRules bool
102 brokenUsesNetwork bool
103 brokenNinjaEnvVars []string
Dan Willemsen18490112018-05-25 16:30:04 -0700104
105 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000106
MarkDacekb78465d2022-10-18 20:10:16 +0000107 bazelProdMode bool
108 bazelDevMode bool
109 bazelStagingMode bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000110
Colin Crossf3bdbcb2021-06-01 11:43:55 -0700111 // Set by multiproduct_kati
112 emptyNinjaFile bool
Yu Liu6e13b402021-07-27 14:29:06 -0700113
114 metricsUploader string
MarkDacekd06db5d2022-11-29 00:47:59 +0000115
116 bazelForceEnabledModules string
Spandan Dasc5763832022-11-08 18:42:16 +0000117
118 includeTags []string
Dan Willemsen1e704462016-08-21 15:17:17 -0700119}
120
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800121const srcDirFileCheck = "build/soong/root.bp"
122
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700123var buildFiles = []string{"Android.mk", "Android.bp"}
124
Patrice Arruda13848222019-04-22 17:12:02 -0700125type BuildAction uint
126
127const (
128 // Builds all of the modules and their dependencies of a specified directory, relative to the root
129 // directory of the source tree.
130 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
131
132 // Builds all of the modules and their dependencies of a list of specified directories. All specified
133 // directories are relative to the root directory of the source tree.
134 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700135
136 // Build a list of specified modules. If none was specified, simply build the whole source tree.
137 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700138)
139
140// checkTopDir validates that the current directory is at the root directory of the source tree.
141func checkTopDir(ctx Context) {
142 if _, err := os.Stat(srcDirFileCheck); err != nil {
143 if os.IsNotExist(err) {
144 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
145 }
146 ctx.Fatalln("Error verifying tree state:", err)
147 }
148}
149
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500150// fetchEnvConfig optionally fetches environment config from an
151// experiments system to control Soong features dynamically.
152func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
David Goldsmith62243a32022-04-08 13:42:04 +0000153 configName := envConfigName + "." + jsonSuffix
Kousik Kumarc75e1292022-07-07 02:20:51 +0000154 expConfigFetcher := &smpb.ExpConfigFetcher{Filename: &configName}
David Goldsmith62243a32022-04-08 13:42:04 +0000155 defer func() {
156 ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
157 }()
Kousik Kumarc75e1292022-07-07 02:20:51 +0000158 if !config.GoogleProdCredsExist() {
159 status := smpb.ExpConfigFetcher_MISSING_GCERT
160 expConfigFetcher.Status = &status
161 return nil
162 }
David Goldsmith62243a32022-04-08 13:42:04 +0000163
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500164 s, err := os.Stat(configFetcher)
165 if err != nil {
166 if os.IsNotExist(err) {
167 return nil
168 }
169 return err
170 }
171 if s.Mode()&0111 == 0 {
David Goldsmith62243a32022-04-08 13:42:04 +0000172 status := smpb.ExpConfigFetcher_ERROR
173 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500174 return fmt.Errorf("configuration fetcher binary %v is not executable: %v", configFetcher, s.Mode())
175 }
176
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500177 tCtx, cancel := context.WithTimeout(ctx, envConfigFetchTimeout)
178 defer cancel()
David Goldsmith62243a32022-04-08 13:42:04 +0000179 fetchStart := time.Now()
180 cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir(),
181 "-output_config_name", configName)
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500182 if err := cmd.Start(); err != nil {
David Goldsmith62243a32022-04-08 13:42:04 +0000183 status := smpb.ExpConfigFetcher_ERROR
184 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500185 return err
186 }
187
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500188 if err := cmd.Wait(); err != nil {
David Goldsmith62243a32022-04-08 13:42:04 +0000189 status := smpb.ExpConfigFetcher_ERROR
190 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500191 return err
192 }
David Goldsmith62243a32022-04-08 13:42:04 +0000193 fetchEnd := time.Now()
194 expConfigFetcher.Micros = proto.Uint64(uint64(fetchEnd.Sub(fetchStart).Microseconds()))
195 outConfigFilePath := filepath.Join(config.OutDir(), configName)
196 expConfigFetcher.Filename = proto.String(outConfigFilePath)
197 if _, err := os.Stat(outConfigFilePath); err == nil {
198 status := smpb.ExpConfigFetcher_CONFIG
199 expConfigFetcher.Status = &status
200 } else {
201 status := smpb.ExpConfigFetcher_NO_CONFIG
202 expConfigFetcher.Status = &status
203 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500204 return nil
205}
206
207func loadEnvConfig(ctx Context, config *configImpl) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500208 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
209 if bc == "" {
210 return nil
211 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500212
213 if err := fetchEnvConfig(ctx, config, bc); err != nil {
Kousik Kumar595fb1c2022-06-24 16:49:52 +0000214 ctx.Verbosef("Failed to fetch config file: %v\n", err)
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500215 }
216
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500217 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500218 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500219 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500220 envConfigDir,
221 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500222 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500223 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
224 envVarsJSON, err := ioutil.ReadFile(cfgFile)
225 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500226 continue
227 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500228 ctx.Verbosef("Loading config file %v\n", cfgFile)
229 var envVars map[string]map[string]string
230 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
231 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
232 continue
233 }
234 for k, v := range envVars["env"] {
235 if os.Getenv(k) != "" {
236 continue
237 }
238 config.environ.Set(k, v)
239 }
240 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
241 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500242 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500243
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500244 return nil
245}
246
Chris Parsonsb6e96902022-10-31 20:08:45 -0400247func defaultBazelProdMode(cfg *configImpl) bool {
MarkDacekd06db5d2022-11-29 00:47:59 +0000248 // Environment flag to disable Bazel for users which experience
Chris Parsonsb6e96902022-10-31 20:08:45 -0400249 // broken bazel-handled builds, or significant performance regressions.
250 if cfg.IsBazelMixedBuildForceDisabled() {
251 return false
252 }
253 // Darwin-host builds are currently untested with Bazel.
254 if runtime.GOOS == "darwin" {
255 return false
256 }
Chris Parsons035e03a2022-11-01 14:25:45 -0400257 return true
Chris Parsonsb6e96902022-10-31 20:08:45 -0400258}
259
MarkDacek6614d9c2022-12-07 21:57:38 +0000260func UploadOnlyConfig(ctx Context, _ ...string) Config {
261 ret := &configImpl{
262 environ: OsEnvironment(),
263 sandboxConfig: &SandboxConfig{},
264 }
265 return Config{ret}
266}
267
Dan Willemsen1e704462016-08-21 15:17:17 -0700268func NewConfig(ctx Context, args ...string) Config {
269 ret := &configImpl{
Spandan Dasa3639e62021-05-25 19:14:02 +0000270 environ: OsEnvironment(),
271 sandboxConfig: &SandboxConfig{},
Dan Willemsen1e704462016-08-21 15:17:17 -0700272 }
273
Patrice Arruda90109172020-07-28 18:07:27 +0000274 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700275 ret.parallel = runtime.NumCPU() + 2
276 ret.keepGoing = 1
277
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800278 ret.totalRAM = detectTotalRAM(ctx)
Dan Willemsen9b587492017-07-10 22:13:00 -0700279 ret.parseArgs(ctx, args)
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800280 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700281 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
282 ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
283 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800284 outDir := "out"
285 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
286 if wd, err := os.Getwd(); err != nil {
287 ctx.Fatalln("Failed to get working directory:", err)
288 } else {
289 outDir = filepath.Join(baseDir, filepath.Base(wd))
290 }
291 }
292 ret.environ.Set("OUT_DIR", outDir)
293 }
294
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500295 // loadEnvConfig needs to know what the OUT_DIR is, so it should
296 // be called after we determine the appropriate out directory.
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500297 if err := loadEnvConfig(ctx, ret); err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500298 ctx.Fatalln("Failed to parse env config files: %v", err)
299 }
300
Dan Willemsen2d31a442018-10-20 21:33:41 -0700301 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
302 ret.distDir = filepath.Clean(distDir)
303 } else {
304 ret.distDir = filepath.Join(ret.OutDir(), "dist")
305 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700306
Spandan Das05063612021-06-25 01:39:04 +0000307 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
308 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
309 }
310
Dan Willemsen1e704462016-08-21 15:17:17 -0700311 ret.environ.Unset(
312 // We're already using it
313 "USE_SOONG_UI",
314
315 // We should never use GOROOT/GOPATH from the shell environment
316 "GOROOT",
317 "GOPATH",
318
319 // These should only come from Soong, not the environment.
320 "CLANG",
321 "CLANG_CXX",
322 "CCC_CC",
323 "CCC_CXX",
324
325 // Used by the goma compiler wrapper, but should only be set by
326 // gomacc
327 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800328
329 // We handle this above
330 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700331
Dan Willemsen2d31a442018-10-20 21:33:41 -0700332 // This is handled above too, and set for individual commands later
333 "DIST_DIR",
334
Dan Willemsen68a09852017-04-18 13:56:57 -0700335 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000336 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700337 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700338 "DISPLAY",
339 "GREP_OPTIONS",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700340 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700341 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700342
343 // Drop make flags
344 "MAKEFLAGS",
345 "MAKELEVEL",
346 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700347
348 // Set in envsetup.sh, reset in makefiles
349 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700350
351 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
352 "ANDROID_BUILD_TOP",
353 "ANDROID_HOST_OUT",
354 "ANDROID_PRODUCT_OUT",
355 "ANDROID_HOST_OUT_TESTCASES",
356 "ANDROID_TARGET_OUT_TESTCASES",
357 "ANDROID_TOOLCHAIN",
358 "ANDROID_TOOLCHAIN_2ND_ARCH",
359 "ANDROID_DEV_SCRIPTS",
360 "ANDROID_EMULATOR_PREBUILTS",
361 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700362 )
363
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400364 if ret.UseGoma() || ret.ForceUseGoma() {
365 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
366 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400367 }
368
Dan Willemsen1e704462016-08-21 15:17:17 -0700369 // Tell python not to spam the source tree with .pyc files.
370 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
371
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400372 tmpDir := absPath(ctx, ret.TempDir())
373 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800374
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700375 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
376 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
377 "llvm-binutils-stable/llvm-symbolizer")
378 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
379
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800380 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700381 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800382
Yu Liu6e13b402021-07-27 14:29:06 -0700383 srcDir := absPath(ctx, ".")
384 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700385 ctx.Println("You are building in a directory whose absolute path contains a space character:")
386 ctx.Println()
387 ctx.Printf("%q\n", srcDir)
388 ctx.Println()
389 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700390 }
391
Yu Liu6e13b402021-07-27 14:29:06 -0700392 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
393
Dan Willemsendb8457c2017-05-12 16:38:17 -0700394 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700395 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
396 ctx.Println()
397 ctx.Printf("%q\n", outDir)
398 ctx.Println()
399 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700400 }
401
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000402 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700403 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
404 ctx.Println()
405 ctx.Printf("%q\n", distDir)
406 ctx.Println()
407 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700408 }
409
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700410 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000411 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
412 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100413 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Colin Cross59c1e6a2022-03-04 13:37:19 -0800414 java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700415 javaHome := func() string {
416 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
417 return override
418 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000419 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
420 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 +0100421 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000422 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
423 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
424 }
425 return java17Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700426 }()
427 absJavaHome := absPath(ctx, javaHome)
428
Dan Willemsened869522018-01-08 14:58:46 -0800429 ret.configureLocale(ctx)
430
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700431 newPath := []string{filepath.Join(absJavaHome, "bin")}
432 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
433 newPath = append(newPath, path)
434 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100435
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700436 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
437 ret.environ.Set("JAVA_HOME", absJavaHome)
438 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000439 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
440 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100441 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700442 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
443
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800444 outDir := ret.OutDir()
445 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800446 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800447 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800448 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800449 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800450 }
Colin Cross28f527c2019-11-26 16:19:04 -0800451
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800452 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
453
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400454 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400455 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400456 ret.environ.Set(k, v)
457 }
458 }
459
Patrice Arruda83842d72020-12-08 19:42:08 +0000460 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800461 if err := os.RemoveAll(bpd); err != nil {
462 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
463 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000464
Patrice Arruda96850362020-08-11 20:41:11 +0000465 c := Config{ret}
466 storeConfigMetrics(ctx, c)
467 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700468}
469
Patrice Arruda13848222019-04-22 17:12:02 -0700470// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
471// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700472func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
473 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700474}
475
Patrice Arruda96850362020-08-11 20:41:11 +0000476// storeConfigMetrics selects a set of configuration information and store in
477// the metrics system for further analysis.
478func storeConfigMetrics(ctx Context, config Config) {
479 if ctx.Metrics == nil {
480 return
481 }
482
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400483 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000484
485 s := &smpb.SystemResourceInfo{
486 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
487 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
488 }
489 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000490}
491
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400492func buildConfig(config Config) *smpb.BuildConfig {
Yu Liue737a992021-10-04 13:21:41 -0700493 c := &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -0400494 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
495 UseGoma: proto.Bool(config.UseGoma()),
496 UseRbe: proto.Bool(config.UseRBE()),
497 BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
498 ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400499 }
Yu Liue737a992021-10-04 13:21:41 -0700500 c.Targets = append(c.Targets, config.arguments...)
501
502 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400503}
504
Patrice Arruda13848222019-04-22 17:12:02 -0700505// getConfigArgs processes the command arguments based on the build action and creates a set of new
506// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700507func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700508 // The next block of code verifies that the current directory is the root directory of the source
509 // tree. It then finds the relative path of dir based on the root directory of the source tree
510 // and verify that dir is inside of the source tree.
511 checkTopDir(ctx)
512 topDir, err := os.Getwd()
513 if err != nil {
514 ctx.Fatalf("Error retrieving top directory: %v", err)
515 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700516 dir, err = filepath.EvalSymlinks(dir)
517 if err != nil {
518 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
519 }
Patrice Arruda13848222019-04-22 17:12:02 -0700520 dir, err = filepath.Abs(dir)
521 if err != nil {
522 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
523 }
524 relDir, err := filepath.Rel(topDir, dir)
525 if err != nil {
526 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
527 }
528 // If there are ".." in the path, it's not in the source tree.
529 if strings.Contains(relDir, "..") {
530 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
531 }
532
533 configArgs := args[:]
534
535 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
536 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
537 targetNamePrefix := "MODULES-IN-"
538 if inList("GET-INSTALL-PATH", configArgs) {
539 targetNamePrefix = "GET-INSTALL-PATH-IN-"
540 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
541 }
542
Patrice Arruda13848222019-04-22 17:12:02 -0700543 var targets []string
544
545 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700546 case BUILD_MODULES:
547 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700548 case BUILD_MODULES_IN_A_DIRECTORY:
549 // If dir is the root source tree, all the modules are built of the source tree are built so
550 // no need to find the build file.
551 if topDir == dir {
552 break
553 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700554
Patrice Arruda13848222019-04-22 17:12:02 -0700555 buildFile := findBuildFile(ctx, relDir)
556 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700557 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700558 }
Patrice Arruda13848222019-04-22 17:12:02 -0700559 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
560 case BUILD_MODULES_IN_DIRECTORIES:
561 newConfigArgs, dirs := splitArgs(configArgs)
562 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700563 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700564 }
565
566 // Tidy only override all other specified targets.
567 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
568 if tidyOnly == "true" || tidyOnly == "1" {
569 configArgs = append(configArgs, "tidy_only")
570 } else {
571 configArgs = append(configArgs, targets...)
572 }
573
574 return configArgs
575}
576
577// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
578func convertToTarget(dir string, targetNamePrefix string) string {
579 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
580}
581
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700582// hasBuildFile returns true if dir contains an Android build file.
583func hasBuildFile(ctx Context, dir string) bool {
584 for _, buildFile := range buildFiles {
585 _, err := os.Stat(filepath.Join(dir, buildFile))
586 if err == nil {
587 return true
588 }
589 if !os.IsNotExist(err) {
590 ctx.Fatalf("Error retrieving the build file stats: %v", err)
591 }
592 }
593 return false
594}
595
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700596// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
597// in the current and any sub directory of dir. If a build file is not found, traverse the path
598// up by one directory and repeat again until either a build file is found or reached to the root
599// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
600// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700601func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700602 // If the string is empty or ".", assume it is top directory of the source tree.
603 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700604 return ""
605 }
606
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700607 found := false
608 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
609 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
610 if err != nil {
611 return err
612 }
613 if found {
614 return filepath.SkipDir
615 }
616 if info.IsDir() {
617 return nil
618 }
619 for _, buildFile := range buildFiles {
620 if info.Name() == buildFile {
621 found = true
622 return filepath.SkipDir
623 }
624 }
625 return nil
626 })
627 if err != nil {
628 ctx.Fatalf("Error finding Android build file: %v", err)
629 }
630
631 if found {
632 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700633 }
634 }
635
636 return ""
637}
638
639// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
640func splitArgs(args []string) (newArgs []string, dirs []string) {
641 specialArgs := map[string]bool{
642 "showcommands": true,
643 "snod": true,
644 "dist": true,
645 "checkbuild": true,
646 }
647
648 newArgs = []string{}
649 dirs = []string{}
650
651 for _, arg := range args {
652 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
653 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
654 newArgs = append(newArgs, arg)
655 continue
656 }
657
658 if _, ok := specialArgs[arg]; ok {
659 newArgs = append(newArgs, arg)
660 continue
661 }
662
663 dirs = append(dirs, arg)
664 }
665
666 return newArgs, dirs
667}
668
669// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
670// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
671// source root tree where the build action command was invoked. Each directory is validated if the
672// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700673func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700674 for _, dir := range dirs {
675 // The directory may have specified specific modules to build. ":" is the separator to separate
676 // the directory and the list of modules.
677 s := strings.Split(dir, ":")
678 l := len(s)
679 if l > 2 { // more than one ":" was specified.
680 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
681 }
682
683 dir = filepath.Join(relDir, s[0])
684 if _, err := os.Stat(dir); err != nil {
685 ctx.Fatalf("couldn't find directory %s", dir)
686 }
687
688 // Verify that if there are any targets specified after ":". Each target is separated by ",".
689 var newTargets []string
690 if l == 2 && s[1] != "" {
691 newTargets = strings.Split(s[1], ",")
692 if inList("", newTargets) {
693 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
694 }
695 }
696
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700697 // If there are specified targets to build in dir, an android build file must exist for the one
698 // shot build. For the non-targets case, find the appropriate build file and build all the
699 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700700 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700701 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700702 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
703 }
704 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700705 buildFile := findBuildFile(ctx, dir)
706 if buildFile == "" {
707 ctx.Fatalf("Build file not found for %s directory", dir)
708 }
709 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700710 }
711
Patrice Arruda13848222019-04-22 17:12:02 -0700712 targets = append(targets, newTargets...)
713 }
714
Dan Willemsence41e942019-07-29 23:39:30 -0700715 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700716}
717
Dan Willemsen9b587492017-07-10 22:13:00 -0700718func (c *configImpl) parseArgs(ctx Context, args []string) {
719 for i := 0; i < len(args); i++ {
720 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100721 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700722 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200723 } else if arg == "--empty-ninja-file" {
724 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100725 } else if arg == "--skip-ninja" {
726 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700727 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700728 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
729 // but it does run a Kati ninja file if the .kati_enabled marker file was created
730 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000731 c.skipConfig = true
732 c.skipKati = true
733 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100734 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000735 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100736 } else if arg == "--soong-only" {
737 c.skipKati = true
738 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200739 } else if arg == "--config-only" {
740 c.skipKati = true
741 c.skipKatiNinja = true
742 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700743 } else if arg == "--skip-config" {
744 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700745 } else if arg == "--skip-soong-tests" {
746 c.skipSoongTests = true
MarkDacekd0e7cd32022-12-02 22:22:40 +0000747 } else if arg == "--skip-metrics-upload" {
748 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500749 } else if arg == "--mk-metrics" {
750 c.reportMkMetrics = true
Chris Parsonsef615e52022-08-18 22:04:11 -0400751 } else if arg == "--bazel-mode" {
752 c.bazelProdMode = true
753 } else if arg == "--bazel-mode-dev" {
754 c.bazelDevMode = true
MarkDacekb78465d2022-10-18 20:10:16 +0000755 } else if arg == "--bazel-mode-staging" {
756 c.bazelStagingMode = true
Spandan Das394aa322022-11-03 17:02:10 +0000757 } else if arg == "--search-api-dir" {
758 c.searchApiDir = true
MarkDacekb96561e2022-12-02 04:34:43 +0000759 } else if strings.HasPrefix(arg, "--build-command=") {
760 buildCmd := strings.TrimPrefix(arg, "--build-command=")
761 // remove quotations
762 buildCmd = strings.TrimPrefix(buildCmd, "\"")
763 buildCmd = strings.TrimSuffix(buildCmd, "\"")
764 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacekd06db5d2022-11-29 00:47:59 +0000765 } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
766 c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
MarkDacek6614d9c2022-12-07 21:57:38 +0000767 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
768 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
769 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
770 if err == nil {
771 c.buildStartedTime = val
772 } else {
773 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
774 }
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700775 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700776 parseArgNum := func(def int) int {
777 if len(arg) > 2 {
778 p, err := strconv.ParseUint(arg[2:], 10, 31)
779 if err != nil {
780 ctx.Fatalf("Failed to parse %q: %v", arg, err)
781 }
782 return int(p)
783 } else if i+1 < len(args) {
784 p, err := strconv.ParseUint(args[i+1], 10, 31)
785 if err == nil {
786 i++
787 return int(p)
788 }
789 }
790 return def
791 }
792
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700793 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700794 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700795 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700796 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700797 } else {
798 ctx.Fatalln("Unknown option:", arg)
799 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700800 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700801 if k == "OUT_DIR" {
802 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
803 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700804 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700805 } else if arg == "dist" {
806 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200807 } else if arg == "json-module-graph" {
808 c.jsonModuleGraph = true
809 } else if arg == "bp2build" {
810 c.bp2build = true
Spandan Das5af0bd32022-09-28 20:43:08 +0000811 } else if arg == "api_bp2build" {
812 c.apiBp2build = true
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200813 } else if arg == "queryview" {
814 c.queryview = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200815 } else if arg == "soong_docs" {
816 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700817 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700818 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800819 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700820 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700821 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700822 }
823 }
Chris Parsonsb6e96902022-10-31 20:08:45 -0400824 if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
825 c.bazelProdMode = defaultBazelProdMode(c)
826 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700827}
828
Dan Willemsened869522018-01-08 14:58:46 -0800829func (c *configImpl) configureLocale(ctx Context) {
830 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
831 output, err := cmd.Output()
832
833 var locales []string
834 if err == nil {
835 locales = strings.Split(string(output), "\n")
836 } else {
837 // If we're unable to list the locales, let's assume en_US.UTF-8
838 locales = []string{"en_US.UTF-8"}
839 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
840 }
841
842 // gettext uses LANGUAGE, which is passed directly through
843
844 // For LANG and LC_*, only preserve the evaluated version of
845 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800846 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800847 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800848 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800849 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800850 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800851 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800852 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800853 }
854
855 c.environ.UnsetWithPrefix("LC_")
856
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800857 if userLang != "" {
858 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800859 }
860
861 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
862 // for others)
863 if inList("C.UTF-8", locales) {
864 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500865 } else if inList("C.utf8", locales) {
866 // These normalize to the same thing
867 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800868 } else if inList("en_US.UTF-8", locales) {
869 c.environ.Set("LANG", "en_US.UTF-8")
870 } else if inList("en_US.utf8", locales) {
871 // These normalize to the same thing
872 c.environ.Set("LANG", "en_US.UTF-8")
873 } else {
874 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
875 }
876}
877
Dan Willemsen1e704462016-08-21 15:17:17 -0700878func (c *configImpl) Environment() *Environment {
879 return c.environ
880}
881
882func (c *configImpl) Arguments() []string {
883 return c.arguments
884}
885
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200886func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200887 if len(c.Arguments()) > 0 {
888 // Explicit targets requested that are not special targets like b2pbuild
889 // or the JSON module graph
890 return true
891 }
892
Spandan Das5af0bd32022-09-28 20:43:08 +0000893 if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200894 // Command line was empty, the default Ninja target is built
895 return true
896 }
897
Liz Kammer88677422021-12-15 15:03:19 -0500898 // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
899 if c.Dist() && !c.Bp2Build() {
900 return true
901 }
902
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200903 // build.ninja doesn't need to be generated
904 return false
905}
906
Dan Willemsen1e704462016-08-21 15:17:17 -0700907func (c *configImpl) OutDir() string {
908 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700909 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700910 }
911 return "out"
912}
913
Dan Willemsen8a073a82017-02-04 17:30:44 -0800914func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -0400915 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000916}
917
918func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700919 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800920}
921
Dan Willemsen1e704462016-08-21 15:17:17 -0700922func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000923 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700924 return c.arguments
925 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700926 return c.ninjaArgs
927}
928
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500929func (c *configImpl) BazelOutDir() string {
930 return filepath.Join(c.OutDir(), "bazel")
931}
932
Liz Kammer2af5ea82022-11-11 14:21:03 -0500933func (c *configImpl) bazelOutputBase() string {
934 return filepath.Join(c.BazelOutDir(), "output")
935}
936
Dan Willemsen1e704462016-08-21 15:17:17 -0700937func (c *configImpl) SoongOutDir() string {
938 return filepath.Join(c.OutDir(), "soong")
939}
940
Spandan Das394aa322022-11-03 17:02:10 +0000941func (c *configImpl) ApiSurfacesOutDir() string {
942 return filepath.Join(c.OutDir(), "api_surfaces")
943}
944
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200945func (c *configImpl) PrebuiltOS() string {
946 switch runtime.GOOS {
947 case "linux":
948 return "linux-x86"
949 case "darwin":
950 return "darwin-x86"
951 default:
952 panic("Unknown GOOS")
953 }
954}
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100955
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200956func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -0700957 if c.SkipKatiNinja() {
958 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
959 } else {
960 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
961 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200962}
963
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200964func (c *configImpl) NamedGlobFile(name string) string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100965 return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200966}
967
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200968func (c *configImpl) UsedEnvFile(tag string) string {
969 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
970}
971
Lukacs T. Berkic541cd22022-10-26 07:26:50 +0000972func (c *configImpl) Bp2BuildFilesMarkerFile() string {
973 return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
974}
975
976func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100977 return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200978}
979
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200980func (c *configImpl) SoongDocsHtml() string {
981 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
982}
983
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200984func (c *configImpl) QueryviewMarkerFile() string {
985 return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
986}
987
Spandan Das5af0bd32022-09-28 20:43:08 +0000988func (c *configImpl) ApiBp2buildMarkerFile() string {
989 return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
990}
991
Lukacs T. Berkie571dc32021-08-25 14:14:13 +0200992func (c *configImpl) ModuleGraphFile() string {
993 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
994}
995
kgui67007242022-01-25 13:50:25 +0800996func (c *configImpl) ModuleActionsFile() string {
997 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
998}
999
Jeff Gastonefc1b412017-03-29 17:29:06 -07001000func (c *configImpl) TempDir() string {
1001 return shared.TempDirForOutDir(c.SoongOutDir())
1002}
1003
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001004func (c *configImpl) FileListDir() string {
1005 return filepath.Join(c.OutDir(), ".module_paths")
1006}
1007
Dan Willemsen1e704462016-08-21 15:17:17 -07001008func (c *configImpl) KatiSuffix() string {
1009 if c.katiSuffix != "" {
1010 return c.katiSuffix
1011 }
1012 panic("SetKatiSuffix has not been called")
1013}
1014
Colin Cross37193492017-11-16 17:55:00 -08001015// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1016// user is interested in additional checks at the expense of build time.
1017func (c *configImpl) Checkbuild() bool {
1018 return c.checkbuild
1019}
1020
Dan Willemsen8a073a82017-02-04 17:30:44 -08001021func (c *configImpl) Dist() bool {
1022 return c.dist
1023}
1024
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001025func (c *configImpl) JsonModuleGraph() bool {
1026 return c.jsonModuleGraph
1027}
1028
1029func (c *configImpl) Bp2Build() bool {
1030 return c.bp2build
1031}
1032
Spandan Das5af0bd32022-09-28 20:43:08 +00001033func (c *configImpl) ApiBp2build() bool {
1034 return c.apiBp2build
1035}
1036
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001037func (c *configImpl) Queryview() bool {
1038 return c.queryview
1039}
1040
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001041func (c *configImpl) SoongDocs() bool {
1042 return c.soongDocs
1043}
1044
Dan Willemsen1e704462016-08-21 15:17:17 -07001045func (c *configImpl) IsVerbose() bool {
1046 return c.verbose
1047}
1048
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001049func (c *configImpl) SkipKati() bool {
1050 return c.skipKati
1051}
1052
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001053func (c *configImpl) SkipKatiNinja() bool {
1054 return c.skipKatiNinja
1055}
1056
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001057func (c *configImpl) SkipSoong() bool {
1058 return c.skipSoong
1059}
1060
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001061func (c *configImpl) SkipNinja() bool {
1062 return c.skipNinja
1063}
1064
Anton Hansson5a7861a2021-06-04 10:09:01 +01001065func (c *configImpl) SetSkipNinja(v bool) {
1066 c.skipNinja = v
1067}
1068
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001069func (c *configImpl) SkipConfig() bool {
1070 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001071}
1072
Dan Willemsen1e704462016-08-21 15:17:17 -07001073func (c *configImpl) TargetProduct() string {
1074 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1075 return v
1076 }
1077 panic("TARGET_PRODUCT is not defined")
1078}
1079
Dan Willemsen02781d52017-05-12 19:28:13 -07001080func (c *configImpl) TargetDevice() string {
1081 return c.targetDevice
1082}
1083
1084func (c *configImpl) SetTargetDevice(device string) {
1085 c.targetDevice = device
1086}
1087
1088func (c *configImpl) TargetBuildVariant() string {
1089 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1090 return v
1091 }
1092 panic("TARGET_BUILD_VARIANT is not defined")
1093}
1094
Dan Willemsen1e704462016-08-21 15:17:17 -07001095func (c *configImpl) KatiArgs() []string {
1096 return c.katiArgs
1097}
1098
1099func (c *configImpl) Parallel() int {
1100 return c.parallel
1101}
1102
Spandan Dasc5763832022-11-08 18:42:16 +00001103func (c *configImpl) GetIncludeTags() []string {
1104 return c.includeTags
1105}
1106
1107func (c *configImpl) SetIncludeTags(i []string) {
1108 c.includeTags = i
1109}
1110
MarkDacek6614d9c2022-12-07 21:57:38 +00001111func (c *configImpl) GetLogsPrefix() string {
1112 return c.logsPrefix
1113}
1114
1115func (c *configImpl) SetLogsPrefix(prefix string) {
1116 c.logsPrefix = prefix
1117}
1118
Colin Cross8b8bec32019-11-15 13:18:43 -08001119func (c *configImpl) HighmemParallel() int {
1120 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1121 return i
1122 }
1123
1124 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1125 parallel := c.Parallel()
1126 if c.UseRemoteBuild() {
1127 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1128 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1129 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1130 // Return 1/16th of the size of the local pool, rounding up.
1131 return (parallel + 15) / 16
1132 } else if c.totalRAM == 0 {
1133 // Couldn't detect the total RAM, don't restrict highmem processes.
1134 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001135 } else if c.totalRAM <= 16*1024*1024*1024 {
1136 // Less than 16GB of ram, restrict to 1 highmem processes
1137 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001138 } else if c.totalRAM <= 32*1024*1024*1024 {
1139 // Less than 32GB of ram, restrict to 2 highmem processes
1140 return 2
1141 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1142 // If less than 8GB total RAM per process, reduce the number of highmem processes
1143 return p
1144 }
1145 // No restriction on highmem processes
1146 return parallel
1147}
1148
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001149func (c *configImpl) TotalRAM() uint64 {
1150 return c.totalRAM
1151}
1152
Kousik Kumarec478642020-09-21 13:39:24 -04001153// ForceUseGoma determines whether we should override Goma deprecation
1154// and use Goma for the current build or not.
1155func (c *configImpl) ForceUseGoma() bool {
1156 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1157 v = strings.TrimSpace(v)
1158 if v != "" && v != "false" {
1159 return true
1160 }
1161 }
1162 return false
1163}
1164
Dan Willemsen1e704462016-08-21 15:17:17 -07001165func (c *configImpl) UseGoma() bool {
1166 if v, ok := c.environ.Get("USE_GOMA"); ok {
1167 v = strings.TrimSpace(v)
1168 if v != "" && v != "false" {
1169 return true
1170 }
1171 }
1172 return false
1173}
1174
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001175func (c *configImpl) StartGoma() bool {
1176 if !c.UseGoma() {
1177 return false
1178 }
1179
1180 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1181 v = strings.TrimSpace(v)
1182 if v != "" && v != "false" {
1183 return false
1184 }
1185 }
1186 return true
1187}
1188
Ramy Medhatbbf25672019-07-17 12:30:04 +00001189func (c *configImpl) UseRBE() bool {
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001190 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001191 v = strings.TrimSpace(v)
1192 if v != "" && v != "false" {
1193 return true
1194 }
1195 }
1196 return false
1197}
1198
Chris Parsonsef615e52022-08-18 22:04:11 -04001199func (c *configImpl) BazelBuildEnabled() bool {
MarkDacekb78465d2022-10-18 20:10:16 +00001200 return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
Chris Parsonsec1a3dc2021-04-20 15:32:07 -04001201}
1202
Ramy Medhatbbf25672019-07-17 12:30:04 +00001203func (c *configImpl) StartRBE() bool {
1204 if !c.UseRBE() {
1205 return false
1206 }
1207
1208 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1209 v = strings.TrimSpace(v)
1210 if v != "" && v != "false" {
1211 return false
1212 }
1213 }
1214 return true
1215}
1216
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001217func (c *configImpl) rbeProxyLogsDir() string {
1218 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001219 if v, ok := c.environ.Get(f); ok {
1220 return v
1221 }
1222 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001223 buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
1224 return filepath.Join(buildTmpDir, "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001225}
1226
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001227func (c *configImpl) shouldCleanupRBELogsDir() bool {
1228 // Perform a log directory cleanup only when the log directory
1229 // is auto created by the build rather than user-specified.
1230 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
1231 if _, ok := c.environ.Get(f); ok {
1232 return false
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001233 }
1234 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001235 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001236}
1237
1238func (c *configImpl) rbeExecRoot() string {
1239 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1240 if v, ok := c.environ.Get(f); ok {
1241 return v
1242 }
1243 }
1244 wd, err := os.Getwd()
1245 if err != nil {
1246 return ""
1247 }
1248 return wd
1249}
1250
1251func (c *configImpl) rbeDir() string {
1252 if v, ok := c.environ.Get("RBE_DIR"); ok {
1253 return v
1254 }
1255 return "prebuilts/remoteexecution-client/live/"
1256}
1257
1258func (c *configImpl) rbeReproxy() string {
1259 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1260 if v, ok := c.environ.Get(f); ok {
1261 return v
1262 }
1263 }
1264 return filepath.Join(c.rbeDir(), "reproxy")
1265}
1266
1267func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001268 credFlags := []string{
1269 "use_application_default_credentials",
1270 "use_gce_credentials",
1271 "credential_file",
1272 "use_google_prod_creds",
1273 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001274 for _, cf := range credFlags {
1275 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1276 if v, ok := c.environ.Get(f); ok {
1277 v = strings.TrimSpace(v)
1278 if v != "" && v != "false" && v != "0" {
1279 return "RBE_" + cf, v
1280 }
1281 }
1282 }
1283 }
1284 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001285}
1286
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001287func (c *configImpl) rbeSockAddr(dir string) (string, error) {
1288 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
1289 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1290
1291 name := filepath.Join(dir, base)
1292 if len(name) < maxNameLen {
1293 return name, nil
1294 }
1295
1296 name = filepath.Join("/tmp", base)
1297 if len(name) < maxNameLen {
1298 return name, nil
1299 }
1300
1301 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1302}
1303
Kousik Kumar7bc78192022-04-27 14:52:56 -04001304// IsGooglerEnvironment returns true if the current build is running
1305// on a Google developer machine and false otherwise.
1306func (c *configImpl) IsGooglerEnvironment() bool {
1307 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1308 if v, ok := c.environ.Get(cf); ok {
1309 return v == "googler"
1310 }
1311 return false
1312}
1313
1314// GoogleProdCredsExist determine whether credentials exist on the
1315// Googler machine to use remote execution.
1316func (c *configImpl) GoogleProdCredsExist() bool {
1317 if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
1318 return false
1319 }
1320 return true
1321}
1322
1323// UseRemoteBuild indicates whether to use a remote build acceleration system
1324// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001325func (c *configImpl) UseRemoteBuild() bool {
1326 return c.UseGoma() || c.UseRBE()
1327}
1328
Kousik Kumar7bc78192022-04-27 14:52:56 -04001329// StubbyExists checks whether the stubby binary exists on the machine running
1330// the build.
1331func (c *configImpl) StubbyExists() bool {
1332 if _, err := exec.LookPath("stubby"); err != nil {
1333 return false
1334 }
1335 return true
1336}
1337
Dan Willemsen1e704462016-08-21 15:17:17 -07001338// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001339// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001340// still limited by Parallel()
1341func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001342 if !c.UseRemoteBuild() {
1343 return 0
1344 }
1345 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1346 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001347 }
1348 return 500
1349}
1350
1351func (c *configImpl) SetKatiArgs(args []string) {
1352 c.katiArgs = args
1353}
1354
1355func (c *configImpl) SetNinjaArgs(args []string) {
1356 c.ninjaArgs = args
1357}
1358
1359func (c *configImpl) SetKatiSuffix(suffix string) {
1360 c.katiSuffix = suffix
1361}
1362
Dan Willemsene0879fc2017-08-04 15:06:27 -07001363func (c *configImpl) LastKatiSuffixFile() string {
1364 return filepath.Join(c.OutDir(), "last_kati_suffix")
1365}
1366
1367func (c *configImpl) HasKatiSuffix() bool {
1368 return c.katiSuffix != ""
1369}
1370
Dan Willemsen1e704462016-08-21 15:17:17 -07001371func (c *configImpl) KatiEnvFile() string {
1372 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1373}
1374
Dan Willemsen29971232018-09-26 14:58:30 -07001375func (c *configImpl) KatiBuildNinjaFile() string {
1376 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001377}
1378
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001379func (c *configImpl) KatiPackageNinjaFile() string {
1380 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1381}
1382
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001383func (c *configImpl) SoongVarsFile() string {
1384 return filepath.Join(c.SoongOutDir(), "soong.variables")
1385}
1386
Dan Willemsen1e704462016-08-21 15:17:17 -07001387func (c *configImpl) SoongNinjaFile() string {
1388 return filepath.Join(c.SoongOutDir(), "build.ninja")
1389}
1390
1391func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001392 if c.katiSuffix == "" {
1393 return filepath.Join(c.OutDir(), "combined.ninja")
1394 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001395 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1396}
1397
1398func (c *configImpl) SoongAndroidMk() string {
1399 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1400}
1401
1402func (c *configImpl) SoongMakeVarsMk() string {
1403 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1404}
1405
Dan Willemsenf052f782017-05-18 15:29:04 -07001406func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001407 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001408}
1409
Dan Willemsen02781d52017-05-12 19:28:13 -07001410func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001411 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1412}
1413
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001414func (c *configImpl) KatiPackageMkDir() string {
1415 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1416}
1417
Dan Willemsenf052f782017-05-18 15:29:04 -07001418func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001419 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001420}
1421
1422func (c *configImpl) HostOut() string {
1423 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1424}
1425
1426// This probably needs to be multi-valued, so not exporting it for now
1427func (c *configImpl) hostCrossOut() string {
1428 if runtime.GOOS == "linux" {
1429 return filepath.Join(c.hostOutRoot(), "windows-x86")
1430 } else {
1431 return ""
1432 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001433}
1434
Dan Willemsen1e704462016-08-21 15:17:17 -07001435func (c *configImpl) HostPrebuiltTag() string {
1436 if runtime.GOOS == "linux" {
1437 return "linux-x86"
1438 } else if runtime.GOOS == "darwin" {
1439 return "darwin-x86"
1440 } else {
1441 panic("Unsupported OS")
1442 }
1443}
Dan Willemsenf173d592017-04-27 14:28:00 -07001444
Dan Willemsen8122bd52017-10-12 20:20:41 -07001445func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001446 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1447 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001448 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1449 if _, err := os.Stat(asan); err == nil {
1450 return asan
1451 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001452 }
1453 }
1454 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1455}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001456
1457func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1458 c.brokenDupRules = val
1459}
1460
1461func (c *configImpl) BuildBrokenDupRules() bool {
1462 return c.brokenDupRules
1463}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001464
Dan Willemsen25e6f092019-04-09 10:22:43 -07001465func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1466 c.brokenUsesNetwork = val
1467}
1468
1469func (c *configImpl) BuildBrokenUsesNetwork() bool {
1470 return c.brokenUsesNetwork
1471}
1472
Dan Willemsene3336352020-01-02 19:10:38 -08001473func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1474 c.brokenNinjaEnvVars = val
1475}
1476
1477func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1478 return c.brokenNinjaEnvVars
1479}
1480
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001481func (c *configImpl) SetTargetDeviceDir(dir string) {
1482 c.targetDeviceDir = dir
1483}
1484
1485func (c *configImpl) TargetDeviceDir() string {
1486 return c.targetDeviceDir
1487}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001488
Patrice Arruda219eef32020-06-01 17:29:30 +00001489func (c *configImpl) BuildDateTime() string {
1490 return c.buildDateTime
1491}
1492
1493func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001494 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001495}
Patrice Arruda83842d72020-12-08 19:42:08 +00001496
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001497// LogsDir returns the absolute path to the logs directory where build log and
1498// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001499// directory. If the argument dist is specified, the logs directory
1500// is <dist_dir>/logs.
1501func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001502 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001503 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001504 // Always write logs to the real dist dir, even if Bazel is using a rigged dist dir for other files
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001505 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001506 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001507 absDir, err := filepath.Abs(dir)
1508 if err != nil {
1509 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1510 os.Exit(1)
1511 }
1512 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001513}
1514
1515// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1516// where the bazel profiles are located.
1517func (c *configImpl) BazelMetricsDir() string {
1518 return filepath.Join(c.LogsDir(), "bazel_metrics")
1519}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001520
Chris Parsons53f68ae2022-03-03 12:01:40 -05001521// MkFileMetrics returns the file path for make-related metrics.
1522func (c *configImpl) MkMetrics() string {
1523 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1524}
1525
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001526func (c *configImpl) SetEmptyNinjaFile(v bool) {
1527 c.emptyNinjaFile = v
1528}
1529
1530func (c *configImpl) EmptyNinjaFile() bool {
1531 return c.emptyNinjaFile
1532}
Yu Liu6e13b402021-07-27 14:29:06 -07001533
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001534func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
1535 return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
1536}
1537
MarkDacekd06db5d2022-11-29 00:47:59 +00001538func (c *configImpl) BazelModulesForceEnabledByFlag() string {
1539 return c.bazelForceEnabledModules
1540}
1541
MarkDacekd0e7cd32022-12-02 22:22:40 +00001542func (c *configImpl) SkipMetricsUpload() bool {
1543 return c.skipMetricsUpload
1544}
1545
MarkDacek6614d9c2022-12-07 21:57:38 +00001546// Returns a Time object if one was passed via a command-line flag.
1547// Otherwise returns the passed default.
1548func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1549 if c.buildStartedTime == 0 {
1550 return defaultTime
1551 }
1552 return time.UnixMilli(c.buildStartedTime)
1553}
1554
Yu Liu6e13b402021-07-27 14:29:06 -07001555func GetMetricsUploader(topDir string, env *Environment) string {
1556 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1557 metricsUploader := filepath.Join(topDir, p)
1558 if _, err := os.Stat(metricsUploader); err == nil {
1559 return metricsUploader
1560 }
1561 }
1562
1563 return ""
1564}