blob: 84e4005669796357739feea0b7b18f6502fdffad [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 Kumar3ff037e2022-01-25 22:11:01 -050018 "encoding/json"
Jeongik Chaa87506f2023-06-01 23:16:41 +090019 "errors"
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"
Cole Faust583dfb42023-09-28 13:56:30 -070025 "os/user"
Dan Willemsen1e704462016-08-21 15:17:17 -070026 "path/filepath"
27 "runtime"
28 "strconv"
29 "strings"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040030 "syscall"
Nan Zhang2e6a4ff2018-02-14 13:27:26 -080031 "time"
Jeff Gastonefc1b412017-03-29 17:29:06 -070032
LaMont Jones54b01cd2024-10-23 13:59:40 -070033 "android/soong/finder/fs"
Jeff Gastonefc1b412017-03-29 17:29:06 -070034 "android/soong/shared"
LaMont Jones9a912862023-11-06 22:11:08 +000035 "android/soong/ui/metrics"
Kousik Kumarec478642020-09-21 13:39:24 -040036
Dan Willemsen4591b642021-05-24 14:24:12 -070037 "google.golang.org/protobuf/proto"
Patrice Arruda96850362020-08-11 20:41:11 +000038
39 smpb "android/soong/ui/metrics/metrics_proto"
Dan Willemsen1e704462016-08-21 15:17:17 -070040)
41
Kousik Kumar3ff037e2022-01-25 22:11:01 -050042const (
Chris Parsons53f68ae2022-03-03 12:01:40 -050043 envConfigDir = "vendor/google/tools/soong_config"
44 jsonSuffix = "json"
Taylor Santiago8b0bed72024-09-03 13:30:22 -070045 abfsSrcDir = "/src"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050046)
47
Kousik Kumar4c180ad2022-05-27 07:48:37 -040048var (
Kevin Dagostino096ab2f2023-03-03 19:47:17 +000049 rbeRandPrefix int
50 googleProdCredsExistCache bool
Kousik Kumar4c180ad2022-05-27 07:48:37 -040051)
52
53func init() {
54 rand.Seed(time.Now().UnixNano())
55 rbeRandPrefix = rand.Intn(1000)
56}
57
LaMont Jonesece626c2024-09-03 11:19:31 -070058// Which builder are we using?
59type ninjaCommandType = int
60
61const (
62 _ = iota
63 NINJA_NINJA
64 NINJA_N2
65 NINJA_SISO
Taylor Santiago2fa40d02025-01-20 20:36:37 -080066 NINJA_NINJAGO
LaMont Jonesece626c2024-09-03 11:19:31 -070067)
68
Dan Willemsen1e704462016-08-21 15:17:17 -070069type Config struct{ *configImpl }
70
71type configImpl struct {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020072 // Some targets that are implemented in soong_build
Colin Cross28f527c2019-11-26 16:19:04 -080073 arguments []string
74 goma bool
75 environ *Environment
76 distDir string
77 buildDateTime string
MarkDacek6614d9c2022-12-07 21:57:38 +000078 logsPrefix string
Dan Willemsen1e704462016-08-21 15:17:17 -070079
80 // From the arguments
Cole Faust3740b282025-01-21 15:59:50 -080081 parallel int
82 keepGoing int
83 verbose bool
84 checkbuild bool
85 dist bool
86 jsonModuleGraph bool
87 reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
88 soongDocs bool
89 skipConfig bool
90 skipKati bool
91 skipKatiControlledByFlags bool
92 skipKatiNinja bool
93 skipSoong bool
94 skipNinja bool
95 skipSoongTests bool
96 searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
97 skipMetricsUpload bool
98 buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
99 buildFromSourceStub bool
100 incrementalBuildActions bool
101 ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
Dan Willemsen1e704462016-08-21 15:17:17 -0700102
103 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -0700104 katiArgs []string
105 ninjaArgs []string
106 katiSuffix string
107 targetDevice string
108 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +0000109 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -0700110
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800111 // Autodetected
LaMont Jones54b01cd2024-10-23 13:59:40 -0700112 totalRAM uint64
113 systemCpuInfo *metrics.CpuInfo
114 systemMemInfo *metrics.MemInfo
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800115
Spandan Das28a6f192024-07-01 21:00:25 +0000116 brokenDupRules bool
117 brokenUsesNetwork bool
118 brokenNinjaEnvVars []string
119 brokenMissingOutputs bool
Dan Willemsen18490112018-05-25 16:30:04 -0700120
121 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000122
Colin Crossf3bdbcb2021-06-01 11:43:55 -0700123 // Set by multiproduct_kati
124 emptyNinjaFile bool
Yu Liu6e13b402021-07-27 14:29:06 -0700125
126 metricsUploader string
MarkDacekd06db5d2022-11-29 00:47:59 +0000127
Sam Delmerico98a73292023-02-21 11:50:29 -0500128 includeTags []string
129 sourceRootDirs []string
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900130
131 // Data source to write ninja weight list
132 ninjaWeightListSource NinjaWeightListSource
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800133
134 // This file is a detailed dump of all soong-defined modules for debugging purposes.
135 // There's quite a bit of overlap with module-info.json and soong module graph. We
136 // could consider merging them.
137 moduleDebugFile string
Cole Faustbee030d2024-01-03 13:45:48 -0800138
LaMont Jonesece626c2024-09-03 11:19:31 -0700139 // Which builder are we using
140 ninjaCommand ninjaCommandType
Dan Willemsen1e704462016-08-21 15:17:17 -0700141}
142
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900143type NinjaWeightListSource uint
144
145const (
146 // ninja doesn't use weight list.
147 NOT_USED NinjaWeightListSource = iota
148 // ninja uses weight list based on previous builds by ninja log
149 NINJA_LOG
150 // ninja thinks every task has the same weight.
151 EVENLY_DISTRIBUTED
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900152 // ninja uses an external custom weight list
153 EXTERNAL_FILE
Jeongik Chae114e602023-03-19 00:12:39 +0900154 // ninja uses a prioritized module list from Soong
155 HINT_FROM_SOONG
Jeongik Chaa87506f2023-06-01 23:16:41 +0900156 // If ninja log exists, use NINJA_LOG, if not, use HINT_FROM_SOONG instead.
157 // We can assume it is an incremental build if ninja log exists.
158 DEFAULT
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900159)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800160const srcDirFileCheck = "build/soong/root.bp"
161
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700162var buildFiles = []string{"Android.mk", "Android.bp"}
163
Patrice Arruda13848222019-04-22 17:12:02 -0700164type BuildAction uint
165
166const (
167 // Builds all of the modules and their dependencies of a specified directory, relative to the root
168 // directory of the source tree.
169 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
170
171 // Builds all of the modules and their dependencies of a list of specified directories. All specified
172 // directories are relative to the root directory of the source tree.
173 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700174
175 // Build a list of specified modules. If none was specified, simply build the whole source tree.
176 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700177)
178
179// checkTopDir validates that the current directory is at the root directory of the source tree.
180func checkTopDir(ctx Context) {
181 if _, err := os.Stat(srcDirFileCheck); err != nil {
182 if os.IsNotExist(err) {
183 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
184 }
185 ctx.Fatalln("Error verifying tree state:", err)
186 }
187}
188
MarkDacek7901e582023-01-09 19:48:01 +0000189func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500190 if bc == "" {
191 return nil
192 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500193
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500194 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500195 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500196 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500197 envConfigDir,
198 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500199 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500200 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
201 envVarsJSON, err := ioutil.ReadFile(cfgFile)
202 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500203 continue
204 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500205 ctx.Verbosef("Loading config file %v\n", cfgFile)
206 var envVars map[string]map[string]string
207 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
208 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
209 continue
210 }
211 for k, v := range envVars["env"] {
212 if os.Getenv(k) != "" {
213 continue
214 }
215 config.environ.Set(k, v)
216 }
217 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
218 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500219 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500220
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500221 return nil
222}
223
Dan Willemsen1e704462016-08-21 15:17:17 -0700224func NewConfig(ctx Context, args ...string) Config {
225 ret := &configImpl{
Jeongik Chaf2ecf762023-05-19 14:03:45 +0900226 environ: OsEnvironment(),
227 sandboxConfig: &SandboxConfig{},
Jeongik Chaa87506f2023-06-01 23:16:41 +0900228 ninjaWeightListSource: DEFAULT,
Dan Willemsen1e704462016-08-21 15:17:17 -0700229 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700230 wd, err := os.Getwd()
231 if err != nil {
232 ctx.Fatalln("Failed to get working directory:", err)
233 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700234
Colin Cross106d6ef2023-10-24 10:34:56 -0700235 // Skip soong tests by default on Linux
236 if runtime.GOOS == "linux" {
237 ret.skipSoongTests = true
238 }
239
Patrice Arruda90109172020-07-28 18:07:27 +0000240 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700241 ret.parallel = runtime.NumCPU() + 2
242 ret.keepGoing = 1
243
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800244 ret.totalRAM = detectTotalRAM(ctx)
LaMont Jones54b01cd2024-10-23 13:59:40 -0700245 ret.systemCpuInfo, err = metrics.NewCpuInfo(fs.OsFs)
246 if err != nil {
247 ctx.Fatalln("Failed to get cpuinfo:", err)
248 }
249 ret.systemMemInfo, err = metrics.NewMemInfo(fs.OsFs)
250 if err != nil {
251 ctx.Fatalln("Failed to get meminfo:", err)
252 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700253 ret.parseArgs(ctx, args)
Jeongik Chae114e602023-03-19 00:12:39 +0900254
255 if ret.ninjaWeightListSource == HINT_FROM_SOONG {
Jeongik Chaa87506f2023-06-01 23:16:41 +0900256 ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "always")
257 } else if ret.ninjaWeightListSource == DEFAULT {
258 defaultNinjaWeightListSource := NINJA_LOG
259 if _, err := os.Stat(filepath.Join(ret.OutDir(), ninjaLogFileName)); errors.Is(err, os.ErrNotExist) {
260 ctx.Verboseln("$OUT/.ninja_log doesn't exist, use HINT_FROM_SOONG instead")
261 defaultNinjaWeightListSource = HINT_FROM_SOONG
262 } else {
263 ctx.Verboseln("$OUT/.ninja_log exist, use NINJA_LOG")
264 }
265 ret.ninjaWeightListSource = defaultNinjaWeightListSource
266 // soong_build generates ninja hint depending on ninja log existence.
267 // Set it "depend" to avoid soong re-run due to env variable change.
268 ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "depend")
Jeongik Chae114e602023-03-19 00:12:39 +0900269 }
Jeongik Chaa87506f2023-06-01 23:16:41 +0900270
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800271 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700272 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700273 ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, filepath.Clean(outDir)))
Dan Willemsen02f3add2017-05-12 13:50:19 -0700274 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800275 outDir := "out"
276 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700277 outDir = filepath.Join(baseDir, filepath.Base(wd))
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800278 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700279 ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, outDir))
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800280 }
281
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500282 // loadEnvConfig needs to know what the OUT_DIR is, so it should
283 // be called after we determine the appropriate out directory.
MarkDacek7901e582023-01-09 19:48:01 +0000284 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
285
286 if bc != "" {
Kousik Kumarc8818332023-01-16 16:33:05 +0000287 if err := loadEnvConfig(ctx, ret, bc); err != nil {
MarkDacek7901e582023-01-09 19:48:01 +0000288 ctx.Fatalln("Failed to parse env config files: %v", err)
289 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +0000290 if !ret.canSupportRBE() {
291 // Explicitly set USE_RBE env variable to false when we cannot run
292 // an RBE build to avoid ninja local execution pool issues.
293 ret.environ.Set("USE_RBE", "false")
294 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500295 }
296
Dan Willemsen2d31a442018-10-20 21:33:41 -0700297 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
298 ret.distDir = filepath.Clean(distDir)
299 } else {
300 ret.distDir = filepath.Join(ret.OutDir(), "dist")
301 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700302
Spandan Das05063612021-06-25 01:39:04 +0000303 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
304 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
305 }
306
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800307 if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
308 ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
309 }
310
LaMont Jones99f18962024-10-17 11:50:44 -0700311 // If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
312 // This simplifies the generated Ninja rules, so that they only need to check for the empty string.
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800313 if value, ok := ret.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
LaMont Jones99f18962024-10-17 11:50:44 -0700314 if value == "true" || value == "1" || value == "y" || value == "yes" {
315 value = "true"
316 } else {
317 value = ""
318 }
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800319 ret.environ.Set("SOONG_USE_PARTIAL_COMPILE", value)
LaMont Jones99f18962024-10-17 11:50:44 -0700320 }
321
LaMont Jonesece626c2024-09-03 11:19:31 -0700322 ret.ninjaCommand = NINJA_NINJA
323 switch os.Getenv("SOONG_NINJA") {
324 case "n2":
325 ret.ninjaCommand = NINJA_N2
326 case "siso":
327 ret.ninjaCommand = NINJA_SISO
Taylor Santiago2fa40d02025-01-20 20:36:37 -0800328 case "ninjago":
329 ret.ninjaCommand = NINJA_NINJAGO
LaMont Jonesece626c2024-09-03 11:19:31 -0700330 default:
331 if os.Getenv("SOONG_USE_N2") == "true" {
332 ret.ninjaCommand = NINJA_N2
333 }
Cole Faustbee030d2024-01-03 13:45:48 -0800334 }
335
Dan Willemsen1e704462016-08-21 15:17:17 -0700336 ret.environ.Unset(
337 // We're already using it
338 "USE_SOONG_UI",
339
340 // We should never use GOROOT/GOPATH from the shell environment
341 "GOROOT",
342 "GOPATH",
343
344 // These should only come from Soong, not the environment.
345 "CLANG",
346 "CLANG_CXX",
347 "CCC_CC",
348 "CCC_CXX",
349
350 // Used by the goma compiler wrapper, but should only be set by
351 // gomacc
352 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800353
354 // We handle this above
355 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700356
Dan Willemsen2d31a442018-10-20 21:33:41 -0700357 // This is handled above too, and set for individual commands later
358 "DIST_DIR",
359
Dan Willemsen68a09852017-04-18 13:56:57 -0700360 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000361 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700362 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700363 "DISPLAY",
364 "GREP_OPTIONS",
Nathan Egge7b067fb2023-02-17 17:54:31 +0000365 "JAVAC",
Nathan Egge978c9342024-07-03 21:13:03 +0000366 "LEX",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700367 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700368 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700369
370 // Drop make flags
371 "MAKEFLAGS",
372 "MAKELEVEL",
373 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700374
375 // Set in envsetup.sh, reset in makefiles
376 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700377
378 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
379 "ANDROID_BUILD_TOP",
380 "ANDROID_HOST_OUT",
381 "ANDROID_PRODUCT_OUT",
382 "ANDROID_HOST_OUT_TESTCASES",
383 "ANDROID_TARGET_OUT_TESTCASES",
384 "ANDROID_TOOLCHAIN",
385 "ANDROID_TOOLCHAIN_2ND_ARCH",
386 "ANDROID_DEV_SCRIPTS",
387 "ANDROID_EMULATOR_PREBUILTS",
388 "ANDROID_PRE_BUILD_PATHS",
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800389
390 // We read it here already, don't let others share in the fun
391 "GENERATE_SOONG_DEBUG",
Cole Faustbee030d2024-01-03 13:45:48 -0800392
LaMont Jonesece626c2024-09-03 11:19:31 -0700393 // Use config.ninjaCommand instead.
394 "SOONG_NINJA",
Cole Faustbee030d2024-01-03 13:45:48 -0800395 "SOONG_USE_N2",
Dan Willemsen1e704462016-08-21 15:17:17 -0700396 )
397
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400398 if ret.UseGoma() || ret.ForceUseGoma() {
399 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
400 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400401 }
402
Dan Willemsen1e704462016-08-21 15:17:17 -0700403 // Tell python not to spam the source tree with .pyc files.
404 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
405
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400406 tmpDir := absPath(ctx, ret.TempDir())
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700407 ret.environ.Set("TMPDIR", ret.sandboxPath(wd, tmpDir))
Dan Willemsen32a669b2018-03-08 19:42:00 -0800408
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700409 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
410 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
411 "llvm-binutils-stable/llvm-symbolizer")
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700412 ret.environ.Set("ASAN_SYMBOLIZER_PATH", ret.sandboxPath(wd, absPath(ctx, symbolizerPath)))
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700413
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800414 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700415 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800416
Yu Liu6e13b402021-07-27 14:29:06 -0700417 srcDir := absPath(ctx, ".")
418 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700419 ctx.Println("You are building in a directory whose absolute path contains a space character:")
420 ctx.Println()
421 ctx.Printf("%q\n", srcDir)
422 ctx.Println()
423 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700424 }
425
Yu Liu6e13b402021-07-27 14:29:06 -0700426 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
427
Dan Willemsendb8457c2017-05-12 16:38:17 -0700428 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700429 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
430 ctx.Println()
431 ctx.Printf("%q\n", outDir)
432 ctx.Println()
433 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700434 }
435
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000436 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700437 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
438 ctx.Println()
439 ctx.Printf("%q\n", distDir)
440 ctx.Println()
441 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700442 }
443
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700444 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000445 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
Sorin Basca0760c892023-11-29 19:13:55 +0000446 java21Home := filepath.Join("prebuilts/jdk/jdk21", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700447 javaHome := func() string {
448 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
449 return override
450 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000451 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
Sorin Basca5dfa2382024-03-11 17:23:06 +0000452 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
Pete Gillin1f52e932019-10-09 17:10:08 +0100453 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000454 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
Sorin Basca5dfa2382024-03-11 17:23:06 +0000455 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
Sorin Basca7e094b32022-10-05 08:20:12 +0000456 }
Sorin Basca5dfa2382024-03-11 17:23:06 +0000457 if toolchain21, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN"); ok && toolchain21 != "true" {
458 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
459 }
460 return java21Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700461 }()
462 absJavaHome := absPath(ctx, javaHome)
463
Dan Willemsened869522018-01-08 14:58:46 -0800464 ret.configureLocale(ctx)
465
PODISHETTY KUMAR (xWF)9543d192024-09-02 03:54:36 +0000466 newPath := []string{filepath.Join(absJavaHome, "bin")}
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700467 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
PODISHETTY KUMAR (xWF)9543d192024-09-02 03:54:36 +0000468 newPath = append(newPath, path)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700469 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100470
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700471 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700472 ret.environ.Set("JAVA_HOME", ret.sandboxPath(wd, absJavaHome))
473 ret.environ.Set("ANDROID_JAVA_HOME", ret.sandboxPath(wd, javaHome))
474 ret.environ.Set("ANDROID_JAVA8_HOME", ret.sandboxPath(wd, java8Home))
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700475 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
476
Colin Crossfe5ed4d2023-07-28 09:27:23 -0700477 // b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches
478 // to unzip to enable zipbomb detection that incorrectly handle zip64 and data descriptors and fail on large
479 // zip files produced by soong_zip. Disable zipbomb detection.
480 ret.environ.Set("UNZIP_DISABLE_ZIPBOMB_DETECTION", "TRUE")
481
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800482 outDir := ret.OutDir()
483 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800484 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800485 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800486 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800487 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800488 }
Colin Cross28f527c2019-11-26 16:19:04 -0800489
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700490 ret.environ.Set("BUILD_DATETIME_FILE", ret.sandboxPath(wd, buildDateTimeFile))
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800491
Cole Faust583dfb42023-09-28 13:56:30 -0700492 if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok {
493 username := "unknown"
494 if u, err := user.Current(); err == nil {
495 username = u.Username
496 } else {
497 ctx.Println("Failed to get current user:", err)
498 }
499 ret.environ.Set("BUILD_USERNAME", username)
500 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700501 ret.environ.Set("PWD", ret.sandboxPath(wd, wd))
Cole Faust583dfb42023-09-28 13:56:30 -0700502
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400503 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400504 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400505 ret.environ.Set(k, v)
506 }
507 }
508
Patrice Arruda96850362020-08-11 20:41:11 +0000509 c := Config{ret}
510 storeConfigMetrics(ctx, c)
511 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700512}
513
Patrice Arruda13848222019-04-22 17:12:02 -0700514// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
515// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700516func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
517 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700518}
519
LaMont Jones9a912862023-11-06 22:11:08 +0000520// Prepare for getting make variables. For them to be accurate, we need to have
521// obtained PRODUCT_RELEASE_CONFIG_MAPS.
522//
523// Returns:
524//
525// Whether config should be called again.
526//
527// TODO: when converting product config to a declarative language, make sure
528// that PRODUCT_RELEASE_CONFIG_MAPS is properly handled as a separate step in
529// that process.
530func SetProductReleaseConfigMaps(ctx Context, config Config) bool {
531 ctx.BeginTrace(metrics.RunKati, "SetProductReleaseConfigMaps")
532 defer ctx.EndTrace()
533
534 if config.SkipConfig() {
535 // This duplicates the logic from Build to skip product config
536 // if the user has explicitly said to.
537 return false
538 }
539
540 releaseConfigVars := []string{
541 "PRODUCT_RELEASE_CONFIG_MAPS",
542 }
543
544 origValue, _ := config.environ.Get("PRODUCT_RELEASE_CONFIG_MAPS")
545 // Get the PRODUCT_RELEASE_CONFIG_MAPS for this product, to avoid polluting the environment
546 // when we run product config to get the rest of the make vars.
547 releaseMapVars, err := dumpMakeVars(ctx, config, nil, releaseConfigVars, false, "")
548 if err != nil {
549 ctx.Fatalln("Error getting PRODUCT_RELEASE_CONFIG_MAPS:", err)
550 }
551 productReleaseConfigMaps := releaseMapVars["PRODUCT_RELEASE_CONFIG_MAPS"]
552 os.Setenv("PRODUCT_RELEASE_CONFIG_MAPS", productReleaseConfigMaps)
553 return origValue != productReleaseConfigMaps
554}
555
Patrice Arruda96850362020-08-11 20:41:11 +0000556// storeConfigMetrics selects a set of configuration information and store in
557// the metrics system for further analysis.
558func storeConfigMetrics(ctx Context, config Config) {
559 if ctx.Metrics == nil {
560 return
561 }
562
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400563 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000564
LaMont Jones54b01cd2024-10-23 13:59:40 -0700565 cpuInfo := &smpb.SystemCpuInfo{
566 VendorId: proto.String(config.systemCpuInfo.VendorId),
567 ModelName: proto.String(config.systemCpuInfo.ModelName),
568 CpuCores: proto.Int32(config.systemCpuInfo.CpuCores),
569 Flags: proto.String(config.systemCpuInfo.Flags),
570 }
571 memInfo := &smpb.SystemMemInfo{
572 MemTotal: proto.Uint64(config.systemMemInfo.MemTotal),
573 MemFree: proto.Uint64(config.systemMemInfo.MemFree),
574 MemAvailable: proto.Uint64(config.systemMemInfo.MemAvailable),
575 }
576
Patrice Arruda3edfd482020-10-13 23:58:41 +0000577 s := &smpb.SystemResourceInfo{
578 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
579 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
LaMont Jones54b01cd2024-10-23 13:59:40 -0700580 CpuInfo: cpuInfo,
581 MemInfo: memInfo,
Patrice Arruda3edfd482020-10-13 23:58:41 +0000582 }
583 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000584}
585
Jeongik Cha8d63d562023-03-17 03:52:13 +0900586func getNinjaWeightListSourceInMetric(s NinjaWeightListSource) *smpb.BuildConfig_NinjaWeightListSource {
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900587 switch s {
588 case NINJA_LOG:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900589 return smpb.BuildConfig_NINJA_LOG.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900590 case EVENLY_DISTRIBUTED:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900591 return smpb.BuildConfig_EVENLY_DISTRIBUTED.Enum()
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900592 case EXTERNAL_FILE:
593 return smpb.BuildConfig_EXTERNAL_FILE.Enum()
Jeongik Chae114e602023-03-19 00:12:39 +0900594 case HINT_FROM_SOONG:
595 return smpb.BuildConfig_HINT_FROM_SOONG.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900596 default:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900597 return smpb.BuildConfig_NOT_USED.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900598 }
599}
600
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400601func buildConfig(config Config) *smpb.BuildConfig {
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800602 var soongEnvVars *smpb.SoongEnvVars
603 ensure := func() *smpb.SoongEnvVars {
604 // Create soongEnvVars if it doesn't already exist.
605 if soongEnvVars == nil {
606 soongEnvVars = &smpb.SoongEnvVars{}
607 }
608 return soongEnvVars
609 }
610 if value, ok := config.environ.Get("SOONG_PARTIAL_COMPILE"); ok {
611 ensure().PartialCompile = proto.String(value)
612 }
613 if value, ok := config.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
614 ensure().UsePartialCompile = proto.String(value)
615 }
Yu Liue737a992021-10-04 13:21:41 -0700616 c := &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -0800617 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
618 UseGoma: proto.Bool(config.UseGoma()),
619 UseRbe: proto.Bool(config.UseRBE()),
620 NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800621 SoongEnvVars: soongEnvVars,
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400622 }
Yu Liue737a992021-10-04 13:21:41 -0700623 c.Targets = append(c.Targets, config.arguments...)
624
625 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400626}
627
Patrice Arruda13848222019-04-22 17:12:02 -0700628// getConfigArgs processes the command arguments based on the build action and creates a set of new
629// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700630func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700631 // The next block of code verifies that the current directory is the root directory of the source
632 // tree. It then finds the relative path of dir based on the root directory of the source tree
633 // and verify that dir is inside of the source tree.
634 checkTopDir(ctx)
635 topDir, err := os.Getwd()
636 if err != nil {
637 ctx.Fatalf("Error retrieving top directory: %v", err)
638 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700639 dir, err = filepath.EvalSymlinks(dir)
640 if err != nil {
641 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
642 }
Patrice Arruda13848222019-04-22 17:12:02 -0700643 dir, err = filepath.Abs(dir)
644 if err != nil {
645 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
646 }
647 relDir, err := filepath.Rel(topDir, dir)
648 if err != nil {
649 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
650 }
651 // If there are ".." in the path, it's not in the source tree.
652 if strings.Contains(relDir, "..") {
653 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
654 }
655
656 configArgs := args[:]
657
658 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
659 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
660 targetNamePrefix := "MODULES-IN-"
661 if inList("GET-INSTALL-PATH", configArgs) {
662 targetNamePrefix = "GET-INSTALL-PATH-IN-"
663 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
664 }
665
Patrice Arruda13848222019-04-22 17:12:02 -0700666 var targets []string
667
668 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700669 case BUILD_MODULES:
670 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700671 case BUILD_MODULES_IN_A_DIRECTORY:
672 // If dir is the root source tree, all the modules are built of the source tree are built so
673 // no need to find the build file.
674 if topDir == dir {
675 break
676 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700677
Patrice Arruda13848222019-04-22 17:12:02 -0700678 buildFile := findBuildFile(ctx, relDir)
679 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700680 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700681 }
Patrice Arruda13848222019-04-22 17:12:02 -0700682 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
683 case BUILD_MODULES_IN_DIRECTORIES:
684 newConfigArgs, dirs := splitArgs(configArgs)
685 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700686 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700687 }
688
689 // Tidy only override all other specified targets.
690 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
691 if tidyOnly == "true" || tidyOnly == "1" {
692 configArgs = append(configArgs, "tidy_only")
693 } else {
694 configArgs = append(configArgs, targets...)
695 }
696
697 return configArgs
698}
699
700// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
701func convertToTarget(dir string, targetNamePrefix string) string {
702 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
703}
704
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700705// hasBuildFile returns true if dir contains an Android build file.
706func hasBuildFile(ctx Context, dir string) bool {
707 for _, buildFile := range buildFiles {
708 _, err := os.Stat(filepath.Join(dir, buildFile))
709 if err == nil {
710 return true
711 }
712 if !os.IsNotExist(err) {
713 ctx.Fatalf("Error retrieving the build file stats: %v", err)
714 }
715 }
716 return false
717}
718
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700719// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
720// in the current and any sub directory of dir. If a build file is not found, traverse the path
721// up by one directory and repeat again until either a build file is found or reached to the root
722// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
723// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700724func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700725 // If the string is empty or ".", assume it is top directory of the source tree.
726 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700727 return ""
728 }
729
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700730 found := false
731 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
732 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
733 if err != nil {
734 return err
735 }
736 if found {
737 return filepath.SkipDir
738 }
739 if info.IsDir() {
740 return nil
741 }
742 for _, buildFile := range buildFiles {
743 if info.Name() == buildFile {
744 found = true
745 return filepath.SkipDir
746 }
747 }
748 return nil
749 })
750 if err != nil {
751 ctx.Fatalf("Error finding Android build file: %v", err)
752 }
753
754 if found {
755 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700756 }
757 }
758
759 return ""
760}
761
762// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
763func splitArgs(args []string) (newArgs []string, dirs []string) {
764 specialArgs := map[string]bool{
765 "showcommands": true,
766 "snod": true,
767 "dist": true,
768 "checkbuild": true,
769 }
770
771 newArgs = []string{}
772 dirs = []string{}
773
774 for _, arg := range args {
775 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
776 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
777 newArgs = append(newArgs, arg)
778 continue
779 }
780
781 if _, ok := specialArgs[arg]; ok {
782 newArgs = append(newArgs, arg)
783 continue
784 }
785
786 dirs = append(dirs, arg)
787 }
788
789 return newArgs, dirs
790}
791
792// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
793// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
794// source root tree where the build action command was invoked. Each directory is validated if the
795// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700796func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700797 for _, dir := range dirs {
798 // The directory may have specified specific modules to build. ":" is the separator to separate
799 // the directory and the list of modules.
800 s := strings.Split(dir, ":")
801 l := len(s)
802 if l > 2 { // more than one ":" was specified.
803 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
804 }
805
806 dir = filepath.Join(relDir, s[0])
807 if _, err := os.Stat(dir); err != nil {
808 ctx.Fatalf("couldn't find directory %s", dir)
809 }
810
811 // Verify that if there are any targets specified after ":". Each target is separated by ",".
812 var newTargets []string
813 if l == 2 && s[1] != "" {
814 newTargets = strings.Split(s[1], ",")
815 if inList("", newTargets) {
816 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
817 }
818 }
819
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700820 // If there are specified targets to build in dir, an android build file must exist for the one
821 // shot build. For the non-targets case, find the appropriate build file and build all the
822 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700823 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700824 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700825 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
826 }
827 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700828 buildFile := findBuildFile(ctx, dir)
829 if buildFile == "" {
830 ctx.Fatalf("Build file not found for %s directory", dir)
831 }
832 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700833 }
834
Patrice Arruda13848222019-04-22 17:12:02 -0700835 targets = append(targets, newTargets...)
836 }
837
Dan Willemsence41e942019-07-29 23:39:30 -0700838 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700839}
840
Dan Willemsen9b587492017-07-10 22:13:00 -0700841func (c *configImpl) parseArgs(ctx Context, args []string) {
842 for i := 0; i < len(args); i++ {
843 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100844 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700845 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200846 } else if arg == "--empty-ninja-file" {
847 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100848 } else if arg == "--skip-ninja" {
849 c.skipNinja = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100850 } else if arg == "--soong-only" {
Cole Faust3740b282025-01-21 15:59:50 -0800851 if c.skipKatiControlledByFlags {
852 ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
853 }
854 c.skipKatiControlledByFlags = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100855 c.skipKati = true
856 c.skipKatiNinja = true
Cole Faust3740b282025-01-21 15:59:50 -0800857 } else if arg == "--no-soong-only" {
858 if c.skipKatiControlledByFlags {
859 ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
860 }
861 c.skipKatiControlledByFlags = true
862 c.skipKati = false
863 c.skipKatiNinja = false
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200864 } else if arg == "--config-only" {
865 c.skipKati = true
866 c.skipKatiNinja = true
867 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700868 } else if arg == "--skip-config" {
869 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700870 } else if arg == "--skip-soong-tests" {
871 c.skipSoongTests = true
Colin Cross106d6ef2023-10-24 10:34:56 -0700872 } else if arg == "--no-skip-soong-tests" {
873 c.skipSoongTests = false
MarkDacekd0e7cd32022-12-02 22:22:40 +0000874 } else if arg == "--skip-metrics-upload" {
875 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500876 } else if arg == "--mk-metrics" {
877 c.reportMkMetrics = true
Spandan Das394aa322022-11-03 17:02:10 +0000878 } else if arg == "--search-api-dir" {
879 c.searchApiDir = true
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900880 } else if strings.HasPrefix(arg, "--ninja_weight_source=") {
881 source := strings.TrimPrefix(arg, "--ninja_weight_source=")
882 if source == "ninja_log" {
883 c.ninjaWeightListSource = NINJA_LOG
884 } else if source == "evenly_distributed" {
885 c.ninjaWeightListSource = EVENLY_DISTRIBUTED
886 } else if source == "not_used" {
887 c.ninjaWeightListSource = NOT_USED
Jeongik Chae114e602023-03-19 00:12:39 +0900888 } else if source == "soong" {
889 c.ninjaWeightListSource = HINT_FROM_SOONG
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900890 } else if strings.HasPrefix(source, "file,") {
891 c.ninjaWeightListSource = EXTERNAL_FILE
892 filePath := strings.TrimPrefix(source, "file,")
893 err := validateNinjaWeightList(filePath)
894 if err != nil {
895 ctx.Fatalf("Malformed weight list from %s: %s", filePath, err)
896 }
897 _, err = copyFile(filePath, filepath.Join(c.OutDir(), ".ninja_weight_list"))
898 if err != nil {
899 ctx.Fatalf("Error to copy ninja weight list from %s: %s", filePath, err)
900 }
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900901 } else {
902 ctx.Fatalf("unknown option for ninja_weight_source: %s", source)
903 }
Jihoon Kang2a929ad2023-06-08 19:02:07 +0000904 } else if arg == "--build-from-source-stub" {
905 c.buildFromSourceStub = true
Yu Liufa297642024-06-11 00:13:02 +0000906 } else if arg == "--incremental-build-actions" {
907 c.incrementalBuildActions = true
MarkDacekb96561e2022-12-02 04:34:43 +0000908 } else if strings.HasPrefix(arg, "--build-command=") {
909 buildCmd := strings.TrimPrefix(arg, "--build-command=")
910 // remove quotations
911 buildCmd = strings.TrimPrefix(buildCmd, "\"")
912 buildCmd = strings.TrimSuffix(buildCmd, "\"")
913 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacek6614d9c2022-12-07 21:57:38 +0000914 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
915 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
916 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
917 if err == nil {
918 c.buildStartedTime = val
919 } else {
920 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
921 }
MarkDacekf47e1422023-04-19 16:47:36 +0000922 } else if arg == "--ensure-allowlist-integrity" {
923 c.ensureAllowlistIntegrity = true
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700924 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700925 parseArgNum := func(def int) int {
926 if len(arg) > 2 {
927 p, err := strconv.ParseUint(arg[2:], 10, 31)
928 if err != nil {
929 ctx.Fatalf("Failed to parse %q: %v", arg, err)
930 }
931 return int(p)
932 } else if i+1 < len(args) {
933 p, err := strconv.ParseUint(args[i+1], 10, 31)
934 if err == nil {
935 i++
936 return int(p)
937 }
938 }
939 return def
940 }
941
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700942 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700943 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700944 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700945 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700946 } else {
947 ctx.Fatalln("Unknown option:", arg)
948 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700949 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700950 if k == "OUT_DIR" {
951 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
952 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700953 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700954 } else if arg == "dist" {
955 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200956 } else if arg == "json-module-graph" {
957 c.jsonModuleGraph = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200958 } else if arg == "soong_docs" {
959 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700960 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700961 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800962 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700963 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700964 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700965 }
966 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700967}
968
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900969func validateNinjaWeightList(weightListFilePath string) (err error) {
970 data, err := os.ReadFile(weightListFilePath)
971 if err != nil {
972 return
973 }
974 lines := strings.Split(strings.TrimSpace(string(data)), "\n")
975 for _, line := range lines {
976 fields := strings.Split(line, ",")
977 if len(fields) != 2 {
978 return fmt.Errorf("wrong format, each line should have two fields, but '%s'", line)
979 }
980 _, err = strconv.Atoi(fields[1])
981 if err != nil {
982 return
983 }
984 }
985 return
986}
987
Dan Willemsened869522018-01-08 14:58:46 -0800988func (c *configImpl) configureLocale(ctx Context) {
989 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
990 output, err := cmd.Output()
991
992 var locales []string
993 if err == nil {
994 locales = strings.Split(string(output), "\n")
995 } else {
996 // If we're unable to list the locales, let's assume en_US.UTF-8
997 locales = []string{"en_US.UTF-8"}
998 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
999 }
1000
1001 // gettext uses LANGUAGE, which is passed directly through
1002
1003 // For LANG and LC_*, only preserve the evaluated version of
1004 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001005 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -08001006 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001007 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -08001008 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001009 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -08001010 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001011 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -08001012 }
1013
1014 c.environ.UnsetWithPrefix("LC_")
1015
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001016 if userLang != "" {
1017 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -08001018 }
1019
1020 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
1021 // for others)
1022 if inList("C.UTF-8", locales) {
1023 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -05001024 } else if inList("C.utf8", locales) {
1025 // These normalize to the same thing
1026 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -08001027 } else if inList("en_US.UTF-8", locales) {
1028 c.environ.Set("LANG", "en_US.UTF-8")
1029 } else if inList("en_US.utf8", locales) {
1030 // These normalize to the same thing
1031 c.environ.Set("LANG", "en_US.UTF-8")
1032 } else {
1033 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
1034 }
1035}
1036
Dan Willemsen1e704462016-08-21 15:17:17 -07001037func (c *configImpl) Environment() *Environment {
1038 return c.environ
1039}
1040
1041func (c *configImpl) Arguments() []string {
1042 return c.arguments
1043}
1044
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001045func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001046 if len(c.Arguments()) > 0 {
1047 // Explicit targets requested that are not special targets like b2pbuild
1048 // or the JSON module graph
1049 return true
1050 }
1051
Joe Onorato35f300d2024-10-21 15:02:44 -07001052 if !c.JsonModuleGraph() && !c.SoongDocs() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001053 // Command line was empty, the default Ninja target is built
1054 return true
1055 }
1056
Colin Cross8d411ff2023-12-07 10:31:24 -08001057 if c.Dist() {
Liz Kammer88677422021-12-15 15:03:19 -05001058 return true
1059 }
1060
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001061 // build.ninja doesn't need to be generated
1062 return false
1063}
1064
Dan Willemsen1e704462016-08-21 15:17:17 -07001065func (c *configImpl) OutDir() string {
1066 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -07001067 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -07001068 }
1069 return "out"
1070}
1071
Dan Willemsen8a073a82017-02-04 17:30:44 -08001072func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -04001073 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001074}
1075
1076func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -07001077 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -08001078}
1079
Dan Willemsen1e704462016-08-21 15:17:17 -07001080func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001081 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001082 return c.arguments
1083 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001084 return c.ninjaArgs
1085}
1086
1087func (c *configImpl) SoongOutDir() string {
1088 return filepath.Join(c.OutDir(), "soong")
1089}
1090
Spandan Das394aa322022-11-03 17:02:10 +00001091func (c *configImpl) ApiSurfacesOutDir() string {
1092 return filepath.Join(c.OutDir(), "api_surfaces")
1093}
1094
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001095func (c *configImpl) PrebuiltOS() string {
1096 switch runtime.GOOS {
1097 case "linux":
1098 return "linux-x86"
1099 case "darwin":
1100 return "darwin-x86"
1101 default:
1102 panic("Unknown GOOS")
1103 }
1104}
Lukacs T. Berki90b43342021-11-02 14:42:04 +01001105
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001106func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -07001107 if c.SkipKatiNinja() {
1108 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
1109 } else {
1110 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
1111 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001112}
1113
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001114func (c *configImpl) UsedEnvFile(tag string) string {
Kiyoung Kimeaa55a82023-06-05 16:56:49 +09001115 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
Qing Shen713c5422024-08-23 04:09:18 +00001116 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+c.CoverageSuffix()+"."+tag)
Kiyoung Kimeaa55a82023-06-05 16:56:49 +09001117 }
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001118 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
1119}
1120
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001121func (c *configImpl) SoongDocsHtml() string {
1122 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
1123}
1124
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001125func (c *configImpl) ModuleGraphFile() string {
1126 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1127}
1128
kgui67007242022-01-25 13:50:25 +08001129func (c *configImpl) ModuleActionsFile() string {
1130 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1131}
1132
Jeff Gastonefc1b412017-03-29 17:29:06 -07001133func (c *configImpl) TempDir() string {
1134 return shared.TempDirForOutDir(c.SoongOutDir())
1135}
1136
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001137func (c *configImpl) FileListDir() string {
1138 return filepath.Join(c.OutDir(), ".module_paths")
1139}
1140
Dan Willemsen1e704462016-08-21 15:17:17 -07001141func (c *configImpl) KatiSuffix() string {
1142 if c.katiSuffix != "" {
1143 return c.katiSuffix
1144 }
1145 panic("SetKatiSuffix has not been called")
1146}
1147
Colin Cross37193492017-11-16 17:55:00 -08001148// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1149// user is interested in additional checks at the expense of build time.
1150func (c *configImpl) Checkbuild() bool {
1151 return c.checkbuild
1152}
1153
Dan Willemsen8a073a82017-02-04 17:30:44 -08001154func (c *configImpl) Dist() bool {
1155 return c.dist
1156}
1157
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001158func (c *configImpl) JsonModuleGraph() bool {
1159 return c.jsonModuleGraph
1160}
1161
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001162func (c *configImpl) SoongDocs() bool {
1163 return c.soongDocs
1164}
1165
Dan Willemsen1e704462016-08-21 15:17:17 -07001166func (c *configImpl) IsVerbose() bool {
1167 return c.verbose
1168}
1169
Jeongik Cha0cf44d52023-03-15 00:10:45 +09001170func (c *configImpl) NinjaWeightListSource() NinjaWeightListSource {
1171 return c.ninjaWeightListSource
1172}
1173
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001174func (c *configImpl) SkipKati() bool {
1175 return c.skipKati
1176}
1177
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001178func (c *configImpl) SkipKatiNinja() bool {
1179 return c.skipKatiNinja
1180}
1181
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001182func (c *configImpl) SkipSoong() bool {
1183 return c.skipSoong
1184}
1185
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001186func (c *configImpl) SkipNinja() bool {
1187 return c.skipNinja
1188}
1189
Anton Hansson5a7861a2021-06-04 10:09:01 +01001190func (c *configImpl) SetSkipNinja(v bool) {
1191 c.skipNinja = v
1192}
1193
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001194func (c *configImpl) SkipConfig() bool {
1195 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001196}
1197
Jihoon Kang1bff0342023-01-17 20:40:22 +00001198func (c *configImpl) BuildFromTextStub() bool {
Jihoon Kang2a929ad2023-06-08 19:02:07 +00001199 return !c.buildFromSourceStub
Jihoon Kang1bff0342023-01-17 20:40:22 +00001200}
1201
Dan Willemsen1e704462016-08-21 15:17:17 -07001202func (c *configImpl) TargetProduct() string {
1203 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1204 return v
1205 }
1206 panic("TARGET_PRODUCT is not defined")
1207}
1208
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001209func (c *configImpl) TargetProductOrErr() (string, error) {
1210 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1211 return v, nil
1212 }
1213 return "", fmt.Errorf("TARGET_PRODUCT is not defined")
1214}
1215
Qing Shen713c5422024-08-23 04:09:18 +00001216func (c *configImpl) CoverageSuffix() string {
1217 if v := c.environ.IsEnvTrue("EMMA_INSTRUMENT"); v {
1218 return ".coverage"
1219 }
1220 return ""
1221}
1222
Dan Willemsen02781d52017-05-12 19:28:13 -07001223func (c *configImpl) TargetDevice() string {
1224 return c.targetDevice
1225}
1226
1227func (c *configImpl) SetTargetDevice(device string) {
1228 c.targetDevice = device
1229}
1230
1231func (c *configImpl) TargetBuildVariant() string {
1232 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1233 return v
1234 }
1235 panic("TARGET_BUILD_VARIANT is not defined")
1236}
1237
Dan Willemsen1e704462016-08-21 15:17:17 -07001238func (c *configImpl) KatiArgs() []string {
1239 return c.katiArgs
1240}
1241
1242func (c *configImpl) Parallel() int {
1243 return c.parallel
1244}
1245
Sam Delmerico98a73292023-02-21 11:50:29 -05001246func (c *configImpl) GetSourceRootDirs() []string {
1247 return c.sourceRootDirs
1248}
1249
1250func (c *configImpl) SetSourceRootDirs(i []string) {
1251 c.sourceRootDirs = i
1252}
1253
MarkDacek6614d9c2022-12-07 21:57:38 +00001254func (c *configImpl) GetLogsPrefix() string {
1255 return c.logsPrefix
1256}
1257
1258func (c *configImpl) SetLogsPrefix(prefix string) {
1259 c.logsPrefix = prefix
1260}
1261
Colin Cross8b8bec32019-11-15 13:18:43 -08001262func (c *configImpl) HighmemParallel() int {
1263 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1264 return i
1265 }
1266
1267 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1268 parallel := c.Parallel()
1269 if c.UseRemoteBuild() {
1270 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1271 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1272 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1273 // Return 1/16th of the size of the local pool, rounding up.
1274 return (parallel + 15) / 16
1275 } else if c.totalRAM == 0 {
1276 // Couldn't detect the total RAM, don't restrict highmem processes.
1277 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001278 } else if c.totalRAM <= 16*1024*1024*1024 {
1279 // Less than 16GB of ram, restrict to 1 highmem processes
1280 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001281 } else if c.totalRAM <= 32*1024*1024*1024 {
1282 // Less than 32GB of ram, restrict to 2 highmem processes
1283 return 2
1284 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1285 // If less than 8GB total RAM per process, reduce the number of highmem processes
1286 return p
1287 }
1288 // No restriction on highmem processes
1289 return parallel
1290}
1291
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001292func (c *configImpl) TotalRAM() uint64 {
1293 return c.totalRAM
1294}
1295
Kousik Kumarec478642020-09-21 13:39:24 -04001296// ForceUseGoma determines whether we should override Goma deprecation
1297// and use Goma for the current build or not.
1298func (c *configImpl) ForceUseGoma() bool {
1299 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1300 v = strings.TrimSpace(v)
1301 if v != "" && v != "false" {
1302 return true
1303 }
1304 }
1305 return false
1306}
1307
Dan Willemsen1e704462016-08-21 15:17:17 -07001308func (c *configImpl) UseGoma() bool {
1309 if v, ok := c.environ.Get("USE_GOMA"); ok {
1310 v = strings.TrimSpace(v)
1311 if v != "" && v != "false" {
1312 return true
1313 }
1314 }
1315 return false
1316}
1317
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001318func (c *configImpl) StartGoma() bool {
1319 if !c.UseGoma() {
1320 return false
1321 }
1322
1323 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1324 v = strings.TrimSpace(v)
1325 if v != "" && v != "false" {
1326 return false
1327 }
1328 }
1329 return true
1330}
1331
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001332func (c *configImpl) canSupportRBE() bool {
Joe Onorato86f50e72024-06-24 14:28:25 -07001333 // Only supported on linux
1334 if runtime.GOOS != "linux" {
1335 return false
1336 }
1337
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001338 // Do not use RBE with prod credentials in scenarios when stubby doesn't exist, since
1339 // its unlikely that we will be able to obtain necessary creds without stubby.
1340 authType, _ := c.rbeAuth()
1341 if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") {
1342 return false
1343 }
Taylor Santiago3c16e612024-05-30 14:41:31 -07001344 if c.UseABFS() {
1345 return false
1346 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001347 return true
1348}
1349
Taylor Santiago3c16e612024-05-30 14:41:31 -07001350func (c *configImpl) UseABFS() bool {
Taylor Santiago2fa40d02025-01-20 20:36:37 -08001351 if c.ninjaCommand == NINJA_NINJAGO {
1352 return true
1353 }
1354
Taylor Santiago3c16e612024-05-30 14:41:31 -07001355 if v, ok := c.environ.Get("NO_ABFS"); ok {
1356 v = strings.ToLower(strings.TrimSpace(v))
1357 if v == "true" || v == "1" {
1358 return false
1359 }
1360 }
1361
1362 abfsBox := c.PrebuiltBuildTool("abfsbox")
1363 err := exec.Command(abfsBox, "hash", srcDirFileCheck).Run()
1364 return err == nil
1365}
1366
Taylor Santiago8b0bed72024-09-03 13:30:22 -07001367func (c *configImpl) sandboxPath(base, in string) string {
1368 if !c.UseABFS() {
1369 return in
1370 }
1371
1372 rel, err := filepath.Rel(base, in)
1373 if err != nil {
1374 return in
1375 }
1376
1377 return filepath.Join(abfsSrcDir, rel)
1378}
1379
Ramy Medhatbbf25672019-07-17 12:30:04 +00001380func (c *configImpl) UseRBE() bool {
Jingwen Chend7ccde12023-06-28 07:19:26 +00001381 // These alternate modes of running Soong do not use RBE / reclient.
Joe Onorato35f300d2024-10-21 15:02:44 -07001382 if c.JsonModuleGraph() {
Jingwen Chend7ccde12023-06-28 07:19:26 +00001383 return false
1384 }
1385
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001386 if !c.canSupportRBE() {
Kousik Kumar67ad4342023-06-06 15:09:27 -04001387 return false
1388 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001389
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001390 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001391 v = strings.TrimSpace(v)
1392 if v != "" && v != "false" {
1393 return true
1394 }
1395 }
1396 return false
1397}
1398
1399func (c *configImpl) StartRBE() bool {
1400 if !c.UseRBE() {
1401 return false
1402 }
1403
1404 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1405 v = strings.TrimSpace(v)
1406 if v != "" && v != "false" {
1407 return false
1408 }
1409 }
1410 return true
1411}
1412
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001413func (c *configImpl) rbeProxyLogsDir() string {
1414 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001415 if v, ok := c.environ.Get(f); ok {
1416 return v
1417 }
1418 }
Ramy Medhatbc061762023-10-10 18:36:59 +00001419 return c.rbeTmpDir()
1420}
1421
1422func (c *configImpl) rbeDownloadTmpDir() string {
Cole Faust06ea5312023-10-18 17:38:40 -07001423 for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
Ramy Medhatbc061762023-10-10 18:36:59 +00001424 if v, ok := c.environ.Get(f); ok {
1425 return v
1426 }
1427 }
1428 return c.rbeTmpDir()
1429}
1430
1431func (c *configImpl) rbeTmpDir() string {
Yaowen Meid4da2662024-07-24 08:25:12 +00001432 return filepath.Join(c.SoongOutDir(), "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001433}
1434
Ramy Medhatc8f6cc22023-03-31 09:50:34 -04001435func (c *configImpl) rbeCacheDir() string {
1436 for _, f := range []string{"RBE_cache_dir", "FLAG_cache_dir"} {
1437 if v, ok := c.environ.Get(f); ok {
1438 return v
1439 }
1440 }
1441 return shared.JoinPath(c.SoongOutDir(), "rbe")
1442}
1443
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001444func (c *configImpl) shouldCleanupRBELogsDir() bool {
1445 // Perform a log directory cleanup only when the log directory
1446 // is auto created by the build rather than user-specified.
1447 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Yaowen Meid9108d22024-08-29 16:56:32 +00001448 if v, ok := c.environ.Get(f); ok {
1449 if v != c.rbeTmpDir() {
1450 return false
1451 }
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001452 }
1453 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001454 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001455}
1456
1457func (c *configImpl) rbeExecRoot() string {
1458 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1459 if v, ok := c.environ.Get(f); ok {
1460 return v
1461 }
1462 }
1463 wd, err := os.Getwd()
1464 if err != nil {
1465 return ""
1466 }
1467 return wd
1468}
1469
1470func (c *configImpl) rbeDir() string {
1471 if v, ok := c.environ.Get("RBE_DIR"); ok {
1472 return v
1473 }
1474 return "prebuilts/remoteexecution-client/live/"
1475}
1476
1477func (c *configImpl) rbeReproxy() string {
1478 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1479 if v, ok := c.environ.Get(f); ok {
1480 return v
1481 }
1482 }
1483 return filepath.Join(c.rbeDir(), "reproxy")
1484}
1485
1486func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001487 credFlags := []string{
1488 "use_application_default_credentials",
1489 "use_gce_credentials",
1490 "credential_file",
1491 "use_google_prod_creds",
1492 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001493 for _, cf := range credFlags {
1494 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1495 if v, ok := c.environ.Get(f); ok {
1496 v = strings.TrimSpace(v)
1497 if v != "" && v != "false" && v != "0" {
1498 return "RBE_" + cf, v
1499 }
1500 }
1501 }
1502 }
1503 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001504}
1505
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001506func (c *configImpl) rbeSockAddr(dir string) (string, error) {
Andus Yuc917eb82024-03-06 21:54:15 +00001507 // Absolute path socket addresses have a prefix of //. This should
1508 // be included in the length limit.
1509 maxNameLen := len(syscall.RawSockaddrUnix{}.Path) - 2
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001510 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1511
1512 name := filepath.Join(dir, base)
1513 if len(name) < maxNameLen {
1514 return name, nil
1515 }
1516
1517 name = filepath.Join("/tmp", base)
1518 if len(name) < maxNameLen {
1519 return name, nil
1520 }
1521
1522 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1523}
1524
Kousik Kumar7bc78192022-04-27 14:52:56 -04001525// IsGooglerEnvironment returns true if the current build is running
1526// on a Google developer machine and false otherwise.
1527func (c *configImpl) IsGooglerEnvironment() bool {
1528 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1529 if v, ok := c.environ.Get(cf); ok {
1530 return v == "googler"
1531 }
1532 return false
1533}
1534
1535// GoogleProdCredsExist determine whether credentials exist on the
1536// Googler machine to use remote execution.
1537func (c *configImpl) GoogleProdCredsExist() bool {
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001538 if googleProdCredsExistCache {
1539 return googleProdCredsExistCache
1540 }
andusyu0b3dc032023-06-21 17:29:32 -04001541 if _, err := exec.Command("/usr/bin/gcertstatus", "-nocheck_ssh").Output(); err != nil {
Kousik Kumar7bc78192022-04-27 14:52:56 -04001542 return false
1543 }
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001544 googleProdCredsExistCache = true
Kousik Kumar7bc78192022-04-27 14:52:56 -04001545 return true
1546}
1547
1548// UseRemoteBuild indicates whether to use a remote build acceleration system
1549// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001550func (c *configImpl) UseRemoteBuild() bool {
1551 return c.UseGoma() || c.UseRBE()
1552}
1553
Kousik Kumar7bc78192022-04-27 14:52:56 -04001554// StubbyExists checks whether the stubby binary exists on the machine running
1555// the build.
1556func (c *configImpl) StubbyExists() bool {
1557 if _, err := exec.LookPath("stubby"); err != nil {
1558 return false
1559 }
1560 return true
1561}
1562
Dan Willemsen1e704462016-08-21 15:17:17 -07001563// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001564// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001565// still limited by Parallel()
1566func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001567 if !c.UseRemoteBuild() {
1568 return 0
1569 }
1570 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1571 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001572 }
1573 return 500
1574}
1575
1576func (c *configImpl) SetKatiArgs(args []string) {
1577 c.katiArgs = args
1578}
1579
1580func (c *configImpl) SetNinjaArgs(args []string) {
1581 c.ninjaArgs = args
1582}
1583
1584func (c *configImpl) SetKatiSuffix(suffix string) {
1585 c.katiSuffix = suffix
1586}
1587
Dan Willemsene0879fc2017-08-04 15:06:27 -07001588func (c *configImpl) LastKatiSuffixFile() string {
1589 return filepath.Join(c.OutDir(), "last_kati_suffix")
1590}
1591
1592func (c *configImpl) HasKatiSuffix() bool {
1593 return c.katiSuffix != ""
1594}
1595
Dan Willemsen1e704462016-08-21 15:17:17 -07001596func (c *configImpl) KatiEnvFile() string {
1597 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1598}
1599
Dan Willemsen29971232018-09-26 14:58:30 -07001600func (c *configImpl) KatiBuildNinjaFile() string {
1601 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001602}
1603
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001604func (c *configImpl) KatiPackageNinjaFile() string {
1605 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1606}
1607
Cole Faustc5bfbdd2025-01-08 13:05:40 -08001608func (c *configImpl) KatiSoongOnlyPackageNinjaFile() string {
1609 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiSoongOnlyPackageSuffix+".ninja")
1610}
1611
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001612func (c *configImpl) SoongVarsFile() string {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001613 targetProduct, err := c.TargetProductOrErr()
1614 if err != nil {
1615 return filepath.Join(c.SoongOutDir(), "soong.variables")
1616 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001617 return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".variables")
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001618 }
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001619}
1620
Inseob Kim58c802f2024-06-11 10:59:00 +09001621func (c *configImpl) SoongExtraVarsFile() string {
1622 targetProduct, err := c.TargetProductOrErr()
1623 if err != nil {
1624 return filepath.Join(c.SoongOutDir(), "soong.extra.variables")
1625 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001626 return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".extra.variables")
Inseob Kim58c802f2024-06-11 10:59:00 +09001627 }
1628}
1629
Dan Willemsen1e704462016-08-21 15:17:17 -07001630func (c *configImpl) SoongNinjaFile() string {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001631 targetProduct, err := c.TargetProductOrErr()
1632 if err != nil {
1633 return filepath.Join(c.SoongOutDir(), "build.ninja")
1634 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001635 return filepath.Join(c.SoongOutDir(), "build."+targetProduct+c.CoverageSuffix()+".ninja")
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001636 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001637}
1638
1639func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001640 if c.katiSuffix == "" {
1641 return filepath.Join(c.OutDir(), "combined.ninja")
1642 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001643 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1644}
1645
1646func (c *configImpl) SoongAndroidMk() string {
Qing Shen713c5422024-08-23 04:09:18 +00001647 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
Dan Willemsen1e704462016-08-21 15:17:17 -07001648}
1649
1650func (c *configImpl) SoongMakeVarsMk() string {
Qing Shen713c5422024-08-23 04:09:18 +00001651 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
Dan Willemsen1e704462016-08-21 15:17:17 -07001652}
1653
Colin Crossaa9a2732023-10-27 10:54:27 -07001654func (c *configImpl) SoongBuildMetrics() string {
Colin Crossb67b0612023-10-31 10:02:45 -07001655 return filepath.Join(c.LogsDir(), "soong_build_metrics.pb")
Colin Crossaa9a2732023-10-27 10:54:27 -07001656}
1657
Dan Willemsenf052f782017-05-18 15:29:04 -07001658func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001659 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001660}
1661
Dan Willemsen02781d52017-05-12 19:28:13 -07001662func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001663 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1664}
1665
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001666func (c *configImpl) KatiPackageMkDir() string {
Cole Faustc5bfbdd2025-01-08 13:05:40 -08001667 return filepath.Join(c.SoongOutDir(), "kati_packaging"+c.KatiSuffix())
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001668}
1669
Dan Willemsenf052f782017-05-18 15:29:04 -07001670func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001671 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001672}
1673
1674func (c *configImpl) HostOut() string {
1675 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1676}
1677
1678// This probably needs to be multi-valued, so not exporting it for now
1679func (c *configImpl) hostCrossOut() string {
1680 if runtime.GOOS == "linux" {
1681 return filepath.Join(c.hostOutRoot(), "windows-x86")
1682 } else {
1683 return ""
1684 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001685}
1686
Dan Willemsen1e704462016-08-21 15:17:17 -07001687func (c *configImpl) HostPrebuiltTag() string {
1688 if runtime.GOOS == "linux" {
1689 return "linux-x86"
1690 } else if runtime.GOOS == "darwin" {
1691 return "darwin-x86"
1692 } else {
1693 panic("Unsupported OS")
1694 }
1695}
Dan Willemsenf173d592017-04-27 14:28:00 -07001696
Taylor Santiago3c16e612024-05-30 14:41:31 -07001697func (c *configImpl) KatiBin() string {
1698 binName := "ckati"
1699 if c.UseABFS() {
1700 binName = "ckati-wrap"
1701 }
1702
1703 return c.PrebuiltBuildTool(binName)
1704}
1705
1706func (c *configImpl) NinjaBin() string {
1707 binName := "ninja"
1708 if c.UseABFS() {
1709 binName = "ninjago"
1710 }
1711 return c.PrebuiltBuildTool(binName)
1712}
1713
Cole Faust4e58bba2024-08-22 14:27:03 -07001714func (c *configImpl) N2Bin() string {
1715 path := c.PrebuiltBuildTool("n2")
1716 // Use musl instead of glibc because glibc on the build server is old and has bugs
1717 return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
1718}
1719
LaMont Jonesece626c2024-09-03 11:19:31 -07001720func (c *configImpl) SisoBin() string {
1721 path := c.PrebuiltBuildTool("siso")
1722 // Use musl instead of glibc because glibc on the build server is old and has bugs
1723 return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
1724}
1725
Dan Willemsen8122bd52017-10-12 20:20:41 -07001726func (c *configImpl) PrebuiltBuildTool(name string) string {
Colin Cross7077be42024-10-04 20:37:16 +00001727 if c.environ.IsEnvTrue("SANITIZE_BUILD_TOOL_PREBUILTS") {
1728 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1729 if _, err := os.Stat(asan); err == nil {
1730 return asan
Dan Willemsenf173d592017-04-27 14:28:00 -07001731 }
1732 }
1733 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1734}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001735
1736func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1737 c.brokenDupRules = val
1738}
1739
1740func (c *configImpl) BuildBrokenDupRules() bool {
1741 return c.brokenDupRules
1742}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001743
Dan Willemsen25e6f092019-04-09 10:22:43 -07001744func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1745 c.brokenUsesNetwork = val
1746}
1747
1748func (c *configImpl) BuildBrokenUsesNetwork() bool {
1749 return c.brokenUsesNetwork
1750}
1751
Dan Willemsene3336352020-01-02 19:10:38 -08001752func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1753 c.brokenNinjaEnvVars = val
1754}
1755
1756func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1757 return c.brokenNinjaEnvVars
1758}
1759
Spandan Das28a6f192024-07-01 21:00:25 +00001760func (c *configImpl) SetBuildBrokenMissingOutputs(val bool) {
1761 c.brokenMissingOutputs = val
1762}
1763
1764func (c *configImpl) BuildBrokenMissingOutputs() bool {
1765 return c.brokenMissingOutputs
1766}
1767
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001768func (c *configImpl) SetTargetDeviceDir(dir string) {
1769 c.targetDeviceDir = dir
1770}
1771
1772func (c *configImpl) TargetDeviceDir() string {
1773 return c.targetDeviceDir
1774}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001775
Patrice Arruda219eef32020-06-01 17:29:30 +00001776func (c *configImpl) BuildDateTime() string {
1777 return c.buildDateTime
1778}
1779
1780func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001781 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001782}
Patrice Arruda83842d72020-12-08 19:42:08 +00001783
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001784// LogsDir returns the absolute path to the logs directory where build log and
1785// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001786// directory. If the argument dist is specified, the logs directory
1787// is <dist_dir>/logs.
1788func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001789 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001790 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001791 // 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 -05001792 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001793 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001794 absDir, err := filepath.Abs(dir)
1795 if err != nil {
1796 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1797 os.Exit(1)
1798 }
1799 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001800}
1801
Chris Parsons53f68ae2022-03-03 12:01:40 -05001802// MkFileMetrics returns the file path for make-related metrics.
1803func (c *configImpl) MkMetrics() string {
1804 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1805}
1806
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001807func (c *configImpl) SetEmptyNinjaFile(v bool) {
1808 c.emptyNinjaFile = v
1809}
1810
1811func (c *configImpl) EmptyNinjaFile() bool {
1812 return c.emptyNinjaFile
1813}
Yu Liu6e13b402021-07-27 14:29:06 -07001814
MarkDacekd0e7cd32022-12-02 22:22:40 +00001815func (c *configImpl) SkipMetricsUpload() bool {
Taylor Santiago8b0bed72024-09-03 13:30:22 -07001816 // b/362625275 - Metrics upload sometimes prevents abfs unmount
1817 if c.UseABFS() {
1818 return true
1819 }
1820
MarkDacekd0e7cd32022-12-02 22:22:40 +00001821 return c.skipMetricsUpload
1822}
1823
MarkDacekf47e1422023-04-19 16:47:36 +00001824func (c *configImpl) EnsureAllowlistIntegrity() bool {
1825 return c.ensureAllowlistIntegrity
1826}
1827
MarkDacek6614d9c2022-12-07 21:57:38 +00001828// Returns a Time object if one was passed via a command-line flag.
1829// Otherwise returns the passed default.
1830func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1831 if c.buildStartedTime == 0 {
1832 return defaultTime
1833 }
1834 return time.UnixMilli(c.buildStartedTime)
1835}
1836
Yu Liu6e13b402021-07-27 14:29:06 -07001837func GetMetricsUploader(topDir string, env *Environment) string {
1838 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1839 metricsUploader := filepath.Join(topDir, p)
1840 if _, err := os.Stat(metricsUploader); err == nil {
1841 return metricsUploader
1842 }
1843 }
1844
1845 return ""
1846}