blob: 73e2c45e113dfd20ba390759ac29b5f57895e6da [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",
Nathan Egge7b067fb2023-02-17 17:54:31 +0000372 "JAVAC",
Dan Willemsenebfe33a2018-05-01 10:07:50 -0700373 "NDK_ROOT",
Dan Willemsen00fcb262018-08-15 15:35:38 -0700374 "POSIXLY_CORRECT",
Dan Willemsenc40e10b2017-07-11 14:30:00 -0700375
376 // Drop make flags
377 "MAKEFLAGS",
378 "MAKELEVEL",
379 "MFLAGS",
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700380
381 // Set in envsetup.sh, reset in makefiles
382 "ANDROID_JAVA_TOOLCHAIN",
Colin Cross7f09c402018-07-11 14:49:31 -0700383
384 // Set by envsetup.sh, but shouldn't be used inside the build because envsetup.sh is optional
385 "ANDROID_BUILD_TOP",
386 "ANDROID_HOST_OUT",
387 "ANDROID_PRODUCT_OUT",
388 "ANDROID_HOST_OUT_TESTCASES",
389 "ANDROID_TARGET_OUT_TESTCASES",
390 "ANDROID_TOOLCHAIN",
391 "ANDROID_TOOLCHAIN_2ND_ARCH",
392 "ANDROID_DEV_SCRIPTS",
393 "ANDROID_EMULATOR_PREBUILTS",
394 "ANDROID_PRE_BUILD_PATHS",
Dan Willemsen1e704462016-08-21 15:17:17 -0700395 )
396
Kousik Kumarb328f6d2020-10-19 01:45:46 -0400397 if ret.UseGoma() || ret.ForceUseGoma() {
398 ctx.Println("Goma for Android has been deprecated and replaced with RBE. See go/rbe_for_android for instructions on how to use RBE.")
399 ctx.Fatalln("USE_GOMA / FORCE_USE_GOMA flag is no longer supported.")
Kousik Kumarec478642020-09-21 13:39:24 -0400400 }
401
Dan Willemsen1e704462016-08-21 15:17:17 -0700402 // Tell python not to spam the source tree with .pyc files.
403 ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1")
404
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400405 tmpDir := absPath(ctx, ret.TempDir())
406 ret.environ.Set("TMPDIR", tmpDir)
Dan Willemsen32a669b2018-03-08 19:42:00 -0800407
Dan Willemsen70c1ff82019-08-21 14:56:13 -0700408 // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes
409 symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(),
410 "llvm-binutils-stable/llvm-symbolizer")
411 ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath))
412
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800413 // Precondition: the current directory is the top of the source tree
Patrice Arruda13848222019-04-22 17:12:02 -0700414 checkTopDir(ctx)
Dan Willemsenc2af0be2017-01-20 14:10:01 -0800415
Yu Liu6e13b402021-07-27 14:29:06 -0700416 srcDir := absPath(ctx, ".")
417 if strings.ContainsRune(srcDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700418 ctx.Println("You are building in a directory whose absolute path contains a space character:")
419 ctx.Println()
420 ctx.Printf("%q\n", srcDir)
421 ctx.Println()
422 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700423 }
424
Yu Liu6e13b402021-07-27 14:29:06 -0700425 ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
426
Dan Willemsendb8457c2017-05-12 16:38:17 -0700427 if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700428 ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
429 ctx.Println()
430 ctx.Printf("%q\n", outDir)
431 ctx.Println()
432 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700433 }
434
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000435 if distDir := ret.RealDistDir(); strings.ContainsRune(distDir, ' ') {
Colin Cross1f6faeb2019-09-23 15:52:40 -0700436 ctx.Println("The absolute path of your dist directory ($DIST_DIR) contains a space character:")
437 ctx.Println()
438 ctx.Printf("%q\n", distDir)
439 ctx.Println()
440 ctx.Fatalln("Directory names containing spaces are not supported")
Dan Willemsendb8457c2017-05-12 16:38:17 -0700441 }
442
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700443 // Configure Java-related variables, including adding it to $PATH
Tobias Thierere59aeff2017-12-20 22:40:39 +0000444 java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
445 java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
Pete Gillin1f52e932019-10-09 17:10:08 +0100446 java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
Colin Cross59c1e6a2022-03-04 13:37:19 -0800447 java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700448 javaHome := func() string {
449 if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
450 return override
451 }
Pete Gillina7a3d642019-11-07 18:58:42 +0000452 if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
453 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 +0100454 }
Sorin Basca7e094b32022-10-05 08:20:12 +0000455 if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
456 ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
457 }
458 return java17Home
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700459 }()
460 absJavaHome := absPath(ctx, javaHome)
461
Dan Willemsened869522018-01-08 14:58:46 -0800462 ret.configureLocale(ctx)
463
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700464 newPath := []string{filepath.Join(absJavaHome, "bin")}
465 if path, ok := ret.environ.Get("PATH"); ok && path != "" {
466 newPath = append(newPath, path)
467 }
Pete Gillin1f52e932019-10-09 17:10:08 +0100468
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700469 ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME")
470 ret.environ.Set("JAVA_HOME", absJavaHome)
471 ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
Tobias Thierere59aeff2017-12-20 22:40:39 +0000472 ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
473 ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
Pete Gillin1f52e932019-10-09 17:10:08 +0100474 ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
Dan Willemsend9e8f0a2017-10-30 13:42:06 -0700475 ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
476
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800477 outDir := ret.OutDir()
478 buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800479 if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
Colin Cross28f527c2019-11-26 16:19:04 -0800480 ret.buildDateTime = buildDateTime
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800481 } else {
Colin Cross28f527c2019-11-26 16:19:04 -0800482 ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800483 }
Colin Cross28f527c2019-11-26 16:19:04 -0800484
Nan Zhang2e6a4ff2018-02-14 13:27:26 -0800485 ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
486
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400487 if ret.UseRBE() {
Ramy Medhat0fc67eb2020-08-12 01:26:23 -0400488 for k, v := range getRBEVars(ctx, Config{ret}) {
Ramy Medhatca1e44c2020-07-16 12:18:37 -0400489 ret.environ.Set(k, v)
490 }
491 }
492
Patrice Arruda83842d72020-12-08 19:42:08 +0000493 bpd := ret.BazelMetricsDir()
Patrice Arrudaaf880da2020-11-13 08:41:26 -0800494 if err := os.RemoveAll(bpd); err != nil {
495 ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
496 }
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000497
Patrice Arruda96850362020-08-11 20:41:11 +0000498 c := Config{ret}
499 storeConfigMetrics(ctx, c)
500 return c
Dan Willemsen9b587492017-07-10 22:13:00 -0700501}
502
Patrice Arruda13848222019-04-22 17:12:02 -0700503// NewBuildActionConfig returns a build configuration based on the build action. The arguments are
504// processed based on the build action and extracts any arguments that belongs to the build action.
Dan Willemsence41e942019-07-29 23:39:30 -0700505func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
506 return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
Patrice Arruda13848222019-04-22 17:12:02 -0700507}
508
Patrice Arruda96850362020-08-11 20:41:11 +0000509// storeConfigMetrics selects a set of configuration information and store in
510// the metrics system for further analysis.
511func storeConfigMetrics(ctx Context, config Config) {
512 if ctx.Metrics == nil {
513 return
514 }
515
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400516 ctx.Metrics.BuildConfig(buildConfig(config))
Patrice Arruda3edfd482020-10-13 23:58:41 +0000517
518 s := &smpb.SystemResourceInfo{
519 TotalPhysicalMemory: proto.Uint64(config.TotalRAM()),
520 AvailableCpus: proto.Int32(int32(runtime.NumCPU())),
521 }
522 ctx.Metrics.SystemResourceInfo(s)
Patrice Arruda96850362020-08-11 20:41:11 +0000523}
524
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400525func buildConfig(config Config) *smpb.BuildConfig {
Yu Liue737a992021-10-04 13:21:41 -0700526 c := &smpb.BuildConfig{
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -0400527 ForceUseGoma: proto.Bool(config.ForceUseGoma()),
528 UseGoma: proto.Bool(config.UseGoma()),
529 UseRbe: proto.Bool(config.UseRBE()),
530 BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
531 ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400532 }
Yu Liue737a992021-10-04 13:21:41 -0700533 c.Targets = append(c.Targets, config.arguments...)
534
535 return c
Liz Kammerca9cb2e2021-07-14 15:29:57 -0400536}
537
Patrice Arruda13848222019-04-22 17:12:02 -0700538// getConfigArgs processes the command arguments based on the build action and creates a set of new
539// arguments to be accepted by Config.
Dan Willemsence41e942019-07-29 23:39:30 -0700540func getConfigArgs(action BuildAction, dir string, ctx Context, args []string) []string {
Patrice Arruda13848222019-04-22 17:12:02 -0700541 // The next block of code verifies that the current directory is the root directory of the source
542 // tree. It then finds the relative path of dir based on the root directory of the source tree
543 // and verify that dir is inside of the source tree.
544 checkTopDir(ctx)
545 topDir, err := os.Getwd()
546 if err != nil {
547 ctx.Fatalf("Error retrieving top directory: %v", err)
548 }
Patrice Arrudababa9a92019-07-03 10:47:34 -0700549 dir, err = filepath.EvalSymlinks(dir)
550 if err != nil {
551 ctx.Fatalf("Unable to evaluate symlink of %s: %v", dir, err)
552 }
Patrice Arruda13848222019-04-22 17:12:02 -0700553 dir, err = filepath.Abs(dir)
554 if err != nil {
555 ctx.Fatalf("Unable to find absolute path %s: %v", dir, err)
556 }
557 relDir, err := filepath.Rel(topDir, dir)
558 if err != nil {
559 ctx.Fatalf("Unable to find relative path %s of %s: %v", relDir, topDir, err)
560 }
561 // If there are ".." in the path, it's not in the source tree.
562 if strings.Contains(relDir, "..") {
563 ctx.Fatalf("Directory %s is not under the source tree %s", dir, topDir)
564 }
565
566 configArgs := args[:]
567
568 // If the arguments contains GET-INSTALL-PATH, change the target name prefix from MODULES-IN- to
569 // GET-INSTALL-PATH-IN- to extract the installation path instead of building the modules.
570 targetNamePrefix := "MODULES-IN-"
571 if inList("GET-INSTALL-PATH", configArgs) {
572 targetNamePrefix = "GET-INSTALL-PATH-IN-"
573 configArgs = removeFromList("GET-INSTALL-PATH", configArgs)
574 }
575
Patrice Arruda13848222019-04-22 17:12:02 -0700576 var targets []string
577
578 switch action {
Patrice Arruda39282062019-06-20 16:35:12 -0700579 case BUILD_MODULES:
580 // No additional processing is required when building a list of specific modules or all modules.
Patrice Arruda13848222019-04-22 17:12:02 -0700581 case BUILD_MODULES_IN_A_DIRECTORY:
582 // If dir is the root source tree, all the modules are built of the source tree are built so
583 // no need to find the build file.
584 if topDir == dir {
585 break
586 }
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700587
Patrice Arruda13848222019-04-22 17:12:02 -0700588 buildFile := findBuildFile(ctx, relDir)
589 if buildFile == "" {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700590 ctx.Fatalf("Build file not found for %s directory", relDir)
Patrice Arruda13848222019-04-22 17:12:02 -0700591 }
Patrice Arruda13848222019-04-22 17:12:02 -0700592 targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
593 case BUILD_MODULES_IN_DIRECTORIES:
594 newConfigArgs, dirs := splitArgs(configArgs)
595 configArgs = newConfigArgs
Dan Willemsence41e942019-07-29 23:39:30 -0700596 targets = getTargetsFromDirs(ctx, relDir, dirs, targetNamePrefix)
Patrice Arruda13848222019-04-22 17:12:02 -0700597 }
598
599 // Tidy only override all other specified targets.
600 tidyOnly := os.Getenv("WITH_TIDY_ONLY")
601 if tidyOnly == "true" || tidyOnly == "1" {
602 configArgs = append(configArgs, "tidy_only")
603 } else {
604 configArgs = append(configArgs, targets...)
605 }
606
607 return configArgs
608}
609
610// convertToTarget replaces "/" to "-" in dir and pre-append the targetNamePrefix to the target name.
611func convertToTarget(dir string, targetNamePrefix string) string {
612 return targetNamePrefix + strings.ReplaceAll(dir, "/", "-")
613}
614
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700615// hasBuildFile returns true if dir contains an Android build file.
616func hasBuildFile(ctx Context, dir string) bool {
617 for _, buildFile := range buildFiles {
618 _, err := os.Stat(filepath.Join(dir, buildFile))
619 if err == nil {
620 return true
621 }
622 if !os.IsNotExist(err) {
623 ctx.Fatalf("Error retrieving the build file stats: %v", err)
624 }
625 }
626 return false
627}
628
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700629// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
630// in the current and any sub directory of dir. If a build file is not found, traverse the path
631// up by one directory and repeat again until either a build file is found or reached to the root
632// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
633// string is returned.
Patrice Arruda13848222019-04-22 17:12:02 -0700634func findBuildFile(ctx Context, dir string) string {
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700635 // If the string is empty or ".", assume it is top directory of the source tree.
636 if dir == "" || dir == "." {
Patrice Arruda13848222019-04-22 17:12:02 -0700637 return ""
638 }
639
Patrice Arruda0dcf27f2019-07-08 17:03:33 -0700640 found := false
641 for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
642 err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
643 if err != nil {
644 return err
645 }
646 if found {
647 return filepath.SkipDir
648 }
649 if info.IsDir() {
650 return nil
651 }
652 for _, buildFile := range buildFiles {
653 if info.Name() == buildFile {
654 found = true
655 return filepath.SkipDir
656 }
657 }
658 return nil
659 })
660 if err != nil {
661 ctx.Fatalf("Error finding Android build file: %v", err)
662 }
663
664 if found {
665 return filepath.Join(buildDir, "Android.mk")
Patrice Arruda13848222019-04-22 17:12:02 -0700666 }
667 }
668
669 return ""
670}
671
672// splitArgs iterates over the arguments list and splits into two lists: arguments and directories.
673func splitArgs(args []string) (newArgs []string, dirs []string) {
674 specialArgs := map[string]bool{
675 "showcommands": true,
676 "snod": true,
677 "dist": true,
678 "checkbuild": true,
679 }
680
681 newArgs = []string{}
682 dirs = []string{}
683
684 for _, arg := range args {
685 // It's a dash argument if it starts with "-" or it's a key=value pair, it's not a directory.
686 if strings.IndexRune(arg, '-') == 0 || strings.IndexRune(arg, '=') != -1 {
687 newArgs = append(newArgs, arg)
688 continue
689 }
690
691 if _, ok := specialArgs[arg]; ok {
692 newArgs = append(newArgs, arg)
693 continue
694 }
695
696 dirs = append(dirs, arg)
697 }
698
699 return newArgs, dirs
700}
701
702// getTargetsFromDirs iterates over the dirs list and creates a list of targets to build. If a
703// directory from the dirs list does not exist, a fatal error is raised. relDir is related to the
704// source root tree where the build action command was invoked. Each directory is validated if the
705// build file can be found and follows the format "dir1:target1,target2,...". Target is optional.
Dan Willemsence41e942019-07-29 23:39:30 -0700706func getTargetsFromDirs(ctx Context, relDir string, dirs []string, targetNamePrefix string) (targets []string) {
Patrice Arruda13848222019-04-22 17:12:02 -0700707 for _, dir := range dirs {
708 // The directory may have specified specific modules to build. ":" is the separator to separate
709 // the directory and the list of modules.
710 s := strings.Split(dir, ":")
711 l := len(s)
712 if l > 2 { // more than one ":" was specified.
713 ctx.Fatalf("%s not in proper directory:target1,target2,... format (\":\" was specified more than once)", dir)
714 }
715
716 dir = filepath.Join(relDir, s[0])
717 if _, err := os.Stat(dir); err != nil {
718 ctx.Fatalf("couldn't find directory %s", dir)
719 }
720
721 // Verify that if there are any targets specified after ":". Each target is separated by ",".
722 var newTargets []string
723 if l == 2 && s[1] != "" {
724 newTargets = strings.Split(s[1], ",")
725 if inList("", newTargets) {
726 ctx.Fatalf("%s not in proper directory:target1,target2,... format", dir)
727 }
728 }
729
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700730 // If there are specified targets to build in dir, an android build file must exist for the one
731 // shot build. For the non-targets case, find the appropriate build file and build all the
732 // modules in dir (or the closest one in the dir path).
Patrice Arruda13848222019-04-22 17:12:02 -0700733 if len(newTargets) > 0 {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700734 if !hasBuildFile(ctx, dir) {
Patrice Arruda13848222019-04-22 17:12:02 -0700735 ctx.Fatalf("Couldn't locate a build file from %s directory", dir)
736 }
737 } else {
Patrice Arruda9450d0b2019-07-08 11:06:46 -0700738 buildFile := findBuildFile(ctx, dir)
739 if buildFile == "" {
740 ctx.Fatalf("Build file not found for %s directory", dir)
741 }
742 newTargets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
Patrice Arruda13848222019-04-22 17:12:02 -0700743 }
744
Patrice Arruda13848222019-04-22 17:12:02 -0700745 targets = append(targets, newTargets...)
746 }
747
Dan Willemsence41e942019-07-29 23:39:30 -0700748 return targets
Patrice Arruda13848222019-04-22 17:12:02 -0700749}
750
Dan Willemsen9b587492017-07-10 22:13:00 -0700751func (c *configImpl) parseArgs(ctx Context, args []string) {
752 for i := 0; i < len(args); i++ {
753 arg := strings.TrimSpace(args[i])
Anton Hansson5a7861a2021-06-04 10:09:01 +0100754 if arg == "showcommands" {
Dan Willemsen9b587492017-07-10 22:13:00 -0700755 c.verbose = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200756 } else if arg == "--empty-ninja-file" {
757 c.emptyNinjaFile = true
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +0100758 } else if arg == "--skip-ninja" {
759 c.skipNinja = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700760 } else if arg == "--skip-make" {
Colin Cross30e444b2021-06-18 11:26:19 -0700761 // TODO(ccross): deprecate this, it has confusing behaviors. It doesn't run kati,
762 // but it does run a Kati ninja file if the .kati_enabled marker file was created
763 // by a previous build.
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000764 c.skipConfig = true
765 c.skipKati = true
766 } else if arg == "--skip-kati" {
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100767 // TODO: remove --skip-kati once module builds have been migrated to --song-only
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000768 c.skipKati = true
Anton Hansson0b55bdb2021-06-04 10:08:08 +0100769 } else if arg == "--soong-only" {
770 c.skipKati = true
771 c.skipKatiNinja = true
Lukacs T. Berkicef87b62021-08-10 15:01:13 +0200772 } else if arg == "--config-only" {
773 c.skipKati = true
774 c.skipKatiNinja = true
775 c.skipSoong = true
Colin Cross30e444b2021-06-18 11:26:19 -0700776 } else if arg == "--skip-config" {
777 c.skipConfig = true
Colin Cross00a8a3f2020-10-29 14:08:31 -0700778 } else if arg == "--skip-soong-tests" {
779 c.skipSoongTests = true
MarkDacekd0e7cd32022-12-02 22:22:40 +0000780 } else if arg == "--skip-metrics-upload" {
781 c.skipMetricsUpload = true
Chris Parsons53f68ae2022-03-03 12:01:40 -0500782 } else if arg == "--mk-metrics" {
783 c.reportMkMetrics = true
Chris Parsonsef615e52022-08-18 22:04:11 -0400784 } else if arg == "--bazel-mode" {
785 c.bazelProdMode = true
786 } else if arg == "--bazel-mode-dev" {
787 c.bazelDevMode = true
MarkDacekb78465d2022-10-18 20:10:16 +0000788 } else if arg == "--bazel-mode-staging" {
789 c.bazelStagingMode = true
Spandan Das394aa322022-11-03 17:02:10 +0000790 } else if arg == "--search-api-dir" {
791 c.searchApiDir = true
MarkDacekb96561e2022-12-02 04:34:43 +0000792 } else if strings.HasPrefix(arg, "--build-command=") {
793 buildCmd := strings.TrimPrefix(arg, "--build-command=")
794 // remove quotations
795 buildCmd = strings.TrimPrefix(buildCmd, "\"")
796 buildCmd = strings.TrimSuffix(buildCmd, "\"")
797 ctx.Metrics.SetBuildCommand([]string{buildCmd})
MarkDacekd06db5d2022-11-29 00:47:59 +0000798 } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
799 c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
MarkDacek6614d9c2022-12-07 21:57:38 +0000800 } else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
801 buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
802 val, err := strconv.ParseInt(buildTimeStr, 10, 64)
803 if err == nil {
804 c.buildStartedTime = val
805 } else {
806 ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
807 }
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700808 } else if len(arg) > 0 && arg[0] == '-' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700809 parseArgNum := func(def int) int {
810 if len(arg) > 2 {
811 p, err := strconv.ParseUint(arg[2:], 10, 31)
812 if err != nil {
813 ctx.Fatalf("Failed to parse %q: %v", arg, err)
814 }
815 return int(p)
816 } else if i+1 < len(args) {
817 p, err := strconv.ParseUint(args[i+1], 10, 31)
818 if err == nil {
819 i++
820 return int(p)
821 }
822 }
823 return def
824 }
825
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700826 if len(arg) > 1 && arg[1] == 'j' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700827 c.parallel = parseArgNum(c.parallel)
Dan Willemsen6ac63ef2017-10-17 20:35:34 -0700828 } else if len(arg) > 1 && arg[1] == 'k' {
Dan Willemsen9b587492017-07-10 22:13:00 -0700829 c.keepGoing = parseArgNum(0)
Dan Willemsen1e704462016-08-21 15:17:17 -0700830 } else {
831 ctx.Fatalln("Unknown option:", arg)
832 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700833 } else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
Dan Willemsen6dfe30a2018-09-10 12:41:10 -0700834 if k == "OUT_DIR" {
835 ctx.Fatalln("OUT_DIR may only be set in the environment, not as a command line option.")
836 }
Dan Willemsen091525e2017-07-11 14:17:50 -0700837 c.environ.Set(k, v)
Dan Willemsen2d31a442018-10-20 21:33:41 -0700838 } else if arg == "dist" {
839 c.dist = true
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200840 } else if arg == "json-module-graph" {
841 c.jsonModuleGraph = true
842 } else if arg == "bp2build" {
843 c.bp2build = true
Spandan Das5af0bd32022-09-28 20:43:08 +0000844 } else if arg == "api_bp2build" {
845 c.apiBp2build = true
Lukacs T. Berki3a821692021-09-06 17:08:02 +0200846 } else if arg == "queryview" {
847 c.queryview = true
Lukacs T. Berkic6012f32021-09-06 18:31:46 +0200848 } else if arg == "soong_docs" {
849 c.soongDocs = true
Dan Willemsen1e704462016-08-21 15:17:17 -0700850 } else {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700851 if arg == "checkbuild" {
Colin Cross37193492017-11-16 17:55:00 -0800852 c.checkbuild = true
Dan Willemsene0879fc2017-08-04 15:06:27 -0700853 }
Dan Willemsen9b587492017-07-10 22:13:00 -0700854 c.arguments = append(c.arguments, arg)
Dan Willemsen1e704462016-08-21 15:17:17 -0700855 }
856 }
Chris Parsonsb6e96902022-10-31 20:08:45 -0400857 if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
858 c.bazelProdMode = defaultBazelProdMode(c)
859 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700860}
861
Dan Willemsened869522018-01-08 14:58:46 -0800862func (c *configImpl) configureLocale(ctx Context) {
863 cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
864 output, err := cmd.Output()
865
866 var locales []string
867 if err == nil {
868 locales = strings.Split(string(output), "\n")
869 } else {
870 // If we're unable to list the locales, let's assume en_US.UTF-8
871 locales = []string{"en_US.UTF-8"}
872 ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
873 }
874
875 // gettext uses LANGUAGE, which is passed directly through
876
877 // For LANG and LC_*, only preserve the evaluated version of
878 // LC_MESSAGES
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800879 userLang := ""
Dan Willemsened869522018-01-08 14:58:46 -0800880 if lc_all, ok := c.environ.Get("LC_ALL"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800881 userLang = lc_all
Dan Willemsened869522018-01-08 14:58:46 -0800882 } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800883 userLang = lc_messages
Dan Willemsened869522018-01-08 14:58:46 -0800884 } else if lang, ok := c.environ.Get("LANG"); ok {
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800885 userLang = lang
Dan Willemsened869522018-01-08 14:58:46 -0800886 }
887
888 c.environ.UnsetWithPrefix("LC_")
889
Jaewoong Jung18aefc12020-12-21 09:11:10 -0800890 if userLang != "" {
891 c.environ.Set("LC_MESSAGES", userLang)
Dan Willemsened869522018-01-08 14:58:46 -0800892 }
893
894 // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
895 // for others)
896 if inList("C.UTF-8", locales) {
897 c.environ.Set("LANG", "C.UTF-8")
Aaron Klingd236e0e2018-08-07 19:21:36 -0500898 } else if inList("C.utf8", locales) {
899 // These normalize to the same thing
900 c.environ.Set("LANG", "C.UTF-8")
Dan Willemsened869522018-01-08 14:58:46 -0800901 } else if inList("en_US.UTF-8", locales) {
902 c.environ.Set("LANG", "en_US.UTF-8")
903 } else if inList("en_US.utf8", locales) {
904 // These normalize to the same thing
905 c.environ.Set("LANG", "en_US.UTF-8")
906 } else {
907 ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
908 }
909}
910
Dan Willemsen1e704462016-08-21 15:17:17 -0700911func (c *configImpl) Environment() *Environment {
912 return c.environ
913}
914
915func (c *configImpl) Arguments() []string {
916 return c.arguments
917}
918
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200919func (c *configImpl) SoongBuildInvocationNeeded() bool {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200920 if len(c.Arguments()) > 0 {
921 // Explicit targets requested that are not special targets like b2pbuild
922 // or the JSON module graph
923 return true
924 }
925
Spandan Das5af0bd32022-09-28 20:43:08 +0000926 if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200927 // Command line was empty, the default Ninja target is built
928 return true
929 }
930
Liz Kammer88677422021-12-15 15:03:19 -0500931 // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
932 if c.Dist() && !c.Bp2Build() {
933 return true
934 }
935
Lukacs T. Berkia1b93722021-09-02 17:23:06 +0200936 // build.ninja doesn't need to be generated
937 return false
938}
939
Dan Willemsen1e704462016-08-21 15:17:17 -0700940func (c *configImpl) OutDir() string {
941 if outDir, ok := c.environ.Get("OUT_DIR"); ok {
Patrice Arruda19bd53e2019-07-08 17:26:47 -0700942 return outDir
Dan Willemsen1e704462016-08-21 15:17:17 -0700943 }
944 return "out"
945}
946
Dan Willemsen8a073a82017-02-04 17:30:44 -0800947func (c *configImpl) DistDir() string {
Chris Parsons19ab9a42022-08-30 13:15:04 -0400948 return c.distDir
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +0000949}
950
951func (c *configImpl) RealDistDir() string {
Dan Willemsen2d31a442018-10-20 21:33:41 -0700952 return c.distDir
Dan Willemsen8a073a82017-02-04 17:30:44 -0800953}
954
Dan Willemsen1e704462016-08-21 15:17:17 -0700955func (c *configImpl) NinjaArgs() []string {
Anton Hansson5e5c48b2020-11-27 12:35:20 +0000956 if c.skipKati {
Dan Willemsene0879fc2017-08-04 15:06:27 -0700957 return c.arguments
958 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700959 return c.ninjaArgs
960}
961
Jingwen Chen7c6089a2020-11-02 02:56:20 -0500962func (c *configImpl) BazelOutDir() string {
963 return filepath.Join(c.OutDir(), "bazel")
964}
965
Liz Kammer2af5ea82022-11-11 14:21:03 -0500966func (c *configImpl) bazelOutputBase() string {
967 return filepath.Join(c.BazelOutDir(), "output")
968}
969
Dan Willemsen1e704462016-08-21 15:17:17 -0700970func (c *configImpl) SoongOutDir() string {
971 return filepath.Join(c.OutDir(), "soong")
972}
973
Spandan Das394aa322022-11-03 17:02:10 +0000974func (c *configImpl) ApiSurfacesOutDir() string {
975 return filepath.Join(c.OutDir(), "api_surfaces")
976}
977
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200978func (c *configImpl) PrebuiltOS() string {
979 switch runtime.GOOS {
980 case "linux":
981 return "linux-x86"
982 case "darwin":
983 return "darwin-x86"
984 default:
985 panic("Unknown GOOS")
986 }
987}
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100988
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200989func (c *configImpl) HostToolDir() string {
Colin Crossacfcc1f2021-10-25 15:40:32 -0700990 if c.SkipKatiNinja() {
991 return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
992 } else {
993 return filepath.Join(c.OutDir(), "host", c.PrebuiltOS(), "bin")
994 }
Lukacs T. Berkia806e412021-09-01 08:57:48 +0200995}
996
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200997func (c *configImpl) NamedGlobFile(name string) string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +0100998 return shared.JoinPath(c.SoongOutDir(), "globs-"+name+".ninja")
Lukacs T. Berki89fcdcb2021-09-07 09:10:33 +0200999}
1000
Lukacs T. Berkie1df43f2021-09-08 15:31:14 +02001001func (c *configImpl) UsedEnvFile(tag string) string {
1002 return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
1003}
1004
Lukacs T. Berkic541cd22022-10-26 07:26:50 +00001005func (c *configImpl) Bp2BuildFilesMarkerFile() string {
1006 return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
1007}
1008
1009func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
Lukacs T. Berki90b43342021-11-02 14:42:04 +01001010 return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
Lukacs T. Berki56ebaf32021-08-12 14:03:55 +02001011}
1012
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001013func (c *configImpl) SoongDocsHtml() string {
1014 return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
1015}
1016
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001017func (c *configImpl) QueryviewMarkerFile() string {
1018 return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
1019}
1020
Spandan Das5af0bd32022-09-28 20:43:08 +00001021func (c *configImpl) ApiBp2buildMarkerFile() string {
1022 return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
1023}
1024
Lukacs T. Berkie571dc32021-08-25 14:14:13 +02001025func (c *configImpl) ModuleGraphFile() string {
1026 return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
1027}
1028
kgui67007242022-01-25 13:50:25 +08001029func (c *configImpl) ModuleActionsFile() string {
1030 return shared.JoinPath(c.SoongOutDir(), "module-actions.json")
1031}
1032
Jeff Gastonefc1b412017-03-29 17:29:06 -07001033func (c *configImpl) TempDir() string {
1034 return shared.TempDirForOutDir(c.SoongOutDir())
1035}
1036
Jeff Gastonb64fc1c2017-08-04 12:30:12 -07001037func (c *configImpl) FileListDir() string {
1038 return filepath.Join(c.OutDir(), ".module_paths")
1039}
1040
Dan Willemsen1e704462016-08-21 15:17:17 -07001041func (c *configImpl) KatiSuffix() string {
1042 if c.katiSuffix != "" {
1043 return c.katiSuffix
1044 }
1045 panic("SetKatiSuffix has not been called")
1046}
1047
Colin Cross37193492017-11-16 17:55:00 -08001048// Checkbuild returns true if "checkbuild" was one of the build goals, which means that the
1049// user is interested in additional checks at the expense of build time.
1050func (c *configImpl) Checkbuild() bool {
1051 return c.checkbuild
1052}
1053
Dan Willemsen8a073a82017-02-04 17:30:44 -08001054func (c *configImpl) Dist() bool {
1055 return c.dist
1056}
1057
Lukacs T. Berkia1b93722021-09-02 17:23:06 +02001058func (c *configImpl) JsonModuleGraph() bool {
1059 return c.jsonModuleGraph
1060}
1061
1062func (c *configImpl) Bp2Build() bool {
1063 return c.bp2build
1064}
1065
Spandan Das5af0bd32022-09-28 20:43:08 +00001066func (c *configImpl) ApiBp2build() bool {
1067 return c.apiBp2build
1068}
1069
Lukacs T. Berki3a821692021-09-06 17:08:02 +02001070func (c *configImpl) Queryview() bool {
1071 return c.queryview
1072}
1073
Lukacs T. Berkic6012f32021-09-06 18:31:46 +02001074func (c *configImpl) SoongDocs() bool {
1075 return c.soongDocs
1076}
1077
Dan Willemsen1e704462016-08-21 15:17:17 -07001078func (c *configImpl) IsVerbose() bool {
1079 return c.verbose
1080}
1081
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001082func (c *configImpl) SkipKati() bool {
1083 return c.skipKati
1084}
1085
Anton Hansson0b55bdb2021-06-04 10:08:08 +01001086func (c *configImpl) SkipKatiNinja() bool {
1087 return c.skipKatiNinja
1088}
1089
Lukacs T. Berkicef87b62021-08-10 15:01:13 +02001090func (c *configImpl) SkipSoong() bool {
1091 return c.skipSoong
1092}
1093
Lukacs T. Berkid1e3f1f2021-03-16 08:55:23 +01001094func (c *configImpl) SkipNinja() bool {
1095 return c.skipNinja
1096}
1097
Anton Hansson5a7861a2021-06-04 10:09:01 +01001098func (c *configImpl) SetSkipNinja(v bool) {
1099 c.skipNinja = v
1100}
1101
Anton Hansson5e5c48b2020-11-27 12:35:20 +00001102func (c *configImpl) SkipConfig() bool {
1103 return c.skipConfig
Dan Willemsene0879fc2017-08-04 15:06:27 -07001104}
1105
Dan Willemsen1e704462016-08-21 15:17:17 -07001106func (c *configImpl) TargetProduct() string {
1107 if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
1108 return v
1109 }
1110 panic("TARGET_PRODUCT is not defined")
1111}
1112
Dan Willemsen02781d52017-05-12 19:28:13 -07001113func (c *configImpl) TargetDevice() string {
1114 return c.targetDevice
1115}
1116
1117func (c *configImpl) SetTargetDevice(device string) {
1118 c.targetDevice = device
1119}
1120
1121func (c *configImpl) TargetBuildVariant() string {
1122 if v, ok := c.environ.Get("TARGET_BUILD_VARIANT"); ok {
1123 return v
1124 }
1125 panic("TARGET_BUILD_VARIANT is not defined")
1126}
1127
Dan Willemsen1e704462016-08-21 15:17:17 -07001128func (c *configImpl) KatiArgs() []string {
1129 return c.katiArgs
1130}
1131
1132func (c *configImpl) Parallel() int {
1133 return c.parallel
1134}
1135
Spandan Dasc5763832022-11-08 18:42:16 +00001136func (c *configImpl) GetIncludeTags() []string {
1137 return c.includeTags
1138}
1139
1140func (c *configImpl) SetIncludeTags(i []string) {
1141 c.includeTags = i
1142}
1143
MarkDacek6614d9c2022-12-07 21:57:38 +00001144func (c *configImpl) GetLogsPrefix() string {
1145 return c.logsPrefix
1146}
1147
1148func (c *configImpl) SetLogsPrefix(prefix string) {
1149 c.logsPrefix = prefix
1150}
1151
Colin Cross8b8bec32019-11-15 13:18:43 -08001152func (c *configImpl) HighmemParallel() int {
1153 if i, ok := c.environ.GetInt("NINJA_HIGHMEM_NUM_JOBS"); ok {
1154 return i
1155 }
1156
1157 const minMemPerHighmemProcess = 8 * 1024 * 1024 * 1024
1158 parallel := c.Parallel()
1159 if c.UseRemoteBuild() {
1160 // Ninja doesn't support nested pools, and when remote builds are enabled the total ninja parallelism
1161 // is set very high (i.e. 500). Using a large value here would cause the total number of running jobs
1162 // to be the sum of the sizes of the local and highmem pools, which will cause extra CPU contention.
1163 // Return 1/16th of the size of the local pool, rounding up.
1164 return (parallel + 15) / 16
1165 } else if c.totalRAM == 0 {
1166 // Couldn't detect the total RAM, don't restrict highmem processes.
1167 return parallel
Dan Willemsen570a2922020-05-26 23:02:29 -07001168 } else if c.totalRAM <= 16*1024*1024*1024 {
1169 // Less than 16GB of ram, restrict to 1 highmem processes
1170 return 1
Colin Cross8b8bec32019-11-15 13:18:43 -08001171 } else if c.totalRAM <= 32*1024*1024*1024 {
1172 // Less than 32GB of ram, restrict to 2 highmem processes
1173 return 2
1174 } else if p := int(c.totalRAM / minMemPerHighmemProcess); p < parallel {
1175 // If less than 8GB total RAM per process, reduce the number of highmem processes
1176 return p
1177 }
1178 // No restriction on highmem processes
1179 return parallel
1180}
1181
Dan Willemsen2bb82d02019-12-27 09:35:42 -08001182func (c *configImpl) TotalRAM() uint64 {
1183 return c.totalRAM
1184}
1185
Kousik Kumarec478642020-09-21 13:39:24 -04001186// ForceUseGoma determines whether we should override Goma deprecation
1187// and use Goma for the current build or not.
1188func (c *configImpl) ForceUseGoma() bool {
1189 if v, ok := c.environ.Get("FORCE_USE_GOMA"); ok {
1190 v = strings.TrimSpace(v)
1191 if v != "" && v != "false" {
1192 return true
1193 }
1194 }
1195 return false
1196}
1197
Dan Willemsen1e704462016-08-21 15:17:17 -07001198func (c *configImpl) UseGoma() bool {
1199 if v, ok := c.environ.Get("USE_GOMA"); ok {
1200 v = strings.TrimSpace(v)
1201 if v != "" && v != "false" {
1202 return true
1203 }
1204 }
1205 return false
1206}
1207
Yoshisato Yanagisawa2cb0e5d2019-01-10 10:14:16 +09001208func (c *configImpl) StartGoma() bool {
1209 if !c.UseGoma() {
1210 return false
1211 }
1212
1213 if v, ok := c.environ.Get("NOSTART_GOMA"); ok {
1214 v = strings.TrimSpace(v)
1215 if v != "" && v != "false" {
1216 return false
1217 }
1218 }
1219 return true
1220}
1221
Ramy Medhatbbf25672019-07-17 12:30:04 +00001222func (c *configImpl) UseRBE() bool {
Kousik Kumar3ff037e2022-01-25 22:11:01 -05001223 if v, ok := c.Environment().Get("USE_RBE"); ok {
Ramy Medhatbbf25672019-07-17 12:30:04 +00001224 v = strings.TrimSpace(v)
1225 if v != "" && v != "false" {
1226 return true
1227 }
1228 }
1229 return false
1230}
1231
Chris Parsonsef615e52022-08-18 22:04:11 -04001232func (c *configImpl) BazelBuildEnabled() bool {
MarkDacekb78465d2022-10-18 20:10:16 +00001233 return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
Chris Parsonsec1a3dc2021-04-20 15:32:07 -04001234}
1235
Ramy Medhatbbf25672019-07-17 12:30:04 +00001236func (c *configImpl) StartRBE() bool {
1237 if !c.UseRBE() {
1238 return false
1239 }
1240
1241 if v, ok := c.environ.Get("NOSTART_RBE"); ok {
1242 v = strings.TrimSpace(v)
1243 if v != "" && v != "false" {
1244 return false
1245 }
1246 }
1247 return true
1248}
1249
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001250func (c *configImpl) rbeProxyLogsDir() string {
1251 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
Kousik Kumar0d15a722020-09-23 02:54:11 -04001252 if v, ok := c.environ.Get(f); ok {
1253 return v
1254 }
1255 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001256 buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
1257 return filepath.Join(buildTmpDir, "rbe")
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001258}
1259
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001260func (c *configImpl) shouldCleanupRBELogsDir() bool {
1261 // Perform a log directory cleanup only when the log directory
1262 // is auto created by the build rather than user-specified.
1263 for _, f := range []string{"RBE_proxy_log_dir", "FLAG_output_dir"} {
1264 if _, ok := c.environ.Get(f); ok {
1265 return false
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001266 }
1267 }
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001268 return true
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001269}
1270
1271func (c *configImpl) rbeExecRoot() string {
1272 for _, f := range []string{"RBE_exec_root", "FLAG_exec_root"} {
1273 if v, ok := c.environ.Get(f); ok {
1274 return v
1275 }
1276 }
1277 wd, err := os.Getwd()
1278 if err != nil {
1279 return ""
1280 }
1281 return wd
1282}
1283
1284func (c *configImpl) rbeDir() string {
1285 if v, ok := c.environ.Get("RBE_DIR"); ok {
1286 return v
1287 }
1288 return "prebuilts/remoteexecution-client/live/"
1289}
1290
1291func (c *configImpl) rbeReproxy() string {
1292 for _, f := range []string{"RBE_re_proxy", "FLAG_re_proxy"} {
1293 if v, ok := c.environ.Get(f); ok {
1294 return v
1295 }
1296 }
1297 return filepath.Join(c.rbeDir(), "reproxy")
1298}
1299
1300func (c *configImpl) rbeAuth() (string, string) {
Kousik Kumar93d192c2022-03-18 01:39:56 -04001301 credFlags := []string{
1302 "use_application_default_credentials",
1303 "use_gce_credentials",
1304 "credential_file",
1305 "use_google_prod_creds",
1306 }
Ramy Medhat0fc67eb2020-08-12 01:26:23 -04001307 for _, cf := range credFlags {
1308 for _, f := range []string{"RBE_" + cf, "FLAG_" + cf} {
1309 if v, ok := c.environ.Get(f); ok {
1310 v = strings.TrimSpace(v)
1311 if v != "" && v != "false" && v != "0" {
1312 return "RBE_" + cf, v
1313 }
1314 }
1315 }
1316 }
1317 return "RBE_use_application_default_credentials", "true"
Patrice Arruda62f1bf22020-07-07 12:48:26 +00001318}
1319
Kousik Kumar4c180ad2022-05-27 07:48:37 -04001320func (c *configImpl) rbeSockAddr(dir string) (string, error) {
1321 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)
1322 base := fmt.Sprintf("reproxy_%v.sock", rbeRandPrefix)
1323
1324 name := filepath.Join(dir, base)
1325 if len(name) < maxNameLen {
1326 return name, nil
1327 }
1328
1329 name = filepath.Join("/tmp", base)
1330 if len(name) < maxNameLen {
1331 return name, nil
1332 }
1333
1334 return "", fmt.Errorf("cannot generate a proxy socket address shorter than the limit of %v", maxNameLen)
1335}
1336
Kousik Kumar7bc78192022-04-27 14:52:56 -04001337// IsGooglerEnvironment returns true if the current build is running
1338// on a Google developer machine and false otherwise.
1339func (c *configImpl) IsGooglerEnvironment() bool {
1340 cf := "ANDROID_BUILD_ENVIRONMENT_CONFIG"
1341 if v, ok := c.environ.Get(cf); ok {
1342 return v == "googler"
1343 }
1344 return false
1345}
1346
1347// GoogleProdCredsExist determine whether credentials exist on the
1348// Googler machine to use remote execution.
1349func (c *configImpl) GoogleProdCredsExist() bool {
1350 if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
1351 return false
1352 }
1353 return true
1354}
1355
1356// UseRemoteBuild indicates whether to use a remote build acceleration system
1357// to speed up the build.
Colin Cross9016b912019-11-11 14:57:42 -08001358func (c *configImpl) UseRemoteBuild() bool {
1359 return c.UseGoma() || c.UseRBE()
1360}
1361
Kousik Kumar7bc78192022-04-27 14:52:56 -04001362// StubbyExists checks whether the stubby binary exists on the machine running
1363// the build.
1364func (c *configImpl) StubbyExists() bool {
1365 if _, err := exec.LookPath("stubby"); err != nil {
1366 return false
1367 }
1368 return true
1369}
1370
Dan Willemsen1e704462016-08-21 15:17:17 -07001371// RemoteParallel controls how many remote jobs (i.e., commands which contain
Jeff Gastonefc1b412017-03-29 17:29:06 -07001372// gomacc) are run in parallel. Note the parallelism of all other jobs is
Dan Willemsen1e704462016-08-21 15:17:17 -07001373// still limited by Parallel()
1374func (c *configImpl) RemoteParallel() int {
Colin Cross8b8bec32019-11-15 13:18:43 -08001375 if !c.UseRemoteBuild() {
1376 return 0
1377 }
1378 if i, ok := c.environ.GetInt("NINJA_REMOTE_NUM_JOBS"); ok {
1379 return i
Dan Willemsen1e704462016-08-21 15:17:17 -07001380 }
1381 return 500
1382}
1383
1384func (c *configImpl) SetKatiArgs(args []string) {
1385 c.katiArgs = args
1386}
1387
1388func (c *configImpl) SetNinjaArgs(args []string) {
1389 c.ninjaArgs = args
1390}
1391
1392func (c *configImpl) SetKatiSuffix(suffix string) {
1393 c.katiSuffix = suffix
1394}
1395
Dan Willemsene0879fc2017-08-04 15:06:27 -07001396func (c *configImpl) LastKatiSuffixFile() string {
1397 return filepath.Join(c.OutDir(), "last_kati_suffix")
1398}
1399
1400func (c *configImpl) HasKatiSuffix() bool {
1401 return c.katiSuffix != ""
1402}
1403
Dan Willemsen1e704462016-08-21 15:17:17 -07001404func (c *configImpl) KatiEnvFile() string {
1405 return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
1406}
1407
Dan Willemsen29971232018-09-26 14:58:30 -07001408func (c *configImpl) KatiBuildNinjaFile() string {
1409 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
Dan Willemsen1e704462016-08-21 15:17:17 -07001410}
1411
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001412func (c *configImpl) KatiPackageNinjaFile() string {
1413 return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja")
1414}
1415
Jihoon Kang9f4f8a32022-08-16 00:57:30 +00001416func (c *configImpl) SoongVarsFile() string {
1417 return filepath.Join(c.SoongOutDir(), "soong.variables")
1418}
1419
Dan Willemsen1e704462016-08-21 15:17:17 -07001420func (c *configImpl) SoongNinjaFile() string {
1421 return filepath.Join(c.SoongOutDir(), "build.ninja")
1422}
1423
1424func (c *configImpl) CombinedNinjaFile() string {
Dan Willemsene0879fc2017-08-04 15:06:27 -07001425 if c.katiSuffix == "" {
1426 return filepath.Join(c.OutDir(), "combined.ninja")
1427 }
Dan Willemsen1e704462016-08-21 15:17:17 -07001428 return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
1429}
1430
1431func (c *configImpl) SoongAndroidMk() string {
1432 return filepath.Join(c.SoongOutDir(), "Android-"+c.TargetProduct()+".mk")
1433}
1434
1435func (c *configImpl) SoongMakeVarsMk() string {
1436 return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
1437}
1438
Dan Willemsenf052f782017-05-18 15:29:04 -07001439func (c *configImpl) ProductOut() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001440 return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
Dan Willemsenf052f782017-05-18 15:29:04 -07001441}
1442
Dan Willemsen02781d52017-05-12 19:28:13 -07001443func (c *configImpl) DevicePreviousProductConfig() string {
Dan Willemsenf052f782017-05-18 15:29:04 -07001444 return filepath.Join(c.ProductOut(), "previous_build_config.mk")
1445}
1446
Dan Willemsenfb1271a2018-09-26 15:00:42 -07001447func (c *configImpl) KatiPackageMkDir() string {
1448 return filepath.Join(c.ProductOut(), "obj", "CONFIG", "kati_packaging")
1449}
1450
Dan Willemsenf052f782017-05-18 15:29:04 -07001451func (c *configImpl) hostOutRoot() string {
Dan Willemsen4dc4e142017-09-08 14:35:43 -07001452 return filepath.Join(c.OutDir(), "host")
Dan Willemsenf052f782017-05-18 15:29:04 -07001453}
1454
1455func (c *configImpl) HostOut() string {
1456 return filepath.Join(c.hostOutRoot(), c.HostPrebuiltTag())
1457}
1458
1459// This probably needs to be multi-valued, so not exporting it for now
1460func (c *configImpl) hostCrossOut() string {
1461 if runtime.GOOS == "linux" {
1462 return filepath.Join(c.hostOutRoot(), "windows-x86")
1463 } else {
1464 return ""
1465 }
Dan Willemsen02781d52017-05-12 19:28:13 -07001466}
1467
Dan Willemsen1e704462016-08-21 15:17:17 -07001468func (c *configImpl) HostPrebuiltTag() string {
1469 if runtime.GOOS == "linux" {
1470 return "linux-x86"
1471 } else if runtime.GOOS == "darwin" {
1472 return "darwin-x86"
1473 } else {
1474 panic("Unsupported OS")
1475 }
1476}
Dan Willemsenf173d592017-04-27 14:28:00 -07001477
Dan Willemsen8122bd52017-10-12 20:20:41 -07001478func (c *configImpl) PrebuiltBuildTool(name string) string {
Dan Willemsenf173d592017-04-27 14:28:00 -07001479 if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
1480 if sanitize := strings.Fields(v); inList("address", sanitize) {
Dan Willemsen8122bd52017-10-12 20:20:41 -07001481 asan := filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "asan/bin", name)
1482 if _, err := os.Stat(asan); err == nil {
1483 return asan
1484 }
Dan Willemsenf173d592017-04-27 14:28:00 -07001485 }
1486 }
1487 return filepath.Join("prebuilts/build-tools", c.HostPrebuiltTag(), "bin", name)
1488}
Dan Willemsen3d60b112018-04-04 22:25:56 -07001489
1490func (c *configImpl) SetBuildBrokenDupRules(val bool) {
1491 c.brokenDupRules = val
1492}
1493
1494func (c *configImpl) BuildBrokenDupRules() bool {
1495 return c.brokenDupRules
1496}
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001497
Dan Willemsen25e6f092019-04-09 10:22:43 -07001498func (c *configImpl) SetBuildBrokenUsesNetwork(val bool) {
1499 c.brokenUsesNetwork = val
1500}
1501
1502func (c *configImpl) BuildBrokenUsesNetwork() bool {
1503 return c.brokenUsesNetwork
1504}
1505
Dan Willemsene3336352020-01-02 19:10:38 -08001506func (c *configImpl) SetBuildBrokenNinjaUsesEnvVars(val []string) {
1507 c.brokenNinjaEnvVars = val
1508}
1509
1510func (c *configImpl) BuildBrokenNinjaUsesEnvVars() []string {
1511 return c.brokenNinjaEnvVars
1512}
1513
Dan Willemsen6ab79db2018-05-02 00:06:28 -07001514func (c *configImpl) SetTargetDeviceDir(dir string) {
1515 c.targetDeviceDir = dir
1516}
1517
1518func (c *configImpl) TargetDeviceDir() string {
1519 return c.targetDeviceDir
1520}
Dan Willemsenfa42f3c2018-06-15 21:54:47 -07001521
Patrice Arruda219eef32020-06-01 17:29:30 +00001522func (c *configImpl) BuildDateTime() string {
1523 return c.buildDateTime
1524}
1525
1526func (c *configImpl) MetricsUploaderApp() string {
Yu Liu6e13b402021-07-27 14:29:06 -07001527 return c.metricsUploader
Patrice Arruda219eef32020-06-01 17:29:30 +00001528}
Patrice Arruda83842d72020-12-08 19:42:08 +00001529
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001530// LogsDir returns the absolute path to the logs directory where build log and
1531// metrics files are located. By default, the logs directory is the out
Patrice Arruda83842d72020-12-08 19:42:08 +00001532// directory. If the argument dist is specified, the logs directory
1533// is <dist_dir>/logs.
1534func (c *configImpl) LogsDir() string {
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001535 dir := c.OutDir()
Patrice Arruda83842d72020-12-08 19:42:08 +00001536 if c.Dist() {
Rupert Shuttleworth3c9f5ac2020-12-10 11:32:38 +00001537 // 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 -05001538 dir = filepath.Join(c.RealDistDir(), "logs")
Patrice Arruda83842d72020-12-08 19:42:08 +00001539 }
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux947fdbf2021-11-10 09:55:20 -05001540 absDir, err := filepath.Abs(dir)
1541 if err != nil {
1542 fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
1543 os.Exit(1)
1544 }
1545 return absDir
Patrice Arruda83842d72020-12-08 19:42:08 +00001546}
1547
1548// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
1549// where the bazel profiles are located.
1550func (c *configImpl) BazelMetricsDir() string {
1551 return filepath.Join(c.LogsDir(), "bazel_metrics")
1552}
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001553
Chris Parsons53f68ae2022-03-03 12:01:40 -05001554// MkFileMetrics returns the file path for make-related metrics.
1555func (c *configImpl) MkMetrics() string {
1556 return filepath.Join(c.LogsDir(), "mk_metrics.pb")
1557}
1558
Colin Crossf3bdbcb2021-06-01 11:43:55 -07001559func (c *configImpl) SetEmptyNinjaFile(v bool) {
1560 c.emptyNinjaFile = v
1561}
1562
1563func (c *configImpl) EmptyNinjaFile() bool {
1564 return c.emptyNinjaFile
1565}
Yu Liu6e13b402021-07-27 14:29:06 -07001566
Romain Jobredeaux0a7529b2022-10-26 12:56:41 -04001567func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
1568 return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
1569}
1570
MarkDacekd06db5d2022-11-29 00:47:59 +00001571func (c *configImpl) BazelModulesForceEnabledByFlag() string {
1572 return c.bazelForceEnabledModules
1573}
1574
MarkDacekd0e7cd32022-12-02 22:22:40 +00001575func (c *configImpl) SkipMetricsUpload() bool {
1576 return c.skipMetricsUpload
1577}
1578
MarkDacek6614d9c2022-12-07 21:57:38 +00001579// Returns a Time object if one was passed via a command-line flag.
1580// Otherwise returns the passed default.
1581func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
1582 if c.buildStartedTime == 0 {
1583 return defaultTime
1584 }
1585 return time.UnixMilli(c.buildStartedTime)
1586}
1587
Yu Liu6e13b402021-07-27 14:29:06 -07001588func GetMetricsUploader(topDir string, env *Environment) string {
1589 if p, ok := env.Get("METRICS_UPLOADER"); ok {
1590 metricsUploader := filepath.Join(topDir, p)
1591 if _, err := os.Stat(metricsUploader); err == nil {
1592 return metricsUploader
1593 }
1594 }
1595
1596 return ""
1597}