blob: b928faa710517723fbebc542b2661278226c0e8a [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
MarkDacek7901e582023-01-09 19:48:01 +0000207func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500208 if bc == "" {
209 return nil
210 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500211
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500212 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500213 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500214 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500215 envConfigDir,
216 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500217 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500218 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
219 envVarsJSON, err := ioutil.ReadFile(cfgFile)
220 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500221 continue
222 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500223 ctx.Verbosef("Loading config file %v\n", cfgFile)
224 var envVars map[string]map[string]string
225 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
226 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
227 continue
228 }
229 for k, v := range envVars["env"] {
230 if os.Getenv(k) != "" {
231 continue
232 }
233 config.environ.Set(k, v)
234 }
235 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
236 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500237 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500238
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500239 return nil
240}
241
Chris Parsonsb6e96902022-10-31 20:08:45 -0400242func defaultBazelProdMode(cfg *configImpl) bool {
MarkDacekd06db5d2022-11-29 00:47:59 +0000243 // Environment flag to disable Bazel for users which experience
Chris Parsonsb6e96902022-10-31 20:08:45 -0400244 // broken bazel-handled builds, or significant performance regressions.
245 if cfg.IsBazelMixedBuildForceDisabled() {
246 return false
247 }
248 // Darwin-host builds are currently untested with Bazel.
249 if runtime.GOOS == "darwin" {
250 return false
251 }
Chris Parsons035e03a2022-11-01 14:25:45 -0400252 return true
Chris Parsonsb6e96902022-10-31 20:08:45 -0400253}
254
MarkDacek6614d9c2022-12-07 21:57:38 +0000255func UploadOnlyConfig(ctx Context, _ ...string) Config {
256 ret := &configImpl{
257 environ: OsEnvironment(),
258 sandboxConfig: &SandboxConfig{},
259 }
MarkDacek7901e582023-01-09 19:48:01 +0000260 srcDir := absPath(ctx, ".")
261 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
262 if err := loadEnvConfig(ctx, ret, bc); err != nil {
263 ctx.Fatalln("Failed to parse env config files: %v", err)
264 }
265 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
MarkDacek6614d9c2022-12-07 21:57:38 +0000266 return Config{ret}
267}
268
Dan Willemsen1e704462016-08-21 15:17:17 -0700269func NewConfig(ctx Context, args ...string) Config {
270 ret := &configImpl{
Spandan Dasa3639e62021-05-25 19:14:02 +0000271 environ: OsEnvironment(),
272 sandboxConfig: &SandboxConfig{},
Dan Willemsen1e704462016-08-21 15:17:17 -0700273 }
274
Patrice Arruda90109172020-07-28 18:07:27 +0000275 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700276 ret.parallel = runtime.NumCPU() + 2
277 ret.keepGoing = 1
278
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800279 ret.totalRAM = detectTotalRAM(ctx)
Dan Willemsen9b587492017-07-10 22:13:00 -0700280 ret.parseArgs(ctx, args)
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800281 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700282 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
283 ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
284 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800285 outDir := "out"
286 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
287 if wd, err := os.Getwd(); err != nil {
288 ctx.Fatalln("Failed to get working directory:", err)
289 } else {
290 outDir = filepath.Join(baseDir, filepath.Base(wd))
291 }
292 }
293 ret.environ.Set("OUT_DIR", outDir)
294 }
295
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500296 // loadEnvConfig needs to know what the OUT_DIR is, so it should
297 // be called after we determine the appropriate out directory.
MarkDacek7901e582023-01-09 19:48:01 +0000298 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
299
300 if bc != "" {
301 if err := fetchEnvConfig(ctx, ret, bc); err != nil {
302 ctx.Verbosef("Failed to fetch config file: %v\n", err)
303
304 } else if err := loadEnvConfig(ctx, ret, bc); err != nil {
305 ctx.Fatalln("Failed to parse env config files: %v", err)
306 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500307 }
308
Dan Willemsen2d31a442018-10-20 21:33:41 -0700309 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
310 ret.distDir = filepath.Clean(distDir)
311 } else {
312 ret.distDir = filepath.Join(ret.OutDir(), "dist")
313 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700314
Spandan Das05063612021-06-25 01:39:04 +0000315 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
316 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
317 }
318
Dan Willemsen1e704462016-08-21 15:17:17 -0700319 ret.environ.Unset(
320 // We're already using it
321 "USE_SOONG_UI",
322
323 // We should never use GOROOT/GOPATH from the shell environment
324 "GOROOT",
325 "GOPATH",
326
327 // These should only come from Soong, not the environment.
328 "CLANG",
329 "CLANG_CXX",
330 "CCC_CC",
331 "CCC_CXX",
332
333 // Used by the goma compiler wrapper, but should only be set by
334 // gomacc
335 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800336
337 // We handle this above
338 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700339
Dan Willemsen2d31a442018-10-20 21:33:41 -0700340 // This is handled above too, and set for individual commands later
341 "DIST_DIR",
342
Dan Willemsen68a09852017-04-18 13:56:57 -0700343 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000344 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700345 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700346 "DISPLAY",
347 "GREP_OPTIONS",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700348 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700349 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700350
351 // Drop make flags
352 "MAKEFLAGS",
353 "MAKELEVEL",
354 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700355
356 // Set in envsetup.sh, reset in makefiles
357 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700358
359 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
360 "ANDROID_BUILD_TOP",
361 "ANDROID_HOST_OUT",
362 "ANDROID_PRODUCT_OUT",
363 "ANDROID_HOST_OUT_TESTCASES",
364 "ANDROID_TARGET_OUT_TESTCASES",
365 "ANDROID_TOOLCHAIN",
366 "ANDROID_TOOLCHAIN_2ND_ARCH",
367 "ANDROID_DEV_SCRIPTS",
368 "ANDROID_EMULATOR_PREBUILTS",
369 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700370 )
371
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400372 if ret.UseGoma() || ret.ForceUseGoma() {
373 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
374 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400375 }
376
Dan Willemsen1e704462016-08-21 15:17:17 -0700377 // Tell python not to spam the source tree with .pyc files.
378 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
379
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400380 tmpDir := absPath(ctx, ret.TempDir())
381 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800382
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700383 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
384 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
385 "llvm-binutils-stable/llvm-symbolizer")
386 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
387
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800388 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700389 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800390
Yu Liu6e13b402021-07-27 14:29:06 -0700391 srcDir := absPath(ctx, ".")
392 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700393 ctx.Println("You are building in a directory whose absolute path contains a space character:")
394 ctx.Println()
395 ctx.Printf("%q\n", srcDir)
396 ctx.Println()
397 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700398 }
399
Yu Liu6e13b402021-07-27 14:29:06 -0700400 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
401
Dan Willemsendb8457c2017-05-12 16:38:17 -0700402 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700403 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
404 ctx.Println()
405 ctx.Printf("%q\n", outDir)
406 ctx.Println()
407 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700408 }
409
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000410 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700411 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
412 ctx.Println()
413 ctx.Printf("%q\n", distDir)
414 ctx.Println()
415 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700416 }
417
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700418 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000419 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
420 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100421 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Colin Cross59c1e6a2022-03-04 13:37:19 -0800422 java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700423 javaHome := func() string {
424 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
425 return override
426 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000427 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
428 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 +0100429 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000430 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
431 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
432 }
433 return java17Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700434 }()
435 absJavaHome := absPath(ctx, javaHome)
436
Dan Willemsened869522018-01-08 14:58:46 -0800437 ret.configureLocale(ctx)
438
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700439 newPath := []string{filepath.Join(absJavaHome, "bin")}
440 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
441 newPath = append(newPath, path)
442 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100443
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700444 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
445 ret.environ.Set("JAVA_HOME", absJavaHome)
446 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000447 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
448 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100449 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700450 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
451
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800452 outDir := ret.OutDir()
453 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800454 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800455 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800456 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800457 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800458 }
Colin Cross28f527c2019-11-26 16:19:04 -0800459
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800460 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
461
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400462 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400463 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400464 ret.environ.Set(k, v)
465 }
466 }
467
Patrice Arruda83842d72020-12-08 19:42:08 +0000468 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800469 if err := os.RemoveAll(bpd); err != nil {
470 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
471 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000472
Patrice Arruda96850362020-08-11 20:41:11 +0000473 c := Config{ret}
474 storeConfigMetrics(ctx, c)
475 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700476}
477
Patrice Arruda13848222019-04-22 17:12:02 -0700478// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
479// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700480func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
481 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700482}
483
Patrice Arruda96850362020-08-11 20:41:11 +0000484// storeConfigMetrics selects a set of configuration information and store in
485// the metrics system for further analysis.
486func storeConfigMetrics(ctx Context, config Config) {
487 if ctx.Metrics == nil {
488 return
489 }
490
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400491 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000492
493 s := &smpb.SystemResourceInfo{
494 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
495 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
496 }
497 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000498}
499
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400500func buildConfig(config Config) *smpb.BuildConfig {
Yu Liue737a992021-10-04 13:21:41 -0700501 c := &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -0400502 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
503 UseGoma: proto.Bool(config.UseGoma()),
504 UseRbe: proto.Bool(config.UseRBE()),
505 BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
506 ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400507 }
Yu Liue737a992021-10-04 13:21:41 -0700508 c.Targets = append(c.Targets, config.arguments...)
509
510 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400511}
512
Patrice Arruda13848222019-04-22 17:12:02 -0700513// getConfigArgs processes the command arguments based on the build action and creates a set of new
514// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700515func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700516 // The next block of code verifies that the current directory is the root directory of the source
517 // tree. It then finds the relative path of dir based on the root directory of the source tree
518 // and verify that dir is inside of the source tree.
519 checkTopDir(ctx)
520 topDir, err := os.Getwd()
521 if err != nil {
522 ctx.Fatalf("Error retrieving top directory: %v", err)
523 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700524 dir, err = filepath.EvalSymlinks(dir)
525 if err != nil {
526 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
527 }
Patrice Arruda13848222019-04-22 17:12:02 -0700528 dir, err = filepath.Abs(dir)
529 if err != nil {
530 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
531 }
532 relDir, err := filepath.Rel(topDir, dir)
533 if err != nil {
534 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
535 }
536 // If there are ".." in the path, it's not in the source tree.
537 if strings.Contains(relDir, "..") {
538 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
539 }
540
541 configArgs := args[:]
542
543 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
544 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
545 targetNamePrefix := "MODULES-IN-"
546 if inList("GET-INSTALL-PATH", configArgs) {
547 targetNamePrefix = "GET-INSTALL-PATH-IN-"
548 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
549 }
550
Patrice Arruda13848222019-04-22 17:12:02 -0700551 var targets []string
552
553 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700554 case BUILD_MODULES:
555 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700556 case BUILD_MODULES_IN_A_DIRECTORY:
557 // If dir is the root source tree, all the modules are built of the source tree are built so
558 // no need to find the build file.
559 if topDir == dir {
560 break
561 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700562
Patrice Arruda13848222019-04-22 17:12:02 -0700563 buildFile := findBuildFile(ctx, relDir)
564 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700565 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700566 }
Patrice Arruda13848222019-04-22 17:12:02 -0700567 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
568 case BUILD_MODULES_IN_DIRECTORIES:
569 newConfigArgs, dirs := splitArgs(configArgs)
570 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700571 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700572 }
573
574 // Tidy only override all other specified targets.
575 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
576 if tidyOnly == "true" || tidyOnly == "1" {
577 configArgs = append(configArgs, "tidy_only")
578 } else {
579 configArgs = append(configArgs, targets...)
580 }
581
582 return configArgs
583}
584
585// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
586func convertToTarget(dir string, targetNamePrefix string) string {
587 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
588}
589
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700590// hasBuildFile returns true if dir contains an Android build file.
591func hasBuildFile(ctx Context, dir string) bool {
592 for _, buildFile := range buildFiles {
593 _, err := os.Stat(filepath.Join(dir, buildFile))
594 if err == nil {
595 return true
596 }
597 if !os.IsNotExist(err) {
598 ctx.Fatalf("Error retrieving the build file stats: %v", err)
599 }
600 }
601 return false
602}
603
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700604// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
605// in the current and any sub directory of dir. If a build file is not found, traverse the path
606// up by one directory and repeat again until either a build file is found or reached to the root
607// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
608// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700609func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700610 // If the string is empty or ".", assume it is top directory of the source tree.
611 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700612 return ""
613 }
614
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700615 found := false
616 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
617 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
618 if err != nil {
619 return err
620 }
621 if found {
622 return filepath.SkipDir
623 }
624 if info.IsDir() {
625 return nil
626 }
627 for _, buildFile := range buildFiles {
628 if info.Name() == buildFile {
629 found = true
630 return filepath.SkipDir
631 }
632 }
633 return nil
634 })
635 if err != nil {
636 ctx.Fatalf("Error finding Android build file: %v", err)
637 }
638
639 if found {
640 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700641 }
642 }
643
644 return ""
645}
646
647// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
648func splitArgs(args []string) (newArgs []string, dirs []string) {
649 specialArgs := map[string]bool{
650 "showcommands": true,
651 "snod": true,
652 "dist": true,
653 "checkbuild": true,
654 }
655
656 newArgs = []string{}
657 dirs = []string{}
658
659 for _, arg := range args {
660 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
661 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
662 newArgs = append(newArgs, arg)
663 continue
664 }
665
666 if _, ok := specialArgs[arg]; ok {
667 newArgs = append(newArgs, arg)
668 continue
669 }
670
671 dirs = append(dirs, arg)
672 }
673
674 return newArgs, dirs
675}
676
677// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
678// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
679// source root tree where the build action command was invoked. Each directory is validated if the
680// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700681func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700682 for _, dir := range dirs {
683 // The directory may have specified specific modules to build. ":" is the separator to separate
684 // the directory and the list of modules.
685 s := strings.Split(dir, ":")
686 l := len(s)
687 if l > 2 { // more than one ":" was specified.
688 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
689 }
690
691 dir = filepath.Join(relDir, s[0])
692 if _, err := os.Stat(dir); err != nil {
693 ctx.Fatalf("couldn't find directory %s", dir)
694 }
695
696 // Verify that if there are any targets specified after ":". Each target is separated by ",".
697 var newTargets []string
698 if l == 2 && s[1] != "" {
699 newTargets = strings.Split(s[1], ",")
700 if inList("", newTargets) {
701 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
702 }
703 }
704
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700705 // If there are specified targets to build in dir, an android build file must exist for the one
706 // shot build. For the non-targets case, find the appropriate build file and build all the
707 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700708 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700709 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700710 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
711 }
712 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700713 buildFile := findBuildFile(ctx, dir)
714 if buildFile == "" {
715 ctx.Fatalf("Build file not found for %s directory", dir)
716 }
717 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700718 }
719
Patrice Arruda13848222019-04-22 17:12:02 -0700720 targets = append(targets, newTargets...)
721 }
722
Dan Willemsence41e942019-07-29 23:39:30 -0700723 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700724}
725
Dan Willemsen9b587492017-07-10 22:13:00 -0700726func (c *configImpl) parseArgs(ctx Context, args []string) {
727 for i := 0; i < len(args); i++ {
728 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100729 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700730 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200731 } else if arg == "--empty-ninja-file" {
732 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100733 } else if arg == "--skip-ninja" {
734 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700735 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700736 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
737 // but it does run a Kati ninja file if the .kati_enabled marker file was created
738 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000739 c.skipConfig = true
740 c.skipKati = true
741 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100742 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000743 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100744 } else if arg == "--soong-only" {
745 c.skipKati = true
746 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200747 } else if arg == "--config-only" {
748 c.skipKati = true
749 c.skipKatiNinja = true
750 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700751 } else if arg == "--skip-config" {
752 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700753 } else if arg == "--skip-soong-tests" {
754 c.skipSoongTests = true
MarkDacekd0e7cd32022-12-02 22:22:40 +0000755 } else if arg == "--skip-metrics-upload" {
756 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500757 } else if arg == "--mk-metrics" {
758 c.reportMkMetrics = true
Chris Parsonsef615e52022-08-18 22:04:11 -0400759 } else if arg == "--bazel-mode" {
760 c.bazelProdMode = true
761 } else if arg == "--bazel-mode-dev" {
762 c.bazelDevMode = true
MarkDacekb78465d2022-10-18 20:10:16 +0000763 } else if arg == "--bazel-mode-staging" {
764 c.bazelStagingMode = true
Spandan Das394aa322022-11-03 17:02:10 +0000765 } else if arg == "--search-api-dir" {
766 c.searchApiDir = true
MarkDacekb96561e2022-12-02 04:34:43 +0000767 } else if strings.HasPrefix(arg, "--build-command=") {
768 buildCmd := strings.TrimPrefix(arg, "--build-command=")
769 // remove quotations
770 buildCmd = strings.TrimPrefix(buildCmd, "\"")
771 buildCmd = strings.TrimSuffix(buildCmd, "\"")
772 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacekd06db5d2022-11-29 00:47:59 +0000773 } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
774 c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
MarkDacek6614d9c2022-12-07 21:57:38 +0000775 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
776 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
777 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
778 if err == nil {
779 c.buildStartedTime = val
780 } else {
781 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
782 }
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700783 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700784 parseArgNum := func(def int) int {
785 if len(arg) > 2 {
786 p, err := strconv.ParseUint(arg[2:], 10, 31)
787 if err != nil {
788 ctx.Fatalf("Failed to parse %q: %v", arg, err)
789 }
790 return int(p)
791 } else if i+1 < len(args) {
792 p, err := strconv.ParseUint(args[i+1], 10, 31)
793 if err == nil {
794 i++
795 return int(p)
796 }
797 }
798 return def
799 }
800
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700801 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700802 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700803 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700804 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700805 } else {
806 ctx.Fatalln("Unknown option:", arg)
807 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700808 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700809 if k == "OUT_DIR" {
810 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
811 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700812 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700813 } else if arg == "dist" {
814 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200815 } else if arg == "json-module-graph" {
816 c.jsonModuleGraph = true
817 } else if arg == "bp2build" {
818 c.bp2build = true
Spandan Das5af0bd32022-09-28 20:43:08 +0000819 } else if arg == "api_bp2build" {
820 c.apiBp2build = true
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200821 } else if arg == "queryview" {
822 c.queryview = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200823 } else if arg == "soong_docs" {
824 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700825 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700826 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800827 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700828 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700829 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700830 }
831 }
Chris Parsonsb6e96902022-10-31 20:08:45 -0400832 if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
833 c.bazelProdMode = defaultBazelProdMode(c)
834 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700835}
836
Dan Willemsened869522018-01-08 14:58:46 -0800837func (c *configImpl) configureLocale(ctx Context) {
838 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
839 output, err := cmd.Output()
840
841 var locales []string
842 if err == nil {
843 locales = strings.Split(string(output), "\n")
844 } else {
845 // If we're unable to list the locales, let's assume en_US.UTF-8
846 locales = []string{"en_US.UTF-8"}
847 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
848 }
849
850 // gettext uses LANGUAGE, which is passed directly through
851
852 // For LANG and LC_*, only preserve the evaluated version of
853 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800854 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800855 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800856 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800857 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800858 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800859 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800860 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800861 }
862
863 c.environ.UnsetWithPrefix("LC_")
864
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800865 if userLang != "" {
866 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800867 }
868
869 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
870 // for others)
871 if inList("C.UTF-8", locales) {
872 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500873 } else if inList("C.utf8", locales) {
874 // These normalize to the same thing
875 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800876 } else if inList("en_US.UTF-8", locales) {
877 c.environ.Set("LANG", "en_US.UTF-8")
878 } else if inList("en_US.utf8", locales) {
879 // These normalize to the same thing
880 c.environ.Set("LANG", "en_US.UTF-8")
881 } else {
882 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
883 }
884}
885
Dan Willemsen1e704462016-08-21 15:17:17 -0700886func (c *configImpl) Environment() *Environment {
887 return c.environ
888}
889
890func (c *configImpl) Arguments() []string {
891 return c.arguments
892}
893
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200894func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200895 if len(c.Arguments()) > 0 {
896 // Explicit targets requested that are not special targets like b2pbuild
897 // or the JSON module graph
898 return true
899 }
900
Spandan Das5af0bd32022-09-28 20:43:08 +0000901 if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200902 // Command line was empty, the default Ninja target is built
903 return true
904 }
905
Liz Kammer88677422021-12-15 15:03:19 -0500906 // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
907 if c.Dist() && !c.Bp2Build() {
908 return true
909 }
910
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200911 // build.ninja doesn't need to be generated
912 return false
913}
914
Dan Willemsen1e704462016-08-21 15:17:17 -0700915func (c *configImpl) OutDir() string {
916 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700917 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700918 }
919 return "out"
920}
921
Dan Willemsen8a073a82017-02-04 17:30:44 -0800922func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -0400923 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000924}
925
926func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700927 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800928}
929
Dan Willemsen1e704462016-08-21 15:17:17 -0700930func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000931 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700932 return c.arguments
933 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700934 return c.ninjaArgs
935}
936
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500937func (c *configImpl) BazelOutDir() string {
938 return filepath.Join(c.OutDir(), "bazel")
939}
940
Liz Kammer2af5ea82022-11-11 14:21:03 -0500941func (c *configImpl) bazelOutputBase() string {
942 return filepath.Join(c.BazelOutDir(), "output")
943}
944
Dan Willemsen1e704462016-08-21 15:17:17 -0700945func (c *configImpl) SoongOutDir() string {
946 return filepath.Join(c.OutDir(), "soong")
947}
948
Spandan Das394aa322022-11-03 17:02:10 +0000949func (c *configImpl) ApiSurfacesOutDir() string {
950 return filepath.Join(c.OutDir(), "api_surfaces")
951}
952
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200953func (c *configImpl) PrebuiltOS() string {
954 switch runtime.GOOS {
955 case "linux":
956 return "linux-x86"
957 case "darwin":
958 return "darwin-x86"
959 default:
960 panic("Unknown GOOS")
961 }
962}
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100963
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200964func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -0700965 if c.SkipKatiNinja() {
966 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
967 } else {
968 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
969 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200970}
971
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200972func (c *configImpl) NamedGlobFile(name string) string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100973 return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200974}
975
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +0200976func (c *configImpl) UsedEnvFile(tag string) string {
977 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
978}
979
Lukacs T. Berkic541cd22022-10-26 07:26:50 +0000980func (c *configImpl) Bp2BuildFilesMarkerFile() string {
981 return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
982}
983
984func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100985 return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +0200986}
987
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200988func (c *configImpl) SoongDocsHtml() string {
989 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
990}
991
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200992func (c *configImpl) QueryviewMarkerFile() string {
993 return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
994}
995
Spandan Das5af0bd32022-09-28 20:43:08 +0000996func (c *configImpl) ApiBp2buildMarkerFile() string {
997 return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
998}
999
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001000func (c *configImpl) ModuleGraphFile() string {
1001 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1002}
1003
kgui67007242022-01-25 13:50:25 +08001004func (c *configImpl) ModuleActionsFile() string {
1005 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1006}
1007
Jeff Gastonefc1b412017-03-29 17:29:06 -07001008func (c *configImpl) TempDir() string {
1009 return shared.TempDirForOutDir(c.SoongOutDir())
1010}
1011
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001012func (c *configImpl) FileListDir() string {
1013 return filepath.Join(c.OutDir(), ".module_paths")
1014}
1015
Dan Willemsen1e704462016-08-21 15:17:17 -07001016func (c *configImpl) KatiSuffix() string {
1017 if c.katiSuffix != "" {
1018 return c.katiSuffix
1019 }
1020 panic("SetKatiSuffix has not been called")
1021}
1022
Colin Cross37193492017-11-16 17:55:00 -08001023// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1024// user is interested in additional checks at the expense of build time.
1025func (c *configImpl) Checkbuild() bool {
1026 return c.checkbuild
1027}
1028
Dan Willemsen8a073a82017-02-04 17:30:44 -08001029func (c *configImpl) Dist() bool {
1030 return c.dist
1031}
1032
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001033func (c *configImpl) JsonModuleGraph() bool {
1034 return c.jsonModuleGraph
1035}
1036
1037func (c *configImpl) Bp2Build() bool {
1038 return c.bp2build
1039}
1040
Spandan Das5af0bd32022-09-28 20:43:08 +00001041func (c *configImpl) ApiBp2build() bool {
1042 return c.apiBp2build
1043}
1044
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001045func (c *configImpl) Queryview() bool {
1046 return c.queryview
1047}
1048
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001049func (c *configImpl) SoongDocs() bool {
1050 return c.soongDocs
1051}
1052
Dan Willemsen1e704462016-08-21 15:17:17 -07001053func (c *configImpl) IsVerbose() bool {
1054 return c.verbose
1055}
1056
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001057func (c *configImpl) SkipKati() bool {
1058 return c.skipKati
1059}
1060
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001061func (c *configImpl) SkipKatiNinja() bool {
1062 return c.skipKatiNinja
1063}
1064
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001065func (c *configImpl) SkipSoong() bool {
1066 return c.skipSoong
1067}
1068
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001069func (c *configImpl) SkipNinja() bool {
1070 return c.skipNinja
1071}
1072
Anton Hansson5a7861a2021-06-04 10:09:01 +01001073func (c *configImpl) SetSkipNinja(v bool) {
1074 c.skipNinja = v
1075}
1076
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001077func (c *configImpl) SkipConfig() bool {
1078 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001079}
1080
Dan Willemsen1e704462016-08-21 15:17:17 -07001081func (c *configImpl) TargetProduct() string {
1082 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1083 return v
1084 }
1085 panic("TARGET_PRODUCT is not defined")
1086}
1087
Dan Willemsen02781d52017-05-12 19:28:13 -07001088func (c *configImpl) TargetDevice() string {
1089 return c.targetDevice
1090}
1091
1092func (c *configImpl) SetTargetDevice(device string) {
1093 c.targetDevice = device
1094}
1095
1096func (c *configImpl) TargetBuildVariant() string {
1097 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1098 return v
1099 }
1100 panic("TARGET_BUILD_VARIANT is not defined")
1101}
1102
Dan Willemsen1e704462016-08-21 15:17:17 -07001103func (c *configImpl) KatiArgs() []string {
1104 return c.katiArgs
1105}
1106
1107func (c *configImpl) Parallel() int {
1108 return c.parallel
1109}
1110
Spandan Dasc5763832022-11-08 18:42:16 +00001111func (c *configImpl) GetIncludeTags() []string {
1112 return c.includeTags
1113}
1114
1115func (c *configImpl) SetIncludeTags(i []string) {
1116 c.includeTags = i
1117}
1118
MarkDacek6614d9c2022-12-07 21:57:38 +00001119func (c *configImpl) GetLogsPrefix() string {
1120 return c.logsPrefix
1121}
1122
1123func (c *configImpl) SetLogsPrefix(prefix string) {
1124 c.logsPrefix = prefix
1125}
1126
Colin Cross8b8bec32019-11-15 13:18:43 -08001127func (c *configImpl) HighmemParallel() int {
1128 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1129 return i
1130 }
1131
1132 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1133 parallel := c.Parallel()
1134 if c.UseRemoteBuild() {
1135 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1136 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1137 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1138 // Return 1/16th of the size of the local pool, rounding up.
1139 return (parallel + 15) / 16
1140 } else if c.totalRAM == 0 {
1141 // Couldn't detect the total RAM, don't restrict highmem processes.
1142 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001143 } else if c.totalRAM <= 16*1024*1024*1024 {
1144 // Less than 16GB of ram, restrict to 1 highmem processes
1145 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001146 } else if c.totalRAM <= 32*1024*1024*1024 {
1147 // Less than 32GB of ram, restrict to 2 highmem processes
1148 return 2
1149 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1150 // If less than 8GB total RAM per process, reduce the number of highmem processes
1151 return p
1152 }
1153 // No restriction on highmem processes
1154 return parallel
1155}
1156
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001157func (c *configImpl) TotalRAM() uint64 {
1158 return c.totalRAM
1159}
1160
Kousik Kumarec478642020-09-21 13:39:24 -04001161// ForceUseGoma determines whether we should override Goma deprecation
1162// and use Goma for the current build or not.
1163func (c *configImpl) ForceUseGoma() bool {
1164 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1165 v = strings.TrimSpace(v)
1166 if v != "" && v != "false" {
1167 return true
1168 }
1169 }
1170 return false
1171}
1172
Dan Willemsen1e704462016-08-21 15:17:17 -07001173func (c *configImpl) UseGoma() bool {
1174 if v, ok := c.environ.Get("USE_GOMA"); ok {
1175 v = strings.TrimSpace(v)
1176 if v != "" && v != "false" {
1177 return true
1178 }
1179 }
1180 return false
1181}
1182
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001183func (c *configImpl) StartGoma() bool {
1184 if !c.UseGoma() {
1185 return false
1186 }
1187
1188 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1189 v = strings.TrimSpace(v)
1190 if v != "" && v != "false" {
1191 return false
1192 }
1193 }
1194 return true
1195}
1196
Ramy Medhatbbf25672019-07-17 12:30:04 +00001197func (c *configImpl) UseRBE() bool {
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001198 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001199 v = strings.TrimSpace(v)
1200 if v != "" && v != "false" {
1201 return true
1202 }
1203 }
1204 return false
1205}
1206
Chris Parsonsef615e52022-08-18 22:04:11 -04001207func (c *configImpl) BazelBuildEnabled() bool {
MarkDacekb78465d2022-10-18 20:10:16 +00001208 return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
Chris Parsonsec1a3dc2021-04-20 15:32:07 -04001209}
1210
Ramy Medhatbbf25672019-07-17 12:30:04 +00001211func (c *configImpl) StartRBE() bool {
1212 if !c.UseRBE() {
1213 return false
1214 }
1215
1216 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1217 v = strings.TrimSpace(v)
1218 if v != "" && v != "false" {
1219 return false
1220 }
1221 }
1222 return true
1223}
1224
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001225func (c *configImpl) rbeProxyLogsDir() string {
1226 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001227 if v, ok := c.environ.Get(f); ok {
1228 return v
1229 }
1230 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001231 buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
1232 return filepath.Join(buildTmpDir, "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001233}
1234
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001235func (c *configImpl) shouldCleanupRBELogsDir() bool {
1236 // Perform a log directory cleanup only when the log directory
1237 // is auto created by the build rather than user-specified.
1238 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
1239 if _, ok := c.environ.Get(f); ok {
1240 return false
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001241 }
1242 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001243 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001244}
1245
1246func (c *configImpl) rbeExecRoot() string {
1247 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1248 if v, ok := c.environ.Get(f); ok {
1249 return v
1250 }
1251 }
1252 wd, err := os.Getwd()
1253 if err != nil {
1254 return ""
1255 }
1256 return wd
1257}
1258
1259func (c *configImpl) rbeDir() string {
1260 if v, ok := c.environ.Get("RBE_DIR"); ok {
1261 return v
1262 }
1263 return "prebuilts/remoteexecution-client/live/"
1264}
1265
1266func (c *configImpl) rbeReproxy() string {
1267 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1268 if v, ok := c.environ.Get(f); ok {
1269 return v
1270 }
1271 }
1272 return filepath.Join(c.rbeDir(), "reproxy")
1273}
1274
1275func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001276 credFlags := []string{
1277 "use_application_default_credentials",
1278 "use_gce_credentials",
1279 "credential_file",
1280 "use_google_prod_creds",
1281 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001282 for _, cf := range credFlags {
1283 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1284 if v, ok := c.environ.Get(f); ok {
1285 v = strings.TrimSpace(v)
1286 if v != "" && v != "false" && v != "0" {
1287 return "RBE_" + cf, v
1288 }
1289 }
1290 }
1291 }
1292 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001293}
1294
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001295func (c *configImpl) rbeSockAddr(dir string) (string, error) {
1296 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
1297 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1298
1299 name := filepath.Join(dir, base)
1300 if len(name) < maxNameLen {
1301 return name, nil
1302 }
1303
1304 name = filepath.Join("/tmp", base)
1305 if len(name) < maxNameLen {
1306 return name, nil
1307 }
1308
1309 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1310}
1311
Kousik Kumar7bc78192022-04-27 14:52:56 -04001312// IsGooglerEnvironment returns true if the current build is running
1313// on a Google developer machine and false otherwise.
1314func (c *configImpl) IsGooglerEnvironment() bool {
1315 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1316 if v, ok := c.environ.Get(cf); ok {
1317 return v == "googler"
1318 }
1319 return false
1320}
1321
1322// GoogleProdCredsExist determine whether credentials exist on the
1323// Googler machine to use remote execution.
1324func (c *configImpl) GoogleProdCredsExist() bool {
1325 if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
1326 return false
1327 }
1328 return true
1329}
1330
1331// UseRemoteBuild indicates whether to use a remote build acceleration system
1332// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001333func (c *configImpl) UseRemoteBuild() bool {
1334 return c.UseGoma() || c.UseRBE()
1335}
1336
Kousik Kumar7bc78192022-04-27 14:52:56 -04001337// StubbyExists checks whether the stubby binary exists on the machine running
1338// the build.
1339func (c *configImpl) StubbyExists() bool {
1340 if _, err := exec.LookPath("stubby"); err != nil {
1341 return false
1342 }
1343 return true
1344}
1345
Dan Willemsen1e704462016-08-21 15:17:17 -07001346// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001347// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001348// still limited by Parallel()
1349func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001350 if !c.UseRemoteBuild() {
1351 return 0
1352 }
1353 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1354 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001355 }
1356 return 500
1357}
1358
1359func (c *configImpl) SetKatiArgs(args []string) {
1360 c.katiArgs = args
1361}
1362
1363func (c *configImpl) SetNinjaArgs(args []string) {
1364 c.ninjaArgs = args
1365}
1366
1367func (c *configImpl) SetKatiSuffix(suffix string) {
1368 c.katiSuffix = suffix
1369}
1370
Dan Willemsene0879fc2017-08-04 15:06:27 -07001371func (c *configImpl) LastKatiSuffixFile() string {
1372 return filepath.Join(c.OutDir(), "last_kati_suffix")
1373}
1374
1375func (c *configImpl) HasKatiSuffix() bool {
1376 return c.katiSuffix != ""
1377}
1378
Dan Willemsen1e704462016-08-21 15:17:17 -07001379func (c *configImpl) KatiEnvFile() string {
1380 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1381}
1382
Dan Willemsen29971232018-09-26 14:58:30 -07001383func (c *configImpl) KatiBuildNinjaFile() string {
1384 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001385}
1386
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001387func (c *configImpl) KatiPackageNinjaFile() string {
1388 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1389}
1390
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001391func (c *configImpl) SoongVarsFile() string {
1392 return filepath.Join(c.SoongOutDir(), "soong.variables")
1393}
1394
Dan Willemsen1e704462016-08-21 15:17:17 -07001395func (c *configImpl) SoongNinjaFile() string {
1396 return filepath.Join(c.SoongOutDir(), "build.ninja")
1397}
1398
1399func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001400 if c.katiSuffix == "" {
1401 return filepath.Join(c.OutDir(), "combined.ninja")
1402 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001403 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1404}
1405
1406func (c *configImpl) SoongAndroidMk() string {
1407 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1408}
1409
1410func (c *configImpl) SoongMakeVarsMk() string {
1411 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1412}
1413
Dan Willemsenf052f782017-05-18 15:29:04 -07001414func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001415 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001416}
1417
Dan Willemsen02781d52017-05-12 19:28:13 -07001418func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001419 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1420}
1421
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001422func (c *configImpl) KatiPackageMkDir() string {
1423 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1424}
1425
Dan Willemsenf052f782017-05-18 15:29:04 -07001426func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001427 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001428}
1429
1430func (c *configImpl) HostOut() string {
1431 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1432}
1433
1434// This probably needs to be multi-valued, so not exporting it for now
1435func (c *configImpl) hostCrossOut() string {
1436 if runtime.GOOS == "linux" {
1437 return filepath.Join(c.hostOutRoot(), "windows-x86")
1438 } else {
1439 return ""
1440 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001441}
1442
Dan Willemsen1e704462016-08-21 15:17:17 -07001443func (c *configImpl) HostPrebuiltTag() string {
1444 if runtime.GOOS == "linux" {
1445 return "linux-x86"
1446 } else if runtime.GOOS == "darwin" {
1447 return "darwin-x86"
1448 } else {
1449 panic("Unsupported OS")
1450 }
1451}
Dan Willemsenf173d592017-04-27 14:28:00 -07001452
Dan Willemsen8122bd52017-10-12 20:20:41 -07001453func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001454 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1455 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001456 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1457 if _, err := os.Stat(asan); err == nil {
1458 return asan
1459 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001460 }
1461 }
1462 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1463}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001464
1465func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1466 c.brokenDupRules = val
1467}
1468
1469func (c *configImpl) BuildBrokenDupRules() bool {
1470 return c.brokenDupRules
1471}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001472
Dan Willemsen25e6f092019-04-09 10:22:43 -07001473func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1474 c.brokenUsesNetwork = val
1475}
1476
1477func (c *configImpl) BuildBrokenUsesNetwork() bool {
1478 return c.brokenUsesNetwork
1479}
1480
Dan Willemsene3336352020-01-02 19:10:38 -08001481func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1482 c.brokenNinjaEnvVars = val
1483}
1484
1485func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1486 return c.brokenNinjaEnvVars
1487}
1488
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001489func (c *configImpl) SetTargetDeviceDir(dir string) {
1490 c.targetDeviceDir = dir
1491}
1492
1493func (c *configImpl) TargetDeviceDir() string {
1494 return c.targetDeviceDir
1495}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001496
Patrice Arruda219eef32020-06-01 17:29:30 +00001497func (c *configImpl) BuildDateTime() string {
1498 return c.buildDateTime
1499}
1500
1501func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001502 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001503}
Patrice Arruda83842d72020-12-08 19:42:08 +00001504
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001505// LogsDir returns the absolute path to the logs directory where build log and
1506// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001507// directory. If the argument dist is specified, the logs directory
1508// is <dist_dir>/logs.
1509func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001510 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001511 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001512 // 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 -05001513 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001514 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001515 absDir, err := filepath.Abs(dir)
1516 if err != nil {
1517 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1518 os.Exit(1)
1519 }
1520 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001521}
1522
1523// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1524// where the bazel profiles are located.
1525func (c *configImpl) BazelMetricsDir() string {
1526 return filepath.Join(c.LogsDir(), "bazel_metrics")
1527}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001528
Chris Parsons53f68ae2022-03-03 12:01:40 -05001529// MkFileMetrics returns the file path for make-related metrics.
1530func (c *configImpl) MkMetrics() string {
1531 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1532}
1533
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001534func (c *configImpl) SetEmptyNinjaFile(v bool) {
1535 c.emptyNinjaFile = v
1536}
1537
1538func (c *configImpl) EmptyNinjaFile() bool {
1539 return c.emptyNinjaFile
1540}
Yu Liu6e13b402021-07-27 14:29:06 -07001541
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001542func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
1543 return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
1544}
1545
MarkDacekd06db5d2022-11-29 00:47:59 +00001546func (c *configImpl) BazelModulesForceEnabledByFlag() string {
1547 return c.bazelForceEnabledModules
1548}
1549
MarkDacekd0e7cd32022-12-02 22:22:40 +00001550func (c *configImpl) SkipMetricsUpload() bool {
1551 return c.skipMetricsUpload
1552}
1553
MarkDacek6614d9c2022-12-07 21:57:38 +00001554// Returns a Time object if one was passed via a command-line flag.
1555// Otherwise returns the passed default.
1556func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1557 if c.buildStartedTime == 0 {
1558 return defaultTime
1559 }
1560 return time.UnixMilli(c.buildStartedTime)
1561}
1562
Yu Liu6e13b402021-07-27 14:29:06 -07001563func GetMetricsUploader(topDir string, env *Environment) string {
1564 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1565 metricsUploader := filepath.Join(topDir, p)
1566 if _, err := os.Stat(metricsUploader); err == nil {
1567 return metricsUploader
1568 }
1569 }
1570
1571 return ""
1572}