blob: cb7fe1e89631d2d57b7fcd047c6596a35a16c018 [file] [log] [blame]
Dan Willemsen1e704462016-08-21 15:17:17 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package build
16
17import (
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050018 "context"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050019 "encoding/json"
Ramy Medhat0fc67eb2020-08-12 01:26:23 -040020 "fmt"
Kousik Kumar3ff037e2022-01-25 22:11:01 -050021 "io/ioutil"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040022 "math/rand"
Dan Willemsenc2af0be2017-01-20 14:10:01 -080023 "os"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050024 "os/exec"
Dan Willemsen1e704462016-08-21 15:17:17 -070025 "path/filepath"
26 "runtime"
27 "strconv"
28 "strings"
Kousik Kumar4c180ad2022-05-27 07:48:37 -040029 "syscall"
Nan Zhang2e6a4ff2018-02-14 13:27:26 -080030 "time"
Jeff Gastonefc1b412017-03-29 17:29:06 -070031
32 "android/soong/shared"
Kousik Kumarec478642020-09-21 13:39:24 -040033
Dan Willemsen4591b642021-05-24 14:24:12 -070034 "google.golang.org/protobuf/proto"
Patrice Arruda96850362020-08-11 20:41:11 +000035
36 smpb "android/soong/ui/metrics/metrics_proto"
Dan Willemsen1e704462016-08-21 15:17:17 -070037)
38
Kousik Kumar3ff037e2022-01-25 22:11:01 -050039const (
Chris Parsons53f68ae2022-03-03 12:01:40 -050040 envConfigDir = "vendor/google/tools/soong_config"
41 jsonSuffix = "json"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050042
Chris Parsons53f68ae2022-03-03 12:01:40 -050043 configFetcher = "vendor/google/tools/soong/expconfigfetcher"
Kousik Kumar84bd5bf2022-01-26 23:32:22 -050044 envConfigFetchTimeout = 10 * time.Second
Kousik Kumar3ff037e2022-01-25 22:11:01 -050045)
46
Kousik Kumar4c180ad2022-05-27 07:48:37 -040047var (
48 rbeRandPrefix int
49)
50
51func init() {
52 rand.Seed(time.Now().UnixNano())
53 rbeRandPrefix = rand.Intn(1000)
54}
55
Dan Willemsen1e704462016-08-21 15:17:17 -070056type Config struct{ *configImpl }
57
58type configImpl struct {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +020059 // Some targets that are implemented in soong_build
60 // (bp2build, json-module-graph) are not here and have their own bits below.
Colin Cross28f527c2019-11-26 16:19:04 -080061 arguments []string
62 goma bool
63 environ *Environment
64 distDir string
65 buildDateTime string
MarkDacek6614d9c2022-12-07 21:57:38 +000066 logsPrefix string
Dan Willemsen1e704462016-08-21 15:17:17 -070067
68 // From the arguments
MarkDacekd0e7cd32022-12-02 22:22:40 +000069 parallel int
70 keepGoing int
71 verbose bool
72 checkbuild bool
73 dist bool
74 jsonModuleGraph bool
75 apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
76 bp2build bool
77 queryview bool
78 reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
79 soongDocs bool
80 skipConfig bool
81 skipKati bool
82 skipKatiNinja bool
83 skipSoong bool
84 skipNinja bool
85 skipSoongTests bool
86 searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
87 skipMetricsUpload bool
MarkDacek6614d9c2022-12-07 21:57:38 +000088 buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
Dan Willemsen1e704462016-08-21 15:17:17 -070089
90 // From the product config
Dan Willemsen6ab79db2018-05-02 00:06:28 -070091 katiArgs []string
92 ninjaArgs []string
93 katiSuffix string
94 targetDevice string
95 targetDeviceDir string
Spandan Dasa3639e62021-05-25 19:14:02 +000096 sandboxConfig *SandboxConfig
Dan Willemsen3d60b112018-04-04 22:25:56 -070097
Dan Willemsen2bb82d02019-12-27 09:35:42 -080098 // Autodetected
99 totalRAM uint64
100
Dan Willemsene3336352020-01-02 19:10:38 -0800101 brokenDupRules bool
102 brokenUsesNetwork bool
103 brokenNinjaEnvVars []string
Dan Willemsen18490112018-05-25 16:30:04 -0700104
105 pathReplaced bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000106
MarkDacekb78465d2022-10-18 20:10:16 +0000107 bazelProdMode bool
108 bazelDevMode bool
109 bazelStagingMode bool
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000110
Colin Crossf3bdbcb2021-06-01 11:43:55 -0700111 // Set by multiproduct_kati
112 emptyNinjaFile bool
Yu Liu6e13b402021-07-27 14:29:06 -0700113
114 metricsUploader string
MarkDacekd06db5d2022-11-29 00:47:59 +0000115
116 bazelForceEnabledModules string
Spandan Dasc5763832022-11-08 18:42:16 +0000117
118 includeTags []string
Dan Willemsen1e704462016-08-21 15:17:17 -0700119}
120
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800121const srcDirFileCheck = "build/soong/root.bp"
122
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700123var buildFiles = []string{"Android.mk", "Android.bp"}
124
Patrice Arruda13848222019-04-22 17:12:02 -0700125type BuildAction uint
126
127const (
128 // Builds all of the modules and their dependencies of a specified directory, relative to the root
129 // directory of the source tree.
130 BUILD_MODULES_IN_A_DIRECTORY BuildAction = iota
131
132 // Builds all of the modules and their dependencies of a list of specified directories. All specified
133 // directories are relative to the root directory of the source tree.
134 BUILD_MODULES_IN_DIRECTORIES
Patrice Arruda39282062019-06-20 16:35:12 -0700135
136 // Build a list of specified modules. If none was specified, simply build the whole source tree.
137 BUILD_MODULES
Patrice Arruda13848222019-04-22 17:12:02 -0700138)
139
140// checkTopDir validates that the current directory is at the root directory of the source tree.
141func checkTopDir(ctx Context) {
142 if _, err := os.Stat(srcDirFileCheck); err != nil {
143 if os.IsNotExist(err) {
144 ctx.Fatalf("Current working directory must be the source tree. %q not found.", srcDirFileCheck)
145 }
146 ctx.Fatalln("Error verifying tree state:", err)
147 }
148}
149
Kousik Kumarc8818332023-01-16 16:33:05 +0000150// fetchEnvConfig optionally fetches a configuration file that can then subsequently be
151// loaded into Soong environment to control certain aspects of build behavior (e.g., enabling RBE).
152// If a configuration file already exists on disk, the fetch is run in the background
153// so as to NOT block the rest of the build execution.
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500154func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
David Goldsmith62243a32022-04-08 13:42:04 +0000155 configName := envConfigName + "." + jsonSuffix
Kousik Kumarc75e1292022-07-07 02:20:51 +0000156 expConfigFetcher := &smpb.ExpConfigFetcher{Filename: &configName}
David Goldsmith62243a32022-04-08 13:42:04 +0000157 defer func() {
158 ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
159 }()
Kousik Kumarc75e1292022-07-07 02:20:51 +0000160 if !config.GoogleProdCredsExist() {
161 status := smpb.ExpConfigFetcher_MISSING_GCERT
162 expConfigFetcher.Status = &status
163 return nil
164 }
David Goldsmith62243a32022-04-08 13:42:04 +0000165
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500166 s, err := os.Stat(configFetcher)
167 if err != nil {
168 if os.IsNotExist(err) {
169 return nil
170 }
171 return err
172 }
173 if s.Mode()&0111 == 0 {
David Goldsmith62243a32022-04-08 13:42:04 +0000174 status := smpb.ExpConfigFetcher_ERROR
175 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500176 return fmt.Errorf("configuration fetcher binary %v is not executable: %v", configFetcher, s.Mode())
177 }
178
Kousik Kumarc8818332023-01-16 16:33:05 +0000179 configExists := false
180 outConfigFilePath := filepath.Join(config.OutDir(), configName)
181 if _, err := os.Stat(outConfigFilePath); err == nil {
182 configExists = true
183 }
184
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500185 tCtx, cancel := context.WithTimeout(ctx, envConfigFetchTimeout)
David Goldsmith62243a32022-04-08 13:42:04 +0000186 fetchStart := time.Now()
187 cmd := exec.CommandContext(tCtx, configFetcher, "-output_config_dir", config.OutDir(),
188 "-output_config_name", configName)
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500189 if err := cmd.Start(); err != nil {
David Goldsmith62243a32022-04-08 13:42:04 +0000190 status := smpb.ExpConfigFetcher_ERROR
191 expConfigFetcher.Status = &status
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500192 return err
193 }
194
Kousik Kumarc8818332023-01-16 16:33:05 +0000195 fetchCfg := func() error {
196 if err := cmd.Wait(); err != nil {
197 status := smpb.ExpConfigFetcher_ERROR
198 expConfigFetcher.Status = &status
199 return err
200 }
201 fetchEnd := time.Now()
202 expConfigFetcher.Micros = proto.Uint64(uint64(fetchEnd.Sub(fetchStart).Microseconds()))
203 expConfigFetcher.Filename = proto.String(outConfigFilePath)
204
205 if _, err := os.Stat(outConfigFilePath); err != nil {
206 status := smpb.ExpConfigFetcher_NO_CONFIG
207 expConfigFetcher.Status = &status
208 return err
209 }
David Goldsmith62243a32022-04-08 13:42:04 +0000210 status := smpb.ExpConfigFetcher_CONFIG
211 expConfigFetcher.Status = &status
Kousik Kumarc8818332023-01-16 16:33:05 +0000212 return nil
David Goldsmith62243a32022-04-08 13:42:04 +0000213 }
Kousik Kumarc8818332023-01-16 16:33:05 +0000214
215 // If a config file does not exist, wait for the config file to be fetched. Otherwise
216 // fetch the config file in the background and return immediately.
217 if !configExists {
218 defer cancel()
219 return fetchCfg()
220 }
221
222 go func() {
223 defer cancel()
224 if err := fetchCfg(); err != nil {
225 ctx.Verbosef("Failed to fetch config file %v: %v\n", configName, err)
226 }
227 }()
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500228 return nil
229}
230
MarkDacek7901e582023-01-09 19:48:01 +0000231func loadEnvConfig(ctx Context, config *configImpl, bc string) error {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500232 if bc == "" {
233 return nil
234 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500235
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500236 configDirs := []string{
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500237 config.OutDir(),
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500238 os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500239 envConfigDir,
240 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500241 for _, dir := range configDirs {
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500242 cfgFile := filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
243 envVarsJSON, err := ioutil.ReadFile(cfgFile)
244 if err != nil {
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500245 continue
246 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500247 ctx.Verbosef("Loading config file %v\n", cfgFile)
248 var envVars map[string]map[string]string
249 if err := json.Unmarshal(envVarsJSON, &envVars); err != nil {
250 fmt.Fprintf(os.Stderr, "Env vars config file %s did not parse correctly: %s", cfgFile, err.Error())
251 continue
252 }
253 for k, v := range envVars["env"] {
254 if os.Getenv(k) != "" {
255 continue
256 }
257 config.environ.Set(k, v)
258 }
259 ctx.Verbosef("Finished loading config file %v\n", cfgFile)
260 break
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500261 }
Kousik Kumar84bd5bf2022-01-26 23:32:22 -0500262
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500263 return nil
264}
265
Chris Parsonsb6e96902022-10-31 20:08:45 -0400266func defaultBazelProdMode(cfg *configImpl) bool {
MarkDacekd06db5d2022-11-29 00:47:59 +0000267 // Environment flag to disable Bazel for users which experience
Chris Parsonsb6e96902022-10-31 20:08:45 -0400268 // broken bazel-handled builds, or significant performance regressions.
269 if cfg.IsBazelMixedBuildForceDisabled() {
270 return false
271 }
272 // Darwin-host builds are currently untested with Bazel.
273 if runtime.GOOS == "darwin" {
274 return false
275 }
Chris Parsons035e03a2022-11-01 14:25:45 -0400276 return true
Chris Parsonsb6e96902022-10-31 20:08:45 -0400277}
278
MarkDacek6614d9c2022-12-07 21:57:38 +0000279func UploadOnlyConfig(ctx Context, _ ...string) Config {
280 ret := &configImpl{
281 environ: OsEnvironment(),
282 sandboxConfig: &SandboxConfig{},
283 }
MarkDacek7901e582023-01-09 19:48:01 +0000284 srcDir := absPath(ctx, ".")
285 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
286 if err := loadEnvConfig(ctx, ret, bc); err != nil {
287 ctx.Fatalln("Failed to parse env config files: %v", err)
288 }
289 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
MarkDacek6614d9c2022-12-07 21:57:38 +0000290 return Config{ret}
291}
292
Dan Willemsen1e704462016-08-21 15:17:17 -0700293func NewConfig(ctx Context, args ...string) Config {
294 ret := &configImpl{
Spandan Dasa3639e62021-05-25 19:14:02 +0000295 environ: OsEnvironment(),
296 sandboxConfig: &SandboxConfig{},
Dan Willemsen1e704462016-08-21 15:17:17 -0700297 }
298
Patrice Arruda90109172020-07-28 18:07:27 +0000299 // Default matching ninja
Dan Willemsen9b587492017-07-10 22:13:00 -0700300 ret.parallel = runtime.NumCPU() + 2
301 ret.keepGoing = 1
302
Dan Willemsen2bb82d02019-12-27 09:35:42 -0800303 ret.totalRAM = detectTotalRAM(ctx)
Dan Willemsen9b587492017-07-10 22:13:00 -0700304 ret.parseArgs(ctx, args)
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800305 // Make sure OUT_DIR is set appropriately
Dan Willemsen02f3add2017-05-12 13:50:19 -0700306 if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
307 ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
308 } else {
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800309 outDir := "out"
310 if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok {
311 if wd, err := os.Getwd(); err != nil {
312 ctx.Fatalln("Failed to get working directory:", err)
313 } else {
314 outDir = filepath.Join(baseDir, filepath.Base(wd))
315 }
316 }
317 ret.environ.Set("OUT_DIR", outDir)
318 }
319
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500320 // loadEnvConfig needs to know what the OUT_DIR is, so it should
321 // be called after we determine the appropriate out directory.
MarkDacek7901e582023-01-09 19:48:01 +0000322 bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
323
324 if bc != "" {
325 if err := fetchEnvConfig(ctx, ret, bc); err != nil {
326 ctx.Verbosef("Failed to fetch config file: %v\n", err)
Kousik Kumarc8818332023-01-16 16:33:05 +0000327 }
328 if err := loadEnvConfig(ctx, ret, bc); err != nil {
MarkDacek7901e582023-01-09 19:48:01 +0000329 ctx.Fatalln("Failed to parse env config files: %v", err)
330 }
Kousik Kumar3ff037e2022-01-25 22:11:01 -0500331 }
332
Dan Willemsen2d31a442018-10-20 21:33:41 -0700333 if distDir, ok := ret.environ.Get("DIST_DIR"); ok {
334 ret.distDir = filepath.Clean(distDir)
335 } else {
336 ret.distDir = filepath.Join(ret.OutDir(), "dist")
337 }
Dan Willemsend50e89f2018-10-16 17:49:25 -0700338
Spandan Das05063612021-06-25 01:39:04 +0000339 if srcDirIsWritable, ok := ret.environ.Get("BUILD_BROKEN_SRC_DIR_IS_WRITABLE"); ok {
340 ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
341 }
342
Dan Willemsen1e704462016-08-21 15:17:17 -0700343 ret.environ.Unset(
344 // We're already using it
345 "USE_SOONG_UI",
346
347 // We should never use GOROOT/GOPATH from the shell environment
348 "GOROOT",
349 "GOPATH",
350
351 // These should only come from Soong, not the environment.
352 "CLANG",
353 "CLANG_CXX",
354 "CCC_CC",
355 "CCC_CXX",
356
357 // Used by the goma compiler wrapper, but should only be set by
358 // gomacc
359 "GOMACC_PATH",
Dan Willemsen0c3919e2017-03-02 15:49:10 -0800360
361 // We handle this above
362 "OUT_DIR_COMMON_BASE",
Dan Willemsen68a09852017-04-18 13:56:57 -0700363
Dan Willemsen2d31a442018-10-20 21:33:41 -0700364 // This is handled above too, and set for individual commands later
365 "DIST_DIR",
366
Dan Willemsen68a09852017-04-18 13:56:57 -0700367 // Variables that have caused problems in the past
Dan Willemsen1c504d92019-11-18 19:13:53 +0000368 "BASH_ENV",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700369 "CDPATH",
Dan Willemsen68a09852017-04-18 13:56:57 -0700370 "DISPLAY",
371 "GREP_OPTIONS",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700372 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700373 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700374
375 // Drop make flags
376 "MAKEFLAGS",
377 "MAKELEVEL",
378 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700379
380 // Set in envsetup.sh, reset in makefiles
381 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700382
383 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
384 "ANDROID_BUILD_TOP",
385 "ANDROID_HOST_OUT",
386 "ANDROID_PRODUCT_OUT",
387 "ANDROID_HOST_OUT_TESTCASES",
388 "ANDROID_TARGET_OUT_TESTCASES",
389 "ANDROID_TOOLCHAIN",
390 "ANDROID_TOOLCHAIN_2ND_ARCH",
391 "ANDROID_DEV_SCRIPTS",
392 "ANDROID_EMULATOR_PREBUILTS",
393 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700394 )
395
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400396 if ret.UseGoma() || ret.ForceUseGoma() {
397 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
398 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400399 }
400
Dan Willemsen1e704462016-08-21 15:17:17 -0700401 // Tell python not to spam the source tree with .pyc files.
402 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
403
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400404 tmpDir := absPath(ctx, ret.TempDir())
405 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800406
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700407 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
408 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
409 "llvm-binutils-stable/llvm-symbolizer")
410 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
411
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800412 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700413 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800414
Yu Liu6e13b402021-07-27 14:29:06 -0700415 srcDir := absPath(ctx, ".")
416 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700417 ctx.Println("You are building in a directory whose absolute path contains a space character:")
418 ctx.Println()
419 ctx.Printf("%q\n", srcDir)
420 ctx.Println()
421 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700422 }
423
Yu Liu6e13b402021-07-27 14:29:06 -0700424 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
425
Dan Willemsendb8457c2017-05-12 16:38:17 -0700426 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700427 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
428 ctx.Println()
429 ctx.Printf("%q\n", outDir)
430 ctx.Println()
431 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700432 }
433
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000434 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700435 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
436 ctx.Println()
437 ctx.Printf("%q\n", distDir)
438 ctx.Println()
439 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700440 }
441
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700442 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000443 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
444 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100445 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Colin Cross59c1e6a2022-03-04 13:37:19 -0800446 java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700447 javaHome := func() string {
448 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
449 return override
450 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000451 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
452 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 +0100453 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000454 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
455 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
456 }
457 return java17Home
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
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700463 newPath := []string{filepath.Join(absJavaHome, "bin")}
464 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
465 newPath = append(newPath, path)
466 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100467
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700468 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
469 ret.environ.Set("JAVA_HOME", absJavaHome)
470 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000471 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
472 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100473 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700474 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
475
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800476 outDir := ret.OutDir()
477 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800478 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800479 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800480 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800481 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800482 }
Colin Cross28f527c2019-11-26 16:19:04 -0800483
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800484 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
485
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400486 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400487 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400488 ret.environ.Set(k, v)
489 }
490 }
491
Patrice Arruda83842d72020-12-08 19:42:08 +0000492 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800493 if err := os.RemoveAll(bpd); err != nil {
494 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
495 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000496
Patrice Arruda96850362020-08-11 20:41:11 +0000497 c := Config{ret}
498 storeConfigMetrics(ctx, c)
499 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700500}
501
Patrice Arruda13848222019-04-22 17:12:02 -0700502// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
503// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700504func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
505 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700506}
507
Patrice Arruda96850362020-08-11 20:41:11 +0000508// storeConfigMetrics selects a set of configuration information and store in
509// the metrics system for further analysis.
510func storeConfigMetrics(ctx Context, config Config) {
511 if ctx.Metrics == nil {
512 return
513 }
514
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400515 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000516
517 s := &smpb.SystemResourceInfo{
518 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
519 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
520 }
521 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000522}
523
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400524func buildConfig(config Config) *smpb.BuildConfig {
Yu Liue737a992021-10-04 13:21:41 -0700525 c := &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -0400526 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
527 UseGoma: proto.Bool(config.UseGoma()),
528 UseRbe: proto.Bool(config.UseRBE()),
529 BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
530 ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400531 }
Yu Liue737a992021-10-04 13:21:41 -0700532 c.Targets = append(c.Targets, config.arguments...)
533
534 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400535}
536
Patrice Arruda13848222019-04-22 17:12:02 -0700537// getConfigArgs processes the command arguments based on the build action and creates a set of new
538// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700539func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700540 // The next block of code verifies that the current directory is the root directory of the source
541 // tree. It then finds the relative path of dir based on the root directory of the source tree
542 // and verify that dir is inside of the source tree.
543 checkTopDir(ctx)
544 topDir, err := os.Getwd()
545 if err != nil {
546 ctx.Fatalf("Error retrieving top directory: %v", err)
547 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700548 dir, err = filepath.EvalSymlinks(dir)
549 if err != nil {
550 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
551 }
Patrice Arruda13848222019-04-22 17:12:02 -0700552 dir, err = filepath.Abs(dir)
553 if err != nil {
554 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
555 }
556 relDir, err := filepath.Rel(topDir, dir)
557 if err != nil {
558 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
559 }
560 // If there are ".." in the path, it's not in the source tree.
561 if strings.Contains(relDir, "..") {
562 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
563 }
564
565 configArgs := args[:]
566
567 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
568 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
569 targetNamePrefix := "MODULES-IN-"
570 if inList("GET-INSTALL-PATH", configArgs) {
571 targetNamePrefix = "GET-INSTALL-PATH-IN-"
572 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
573 }
574
Patrice Arruda13848222019-04-22 17:12:02 -0700575 var targets []string
576
577 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700578 case BUILD_MODULES:
579 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700580 case BUILD_MODULES_IN_A_DIRECTORY:
581 // If dir is the root source tree, all the modules are built of the source tree are built so
582 // no need to find the build file.
583 if topDir == dir {
584 break
585 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700586
Patrice Arruda13848222019-04-22 17:12:02 -0700587 buildFile := findBuildFile(ctx, relDir)
588 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700589 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700590 }
Patrice Arruda13848222019-04-22 17:12:02 -0700591 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
592 case BUILD_MODULES_IN_DIRECTORIES:
593 newConfigArgs, dirs := splitArgs(configArgs)
594 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700595 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700596 }
597
598 // Tidy only override all other specified targets.
599 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
600 if tidyOnly == "true" || tidyOnly == "1" {
601 configArgs = append(configArgs, "tidy_only")
602 } else {
603 configArgs = append(configArgs, targets...)
604 }
605
606 return configArgs
607}
608
609// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
610func convertToTarget(dir string, targetNamePrefix string) string {
611 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
612}
613
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700614// hasBuildFile returns true if dir contains an Android build file.
615func hasBuildFile(ctx Context, dir string) bool {
616 for _, buildFile := range buildFiles {
617 _, err := os.Stat(filepath.Join(dir, buildFile))
618 if err == nil {
619 return true
620 }
621 if !os.IsNotExist(err) {
622 ctx.Fatalf("Error retrieving the build file stats: %v", err)
623 }
624 }
625 return false
626}
627
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700628// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
629// in the current and any sub directory of dir. If a build file is not found, traverse the path
630// up by one directory and repeat again until either a build file is found or reached to the root
631// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
632// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700633func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700634 // If the string is empty or ".", assume it is top directory of the source tree.
635 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700636 return ""
637 }
638
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700639 found := false
640 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
641 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
642 if err != nil {
643 return err
644 }
645 if found {
646 return filepath.SkipDir
647 }
648 if info.IsDir() {
649 return nil
650 }
651 for _, buildFile := range buildFiles {
652 if info.Name() == buildFile {
653 found = true
654 return filepath.SkipDir
655 }
656 }
657 return nil
658 })
659 if err != nil {
660 ctx.Fatalf("Error finding Android build file: %v", err)
661 }
662
663 if found {
664 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700665 }
666 }
667
668 return ""
669}
670
671// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
672func splitArgs(args []string) (newArgs []string, dirs []string) {
673 specialArgs := map[string]bool{
674 "showcommands": true,
675 "snod": true,
676 "dist": true,
677 "checkbuild": true,
678 }
679
680 newArgs = []string{}
681 dirs = []string{}
682
683 for _, arg := range args {
684 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
685 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
686 newArgs = append(newArgs, arg)
687 continue
688 }
689
690 if _, ok := specialArgs[arg]; ok {
691 newArgs = append(newArgs, arg)
692 continue
693 }
694
695 dirs = append(dirs, arg)
696 }
697
698 return newArgs, dirs
699}
700
701// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
702// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
703// source root tree where the build action command was invoked. Each directory is validated if the
704// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700705func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700706 for _, dir := range dirs {
707 // The directory may have specified specific modules to build. ":" is the separator to separate
708 // the directory and the list of modules.
709 s := strings.Split(dir, ":")
710 l := len(s)
711 if l > 2 { // more than one ":" was specified.
712 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
713 }
714
715 dir = filepath.Join(relDir, s[0])
716 if _, err := os.Stat(dir); err != nil {
717 ctx.Fatalf("couldn't find directory %s", dir)
718 }
719
720 // Verify that if there are any targets specified after ":". Each target is separated by ",".
721 var newTargets []string
722 if l == 2 && s[1] != "" {
723 newTargets = strings.Split(s[1], ",")
724 if inList("", newTargets) {
725 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
726 }
727 }
728
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700729 // If there are specified targets to build in dir, an android build file must exist for the one
730 // shot build. For the non-targets case, find the appropriate build file and build all the
731 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700732 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700733 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700734 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
735 }
736 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700737 buildFile := findBuildFile(ctx, dir)
738 if buildFile == "" {
739 ctx.Fatalf("Build file not found for %s directory", dir)
740 }
741 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700742 }
743
Patrice Arruda13848222019-04-22 17:12:02 -0700744 targets = append(targets, newTargets...)
745 }
746
Dan Willemsence41e942019-07-29 23:39:30 -0700747 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700748}
749
Dan Willemsen9b587492017-07-10 22:13:00 -0700750func (c *configImpl) parseArgs(ctx Context, args []string) {
751 for i := 0; i < len(args); i++ {
752 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100753 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700754 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200755 } else if arg == "--empty-ninja-file" {
756 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100757 } else if arg == "--skip-ninja" {
758 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700759 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700760 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
761 // but it does run a Kati ninja file if the .kati_enabled marker file was created
762 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000763 c.skipConfig = true
764 c.skipKati = true
765 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100766 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000767 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100768 } else if arg == "--soong-only" {
769 c.skipKati = true
770 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200771 } else if arg == "--config-only" {
772 c.skipKati = true
773 c.skipKatiNinja = true
774 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700775 } else if arg == "--skip-config" {
776 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700777 } else if arg == "--skip-soong-tests" {
778 c.skipSoongTests = true
MarkDacekd0e7cd32022-12-02 22:22:40 +0000779 } else if arg == "--skip-metrics-upload" {
780 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500781 } else if arg == "--mk-metrics" {
782 c.reportMkMetrics = true
Chris Parsonsef615e52022-08-18 22:04:11 -0400783 } else if arg == "--bazel-mode" {
784 c.bazelProdMode = true
785 } else if arg == "--bazel-mode-dev" {
786 c.bazelDevMode = true
MarkDacekb78465d2022-10-18 20:10:16 +0000787 } else if arg == "--bazel-mode-staging" {
788 c.bazelStagingMode = true
Spandan Das394aa322022-11-03 17:02:10 +0000789 } else if arg == "--search-api-dir" {
790 c.searchApiDir = true
MarkDacekb96561e2022-12-02 04:34:43 +0000791 } else if strings.HasPrefix(arg, "--build-command=") {
792 buildCmd := strings.TrimPrefix(arg, "--build-command=")
793 // remove quotations
794 buildCmd = strings.TrimPrefix(buildCmd, "\"")
795 buildCmd = strings.TrimSuffix(buildCmd, "\"")
796 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacekd06db5d2022-11-29 00:47:59 +0000797 } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
798 c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
MarkDacek6614d9c2022-12-07 21:57:38 +0000799 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
800 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
801 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
802 if err == nil {
803 c.buildStartedTime = val
804 } else {
805 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
806 }
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700807 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700808 parseArgNum := func(def int) int {
809 if len(arg) > 2 {
810 p, err := strconv.ParseUint(arg[2:], 10, 31)
811 if err != nil {
812 ctx.Fatalf("Failed to parse %q: %v", arg, err)
813 }
814 return int(p)
815 } else if i+1 < len(args) {
816 p, err := strconv.ParseUint(args[i+1], 10, 31)
817 if err == nil {
818 i++
819 return int(p)
820 }
821 }
822 return def
823 }
824
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700825 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700826 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700827 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700828 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700829 } else {
830 ctx.Fatalln("Unknown option:", arg)
831 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700832 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700833 if k == "OUT_DIR" {
834 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
835 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700836 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700837 } else if arg == "dist" {
838 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200839 } else if arg == "json-module-graph" {
840 c.jsonModuleGraph = true
841 } else if arg == "bp2build" {
842 c.bp2build = true
Spandan Das5af0bd32022-09-28 20:43:08 +0000843 } else if arg == "api_bp2build" {
844 c.apiBp2build = true
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200845 } else if arg == "queryview" {
846 c.queryview = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200847 } else if arg == "soong_docs" {
848 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700849 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700850 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800851 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700852 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700853 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700854 }
855 }
Chris Parsonsb6e96902022-10-31 20:08:45 -0400856 if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
857 c.bazelProdMode = defaultBazelProdMode(c)
858 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700859}
860
Dan Willemsened869522018-01-08 14:58:46 -0800861func (c *configImpl) configureLocale(ctx Context) {
862 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
863 output, err := cmd.Output()
864
865 var locales []string
866 if err == nil {
867 locales = strings.Split(string(output), "\n")
868 } else {
869 // If we're unable to list the locales, let's assume en_US.UTF-8
870 locales = []string{"en_US.UTF-8"}
871 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
872 }
873
874 // gettext uses LANGUAGE, which is passed directly through
875
876 // For LANG and LC_*, only preserve the evaluated version of
877 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800878 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800879 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800880 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800881 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800882 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800883 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800884 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800885 }
886
887 c.environ.UnsetWithPrefix("LC_")
888
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800889 if userLang != "" {
890 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800891 }
892
893 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
894 // for others)
895 if inList("C.UTF-8", locales) {
896 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500897 } else if inList("C.utf8", locales) {
898 // These normalize to the same thing
899 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800900 } else if inList("en_US.UTF-8", locales) {
901 c.environ.Set("LANG", "en_US.UTF-8")
902 } else if inList("en_US.utf8", locales) {
903 // These normalize to the same thing
904 c.environ.Set("LANG", "en_US.UTF-8")
905 } else {
906 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
907 }
908}
909
Dan Willemsen1e704462016-08-21 15:17:17 -0700910func (c *configImpl) Environment() *Environment {
911 return c.environ
912}
913
914func (c *configImpl) Arguments() []string {
915 return c.arguments
916}
917
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200918func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200919 if len(c.Arguments()) > 0 {
920 // Explicit targets requested that are not special targets like b2pbuild
921 // or the JSON module graph
922 return true
923 }
924
Spandan Das5af0bd32022-09-28 20:43:08 +0000925 if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200926 // Command line was empty, the default Ninja target is built
927 return true
928 }
929
Liz Kammer88677422021-12-15 15:03:19 -0500930 // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
931 if c.Dist() && !c.Bp2Build() {
932 return true
933 }
934
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200935 // build.ninja doesn't need to be generated
936 return false
937}
938
Dan Willemsen1e704462016-08-21 15:17:17 -0700939func (c *configImpl) OutDir() string {
940 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700941 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700942 }
943 return "out"
944}
945
Dan Willemsen8a073a82017-02-04 17:30:44 -0800946func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -0400947 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000948}
949
950func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700951 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800952}
953
Dan Willemsen1e704462016-08-21 15:17:17 -0700954func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000955 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700956 return c.arguments
957 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700958 return c.ninjaArgs
959}
960
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500961func (c *configImpl) BazelOutDir() string {
962 return filepath.Join(c.OutDir(), "bazel")
963}
964
Liz Kammer2af5ea82022-11-11 14:21:03 -0500965func (c *configImpl) bazelOutputBase() string {
966 return filepath.Join(c.BazelOutDir(), "output")
967}
968
Dan Willemsen1e704462016-08-21 15:17:17 -0700969func (c *configImpl) SoongOutDir() string {
970 return filepath.Join(c.OutDir(), "soong")
971}
972
Spandan Das394aa322022-11-03 17:02:10 +0000973func (c *configImpl) ApiSurfacesOutDir() string {
974 return filepath.Join(c.OutDir(), "api_surfaces")
975}
976
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200977func (c *configImpl) PrebuiltOS() string {
978 switch runtime.GOOS {
979 case "linux":
980 return "linux-x86"
981 case "darwin":
982 return "darwin-x86"
983 default:
984 panic("Unknown GOOS")
985 }
986}
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100987
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200988func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -0700989 if c.SkipKatiNinja() {
990 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
991 } else {
992 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
993 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200994}
995
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200996func (c *configImpl) NamedGlobFile(name string) string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100997 return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200998}
999
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001000func (c *configImpl) UsedEnvFile(tag string) string {
1001 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
1002}
1003
Lukacs T. Berkic541cd22022-10-26 07:26:50 +00001004func (c *configImpl) Bp2BuildFilesMarkerFile() string {
1005 return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
1006}
1007
1008func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +01001009 return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +02001010}
1011
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001012func (c *configImpl) SoongDocsHtml() string {
1013 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
1014}
1015
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001016func (c *configImpl) QueryviewMarkerFile() string {
1017 return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
1018}
1019
Spandan Das5af0bd32022-09-28 20:43:08 +00001020func (c *configImpl) ApiBp2buildMarkerFile() string {
1021 return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
1022}
1023
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001024func (c *configImpl) ModuleGraphFile() string {
1025 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1026}
1027
kgui67007242022-01-25 13:50:25 +08001028func (c *configImpl) ModuleActionsFile() string {
1029 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1030}
1031
Jeff Gastonefc1b412017-03-29 17:29:06 -07001032func (c *configImpl) TempDir() string {
1033 return shared.TempDirForOutDir(c.SoongOutDir())
1034}
1035
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001036func (c *configImpl) FileListDir() string {
1037 return filepath.Join(c.OutDir(), ".module_paths")
1038}
1039
Dan Willemsen1e704462016-08-21 15:17:17 -07001040func (c *configImpl) KatiSuffix() string {
1041 if c.katiSuffix != "" {
1042 return c.katiSuffix
1043 }
1044 panic("SetKatiSuffix has not been called")
1045}
1046
Colin Cross37193492017-11-16 17:55:00 -08001047// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1048// user is interested in additional checks at the expense of build time.
1049func (c *configImpl) Checkbuild() bool {
1050 return c.checkbuild
1051}
1052
Dan Willemsen8a073a82017-02-04 17:30:44 -08001053func (c *configImpl) Dist() bool {
1054 return c.dist
1055}
1056
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001057func (c *configImpl) JsonModuleGraph() bool {
1058 return c.jsonModuleGraph
1059}
1060
1061func (c *configImpl) Bp2Build() bool {
1062 return c.bp2build
1063}
1064
Spandan Das5af0bd32022-09-28 20:43:08 +00001065func (c *configImpl) ApiBp2build() bool {
1066 return c.apiBp2build
1067}
1068
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001069func (c *configImpl) Queryview() bool {
1070 return c.queryview
1071}
1072
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001073func (c *configImpl) SoongDocs() bool {
1074 return c.soongDocs
1075}
1076
Dan Willemsen1e704462016-08-21 15:17:17 -07001077func (c *configImpl) IsVerbose() bool {
1078 return c.verbose
1079}
1080
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001081func (c *configImpl) SkipKati() bool {
1082 return c.skipKati
1083}
1084
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001085func (c *configImpl) SkipKatiNinja() bool {
1086 return c.skipKatiNinja
1087}
1088
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001089func (c *configImpl) SkipSoong() bool {
1090 return c.skipSoong
1091}
1092
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001093func (c *configImpl) SkipNinja() bool {
1094 return c.skipNinja
1095}
1096
Anton Hansson5a7861a2021-06-04 10:09:01 +01001097func (c *configImpl) SetSkipNinja(v bool) {
1098 c.skipNinja = v
1099}
1100
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001101func (c *configImpl) SkipConfig() bool {
1102 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001103}
1104
Dan Willemsen1e704462016-08-21 15:17:17 -07001105func (c *configImpl) TargetProduct() string {
1106 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1107 return v
1108 }
1109 panic("TARGET_PRODUCT is not defined")
1110}
1111
Dan Willemsen02781d52017-05-12 19:28:13 -07001112func (c *configImpl) TargetDevice() string {
1113 return c.targetDevice
1114}
1115
1116func (c *configImpl) SetTargetDevice(device string) {
1117 c.targetDevice = device
1118}
1119
1120func (c *configImpl) TargetBuildVariant() string {
1121 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1122 return v
1123 }
1124 panic("TARGET_BUILD_VARIANT is not defined")
1125}
1126
Dan Willemsen1e704462016-08-21 15:17:17 -07001127func (c *configImpl) KatiArgs() []string {
1128 return c.katiArgs
1129}
1130
1131func (c *configImpl) Parallel() int {
1132 return c.parallel
1133}
1134
Spandan Dasc5763832022-11-08 18:42:16 +00001135func (c *configImpl) GetIncludeTags() []string {
1136 return c.includeTags
1137}
1138
1139func (c *configImpl) SetIncludeTags(i []string) {
1140 c.includeTags = i
1141}
1142
MarkDacek6614d9c2022-12-07 21:57:38 +00001143func (c *configImpl) GetLogsPrefix() string {
1144 return c.logsPrefix
1145}
1146
1147func (c *configImpl) SetLogsPrefix(prefix string) {
1148 c.logsPrefix = prefix
1149}
1150
Colin Cross8b8bec32019-11-15 13:18:43 -08001151func (c *configImpl) HighmemParallel() int {
1152 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1153 return i
1154 }
1155
1156 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1157 parallel := c.Parallel()
1158 if c.UseRemoteBuild() {
1159 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1160 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1161 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1162 // Return 1/16th of the size of the local pool, rounding up.
1163 return (parallel + 15) / 16
1164 } else if c.totalRAM == 0 {
1165 // Couldn't detect the total RAM, don't restrict highmem processes.
1166 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001167 } else if c.totalRAM <= 16*1024*1024*1024 {
1168 // Less than 16GB of ram, restrict to 1 highmem processes
1169 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001170 } else if c.totalRAM <= 32*1024*1024*1024 {
1171 // Less than 32GB of ram, restrict to 2 highmem processes
1172 return 2
1173 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1174 // If less than 8GB total RAM per process, reduce the number of highmem processes
1175 return p
1176 }
1177 // No restriction on highmem processes
1178 return parallel
1179}
1180
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001181func (c *configImpl) TotalRAM() uint64 {
1182 return c.totalRAM
1183}
1184
Kousik Kumarec478642020-09-21 13:39:24 -04001185// ForceUseGoma determines whether we should override Goma deprecation
1186// and use Goma for the current build or not.
1187func (c *configImpl) ForceUseGoma() bool {
1188 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1189 v = strings.TrimSpace(v)
1190 if v != "" && v != "false" {
1191 return true
1192 }
1193 }
1194 return false
1195}
1196
Dan Willemsen1e704462016-08-21 15:17:17 -07001197func (c *configImpl) UseGoma() bool {
1198 if v, ok := c.environ.Get("USE_GOMA"); ok {
1199 v = strings.TrimSpace(v)
1200 if v != "" && v != "false" {
1201 return true
1202 }
1203 }
1204 return false
1205}
1206
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001207func (c *configImpl) StartGoma() bool {
1208 if !c.UseGoma() {
1209 return false
1210 }
1211
1212 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1213 v = strings.TrimSpace(v)
1214 if v != "" && v != "false" {
1215 return false
1216 }
1217 }
1218 return true
1219}
1220
Ramy Medhatbbf25672019-07-17 12:30:04 +00001221func (c *configImpl) UseRBE() bool {
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001222 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001223 v = strings.TrimSpace(v)
1224 if v != "" && v != "false" {
1225 return true
1226 }
1227 }
1228 return false
1229}
1230
Chris Parsonsef615e52022-08-18 22:04:11 -04001231func (c *configImpl) BazelBuildEnabled() bool {
MarkDacekb78465d2022-10-18 20:10:16 +00001232 return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
Chris Parsonsec1a3dc2021-04-20 15:32:07 -04001233}
1234
Ramy Medhatbbf25672019-07-17 12:30:04 +00001235func (c *configImpl) StartRBE() bool {
1236 if !c.UseRBE() {
1237 return false
1238 }
1239
1240 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1241 v = strings.TrimSpace(v)
1242 if v != "" && v != "false" {
1243 return false
1244 }
1245 }
1246 return true
1247}
1248
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001249func (c *configImpl) rbeProxyLogsDir() string {
1250 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001251 if v, ok := c.environ.Get(f); ok {
1252 return v
1253 }
1254 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001255 buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
1256 return filepath.Join(buildTmpDir, "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001257}
1258
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001259func (c *configImpl) shouldCleanupRBELogsDir() bool {
1260 // Perform a log directory cleanup only when the log directory
1261 // is auto created by the build rather than user-specified.
1262 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
1263 if _, ok := c.environ.Get(f); ok {
1264 return false
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001265 }
1266 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001267 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001268}
1269
1270func (c *configImpl) rbeExecRoot() string {
1271 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1272 if v, ok := c.environ.Get(f); ok {
1273 return v
1274 }
1275 }
1276 wd, err := os.Getwd()
1277 if err != nil {
1278 return ""
1279 }
1280 return wd
1281}
1282
1283func (c *configImpl) rbeDir() string {
1284 if v, ok := c.environ.Get("RBE_DIR"); ok {
1285 return v
1286 }
1287 return "prebuilts/remoteexecution-client/live/"
1288}
1289
1290func (c *configImpl) rbeReproxy() string {
1291 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1292 if v, ok := c.environ.Get(f); ok {
1293 return v
1294 }
1295 }
1296 return filepath.Join(c.rbeDir(), "reproxy")
1297}
1298
1299func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001300 credFlags := []string{
1301 "use_application_default_credentials",
1302 "use_gce_credentials",
1303 "credential_file",
1304 "use_google_prod_creds",
1305 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001306 for _, cf := range credFlags {
1307 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1308 if v, ok := c.environ.Get(f); ok {
1309 v = strings.TrimSpace(v)
1310 if v != "" && v != "false" && v != "0" {
1311 return "RBE_" + cf, v
1312 }
1313 }
1314 }
1315 }
1316 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001317}
1318
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001319func (c *configImpl) rbeSockAddr(dir string) (string, error) {
1320 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
1321 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1322
1323 name := filepath.Join(dir, base)
1324 if len(name) < maxNameLen {
1325 return name, nil
1326 }
1327
1328 name = filepath.Join("/tmp", base)
1329 if len(name) < maxNameLen {
1330 return name, nil
1331 }
1332
1333 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1334}
1335
Kousik Kumar7bc78192022-04-27 14:52:56 -04001336// IsGooglerEnvironment returns true if the current build is running
1337// on a Google developer machine and false otherwise.
1338func (c *configImpl) IsGooglerEnvironment() bool {
1339 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1340 if v, ok := c.environ.Get(cf); ok {
1341 return v == "googler"
1342 }
1343 return false
1344}
1345
1346// GoogleProdCredsExist determine whether credentials exist on the
1347// Googler machine to use remote execution.
1348func (c *configImpl) GoogleProdCredsExist() bool {
1349 if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
1350 return false
1351 }
1352 return true
1353}
1354
1355// UseRemoteBuild indicates whether to use a remote build acceleration system
1356// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001357func (c *configImpl) UseRemoteBuild() bool {
1358 return c.UseGoma() || c.UseRBE()
1359}
1360
Kousik Kumar7bc78192022-04-27 14:52:56 -04001361// StubbyExists checks whether the stubby binary exists on the machine running
1362// the build.
1363func (c *configImpl) StubbyExists() bool {
1364 if _, err := exec.LookPath("stubby"); err != nil {
1365 return false
1366 }
1367 return true
1368}
1369
Dan Willemsen1e704462016-08-21 15:17:17 -07001370// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001371// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001372// still limited by Parallel()
1373func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001374 if !c.UseRemoteBuild() {
1375 return 0
1376 }
1377 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1378 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001379 }
1380 return 500
1381}
1382
1383func (c *configImpl) SetKatiArgs(args []string) {
1384 c.katiArgs = args
1385}
1386
1387func (c *configImpl) SetNinjaArgs(args []string) {
1388 c.ninjaArgs = args
1389}
1390
1391func (c *configImpl) SetKatiSuffix(suffix string) {
1392 c.katiSuffix = suffix
1393}
1394
Dan Willemsene0879fc2017-08-04 15:06:27 -07001395func (c *configImpl) LastKatiSuffixFile() string {
1396 return filepath.Join(c.OutDir(), "last_kati_suffix")
1397}
1398
1399func (c *configImpl) HasKatiSuffix() bool {
1400 return c.katiSuffix != ""
1401}
1402
Dan Willemsen1e704462016-08-21 15:17:17 -07001403func (c *configImpl) KatiEnvFile() string {
1404 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1405}
1406
Dan Willemsen29971232018-09-26 14:58:30 -07001407func (c *configImpl) KatiBuildNinjaFile() string {
1408 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001409}
1410
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001411func (c *configImpl) KatiPackageNinjaFile() string {
1412 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1413}
1414
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001415func (c *configImpl) SoongVarsFile() string {
1416 return filepath.Join(c.SoongOutDir(), "soong.variables")
1417}
1418
Dan Willemsen1e704462016-08-21 15:17:17 -07001419func (c *configImpl) SoongNinjaFile() string {
1420 return filepath.Join(c.SoongOutDir(), "build.ninja")
1421}
1422
1423func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001424 if c.katiSuffix == "" {
1425 return filepath.Join(c.OutDir(), "combined.ninja")
1426 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001427 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1428}
1429
1430func (c *configImpl) SoongAndroidMk() string {
1431 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1432}
1433
1434func (c *configImpl) SoongMakeVarsMk() string {
1435 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1436}
1437
Dan Willemsenf052f782017-05-18 15:29:04 -07001438func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001439 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001440}
1441
Dan Willemsen02781d52017-05-12 19:28:13 -07001442func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001443 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1444}
1445
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001446func (c *configImpl) KatiPackageMkDir() string {
1447 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1448}
1449
Dan Willemsenf052f782017-05-18 15:29:04 -07001450func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001451 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001452}
1453
1454func (c *configImpl) HostOut() string {
1455 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1456}
1457
1458// This probably needs to be multi-valued, so not exporting it for now
1459func (c *configImpl) hostCrossOut() string {
1460 if runtime.GOOS == "linux" {
1461 return filepath.Join(c.hostOutRoot(), "windows-x86")
1462 } else {
1463 return ""
1464 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001465}
1466
Dan Willemsen1e704462016-08-21 15:17:17 -07001467func (c *configImpl) HostPrebuiltTag() string {
1468 if runtime.GOOS == "linux" {
1469 return "linux-x86"
1470 } else if runtime.GOOS == "darwin" {
1471 return "darwin-x86"
1472 } else {
1473 panic("Unsupported OS")
1474 }
1475}
Dan Willemsenf173d592017-04-27 14:28:00 -07001476
Dan Willemsen8122bd52017-10-12 20:20:41 -07001477func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001478 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1479 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001480 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1481 if _, err := os.Stat(asan); err == nil {
1482 return asan
1483 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001484 }
1485 }
1486 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1487}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001488
1489func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1490 c.brokenDupRules = val
1491}
1492
1493func (c *configImpl) BuildBrokenDupRules() bool {
1494 return c.brokenDupRules
1495}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001496
Dan Willemsen25e6f092019-04-09 10:22:43 -07001497func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1498 c.brokenUsesNetwork = val
1499}
1500
1501func (c *configImpl) BuildBrokenUsesNetwork() bool {
1502 return c.brokenUsesNetwork
1503}
1504
Dan Willemsene3336352020-01-02 19:10:38 -08001505func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1506 c.brokenNinjaEnvVars = val
1507}
1508
1509func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1510 return c.brokenNinjaEnvVars
1511}
1512
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001513func (c *configImpl) SetTargetDeviceDir(dir string) {
1514 c.targetDeviceDir = dir
1515}
1516
1517func (c *configImpl) TargetDeviceDir() string {
1518 return c.targetDeviceDir
1519}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001520
Patrice Arruda219eef32020-06-01 17:29:30 +00001521func (c *configImpl) BuildDateTime() string {
1522 return c.buildDateTime
1523}
1524
1525func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001526 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001527}
Patrice Arruda83842d72020-12-08 19:42:08 +00001528
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001529// LogsDir returns the absolute path to the logs directory where build log and
1530// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001531// directory. If the argument dist is specified, the logs directory
1532// is <dist_dir>/logs.
1533func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001534 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001535 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001536 // 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 -05001537 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001538 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001539 absDir, err := filepath.Abs(dir)
1540 if err != nil {
1541 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1542 os.Exit(1)
1543 }
1544 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001545}
1546
1547// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1548// where the bazel profiles are located.
1549func (c *configImpl) BazelMetricsDir() string {
1550 return filepath.Join(c.LogsDir(), "bazel_metrics")
1551}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001552
Chris Parsons53f68ae2022-03-03 12:01:40 -05001553// MkFileMetrics returns the file path for make-related metrics.
1554func (c *configImpl) MkMetrics() string {
1555 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1556}
1557
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001558func (c *configImpl) SetEmptyNinjaFile(v bool) {
1559 c.emptyNinjaFile = v
1560}
1561
1562func (c *configImpl) EmptyNinjaFile() bool {
1563 return c.emptyNinjaFile
1564}
Yu Liu6e13b402021-07-27 14:29:06 -07001565
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001566func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
1567 return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
1568}
1569
MarkDacekd06db5d2022-11-29 00:47:59 +00001570func (c *configImpl) BazelModulesForceEnabledByFlag() string {
1571 return c.bazelForceEnabledModules
1572}
1573
MarkDacekd0e7cd32022-12-02 22:22:40 +00001574func (c *configImpl) SkipMetricsUpload() bool {
1575 return c.skipMetricsUpload
1576}
1577
MarkDacek6614d9c2022-12-07 21:57:38 +00001578// Returns a Time object if one was passed via a command-line flag.
1579// Otherwise returns the passed default.
1580func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1581 if c.buildStartedTime == 0 {
1582 return defaultTime
1583 }
1584 return time.UnixMilli(c.buildStartedTime)
1585}
1586
Yu Liu6e13b402021-07-27 14:29:06 -07001587func GetMetricsUploader(topDir string, env *Environment) string {
1588 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1589 metricsUploader := filepath.Join(topDir, p)
1590 if _, err := os.Stat(metricsUploader); err == nil {
1591 return metricsUploader
1592 }
1593 }
1594
1595 return ""
1596}