blob: 9fbbc481cbb2f5699faa7ac0262ea7687ee20154 [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
Cole Faustca27d212025-01-24 10:59:39 -0800255 if value, ok := ret.environ.Get("SOONG_ONLY"); ok && !ret.skipKatiControlledByFlags {
256 if value == "true" || value == "1" || value == "y" || value == "yes" {
257 ret.skipKatiControlledByFlags = true
258 ret.skipKati = true
259 ret.skipKatiNinja = true
260 } else {
261 ret.skipKatiControlledByFlags = true
262 ret.skipKati = false
263 ret.skipKatiNinja = false
264 }
265 }
266
Jeongik Chae114e602023-03-19 00:12:39 +0900267 if ret.ninjaWeightListSource == HINT_FROM_SOONG {
Jeongik Chaa87506f2023-06-01 23:16:41 +0900268 ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "always")
269 } else if ret.ninjaWeightListSource == DEFAULT {
270 defaultNinjaWeightListSource := NINJA_LOG
271 if _, err := os.Stat(filepath.Join(ret.OutDir(), ninjaLogFileName)); errors.Is(err, os.ErrNotExist) {
272 ctx.Verboseln("$OUT/.ninja_log doesn't exist, use HINT_FROM_SOONG instead")
273 defaultNinjaWeightListSource = HINT_FROM_SOONG
274 } else {
275 ctx.Verboseln("$OUT/.ninja_log exist, use NINJA_LOG")
276 }
277 ret.ninjaWeightListSource = defaultNinjaWeightListSource
278 // soong_build generates ninja hint depending on ninja log existence.
279 // Set it "depend" to avoid soong re-run due to env variable change.
280 ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "depend")
Jeongik Chae114e602023-03-19 00:12:39 +0900281 }
Jeongik Chaa87506f2023-06-01 23:16:41 +0900282
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800283 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700284 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700285 ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, filepath.Clean(outDir)))
Dan Willemsen02f3add2017-05-12 13:50:19 -0700286 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800287 outDir := "out"
288 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700289 outDir = filepath.Join(baseDir, filepath.Base(wd))
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800290 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700291 ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, outDir))
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800292 }
293
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500294 // loadEnvConfig needs to know what the OUT_DIR is, so it should
295 // be called after we determine the appropriate out directory.
MarkDacek7901e582023-01-09 19:48:01 +0000296 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
297
298 if bc != "" {
Kousik Kumarc8818332023-01-16 16:33:05 +0000299 if err := loadEnvConfig(ctx, ret, bc); err != nil {
MarkDacek7901e582023-01-09 19:48:01 +0000300 ctx.Fatalln("Failed to parse env config files: %v", err)
301 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +0000302 if !ret.canSupportRBE() {
303 // Explicitly set USE_RBE env variable to false when we cannot run
304 // an RBE build to avoid ninja local execution pool issues.
305 ret.environ.Set("USE_RBE", "false")
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
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800319 if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
320 ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
321 }
322
LaMont Jones99f18962024-10-17 11:50:44 -0700323 // If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
324 // This simplifies the generated Ninja rules, so that they only need to check for the empty string.
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800325 if value, ok := ret.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
LaMont Jones99f18962024-10-17 11:50:44 -0700326 if value == "true" || value == "1" || value == "y" || value == "yes" {
327 value = "true"
328 } else {
329 value = ""
330 }
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800331 ret.environ.Set("SOONG_USE_PARTIAL_COMPILE", value)
LaMont Jones99f18962024-10-17 11:50:44 -0700332 }
333
LaMont Jonesece626c2024-09-03 11:19:31 -0700334 ret.ninjaCommand = NINJA_NINJA
335 switch os.Getenv("SOONG_NINJA") {
336 case "n2":
337 ret.ninjaCommand = NINJA_N2
338 case "siso":
339 ret.ninjaCommand = NINJA_SISO
Taylor Santiago2fa40d02025-01-20 20:36:37 -0800340 case "ninjago":
341 ret.ninjaCommand = NINJA_NINJAGO
LaMont Jonesece626c2024-09-03 11:19:31 -0700342 default:
343 if os.Getenv("SOONG_USE_N2") == "true" {
344 ret.ninjaCommand = NINJA_N2
345 }
Cole Faustbee030d2024-01-03 13:45:48 -0800346 }
347
Dan Willemsen1e704462016-08-21 15:17:17 -0700348 ret.environ.Unset(
349 // We're already using it
350 "USE_SOONG_UI",
351
352 // We should never use GOROOT/GOPATH from the shell environment
353 "GOROOT",
354 "GOPATH",
355
356 // These should only come from Soong, not the environment.
357 "CLANG",
358 "CLANG_CXX",
359 "CCC_CC",
360 "CCC_CXX",
361
362 // Used by the goma compiler wrapper, but should only be set by
363 // gomacc
364 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800365
366 // We handle this above
367 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700368
Dan Willemsen2d31a442018-10-20 21:33:41 -0700369 // This is handled above too, and set for individual commands later
370 "DIST_DIR",
371
Dan Willemsen68a09852017-04-18 13:56:57 -0700372 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000373 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700374 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700375 "DISPLAY",
376 "GREP_OPTIONS",
Nathan Egge7b067fb2023-02-17 17:54:31 +0000377 "JAVAC",
Nathan Egge978c9342024-07-03 21:13:03 +0000378 "LEX",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700379 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700380 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700381
382 // Drop make flags
383 "MAKEFLAGS",
384 "MAKELEVEL",
385 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700386
387 // Set in envsetup.sh, reset in makefiles
388 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700389
390 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
391 "ANDROID_BUILD_TOP",
392 "ANDROID_HOST_OUT",
393 "ANDROID_PRODUCT_OUT",
394 "ANDROID_HOST_OUT_TESTCASES",
395 "ANDROID_TARGET_OUT_TESTCASES",
396 "ANDROID_TOOLCHAIN",
397 "ANDROID_TOOLCHAIN_2ND_ARCH",
398 "ANDROID_DEV_SCRIPTS",
399 "ANDROID_EMULATOR_PREBUILTS",
400 "ANDROID_PRE_BUILD_PATHS",
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800401
402 // We read it here already, don't let others share in the fun
403 "GENERATE_SOONG_DEBUG",
Cole Faustbee030d2024-01-03 13:45:48 -0800404
LaMont Jonesece626c2024-09-03 11:19:31 -0700405 // Use config.ninjaCommand instead.
406 "SOONG_NINJA",
Cole Faustbee030d2024-01-03 13:45:48 -0800407 "SOONG_USE_N2",
Cole Faustca27d212025-01-24 10:59:39 -0800408
409 // Already incorporated into the config object
410 "SOONG_ONLY",
Dan Willemsen1e704462016-08-21 15:17:17 -0700411 )
412
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400413 if ret.UseGoma() || ret.ForceUseGoma() {
414 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
415 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400416 }
417
Dan Willemsen1e704462016-08-21 15:17:17 -0700418 // Tell python not to spam the source tree with .pyc files.
419 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
420
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400421 tmpDir := absPath(ctx, ret.TempDir())
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700422 ret.environ.Set("TMPDIR", ret.sandboxPath(wd, tmpDir))
Dan Willemsen32a669b2018-03-08 19:42:00 -0800423
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700424 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
425 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
426 "llvm-binutils-stable/llvm-symbolizer")
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700427 ret.environ.Set("ASAN_SYMBOLIZER_PATH", ret.sandboxPath(wd, absPath(ctx, symbolizerPath)))
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700428
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800429 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700430 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800431
Yu Liu6e13b402021-07-27 14:29:06 -0700432 srcDir := absPath(ctx, ".")
433 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700434 ctx.Println("You are building in a directory whose absolute path contains a space character:")
435 ctx.Println()
436 ctx.Printf("%q\n", srcDir)
437 ctx.Println()
438 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700439 }
440
Yu Liu6e13b402021-07-27 14:29:06 -0700441 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
442
Dan Willemsendb8457c2017-05-12 16:38:17 -0700443 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700444 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
445 ctx.Println()
446 ctx.Printf("%q\n", outDir)
447 ctx.Println()
448 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700449 }
450
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000451 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700452 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
453 ctx.Println()
454 ctx.Printf("%q\n", distDir)
455 ctx.Println()
456 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700457 }
458
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700459 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000460 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
Sorin Basca0760c892023-11-29 19:13:55 +0000461 java21Home := filepath.Join("prebuilts/jdk/jdk21", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700462 javaHome := func() string {
463 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
464 return override
465 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000466 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
Sorin Basca5dfa2382024-03-11 17:23:06 +0000467 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 +0100468 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000469 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
Sorin Basca5dfa2382024-03-11 17:23:06 +0000470 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 +0000471 }
Sorin Basca5dfa2382024-03-11 17:23:06 +0000472 if toolchain21, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN"); ok && toolchain21 != "true" {
473 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
474 }
475 return java21Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700476 }()
477 absJavaHome := absPath(ctx, javaHome)
478
Dan Willemsened869522018-01-08 14:58:46 -0800479 ret.configureLocale(ctx)
480
PODISHETTY KUMAR (xWF)9543d192024-09-02 03:54:36 +0000481 newPath := []string{filepath.Join(absJavaHome, "bin")}
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700482 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
PODISHETTY KUMAR (xWF)9543d192024-09-02 03:54:36 +0000483 newPath = append(newPath, path)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700484 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100485
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700486 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700487 ret.environ.Set("JAVA_HOME", ret.sandboxPath(wd, absJavaHome))
488 ret.environ.Set("ANDROID_JAVA_HOME", ret.sandboxPath(wd, javaHome))
489 ret.environ.Set("ANDROID_JAVA8_HOME", ret.sandboxPath(wd, java8Home))
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700490 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
491
Colin Crossfe5ed4d2023-07-28 09:27:23 -0700492 // b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches
493 // to unzip to enable zipbomb detection that incorrectly handle zip64 and data descriptors and fail on large
494 // zip files produced by soong_zip. Disable zipbomb detection.
495 ret.environ.Set("UNZIP_DISABLE_ZIPBOMB_DETECTION", "TRUE")
496
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800497 outDir := ret.OutDir()
498 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800499 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800500 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800501 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800502 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800503 }
Colin Cross28f527c2019-11-26 16:19:04 -0800504
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700505 ret.environ.Set("BUILD_DATETIME_FILE", ret.sandboxPath(wd, buildDateTimeFile))
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800506
Cole Faust583dfb42023-09-28 13:56:30 -0700507 if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok {
508 username := "unknown"
509 if u, err := user.Current(); err == nil {
510 username = u.Username
511 } else {
512 ctx.Println("Failed to get current user:", err)
513 }
514 ret.environ.Set("BUILD_USERNAME", username)
515 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700516 ret.environ.Set("PWD", ret.sandboxPath(wd, wd))
Cole Faust583dfb42023-09-28 13:56:30 -0700517
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400518 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400519 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400520 ret.environ.Set(k, v)
521 }
522 }
523
Patrice Arruda96850362020-08-11 20:41:11 +0000524 c := Config{ret}
525 storeConfigMetrics(ctx, c)
526 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700527}
528
Patrice Arruda13848222019-04-22 17:12:02 -0700529// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
530// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700531func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
532 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700533}
534
LaMont Jones9a912862023-11-06 22:11:08 +0000535// Prepare for getting make variables. For them to be accurate, we need to have
536// obtained PRODUCT_RELEASE_CONFIG_MAPS.
537//
538// Returns:
539//
540// Whether config should be called again.
541//
542// TODO: when converting product config to a declarative language, make sure
543// that PRODUCT_RELEASE_CONFIG_MAPS is properly handled as a separate step in
544// that process.
545func SetProductReleaseConfigMaps(ctx Context, config Config) bool {
546 ctx.BeginTrace(metrics.RunKati, "SetProductReleaseConfigMaps")
547 defer ctx.EndTrace()
548
549 if config.SkipConfig() {
550 // This duplicates the logic from Build to skip product config
551 // if the user has explicitly said to.
552 return false
553 }
554
555 releaseConfigVars := []string{
556 "PRODUCT_RELEASE_CONFIG_MAPS",
557 }
558
559 origValue, _ := config.environ.Get("PRODUCT_RELEASE_CONFIG_MAPS")
560 // Get the PRODUCT_RELEASE_CONFIG_MAPS for this product, to avoid polluting the environment
561 // when we run product config to get the rest of the make vars.
562 releaseMapVars, err := dumpMakeVars(ctx, config, nil, releaseConfigVars, false, "")
563 if err != nil {
564 ctx.Fatalln("Error getting PRODUCT_RELEASE_CONFIG_MAPS:", err)
565 }
566 productReleaseConfigMaps := releaseMapVars["PRODUCT_RELEASE_CONFIG_MAPS"]
567 os.Setenv("PRODUCT_RELEASE_CONFIG_MAPS", productReleaseConfigMaps)
568 return origValue != productReleaseConfigMaps
569}
570
Patrice Arruda96850362020-08-11 20:41:11 +0000571// storeConfigMetrics selects a set of configuration information and store in
572// the metrics system for further analysis.
573func storeConfigMetrics(ctx Context, config Config) {
574 if ctx.Metrics == nil {
575 return
576 }
577
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400578 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000579
LaMont Jones54b01cd2024-10-23 13:59:40 -0700580 cpuInfo := &smpb.SystemCpuInfo{
581 VendorId: proto.String(config.systemCpuInfo.VendorId),
582 ModelName: proto.String(config.systemCpuInfo.ModelName),
583 CpuCores: proto.Int32(config.systemCpuInfo.CpuCores),
584 Flags: proto.String(config.systemCpuInfo.Flags),
585 }
586 memInfo := &smpb.SystemMemInfo{
587 MemTotal: proto.Uint64(config.systemMemInfo.MemTotal),
588 MemFree: proto.Uint64(config.systemMemInfo.MemFree),
589 MemAvailable: proto.Uint64(config.systemMemInfo.MemAvailable),
590 }
591
Patrice Arruda3edfd482020-10-13 23:58:41 +0000592 s := &smpb.SystemResourceInfo{
593 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
594 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
LaMont Jones54b01cd2024-10-23 13:59:40 -0700595 CpuInfo: cpuInfo,
596 MemInfo: memInfo,
Patrice Arruda3edfd482020-10-13 23:58:41 +0000597 }
598 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000599}
600
Jeongik Cha8d63d562023-03-17 03:52:13 +0900601func getNinjaWeightListSourceInMetric(s NinjaWeightListSource) *smpb.BuildConfig_NinjaWeightListSource {
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900602 switch s {
603 case NINJA_LOG:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900604 return smpb.BuildConfig_NINJA_LOG.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900605 case EVENLY_DISTRIBUTED:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900606 return smpb.BuildConfig_EVENLY_DISTRIBUTED.Enum()
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900607 case EXTERNAL_FILE:
608 return smpb.BuildConfig_EXTERNAL_FILE.Enum()
Jeongik Chae114e602023-03-19 00:12:39 +0900609 case HINT_FROM_SOONG:
610 return smpb.BuildConfig_HINT_FROM_SOONG.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900611 default:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900612 return smpb.BuildConfig_NOT_USED.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900613 }
614}
615
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400616func buildConfig(config Config) *smpb.BuildConfig {
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800617 var soongEnvVars *smpb.SoongEnvVars
618 ensure := func() *smpb.SoongEnvVars {
619 // Create soongEnvVars if it doesn't already exist.
620 if soongEnvVars == nil {
621 soongEnvVars = &smpb.SoongEnvVars{}
622 }
623 return soongEnvVars
624 }
625 if value, ok := config.environ.Get("SOONG_PARTIAL_COMPILE"); ok {
626 ensure().PartialCompile = proto.String(value)
627 }
628 if value, ok := config.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
629 ensure().UsePartialCompile = proto.String(value)
630 }
Yu Liue737a992021-10-04 13:21:41 -0700631 c := &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -0800632 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
633 UseGoma: proto.Bool(config.UseGoma()),
634 UseRbe: proto.Bool(config.UseRBE()),
635 NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800636 SoongEnvVars: soongEnvVars,
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400637 }
Yu Liue737a992021-10-04 13:21:41 -0700638 c.Targets = append(c.Targets, config.arguments...)
639
640 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400641}
642
Patrice Arruda13848222019-04-22 17:12:02 -0700643// getConfigArgs processes the command arguments based on the build action and creates a set of new
644// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700645func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700646 // The next block of code verifies that the current directory is the root directory of the source
647 // tree. It then finds the relative path of dir based on the root directory of the source tree
648 // and verify that dir is inside of the source tree.
649 checkTopDir(ctx)
650 topDir, err := os.Getwd()
651 if err != nil {
652 ctx.Fatalf("Error retrieving top directory: %v", err)
653 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700654 dir, err = filepath.EvalSymlinks(dir)
655 if err != nil {
656 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
657 }
Patrice Arruda13848222019-04-22 17:12:02 -0700658 dir, err = filepath.Abs(dir)
659 if err != nil {
660 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
661 }
662 relDir, err := filepath.Rel(topDir, dir)
663 if err != nil {
664 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
665 }
666 // If there are ".." in the path, it's not in the source tree.
667 if strings.Contains(relDir, "..") {
668 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
669 }
670
671 configArgs := args[:]
672
673 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
674 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
675 targetNamePrefix := "MODULES-IN-"
676 if inList("GET-INSTALL-PATH", configArgs) {
677 targetNamePrefix = "GET-INSTALL-PATH-IN-"
678 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
679 }
680
Patrice Arruda13848222019-04-22 17:12:02 -0700681 var targets []string
682
683 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700684 case BUILD_MODULES:
685 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700686 case BUILD_MODULES_IN_A_DIRECTORY:
687 // If dir is the root source tree, all the modules are built of the source tree are built so
688 // no need to find the build file.
689 if topDir == dir {
690 break
691 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700692
Patrice Arruda13848222019-04-22 17:12:02 -0700693 buildFile := findBuildFile(ctx, relDir)
694 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700695 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700696 }
Patrice Arruda13848222019-04-22 17:12:02 -0700697 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
698 case BUILD_MODULES_IN_DIRECTORIES:
699 newConfigArgs, dirs := splitArgs(configArgs)
700 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700701 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700702 }
703
704 // Tidy only override all other specified targets.
705 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
706 if tidyOnly == "true" || tidyOnly == "1" {
707 configArgs = append(configArgs, "tidy_only")
708 } else {
709 configArgs = append(configArgs, targets...)
710 }
711
712 return configArgs
713}
714
715// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
716func convertToTarget(dir string, targetNamePrefix string) string {
717 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
718}
719
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700720// hasBuildFile returns true if dir contains an Android build file.
721func hasBuildFile(ctx Context, dir string) bool {
722 for _, buildFile := range buildFiles {
723 _, err := os.Stat(filepath.Join(dir, buildFile))
724 if err == nil {
725 return true
726 }
727 if !os.IsNotExist(err) {
728 ctx.Fatalf("Error retrieving the build file stats: %v", err)
729 }
730 }
731 return false
732}
733
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700734// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
735// in the current and any sub directory of dir. If a build file is not found, traverse the path
736// up by one directory and repeat again until either a build file is found or reached to the root
737// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
738// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700739func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700740 // If the string is empty or ".", assume it is top directory of the source tree.
741 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700742 return ""
743 }
744
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700745 found := false
746 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
747 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
748 if err != nil {
749 return err
750 }
751 if found {
752 return filepath.SkipDir
753 }
754 if info.IsDir() {
755 return nil
756 }
757 for _, buildFile := range buildFiles {
758 if info.Name() == buildFile {
759 found = true
760 return filepath.SkipDir
761 }
762 }
763 return nil
764 })
765 if err != nil {
766 ctx.Fatalf("Error finding Android build file: %v", err)
767 }
768
769 if found {
770 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700771 }
772 }
773
774 return ""
775}
776
777// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
778func splitArgs(args []string) (newArgs []string, dirs []string) {
779 specialArgs := map[string]bool{
780 "showcommands": true,
781 "snod": true,
782 "dist": true,
783 "checkbuild": true,
784 }
785
786 newArgs = []string{}
787 dirs = []string{}
788
789 for _, arg := range args {
790 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
791 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
792 newArgs = append(newArgs, arg)
793 continue
794 }
795
796 if _, ok := specialArgs[arg]; ok {
797 newArgs = append(newArgs, arg)
798 continue
799 }
800
801 dirs = append(dirs, arg)
802 }
803
804 return newArgs, dirs
805}
806
807// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
808// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
809// source root tree where the build action command was invoked. Each directory is validated if the
810// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700811func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700812 for _, dir := range dirs {
813 // The directory may have specified specific modules to build. ":" is the separator to separate
814 // the directory and the list of modules.
815 s := strings.Split(dir, ":")
816 l := len(s)
817 if l > 2 { // more than one ":" was specified.
818 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
819 }
820
821 dir = filepath.Join(relDir, s[0])
822 if _, err := os.Stat(dir); err != nil {
823 ctx.Fatalf("couldn't find directory %s", dir)
824 }
825
826 // Verify that if there are any targets specified after ":". Each target is separated by ",".
827 var newTargets []string
828 if l == 2 && s[1] != "" {
829 newTargets = strings.Split(s[1], ",")
830 if inList("", newTargets) {
831 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
832 }
833 }
834
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700835 // If there are specified targets to build in dir, an android build file must exist for the one
836 // shot build. For the non-targets case, find the appropriate build file and build all the
837 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700838 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700839 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700840 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
841 }
842 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700843 buildFile := findBuildFile(ctx, dir)
844 if buildFile == "" {
845 ctx.Fatalf("Build file not found for %s directory", dir)
846 }
847 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700848 }
849
Patrice Arruda13848222019-04-22 17:12:02 -0700850 targets = append(targets, newTargets...)
851 }
852
Dan Willemsence41e942019-07-29 23:39:30 -0700853 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700854}
855
Dan Willemsen9b587492017-07-10 22:13:00 -0700856func (c *configImpl) parseArgs(ctx Context, args []string) {
857 for i := 0; i < len(args); i++ {
858 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100859 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700860 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200861 } else if arg == "--empty-ninja-file" {
862 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100863 } else if arg == "--skip-ninja" {
864 c.skipNinja = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100865 } else if arg == "--soong-only" {
Cole Faust3740b282025-01-21 15:59:50 -0800866 if c.skipKatiControlledByFlags {
867 ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
868 }
869 c.skipKatiControlledByFlags = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100870 c.skipKati = true
871 c.skipKatiNinja = true
Cole Faust3740b282025-01-21 15:59:50 -0800872 } else if arg == "--no-soong-only" {
873 if c.skipKatiControlledByFlags {
874 ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
875 }
876 c.skipKatiControlledByFlags = true
877 c.skipKati = false
878 c.skipKatiNinja = false
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200879 } else if arg == "--config-only" {
880 c.skipKati = true
881 c.skipKatiNinja = true
882 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700883 } else if arg == "--skip-config" {
884 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700885 } else if arg == "--skip-soong-tests" {
886 c.skipSoongTests = true
Colin Cross106d6ef2023-10-24 10:34:56 -0700887 } else if arg == "--no-skip-soong-tests" {
888 c.skipSoongTests = false
MarkDacekd0e7cd32022-12-02 22:22:40 +0000889 } else if arg == "--skip-metrics-upload" {
890 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500891 } else if arg == "--mk-metrics" {
892 c.reportMkMetrics = true
Spandan Das394aa322022-11-03 17:02:10 +0000893 } else if arg == "--search-api-dir" {
894 c.searchApiDir = true
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900895 } else if strings.HasPrefix(arg, "--ninja_weight_source=") {
896 source := strings.TrimPrefix(arg, "--ninja_weight_source=")
897 if source == "ninja_log" {
898 c.ninjaWeightListSource = NINJA_LOG
899 } else if source == "evenly_distributed" {
900 c.ninjaWeightListSource = EVENLY_DISTRIBUTED
901 } else if source == "not_used" {
902 c.ninjaWeightListSource = NOT_USED
Jeongik Chae114e602023-03-19 00:12:39 +0900903 } else if source == "soong" {
904 c.ninjaWeightListSource = HINT_FROM_SOONG
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900905 } else if strings.HasPrefix(source, "file,") {
906 c.ninjaWeightListSource = EXTERNAL_FILE
907 filePath := strings.TrimPrefix(source, "file,")
908 err := validateNinjaWeightList(filePath)
909 if err != nil {
910 ctx.Fatalf("Malformed weight list from %s: %s", filePath, err)
911 }
912 _, err = copyFile(filePath, filepath.Join(c.OutDir(), ".ninja_weight_list"))
913 if err != nil {
914 ctx.Fatalf("Error to copy ninja weight list from %s: %s", filePath, err)
915 }
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900916 } else {
917 ctx.Fatalf("unknown option for ninja_weight_source: %s", source)
918 }
Jihoon Kang2a929ad2023-06-08 19:02:07 +0000919 } else if arg == "--build-from-source-stub" {
920 c.buildFromSourceStub = true
Yu Liufa297642024-06-11 00:13:02 +0000921 } else if arg == "--incremental-build-actions" {
922 c.incrementalBuildActions = true
MarkDacekb96561e2022-12-02 04:34:43 +0000923 } else if strings.HasPrefix(arg, "--build-command=") {
924 buildCmd := strings.TrimPrefix(arg, "--build-command=")
925 // remove quotations
926 buildCmd = strings.TrimPrefix(buildCmd, "\"")
927 buildCmd = strings.TrimSuffix(buildCmd, "\"")
928 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacek6614d9c2022-12-07 21:57:38 +0000929 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
930 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
931 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
932 if err == nil {
933 c.buildStartedTime = val
934 } else {
935 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
936 }
MarkDacekf47e1422023-04-19 16:47:36 +0000937 } else if arg == "--ensure-allowlist-integrity" {
938 c.ensureAllowlistIntegrity = true
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700939 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700940 parseArgNum := func(def int) int {
941 if len(arg) > 2 {
942 p, err := strconv.ParseUint(arg[2:], 10, 31)
943 if err != nil {
944 ctx.Fatalf("Failed to parse %q: %v", arg, err)
945 }
946 return int(p)
947 } else if i+1 < len(args) {
948 p, err := strconv.ParseUint(args[i+1], 10, 31)
949 if err == nil {
950 i++
951 return int(p)
952 }
953 }
954 return def
955 }
956
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700957 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700958 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700959 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700960 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700961 } else {
962 ctx.Fatalln("Unknown option:", arg)
963 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700964 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700965 if k == "OUT_DIR" {
966 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
967 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700968 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700969 } else if arg == "dist" {
970 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200971 } else if arg == "json-module-graph" {
972 c.jsonModuleGraph = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200973 } else if arg == "soong_docs" {
974 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700975 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700976 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800977 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700978 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700979 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700980 }
981 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700982}
983
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900984func validateNinjaWeightList(weightListFilePath string) (err error) {
985 data, err := os.ReadFile(weightListFilePath)
986 if err != nil {
987 return
988 }
989 lines := strings.Split(strings.TrimSpace(string(data)), "\n")
990 for _, line := range lines {
991 fields := strings.Split(line, ",")
992 if len(fields) != 2 {
993 return fmt.Errorf("wrong format, each line should have two fields, but '%s'", line)
994 }
995 _, err = strconv.Atoi(fields[1])
996 if err != nil {
997 return
998 }
999 }
1000 return
1001}
1002
Dan Willemsened869522018-01-08 14:58:46 -08001003func (c *configImpl) configureLocale(ctx Context) {
1004 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
1005 output, err := cmd.Output()
1006
1007 var locales []string
1008 if err == nil {
1009 locales = strings.Split(string(output), "\n")
1010 } else {
1011 // If we're unable to list the locales, let's assume en_US.UTF-8
1012 locales = []string{"en_US.UTF-8"}
1013 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
1014 }
1015
1016 // gettext uses LANGUAGE, which is passed directly through
1017
1018 // For LANG and LC_*, only preserve the evaluated version of
1019 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001020 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -08001021 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001022 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -08001023 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001024 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -08001025 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001026 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -08001027 }
1028
1029 c.environ.UnsetWithPrefix("LC_")
1030
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001031 if userLang != "" {
1032 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -08001033 }
1034
1035 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
1036 // for others)
1037 if inList("C.UTF-8", locales) {
1038 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -05001039 } else if inList("C.utf8", locales) {
1040 // These normalize to the same thing
1041 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -08001042 } else if inList("en_US.UTF-8", locales) {
1043 c.environ.Set("LANG", "en_US.UTF-8")
1044 } else if inList("en_US.utf8", locales) {
1045 // These normalize to the same thing
1046 c.environ.Set("LANG", "en_US.UTF-8")
1047 } else {
1048 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
1049 }
1050}
1051
Dan Willemsen1e704462016-08-21 15:17:17 -07001052func (c *configImpl) Environment() *Environment {
1053 return c.environ
1054}
1055
1056func (c *configImpl) Arguments() []string {
1057 return c.arguments
1058}
1059
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001060func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001061 if len(c.Arguments()) > 0 {
1062 // Explicit targets requested that are not special targets like b2pbuild
1063 // or the JSON module graph
1064 return true
1065 }
1066
Joe Onorato35f300d2024-10-21 15:02:44 -07001067 if !c.JsonModuleGraph() && !c.SoongDocs() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001068 // Command line was empty, the default Ninja target is built
1069 return true
1070 }
1071
Colin Cross8d411ff2023-12-07 10:31:24 -08001072 if c.Dist() {
Liz Kammer88677422021-12-15 15:03:19 -05001073 return true
1074 }
1075
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001076 // build.ninja doesn't need to be generated
1077 return false
1078}
1079
Dan Willemsen1e704462016-08-21 15:17:17 -07001080func (c *configImpl) OutDir() string {
1081 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -07001082 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -07001083 }
1084 return "out"
1085}
1086
Dan Willemsen8a073a82017-02-04 17:30:44 -08001087func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -04001088 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001089}
1090
1091func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -07001092 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -08001093}
1094
Dan Willemsen1e704462016-08-21 15:17:17 -07001095func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001096 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001097 return c.arguments
1098 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001099 return c.ninjaArgs
1100}
1101
1102func (c *configImpl) SoongOutDir() string {
1103 return filepath.Join(c.OutDir(), "soong")
1104}
1105
Spandan Das394aa322022-11-03 17:02:10 +00001106func (c *configImpl) ApiSurfacesOutDir() string {
1107 return filepath.Join(c.OutDir(), "api_surfaces")
1108}
1109
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001110func (c *configImpl) PrebuiltOS() string {
1111 switch runtime.GOOS {
1112 case "linux":
1113 return "linux-x86"
1114 case "darwin":
1115 return "darwin-x86"
1116 default:
1117 panic("Unknown GOOS")
1118 }
1119}
Lukacs T. Berki90b43342021-11-02 14:42:04 +01001120
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001121func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -07001122 if c.SkipKatiNinja() {
1123 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
1124 } else {
1125 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
1126 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001127}
1128
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001129func (c *configImpl) UsedEnvFile(tag string) string {
Kiyoung Kimeaa55a82023-06-05 16:56:49 +09001130 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
Qing Shen713c5422024-08-23 04:09:18 +00001131 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+c.CoverageSuffix()+"."+tag)
Kiyoung Kimeaa55a82023-06-05 16:56:49 +09001132 }
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001133 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
1134}
1135
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001136func (c *configImpl) SoongDocsHtml() string {
1137 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
1138}
1139
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001140func (c *configImpl) ModuleGraphFile() string {
1141 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1142}
1143
kgui67007242022-01-25 13:50:25 +08001144func (c *configImpl) ModuleActionsFile() string {
1145 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1146}
1147
Jeff Gastonefc1b412017-03-29 17:29:06 -07001148func (c *configImpl) TempDir() string {
1149 return shared.TempDirForOutDir(c.SoongOutDir())
1150}
1151
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001152func (c *configImpl) FileListDir() string {
1153 return filepath.Join(c.OutDir(), ".module_paths")
1154}
1155
Dan Willemsen1e704462016-08-21 15:17:17 -07001156func (c *configImpl) KatiSuffix() string {
1157 if c.katiSuffix != "" {
1158 return c.katiSuffix
1159 }
1160 panic("SetKatiSuffix has not been called")
1161}
1162
Colin Cross37193492017-11-16 17:55:00 -08001163// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1164// user is interested in additional checks at the expense of build time.
1165func (c *configImpl) Checkbuild() bool {
1166 return c.checkbuild
1167}
1168
Dan Willemsen8a073a82017-02-04 17:30:44 -08001169func (c *configImpl) Dist() bool {
1170 return c.dist
1171}
1172
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001173func (c *configImpl) JsonModuleGraph() bool {
1174 return c.jsonModuleGraph
1175}
1176
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001177func (c *configImpl) SoongDocs() bool {
1178 return c.soongDocs
1179}
1180
Dan Willemsen1e704462016-08-21 15:17:17 -07001181func (c *configImpl) IsVerbose() bool {
1182 return c.verbose
1183}
1184
Jeongik Cha0cf44d52023-03-15 00:10:45 +09001185func (c *configImpl) NinjaWeightListSource() NinjaWeightListSource {
1186 return c.ninjaWeightListSource
1187}
1188
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001189func (c *configImpl) SkipKati() bool {
1190 return c.skipKati
1191}
1192
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001193func (c *configImpl) SkipKatiNinja() bool {
1194 return c.skipKatiNinja
1195}
1196
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001197func (c *configImpl) SkipSoong() bool {
1198 return c.skipSoong
1199}
1200
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001201func (c *configImpl) SkipNinja() bool {
1202 return c.skipNinja
1203}
1204
Anton Hansson5a7861a2021-06-04 10:09:01 +01001205func (c *configImpl) SetSkipNinja(v bool) {
1206 c.skipNinja = v
1207}
1208
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001209func (c *configImpl) SkipConfig() bool {
1210 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001211}
1212
Jihoon Kang1bff0342023-01-17 20:40:22 +00001213func (c *configImpl) BuildFromTextStub() bool {
Jihoon Kang2a929ad2023-06-08 19:02:07 +00001214 return !c.buildFromSourceStub
Jihoon Kang1bff0342023-01-17 20:40:22 +00001215}
1216
Dan Willemsen1e704462016-08-21 15:17:17 -07001217func (c *configImpl) TargetProduct() string {
1218 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1219 return v
1220 }
1221 panic("TARGET_PRODUCT is not defined")
1222}
1223
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001224func (c *configImpl) TargetProductOrErr() (string, error) {
1225 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1226 return v, nil
1227 }
1228 return "", fmt.Errorf("TARGET_PRODUCT is not defined")
1229}
1230
Qing Shen713c5422024-08-23 04:09:18 +00001231func (c *configImpl) CoverageSuffix() string {
1232 if v := c.environ.IsEnvTrue("EMMA_INSTRUMENT"); v {
1233 return ".coverage"
1234 }
1235 return ""
1236}
1237
Dan Willemsen02781d52017-05-12 19:28:13 -07001238func (c *configImpl) TargetDevice() string {
1239 return c.targetDevice
1240}
1241
1242func (c *configImpl) SetTargetDevice(device string) {
1243 c.targetDevice = device
1244}
1245
1246func (c *configImpl) TargetBuildVariant() string {
1247 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1248 return v
1249 }
1250 panic("TARGET_BUILD_VARIANT is not defined")
1251}
1252
Dan Willemsen1e704462016-08-21 15:17:17 -07001253func (c *configImpl) KatiArgs() []string {
1254 return c.katiArgs
1255}
1256
1257func (c *configImpl) Parallel() int {
1258 return c.parallel
1259}
1260
Sam Delmerico98a73292023-02-21 11:50:29 -05001261func (c *configImpl) GetSourceRootDirs() []string {
1262 return c.sourceRootDirs
1263}
1264
1265func (c *configImpl) SetSourceRootDirs(i []string) {
1266 c.sourceRootDirs = i
1267}
1268
MarkDacek6614d9c2022-12-07 21:57:38 +00001269func (c *configImpl) GetLogsPrefix() string {
1270 return c.logsPrefix
1271}
1272
1273func (c *configImpl) SetLogsPrefix(prefix string) {
1274 c.logsPrefix = prefix
1275}
1276
Colin Cross8b8bec32019-11-15 13:18:43 -08001277func (c *configImpl) HighmemParallel() int {
1278 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1279 return i
1280 }
1281
1282 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1283 parallel := c.Parallel()
1284 if c.UseRemoteBuild() {
1285 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1286 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1287 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1288 // Return 1/16th of the size of the local pool, rounding up.
1289 return (parallel + 15) / 16
1290 } else if c.totalRAM == 0 {
1291 // Couldn't detect the total RAM, don't restrict highmem processes.
1292 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001293 } else if c.totalRAM <= 16*1024*1024*1024 {
1294 // Less than 16GB of ram, restrict to 1 highmem processes
1295 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001296 } else if c.totalRAM <= 32*1024*1024*1024 {
1297 // Less than 32GB of ram, restrict to 2 highmem processes
1298 return 2
1299 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1300 // If less than 8GB total RAM per process, reduce the number of highmem processes
1301 return p
1302 }
1303 // No restriction on highmem processes
1304 return parallel
1305}
1306
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001307func (c *configImpl) TotalRAM() uint64 {
1308 return c.totalRAM
1309}
1310
Kousik Kumarec478642020-09-21 13:39:24 -04001311// ForceUseGoma determines whether we should override Goma deprecation
1312// and use Goma for the current build or not.
1313func (c *configImpl) ForceUseGoma() bool {
1314 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1315 v = strings.TrimSpace(v)
1316 if v != "" && v != "false" {
1317 return true
1318 }
1319 }
1320 return false
1321}
1322
Dan Willemsen1e704462016-08-21 15:17:17 -07001323func (c *configImpl) UseGoma() bool {
1324 if v, ok := c.environ.Get("USE_GOMA"); ok {
1325 v = strings.TrimSpace(v)
1326 if v != "" && v != "false" {
1327 return true
1328 }
1329 }
1330 return false
1331}
1332
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001333func (c *configImpl) StartGoma() bool {
1334 if !c.UseGoma() {
1335 return false
1336 }
1337
1338 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1339 v = strings.TrimSpace(v)
1340 if v != "" && v != "false" {
1341 return false
1342 }
1343 }
1344 return true
1345}
1346
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001347func (c *configImpl) canSupportRBE() bool {
Joe Onorato86f50e72024-06-24 14:28:25 -07001348 // Only supported on linux
1349 if runtime.GOOS != "linux" {
1350 return false
1351 }
1352
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001353 // Do not use RBE with prod credentials in scenarios when stubby doesn't exist, since
1354 // its unlikely that we will be able to obtain necessary creds without stubby.
1355 authType, _ := c.rbeAuth()
1356 if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") {
1357 return false
1358 }
Taylor Santiago3c16e612024-05-30 14:41:31 -07001359 if c.UseABFS() {
1360 return false
1361 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001362 return true
1363}
1364
Taylor Santiago3c16e612024-05-30 14:41:31 -07001365func (c *configImpl) UseABFS() bool {
Taylor Santiago2fa40d02025-01-20 20:36:37 -08001366 if c.ninjaCommand == NINJA_NINJAGO {
1367 return true
1368 }
1369
Taylor Santiago3c16e612024-05-30 14:41:31 -07001370 if v, ok := c.environ.Get("NO_ABFS"); ok {
1371 v = strings.ToLower(strings.TrimSpace(v))
1372 if v == "true" || v == "1" {
1373 return false
1374 }
1375 }
1376
1377 abfsBox := c.PrebuiltBuildTool("abfsbox")
1378 err := exec.Command(abfsBox, "hash", srcDirFileCheck).Run()
1379 return err == nil
1380}
1381
Taylor Santiago8b0bed72024-09-03 13:30:22 -07001382func (c *configImpl) sandboxPath(base, in string) string {
1383 if !c.UseABFS() {
1384 return in
1385 }
1386
1387 rel, err := filepath.Rel(base, in)
1388 if err != nil {
1389 return in
1390 }
1391
1392 return filepath.Join(abfsSrcDir, rel)
1393}
1394
Ramy Medhatbbf25672019-07-17 12:30:04 +00001395func (c *configImpl) UseRBE() bool {
Jingwen Chend7ccde12023-06-28 07:19:26 +00001396 // These alternate modes of running Soong do not use RBE / reclient.
Joe Onorato35f300d2024-10-21 15:02:44 -07001397 if c.JsonModuleGraph() {
Jingwen Chend7ccde12023-06-28 07:19:26 +00001398 return false
1399 }
1400
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001401 if !c.canSupportRBE() {
Kousik Kumar67ad4342023-06-06 15:09:27 -04001402 return false
1403 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001404
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001405 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001406 v = strings.TrimSpace(v)
1407 if v != "" && v != "false" {
1408 return true
1409 }
1410 }
1411 return false
1412}
1413
1414func (c *configImpl) StartRBE() bool {
1415 if !c.UseRBE() {
1416 return false
1417 }
1418
1419 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1420 v = strings.TrimSpace(v)
1421 if v != "" && v != "false" {
1422 return false
1423 }
1424 }
1425 return true
1426}
1427
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001428func (c *configImpl) rbeProxyLogsDir() string {
1429 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001430 if v, ok := c.environ.Get(f); ok {
1431 return v
1432 }
1433 }
Ramy Medhatbc061762023-10-10 18:36:59 +00001434 return c.rbeTmpDir()
1435}
1436
1437func (c *configImpl) rbeDownloadTmpDir() string {
Cole Faust06ea5312023-10-18 17:38:40 -07001438 for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
Ramy Medhatbc061762023-10-10 18:36:59 +00001439 if v, ok := c.environ.Get(f); ok {
1440 return v
1441 }
1442 }
1443 return c.rbeTmpDir()
1444}
1445
1446func (c *configImpl) rbeTmpDir() string {
Yaowen Meid4da2662024-07-24 08:25:12 +00001447 return filepath.Join(c.SoongOutDir(), "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001448}
1449
Ramy Medhatc8f6cc22023-03-31 09:50:34 -04001450func (c *configImpl) rbeCacheDir() string {
1451 for _, f := range []string{"RBE_cache_dir", "FLAG_cache_dir"} {
1452 if v, ok := c.environ.Get(f); ok {
1453 return v
1454 }
1455 }
1456 return shared.JoinPath(c.SoongOutDir(), "rbe")
1457}
1458
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001459func (c *configImpl) shouldCleanupRBELogsDir() bool {
1460 // Perform a log directory cleanup only when the log directory
1461 // is auto created by the build rather than user-specified.
1462 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Yaowen Meid9108d22024-08-29 16:56:32 +00001463 if v, ok := c.environ.Get(f); ok {
1464 if v != c.rbeTmpDir() {
1465 return false
1466 }
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001467 }
1468 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001469 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001470}
1471
1472func (c *configImpl) rbeExecRoot() string {
1473 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1474 if v, ok := c.environ.Get(f); ok {
1475 return v
1476 }
1477 }
1478 wd, err := os.Getwd()
1479 if err != nil {
1480 return ""
1481 }
1482 return wd
1483}
1484
1485func (c *configImpl) rbeDir() string {
1486 if v, ok := c.environ.Get("RBE_DIR"); ok {
1487 return v
1488 }
1489 return "prebuilts/remoteexecution-client/live/"
1490}
1491
1492func (c *configImpl) rbeReproxy() string {
1493 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1494 if v, ok := c.environ.Get(f); ok {
1495 return v
1496 }
1497 }
1498 return filepath.Join(c.rbeDir(), "reproxy")
1499}
1500
1501func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001502 credFlags := []string{
1503 "use_application_default_credentials",
1504 "use_gce_credentials",
1505 "credential_file",
1506 "use_google_prod_creds",
1507 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001508 for _, cf := range credFlags {
1509 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1510 if v, ok := c.environ.Get(f); ok {
1511 v = strings.TrimSpace(v)
1512 if v != "" && v != "false" && v != "0" {
1513 return "RBE_" + cf, v
1514 }
1515 }
1516 }
1517 }
1518 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001519}
1520
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001521func (c *configImpl) rbeSockAddr(dir string) (string, error) {
Andus Yuc917eb82024-03-06 21:54:15 +00001522 // Absolute path socket addresses have a prefix of //. This should
1523 // be included in the length limit.
1524 maxNameLen := len(syscall.RawSockaddrUnix{}.Path) - 2
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001525 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1526
1527 name := filepath.Join(dir, base)
1528 if len(name) < maxNameLen {
1529 return name, nil
1530 }
1531
1532 name = filepath.Join("/tmp", base)
1533 if len(name) < maxNameLen {
1534 return name, nil
1535 }
1536
1537 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1538}
1539
Kousik Kumar7bc78192022-04-27 14:52:56 -04001540// IsGooglerEnvironment returns true if the current build is running
1541// on a Google developer machine and false otherwise.
1542func (c *configImpl) IsGooglerEnvironment() bool {
1543 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1544 if v, ok := c.environ.Get(cf); ok {
1545 return v == "googler"
1546 }
1547 return false
1548}
1549
1550// GoogleProdCredsExist determine whether credentials exist on the
1551// Googler machine to use remote execution.
1552func (c *configImpl) GoogleProdCredsExist() bool {
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001553 if googleProdCredsExistCache {
1554 return googleProdCredsExistCache
1555 }
andusyu0b3dc032023-06-21 17:29:32 -04001556 if _, err := exec.Command("/usr/bin/gcertstatus", "-nocheck_ssh").Output(); err != nil {
Kousik Kumar7bc78192022-04-27 14:52:56 -04001557 return false
1558 }
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001559 googleProdCredsExistCache = true
Kousik Kumar7bc78192022-04-27 14:52:56 -04001560 return true
1561}
1562
1563// UseRemoteBuild indicates whether to use a remote build acceleration system
1564// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001565func (c *configImpl) UseRemoteBuild() bool {
1566 return c.UseGoma() || c.UseRBE()
1567}
1568
Kousik Kumar7bc78192022-04-27 14:52:56 -04001569// StubbyExists checks whether the stubby binary exists on the machine running
1570// the build.
1571func (c *configImpl) StubbyExists() bool {
1572 if _, err := exec.LookPath("stubby"); err != nil {
1573 return false
1574 }
1575 return true
1576}
1577
Dan Willemsen1e704462016-08-21 15:17:17 -07001578// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001579// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001580// still limited by Parallel()
1581func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001582 if !c.UseRemoteBuild() {
1583 return 0
1584 }
1585 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1586 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001587 }
1588 return 500
1589}
1590
1591func (c *configImpl) SetKatiArgs(args []string) {
1592 c.katiArgs = args
1593}
1594
1595func (c *configImpl) SetNinjaArgs(args []string) {
1596 c.ninjaArgs = args
1597}
1598
1599func (c *configImpl) SetKatiSuffix(suffix string) {
1600 c.katiSuffix = suffix
1601}
1602
Dan Willemsene0879fc2017-08-04 15:06:27 -07001603func (c *configImpl) LastKatiSuffixFile() string {
1604 return filepath.Join(c.OutDir(), "last_kati_suffix")
1605}
1606
1607func (c *configImpl) HasKatiSuffix() bool {
1608 return c.katiSuffix != ""
1609}
1610
Dan Willemsen1e704462016-08-21 15:17:17 -07001611func (c *configImpl) KatiEnvFile() string {
1612 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1613}
1614
Dan Willemsen29971232018-09-26 14:58:30 -07001615func (c *configImpl) KatiBuildNinjaFile() string {
1616 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001617}
1618
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001619func (c *configImpl) KatiPackageNinjaFile() string {
1620 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1621}
1622
Cole Faustc5bfbdd2025-01-08 13:05:40 -08001623func (c *configImpl) KatiSoongOnlyPackageNinjaFile() string {
1624 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiSoongOnlyPackageSuffix+".ninja")
1625}
1626
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001627func (c *configImpl) SoongVarsFile() string {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001628 targetProduct, err := c.TargetProductOrErr()
1629 if err != nil {
1630 return filepath.Join(c.SoongOutDir(), "soong.variables")
1631 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001632 return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".variables")
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001633 }
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001634}
1635
Inseob Kim58c802f2024-06-11 10:59:00 +09001636func (c *configImpl) SoongExtraVarsFile() string {
1637 targetProduct, err := c.TargetProductOrErr()
1638 if err != nil {
1639 return filepath.Join(c.SoongOutDir(), "soong.extra.variables")
1640 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001641 return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".extra.variables")
Inseob Kim58c802f2024-06-11 10:59:00 +09001642 }
1643}
1644
Dan Willemsen1e704462016-08-21 15:17:17 -07001645func (c *configImpl) SoongNinjaFile() string {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001646 targetProduct, err := c.TargetProductOrErr()
1647 if err != nil {
1648 return filepath.Join(c.SoongOutDir(), "build.ninja")
1649 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001650 return filepath.Join(c.SoongOutDir(), "build."+targetProduct+c.CoverageSuffix()+".ninja")
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001651 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001652}
1653
1654func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001655 if c.katiSuffix == "" {
1656 return filepath.Join(c.OutDir(), "combined.ninja")
1657 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001658 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1659}
1660
1661func (c *configImpl) SoongAndroidMk() string {
Qing Shen713c5422024-08-23 04:09:18 +00001662 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
Dan Willemsen1e704462016-08-21 15:17:17 -07001663}
1664
1665func (c *configImpl) SoongMakeVarsMk() string {
Qing Shen713c5422024-08-23 04:09:18 +00001666 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
Dan Willemsen1e704462016-08-21 15:17:17 -07001667}
1668
Colin Crossaa9a2732023-10-27 10:54:27 -07001669func (c *configImpl) SoongBuildMetrics() string {
Colin Crossb67b0612023-10-31 10:02:45 -07001670 return filepath.Join(c.LogsDir(), "soong_build_metrics.pb")
Colin Crossaa9a2732023-10-27 10:54:27 -07001671}
1672
Dan Willemsenf052f782017-05-18 15:29:04 -07001673func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001674 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001675}
1676
Dan Willemsen02781d52017-05-12 19:28:13 -07001677func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001678 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1679}
1680
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001681func (c *configImpl) KatiPackageMkDir() string {
Cole Faustc5bfbdd2025-01-08 13:05:40 -08001682 return filepath.Join(c.SoongOutDir(), "kati_packaging"+c.KatiSuffix())
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001683}
1684
Dan Willemsenf052f782017-05-18 15:29:04 -07001685func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001686 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001687}
1688
1689func (c *configImpl) HostOut() string {
1690 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1691}
1692
1693// This probably needs to be multi-valued, so not exporting it for now
1694func (c *configImpl) hostCrossOut() string {
1695 if runtime.GOOS == "linux" {
1696 return filepath.Join(c.hostOutRoot(), "windows-x86")
1697 } else {
1698 return ""
1699 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001700}
1701
Dan Willemsen1e704462016-08-21 15:17:17 -07001702func (c *configImpl) HostPrebuiltTag() string {
1703 if runtime.GOOS == "linux" {
1704 return "linux-x86"
1705 } else if runtime.GOOS == "darwin" {
1706 return "darwin-x86"
1707 } else {
1708 panic("Unsupported OS")
1709 }
1710}
Dan Willemsenf173d592017-04-27 14:28:00 -07001711
Taylor Santiago3c16e612024-05-30 14:41:31 -07001712func (c *configImpl) KatiBin() string {
1713 binName := "ckati"
1714 if c.UseABFS() {
1715 binName = "ckati-wrap"
1716 }
1717
1718 return c.PrebuiltBuildTool(binName)
1719}
1720
1721func (c *configImpl) NinjaBin() string {
1722 binName := "ninja"
1723 if c.UseABFS() {
1724 binName = "ninjago"
1725 }
1726 return c.PrebuiltBuildTool(binName)
1727}
1728
Cole Faust4e58bba2024-08-22 14:27:03 -07001729func (c *configImpl) N2Bin() string {
1730 path := c.PrebuiltBuildTool("n2")
1731 // Use musl instead of glibc because glibc on the build server is old and has bugs
1732 return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
1733}
1734
LaMont Jonesece626c2024-09-03 11:19:31 -07001735func (c *configImpl) SisoBin() string {
1736 path := c.PrebuiltBuildTool("siso")
1737 // Use musl instead of glibc because glibc on the build server is old and has bugs
1738 return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
1739}
1740
Dan Willemsen8122bd52017-10-12 20:20:41 -07001741func (c *configImpl) PrebuiltBuildTool(name string) string {
Colin Cross7077be42024-10-04 20:37:16 +00001742 if c.environ.IsEnvTrue("SANITIZE_BUILD_TOOL_PREBUILTS") {
1743 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1744 if _, err := os.Stat(asan); err == nil {
1745 return asan
Dan Willemsenf173d592017-04-27 14:28:00 -07001746 }
1747 }
1748 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1749}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001750
1751func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1752 c.brokenDupRules = val
1753}
1754
1755func (c *configImpl) BuildBrokenDupRules() bool {
1756 return c.brokenDupRules
1757}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001758
Dan Willemsen25e6f092019-04-09 10:22:43 -07001759func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1760 c.brokenUsesNetwork = val
1761}
1762
1763func (c *configImpl) BuildBrokenUsesNetwork() bool {
1764 return c.brokenUsesNetwork
1765}
1766
Dan Willemsene3336352020-01-02 19:10:38 -08001767func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1768 c.brokenNinjaEnvVars = val
1769}
1770
1771func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1772 return c.brokenNinjaEnvVars
1773}
1774
Spandan Das28a6f192024-07-01 21:00:25 +00001775func (c *configImpl) SetBuildBrokenMissingOutputs(val bool) {
1776 c.brokenMissingOutputs = val
1777}
1778
1779func (c *configImpl) BuildBrokenMissingOutputs() bool {
1780 return c.brokenMissingOutputs
1781}
1782
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001783func (c *configImpl) SetTargetDeviceDir(dir string) {
1784 c.targetDeviceDir = dir
1785}
1786
1787func (c *configImpl) TargetDeviceDir() string {
1788 return c.targetDeviceDir
1789}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001790
Patrice Arruda219eef32020-06-01 17:29:30 +00001791func (c *configImpl) BuildDateTime() string {
1792 return c.buildDateTime
1793}
1794
1795func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001796 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001797}
Patrice Arruda83842d72020-12-08 19:42:08 +00001798
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001799// LogsDir returns the absolute path to the logs directory where build log and
1800// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001801// directory. If the argument dist is specified, the logs directory
1802// is <dist_dir>/logs.
1803func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001804 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001805 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001806 // 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 -05001807 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001808 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001809 absDir, err := filepath.Abs(dir)
1810 if err != nil {
1811 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1812 os.Exit(1)
1813 }
1814 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001815}
1816
Chris Parsons53f68ae2022-03-03 12:01:40 -05001817// MkFileMetrics returns the file path for make-related metrics.
1818func (c *configImpl) MkMetrics() string {
1819 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1820}
1821
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001822func (c *configImpl) SetEmptyNinjaFile(v bool) {
1823 c.emptyNinjaFile = v
1824}
1825
1826func (c *configImpl) EmptyNinjaFile() bool {
1827 return c.emptyNinjaFile
1828}
Yu Liu6e13b402021-07-27 14:29:06 -07001829
MarkDacekd0e7cd32022-12-02 22:22:40 +00001830func (c *configImpl) SkipMetricsUpload() bool {
Taylor Santiago8b0bed72024-09-03 13:30:22 -07001831 // b/362625275 - Metrics upload sometimes prevents abfs unmount
1832 if c.UseABFS() {
1833 return true
1834 }
1835
MarkDacekd0e7cd32022-12-02 22:22:40 +00001836 return c.skipMetricsUpload
1837}
1838
MarkDacekf47e1422023-04-19 16:47:36 +00001839func (c *configImpl) EnsureAllowlistIntegrity() bool {
1840 return c.ensureAllowlistIntegrity
1841}
1842
MarkDacek6614d9c2022-12-07 21:57:38 +00001843// Returns a Time object if one was passed via a command-line flag.
1844// Otherwise returns the passed default.
1845func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1846 if c.buildStartedTime == 0 {
1847 return defaultTime
1848 }
1849 return time.UnixMilli(c.buildStartedTime)
1850}
1851
Yu Liu6e13b402021-07-27 14:29:06 -07001852func GetMetricsUploader(topDir string, env *Environment) string {
1853 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1854 metricsUploader := filepath.Join(topDir, p)
1855 if _, err := os.Stat(metricsUploader); err == nil {
1856 return metricsUploader
1857 }
1858 }
1859
1860 return ""
1861}