blob: 8b73f9ff7670e035a0e833db822608e36c3986a0 [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
66)
67
Dan Willemsen1e704462016-08-21 15:17:17 -070068type Config struct{ *configImpl }
69
70type configImpl struct {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020071 // Some targets that are implemented in soong_build
Colin Cross28f527c2019-11-26 16:19:04 -080072 arguments []string
73 goma bool
74 environ *Environment
75 distDir string
76 buildDateTime string
MarkDacek6614d9c2022-12-07 21:57:38 +000077 logsPrefix string
Dan Willemsen1e704462016-08-21 15:17:17 -070078
79 // From the arguments
Cole Faust3740b282025-01-21 15:59:50 -080080 parallel int
81 keepGoing int
82 verbose bool
83 checkbuild bool
84 dist bool
85 jsonModuleGraph bool
86 reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
87 soongDocs bool
88 skipConfig bool
89 skipKati bool
90 skipKatiControlledByFlags bool
91 skipKatiNinja bool
92 skipSoong bool
93 skipNinja bool
94 skipSoongTests bool
95 searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
96 skipMetricsUpload bool
97 buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
98 buildFromSourceStub bool
99 incrementalBuildActions bool
100 ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
Dan Willemsen1e704462016-08-21 15:17:17 -0700101
102 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -0700103 katiArgs []string
104 ninjaArgs []string
105 katiSuffix string
106 targetDevice string
107 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +0000108 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -0700109
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800110 // Autodetected
LaMont Jones54b01cd2024-10-23 13:59:40 -0700111 totalRAM uint64
112 systemCpuInfo *metrics.CpuInfo
113 systemMemInfo *metrics.MemInfo
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800114
Spandan Das28a6f192024-07-01 21:00:25 +0000115 brokenDupRules bool
116 brokenUsesNetwork bool
117 brokenNinjaEnvVars []string
118 brokenMissingOutputs bool
Dan Willemsen18490112018-05-25 16:30:04 -0700119
120 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000121
Colin Crossf3bdbcb2021-06-01 11:43:55 -0700122 // Set by multiproduct_kati
123 emptyNinjaFile bool
Yu Liu6e13b402021-07-27 14:29:06 -0700124
125 metricsUploader string
MarkDacekd06db5d2022-11-29 00:47:59 +0000126
Sam Delmerico98a73292023-02-21 11:50:29 -0500127 includeTags []string
128 sourceRootDirs []string
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900129
130 // Data source to write ninja weight list
131 ninjaWeightListSource NinjaWeightListSource
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800132
133 // This file is a detailed dump of all soong-defined modules for debugging purposes.
134 // There's quite a bit of overlap with module-info.json and soong module graph. We
135 // could consider merging them.
136 moduleDebugFile string
Cole Faustbee030d2024-01-03 13:45:48 -0800137
LaMont Jonesece626c2024-09-03 11:19:31 -0700138 // Which builder are we using
139 ninjaCommand ninjaCommandType
Dan Willemsen1e704462016-08-21 15:17:17 -0700140}
141
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900142type NinjaWeightListSource uint
143
144const (
145 // ninja doesn't use weight list.
146 NOT_USED NinjaWeightListSource = iota
147 // ninja uses weight list based on previous builds by ninja log
148 NINJA_LOG
149 // ninja thinks every task has the same weight.
150 EVENLY_DISTRIBUTED
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900151 // ninja uses an external custom weight list
152 EXTERNAL_FILE
Jeongik Chae114e602023-03-19 00:12:39 +0900153 // ninja uses a prioritized module list from Soong
154 HINT_FROM_SOONG
Jeongik Chaa87506f2023-06-01 23:16:41 +0900155 // If ninja log exists, use NINJA_LOG, if not, use HINT_FROM_SOONG instead.
156 // We can assume it is an incremental build if ninja log exists.
157 DEFAULT
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900158)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800159const srcDirFileCheck = "build/soong/root.bp"
160
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700161var buildFiles = []string{"Android.mk", "Android.bp"}
162
Patrice Arruda13848222019-04-22 17:12:02 -0700163type BuildAction uint
164
165const (
166 // Builds all of the modules and their dependencies of a specified directory, relative to the root
167 // directory of the source tree.
168 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
169
170 // Builds all of the modules and their dependencies of a list of specified directories. All specified
171 // directories are relative to the root directory of the source tree.
172 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700173
174 // Build a list of specified modules. If none was specified, simply build the whole source tree.
175 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700176)
177
178// checkTopDir validates that the current directory is at the root directory of the source tree.
179func checkTopDir(ctx Context) {
180 if _, err := os.Stat(srcDirFileCheck); err != nil {
181 if os.IsNotExist(err) {
182 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
183 }
184 ctx.Fatalln("Error verifying tree state:", err)
185 }
186}
187
MarkDacek7901e582023-01-09 19:48:01 +0000188func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500189 if bc == "" {
190 return nil
191 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500192
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500193 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500194 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500195 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500196 envConfigDir,
197 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500198 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500199 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
200 envVarsJSON, err := ioutil.ReadFile(cfgFile)
201 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500202 continue
203 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500204 ctx.Verbosef("Loading config file %v\n", cfgFile)
205 var envVars map[string]map[string]string
206 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
207 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
208 continue
209 }
210 for k, v := range envVars["env"] {
211 if os.Getenv(k) != "" {
212 continue
213 }
214 config.environ.Set(k, v)
215 }
216 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
217 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500218 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500219
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500220 return nil
221}
222
Dan Willemsen1e704462016-08-21 15:17:17 -0700223func NewConfig(ctx Context, args ...string) Config {
224 ret := &configImpl{
Jeongik Chaf2ecf762023-05-19 14:03:45 +0900225 environ: OsEnvironment(),
226 sandboxConfig: &SandboxConfig{},
Jeongik Chaa87506f2023-06-01 23:16:41 +0900227 ninjaWeightListSource: DEFAULT,
Dan Willemsen1e704462016-08-21 15:17:17 -0700228 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700229 wd, err := os.Getwd()
230 if err != nil {
231 ctx.Fatalln("Failed to get working directory:", err)
232 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700233
Colin Cross106d6ef2023-10-24 10:34:56 -0700234 // Skip soong tests by default on Linux
235 if runtime.GOOS == "linux" {
236 ret.skipSoongTests = true
237 }
238
Patrice Arruda90109172020-07-28 18:07:27 +0000239 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700240 ret.parallel = runtime.NumCPU() + 2
241 ret.keepGoing = 1
242
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800243 ret.totalRAM = detectTotalRAM(ctx)
LaMont Jones54b01cd2024-10-23 13:59:40 -0700244 ret.systemCpuInfo, err = metrics.NewCpuInfo(fs.OsFs)
245 if err != nil {
246 ctx.Fatalln("Failed to get cpuinfo:", err)
247 }
248 ret.systemMemInfo, err = metrics.NewMemInfo(fs.OsFs)
249 if err != nil {
250 ctx.Fatalln("Failed to get meminfo:", err)
251 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700252 ret.parseArgs(ctx, args)
Jeongik Chae114e602023-03-19 00:12:39 +0900253
254 if ret.ninjaWeightListSource == HINT_FROM_SOONG {
Jeongik Chaa87506f2023-06-01 23:16:41 +0900255 ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "always")
256 } else if ret.ninjaWeightListSource == DEFAULT {
257 defaultNinjaWeightListSource := NINJA_LOG
258 if _, err := os.Stat(filepath.Join(ret.OutDir(), ninjaLogFileName)); errors.Is(err, os.ErrNotExist) {
259 ctx.Verboseln("$OUT/.ninja_log doesn't exist, use HINT_FROM_SOONG instead")
260 defaultNinjaWeightListSource = HINT_FROM_SOONG
261 } else {
262 ctx.Verboseln("$OUT/.ninja_log exist, use NINJA_LOG")
263 }
264 ret.ninjaWeightListSource = defaultNinjaWeightListSource
265 // soong_build generates ninja hint depending on ninja log existence.
266 // Set it "depend" to avoid soong re-run due to env variable change.
267 ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "depend")
Jeongik Chae114e602023-03-19 00:12:39 +0900268 }
Jeongik Chaa87506f2023-06-01 23:16:41 +0900269
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800270 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700271 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700272 ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, filepath.Clean(outDir)))
Dan Willemsen02f3add2017-05-12 13:50:19 -0700273 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800274 outDir := "out"
275 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700276 outDir = filepath.Join(baseDir, filepath.Base(wd))
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800277 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700278 ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, outDir))
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800279 }
280
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500281 // loadEnvConfig needs to know what the OUT_DIR is, so it should
282 // be called after we determine the appropriate out directory.
MarkDacek7901e582023-01-09 19:48:01 +0000283 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
284
285 if bc != "" {
Kousik Kumarc8818332023-01-16 16:33:05 +0000286 if err := loadEnvConfig(ctx, ret, bc); err != nil {
MarkDacek7901e582023-01-09 19:48:01 +0000287 ctx.Fatalln("Failed to parse env config files: %v", err)
288 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +0000289 if !ret.canSupportRBE() {
290 // Explicitly set USE_RBE env variable to false when we cannot run
291 // an RBE build to avoid ninja local execution pool issues.
292 ret.environ.Set("USE_RBE", "false")
293 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500294 }
295
Dan Willemsen2d31a442018-10-20 21:33:41 -0700296 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
297 ret.distDir = filepath.Clean(distDir)
298 } else {
299 ret.distDir = filepath.Join(ret.OutDir(), "dist")
300 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700301
Spandan Das05063612021-06-25 01:39:04 +0000302 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
303 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
304 }
305
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800306 if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
307 ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
308 }
309
LaMont Jones99f18962024-10-17 11:50:44 -0700310 // If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
311 // This simplifies the generated Ninja rules, so that they only need to check for the empty string.
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800312 if value, ok := ret.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
LaMont Jones99f18962024-10-17 11:50:44 -0700313 if value == "true" || value == "1" || value == "y" || value == "yes" {
314 value = "true"
315 } else {
316 value = ""
317 }
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800318 ret.environ.Set("SOONG_USE_PARTIAL_COMPILE", value)
LaMont Jones99f18962024-10-17 11:50:44 -0700319 }
320
LaMont Jonesece626c2024-09-03 11:19:31 -0700321 ret.ninjaCommand = NINJA_NINJA
322 switch os.Getenv("SOONG_NINJA") {
323 case "n2":
324 ret.ninjaCommand = NINJA_N2
325 case "siso":
326 ret.ninjaCommand = NINJA_SISO
327 default:
328 if os.Getenv("SOONG_USE_N2") == "true" {
329 ret.ninjaCommand = NINJA_N2
330 }
Cole Faustbee030d2024-01-03 13:45:48 -0800331 }
332
Dan Willemsen1e704462016-08-21 15:17:17 -0700333 ret.environ.Unset(
334 // We're already using it
335 "USE_SOONG_UI",
336
337 // We should never use GOROOT/GOPATH from the shell environment
338 "GOROOT",
339 "GOPATH",
340
341 // These should only come from Soong, not the environment.
342 "CLANG",
343 "CLANG_CXX",
344 "CCC_CC",
345 "CCC_CXX",
346
347 // Used by the goma compiler wrapper, but should only be set by
348 // gomacc
349 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800350
351 // We handle this above
352 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700353
Dan Willemsen2d31a442018-10-20 21:33:41 -0700354 // This is handled above too, and set for individual commands later
355 "DIST_DIR",
356
Dan Willemsen68a09852017-04-18 13:56:57 -0700357 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000358 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700359 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700360 "DISPLAY",
361 "GREP_OPTIONS",
Nathan Egge7b067fb2023-02-17 17:54:31 +0000362 "JAVAC",
Nathan Egge978c9342024-07-03 21:13:03 +0000363 "LEX",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700364 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700365 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700366
367 // Drop make flags
368 "MAKEFLAGS",
369 "MAKELEVEL",
370 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700371
372 // Set in envsetup.sh, reset in makefiles
373 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700374
375 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
376 "ANDROID_BUILD_TOP",
377 "ANDROID_HOST_OUT",
378 "ANDROID_PRODUCT_OUT",
379 "ANDROID_HOST_OUT_TESTCASES",
380 "ANDROID_TARGET_OUT_TESTCASES",
381 "ANDROID_TOOLCHAIN",
382 "ANDROID_TOOLCHAIN_2ND_ARCH",
383 "ANDROID_DEV_SCRIPTS",
384 "ANDROID_EMULATOR_PREBUILTS",
385 "ANDROID_PRE_BUILD_PATHS",
Joe Onoratoe5ed3472024-02-02 14:52:05 -0800386
387 // We read it here already, don't let others share in the fun
388 "GENERATE_SOONG_DEBUG",
Cole Faustbee030d2024-01-03 13:45:48 -0800389
LaMont Jonesece626c2024-09-03 11:19:31 -0700390 // Use config.ninjaCommand instead.
391 "SOONG_NINJA",
Cole Faustbee030d2024-01-03 13:45:48 -0800392 "SOONG_USE_N2",
Dan Willemsen1e704462016-08-21 15:17:17 -0700393 )
394
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400395 if ret.UseGoma() || ret.ForceUseGoma() {
396 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
397 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400398 }
399
Dan Willemsen1e704462016-08-21 15:17:17 -0700400 // Tell python not to spam the source tree with .pyc files.
401 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
402
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400403 tmpDir := absPath(ctx, ret.TempDir())
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700404 ret.environ.Set("TMPDIR", ret.sandboxPath(wd, tmpDir))
Dan Willemsen32a669b2018-03-08 19:42:00 -0800405
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700406 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
407 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
408 "llvm-binutils-stable/llvm-symbolizer")
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700409 ret.environ.Set("ASAN_SYMBOLIZER_PATH", ret.sandboxPath(wd, absPath(ctx, symbolizerPath)))
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700410
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800411 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700412 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800413
Yu Liu6e13b402021-07-27 14:29:06 -0700414 srcDir := absPath(ctx, ".")
415 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700416 ctx.Println("You are building in a directory whose absolute path contains a space character:")
417 ctx.Println()
418 ctx.Printf("%q\n", srcDir)
419 ctx.Println()
420 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700421 }
422
Yu Liu6e13b402021-07-27 14:29:06 -0700423 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
424
Dan Willemsendb8457c2017-05-12 16:38:17 -0700425 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700426 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
427 ctx.Println()
428 ctx.Printf("%q\n", outDir)
429 ctx.Println()
430 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700431 }
432
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000433 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700434 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
435 ctx.Println()
436 ctx.Printf("%q\n", distDir)
437 ctx.Println()
438 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700439 }
440
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700441 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000442 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
Sorin Basca0760c892023-11-29 19:13:55 +0000443 java21Home := filepath.Join("prebuilts/jdk/jdk21", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700444 javaHome := func() string {
445 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
446 return override
447 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000448 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
Sorin Basca5dfa2382024-03-11 17:23:06 +0000449 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 +0100450 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000451 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
Sorin Basca5dfa2382024-03-11 17:23:06 +0000452 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 +0000453 }
Sorin Basca5dfa2382024-03-11 17:23:06 +0000454 if toolchain21, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN"); ok && toolchain21 != "true" {
455 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN is no longer supported. An OpenJDK 21 toolchain is now the global default.")
456 }
457 return java21Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700458 }()
459 absJavaHome := absPath(ctx, javaHome)
460
Dan Willemsened869522018-01-08 14:58:46 -0800461 ret.configureLocale(ctx)
462
PODISHETTY KUMAR (xWF)9543d192024-09-02 03:54:36 +0000463 newPath := []string{filepath.Join(absJavaHome, "bin")}
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700464 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
PODISHETTY KUMAR (xWF)9543d192024-09-02 03:54:36 +0000465 newPath = append(newPath, path)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700466 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100467
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700468 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700469 ret.environ.Set("JAVA_HOME", ret.sandboxPath(wd, absJavaHome))
470 ret.environ.Set("ANDROID_JAVA_HOME", ret.sandboxPath(wd, javaHome))
471 ret.environ.Set("ANDROID_JAVA8_HOME", ret.sandboxPath(wd, java8Home))
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700472 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
473
Colin Crossfe5ed4d2023-07-28 09:27:23 -0700474 // b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches
475 // to unzip to enable zipbomb detection that incorrectly handle zip64 and data descriptors and fail on large
476 // zip files produced by soong_zip. Disable zipbomb detection.
477 ret.environ.Set("UNZIP_DISABLE_ZIPBOMB_DETECTION", "TRUE")
478
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800479 outDir := ret.OutDir()
480 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800481 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800482 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800483 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800484 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800485 }
Colin Cross28f527c2019-11-26 16:19:04 -0800486
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700487 ret.environ.Set("BUILD_DATETIME_FILE", ret.sandboxPath(wd, buildDateTimeFile))
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800488
Cole Faust583dfb42023-09-28 13:56:30 -0700489 if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok {
490 username := "unknown"
491 if u, err := user.Current(); err == nil {
492 username = u.Username
493 } else {
494 ctx.Println("Failed to get current user:", err)
495 }
496 ret.environ.Set("BUILD_USERNAME", username)
497 }
Taylor Santiago8b0bed72024-09-03 13:30:22 -0700498 ret.environ.Set("PWD", ret.sandboxPath(wd, wd))
Cole Faust583dfb42023-09-28 13:56:30 -0700499
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400500 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400501 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400502 ret.environ.Set(k, v)
503 }
504 }
505
Patrice Arruda96850362020-08-11 20:41:11 +0000506 c := Config{ret}
507 storeConfigMetrics(ctx, c)
508 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700509}
510
Patrice Arruda13848222019-04-22 17:12:02 -0700511// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
512// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700513func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
514 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700515}
516
LaMont Jones9a912862023-11-06 22:11:08 +0000517// Prepare for getting make variables. For them to be accurate, we need to have
518// obtained PRODUCT_RELEASE_CONFIG_MAPS.
519//
520// Returns:
521//
522// Whether config should be called again.
523//
524// TODO: when converting product config to a declarative language, make sure
525// that PRODUCT_RELEASE_CONFIG_MAPS is properly handled as a separate step in
526// that process.
527func SetProductReleaseConfigMaps(ctx Context, config Config) bool {
528 ctx.BeginTrace(metrics.RunKati, "SetProductReleaseConfigMaps")
529 defer ctx.EndTrace()
530
531 if config.SkipConfig() {
532 // This duplicates the logic from Build to skip product config
533 // if the user has explicitly said to.
534 return false
535 }
536
537 releaseConfigVars := []string{
538 "PRODUCT_RELEASE_CONFIG_MAPS",
539 }
540
541 origValue, _ := config.environ.Get("PRODUCT_RELEASE_CONFIG_MAPS")
542 // Get the PRODUCT_RELEASE_CONFIG_MAPS for this product, to avoid polluting the environment
543 // when we run product config to get the rest of the make vars.
544 releaseMapVars, err := dumpMakeVars(ctx, config, nil, releaseConfigVars, false, "")
545 if err != nil {
546 ctx.Fatalln("Error getting PRODUCT_RELEASE_CONFIG_MAPS:", err)
547 }
548 productReleaseConfigMaps := releaseMapVars["PRODUCT_RELEASE_CONFIG_MAPS"]
549 os.Setenv("PRODUCT_RELEASE_CONFIG_MAPS", productReleaseConfigMaps)
550 return origValue != productReleaseConfigMaps
551}
552
Patrice Arruda96850362020-08-11 20:41:11 +0000553// storeConfigMetrics selects a set of configuration information and store in
554// the metrics system for further analysis.
555func storeConfigMetrics(ctx Context, config Config) {
556 if ctx.Metrics == nil {
557 return
558 }
559
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400560 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000561
LaMont Jones54b01cd2024-10-23 13:59:40 -0700562 cpuInfo := &smpb.SystemCpuInfo{
563 VendorId: proto.String(config.systemCpuInfo.VendorId),
564 ModelName: proto.String(config.systemCpuInfo.ModelName),
565 CpuCores: proto.Int32(config.systemCpuInfo.CpuCores),
566 Flags: proto.String(config.systemCpuInfo.Flags),
567 }
568 memInfo := &smpb.SystemMemInfo{
569 MemTotal: proto.Uint64(config.systemMemInfo.MemTotal),
570 MemFree: proto.Uint64(config.systemMemInfo.MemFree),
571 MemAvailable: proto.Uint64(config.systemMemInfo.MemAvailable),
572 }
573
Patrice Arruda3edfd482020-10-13 23:58:41 +0000574 s := &smpb.SystemResourceInfo{
575 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
576 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
LaMont Jones54b01cd2024-10-23 13:59:40 -0700577 CpuInfo: cpuInfo,
578 MemInfo: memInfo,
Patrice Arruda3edfd482020-10-13 23:58:41 +0000579 }
580 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000581}
582
Jeongik Cha8d63d562023-03-17 03:52:13 +0900583func getNinjaWeightListSourceInMetric(s NinjaWeightListSource) *smpb.BuildConfig_NinjaWeightListSource {
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900584 switch s {
585 case NINJA_LOG:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900586 return smpb.BuildConfig_NINJA_LOG.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900587 case EVENLY_DISTRIBUTED:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900588 return smpb.BuildConfig_EVENLY_DISTRIBUTED.Enum()
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900589 case EXTERNAL_FILE:
590 return smpb.BuildConfig_EXTERNAL_FILE.Enum()
Jeongik Chae114e602023-03-19 00:12:39 +0900591 case HINT_FROM_SOONG:
592 return smpb.BuildConfig_HINT_FROM_SOONG.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900593 default:
Jeongik Cha8d63d562023-03-17 03:52:13 +0900594 return smpb.BuildConfig_NOT_USED.Enum()
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900595 }
596}
597
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400598func buildConfig(config Config) *smpb.BuildConfig {
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800599 var soongEnvVars *smpb.SoongEnvVars
600 ensure := func() *smpb.SoongEnvVars {
601 // Create soongEnvVars if it doesn't already exist.
602 if soongEnvVars == nil {
603 soongEnvVars = &smpb.SoongEnvVars{}
604 }
605 return soongEnvVars
606 }
607 if value, ok := config.environ.Get("SOONG_PARTIAL_COMPILE"); ok {
608 ensure().PartialCompile = proto.String(value)
609 }
610 if value, ok := config.environ.Get("SOONG_USE_PARTIAL_COMPILE"); ok {
611 ensure().UsePartialCompile = proto.String(value)
612 }
Yu Liue737a992021-10-04 13:21:41 -0700613 c := &smpb.BuildConfig{
Colin Cross8d411ff2023-12-07 10:31:24 -0800614 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
615 UseGoma: proto.Bool(config.UseGoma()),
616 UseRbe: proto.Bool(config.UseRBE()),
617 NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
LaMont Jonesb547c7e2024-12-19 09:52:01 -0800618 SoongEnvVars: soongEnvVars,
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400619 }
Yu Liue737a992021-10-04 13:21:41 -0700620 c.Targets = append(c.Targets, config.arguments...)
621
622 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400623}
624
Patrice Arruda13848222019-04-22 17:12:02 -0700625// getConfigArgs processes the command arguments based on the build action and creates a set of new
626// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700627func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700628 // The next block of code verifies that the current directory is the root directory of the source
629 // tree. It then finds the relative path of dir based on the root directory of the source tree
630 // and verify that dir is inside of the source tree.
631 checkTopDir(ctx)
632 topDir, err := os.Getwd()
633 if err != nil {
634 ctx.Fatalf("Error retrieving top directory: %v", err)
635 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700636 dir, err = filepath.EvalSymlinks(dir)
637 if err != nil {
638 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
639 }
Patrice Arruda13848222019-04-22 17:12:02 -0700640 dir, err = filepath.Abs(dir)
641 if err != nil {
642 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
643 }
644 relDir, err := filepath.Rel(topDir, dir)
645 if err != nil {
646 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
647 }
648 // If there are ".." in the path, it's not in the source tree.
649 if strings.Contains(relDir, "..") {
650 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
651 }
652
653 configArgs := args[:]
654
655 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
656 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
657 targetNamePrefix := "MODULES-IN-"
658 if inList("GET-INSTALL-PATH", configArgs) {
659 targetNamePrefix = "GET-INSTALL-PATH-IN-"
660 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
661 }
662
Patrice Arruda13848222019-04-22 17:12:02 -0700663 var targets []string
664
665 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700666 case BUILD_MODULES:
667 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700668 case BUILD_MODULES_IN_A_DIRECTORY:
669 // If dir is the root source tree, all the modules are built of the source tree are built so
670 // no need to find the build file.
671 if topDir == dir {
672 break
673 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700674
Patrice Arruda13848222019-04-22 17:12:02 -0700675 buildFile := findBuildFile(ctx, relDir)
676 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700677 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700678 }
Patrice Arruda13848222019-04-22 17:12:02 -0700679 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
680 case BUILD_MODULES_IN_DIRECTORIES:
681 newConfigArgs, dirs := splitArgs(configArgs)
682 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700683 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700684 }
685
686 // Tidy only override all other specified targets.
687 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
688 if tidyOnly == "true" || tidyOnly == "1" {
689 configArgs = append(configArgs, "tidy_only")
690 } else {
691 configArgs = append(configArgs, targets...)
692 }
693
694 return configArgs
695}
696
697// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
698func convertToTarget(dir string, targetNamePrefix string) string {
699 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
700}
701
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700702// hasBuildFile returns true if dir contains an Android build file.
703func hasBuildFile(ctx Context, dir string) bool {
704 for _, buildFile := range buildFiles {
705 _, err := os.Stat(filepath.Join(dir, buildFile))
706 if err == nil {
707 return true
708 }
709 if !os.IsNotExist(err) {
710 ctx.Fatalf("Error retrieving the build file stats: %v", err)
711 }
712 }
713 return false
714}
715
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700716// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
717// in the current and any sub directory of dir. If a build file is not found, traverse the path
718// up by one directory and repeat again until either a build file is found or reached to the root
719// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
720// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700721func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700722 // If the string is empty or ".", assume it is top directory of the source tree.
723 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700724 return ""
725 }
726
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700727 found := false
728 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
729 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
730 if err != nil {
731 return err
732 }
733 if found {
734 return filepath.SkipDir
735 }
736 if info.IsDir() {
737 return nil
738 }
739 for _, buildFile := range buildFiles {
740 if info.Name() == buildFile {
741 found = true
742 return filepath.SkipDir
743 }
744 }
745 return nil
746 })
747 if err != nil {
748 ctx.Fatalf("Error finding Android build file: %v", err)
749 }
750
751 if found {
752 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700753 }
754 }
755
756 return ""
757}
758
759// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
760func splitArgs(args []string) (newArgs []string, dirs []string) {
761 specialArgs := map[string]bool{
762 "showcommands": true,
763 "snod": true,
764 "dist": true,
765 "checkbuild": true,
766 }
767
768 newArgs = []string{}
769 dirs = []string{}
770
771 for _, arg := range args {
772 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
773 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
774 newArgs = append(newArgs, arg)
775 continue
776 }
777
778 if _, ok := specialArgs[arg]; ok {
779 newArgs = append(newArgs, arg)
780 continue
781 }
782
783 dirs = append(dirs, arg)
784 }
785
786 return newArgs, dirs
787}
788
789// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
790// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
791// source root tree where the build action command was invoked. Each directory is validated if the
792// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700793func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700794 for _, dir := range dirs {
795 // The directory may have specified specific modules to build. ":" is the separator to separate
796 // the directory and the list of modules.
797 s := strings.Split(dir, ":")
798 l := len(s)
799 if l > 2 { // more than one ":" was specified.
800 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
801 }
802
803 dir = filepath.Join(relDir, s[0])
804 if _, err := os.Stat(dir); err != nil {
805 ctx.Fatalf("couldn't find directory %s", dir)
806 }
807
808 // Verify that if there are any targets specified after ":". Each target is separated by ",".
809 var newTargets []string
810 if l == 2 && s[1] != "" {
811 newTargets = strings.Split(s[1], ",")
812 if inList("", newTargets) {
813 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
814 }
815 }
816
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700817 // If there are specified targets to build in dir, an android build file must exist for the one
818 // shot build. For the non-targets case, find the appropriate build file and build all the
819 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700820 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700821 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700822 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
823 }
824 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700825 buildFile := findBuildFile(ctx, dir)
826 if buildFile == "" {
827 ctx.Fatalf("Build file not found for %s directory", dir)
828 }
829 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700830 }
831
Patrice Arruda13848222019-04-22 17:12:02 -0700832 targets = append(targets, newTargets...)
833 }
834
Dan Willemsence41e942019-07-29 23:39:30 -0700835 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700836}
837
Dan Willemsen9b587492017-07-10 22:13:00 -0700838func (c *configImpl) parseArgs(ctx Context, args []string) {
839 for i := 0; i < len(args); i++ {
840 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100841 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700842 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200843 } else if arg == "--empty-ninja-file" {
844 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100845 } else if arg == "--skip-ninja" {
846 c.skipNinja = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100847 } else if arg == "--soong-only" {
Cole Faust3740b282025-01-21 15:59:50 -0800848 if c.skipKatiControlledByFlags {
849 ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
850 }
851 c.skipKatiControlledByFlags = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100852 c.skipKati = true
853 c.skipKatiNinja = true
Cole Faust3740b282025-01-21 15:59:50 -0800854 } else if arg == "--no-soong-only" {
855 if c.skipKatiControlledByFlags {
856 ctx.Fatalf("Cannot specify both --soong-only and --no-soong-only")
857 }
858 c.skipKatiControlledByFlags = true
859 c.skipKati = false
860 c.skipKatiNinja = false
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200861 } else if arg == "--config-only" {
862 c.skipKati = true
863 c.skipKatiNinja = true
864 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700865 } else if arg == "--skip-config" {
866 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700867 } else if arg == "--skip-soong-tests" {
868 c.skipSoongTests = true
Colin Cross106d6ef2023-10-24 10:34:56 -0700869 } else if arg == "--no-skip-soong-tests" {
870 c.skipSoongTests = false
MarkDacekd0e7cd32022-12-02 22:22:40 +0000871 } else if arg == "--skip-metrics-upload" {
872 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500873 } else if arg == "--mk-metrics" {
874 c.reportMkMetrics = true
Spandan Das394aa322022-11-03 17:02:10 +0000875 } else if arg == "--search-api-dir" {
876 c.searchApiDir = true
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900877 } else if strings.HasPrefix(arg, "--ninja_weight_source=") {
878 source := strings.TrimPrefix(arg, "--ninja_weight_source=")
879 if source == "ninja_log" {
880 c.ninjaWeightListSource = NINJA_LOG
881 } else if source == "evenly_distributed" {
882 c.ninjaWeightListSource = EVENLY_DISTRIBUTED
883 } else if source == "not_used" {
884 c.ninjaWeightListSource = NOT_USED
Jeongik Chae114e602023-03-19 00:12:39 +0900885 } else if source == "soong" {
886 c.ninjaWeightListSource = HINT_FROM_SOONG
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900887 } else if strings.HasPrefix(source, "file,") {
888 c.ninjaWeightListSource = EXTERNAL_FILE
889 filePath := strings.TrimPrefix(source, "file,")
890 err := validateNinjaWeightList(filePath)
891 if err != nil {
892 ctx.Fatalf("Malformed weight list from %s: %s", filePath, err)
893 }
894 _, err = copyFile(filePath, filepath.Join(c.OutDir(), ".ninja_weight_list"))
895 if err != nil {
896 ctx.Fatalf("Error to copy ninja weight list from %s: %s", filePath, err)
897 }
Jeongik Cha0cf44d52023-03-15 00:10:45 +0900898 } else {
899 ctx.Fatalf("unknown option for ninja_weight_source: %s", source)
900 }
Jihoon Kang2a929ad2023-06-08 19:02:07 +0000901 } else if arg == "--build-from-source-stub" {
902 c.buildFromSourceStub = true
Yu Liufa297642024-06-11 00:13:02 +0000903 } else if arg == "--incremental-build-actions" {
904 c.incrementalBuildActions = true
MarkDacekb96561e2022-12-02 04:34:43 +0000905 } else if strings.HasPrefix(arg, "--build-command=") {
906 buildCmd := strings.TrimPrefix(arg, "--build-command=")
907 // remove quotations
908 buildCmd = strings.TrimPrefix(buildCmd, "\"")
909 buildCmd = strings.TrimSuffix(buildCmd, "\"")
910 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacek6614d9c2022-12-07 21:57:38 +0000911 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
912 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
913 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
914 if err == nil {
915 c.buildStartedTime = val
916 } else {
917 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
918 }
MarkDacekf47e1422023-04-19 16:47:36 +0000919 } else if arg == "--ensure-allowlist-integrity" {
920 c.ensureAllowlistIntegrity = true
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700921 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700922 parseArgNum := func(def int) int {
923 if len(arg) > 2 {
924 p, err := strconv.ParseUint(arg[2:], 10, 31)
925 if err != nil {
926 ctx.Fatalf("Failed to parse %q: %v", arg, err)
927 }
928 return int(p)
929 } else if i+1 < len(args) {
930 p, err := strconv.ParseUint(args[i+1], 10, 31)
931 if err == nil {
932 i++
933 return int(p)
934 }
935 }
936 return def
937 }
938
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700939 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700940 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700941 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700942 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700943 } else {
944 ctx.Fatalln("Unknown option:", arg)
945 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700946 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700947 if k == "OUT_DIR" {
948 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
949 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700950 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700951 } else if arg == "dist" {
952 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200953 } else if arg == "json-module-graph" {
954 c.jsonModuleGraph = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200955 } else if arg == "soong_docs" {
956 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700957 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700958 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800959 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700960 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700961 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700962 }
963 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700964}
965
Jeongik Cha518f3ea2023-03-19 00:12:39 +0900966func validateNinjaWeightList(weightListFilePath string) (err error) {
967 data, err := os.ReadFile(weightListFilePath)
968 if err != nil {
969 return
970 }
971 lines := strings.Split(strings.TrimSpace(string(data)), "\n")
972 for _, line := range lines {
973 fields := strings.Split(line, ",")
974 if len(fields) != 2 {
975 return fmt.Errorf("wrong format, each line should have two fields, but '%s'", line)
976 }
977 _, err = strconv.Atoi(fields[1])
978 if err != nil {
979 return
980 }
981 }
982 return
983}
984
Dan Willemsened869522018-01-08 14:58:46 -0800985func (c *configImpl) configureLocale(ctx Context) {
986 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
987 output, err := cmd.Output()
988
989 var locales []string
990 if err == nil {
991 locales = strings.Split(string(output), "\n")
992 } else {
993 // If we're unable to list the locales, let's assume en_US.UTF-8
994 locales = []string{"en_US.UTF-8"}
995 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
996 }
997
998 // gettext uses LANGUAGE, which is passed directly through
999
1000 // For LANG and LC_*, only preserve the evaluated version of
1001 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001002 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -08001003 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001004 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -08001005 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001006 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -08001007 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001008 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -08001009 }
1010
1011 c.environ.UnsetWithPrefix("LC_")
1012
Jaewoong Jung18aefc12020-12-21 09:11:10 -08001013 if userLang != "" {
1014 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -08001015 }
1016
1017 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
1018 // for others)
1019 if inList("C.UTF-8", locales) {
1020 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -05001021 } else if inList("C.utf8", locales) {
1022 // These normalize to the same thing
1023 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -08001024 } else if inList("en_US.UTF-8", locales) {
1025 c.environ.Set("LANG", "en_US.UTF-8")
1026 } else if inList("en_US.utf8", locales) {
1027 // These normalize to the same thing
1028 c.environ.Set("LANG", "en_US.UTF-8")
1029 } else {
1030 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
1031 }
1032}
1033
Dan Willemsen1e704462016-08-21 15:17:17 -07001034func (c *configImpl) Environment() *Environment {
1035 return c.environ
1036}
1037
1038func (c *configImpl) Arguments() []string {
1039 return c.arguments
1040}
1041
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001042func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001043 if len(c.Arguments()) > 0 {
1044 // Explicit targets requested that are not special targets like b2pbuild
1045 // or the JSON module graph
1046 return true
1047 }
1048
Joe Onorato35f300d2024-10-21 15:02:44 -07001049 if !c.JsonModuleGraph() && !c.SoongDocs() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001050 // Command line was empty, the default Ninja target is built
1051 return true
1052 }
1053
Colin Cross8d411ff2023-12-07 10:31:24 -08001054 if c.Dist() {
Liz Kammer88677422021-12-15 15:03:19 -05001055 return true
1056 }
1057
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001058 // build.ninja doesn't need to be generated
1059 return false
1060}
1061
Dan Willemsen1e704462016-08-21 15:17:17 -07001062func (c *configImpl) OutDir() string {
1063 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -07001064 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -07001065 }
1066 return "out"
1067}
1068
Dan Willemsen8a073a82017-02-04 17:30:44 -08001069func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -04001070 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001071}
1072
1073func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -07001074 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -08001075}
1076
Dan Willemsen1e704462016-08-21 15:17:17 -07001077func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001078 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001079 return c.arguments
1080 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001081 return c.ninjaArgs
1082}
1083
1084func (c *configImpl) SoongOutDir() string {
1085 return filepath.Join(c.OutDir(), "soong")
1086}
1087
Spandan Das394aa322022-11-03 17:02:10 +00001088func (c *configImpl) ApiSurfacesOutDir() string {
1089 return filepath.Join(c.OutDir(), "api_surfaces")
1090}
1091
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001092func (c *configImpl) PrebuiltOS() string {
1093 switch runtime.GOOS {
1094 case "linux":
1095 return "linux-x86"
1096 case "darwin":
1097 return "darwin-x86"
1098 default:
1099 panic("Unknown GOOS")
1100 }
1101}
Lukacs T. Berki90b43342021-11-02 14:42:04 +01001102
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001103func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -07001104 if c.SkipKatiNinja() {
1105 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
1106 } else {
1107 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
1108 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +02001109}
1110
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001111func (c *configImpl) UsedEnvFile(tag string) string {
Kiyoung Kimeaa55a82023-06-05 16:56:49 +09001112 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
Qing Shen713c5422024-08-23 04:09:18 +00001113 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+v+c.CoverageSuffix()+"."+tag)
Kiyoung Kimeaa55a82023-06-05 16:56:49 +09001114 }
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001115 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
1116}
1117
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001118func (c *configImpl) SoongDocsHtml() string {
1119 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
1120}
1121
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001122func (c *configImpl) ModuleGraphFile() string {
1123 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1124}
1125
kgui67007242022-01-25 13:50:25 +08001126func (c *configImpl) ModuleActionsFile() string {
1127 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1128}
1129
Jeff Gastonefc1b412017-03-29 17:29:06 -07001130func (c *configImpl) TempDir() string {
1131 return shared.TempDirForOutDir(c.SoongOutDir())
1132}
1133
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001134func (c *configImpl) FileListDir() string {
1135 return filepath.Join(c.OutDir(), ".module_paths")
1136}
1137
Dan Willemsen1e704462016-08-21 15:17:17 -07001138func (c *configImpl) KatiSuffix() string {
1139 if c.katiSuffix != "" {
1140 return c.katiSuffix
1141 }
1142 panic("SetKatiSuffix has not been called")
1143}
1144
Colin Cross37193492017-11-16 17:55:00 -08001145// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1146// user is interested in additional checks at the expense of build time.
1147func (c *configImpl) Checkbuild() bool {
1148 return c.checkbuild
1149}
1150
Dan Willemsen8a073a82017-02-04 17:30:44 -08001151func (c *configImpl) Dist() bool {
1152 return c.dist
1153}
1154
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001155func (c *configImpl) JsonModuleGraph() bool {
1156 return c.jsonModuleGraph
1157}
1158
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001159func (c *configImpl) SoongDocs() bool {
1160 return c.soongDocs
1161}
1162
Dan Willemsen1e704462016-08-21 15:17:17 -07001163func (c *configImpl) IsVerbose() bool {
1164 return c.verbose
1165}
1166
Jeongik Cha0cf44d52023-03-15 00:10:45 +09001167func (c *configImpl) NinjaWeightListSource() NinjaWeightListSource {
1168 return c.ninjaWeightListSource
1169}
1170
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001171func (c *configImpl) SkipKati() bool {
1172 return c.skipKati
1173}
1174
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001175func (c *configImpl) SkipKatiNinja() bool {
1176 return c.skipKatiNinja
1177}
1178
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001179func (c *configImpl) SkipSoong() bool {
1180 return c.skipSoong
1181}
1182
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001183func (c *configImpl) SkipNinja() bool {
1184 return c.skipNinja
1185}
1186
Anton Hansson5a7861a2021-06-04 10:09:01 +01001187func (c *configImpl) SetSkipNinja(v bool) {
1188 c.skipNinja = v
1189}
1190
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001191func (c *configImpl) SkipConfig() bool {
1192 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001193}
1194
Jihoon Kang1bff0342023-01-17 20:40:22 +00001195func (c *configImpl) BuildFromTextStub() bool {
Jihoon Kang2a929ad2023-06-08 19:02:07 +00001196 return !c.buildFromSourceStub
Jihoon Kang1bff0342023-01-17 20:40:22 +00001197}
1198
Dan Willemsen1e704462016-08-21 15:17:17 -07001199func (c *configImpl) TargetProduct() string {
1200 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1201 return v
1202 }
1203 panic("TARGET_PRODUCT is not defined")
1204}
1205
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001206func (c *configImpl) TargetProductOrErr() (string, error) {
1207 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1208 return v, nil
1209 }
1210 return "", fmt.Errorf("TARGET_PRODUCT is not defined")
1211}
1212
Qing Shen713c5422024-08-23 04:09:18 +00001213func (c *configImpl) CoverageSuffix() string {
1214 if v := c.environ.IsEnvTrue("EMMA_INSTRUMENT"); v {
1215 return ".coverage"
1216 }
1217 return ""
1218}
1219
Dan Willemsen02781d52017-05-12 19:28:13 -07001220func (c *configImpl) TargetDevice() string {
1221 return c.targetDevice
1222}
1223
1224func (c *configImpl) SetTargetDevice(device string) {
1225 c.targetDevice = device
1226}
1227
1228func (c *configImpl) TargetBuildVariant() string {
1229 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1230 return v
1231 }
1232 panic("TARGET_BUILD_VARIANT is not defined")
1233}
1234
Dan Willemsen1e704462016-08-21 15:17:17 -07001235func (c *configImpl) KatiArgs() []string {
1236 return c.katiArgs
1237}
1238
1239func (c *configImpl) Parallel() int {
1240 return c.parallel
1241}
1242
Sam Delmerico98a73292023-02-21 11:50:29 -05001243func (c *configImpl) GetSourceRootDirs() []string {
1244 return c.sourceRootDirs
1245}
1246
1247func (c *configImpl) SetSourceRootDirs(i []string) {
1248 c.sourceRootDirs = i
1249}
1250
MarkDacek6614d9c2022-12-07 21:57:38 +00001251func (c *configImpl) GetLogsPrefix() string {
1252 return c.logsPrefix
1253}
1254
1255func (c *configImpl) SetLogsPrefix(prefix string) {
1256 c.logsPrefix = prefix
1257}
1258
Colin Cross8b8bec32019-11-15 13:18:43 -08001259func (c *configImpl) HighmemParallel() int {
1260 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1261 return i
1262 }
1263
1264 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1265 parallel := c.Parallel()
1266 if c.UseRemoteBuild() {
1267 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1268 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1269 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1270 // Return 1/16th of the size of the local pool, rounding up.
1271 return (parallel + 15) / 16
1272 } else if c.totalRAM == 0 {
1273 // Couldn't detect the total RAM, don't restrict highmem processes.
1274 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001275 } else if c.totalRAM <= 16*1024*1024*1024 {
1276 // Less than 16GB of ram, restrict to 1 highmem processes
1277 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001278 } else if c.totalRAM <= 32*1024*1024*1024 {
1279 // Less than 32GB of ram, restrict to 2 highmem processes
1280 return 2
1281 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1282 // If less than 8GB total RAM per process, reduce the number of highmem processes
1283 return p
1284 }
1285 // No restriction on highmem processes
1286 return parallel
1287}
1288
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001289func (c *configImpl) TotalRAM() uint64 {
1290 return c.totalRAM
1291}
1292
Kousik Kumarec478642020-09-21 13:39:24 -04001293// ForceUseGoma determines whether we should override Goma deprecation
1294// and use Goma for the current build or not.
1295func (c *configImpl) ForceUseGoma() bool {
1296 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1297 v = strings.TrimSpace(v)
1298 if v != "" && v != "false" {
1299 return true
1300 }
1301 }
1302 return false
1303}
1304
Dan Willemsen1e704462016-08-21 15:17:17 -07001305func (c *configImpl) UseGoma() bool {
1306 if v, ok := c.environ.Get("USE_GOMA"); ok {
1307 v = strings.TrimSpace(v)
1308 if v != "" && v != "false" {
1309 return true
1310 }
1311 }
1312 return false
1313}
1314
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001315func (c *configImpl) StartGoma() bool {
1316 if !c.UseGoma() {
1317 return false
1318 }
1319
1320 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1321 v = strings.TrimSpace(v)
1322 if v != "" && v != "false" {
1323 return false
1324 }
1325 }
1326 return true
1327}
1328
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001329func (c *configImpl) canSupportRBE() bool {
Joe Onorato86f50e72024-06-24 14:28:25 -07001330 // Only supported on linux
1331 if runtime.GOOS != "linux" {
1332 return false
1333 }
1334
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001335 // Do not use RBE with prod credentials in scenarios when stubby doesn't exist, since
1336 // its unlikely that we will be able to obtain necessary creds without stubby.
1337 authType, _ := c.rbeAuth()
1338 if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") {
1339 return false
1340 }
Taylor Santiago3c16e612024-05-30 14:41:31 -07001341 if c.UseABFS() {
1342 return false
1343 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001344 return true
1345}
1346
Taylor Santiago3c16e612024-05-30 14:41:31 -07001347func (c *configImpl) UseABFS() bool {
1348 if v, ok := c.environ.Get("NO_ABFS"); ok {
1349 v = strings.ToLower(strings.TrimSpace(v))
1350 if v == "true" || v == "1" {
1351 return false
1352 }
1353 }
1354
1355 abfsBox := c.PrebuiltBuildTool("abfsbox")
1356 err := exec.Command(abfsBox, "hash", srcDirFileCheck).Run()
1357 return err == nil
1358}
1359
Taylor Santiago8b0bed72024-09-03 13:30:22 -07001360func (c *configImpl) sandboxPath(base, in string) string {
1361 if !c.UseABFS() {
1362 return in
1363 }
1364
1365 rel, err := filepath.Rel(base, in)
1366 if err != nil {
1367 return in
1368 }
1369
1370 return filepath.Join(abfsSrcDir, rel)
1371}
1372
Ramy Medhatbbf25672019-07-17 12:30:04 +00001373func (c *configImpl) UseRBE() bool {
Jingwen Chend7ccde12023-06-28 07:19:26 +00001374 // These alternate modes of running Soong do not use RBE / reclient.
Joe Onorato35f300d2024-10-21 15:02:44 -07001375 if c.JsonModuleGraph() {
Jingwen Chend7ccde12023-06-28 07:19:26 +00001376 return false
1377 }
1378
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001379 if !c.canSupportRBE() {
Kousik Kumar67ad4342023-06-06 15:09:27 -04001380 return false
1381 }
Kousik Kumar6d1e3482023-07-24 03:44:16 +00001382
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001383 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001384 v = strings.TrimSpace(v)
1385 if v != "" && v != "false" {
1386 return true
1387 }
1388 }
1389 return false
1390}
1391
1392func (c *configImpl) StartRBE() bool {
1393 if !c.UseRBE() {
1394 return false
1395 }
1396
1397 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1398 v = strings.TrimSpace(v)
1399 if v != "" && v != "false" {
1400 return false
1401 }
1402 }
1403 return true
1404}
1405
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001406func (c *configImpl) rbeProxyLogsDir() string {
1407 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001408 if v, ok := c.environ.Get(f); ok {
1409 return v
1410 }
1411 }
Ramy Medhatbc061762023-10-10 18:36:59 +00001412 return c.rbeTmpDir()
1413}
1414
1415func (c *configImpl) rbeDownloadTmpDir() string {
Cole Faust06ea5312023-10-18 17:38:40 -07001416 for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
Ramy Medhatbc061762023-10-10 18:36:59 +00001417 if v, ok := c.environ.Get(f); ok {
1418 return v
1419 }
1420 }
1421 return c.rbeTmpDir()
1422}
1423
1424func (c *configImpl) rbeTmpDir() string {
Yaowen Meid4da2662024-07-24 08:25:12 +00001425 return filepath.Join(c.SoongOutDir(), "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001426}
1427
Ramy Medhatc8f6cc22023-03-31 09:50:34 -04001428func (c *configImpl) rbeCacheDir() string {
1429 for _, f := range []string{"RBE_cache_dir", "FLAG_cache_dir"} {
1430 if v, ok := c.environ.Get(f); ok {
1431 return v
1432 }
1433 }
1434 return shared.JoinPath(c.SoongOutDir(), "rbe")
1435}
1436
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001437func (c *configImpl) shouldCleanupRBELogsDir() bool {
1438 // Perform a log directory cleanup only when the log directory
1439 // is auto created by the build rather than user-specified.
1440 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Yaowen Meid9108d22024-08-29 16:56:32 +00001441 if v, ok := c.environ.Get(f); ok {
1442 if v != c.rbeTmpDir() {
1443 return false
1444 }
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001445 }
1446 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001447 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001448}
1449
1450func (c *configImpl) rbeExecRoot() string {
1451 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1452 if v, ok := c.environ.Get(f); ok {
1453 return v
1454 }
1455 }
1456 wd, err := os.Getwd()
1457 if err != nil {
1458 return ""
1459 }
1460 return wd
1461}
1462
1463func (c *configImpl) rbeDir() string {
1464 if v, ok := c.environ.Get("RBE_DIR"); ok {
1465 return v
1466 }
1467 return "prebuilts/remoteexecution-client/live/"
1468}
1469
1470func (c *configImpl) rbeReproxy() string {
1471 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1472 if v, ok := c.environ.Get(f); ok {
1473 return v
1474 }
1475 }
1476 return filepath.Join(c.rbeDir(), "reproxy")
1477}
1478
1479func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001480 credFlags := []string{
1481 "use_application_default_credentials",
1482 "use_gce_credentials",
1483 "credential_file",
1484 "use_google_prod_creds",
1485 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001486 for _, cf := range credFlags {
1487 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1488 if v, ok := c.environ.Get(f); ok {
1489 v = strings.TrimSpace(v)
1490 if v != "" && v != "false" && v != "0" {
1491 return "RBE_" + cf, v
1492 }
1493 }
1494 }
1495 }
1496 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001497}
1498
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001499func (c *configImpl) rbeSockAddr(dir string) (string, error) {
Andus Yuc917eb82024-03-06 21:54:15 +00001500 // Absolute path socket addresses have a prefix of //. This should
1501 // be included in the length limit.
1502 maxNameLen := len(syscall.RawSockaddrUnix{}.Path) - 2
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001503 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1504
1505 name := filepath.Join(dir, base)
1506 if len(name) < maxNameLen {
1507 return name, nil
1508 }
1509
1510 name = filepath.Join("/tmp", base)
1511 if len(name) < maxNameLen {
1512 return name, nil
1513 }
1514
1515 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1516}
1517
Kousik Kumar7bc78192022-04-27 14:52:56 -04001518// IsGooglerEnvironment returns true if the current build is running
1519// on a Google developer machine and false otherwise.
1520func (c *configImpl) IsGooglerEnvironment() bool {
1521 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1522 if v, ok := c.environ.Get(cf); ok {
1523 return v == "googler"
1524 }
1525 return false
1526}
1527
1528// GoogleProdCredsExist determine whether credentials exist on the
1529// Googler machine to use remote execution.
1530func (c *configImpl) GoogleProdCredsExist() bool {
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001531 if googleProdCredsExistCache {
1532 return googleProdCredsExistCache
1533 }
andusyu0b3dc032023-06-21 17:29:32 -04001534 if _, err := exec.Command("/usr/bin/gcertstatus", "-nocheck_ssh").Output(); err != nil {
Kousik Kumar7bc78192022-04-27 14:52:56 -04001535 return false
1536 }
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001537 googleProdCredsExistCache = true
Kousik Kumar7bc78192022-04-27 14:52:56 -04001538 return true
1539}
1540
1541// UseRemoteBuild indicates whether to use a remote build acceleration system
1542// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001543func (c *configImpl) UseRemoteBuild() bool {
1544 return c.UseGoma() || c.UseRBE()
1545}
1546
Kousik Kumar7bc78192022-04-27 14:52:56 -04001547// StubbyExists checks whether the stubby binary exists on the machine running
1548// the build.
1549func (c *configImpl) StubbyExists() bool {
1550 if _, err := exec.LookPath("stubby"); err != nil {
1551 return false
1552 }
1553 return true
1554}
1555
Dan Willemsen1e704462016-08-21 15:17:17 -07001556// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001557// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001558// still limited by Parallel()
1559func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001560 if !c.UseRemoteBuild() {
1561 return 0
1562 }
1563 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1564 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001565 }
1566 return 500
1567}
1568
1569func (c *configImpl) SetKatiArgs(args []string) {
1570 c.katiArgs = args
1571}
1572
1573func (c *configImpl) SetNinjaArgs(args []string) {
1574 c.ninjaArgs = args
1575}
1576
1577func (c *configImpl) SetKatiSuffix(suffix string) {
1578 c.katiSuffix = suffix
1579}
1580
Dan Willemsene0879fc2017-08-04 15:06:27 -07001581func (c *configImpl) LastKatiSuffixFile() string {
1582 return filepath.Join(c.OutDir(), "last_kati_suffix")
1583}
1584
1585func (c *configImpl) HasKatiSuffix() bool {
1586 return c.katiSuffix != ""
1587}
1588
Dan Willemsen1e704462016-08-21 15:17:17 -07001589func (c *configImpl) KatiEnvFile() string {
1590 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1591}
1592
Dan Willemsen29971232018-09-26 14:58:30 -07001593func (c *configImpl) KatiBuildNinjaFile() string {
1594 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001595}
1596
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001597func (c *configImpl) KatiPackageNinjaFile() string {
1598 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1599}
1600
Cole Faustc5bfbdd2025-01-08 13:05:40 -08001601func (c *configImpl) KatiSoongOnlyPackageNinjaFile() string {
1602 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiSoongOnlyPackageSuffix+".ninja")
1603}
1604
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001605func (c *configImpl) SoongVarsFile() string {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001606 targetProduct, err := c.TargetProductOrErr()
1607 if err != nil {
1608 return filepath.Join(c.SoongOutDir(), "soong.variables")
1609 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001610 return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".variables")
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001611 }
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001612}
1613
Inseob Kim58c802f2024-06-11 10:59:00 +09001614func (c *configImpl) SoongExtraVarsFile() string {
1615 targetProduct, err := c.TargetProductOrErr()
1616 if err != nil {
1617 return filepath.Join(c.SoongOutDir(), "soong.extra.variables")
1618 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001619 return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+c.CoverageSuffix()+".extra.variables")
Inseob Kim58c802f2024-06-11 10:59:00 +09001620 }
1621}
1622
Dan Willemsen1e704462016-08-21 15:17:17 -07001623func (c *configImpl) SoongNinjaFile() string {
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001624 targetProduct, err := c.TargetProductOrErr()
1625 if err != nil {
1626 return filepath.Join(c.SoongOutDir(), "build.ninja")
1627 } else {
Qing Shen713c5422024-08-23 04:09:18 +00001628 return filepath.Join(c.SoongOutDir(), "build."+targetProduct+c.CoverageSuffix()+".ninja")
Kiyoung Kima37d9ba2023-04-19 13:13:45 +09001629 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001630}
1631
1632func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001633 if c.katiSuffix == "" {
1634 return filepath.Join(c.OutDir(), "combined.ninja")
1635 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001636 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1637}
1638
1639func (c *configImpl) SoongAndroidMk() string {
Qing Shen713c5422024-08-23 04:09:18 +00001640 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
Dan Willemsen1e704462016-08-21 15:17:17 -07001641}
1642
1643func (c *configImpl) SoongMakeVarsMk() string {
Qing Shen713c5422024-08-23 04:09:18 +00001644 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+c.CoverageSuffix()+".mk")
Dan Willemsen1e704462016-08-21 15:17:17 -07001645}
1646
Colin Crossaa9a2732023-10-27 10:54:27 -07001647func (c *configImpl) SoongBuildMetrics() string {
Colin Crossb67b0612023-10-31 10:02:45 -07001648 return filepath.Join(c.LogsDir(), "soong_build_metrics.pb")
Colin Crossaa9a2732023-10-27 10:54:27 -07001649}
1650
Dan Willemsenf052f782017-05-18 15:29:04 -07001651func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001652 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001653}
1654
Dan Willemsen02781d52017-05-12 19:28:13 -07001655func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001656 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1657}
1658
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001659func (c *configImpl) KatiPackageMkDir() string {
Cole Faustc5bfbdd2025-01-08 13:05:40 -08001660 return filepath.Join(c.SoongOutDir(), "kati_packaging"+c.KatiSuffix())
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001661}
1662
Dan Willemsenf052f782017-05-18 15:29:04 -07001663func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001664 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001665}
1666
1667func (c *configImpl) HostOut() string {
1668 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1669}
1670
1671// This probably needs to be multi-valued, so not exporting it for now
1672func (c *configImpl) hostCrossOut() string {
1673 if runtime.GOOS == "linux" {
1674 return filepath.Join(c.hostOutRoot(), "windows-x86")
1675 } else {
1676 return ""
1677 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001678}
1679
Dan Willemsen1e704462016-08-21 15:17:17 -07001680func (c *configImpl) HostPrebuiltTag() string {
1681 if runtime.GOOS == "linux" {
1682 return "linux-x86"
1683 } else if runtime.GOOS == "darwin" {
1684 return "darwin-x86"
1685 } else {
1686 panic("Unsupported OS")
1687 }
1688}
Dan Willemsenf173d592017-04-27 14:28:00 -07001689
Taylor Santiago3c16e612024-05-30 14:41:31 -07001690func (c *configImpl) KatiBin() string {
1691 binName := "ckati"
1692 if c.UseABFS() {
1693 binName = "ckati-wrap"
1694 }
1695
1696 return c.PrebuiltBuildTool(binName)
1697}
1698
1699func (c *configImpl) NinjaBin() string {
1700 binName := "ninja"
1701 if c.UseABFS() {
1702 binName = "ninjago"
1703 }
1704 return c.PrebuiltBuildTool(binName)
1705}
1706
Cole Faust4e58bba2024-08-22 14:27:03 -07001707func (c *configImpl) N2Bin() string {
1708 path := c.PrebuiltBuildTool("n2")
1709 // Use musl instead of glibc because glibc on the build server is old and has bugs
1710 return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
1711}
1712
LaMont Jonesece626c2024-09-03 11:19:31 -07001713func (c *configImpl) SisoBin() string {
1714 path := c.PrebuiltBuildTool("siso")
1715 // Use musl instead of glibc because glibc on the build server is old and has bugs
1716 return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
1717}
1718
Dan Willemsen8122bd52017-10-12 20:20:41 -07001719func (c *configImpl) PrebuiltBuildTool(name string) string {
Colin Cross7077be42024-10-04 20:37:16 +00001720 if c.environ.IsEnvTrue("SANITIZE_BUILD_TOOL_PREBUILTS") {
1721 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1722 if _, err := os.Stat(asan); err == nil {
1723 return asan
Dan Willemsenf173d592017-04-27 14:28:00 -07001724 }
1725 }
1726 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1727}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001728
1729func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1730 c.brokenDupRules = val
1731}
1732
1733func (c *configImpl) BuildBrokenDupRules() bool {
1734 return c.brokenDupRules
1735}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001736
Dan Willemsen25e6f092019-04-09 10:22:43 -07001737func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1738 c.brokenUsesNetwork = val
1739}
1740
1741func (c *configImpl) BuildBrokenUsesNetwork() bool {
1742 return c.brokenUsesNetwork
1743}
1744
Dan Willemsene3336352020-01-02 19:10:38 -08001745func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1746 c.brokenNinjaEnvVars = val
1747}
1748
1749func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1750 return c.brokenNinjaEnvVars
1751}
1752
Spandan Das28a6f192024-07-01 21:00:25 +00001753func (c *configImpl) SetBuildBrokenMissingOutputs(val bool) {
1754 c.brokenMissingOutputs = val
1755}
1756
1757func (c *configImpl) BuildBrokenMissingOutputs() bool {
1758 return c.brokenMissingOutputs
1759}
1760
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001761func (c *configImpl) SetTargetDeviceDir(dir string) {
1762 c.targetDeviceDir = dir
1763}
1764
1765func (c *configImpl) TargetDeviceDir() string {
1766 return c.targetDeviceDir
1767}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001768
Patrice Arruda219eef32020-06-01 17:29:30 +00001769func (c *configImpl) BuildDateTime() string {
1770 return c.buildDateTime
1771}
1772
1773func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001774 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001775}
Patrice Arruda83842d72020-12-08 19:42:08 +00001776
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001777// LogsDir returns the absolute path to the logs directory where build log and
1778// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001779// directory. If the argument dist is specified, the logs directory
1780// is <dist_dir>/logs.
1781func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001782 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001783 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001784 // 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 -05001785 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001786 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001787 absDir, err := filepath.Abs(dir)
1788 if err != nil {
1789 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1790 os.Exit(1)
1791 }
1792 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001793}
1794
Chris Parsons53f68ae2022-03-03 12:01:40 -05001795// MkFileMetrics returns the file path for make-related metrics.
1796func (c *configImpl) MkMetrics() string {
1797 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1798}
1799
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001800func (c *configImpl) SetEmptyNinjaFile(v bool) {
1801 c.emptyNinjaFile = v
1802}
1803
1804func (c *configImpl) EmptyNinjaFile() bool {
1805 return c.emptyNinjaFile
1806}
Yu Liu6e13b402021-07-27 14:29:06 -07001807
MarkDacekd0e7cd32022-12-02 22:22:40 +00001808func (c *configImpl) SkipMetricsUpload() bool {
Taylor Santiago8b0bed72024-09-03 13:30:22 -07001809 // b/362625275 - Metrics upload sometimes prevents abfs unmount
1810 if c.UseABFS() {
1811 return true
1812 }
1813
MarkDacekd0e7cd32022-12-02 22:22:40 +00001814 return c.skipMetricsUpload
1815}
1816
MarkDacekf47e1422023-04-19 16:47:36 +00001817func (c *configImpl) EnsureAllowlistIntegrity() bool {
1818 return c.ensureAllowlistIntegrity
1819}
1820
MarkDacek6614d9c2022-12-07 21:57:38 +00001821// Returns a Time object if one was passed via a command-line flag.
1822// Otherwise returns the passed default.
1823func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1824 if c.buildStartedTime == 0 {
1825 return defaultTime
1826 }
1827 return time.UnixMilli(c.buildStartedTime)
1828}
1829
Yu Liu6e13b402021-07-27 14:29:06 -07001830func GetMetricsUploader(topDir string, env *Environment) string {
1831 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1832 metricsUploader := filepath.Join(topDir, p)
1833 if _, err := os.Stat(metricsUploader); err == nil {
1834 return metricsUploader
1835 }
1836 }
1837
1838 return ""
1839}