blob: d9103badfb1cc49711f20d1001e20063f91d64f8 [file] [log] [blame]
Dan Willemsen1e704462016-08-21 15:17:17 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package build
16
17import (
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050018 "context"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050019 "encoding/json"
Ramy Medhat0fc67eb2020-08-12 01:26:23 -040020 "fmt"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050021 "io/ioutil"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040022 "math/rand"
Dan Willemsenc2af0be2017-01-20 14:10:01 -080023 "os"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050024 "os/exec"
Dan Willemsen1e704462016-08-21 15:17:17 -070025 "path/filepath"
26 "runtime"
27 "strconv"
28 "strings"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040029 "syscall"
Nan Zhang2e6a4ff2018-02-14 13:27:26 -080030 "time"
Jeff Gastonefc1b412017-03-29 17:29:06 -070031
32 "android/soong/shared"
Kousik Kumarec478642020-09-21 13:39:24 -040033
Dan Willemsen4591b642021-05-24 14:24:12 -070034 "google.golang.org/protobuf/proto"
Patrice Arruda96850362020-08-11 20:41:11 +000035
36 smpb "android/soong/ui/metrics/metrics_proto"
Dan Willemsen1e704462016-08-21 15:17:17 -070037)
38
Kousik Kumar3ff037e2022-01-25 22:11:01 -050039const (
Chris Parsons53f68ae2022-03-03 12:01:40 -050040 envConfigDir = "vendor/google/tools/soong_config"
41 jsonSuffix = "json"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050042
Chris Parsons53f68ae2022-03-03 12:01:40 -050043 configFetcher = "vendor/google/tools/soong/expconfigfetcher"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050044 envConfigFetchTimeout = 10 * time.Second
Kousik Kumar3ff037e2022-01-25 22:11:01 -050045)
46
Kousik Kumar4c180ad2022-05-27 07:48:37 -040047var (
Kevin Dagostino096ab2f2023-03-03 19:47:17 +000048 rbeRandPrefix int
49 googleProdCredsExistCache bool
Kousik Kumar4c180ad2022-05-27 07:48:37 -040050)
51
52func init() {
53 rand.Seed(time.Now().UnixNano())
54 rbeRandPrefix = rand.Intn(1000)
55}
56
Dan Willemsen1e704462016-08-21 15:17:17 -070057type Config struct{ *configImpl }
58
59type configImpl struct {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020060 // Some targets that are implemented in soong_build
61 // (bp2build, json-module-graph) are not here and have their own bits below.
Colin Cross28f527c2019-11-26 16:19:04 -080062 arguments []string
63 goma bool
64 environ *Environment
65 distDir string
66 buildDateTime string
MarkDacek6614d9c2022-12-07 21:57:38 +000067 logsPrefix string
Dan Willemsen1e704462016-08-21 15:17:17 -070068
69 // From the arguments
MarkDacekd0e7cd32022-12-02 22:22:40 +000070 parallel int
71 keepGoing int
72 verbose bool
73 checkbuild bool
74 dist bool
75 jsonModuleGraph bool
76 apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
77 bp2build bool
78 queryview bool
79 reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
80 soongDocs bool
81 skipConfig bool
82 skipKati bool
83 skipKatiNinja bool
84 skipSoong bool
85 skipNinja bool
86 skipSoongTests bool
87 searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
88 skipMetricsUpload bool
MarkDacek6614d9c2022-12-07 21:57:38 +000089 buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
Dan Willemsen1e704462016-08-21 15:17:17 -070090
91 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -070092 katiArgs []string
93 ninjaArgs []string
94 katiSuffix string
95 targetDevice string
96 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +000097 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -070098
Dan Willemsen2bb82d02019-12-27 09:35:42 -080099 // Autodetected
100 totalRAM uint64
101
Dan Willemsene3336352020-01-02 19:10:38 -0800102 brokenDupRules bool
103 brokenUsesNetwork bool
104 brokenNinjaEnvVars []string
Dan Willemsen18490112018-05-25 16:30:04 -0700105
106 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000107
MarkDacekb78465d2022-10-18 20:10:16 +0000108 bazelProdMode bool
109 bazelDevMode bool
110 bazelStagingMode bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000111
Colin Crossf3bdbcb2021-06-01 11:43:55 -0700112 // Set by multiproduct_kati
113 emptyNinjaFile bool
Yu Liu6e13b402021-07-27 14:29:06 -0700114
115 metricsUploader string
MarkDacekd06db5d2022-11-29 00:47:59 +0000116
117 bazelForceEnabledModules string
Spandan Dasc5763832022-11-08 18:42:16 +0000118
119 includeTags []string
Dan Willemsen1e704462016-08-21 15:17:17 -0700120}
121
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800122const srcDirFileCheck = "build/soong/root.bp"
123
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700124var buildFiles = []string{"Android.mk", "Android.bp"}
125
Patrice Arruda13848222019-04-22 17:12:02 -0700126type BuildAction uint
127
128const (
129 // Builds all of the modules and their dependencies of a specified directory, relative to the root
130 // directory of the source tree.
131 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
132
133 // Builds all of the modules and their dependencies of a list of specified directories. All specified
134 // directories are relative to the root directory of the source tree.
135 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700136
137 // Build a list of specified modules. If none was specified, simply build the whole source tree.
138 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700139)
140
141// checkTopDir validates that the current directory is at the root directory of the source tree.
142func checkTopDir(ctx Context) {
143 if _, err := os.Stat(srcDirFileCheck); err != nil {
144 if os.IsNotExist(err) {
145 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
146 }
147 ctx.Fatalln("Error verifying tree state:", err)
148 }
149}
150
Kousik Kumarc8818332023-01-16 16:33:05 +0000151// fetchEnvConfig optionally fetches a configuration file that can then subsequently be
152// loaded into Soong environment to control certain aspects of build behavior (e.g., enabling RBE).
153// If a configuration file already exists on disk, the fetch is run in the background
154// so as to NOT block the rest of the build execution.
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500155func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
David Goldsmith62243a32022-04-08 13:42:04 +0000156 configName := envConfigName + "." + jsonSuffix
Kousik Kumarc75e1292022-07-07 02:20:51 +0000157 expConfigFetcher := &smpb.ExpConfigFetcher{Filename: &configName}
David Goldsmith62243a32022-04-08 13:42:04 +0000158 defer func() {
159 ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
160 }()
Kousik Kumarc75e1292022-07-07 02:20:51 +0000161 if !config.GoogleProdCredsExist() {
162 status := smpb.ExpConfigFetcher_MISSING_GCERT
163 expConfigFetcher.Status = &status
164 return nil
165 }
David Goldsmith62243a32022-04-08 13:42:04 +0000166
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500167 s, err := os.Stat(configFetcher)
168 if err != nil {
169 if os.IsNotExist(err) {
170 return nil
171 }
172 return err
173 }
174 if s.Mode()&0111 == 0 {
David Goldsmith62243a32022-04-08 13:42:04 +0000175 status := smpb.ExpConfigFetcher_ERROR
176 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500177 return fmt.Errorf("configuration fetcher binary %v is not executable: %v", configFetcher, s.Mode())
178 }
179
Kousik Kumarc8818332023-01-16 16:33:05 +0000180 configExists := false
181 outConfigFilePath := filepath.Join(config.OutDir(), configName)
182 if _, err := os.Stat(outConfigFilePath); err == nil {
183 configExists = true
184 }
185
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500186 tCtx, cancel := context.WithTimeout(ctx, envConfigFetchTimeout)
David Goldsmith62243a32022-04-08 13:42:04 +0000187 fetchStart := time.Now()
188 cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir(),
189 "-output_config_name", configName)
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500190 if err := cmd.Start(); err != nil {
David Goldsmith62243a32022-04-08 13:42:04 +0000191 status := smpb.ExpConfigFetcher_ERROR
192 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500193 return err
194 }
195
Kousik Kumarc8818332023-01-16 16:33:05 +0000196 fetchCfg := func() error {
197 if err := cmd.Wait(); err != nil {
198 status := smpb.ExpConfigFetcher_ERROR
199 expConfigFetcher.Status = &status
200 return err
201 }
202 fetchEnd := time.Now()
203 expConfigFetcher.Micros = proto.Uint64(uint64(fetchEnd.Sub(fetchStart).Microseconds()))
204 expConfigFetcher.Filename = proto.String(outConfigFilePath)
205
206 if _, err := os.Stat(outConfigFilePath); err != nil {
207 status := smpb.ExpConfigFetcher_NO_CONFIG
208 expConfigFetcher.Status = &status
209 return err
210 }
David Goldsmith62243a32022-04-08 13:42:04 +0000211 status := smpb.ExpConfigFetcher_CONFIG
212 expConfigFetcher.Status = &status
Kousik Kumarc8818332023-01-16 16:33:05 +0000213 return nil
David Goldsmith62243a32022-04-08 13:42:04 +0000214 }
Kousik Kumarc8818332023-01-16 16:33:05 +0000215
216 // If a config file does not exist, wait for the config file to be fetched. Otherwise
217 // fetch the config file in the background and return immediately.
218 if !configExists {
219 defer cancel()
220 return fetchCfg()
221 }
222
223 go func() {
224 defer cancel()
225 if err := fetchCfg(); err != nil {
226 ctx.Verbosef("Failed to fetch config file %v: %v\n", configName, err)
227 }
228 }()
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500229 return nil
230}
231
MarkDacek7901e582023-01-09 19:48:01 +0000232func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500233 if bc == "" {
234 return nil
235 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500236
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500237 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500238 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500239 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500240 envConfigDir,
241 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500242 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500243 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
244 envVarsJSON, err := ioutil.ReadFile(cfgFile)
245 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500246 continue
247 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500248 ctx.Verbosef("Loading config file %v\n", cfgFile)
249 var envVars map[string]map[string]string
250 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
251 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
252 continue
253 }
254 for k, v := range envVars["env"] {
255 if os.Getenv(k) != "" {
256 continue
257 }
258 config.environ.Set(k, v)
259 }
260 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
261 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500262 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500263
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500264 return nil
265}
266
Chris Parsonsb6e96902022-10-31 20:08:45 -0400267func defaultBazelProdMode(cfg *configImpl) bool {
MarkDacekd06db5d2022-11-29 00:47:59 +0000268 // Environment flag to disable Bazel for users which experience
Chris Parsonsb6e96902022-10-31 20:08:45 -0400269 // broken bazel-handled builds, or significant performance regressions.
270 if cfg.IsBazelMixedBuildForceDisabled() {
271 return false
272 }
273 // Darwin-host builds are currently untested with Bazel.
274 if runtime.GOOS == "darwin" {
275 return false
276 }
Chris Parsons035e03a2022-11-01 14:25:45 -0400277 return true
Chris Parsonsb6e96902022-10-31 20:08:45 -0400278}
279
MarkDacek6614d9c2022-12-07 21:57:38 +0000280func UploadOnlyConfig(ctx Context, _ ...string) Config {
281 ret := &configImpl{
282 environ: OsEnvironment(),
283 sandboxConfig: &SandboxConfig{},
284 }
MarkDacek7901e582023-01-09 19:48:01 +0000285 srcDir := absPath(ctx, ".")
286 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
287 if err := loadEnvConfig(ctx, ret, bc); err != nil {
288 ctx.Fatalln("Failed to parse env config files: %v", err)
289 }
290 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
MarkDacek6614d9c2022-12-07 21:57:38 +0000291 return Config{ret}
292}
293
Dan Willemsen1e704462016-08-21 15:17:17 -0700294func NewConfig(ctx Context, args ...string) Config {
295 ret := &configImpl{
Spandan Dasa3639e62021-05-25 19:14:02 +0000296 environ: OsEnvironment(),
297 sandboxConfig: &SandboxConfig{},
Dan Willemsen1e704462016-08-21 15:17:17 -0700298 }
299
Patrice Arruda90109172020-07-28 18:07:27 +0000300 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700301 ret.parallel = runtime.NumCPU() + 2
302 ret.keepGoing = 1
303
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800304 ret.totalRAM = detectTotalRAM(ctx)
Dan Willemsen9b587492017-07-10 22:13:00 -0700305 ret.parseArgs(ctx, args)
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800306 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700307 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
308 ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
309 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800310 outDir := "out"
311 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
312 if wd, err := os.Getwd(); err != nil {
313 ctx.Fatalln("Failed to get working directory:", err)
314 } else {
315 outDir = filepath.Join(baseDir, filepath.Base(wd))
316 }
317 }
318 ret.environ.Set("OUT_DIR", outDir)
319 }
320
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500321 // loadEnvConfig needs to know what the OUT_DIR is, so it should
322 // be called after we determine the appropriate out directory.
MarkDacek7901e582023-01-09 19:48:01 +0000323 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
324
325 if bc != "" {
326 if err := fetchEnvConfig(ctx, ret, bc); err != nil {
327 ctx.Verbosef("Failed to fetch config file: %v\n", err)
Kousik Kumarc8818332023-01-16 16:33:05 +0000328 }
329 if err := loadEnvConfig(ctx, ret, bc); err != nil {
MarkDacek7901e582023-01-09 19:48:01 +0000330 ctx.Fatalln("Failed to parse env config files: %v", err)
331 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500332 }
333
Dan Willemsen2d31a442018-10-20 21:33:41 -0700334 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
335 ret.distDir = filepath.Clean(distDir)
336 } else {
337 ret.distDir = filepath.Join(ret.OutDir(), "dist")
338 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700339
Spandan Das05063612021-06-25 01:39:04 +0000340 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
341 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
342 }
343
Dan Willemsen1e704462016-08-21 15:17:17 -0700344 ret.environ.Unset(
345 // We're already using it
346 "USE_SOONG_UI",
347
348 // We should never use GOROOT/GOPATH from the shell environment
349 "GOROOT",
350 "GOPATH",
351
352 // These should only come from Soong, not the environment.
353 "CLANG",
354 "CLANG_CXX",
355 "CCC_CC",
356 "CCC_CXX",
357
358 // Used by the goma compiler wrapper, but should only be set by
359 // gomacc
360 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800361
362 // We handle this above
363 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700364
Dan Willemsen2d31a442018-10-20 21:33:41 -0700365 // This is handled above too, and set for individual commands later
366 "DIST_DIR",
367
Dan Willemsen68a09852017-04-18 13:56:57 -0700368 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000369 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700370 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700371 "DISPLAY",
372 "GREP_OPTIONS",
Nathan Egge7b067fb2023-02-17 17:54:31 +0000373 "JAVAC",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700374 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700375 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700376
377 // Drop make flags
378 "MAKEFLAGS",
379 "MAKELEVEL",
380 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700381
382 // Set in envsetup.sh, reset in makefiles
383 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700384
385 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
386 "ANDROID_BUILD_TOP",
387 "ANDROID_HOST_OUT",
388 "ANDROID_PRODUCT_OUT",
389 "ANDROID_HOST_OUT_TESTCASES",
390 "ANDROID_TARGET_OUT_TESTCASES",
391 "ANDROID_TOOLCHAIN",
392 "ANDROID_TOOLCHAIN_2ND_ARCH",
393 "ANDROID_DEV_SCRIPTS",
394 "ANDROID_EMULATOR_PREBUILTS",
395 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700396 )
397
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400398 if ret.UseGoma() || ret.ForceUseGoma() {
399 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
400 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400401 }
402
Dan Willemsen1e704462016-08-21 15:17:17 -0700403 // Tell python not to spam the source tree with .pyc files.
404 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
405
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400406 tmpDir := absPath(ctx, ret.TempDir())
407 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800408
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700409 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
410 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
411 "llvm-binutils-stable/llvm-symbolizer")
412 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
413
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800414 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700415 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800416
Yu Liu6e13b402021-07-27 14:29:06 -0700417 srcDir := absPath(ctx, ".")
418 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700419 ctx.Println("You are building in a directory whose absolute path contains a space character:")
420 ctx.Println()
421 ctx.Printf("%q\n", srcDir)
422 ctx.Println()
423 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700424 }
425
Yu Liu6e13b402021-07-27 14:29:06 -0700426 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
427
Dan Willemsendb8457c2017-05-12 16:38:17 -0700428 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700429 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
430 ctx.Println()
431 ctx.Printf("%q\n", outDir)
432 ctx.Println()
433 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700434 }
435
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000436 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700437 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
438 ctx.Println()
439 ctx.Printf("%q\n", distDir)
440 ctx.Println()
441 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700442 }
443
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700444 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000445 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
446 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100447 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Colin Cross59c1e6a2022-03-04 13:37:19 -0800448 java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700449 javaHome := func() string {
450 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
451 return override
452 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000453 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
454 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
Pete Gillin1f52e932019-10-09 17:10:08 +0100455 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000456 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
457 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
458 }
459 return java17Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700460 }()
461 absJavaHome := absPath(ctx, javaHome)
462
Dan Willemsened869522018-01-08 14:58:46 -0800463 ret.configureLocale(ctx)
464
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700465 newPath := []string{filepath.Join(absJavaHome, "bin")}
466 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
467 newPath = append(newPath, path)
468 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100469
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700470 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
471 ret.environ.Set("JAVA_HOME", absJavaHome)
472 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000473 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
474 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100475 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700476 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
477
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800478 outDir := ret.OutDir()
479 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800480 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800481 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800482 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800483 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800484 }
Colin Cross28f527c2019-11-26 16:19:04 -0800485
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800486 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
487
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400488 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400489 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400490 ret.environ.Set(k, v)
491 }
492 }
493
Patrice Arruda83842d72020-12-08 19:42:08 +0000494 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800495 if err := os.RemoveAll(bpd); err != nil {
496 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
497 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000498
Patrice Arruda96850362020-08-11 20:41:11 +0000499 c := Config{ret}
500 storeConfigMetrics(ctx, c)
501 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700502}
503
Patrice Arruda13848222019-04-22 17:12:02 -0700504// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
505// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700506func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
507 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700508}
509
Patrice Arruda96850362020-08-11 20:41:11 +0000510// storeConfigMetrics selects a set of configuration information and store in
511// the metrics system for further analysis.
512func storeConfigMetrics(ctx Context, config Config) {
513 if ctx.Metrics == nil {
514 return
515 }
516
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400517 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000518
519 s := &smpb.SystemResourceInfo{
520 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
521 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
522 }
523 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000524}
525
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400526func buildConfig(config Config) *smpb.BuildConfig {
Yu Liue737a992021-10-04 13:21:41 -0700527 c := &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -0400528 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
529 UseGoma: proto.Bool(config.UseGoma()),
530 UseRbe: proto.Bool(config.UseRBE()),
531 BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
532 ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400533 }
Yu Liue737a992021-10-04 13:21:41 -0700534 c.Targets = append(c.Targets, config.arguments...)
535
536 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400537}
538
Patrice Arruda13848222019-04-22 17:12:02 -0700539// getConfigArgs processes the command arguments based on the build action and creates a set of new
540// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700541func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700542 // The next block of code verifies that the current directory is the root directory of the source
543 // tree. It then finds the relative path of dir based on the root directory of the source tree
544 // and verify that dir is inside of the source tree.
545 checkTopDir(ctx)
546 topDir, err := os.Getwd()
547 if err != nil {
548 ctx.Fatalf("Error retrieving top directory: %v", err)
549 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700550 dir, err = filepath.EvalSymlinks(dir)
551 if err != nil {
552 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
553 }
Patrice Arruda13848222019-04-22 17:12:02 -0700554 dir, err = filepath.Abs(dir)
555 if err != nil {
556 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
557 }
558 relDir, err := filepath.Rel(topDir, dir)
559 if err != nil {
560 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
561 }
562 // If there are ".." in the path, it's not in the source tree.
563 if strings.Contains(relDir, "..") {
564 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
565 }
566
567 configArgs := args[:]
568
569 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
570 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
571 targetNamePrefix := "MODULES-IN-"
572 if inList("GET-INSTALL-PATH", configArgs) {
573 targetNamePrefix = "GET-INSTALL-PATH-IN-"
574 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
575 }
576
Patrice Arruda13848222019-04-22 17:12:02 -0700577 var targets []string
578
579 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700580 case BUILD_MODULES:
581 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700582 case BUILD_MODULES_IN_A_DIRECTORY:
583 // If dir is the root source tree, all the modules are built of the source tree are built so
584 // no need to find the build file.
585 if topDir == dir {
586 break
587 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700588
Patrice Arruda13848222019-04-22 17:12:02 -0700589 buildFile := findBuildFile(ctx, relDir)
590 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700591 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700592 }
Patrice Arruda13848222019-04-22 17:12:02 -0700593 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
594 case BUILD_MODULES_IN_DIRECTORIES:
595 newConfigArgs, dirs := splitArgs(configArgs)
596 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700597 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700598 }
599
600 // Tidy only override all other specified targets.
601 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
602 if tidyOnly == "true" || tidyOnly == "1" {
603 configArgs = append(configArgs, "tidy_only")
604 } else {
605 configArgs = append(configArgs, targets...)
606 }
607
608 return configArgs
609}
610
611// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
612func convertToTarget(dir string, targetNamePrefix string) string {
613 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
614}
615
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700616// hasBuildFile returns true if dir contains an Android build file.
617func hasBuildFile(ctx Context, dir string) bool {
618 for _, buildFile := range buildFiles {
619 _, err := os.Stat(filepath.Join(dir, buildFile))
620 if err == nil {
621 return true
622 }
623 if !os.IsNotExist(err) {
624 ctx.Fatalf("Error retrieving the build file stats: %v", err)
625 }
626 }
627 return false
628}
629
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700630// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
631// in the current and any sub directory of dir. If a build file is not found, traverse the path
632// up by one directory and repeat again until either a build file is found or reached to the root
633// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
634// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700635func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700636 // If the string is empty or ".", assume it is top directory of the source tree.
637 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700638 return ""
639 }
640
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700641 found := false
642 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
643 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
644 if err != nil {
645 return err
646 }
647 if found {
648 return filepath.SkipDir
649 }
650 if info.IsDir() {
651 return nil
652 }
653 for _, buildFile := range buildFiles {
654 if info.Name() == buildFile {
655 found = true
656 return filepath.SkipDir
657 }
658 }
659 return nil
660 })
661 if err != nil {
662 ctx.Fatalf("Error finding Android build file: %v", err)
663 }
664
665 if found {
666 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700667 }
668 }
669
670 return ""
671}
672
673// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
674func splitArgs(args []string) (newArgs []string, dirs []string) {
675 specialArgs := map[string]bool{
676 "showcommands": true,
677 "snod": true,
678 "dist": true,
679 "checkbuild": true,
680 }
681
682 newArgs = []string{}
683 dirs = []string{}
684
685 for _, arg := range args {
686 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
687 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
688 newArgs = append(newArgs, arg)
689 continue
690 }
691
692 if _, ok := specialArgs[arg]; ok {
693 newArgs = append(newArgs, arg)
694 continue
695 }
696
697 dirs = append(dirs, arg)
698 }
699
700 return newArgs, dirs
701}
702
703// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
704// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
705// source root tree where the build action command was invoked. Each directory is validated if the
706// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700707func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700708 for _, dir := range dirs {
709 // The directory may have specified specific modules to build. ":" is the separator to separate
710 // the directory and the list of modules.
711 s := strings.Split(dir, ":")
712 l := len(s)
713 if l > 2 { // more than one ":" was specified.
714 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
715 }
716
717 dir = filepath.Join(relDir, s[0])
718 if _, err := os.Stat(dir); err != nil {
719 ctx.Fatalf("couldn't find directory %s", dir)
720 }
721
722 // Verify that if there are any targets specified after ":". Each target is separated by ",".
723 var newTargets []string
724 if l == 2 && s[1] != "" {
725 newTargets = strings.Split(s[1], ",")
726 if inList("", newTargets) {
727 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
728 }
729 }
730
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700731 // If there are specified targets to build in dir, an android build file must exist for the one
732 // shot build. For the non-targets case, find the appropriate build file and build all the
733 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700734 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700735 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700736 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
737 }
738 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700739 buildFile := findBuildFile(ctx, dir)
740 if buildFile == "" {
741 ctx.Fatalf("Build file not found for %s directory", dir)
742 }
743 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700744 }
745
Patrice Arruda13848222019-04-22 17:12:02 -0700746 targets = append(targets, newTargets...)
747 }
748
Dan Willemsence41e942019-07-29 23:39:30 -0700749 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700750}
751
Dan Willemsen9b587492017-07-10 22:13:00 -0700752func (c *configImpl) parseArgs(ctx Context, args []string) {
753 for i := 0; i < len(args); i++ {
754 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100755 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700756 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200757 } else if arg == "--empty-ninja-file" {
758 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100759 } else if arg == "--skip-ninja" {
760 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700761 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700762 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
763 // but it does run a Kati ninja file if the .kati_enabled marker file was created
764 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000765 c.skipConfig = true
766 c.skipKati = true
767 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100768 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000769 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100770 } else if arg == "--soong-only" {
771 c.skipKati = true
772 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200773 } else if arg == "--config-only" {
774 c.skipKati = true
775 c.skipKatiNinja = true
776 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700777 } else if arg == "--skip-config" {
778 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700779 } else if arg == "--skip-soong-tests" {
780 c.skipSoongTests = true
MarkDacekd0e7cd32022-12-02 22:22:40 +0000781 } else if arg == "--skip-metrics-upload" {
782 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500783 } else if arg == "--mk-metrics" {
784 c.reportMkMetrics = true
Chris Parsonsef615e52022-08-18 22:04:11 -0400785 } else if arg == "--bazel-mode" {
786 c.bazelProdMode = true
787 } else if arg == "--bazel-mode-dev" {
788 c.bazelDevMode = true
MarkDacekb78465d2022-10-18 20:10:16 +0000789 } else if arg == "--bazel-mode-staging" {
790 c.bazelStagingMode = true
Spandan Das394aa322022-11-03 17:02:10 +0000791 } else if arg == "--search-api-dir" {
792 c.searchApiDir = true
MarkDacekb96561e2022-12-02 04:34:43 +0000793 } else if strings.HasPrefix(arg, "--build-command=") {
794 buildCmd := strings.TrimPrefix(arg, "--build-command=")
795 // remove quotations
796 buildCmd = strings.TrimPrefix(buildCmd, "\"")
797 buildCmd = strings.TrimSuffix(buildCmd, "\"")
798 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacekd06db5d2022-11-29 00:47:59 +0000799 } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
800 c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
MarkDacek6614d9c2022-12-07 21:57:38 +0000801 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
802 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
803 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
804 if err == nil {
805 c.buildStartedTime = val
806 } else {
807 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
808 }
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700809 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700810 parseArgNum := func(def int) int {
811 if len(arg) > 2 {
812 p, err := strconv.ParseUint(arg[2:], 10, 31)
813 if err != nil {
814 ctx.Fatalf("Failed to parse %q: %v", arg, err)
815 }
816 return int(p)
817 } else if i+1 < len(args) {
818 p, err := strconv.ParseUint(args[i+1], 10, 31)
819 if err == nil {
820 i++
821 return int(p)
822 }
823 }
824 return def
825 }
826
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700827 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700828 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700829 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700830 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700831 } else {
832 ctx.Fatalln("Unknown option:", arg)
833 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700834 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700835 if k == "OUT_DIR" {
836 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
837 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700838 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700839 } else if arg == "dist" {
840 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200841 } else if arg == "json-module-graph" {
842 c.jsonModuleGraph = true
843 } else if arg == "bp2build" {
844 c.bp2build = true
Spandan Das5af0bd32022-09-28 20:43:08 +0000845 } else if arg == "api_bp2build" {
846 c.apiBp2build = true
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200847 } else if arg == "queryview" {
848 c.queryview = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200849 } else if arg == "soong_docs" {
850 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700851 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700852 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800853 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700854 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700855 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700856 }
857 }
Chris Parsonsb6e96902022-10-31 20:08:45 -0400858 if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
859 c.bazelProdMode = defaultBazelProdMode(c)
860 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700861}
862
Dan Willemsened869522018-01-08 14:58:46 -0800863func (c *configImpl) configureLocale(ctx Context) {
864 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
865 output, err := cmd.Output()
866
867 var locales []string
868 if err == nil {
869 locales = strings.Split(string(output), "\n")
870 } else {
871 // If we're unable to list the locales, let's assume en_US.UTF-8
872 locales = []string{"en_US.UTF-8"}
873 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
874 }
875
876 // gettext uses LANGUAGE, which is passed directly through
877
878 // For LANG and LC_*, only preserve the evaluated version of
879 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800880 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800881 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800882 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800883 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800884 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800885 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800886 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800887 }
888
889 c.environ.UnsetWithPrefix("LC_")
890
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800891 if userLang != "" {
892 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800893 }
894
895 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
896 // for others)
897 if inList("C.UTF-8", locales) {
898 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500899 } else if inList("C.utf8", locales) {
900 // These normalize to the same thing
901 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800902 } else if inList("en_US.UTF-8", locales) {
903 c.environ.Set("LANG", "en_US.UTF-8")
904 } else if inList("en_US.utf8", locales) {
905 // These normalize to the same thing
906 c.environ.Set("LANG", "en_US.UTF-8")
907 } else {
908 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
909 }
910}
911
Dan Willemsen1e704462016-08-21 15:17:17 -0700912func (c *configImpl) Environment() *Environment {
913 return c.environ
914}
915
916func (c *configImpl) Arguments() []string {
917 return c.arguments
918}
919
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200920func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200921 if len(c.Arguments()) > 0 {
922 // Explicit targets requested that are not special targets like b2pbuild
923 // or the JSON module graph
924 return true
925 }
926
Spandan Das5af0bd32022-09-28 20:43:08 +0000927 if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200928 // Command line was empty, the default Ninja target is built
929 return true
930 }
931
Liz Kammer88677422021-12-15 15:03:19 -0500932 // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
933 if c.Dist() && !c.Bp2Build() {
934 return true
935 }
936
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200937 // build.ninja doesn't need to be generated
938 return false
939}
940
Dan Willemsen1e704462016-08-21 15:17:17 -0700941func (c *configImpl) OutDir() string {
942 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700943 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700944 }
945 return "out"
946}
947
Dan Willemsen8a073a82017-02-04 17:30:44 -0800948func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -0400949 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000950}
951
952func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700953 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800954}
955
Dan Willemsen1e704462016-08-21 15:17:17 -0700956func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000957 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700958 return c.arguments
959 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700960 return c.ninjaArgs
961}
962
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500963func (c *configImpl) BazelOutDir() string {
964 return filepath.Join(c.OutDir(), "bazel")
965}
966
Liz Kammer2af5ea82022-11-11 14:21:03 -0500967func (c *configImpl) bazelOutputBase() string {
968 return filepath.Join(c.BazelOutDir(), "output")
969}
970
Dan Willemsen1e704462016-08-21 15:17:17 -0700971func (c *configImpl) SoongOutDir() string {
972 return filepath.Join(c.OutDir(), "soong")
973}
974
Spandan Das394aa322022-11-03 17:02:10 +0000975func (c *configImpl) ApiSurfacesOutDir() string {
976 return filepath.Join(c.OutDir(), "api_surfaces")
977}
978
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200979func (c *configImpl) PrebuiltOS() string {
980 switch runtime.GOOS {
981 case "linux":
982 return "linux-x86"
983 case "darwin":
984 return "darwin-x86"
985 default:
986 panic("Unknown GOOS")
987 }
988}
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100989
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200990func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -0700991 if c.SkipKatiNinja() {
992 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
993 } else {
994 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
995 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200996}
997
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200998func (c *configImpl) NamedGlobFile(name string) string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100999 return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +02001000}
1001
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001002func (c *configImpl) UsedEnvFile(tag string) string {
1003 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
1004}
1005
Lukacs T. Berkic541cd22022-10-26 07:26:50 +00001006func (c *configImpl) Bp2BuildFilesMarkerFile() string {
1007 return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
1008}
1009
1010func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +01001011 return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +02001012}
1013
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001014func (c *configImpl) SoongDocsHtml() string {
1015 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
1016}
1017
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001018func (c *configImpl) QueryviewMarkerFile() string {
1019 return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
1020}
1021
Spandan Das5af0bd32022-09-28 20:43:08 +00001022func (c *configImpl) ApiBp2buildMarkerFile() string {
1023 return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
1024}
1025
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001026func (c *configImpl) ModuleGraphFile() string {
1027 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1028}
1029
kgui67007242022-01-25 13:50:25 +08001030func (c *configImpl) ModuleActionsFile() string {
1031 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1032}
1033
Jeff Gastonefc1b412017-03-29 17:29:06 -07001034func (c *configImpl) TempDir() string {
1035 return shared.TempDirForOutDir(c.SoongOutDir())
1036}
1037
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001038func (c *configImpl) FileListDir() string {
1039 return filepath.Join(c.OutDir(), ".module_paths")
1040}
1041
Dan Willemsen1e704462016-08-21 15:17:17 -07001042func (c *configImpl) KatiSuffix() string {
1043 if c.katiSuffix != "" {
1044 return c.katiSuffix
1045 }
1046 panic("SetKatiSuffix has not been called")
1047}
1048
Colin Cross37193492017-11-16 17:55:00 -08001049// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1050// user is interested in additional checks at the expense of build time.
1051func (c *configImpl) Checkbuild() bool {
1052 return c.checkbuild
1053}
1054
Dan Willemsen8a073a82017-02-04 17:30:44 -08001055func (c *configImpl) Dist() bool {
1056 return c.dist
1057}
1058
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001059func (c *configImpl) JsonModuleGraph() bool {
1060 return c.jsonModuleGraph
1061}
1062
1063func (c *configImpl) Bp2Build() bool {
1064 return c.bp2build
1065}
1066
Spandan Das5af0bd32022-09-28 20:43:08 +00001067func (c *configImpl) ApiBp2build() bool {
1068 return c.apiBp2build
1069}
1070
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001071func (c *configImpl) Queryview() bool {
1072 return c.queryview
1073}
1074
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001075func (c *configImpl) SoongDocs() bool {
1076 return c.soongDocs
1077}
1078
Dan Willemsen1e704462016-08-21 15:17:17 -07001079func (c *configImpl) IsVerbose() bool {
1080 return c.verbose
1081}
1082
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001083func (c *configImpl) SkipKati() bool {
1084 return c.skipKati
1085}
1086
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001087func (c *configImpl) SkipKatiNinja() bool {
1088 return c.skipKatiNinja
1089}
1090
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001091func (c *configImpl) SkipSoong() bool {
1092 return c.skipSoong
1093}
1094
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001095func (c *configImpl) SkipNinja() bool {
1096 return c.skipNinja
1097}
1098
Anton Hansson5a7861a2021-06-04 10:09:01 +01001099func (c *configImpl) SetSkipNinja(v bool) {
1100 c.skipNinja = v
1101}
1102
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001103func (c *configImpl) SkipConfig() bool {
1104 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001105}
1106
Dan Willemsen1e704462016-08-21 15:17:17 -07001107func (c *configImpl) TargetProduct() string {
1108 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1109 return v
1110 }
1111 panic("TARGET_PRODUCT is not defined")
1112}
1113
Dan Willemsen02781d52017-05-12 19:28:13 -07001114func (c *configImpl) TargetDevice() string {
1115 return c.targetDevice
1116}
1117
1118func (c *configImpl) SetTargetDevice(device string) {
1119 c.targetDevice = device
1120}
1121
1122func (c *configImpl) TargetBuildVariant() string {
1123 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1124 return v
1125 }
1126 panic("TARGET_BUILD_VARIANT is not defined")
1127}
1128
Dan Willemsen1e704462016-08-21 15:17:17 -07001129func (c *configImpl) KatiArgs() []string {
1130 return c.katiArgs
1131}
1132
1133func (c *configImpl) Parallel() int {
1134 return c.parallel
1135}
1136
Spandan Dasc5763832022-11-08 18:42:16 +00001137func (c *configImpl) GetIncludeTags() []string {
1138 return c.includeTags
1139}
1140
1141func (c *configImpl) SetIncludeTags(i []string) {
1142 c.includeTags = i
1143}
1144
MarkDacek6614d9c2022-12-07 21:57:38 +00001145func (c *configImpl) GetLogsPrefix() string {
1146 return c.logsPrefix
1147}
1148
1149func (c *configImpl) SetLogsPrefix(prefix string) {
1150 c.logsPrefix = prefix
1151}
1152
Colin Cross8b8bec32019-11-15 13:18:43 -08001153func (c *configImpl) HighmemParallel() int {
1154 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1155 return i
1156 }
1157
1158 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1159 parallel := c.Parallel()
1160 if c.UseRemoteBuild() {
1161 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1162 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1163 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1164 // Return 1/16th of the size of the local pool, rounding up.
1165 return (parallel + 15) / 16
1166 } else if c.totalRAM == 0 {
1167 // Couldn't detect the total RAM, don't restrict highmem processes.
1168 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001169 } else if c.totalRAM <= 16*1024*1024*1024 {
1170 // Less than 16GB of ram, restrict to 1 highmem processes
1171 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001172 } else if c.totalRAM <= 32*1024*1024*1024 {
1173 // Less than 32GB of ram, restrict to 2 highmem processes
1174 return 2
1175 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1176 // If less than 8GB total RAM per process, reduce the number of highmem processes
1177 return p
1178 }
1179 // No restriction on highmem processes
1180 return parallel
1181}
1182
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001183func (c *configImpl) TotalRAM() uint64 {
1184 return c.totalRAM
1185}
1186
Kousik Kumarec478642020-09-21 13:39:24 -04001187// ForceUseGoma determines whether we should override Goma deprecation
1188// and use Goma for the current build or not.
1189func (c *configImpl) ForceUseGoma() bool {
1190 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1191 v = strings.TrimSpace(v)
1192 if v != "" && v != "false" {
1193 return true
1194 }
1195 }
1196 return false
1197}
1198
Dan Willemsen1e704462016-08-21 15:17:17 -07001199func (c *configImpl) UseGoma() bool {
1200 if v, ok := c.environ.Get("USE_GOMA"); ok {
1201 v = strings.TrimSpace(v)
1202 if v != "" && v != "false" {
1203 return true
1204 }
1205 }
1206 return false
1207}
1208
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001209func (c *configImpl) StartGoma() bool {
1210 if !c.UseGoma() {
1211 return false
1212 }
1213
1214 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1215 v = strings.TrimSpace(v)
1216 if v != "" && v != "false" {
1217 return false
1218 }
1219 }
1220 return true
1221}
1222
Ramy Medhatbbf25672019-07-17 12:30:04 +00001223func (c *configImpl) UseRBE() bool {
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001224 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001225 v = strings.TrimSpace(v)
1226 if v != "" && v != "false" {
1227 return true
1228 }
1229 }
1230 return false
1231}
1232
Chris Parsonsef615e52022-08-18 22:04:11 -04001233func (c *configImpl) BazelBuildEnabled() bool {
MarkDacekb78465d2022-10-18 20:10:16 +00001234 return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
Chris Parsonsec1a3dc2021-04-20 15:32:07 -04001235}
1236
Ramy Medhatbbf25672019-07-17 12:30:04 +00001237func (c *configImpl) StartRBE() bool {
1238 if !c.UseRBE() {
1239 return false
1240 }
1241
1242 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1243 v = strings.TrimSpace(v)
1244 if v != "" && v != "false" {
1245 return false
1246 }
1247 }
1248 return true
1249}
1250
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001251func (c *configImpl) rbeProxyLogsDir() string {
1252 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001253 if v, ok := c.environ.Get(f); ok {
1254 return v
1255 }
1256 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001257 buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
1258 return filepath.Join(buildTmpDir, "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001259}
1260
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001261func (c *configImpl) shouldCleanupRBELogsDir() bool {
1262 // Perform a log directory cleanup only when the log directory
1263 // is auto created by the build rather than user-specified.
1264 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
1265 if _, ok := c.environ.Get(f); ok {
1266 return false
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001267 }
1268 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001269 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001270}
1271
1272func (c *configImpl) rbeExecRoot() string {
1273 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1274 if v, ok := c.environ.Get(f); ok {
1275 return v
1276 }
1277 }
1278 wd, err := os.Getwd()
1279 if err != nil {
1280 return ""
1281 }
1282 return wd
1283}
1284
1285func (c *configImpl) rbeDir() string {
1286 if v, ok := c.environ.Get("RBE_DIR"); ok {
1287 return v
1288 }
1289 return "prebuilts/remoteexecution-client/live/"
1290}
1291
1292func (c *configImpl) rbeReproxy() string {
1293 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1294 if v, ok := c.environ.Get(f); ok {
1295 return v
1296 }
1297 }
1298 return filepath.Join(c.rbeDir(), "reproxy")
1299}
1300
1301func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001302 credFlags := []string{
1303 "use_application_default_credentials",
1304 "use_gce_credentials",
1305 "credential_file",
1306 "use_google_prod_creds",
1307 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001308 for _, cf := range credFlags {
1309 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1310 if v, ok := c.environ.Get(f); ok {
1311 v = strings.TrimSpace(v)
1312 if v != "" && v != "false" && v != "0" {
1313 return "RBE_" + cf, v
1314 }
1315 }
1316 }
1317 }
1318 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001319}
1320
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001321func (c *configImpl) rbeSockAddr(dir string) (string, error) {
1322 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
1323 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1324
1325 name := filepath.Join(dir, base)
1326 if len(name) < maxNameLen {
1327 return name, nil
1328 }
1329
1330 name = filepath.Join("/tmp", base)
1331 if len(name) < maxNameLen {
1332 return name, nil
1333 }
1334
1335 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1336}
1337
Kousik Kumar7bc78192022-04-27 14:52:56 -04001338// IsGooglerEnvironment returns true if the current build is running
1339// on a Google developer machine and false otherwise.
1340func (c *configImpl) IsGooglerEnvironment() bool {
1341 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1342 if v, ok := c.environ.Get(cf); ok {
1343 return v == "googler"
1344 }
1345 return false
1346}
1347
1348// GoogleProdCredsExist determine whether credentials exist on the
1349// Googler machine to use remote execution.
1350func (c *configImpl) GoogleProdCredsExist() bool {
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001351 if googleProdCredsExistCache {
1352 return googleProdCredsExistCache
1353 }
Kousik Kumar7bc78192022-04-27 14:52:56 -04001354 if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
1355 return false
1356 }
Kevin Dagostino096ab2f2023-03-03 19:47:17 +00001357 googleProdCredsExistCache = true
Kousik Kumar7bc78192022-04-27 14:52:56 -04001358 return true
1359}
1360
1361// UseRemoteBuild indicates whether to use a remote build acceleration system
1362// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001363func (c *configImpl) UseRemoteBuild() bool {
1364 return c.UseGoma() || c.UseRBE()
1365}
1366
Kousik Kumar7bc78192022-04-27 14:52:56 -04001367// StubbyExists checks whether the stubby binary exists on the machine running
1368// the build.
1369func (c *configImpl) StubbyExists() bool {
1370 if _, err := exec.LookPath("stubby"); err != nil {
1371 return false
1372 }
1373 return true
1374}
1375
Dan Willemsen1e704462016-08-21 15:17:17 -07001376// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001377// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001378// still limited by Parallel()
1379func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001380 if !c.UseRemoteBuild() {
1381 return 0
1382 }
1383 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1384 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001385 }
1386 return 500
1387}
1388
1389func (c *configImpl) SetKatiArgs(args []string) {
1390 c.katiArgs = args
1391}
1392
1393func (c *configImpl) SetNinjaArgs(args []string) {
1394 c.ninjaArgs = args
1395}
1396
1397func (c *configImpl) SetKatiSuffix(suffix string) {
1398 c.katiSuffix = suffix
1399}
1400
Dan Willemsene0879fc2017-08-04 15:06:27 -07001401func (c *configImpl) LastKatiSuffixFile() string {
1402 return filepath.Join(c.OutDir(), "last_kati_suffix")
1403}
1404
1405func (c *configImpl) HasKatiSuffix() bool {
1406 return c.katiSuffix != ""
1407}
1408
Dan Willemsen1e704462016-08-21 15:17:17 -07001409func (c *configImpl) KatiEnvFile() string {
1410 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1411}
1412
Dan Willemsen29971232018-09-26 14:58:30 -07001413func (c *configImpl) KatiBuildNinjaFile() string {
1414 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001415}
1416
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001417func (c *configImpl) KatiPackageNinjaFile() string {
1418 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1419}
1420
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001421func (c *configImpl) SoongVarsFile() string {
1422 return filepath.Join(c.SoongOutDir(), "soong.variables")
1423}
1424
Dan Willemsen1e704462016-08-21 15:17:17 -07001425func (c *configImpl) SoongNinjaFile() string {
1426 return filepath.Join(c.SoongOutDir(), "build.ninja")
1427}
1428
1429func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001430 if c.katiSuffix == "" {
1431 return filepath.Join(c.OutDir(), "combined.ninja")
1432 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001433 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1434}
1435
1436func (c *configImpl) SoongAndroidMk() string {
1437 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1438}
1439
1440func (c *configImpl) SoongMakeVarsMk() string {
1441 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1442}
1443
Dan Willemsenf052f782017-05-18 15:29:04 -07001444func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001445 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001446}
1447
Dan Willemsen02781d52017-05-12 19:28:13 -07001448func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001449 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1450}
1451
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001452func (c *configImpl) KatiPackageMkDir() string {
1453 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1454}
1455
Dan Willemsenf052f782017-05-18 15:29:04 -07001456func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001457 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001458}
1459
1460func (c *configImpl) HostOut() string {
1461 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1462}
1463
1464// This probably needs to be multi-valued, so not exporting it for now
1465func (c *configImpl) hostCrossOut() string {
1466 if runtime.GOOS == "linux" {
1467 return filepath.Join(c.hostOutRoot(), "windows-x86")
1468 } else {
1469 return ""
1470 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001471}
1472
Dan Willemsen1e704462016-08-21 15:17:17 -07001473func (c *configImpl) HostPrebuiltTag() string {
1474 if runtime.GOOS == "linux" {
1475 return "linux-x86"
1476 } else if runtime.GOOS == "darwin" {
1477 return "darwin-x86"
1478 } else {
1479 panic("Unsupported OS")
1480 }
1481}
Dan Willemsenf173d592017-04-27 14:28:00 -07001482
Dan Willemsen8122bd52017-10-12 20:20:41 -07001483func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001484 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1485 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001486 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1487 if _, err := os.Stat(asan); err == nil {
1488 return asan
1489 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001490 }
1491 }
1492 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1493}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001494
1495func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1496 c.brokenDupRules = val
1497}
1498
1499func (c *configImpl) BuildBrokenDupRules() bool {
1500 return c.brokenDupRules
1501}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001502
Dan Willemsen25e6f092019-04-09 10:22:43 -07001503func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1504 c.brokenUsesNetwork = val
1505}
1506
1507func (c *configImpl) BuildBrokenUsesNetwork() bool {
1508 return c.brokenUsesNetwork
1509}
1510
Dan Willemsene3336352020-01-02 19:10:38 -08001511func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1512 c.brokenNinjaEnvVars = val
1513}
1514
1515func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1516 return c.brokenNinjaEnvVars
1517}
1518
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001519func (c *configImpl) SetTargetDeviceDir(dir string) {
1520 c.targetDeviceDir = dir
1521}
1522
1523func (c *configImpl) TargetDeviceDir() string {
1524 return c.targetDeviceDir
1525}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001526
Patrice Arruda219eef32020-06-01 17:29:30 +00001527func (c *configImpl) BuildDateTime() string {
1528 return c.buildDateTime
1529}
1530
1531func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001532 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001533}
Patrice Arruda83842d72020-12-08 19:42:08 +00001534
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001535// LogsDir returns the absolute path to the logs directory where build log and
1536// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001537// directory. If the argument dist is specified, the logs directory
1538// is <dist_dir>/logs.
1539func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001540 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001541 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001542 // 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 -05001543 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001544 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001545 absDir, err := filepath.Abs(dir)
1546 if err != nil {
1547 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1548 os.Exit(1)
1549 }
1550 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001551}
1552
1553// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1554// where the bazel profiles are located.
1555func (c *configImpl) BazelMetricsDir() string {
1556 return filepath.Join(c.LogsDir(), "bazel_metrics")
1557}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001558
Chris Parsons53f68ae2022-03-03 12:01:40 -05001559// MkFileMetrics returns the file path for make-related metrics.
1560func (c *configImpl) MkMetrics() string {
1561 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1562}
1563
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001564func (c *configImpl) SetEmptyNinjaFile(v bool) {
1565 c.emptyNinjaFile = v
1566}
1567
1568func (c *configImpl) EmptyNinjaFile() bool {
1569 return c.emptyNinjaFile
1570}
Yu Liu6e13b402021-07-27 14:29:06 -07001571
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001572func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
1573 return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
1574}
1575
Chris Parsons9402ca82023-02-23 17:28:06 -05001576func (c *configImpl) IsPersistentBazelEnabled() bool {
1577 return c.Environment().IsEnvTrue("USE_PERSISTENT_BAZEL")
1578}
1579
MarkDacekd06db5d2022-11-29 00:47:59 +00001580func (c *configImpl) BazelModulesForceEnabledByFlag() string {
1581 return c.bazelForceEnabledModules
1582}
1583
MarkDacekd0e7cd32022-12-02 22:22:40 +00001584func (c *configImpl) SkipMetricsUpload() bool {
1585 return c.skipMetricsUpload
1586}
1587
MarkDacek6614d9c2022-12-07 21:57:38 +00001588// Returns a Time object if one was passed via a command-line flag.
1589// Otherwise returns the passed default.
1590func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1591 if c.buildStartedTime == 0 {
1592 return defaultTime
1593 }
1594 return time.UnixMilli(c.buildStartedTime)
1595}
1596
Yu Liu6e13b402021-07-27 14:29:06 -07001597func GetMetricsUploader(topDir string, env *Environment) string {
1598 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1599 metricsUploader := filepath.Join(topDir, p)
1600 if _, err := os.Stat(metricsUploader); err == nil {
1601 return metricsUploader
1602 }
1603 }
1604
1605 return ""
1606}